3.开机自启动ROS控制手柄节点
0x00 开机自启动需求
当程序调试差不多后,就可以来配置开机自启动了。因为该控制手柄需要在ubuntu系统上电启动后,一进入正常工作状态时就要自动加载运行。这样就能省去手动输入命令运行launch文件的步骤,这里使用的方法是编写一个开机自启动的服务。当然在本教程中的开机自启动方法也可以用在其他ROS项目中,只需要根据新项目的配置稍微进行修改一下即可。
0x01 项目代码架构
下面结合前面两篇教程编写的代码,来整体介绍下当前项目的目录结构,如下图所示:
由图可知,这里新增了一个control_handle_bringup的软件包。该软件包算是整个ROS项目的入口,这个软件包里面一般只有一个launch文件夹,里面的launch文件用来启动项目其他软件包的launch文件。以后需要注意,一般在ROS项目开发中,了解整个项目架构的入口就是由bringup软件包入手。由于该软件包没有其他实际功能,所以在创建该软件包时也就没有什么依赖项了。一般都是使用下面的命令来创建bringup软件包:
catkin_create_pkg control_handle_bringup
当创建好bringup软件包后,在其中在mkdir一个launch文件夹。在launch文件夹中再编写bringup的launch文件即可,这里我给launch文件命名为control_handle_bringup.launch,具体代码如下:
<!-- Copyright: 2016-2018 ROS小课堂 www.corvin.cn Author: corvin Description:该启动文件负责启动控制手柄的所有节点,使其进入正常工作状态. History: 20181218: Initial this launch file. --> <launch> <!--startup ros handle python node --> <include file="$(find ros_handle_python)/launch/ros_handle.launch" /> </launch>
由于该项目中只有一个ROS软件包负责解析下位机的数据帧,整个项目目前还比较简单,所以bringup中只启动一个launch文件。随着项目的不断扩大,这里的launch文件可以添加更多的要启动的launch文件。
0x02 编写自启动服务
首先来看下软件包目录下的scripts文件夹存储的文件,如下图所示:
在scripts文件夹中,新建了service文件夹。这是用来存储跟服务相关的脚本,其中ros_control_handle.service是自定义的服务文件,该文件源码如下:
[Unit] Description=power on startup ros control handle node - by corvin After=network.target [Service] Type=simple Restart=always RestartSec=10 ExecStart=/usr/bin/ros_control_handle_start ExecStop=/usr/bin/ros_control_handle_stop Restart=on-failure [Install] WantedBy=multi-user.target
在介绍这个服务文件前,我们需要先对systemd有个简单认识才行。systemd它是一个Linux系统基础组件的集合,它提供了一个系统和服务的管理器,运行的PID为1并负责启动其它程序。监视和控制systemd的主要命令是systemctl,该命令可用于查看系统状态和管理系统及服务。
在这里需要特别注意的是[Service]字段下的ExecStart和ExecStop两个参数,后面有对应的执行脚本。当启动该服务时,它就会自动调用ExecStart后面的脚本。当停止该服务时,它就会自动调用ExecStop后面的脚本。这里来分别介绍这两个脚本,下面先看ros_control_handle_start脚本,代码如下:
#!/bin/bash # Copyright: 2016-2018 ROS小课堂 www.corvin.cn # Author: corvin # Description: when poweron auto launch ros control handle node. # History: # 20181214: initial this bash file. source /opt/ros/kinetic/setup.bash cd /home/corvin/ros_control_handle/ros_code/ catkin_make source /home/corvin/ros_control_handle/ros_code/devel/setup.bash export ROS_IP=192.168.138.227 roslaunch control_handle_bringup control_handle_bringup.launch exit 0
该脚本中主要就是配置了下ROS的各环境变量,这里特别需要注意这个export ROS_IP,这个要根据自己ROS系统中手柄连接的主机IP地址来修改。最后就是通过roslaunch来启动相应项目的bringup.launch文件即可。
下面来看ros_control_handle_stop脚本,代码如下:
#!/bin/bash # Copyright: 2016-2018 ROS小课堂 www.corvin.cn # Author: corvin # Description: Stop ros control handle node. # History: # 20181214: initial this bash file. source /opt/ros/kinetic/setup.bash pid=`ps -ef|grep control_handle_bringup.launch|grep -v grep|awk '{print $2}'` if [ -n "$pid" ] then rosnode kill /handle_python_node rosnode kill /handle_dynamic_reconfig echo "kill control_handle_bringup.launch pid:" $pid sudo kill -9 $pid fi exit 0
通过该脚本可以发现停止服务,其实就是停止启动的相应的ROS节点和launch文件。在调用rosnode这个ros系统提供的命令时,需要先source一下ros中的环境变量才行。否则可能会提示无法找到rosnode命令。
0x03 安装和卸载服务
为了方便的安装和卸载服务,这里编写了相应的脚本。这样就很方便了,下面先来介绍安装服务的脚本install_service.sh,脚本代码如下:
#!/bin/bash # Copyright: 2016-2018 ROS小课堂 www.corvin.cn # Author: corvin # Description: install ros control handle service to /lib/systemd/system,this will # auto roslaunch handle when poweron. # History: # 20181214: initial this bash file. sudo cp ./service/ros_control_handle_start /usr/bin/ sudo cp ./service/ros_control_handle_stop /usr/bin/ sudo cp ./service/ros_control_handle.service /lib/systemd/system/ sudo systemctl enable ros_control_handle.service sudo systemctl start ros_control_handle.service exit 0
由上述代码可以得知,其实安装配置服务就是将相应的脚本和服务文件,复制到指定的文件夹中。然后调用systemctl相应命令来使能和启动服务:
sudo systemctl enable ros_control_handle.service:这个是用来使能服务,这样该服务就可以在每次开机的时候自动加载服务运行。
sudo systemctl start ros_control_handle.service:这个是立刻启动服务,这样就可以立刻调用ros_control_handle_start脚本来启动bringup了。
下面来看卸载服务的脚本uninstall_service.sh,具体代码如下:
#!/bin/bash # Copyright: 2016-2018 ROS小课堂 www.corvin.cn # Author: corvin # Description: Uninstall ros_control_handle.service. # History: # 20181214:initial this bash file. pid=`ps -ef|grep control_handle_bringup|grep -v grep|awk '{print $2}'` if [ -n "$pid" ] then /usr/bin/ros_control_handle_stop fi sudo systemctl disable ros_control_handle.service sudo rm /usr/bin/ros_control_handle_start sudo rm /usr/bin/ros_control_handle_stop sudo rm /lib/systemd/system/ros_control_handle.service exit 0
由代码可知,卸载该服务其实就是先调用ros_control_handle_stop,停止当前运行的launch文件和ros节点。然后禁用该服务,这样该服务在下次开机时就不会自动启动运行了。然后再删除相应目录中的脚本和服务文件即可,这样我们就把该开机自启动服务给彻底卸载了。
0x04 运行测试
当编写好所有的脚本和服务后,接下来我们就可以来测试了。下面来分步依次测试所有的功能:
(1)测试安装服务脚本install_service.sh是否正常:
另外,还可以通过使用如下命令来查看是否开机自启动该服务了,命令如下:
systemctl is-enabled ros_control_handle.service
还可以通过如下命令来查看当前服务的运行状态,命令如下:
systemctl status ros_control_handle.service
(2)停止/启动当前服务的运行
有时候我们需要停止当前服务的运行,例如想要调试一下代码什么的。当调试好代码后,又需要立刻运行该服务。那么就需要运行如下命令,先介绍停止运行服务的命令:
sudo systemctl stop ros_control_handle.service
现在再来启动下服务,使用如下命令即可:
sudo systemctl start ros_control_handle.service
(3)使能/禁止服务开机启动
首先来介绍查看是否使能开机自启动服务,该命令前面介绍过,命令如下:
systemctl is-enabled ros_control_handle.service
使能开机自启动服务命令:sudo systemctl enable ros_control_handle.service
禁用开机自启动服务命令:sudo systemctl disable ros_control_handle.service
(4)使用journalctl查看Unit启动日志
systemd有自己的日志系统,被成为journal。使用systemd日志,无需安装额外的日志服务(syslog)。下面就来简单介绍下journalctl(journal + ctrl的缩写)命令:
-
查看指定服务的日志
journalctl -u ros_control_handle.service
在-u参数后面加上需要查看日志的服务名称,在输入服务名时,可以使用tab键的自动补全功能,用起来很方便。
-
查看日志的最新几行
随着服务的不断运行,日志肯定会越来越多。如果我们只使用上面那条命令的话,开始旧的日志在最上面,最新的日志会在最后面。这样每次查看的时候都要拉到最下面,这样很费时间。因此可以新增一个参数-n,这样就可以只查看最新几行的日志了。假如打算只查看最新10行ros_control_handle.service的日志,就可以使用如下的命令:
journalctl -u ros_control_handle.service -n 10
-
要持续跟踪最新的输出日志
上面命令中的-n参数,可以一下输出最新的几行日志。但这只是一次性的输出,没办法持续跟踪。如果要想持续不断的跟踪最新的日志输出,可以使用-f参数,只要不中断该命令,就会一直跟踪日志输出。假如想要持续跟踪查看ros_control_handl.service最新的日志,命令如下:
journalctl -u ros_control_handle.service -f
0x05 References
[1]. corvin_zhang. 树莓派ubuntuMate系统中开机自启动ROS的launch文件.
[2]. archLinux wiki. systemd(简体中文).
https://wiki.archlinux.org/index.php/systemd_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)
[3]. 百度文库. linux编写systemd下服务脚本.
https://wenku.baidu.com/view/a3d2f911f705cc17552709f4.html
[4]. 小李子博客. journalctl工具基础介绍. http://blog.51cto.com/13598893/2072212
[5]. ITer奋斗点滴(IT兄弟盟). systemd日志系统.
https://www.cnblogs.com/itxdm/p/Systemd_log_system_journalctl.html
0x06 Feedback
大家在按照教程操作过程中有任何问题,可以直接在文章末尾给我留言,或者关注ROS小课堂的官方微信公众号,在公众号中给我发消息反馈问题也行。我基本上每天都会处理公众号中的留言!当然如果你要是顺便给ROS小课堂打个赏,我也会感激不尽的,打赏30块还会被邀请进ROS小课堂的微信群,与更多志同道合的小伙伴一起学习和交流!