Skip to content

File sample_ros_wrapper.hpp

File List > include > nebula_sample > sample_ros_wrapper.hpp

Go to the documentation of this file

// Copyright 2026 TIER IV, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef NEBULA_SAMPLE_ROS_WRAPPER_HPP
#define NEBULA_SAMPLE_ROS_WRAPPER_HPP

#include "nebula_sample_decoders/sample_decoder.hpp"
#include "nebula_sample_hw_interfaces/sample_hw_interface.hpp"

#include <diagnostic_updater/diagnostic_updater.hpp>
#include <nebula_core_common/util/expected.hpp>
#include <nebula_core_ros/diagnostics/liveness_monitor.hpp>
#include <nebula_core_ros/diagnostics/rate_bound_status.hpp>
#include <nebula_sample_common/sample_configuration.hpp>
#include <rclcpp/rclcpp.hpp>

#include <nebula_msgs/msg/nebula_packet.hpp>
#include <nebula_msgs/msg/nebula_packets.hpp>
#include <sensor_msgs/msg/point_cloud2.hpp>
#include <std_msgs/msg/float64.hpp>

#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <variant>
#include <vector>

namespace nebula::ros
{

struct ConfigError
{
  enum class Code : uint8_t {
    PARAMETER_DECLARATION_FAILED,  
    PARAMETER_VALIDATION_FAILED,   
  };

  Code code;
  std::string message;
};

util::expected<drivers::SampleSensorConfiguration, ConfigError> load_config_from_ros_parameters(
  rclcpp::Node & node);

class SampleRosWrapper : public rclcpp::Node
{
public:
  struct Error
  {
    enum class Code : uint8_t {
      HW_INTERFACE_NOT_INITIALIZED,  
      HW_STREAM_START_FAILED,        
    };

    Code code;
    std::string message;
  };

  explicit SampleRosWrapper(const rclcpp::NodeOptions & options);
  ~SampleRosWrapper() override;

private:
  struct OnlineMode
  {
    explicit OnlineMode(drivers::ConnectionConfiguration connection_configuration)
    : hw_interface(std::move(connection_configuration))
    {
    }

    drivers::SampleHwInterface hw_interface;
    rclcpp::Publisher<nebula_msgs::msg::NebulaPackets>::SharedPtr packets_pub;
    std::unique_ptr<nebula_msgs::msg::NebulaPackets> current_scan_packets_msg{
      std::make_unique<nebula_msgs::msg::NebulaPackets>()};
  };

  struct OfflineMode
  {
    rclcpp::Subscription<nebula_msgs::msg::NebulaPackets>::SharedPtr packets_sub;
  };

  struct Publishers
  {
    rclcpp::Publisher<sensor_msgs::msg::PointCloud2>::SharedPtr points;
    rclcpp::Publisher<std_msgs::msg::Float64>::SharedPtr receive_duration_ms;
    rclcpp::Publisher<std_msgs::msg::Float64>::SharedPtr decode_duration_ms;
    rclcpp::Publisher<std_msgs::msg::Float64>::SharedPtr publish_duration_ms;
  };

  struct Diagnostics
  {
    explicit Diagnostics(rclcpp::Node * node) : updater(node) {}

    diagnostic_updater::Updater updater;
    std::optional<custom_diagnostic_tasks::RateBoundStatus> publish_rate;
    std::optional<LivenessMonitor> packet_liveness;
  };

  void publish_pointcloud_callback(
    const drivers::NebulaPointCloudPtr & pointcloud, double timestamp_s);

  void receive_cloud_packet_callback(
    std::vector<uint8_t> & packet, const drivers::connections::UdpSocket::RxMetadata & metadata);

  void receive_packets_message_callback(
    std::unique_ptr<nebula_msgs::msg::NebulaPackets> packets_msg);

  void initialize_diagnostics();

  void process_packet(const std::vector<uint8_t> & packet, uint64_t receive_duration_ns);

  void publish_debug_durations(
    uint64_t receive_duration_ns, uint64_t decode_duration_ns, uint64_t publish_duration_ns) const;

  static const char * to_cstr(Error::Code code);

  drivers::SampleSensorConfiguration config_;
  std::string frame_id_;
  Publishers publishers_;
  Diagnostics diagnostics_;

  std::optional<drivers::SampleDecoder> decoder_;
  std::variant<std::monostate, OfflineMode, OnlineMode> runtime_mode_;
};

}  // namespace nebula::ros

#endif  // NEBULA_SAMPLE_ROS_WRAPPER_HPP