ros配置开机自启动

最近在做 RM 项目,需要配置 ros 的开机自启动。原本以为一个上午就能搞定的,结果难度远远超过我的预期,我是从早上配到晚上,才终于解决了。所以在这里记录下来,以便不时之需。

1.先导知识

在配置之前,首先需要了解 Linux 中的 systemd 系统服务和 ros 的 launch 文件的编写。这些在网上都能找到的。

由于我之前就了解过 systemd 的基本写法,所以我只是了解了一下 launch 文件的书写,主要使用到以下几个内容:

<launch>
    <node name="" pkg="" type="" respawn="" output="">
launch>
  • launch 表示一个launch文件的开始位置和结束位置
  • node 表示声明一个节点,其中有name、pkg、type、respawn、output 等参数,但我们只需要使用到这里列举的几个参数。
    • name:节点名称,即执行 launch 后创建的节点名称
    • pkg:启动的功能包名称
    • type:类型,一般为 CMakeLists.txt 中 set_target_properties 里面的命名,在我们项目中一般命名为 node
    • respawn:是否重启,默认为 false。设为 true 的话,系统会一直监听这个节点,如果发现这个节点结束运行(无论正常非正常),则会立即重启这个节点。在我们的项目中,我们会把它设为 true
    • output:输出位置,可选择 log(默认) 或 screen。log 则表示输出会重定位到一个 log 文件中,而 screen 表示输出会显示在屏幕上。不过这个对我们来说影响不大,所以我们最后也没考虑。

关于 pkg 和 type 的另一种说明

一般我们在启动一个功能包时,都会运行以下命令

rosrun arg1 arg2

在 launch 中,pkg 对应着 arg1,type 对应着 arg2。

2.配置过程

一个很简单的思路,就是用 launch 文件写好启动的节点,然后用 shell 文件执行 roslaunch 命令,然后把这个 shell 文件加入到 systemd 服务中去。看起来挺简单的吼,我也是这么想的,但花了我不少的时间,因为中间遇到了几个问题。

问题一:运行路径的问题

一般我们在执行 rosrun 的时候,运行路径都会在当前项目的最高目录下(例如 ~/catkin_ws )。但是使用 launch 执行的时候,执行目录就变到了其它地方。这会导致 在程序中使用相对路径读取模型和配置文件时找不到文件 的问题。具体表现如下:
ros配置开机自启动_第1张图片

可以看到,上述所有配置参数要么为 0,要么为空字符串。这说明我们读取配置文件失败了。这基本可以断定是因为程序实际执行的位置跟 rosrun 不同导致的。

我们可以看到 roslaunch 执行之后的输出:
在这里插入图片描述

这说明我们的这个程序注册到 ~/.ros 文件夹下了,并不是当前文件夹,所以会导致读取配置文件的失败。

之后,我参考了这篇博客:点击这里

发现可以通过设置 ROS_HOME 环境变量对执行目录进行调整。于是我在执行 roslaunch 前执行了以下命令:

export ROS_HOME=`pwd`

之后再运行 roslaunch 就正常了
在这里插入图片描述

然后这个是接收到的数据
ros配置开机自启动_第2张图片

至此,这个问题总算是解决了。

问题二:sudo 找不到 roslaunch 命令

当我信心满满配置上自启动后,发现相机灯闪都不闪一下。然后我查看了 status,发现这个服务一直在重启。于是我想起来,开机自启动的服务好像都是在 root 用户态下执行的。所以我试了一下,用 sudo 去执行 launch,结果真的报错了:

ros配置开机自启动_第3张图片

我尝试了很多种方法,包括配置 root 环境变量、再写一个二级调用脚本、使用 C 语言 system 函数写,但都是报这个问题。之后我参考了之前这个人写的能用的一版 ros 的开机自启动,发现差了一个 source。所以我执行了一下 source 再执行 launch,真的成功了!

ros配置开机自启动_第4张图片

这让我明白了一个道理:当没有头绪的时候,不妨看看之前写过的东西,或许就知道哪里错了。

3.总结

其实最关键的一步是 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)

你可能感兴趣的:(笔记,linux,运维,服务器,bash,ubuntu)