move_base.cpp
中用到的多线程:1
2
3
4
5boost::condition_variable_any planner_cond_;
boost::thread* planner_thread_;
boost::recursive_mutex planner_mutex_;
代价地图里有个锁mutex_t
,其实就是boost::recursive_mutex
,膨胀层里还用到了读写锁boost::shared_mutex* access_
move_base
里用的锁主要是boost::recursive_mutex planner_mutex_
,而且是和boost::unique_lock
, boost::recursive_mutex::scoped_lock
搭配使用。
使用到planner_mutex_
的函数有planThread
, executeCb
, executeCycle
(6次), resetState
。其他3个函数,每个都只使用了一次planner_mutex_
只有一次是在生成路径后,交互变量。其他全是和planThread
有关的,基本是对runPlanner
赋值,比如1
2
3
4
5boost::unique_lock<boost::recursive_mutex> lock(planner_mutex_);
planner_goal_ = goal;
runPlanner_ = true;
planner_cond_.notify_one();
lock.unlock();
经过我大量修改,move_base
在有导航任务时,如果ctrl+C退出,终端必定会出现下面的错误,虽然毫无影响,但是毕竟不优雅
这个错误是在有锁的情况下,仍然加锁。 也就是多调用了lock()
函数。
搜索move_base,发现只有7个lock()
。逐个查看,由于是退出时的报错,所以不可能是makePlan
的那个,很容易发现是planThread
函数最后的那个。加上判断即可解决1
2if( !lock.owns_lock() )
lock.lock();
对于其他使用lock()
的地方,最好也加上这个判断。
1 | [ WARN] [1709619594.875225471]: Control loop missed its desired rate of 300.00 Hz... the loop actually took 0.0087 seconds |
这个问题与时间同步和TF有关,在本地打开Rviz和SSH运行远程程序时,有很小概率出现此错误。
最好在ubuntu18.04编译,如果是20.04会出现PCL和OpenCV
不兼容的问题。
同ROS的工作空间,在根目录执行 colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release
如果编译时提示缺失目录,可手动去创建。
如果CPU不够强,可能需要单独编译某些包,比如lidar_localizer
: colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release --packages-select lidar_localizer
我编译的最终结果1
2Summary: 165 packages finished [7min 55s]
6 packages had stderr output: lanelet2_python op_simulation_package op_utilities trafficlight_recognizer way_planner waypoint_maker
同ninja
类似,colcon
编译的结果在install
目录里,运行的launch实际也是install
目录的,修改源码的cpp和launch后,都需要编译。
world_test_citysim_b.launch
中有一句1
<rosparam file="$(find vehicle_model)/config/controller.yaml" command="load"/>`
打开yaml文件发现有这样的内容1
2joint_state_controller:
type: joint_state_controller/JointStateController
安装插件 sudo apt-get install -y ros-melodic-*-controllers
启动world_test_citysim_a.launch
后,城市环境很快会出现,但是salon前面的白色车要过一会才能出现,这是我们要操作的车。
先写一个脚本file.sh
放在/etc/rc.d/init.d
,chmod -f 777 file
, 再ln -s file /etc/rc.d/rc0.d/K01file
与 /etc/rc.d/rc6.d/K01file
, 同时也要 ln -s file /etc/rc.d/rc3.d/S99file
与 ln -s file /etc/rc.d/rc5.d/S99file
1
2
3
4
5sudo ln -s shell_name /etc/rc0.d/K07shell_name
sudo ln -s shell_name /etc/rc3.d/S99shell_name
sudo ln -s shell_name /etc/rc5.d/S99shell_name
sudo ln -s shell_name /etc/rc6.d/K07shell_name
sudo touch /var/lock/subsys/shell_name
K开头的代表系统关闭的时候执行,S开头的代表开机的时候执行。注意服务器脚本编写的规范,因为有K开通的软链接并不一定会在关机的时候自动去执行,因为执行K脚本的时候会查询/var/lock/subsys/
是否有与K开头脚本同名的空文件名,如果没有就不去执行,所以要按照服务器脚本编写的规范,启动的时候要在/var/lock/subsys/
先touch一个与K01后面同名的空文件. 同时也要调用/etc/rc.d/init.d/functions
能够接受star与stop命令信号,具体可以参考/etc/rc.d/rc
文件
K*
/etc/rc6.d
包含重启脚本K*
Linux关机过程:
在系统关机时,shutdown命令会告诉init程序转换到0运行级别,如果是重新启动则转换到第6运行级别。当进入0或者6运行级别后,系统将会依照下面的顺序运行:
init关闭所有它能关闭的进程(转换到其他运行级别也一样)
rc0.d/rc6.d
目录下的第一个命令开始运行,锁定系统文件为关机作准备
rc0.d/rc6.d
目录下的第二个命令运行,卸载除根文件系统以外的所有文件系统(如挂载的windows分区)
rc0.d/rc6.d
中的命令将把根文件系统重新挂载为只读属性
rc0.d/rc6.d
中的命令调用sync程序把缓存中的数据写入文件系统
最后的命令是重新启动或者关闭内核程序
即使是手动断电,也会执行脚本。但是注意:如果是耗时的脚本命令,断电时间太快,来不及执行。但如果是shutdown
或reboot
命令,是可以执行的
1 | user@user:~/nav$ rosrun test test_node |
安装完ROS后,运行roscore报错1
Traceback (most recent call last): File "/opt/ros/groovy/lib/python2.7/dist-packages/roslaunch/__init__.py", line 230, in main write_pid_file(options.pid_fn, options.core, options.port) File "/opt/ros/groovy/lib/python2.7/dist-packages/roslaunch/__init__.py", line 106, in write_pid_file with open(pid_fn, "w") as f: IOError: [Errno 13] Permission denied: '/home/user/.ros/roscore-11311.pid'
注意rosdep update
不要用sudo,解决方法:sudo rosdep fix-permissions
,然后rosdep update
在一堆报错的最后是:1
InvalidURL: URL can't contain control characters. '192.168.1.35 ' (found at least ' ')
看上去是IP最后多了个空格,改了MASTER_URI
不起作用,最后发现问题是ROS_IP
和 ROS_HOME
,不要再写成hostname -I
,写成192.168.1.35
原因是因为ROS1支持的是Python2.7,而我之前将Ubuntu自带的Python升级到了3.8,也就是默认版本改变了,所以导致了相关的错误。 解决方法
改回来之后,有些程序可能还是需要python3.8,这时运行python3.8 file.py
,可能会报错no module named rospkg
和 no module named pydot
,所以需要pip install rospkg pydot
source setup.bash
出现的错误,发现我用的是zsh,换了之后正常
执行ROS命令结果报错 Network communication failed
这可能是当前用户没有这个权限,切换到root
再试试
这是因为之前运行过了,可以无视这个问题
环境变量没设置好,应当是IP和端口组合
对用到的某个文件没有给权限,找到执行chmod 755
即可
roscore
和rosrun
可以正常运行,但是rosnode list
只有rosout
,rostopic list
没有任何话题。无法用命令对节点和话题操作,可能是通信问题。原因不明,重启电脑后正常。
没有安装yaml-cpp或者版本不对,因为rviz读取PersistentSettings文件时需要这个库,下载0.5.1版本的yaml,把之前安装的yaml删掉,重新编译安装。编译生成的几个文件在/usr/local/lib
和/usr/local/include
,如果找不全,就先用现在的版本再编译一遍就知道了
启动bringup.launch
,偶尔会出现这个错误,这是下位机和ROS通讯失败造成的,报错在rosserial,很少发生
后来明白,原因是发布坐标系的节点在ubuntu 20.04
,rqt在ubuntu 18
运行rqt_tf_tree
,会出现 wait_for_service(/rqt_gui_py_node/tf2_frames), failed to contact ,will keep trying , rqt_tf_tree
一直打不开。
原因是IP变动的问题,重新设置IP地址,最好主机与从机都设置为静态ip。
一次没操作好,导致Rviz报错
这个文件是存在的,和其他电脑上正常的Rviz对应的文件路径相同。一直查不到原因,在网上查来查去,反复查ogre
这个库是不是装的出问题了,还以为是OpenGL版本变高了,其实这是显卡决定的。最后终于发现链接的librviz.so
不是官方路径的,而是我自己工作空间的。可以先用官方的替换
硬盘空间耗尽
1 | The build space at '/home/user/catkin_ws/build' was previously built by ''. Please remove the build space or pick a different build space. |
原因是硬盘空间耗尽
执行任何ROS命令都会报错 Unable to communicate with master
已经运行了ROS节点,结果发现什么ROS命令都会报这个错,后来终于发现,启动节点的环境变量是一套,后来改了,ROS命令都报这个错误。注意ROS_IP
如果使用名称而不是数字,必须是/etc/hosts
里定义的。
Rviz一个关于时间戳的报错,不必理会 Detected jump back in time of 0.223145s. Clearing TF buffer.
客户端的报错:1
ERROR: service [/task_dispatcher] responded with an error: b'Error opening file: '
服务端的报错:1
Exception thrown while processing service call: Error opening file
其实是代码中有错误,而且这个错误不一定和ROS有关,其他问题也会出现这个报错。