目录
1. ros的技巧命令
- rosbag暂停播放 :
rosbag play --clock --pause bagfile.bag
,通过空格来开始暂停和继续。rosbag play --pause bagfile.bag
,一帧帧点云播放,按s
键播放下一帧,通过空格来暂停和继续。rosbag play bagfile.bag -r 0.1
,慢速播放,后面的0.1即为播放的速度,如果改为10,即为10倍播放速度。 - roslaunch重定向,方便调试代码 :
roslaunch lio_sam run.launch 2>&1 | tee log.txt
, 该命令既能输出到屏幕,也可以打印信息到文件中。 - 清理ros磁盘:
rosclean purge
- 调用tf树:
rosrun rqt_tf_tree rqt_tf_tree
- 播放一个包的部分话题:
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
- 调用plotjuggler: 可以看数据中的时间戳是否是一致的,
rosrun plotjuggler plotjuggler
- 警告信息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
- 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
。 - 保存LIO-SAM-6AIXS的结果:
rosservice call /lio_sam_6axis/save_map
- roabag数据包转换成pcd的命令:
rosrun pcl_ros bag_to_pcd ../40m_RsLidar.bag /velodyne_points ./
- rosbag包分割成两部分: 链接: 分割rosbag包
- 查看ubuntu系统:一般在下载ubuntu的安装包时,会让选择是arm64还是x86,可以通过命令
uname -m
查看系统版本,我的系统是x86_64,x64也被称为x86_64,因为x64是从x86延伸过来的。
2. catkin_make问题记录与方案
- 全局查找linux中的文件:
sudo find / -name Python3.framework
或者locate Eigen
进行模糊查询 - catkin_make报错:找不到分享的so文件,具体为Linux error while loading shared libraries: cannot open shared object file: No such file or directory: 参考链接: link,
sudo find / -name the_name_of_the_file.so
,echo $LD_LIBRARY_PATH
,export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/my_library/
。 - 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。
- catkin_make报错error: curl: /usr/local/lib/libcurl.so.4: no version information available (required by curl),主要是软链接错误:参考链接:link,
locate libcurl.so.4
,ls -l /softwares/anaconda3/lib/libcurl.so.4
,rm /softwares/anaconda3/lib/libcurl.so.4
,ln -s /snap/curl/1679/lib/libcurl.so.4.8.0 /softwares/anaconda3/lib/libcurl.so.4
,ls -l /softwares/anaconda3/lib/libcurl.so.4
。 - 打印环境变量:
echo $PATH
,echo $LD_LIBRARY_PATH
,echo $CPLUS_INCLUDE_PATH
- 进入到Conda,用c++画图:进入环境
conda activate
, 退出环境conda deactivate
,进入forcppEnvs画图环境,conda activate forcppEnvs
- matplotlibcpp.h: No such file or directory:先找到matplotlib-cpp,命令为
sudo find / -name matplotlib-cpp
,接下来将找到的路径放到环境变量中,也就是主目录的.bashrc文件中,如下***/matplotlib-cpp
,之后source下,source ~/.bashrc
,重新编译即可。
主要思路就是catkin在编译的时候找不到头文件,将头文件给到编译的文件即可,可以在环境变量中添加,也可以在
Cmakelists
添加,我直接在环境变量中添加,以后写新的代码,就不用再麻烦添加了。
3. C++的技巧
- 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;
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);
上面的代码中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());
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++;
}
}
4.4 extern和static
二者的使用过程中,声明和定义均要分开,要不然无法使用。这两个关键字我都踩了两次坑,都是将声明和定义写在了一起,然后就报错。
4.4.1 extern
extern
的作用域可见extern。
//stdafx.h
enum BoxType{AABB,OBB}; // 边界框类型
extern BoxType boundingBox;
//stdafx.cpp
BoxType boundingBox = AABB;
然后再在别的cpp使用,此时使用如下:
// main.cpp
#include "stdafx.h"
extern BoxType boundingBox;
int main(int argc, char **argv) {
// other Codes
boundingBox = boundingType == 0 ? AABB : OBB;
// ***
}
4.4.2 static
定义和声明,要分来写。
// obs_cluster.h
class CTrackersCenter{
public:
static std::vector<Tracker> sPastTracker;
}
// obs_cluster.cpp
std::vector<Tracker> CTrackersCenter::sPastTracker = {};
4.4.3 声明与定义
变量的声明用于向程序表明变量的类型和名字,当对一个变量进行声明时,编译器不会为其分配内存空间。可以通过使用extern关键字声明变量名而不定义它。不定义的变量的声明包括声明的对象类型,对象名和关键字extern。
变量的定义用于为变量分配存储空间,还可以为变量指定初始值,在一个程序中只能定义一次,出现多次编译器会报错,变量的定义也是声明,当定义一个变量的时声明了它的类型和名字。
注意:声明可以多次,定义在整个程序中只能有一次,定义的同时会为变量分配内存空间
extern int i; //声明,但是没有定义
int i; //声明,也是定义
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
我说为什么catkin_make挂掉了,而且还去访问我的移动硬盘上的路径,不知道啥时候自动给我添加了一个路径。然后直接注释上述代码,而是source一下这个文件就好了。