最近在做 RM 项目,需要配置 ros 的开机自启动。原本以为一个上午就能搞定的,结果难度远远超过我的预期,我是从早上配到晚上,才终于解决了。所以在这里记录下来,以便不时之需。
在配置之前,首先需要了解 Linux 中的 systemd 系统服务和 ros 的 launch 文件的编写。这些在网上都能找到的。
由于我之前就了解过 systemd 的基本写法,所以我只是了解了一下 launch 文件的书写,主要使用到以下几个内容:
<launch>
<node name="" pkg="" type="" respawn="" output="">
launch>
关于 pkg 和 type 的另一种说明
一般我们在启动一个功能包时,都会运行以下命令
rosrun arg1 arg2
在 launch 中,pkg 对应着 arg1,type 对应着 arg2。
一个很简单的思路,就是用 launch 文件写好启动的节点,然后用 shell 文件执行 roslaunch 命令,然后把这个 shell 文件加入到 systemd 服务中去。看起来挺简单的吼,我也是这么想的,但花了我不少的时间,因为中间遇到了几个问题。
一般我们在执行 rosrun 的时候,运行路径都会在当前项目的最高目录下(例如 ~/catkin_ws )。但是使用 launch 执行的时候,执行目录就变到了其它地方。这会导致 在程序中使用相对路径读取模型和配置文件时找不到文件 的问题。具体表现如下:
可以看到,上述所有配置参数要么为 0,要么为空字符串。这说明我们读取配置文件失败了。这基本可以断定是因为程序实际执行的位置跟 rosrun 不同导致的。
这说明我们的这个程序注册到 ~/.ros 文件夹下了,并不是当前文件夹,所以会导致读取配置文件的失败。
之后,我参考了这篇博客:点击这里
发现可以通过设置 ROS_HOME 环境变量对执行目录进行调整。于是我在执行 roslaunch 前执行了以下命令:
export ROS_HOME=`pwd`
至此,这个问题总算是解决了。
当我信心满满配置上自启动后,发现相机灯闪都不闪一下。然后我查看了 status,发现这个服务一直在重启。于是我想起来,开机自启动的服务好像都是在 root 用户态下执行的。所以我试了一下,用 sudo 去执行 launch,结果真的报错了:
我尝试了很多种方法,包括配置 root 环境变量、再写一个二级调用脚本、使用 C 语言 system 函数写,但都是报这个问题。之后我参考了之前这个人写的能用的一版 ros 的开机自启动,发现差了一个 source。所以我执行了一下 source 再执行 launch,真的成功了!
这让我明白了一个道理:当没有头绪的时候,不妨看看之前写过的东西,或许就知道哪里错了。
其实最关键的一步是 launch 文件的编写和 ROS_HOME。其它的都还算简单。下面是一些关键文件的内容:
start.launch,放在工作目录下:
<launch>
<node name="config_node" pkg="config" type="node" respawn="true"/>
<node name="img_catcher_node" pkg="img_catcher" type="node" respawn="true"/>
launch>
Deploy.sh 放在最高级目录的 Tools 子目录下:
#!/bin/bash
shdir=$(pwd)/FYT2023.sh
shdir_tls=$(pwd)
# 生成 FYT2023.sh 脚本
echo "#!/bin/bash" > $shdir
echo "cd $shdir_tls/../" >> $shdir
echo 'export ROS_HOME=`pwd`' >> $shdir
echo "source devel/setup.sh" >> $shdir
echo "roslaunch start.launch" >> $shdir
#将服务文件FYT2023.service加入到系统服务文件夹中
sudo cp ./FYT2023.service /etc/systemd/system/
#将FYT2023.sh复制到 /bin 文件夹中
sudo cp $shdir /bin/
#给bin中的FYT2023.sh赋予可执行权限
sudo chmod +x /bin/FYT2023.sh
#给当前目录中的FYT2023.sh赋予可执行权限
sudo chmod +x $(pwd)/FYT2023.sh
#刷新系统服务列表
sudo systemctl daemon-reload
#启动系统服务
sudo systemctl enable FYT2023.service
Undeploy.sh 同上
#!/bin/sh
sudo systemctl disable FYT2023.service
sudo rm /etc/systemd/system/FYT2023.service
sudo rm /bin/FYT2023.sh
FYT2023.service 同上:
[Unit]
Description=...
[Service]
#寻找ROS环境依赖
Environment=LD_LIBRARY_PATH=/opt/ros/noetic/share/cv_bridge:/opt/ros/noetic/share/image_transport:/opt/ros/noetic/share/fyt_msg:/opt/ros/noetic/share/roscpp:/opt/ros/noetic/share/sensor_msgs:/opt/ros/noetic/share/std_msgs:/opt/ros/noetic/bin
#执行的目标脚本
ExecStart=/bin/FYT-start.sh
#异常中止后是否重启的选项:一直重启
Restart=always
Type=simple
#重启间隔,1s
RestartSec=1
#重启次数限制:无限制
StartLimitInterval=0
[Install]
WantedBy = multi-user.target
cd Tools
sudo chmod +x Deploy.sh
sudo ./Deploy.sh
sudo ./Undeploy.sh
```![在这里插入图片描述](https://img-blog.csdnimg.cn/f9d99e3088434b7fa63d5e5ea1dd324b.png#pic_center)