1.5.9 多线激光雷达仿真(C++)

1.发布方实现

功能包cpp02_laser的src目录下,新建C++文件sim_laser.cpp,并编辑文件,输入如下内容:

/*
    需求:发布点云数据,点云共50行100列,且可以沿X轴周期性运动。
    流程:
        1.包含头文件;
        2.初始化ROS2客户端;
        3.自定义节点类;
          3-1.创建发布方;
          3-2.创建定时器;
          3-3.组织并发布数据。
        4.调用spin函数,并传入节点对象指针;
        5.资源释放。
*/
// 1.包含头文件;
#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/point_cloud2.hpp"
#include "sensor_msgs/msg/point_field.hpp"
#include "cstring"

using namespace std::chrono_literals;
// 3.自定义节点类;
class LaserPublisher: public rclcpp::Node{
public:
    LaserPublisher():Node("laser_publisher_node_cpp"){
        counter = 0;
        publisher = this->create_publisher<sensor_msgs::msg::PointCloud2>("/pcl",10);
        timer = this->create_wall_timer(0.1s,std::bind(&LaserPublisher::on_timer,this));

    }
private:
    rclcpp::Publisher<sensor_msgs::msg::PointCloud2>::SharedPtr publisher;
    rclcpp::TimerBase::SharedPtr timer;
    int counter; // 计数器
    void on_timer(){

        // 创建点云对象
        auto pcl = sensor_msgs::msg::PointCloud2();

        // 设置点云消息标头(时间戳与坐标系)
        pcl.header.stamp = this->get_clock()->now();
        pcl.header.frame_id = "laser";

        // 设置点云宽度与高度
        pcl.height = 50;
        pcl.width = 100;

        // 设置点云坐标点属性
        auto x = sensor_msgs::msg::PointField();
        x.name = "x";
        x.offset = 0;
        x.count = 1;
        x.datatype = sensor_msgs::msg::PointField::FLOAT32;
        auto y = sensor_msgs::msg::PointField();
        y.name = "y";
        y.offset = 4;
        y.count = 1;
        y.datatype = sensor_msgs::msg::PointField::FLOAT32;
        auto z = sensor_msgs::msg::PointField();
        z.name = "z";
        z.offset = 8;
        z.count = 1;
        z.datatype = sensor_msgs::msg::PointField::FLOAT32;
        auto in = sensor_msgs::msg::PointField();
        in.name = "intensity";
        in.offset = 12;
        in.count = 1;
        in.datatype = sensor_msgs::msg::PointField::FLOAT32;

        pcl.fields.push_back(x);
        pcl.fields.push_back(y);
        pcl.fields.push_back(z);
        pcl.fields.push_back(in);

        // 设置每个点的长度
        pcl.point_step = 16;
        // 设置一行的长度
        pcl.row_step = pcl.point_step * pcl.width;
        // 是否有无效点
        pcl.is_dense = false;
        // 是否为大端字节序
        pcl.is_bigendian = false;

        // 生成点云数据
        pcl.data.resize(pcl.row_step * pcl.height);
        std::vector<float> points(pcl.height * pcl.width * 4);

        for (uint32_t i = 0; i < pcl.height; i++)
        {
            for (uint32_t j = 0; j < pcl.width; j++)
            {
                int index = (i * pcl.width + j) * 4;
                points[index] = 1.0 - counter % 30 * 0.02;
                points[index + 1] = 1.0 - 0.02 * j;
                points[index + 2] = 1.0 - 0.02 * i;
                points[index + 3] = i * j;
            }

        }
        std::memcpy(&(pcl.data[0]),points.data(),pcl.data.size());

        // 发布
        publisher->publish(pcl);
        counter++;

    }
};

int main(int argc, char const *argv[])
{
    // 2.初始化ROS2客户端;
    rclcpp::init(argc,argv);
    // 4.调用spain函数,并传入节点对象指针;
    rclcpp::spin(std::make_shared<LaserPublisher>());
    // 5.资源释放。
    rclcpp::shutdown();
    return 0;
}

2.编辑配置文件

1.packages.xml

在创建功能包时,所依赖的功能包已经自动配置了,配置内容如下:

<depend>rclcpp</depend>
<depend>sensor_msgs</depend>
2.CMakeLists.txt

CMakeLists.txt 中核心配置如下:

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(sensor_msgs REQUIRED)

add_executable(sim_laser src/sim_laser.cpp)

ament_target_dependencies(
  sim_laser
  "rclcpp"
  "sensor_msgs"
)

install(TARGETS sim_laser
  DESTINATION lib/${PROJECT_NAME})

3.编译

终端中进入当前工作空间,编译功能包:

colcon build --packages-select cpp02_laser

4.执行

当前工作空间下,启动终端,并输入如下指令:

. install/setup.bash
ros2 run cpp02_laser sim_laser

5.使用rviz2查看结果

新建终端,输入如下指令:

rviz2

rviz2启动后,将参考坐标系设置为laser,添加点云消息插件PointCloud2并将话题设置为pcl,最终运行结果与演示案例类似。

results matching ""

    No results matching ""