当前位置:   article > 正文

ros和c++使用时的技巧和踩过的坑_ros应该如何调试c++

ros应该如何调试c++

1. ros的技巧命令

  1. rosbag暂停播放rosbag play --clock --pause bagfile.bag ,通过空格来开始暂停和继续。rosbag play --pause bagfile.bag ,一帧帧点云播放,按s键播放下一帧,通过空格来暂停和继续。rosbag play bagfile.bag -r 0.1,慢速播放,后面的0.1即为播放的速度,如果改为10,即为10倍播放速度。
  2. roslaunch重定向,方便调试代码roslaunch lio_sam run.launch 2>&1 | tee log.txt, 该命令既能输出到屏幕,也可以打印信息到文件中。
  3. 清理ros磁盘: rosclean purge
  4. 调用tf树rosrun rqt_tf_tree rqt_tf_tree
  5. 播放一个包的部分话题rosbag play record.bag --topics /topic1 /topic2
    rosbag包的使用相关命令可以参考:链接: link 和链接: link ,我播放我的比赛数据包, rosbag play xiamengang_Truck3_918_20230830160116_sunny_zhongzai_2.bag --topic /minibus/front/lslidar_packets /minibus/rear/lslidar_packets /imu /minibus/gpsposition /minibus/insposition
  6. 调用plotjuggler: 可以看数据中的时间戳是否是一致的,rosrun plotjuggler plotjuggler
  7. 警告信息Warning: TF_OLD_DATA: Warning: TF_OLD_DATA ignoring data from the past for frame stm32_imu at time 1.6203e+09 according to authority unknown_publisher Possible reasons are listed at http://wiki.ros.org/tf/Errors%20explained at line 277 in /tmp/binarydeb/ros-kinetic-tf2-0.5.20/src/buffer_core.cpp ,执行rosparam set /use_sim_time true ,然后在播放bag数据时使用参数--clock
  8. evo的使用技巧: 画轨迹图evo_traj tum --ref lio_sam_traj.txt fast_lio_traj.txt --align_origin -ap --plot_mode=xy 其中–align_origin 是原点对齐,–plot_mode=xy为画图显示xy两个方向的结果, -ap是画图,也可以用evo_traj tum --ref GNSS_traj.txt Wgs84Xyz_quaternion_Tum.txt -ap评定绝对误差evo_ape tum GNSS_traj.txt Wgs84Xyz_quaternion_Tum.txt -ap;评定相对误差,evo_rpe tum GNSS_traj.txt Wgs84Xyz_quaternion_Tum.txt -ap
  9. 保存LIO-SAM-6AIXS的结果rosservice call /lio_sam_6axis/save_map
  10. roabag数据包转换成pcd的命令: rosrun pcl_ros bag_to_pcd ../40m_RsLidar.bag /velodyne_points ./
  11. rosbag包分割成两部分: 链接: 分割rosbag包

2. catkin_make问题记录与方案

  1. 全局查找linux中的文件sudo find / -name Python3.framework 或者 locate Eigen进行模糊查询
  2. catkin_make报错:找不到分享的so文件,具体为Linux error while loading shared libraries: cannot open shared object file: No such file or directory: 参考链接: linksudo find / -name the_name_of_the_file.so , echo $LD_LIBRARY_PATH export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/my_library/
  3. catkin_make报错:ymbol lookup error: /lib/x86_64-linux-gnu/libp11-kit.so.0: undefined symbol: ffi_type_pointer, version LIBFFI_BASE_7.0: 参考链接:link
  4. catkin_make报错error: curl: /usr/local/lib/libcurl.so.4: no version information available (required by curl),主要是软链接错误:参考链接:linklocate libcurl.so.4 ,ls -l /softwares/anaconda3/lib/libcurl.so.4rm /softwares/anaconda3/lib/libcurl.so.4ln -s /snap/curl/1679/lib/libcurl.so.4.8.0 /softwares/anaconda3/lib/libcurl.so.4ls -l /softwares/anaconda3/lib/libcurl.so.4
  5. 打印环境变量echo $PATH,echo $LD_LIBRARY_PATHecho $CPLUS_INCLUDE_PATH
  6. 进入到Conda,用c++画图:进入环境conda activate, 退出环境conda deactivate,进入forcppEnvs画图环境,conda activate forcppEnvs
  7. matplotlibcpp.h: No such file or directory:先找到matplotlib-cpp,命令为sudo find / -name matplotlib-cpp,接下来将找到的路径放到环境变量中,也就是主目录的.bashrc文件中,如下***/matplotlib-cpp,之后source下,source ~/.bashrc,重新编译即可。
    插入matplotlib-cpp的路径主要思路就是catkin在编译的时候找不到头文件,将头文件给到编译的文件即可,可以在环境变量中添加,也可以在Cmakelists添加,我直接在环境变量中添加,以后写新的代码,就不用再麻烦添加了。

3. C++的技巧

  1. lio-sam输出轨迹:
std::ofstream ofsTraj;  // Trajectory文件
ofsTraj.open(MO.saveTrajDirectory, ios::out);
// 输出的技巧:
ofsTraj << std::fixed << setprecision(9)  << laserOdometryROS.header.stamp  
                << std::fixed << setprecision(3) << std::right << setw(9)  
                << laserOdometryROS.pose.pose.position.x
                << std::fixed << setprecision(3) << std::right << setw(9)  
                << laserOdometryROS.pose.pose.position.y  
                << std::fixed << setprecision(3) << std::right << setw(9)  
                << laserOdometryROS.pose.pose.position.z << std::endl;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

4. C++踩过的坑

4.1. VectorXd和Vector3d的使用区别

Eigen::Vector3d first_point(p.x, p.y, p.z);
Eigen::Vector3d lla_point;
geo_converter.Reverse(first_point[0], first_point[1], first_point[2], lla_point[0], lla_point[1],
                      lla_point[2]);
lla_vec.push_back(lla_point);

// 存储WGS84下的XYZ和四元数
Eigen::VectorXd wgs84Xyz_orientation = Eigen::VectorXd::Zero(7);
earth.Forward(lla_point[0], lla_point[1], lla_point[2], wgs84Xyz_orientation[0], wgs84Xyz_orientation[1],
                   wgs84Xyz_orientation[2]);
wgs84Xyz_orientation[3] = laserOdometryROS.pose.pose.orientation.x;
wgs84Xyz_orientation[4] = laserOdometryROS.pose.pose.orientation.y;
wgs84Xyz_orientation[5] = laserOdometryROS.pose.pose.orientation.z;
wgs84Xyz_orientation[6] = laserOdometryROS.pose.pose.orientation.w;
wgs84Xyz_quaternion_vec.push_back(wgs84Xyz_orientation);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

上面的代码中lla_point没有初始化,也可以放在geo_converter.Reverse中进行使用,可是wgs84Xyz_orientation就没有这么幸运了,需要初始化才能在earth.Forward中使用。
也就是说想使用代码Eigen::VectorXd 中的变量,必须先初始化,才能使用wgs84Xyz_orientation[0]。而Vector3d不需要初始化。可以参考:链接: link

4.2. GeographicLib::Geocentric earth

GeographicLib::Geocentric earth的定义不能用下面代码块中的注释赋值,这一步我不知道为什么,最后使用上面这句话就调试成功了,现在我还是不明白,下面注释的代码中提供了构造函数,不知道为什么构造不出来。

    GeographicLib::Geocentric earth = GeographicLib::Geocentric(GeographicLib::Constants::WGS84_a(), GeographicLib::Constants::WGS84_f());
    // GeographicLib::Geocentric earth1(GeographicLib::Constants::WGS84_a(), GeographicLib::Constants::WGS84_f());
  • 1
  • 2

4.3. vector中的erase函数

使用erase函数,会删除掉对应元素,此时for循环中的i++就可能会跳过到下一个元素,因此这里删除之后,增加了一个isMerged变量,如果是false,那么就i++,否则出现删除的情况,就可以继续下次循环了。

    vector<GroupProp> mergedGroups;
    for (int i = 0; i < carGroup.size(); ) {
        bool isMerged = false;
        for (int j = 0; j < unknownGroup.size(); ) {
            double deltaX = abs(carGroup[i]._center.x - unknownGroup[j]._center.x);
            double deltaY = abs(carGroup[i]._center.y - unknownGroup[j]._center.y);
            double diagonal = sqrt(deltaX * deltaX + deltaY * deltaY);
            if (deltaX <= 4.68 && deltaY <= 1.7 && diagonal <= 4.9) {
                // 合并group
                GroupProp mergeGroup = carGroup[i] + unknownGroup[j];
                mergeGroup._object = Car;
                mergedGroups.push_back(mergeGroup);
                // 合并后删除carGroup[i]中的元素和unknownGroup[j]中的元素
                carGroup.erase(carGroup.begin() + i);
                unknownGroup.erase(unknownGroup.begin() + j);
                
                mergeNum++;
                std::cout << "mergeNum is %d  " << mergeNum << std::endl;
                
                isMerged = true;
                break;
            } else {
                j++;
            }
        }
        if (!isMerged) {
            i++;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

4.4 extern和static

二者的使用过程中,声明和定义均要分开,要不然无法使用。这两个关键字我都踩了两次坑,都是将声明和定义写在了一起,然后就报错。

4.4.1 extern

extern的作用域可见extern

//stdafx.h
enum BoxType{AABB,OBB}; // 边界框类型
extern BoxType boundingBox;
//stdafx.cpp
BoxType boundingBox = AABB;
  • 1
  • 2
  • 3
  • 4
  • 5

然后再在别的cpp使用,此时使用如下:

// main.cpp
#include "stdafx.h"
extern BoxType boundingBox;
int main(int argc, char **argv) {
  // other Codes
  boundingBox = boundingType == 0 ? AABB : OBB;
  // ***
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4.4.2 static

定义和声明,要分来写

// obs_cluster.h
class CTrackersCenter{
  public:
  static std::vector<Tracker> sPastTracker;
}
// obs_cluster.cpp
std::vector<Tracker> CTrackersCenter::sPastTracker = {};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4.4.3 声明与定义

变量的声明用于向程序表明变量的类型和名字,当对一个变量进行声明时,编译器不会为其分配内存空间。可以通过使用extern关键字声明变量名而不定义它。不定义的变量的声明包括声明的对象类型,对象名和关键字extern。
变量的定义用于为变量分配存储空间,还可以为变量指定初始值,在一个程序中只能定义一次,出现多次编译器会报错,变量的定义也是声明,当定义一个变量的时声明了它的类型和名字。
注意:声明可以多次,定义在整个程序中只能有一次,定义的同时会为变量分配内存空间

extern int i; //声明,但是没有定义 
int i; //声明,也是定义 
  • 1
  • 2

5. Ubuntu踩过的坑

我都不知道什么时候给我ubuntu 下面的.bashrc文件改掉了,而且还加了几行代码,

export  CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/usr/include/pcl-1.10:/usr/include/eigen3:/usr/include/vtk-7.1:/home/zhao/softwares/LAStools-master:/media/zhao/ZhaoZhibo/Codes/RoadsideNotes/RoadsideNotes_add_Carto/catkin_ws/src/cartographer:/media/zhao/ZhaoZhibo/Codes/RoadsideNotes/RoadsideNotes_add_Carto/catkin_ws/src/cartographer_ros:/usr/include/lua5.3/:/usr/lib/x86_64-linux-gnu/
export CMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH:/media/zhao/ZhaoZhibo/Codes/RoadsideNotes/RoadsideNotes_add_Carto/catkin_ws/build_isolated/cartographer/install_isolated
  • 1
  • 2

我说为什么catkin_make挂掉了,而且还去访问我的移动硬盘上的路径,不知道啥时候自动给我添加了一个路径。然后直接注释上述代码,而是source一下这个文件就好了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/496711
推荐阅读
相关标签
  

闽ICP备14008679号