本系列文章是 2024 春季学期北航计算机学院本科生课程《软件工程》(嵌入式方向)的实验部分报告,不包含团队大作业项目内容与相关细节

任务0-ROS配置与话题通信

Ubuntu系统安装

北航云盘(提取码:0GhE)下载 Ubuntu 18.04 版本系统,因为只有 18.04 对应的 ROS 版本是 melodic,其他的版本有所不同。

第一步是创建共享文件夹,首先在虚拟机设置—选项中启用共享文件夹,再在虚拟机中挂载文件夹:

sudo mount -t fuse.vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other

melodic(ROS)安装

wget http://fishros.com/install -O fishros && . fishros

image-20240312204427183

利用鱼香 ROS 安装 ROS 系统,注意安装过程中要选择 melodic 以及 melodic(桌面版)。桌面版有一些可视化的库,在后续展示小车状态时十分有效。

安装后使用 roscore 指令在终端测试 ROS 是否安装成功

cookedbear@ubuntu:~$ roscore
... logging to /home/cookedbear/.ros/log/a0f68c1a-e06e-11ee-9294-000c29175981/roslaunch-ubuntu-36422.log
Checking log directory for disk usage. This may take a while.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

started roslaunch server http://ubuntu:46803/
ros_comm version 1.14.13

创建ROS项目

第一步是创建项目工作目录与环境,首先进入 src 文件夹,在终端中运行 catkin_init_workspace 完成初始化,然后回到上一级目录运行 catkin_make 编译建好的工作空间

mkdir yknb
mkdir yknb/src
cd yknb/src
catkin_init_workspace
cd ..
catkin_make
source ./devel/setup.bash

ROS节点话题通信

首先创建功能包,然后使用 Python 语言新建两个脚本,分别执行 PublisherSubscriber 的功能。

catkin_create_pkg iamyk

Python 代码如下:

#!/usr/bin/env python

# talker.py
import rospy
from std_msgs.msg import String

def talker():
pub = rospy.Publisher('chatter', String, queue_size=10)
rospy.init_node('talker', anonymous=True)
rate = rospy.Rate(10) # 10hz
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()

if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass
#!/usr/bin/env python

# listener.py
import rospy
from std_msgs.msg import String

def callback(data):
rospy.loginfo(rospy.get_caller_id() + 'I heard %s', data.data)

def listener():

# In ROS, nodes are uniquely named. If two nodes with the same
# name are launched, the previous one is kicked off. The
# anonymous=True flag means that rospy will choose a unique
# name for our 'listener' node so that multiple listeners can
# run simultaneously.
rospy.init_node('listener', anonymous=True)

rospy.Subscriber('chatter', String, callback)

# spin() simply keeps python from exiting until this node is stopped
rospy.spin()

if __name__ == '__main__':
listener()

两段代码利用 std_msgs.msg 作为传递字符串的载体,由 talker.py 在指定话题中以固定的频率循环发送信息;listener.py 同样加入该话题,并接收发送的 msg 信息,转化为字符串打印在控制台中

随后修改 CMakeLists.txt 文件,将原本注释的 python 脚本还原,并且加入两个新的脚本:

catkin_install_python(PROGRAMS
scripts/talker.py
scripts/listener.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

设置完毕后,使用 catkin_make 重新编译项目,即可分别在两个命令行中运行两个节点:

cookedbear@ubuntu:~/Desktop/ros/yknb$ rosrun iamyk talker.py
[INFO] [1710258107.379227]: hello world 1710258107.3791575
[INFO] [1710258107.479932]: hello world 1710258107.4797711
[INFO] [1710258107.579850]: hello world 1710258107.5796387
[INFO] [1710258107.679717]: hello world 1710258107.679525
[INFO] [1710258107.780339]: hello world 1710258107.7801197
[INFO] [1710258107.880397]: hello world 1710258107.8802269
[INFO] [1710258107.979713]: hello world 1710258107.9794989
[INFO] [1710258108.079838]: hello world 1710258108.0796237
cookedbear@ubuntu:~/Desktop/ros/yknb$ rosrun iamyk listener.py
[INFO] [1710258131.381349]: /listener_3772_1710258131254I heard hello world 1710258131.380313
[INFO] [1710258131.482291]: /listener_3772_1710258131254I heard hello world 1710258131.4802547
[INFO] [1710258131.581786]: /listener_3772_1710258131254I heard hello world 1710258131.5797513
[INFO] [1710258131.681842]: /listener_3772_1710258131254I heard hello world 1710258131.6798933
[INFO] [1710258131.781949]: /listener_3772_1710258131254I heard hello world 1710258131.77978

在节点运行过程中,使用 rosnode 打印节点名、查询详细信息:

cookedbear@ubuntu:~/Desktop/ros/yknb$ rosnode list
/listener_3802_1710258195435
/rosout
/talker_3826_1710258197701
cookedbear@ubuntu:~/Desktop/ros/yknb$ rosnode info /talker_3826_1710258197701
--------------------------------------------------------------------------------
Node [/talker_3826_1710258197701]
Publications:
* /chatter [std_msgs/String]
* /rosout [rosgraph_msgs/Log]

Subscriptions: None

Services:
* /talker_3826_1710258197701/get_loggers
* /talker_3826_1710258197701/set_logger_level


contacting node http://ubuntu:45411/ ...
Pid: 3826
Connections:
* topic: /chatter
* to: /listener_3802_1710258195435
* direction: outbound (38897 - 127.0.0.1:40302) [10]
* transport: TCPROS
* topic: /rosout
* to: /rosout
* direction: outbound (38897 - 127.0.0.1:40306) [8]
* transport: TCPROS

同样可以使用命令行 rostopic 对话题进行相关信息的查阅:

cookedbear@ubuntu:~/Desktop/ros/yknb$ rostopic list
/chatter
/rosout
/rosout_agg
cookedbear@ubuntu:~/Desktop/ros/yknb$ rostopic info /chatter
Type: std_msgs/String

Publishers:
* /talker_3826_1710258197701 (http://ubuntu:45411/)

Subscribers:
* /listener_3802_1710258195435 (http://ubuntu:36141/)


cookedbear@ubuntu:~/Desktop/ros/yknb$ rostopic echo /chatter
data: "hello world 1710258298.9224079"
---
data: "hello world 1710258299.022878"
---
data: "hello world 1710258299.1224391"
---
data: "hello world 1710258299.2226434"
---
data: "hello world 1710258299.3219335"
---
data: "hello world 1710258299.4222023"

接着新建一个 launch 文件夹和 launcher.launch 文件,实现多节点的同时工作:

<launch>
<node pkg="iamyk" type="talker.py" name="talker1" />
<node pkg="iamyk" type="talker.py" name="talker2" />
<node pkg="iamyk" type="listener.py" name="listener" />
</launch>

最后使用 rqt_graph 生成节点关系图:

image-20240312234728955