镭神C32测试LEGO-LOAM

目录

跑通LEGO-LOAM

安装gtsam(Georgia Tech Smoothing and Mapping library, 4.0.0-alpha2)

安装编译LEGO-LOAM

运行

测试

修改utility.h

修改imageProjection.cpp

转换话题文件

修改LEGO-LOAM配置

测试效果


跑通LEGO-LOAM

安装gtsam(Georgia Tech Smoothing and Mapping library, 4.0.0-alpha2)

wget -O ~/Downloads/gtsam.zip https://github.com/borglab/gtsam/archive/4.0.0-alpha2.zip
cd ~/Downloads/ && unzip gtsam.zip -d ~/Downloads/
cd ~/Downloads/gtsam-4.0.0-alpha2/
mkdir build && cd build
cmake -DGTSAM_BUILD_WITH_MARCH_NATIVE=OFF -DGTSAM_USE_SYSTEM_EIGEN=ON ..
sudo make install

        由于系统是ubuntu20.04中文版,所以把上面的【Downloads】换为【下载】即可,中间会有好多warning,不知道是否影响使用。

安装编译LEGO-LOAM

cd ~/catkin_ws/src
git clone https://github.com/RobustFieldAutonomyLab/LeGO-LOAM.git
cd ..
catkin_make -j1

第一次编译代码时,需要在“catkin_make”后面加上“-j1”来生成一些消息类型。以后的编译不需要“-j1”

编译时报错:

  • In file included from /home/lpf/catkin_ws/src/LeGO-LOAM/LeGO-LOAM/src/imageProjection.cpp:35:/home/lpf/catkin_ws/src/LeGO-LOAM/LeGO-LOAM/include/utility.h:13:10: fatal error: opencv/cv.h: 没有那个文件或目录

   13 | #include <opencv/cv.h>

我记得以前是装过opencv的,应该是版本不同,就去搜了一下,原因是在opencv4中opencv2的cv.h融合进了imgproc.hpp里,所以把utility.h中的#include <opencv/cv.h>改成#include <opencv2/imgproc.hpp>即可。

  • /home/lpf/catkin_ws/src/LeGO-LOAM/LeGO-LOAM/include/utility.h:182:1: error: ‘mulscalar’ is not a member of ‘pcl::traits’

将cmakelists.txt中的c++编译版本改为14

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -O3")

  • /usr/include/pcl-1.10/pcl/filters/voxel_grid.h:340:21: error: ‘Index’ is not a member of ‘Eigen’

这个错误是因为 Lego LOAM 中原作者建议使用的 gtsam 版本为 4.0.0-alpha2,gtsam 是自带了一个 eigen 库的,而这个版本的 gtsam 中使用的是较低版本的 Eigen,还没有 Eigen::Index 这个定义。比较简单的做法是将 PCL 中用到的 Eigen::Index 改为 int 即可。不过使用 gtsam 中低版本的 Eigen 可能也会在别的库造成问题,所以建议的做法是不适用 gtsam 带的第三方库,具体方法为按照作者的方法编译 gtsam 时在 cmake 阶段设置使用系统自带的 Eigen,此外 gtsam 编译时会默认进行 SSE 加速,而如 PCL 等其他库大多数情况不会打开,因此如果一起使用的话会造成节点崩溃,因此一般将其关闭,如下所示:

mkdir build && cd build
cmake -DGTSAM_BUILD_WITH_MARCH_NATIVE=OFF -DGTSAM_USE_SYSTEM_EIGEN=ON ..
sudo make install

又报错:

/usr/bin/ld: 找不到 -lBoost::serialization
/usr/bin/ld: 找不到 -lBoost::thread
/usr/bin/ld: 找不到 -lBoost::timer
/usr/bin/ld: 找不到 -lBoost::chrono

百度查了一下,说是该类问题有通用的解决方法,先用locate定位未找到的共享库,然后建立软链接,试了一下不行,然后继续搜,找到了这篇,是通过修改CmakeList.txt文件,调用这些包。

find_package(Boost REQUIRED COMPONENTS
serialization timer thread chrono)

# include directories
include_directories(
	include
	${catkin_INCLUDE_DIRS}
	${PCL_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
	${GTSAM_INCLUDE_DIR}
	${Boost_INCLUDE_DIRS}
)
# link directories
link_directories(
	include
	${PCL_LIBRARY_DIRS}
  ${OpenCV_LIBRARY_DIRS}
  ${GTSAM_LIBRARY_DIRS}
  ${Boost_INCLUDE_DIRS}
)

到此就编译完成了,如下图

运行

因为 tf2 开始已经不会在 frame_id 前面加 /,所以需要将代码中所有涉及 frame_id 的部分将 / 去掉

roslaunch lego_loam run.launch

Notes: launch文件中 The parameter "/use_sim_time" is set to "true" for simulation, "false" to real robot usage.

rosbag play *.bag --clock --topic /velodyne_points /imu/data

--clock指播放时顺带显示录制文件的时间戳,后面表示播放录制文件中指定话题的消息,参考

但是,我一开始没有加参数,rviz没有显示点云,不知道为什么?这个有影响吗?

根据github提供的代码地址下载数据集,播放same_position.bag文件

测试

换用自己的传感器主要需要修改utility.h以及imageProjection.cpp,并转换topic

修改utility.h

源文件作者的备注:

New Lidar:The key thing to adapt the code to a new sensor is making sure the point cloud can be properly projected to an range image and ground can be correctly detected. For example, VLP-16 has a angular resolution of 0.2° and 2° along two directions. It has 16 beams. The angle of the bottom beam is -15°. Thus, the parameters in “utility.h” are listed as below. When you implement new sensor, make sure that the ground_cloud has enough points for matching. Before you post any issues, please read this.

extern const int N_SCAN = 16;
extern const int Horizon_SCAN = 1800;
extern const float ang_res_x = 0.2;
extern const float ang_res_y = 2.0;
extern const float ang_bottom = 15.0;
extern const int groundScanInd = 7;

Another example for Velodyne HDL-32e range image projection:

extern const int N_SCAN = 32;//线数
extern const int Horizon_SCAN = 1800;//旋转一周的采样数
extern const float ang_res_x = 360.0/Horizon_SCAN;//水平分辨率
extern const float ang_res_y = 41.333/float(N_Scan-1);//垂直分辨率
extern const float ang_bottom = 30.666666;//lidar底部线束的角度偏移
extern const int groundScanInd = 20;//lidar判定为地面的线束

针对镭神C32,参考,在utility.h中添加镭神C32的配置

// LeiShen-32C-5Hz
// extern const int N_SCAN = 32;
// extern const int Horizon_SCAN = 4000;
// extern const float ang_res_x = 360.0 / float(Horizon_SCAN);
// extern const float ang_res_y = 26 / float(N_SCAN-1);
// extern const float ang_bottom = 16.5;
// extern const int groundScanInd = 10; //地面的线扫条数

// LeiShen-32C-10Hz
extern const int N_SCAN = 32;
extern const int Horizon_SCAN = 2000;
extern const float ang_res_x = 360.0 / float(Horizon_SCAN);
extern const float ang_res_y = 31.0 / float(N_SCAN-1);
extern const float ang_bottom = 16.5;//雷达底部线束的偏移角度
extern const int groundScanInd = 10; //地面的线扫条数

查手册,10 Hz时,Horizon_SCAN = 360/0.18 = 2000

 New: a new useCloudRing flag has been added to help with point cloud projection. Velodyne point cloud has “ring” channel that directly gives the point row id in a range image. Other lidars may have a same type of channel, i.e., “r” in Ouster. If you are using a non-Velodyne lidar but it has a similar “ring” channel, you can change the PointXYZIR definition in utility.h and the corresponding code in imageProjection.cpp.

useCloudRing标志帮助点云进行投影,Velodyne点云包含"环"频道,在大范围图像内直接给出点的行id。其他雷达可能也有这个通道。如果您使用的是非velodyne激光雷达,但是它有一个类似的“环形”通道,您可以在utility.h中更改PointXYZIR定义,并在imageproject .cpp中更改相应的代码。

镭神好像是没有Velodyne雷达的ring channel功能,所以useCloudRing设置为false了,设置false后,应该是会通过分辨率和角度来计算属于哪条线束

// Using velodyne cloud "ring" channel for image projection (other lidar may have different name for this channel, change "PointXYZIR" below)
extern const bool useCloudRing = false; // if true, ang_res_y and ang_bottom are not used

修改imageProjection.cpp

找到copyPointCloud,将cloudHeader.stamp = ros::Time::now()的注释去掉

    void copyPointCloud(const sensor_msgs::PointCloud2ConstPtr& laserCloudMsg){

        cloudHeader = laserCloudMsg->header;
        cloudHeader.stamp = ros::Time::now(); // Ouster lidar users may need to uncomment this line
        pcl::fromROSMsg(*laserCloudMsg, *laserCloudIn);
        // Remove Nan points
        std::vector<int> indices;
        pcl::removeNaNFromPointCloud(*laserCloudIn, *laserCloudIn, indices);
        // have "ring" channel in the cloud
        if (useCloudRing == true){
            pcl::fromROSMsg(*laserCloudMsg, *laserCloudInRing);
            if (laserCloudInRing->is_dense == false) {
                ROS_ERROR("Point cloud is not in dense format, please remove NaN points first!");
                ros::shutdown();
            }  
        }
    }

转换话题

LeGO-LOAM默认的接受的topic name是velodyne_points,点云的frame_id是velodyne,镭神驱动发布的topic name为lslidar_point_cloud,frame_id为laser_link。所以,要想LEGO-LOAM可以使用镭神C32,有以下两种方法:

  1. 修改lslidar_c32.launch文件
  2. 写中间文件,将话题消息作下转换

考虑普适性与便利性,应该写中间文件进行话题转换

topic_change_node.cpp

#include "ros/ros.h"
#include "std_msgs/String.h"
#include "sensor_msgs/PointCloud2.h"
#include <string>

#include <sstream>

/**
 * This tutorial demonstrates simple sending of messages over the ROS system.
 */

static ros::Publisher target_pub;
std::string target_frame_id;

static void source_topic_callback(const sensor_msgs::PointCloud2::ConstPtr& input)
{
    sensor_msgs::PointCloud2 msg = *input;
    msg.header.frame_id = target_frame_id;
    target_pub.publish(msg);
}


int main(int argc, char *argv[])
{

    ros::init(argc, argv, "leishen_to_velodye");


    ros::NodeHandle private_nh("~");
    ros::NodeHandle n;


    std::string source_topic;
    std::string target_topic;



    if (!private_nh.getParam("source_topic", source_topic))
    {
        ROS_ERROR("can not get source_topic!");
        exit(0);
    }

    if (!private_nh.getParam("target_topic", target_topic))
    {
        ROS_ERROR("can not get target_topic!");
        exit(0);
    }

    if (!private_nh.getParam("target_frame_id", target_frame_id))
    {
        ROS_ERROR("can not get target_frame_id!");
        exit(0);
    }

    target_pub = n.advertise<sensor_msgs::PointCloud2>(target_topic, 10);
    ros::Subscriber main_topic_sub = n.subscribe<sensor_msgs::PointCloud2>(source_topic, 10000, source_topic_callback);

    /**
     * A count of how many messages we have sent. This is used to create
     * a unique string for each message.
     */
    ros::spin();

    return 0;
}

 topic_change.launch

<launch>
  <arg name="target_topic_name" default="velodyne_points" />
  <arg name="target_frame_id_name" default="velodyne" />
  <arg name="source_topic_name" default="lslidar_point_cloud" />
  

  <node pkg="topic_change" name="topic_change_node" type="topic_change_node" output="screen">  
    <param name="target_topic" value="$(arg target_topic_name)" />
    <param name="source_topic" value="$(arg source_topic_name)" />
    <param name="target_frame_id" value="$(arg target_frame_id_name)" />

  </node>
</launch>

单独编译:catkin_make -DCATKIN_WHITELIST_PACKAGES="topic_change"

恢复编译所有包:catkin_make -DCATKIN_WHITELIST_PACKAGES=""

修改LEGO-LOAM配置

由于布置的分布式通信系统,需要把镭神lslidar_c32.launch文件中的启动rviz注释掉

对于实时建图,需要修改LEGO-LOAM中的run.launch

    <!--- Sim Time -->
    <param name="/use_sim_time" value="false" />

将true改为false,表示不使用仿真时间

测试效果

测试效果如下(雷达放在原位置没有动)

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值