文章

交大荣昶杯游记Day2

1 ROS2与视觉操作

1.1 前世今生

201几年,服务机器人,斯坦福大学本来想做一个家务活的机器人,其中最复杂的一项是叠衣服,“不重复造轮子”,开发一套系统,目的:比较复杂的系统分成各个模块;将模块作为通用性的模块,用到其他机器人上。

ROS:Robot Operating System 机器人操作系统。他只是Linux发行版,用于机器人上,但不是真正的操作系统。分布式构建,数据在各个节点上流通。开源系统,庞大的生态社区。

1.2 工作空间和功能包

工作空间(workspace),在 dev_ws 目录下。

下面有五个子目录,其中前四个较为重要:

  • src:代码空间
  • install:安装空间
  • build:编译空间
  • log:日志空间
  • config:配置文件

调用ROS有两种方法:

  1. 调用单个指令(aka “节点”):ros2 run
1
ros2 run teleop_twist_keyboard teleop_twist_keyboard

功能包:功能相似的节点的集合,放到一起去,如 teleop_twist_keyboard

例如,我们要制作的就是一个小车车道线识别的一个功能包。

  1. 运行多个节点,相当于批处理:ros2 launch,文件名需要为 ***.launch.py 。就不用你开很多终端会话运行很多个 ros2 run 了。
1
ros2 launch originbot_bringup originbot.launch.py

1.3 ROS2命令行操作

  • 查看节点信息:ros2 node list ,多个节点之间实现消息的互通,来操控小车。
  • 查看话题信息:ros2 topic list
    • ros2 topic info <topic_name>:查看话题的详细信息
    • ros2 topic echo <topic_name>:查看话题的消息

1.4 小车运动参数

一个物体,有六个自由度,其中三个方向的直线运动,再加上三个角度的旋转运动。

对小车而言,它是在平面上运动的,只剩下两个自由度:直线运动(沿x轴),转弯(绕z轴)

所以想要控制小车,只需要给它两个值:一个是线性速度,另一个是角速度。

  • 话题: cmd_vel
  • 消息: Twist (标准)
  • from geometry_msgs.msg import Twist
  • 速度: twist.linear.x
  • 转角: twist.angular.z
  • 使用:
1
2
3
4
cmd_vel_pub = create_publisher(Twist, 'cmd_vel', 10)
twist.linear.x = 0.1
twist.angular.z = 0.2
cmd_vel_pub.publish(twist)

在这个案例中,键盘是一个节点,小车控制又是一个节点,键盘按下,转成一个消息,通过话题传给小车控制节点,小车控制节点接收到消息,解析消息,控制小车。

1.5 观测数据流动

第一位同学:

1
ros2 launch originbot_bringup originbot.launch.py

第二位同学:

1
ros2 run teleop_twist_keyboard teleop_twist_keyboard

第三位同学:

1
2
3
4
ros2 node list
ros2 topic list
ros2 topic info /cmd_vel
ros2 topic echo /cmd_vel

7686302bca90def0a9a805c4c710eced.png

2a087a558c30ab4a68b904dbd35a39cb.png

ros2 topic echo /cmd_vel 这条指令会显示小车的运动参数。当没有运动时,将什么都不显示,否则:

截屏2024-07-16 09.43.11.png

1.6 直接控制小车运动参数

通过发布话题消息控制小车

1
ros2 topic pub --rate 1 /cmd_vel geometry_msgs/msg/Twist "linear: x: 2.0, y: 0.0, z: 0.0, angular: x: 0.0, y: 0.0, z: 1.8"

2024-07-16 09.28.57.png

正如上面所说的,指定了 $x$ 和 $z$ 参数,就能控制运动了。

实验表明,$x$ 为正时向前走,$x$ 为负时往后走;

截屏2024-07-16 09.36.11.png

截屏2024-07-16 09.36.41.png

$z$ 为正时向左转,$z$为负时向右转。

截屏2024-07-16 09.38.59.png

截屏2024-07-16 09.37.45.png

/userdata/dev_ws/src/originbot/originbot_demo/originbot_demo/draw_circle.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"""
创建一个发布者节点
"""
class PublisherNode(Node):
    
    def __init__(self, name):
        super().__init__(name)                                    # ROS2节点父类初始化
        self.pub   = self.create_publisher(Twist, 'cmd_vel', 10)  # 创建发布者对象(消息类型、话题名、队列长度)
        self.timer = self.create_timer(0.5, self.timer_callback)  # 创建一个定时器(单位为秒的周期,定时执行的回调函数)
        
    def timer_callback(self):                                     # 创建定时器周期执行的回调函数
        twist = Twist()                                           # 创建一个Twist类型的消息对象
        twist.linear.x  = 0.2                                     # 填充消息对象中的线速度
        twist.angular.z = 0.8                                     # 填充消息对象中的角速度
        self.pub.publish(twist)                                   # 发布话题消息
        self.get_logger().info('Publishing: "linear: %0.2f, angular: %0.2f"' % (twist.linear.x, twist.angular.z))

可以修改线速度和角速度。注意,The 'z' (or 'x') field must be of type 'float'。修改完程序以后,在 dev_ws 目录下执行:

1
colcon build --packages-select originbot_demo --symlink-install

这里 --packages-select 指定只编译 demo 功能包,其他的不要构建,这样速度不会太慢。

--symlink-install 非常好用👍!在构建的时候加上这个参数,然后修改源代码后,重开进程,就能实时看到效果。不需要再编译一遍。

截屏2024-07-16 09.53.34.png

编译(约 $1 min$ )完之后,执行:

1
2
ros2 launch originbot_bringup originbot.launch.py
ros2 run originbot_demo draw_circle

截屏2024-07-16 09.54.43.png

1.7 工作空间和功能包

创建工作空间:mkdir testname_ws/src -p testname_ws 就是工作空间的名称。

创建功能包:在 testname_ws/src 目录下,

1
ros2 pkg create --build-type ament_python learning_pkg_python

learning_pkg_python 就是功能包的名称。

截屏2024-07-16 10.57.27.png

Python源程序放置在 dev_ws/src/learning_pkg_python/learning_pkg_python 下。

2024-07-16 11.02.44.png

  • 修改setup.py:修改dev_ws/src/learning_pkg_python/setup.py,在最后增加 'node_helloworld=learning_pkg_python.node_helloworld:main',,即:

运行程序的名称=功能包名称.源程序名称:main

第一个名称可以随便取,叫阿猫阿狗都行。功能包名称、源程序名称都是自己创建的时候指定的,千万不能随心所欲!

截屏2024-07-16 10.45.38.png

两个名称不要相同。后面不要 .py

然后可以在你的工作空间下编译:

testname_ws/ 下执行: colcon build

截屏2024-07-16 10.34.51.png

编译成功后,source install/setup.bash ,使得 ros 能找到我们的包,否则会:

截屏2024-07-16 10.48.46.png

两个窗口都要 source

运行:ros2 run learning_pkg_python node_helloworld

截屏2024-07-16 10.49.21.png

1.8 Launch 文件的创建

进入这个目录:

截屏2024-07-16 11.10.07.png

新建文件夹 launch 。进入目录,再创建一个 simple.launch.py

截屏2024-07-16 11.14.10.png

simple.launch.py 的内容是(注意修改其中的自定义信息,功能包名称和可执行文件名称):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from launch import LaunchDescription           # launch文件的描述类
from launch_ros.actions import Node            # 节点启动的描述类

def generate_launch_description():             # 自动生成launch文件的函数
    return LaunchDescription([                 # 返回launch文件的描述信息
        Node(                                  # 配置一个节点的启动
            package='learning_pkg_diyanqi',     # 节点所在的功能包
            executable='node_helloworld', # 节点的可执行文件
        ),
        Node(                                  # 配置一个节点的启动
            package='learning_pkg_diyanqi',     # 节点所在的功能包
            executable='node_helloworld2', # 节点的可执行文件名
        ),
    ])

截屏2024-07-16 11.22.58.png

本文由作者按照 CC BY 4.0 进行授权

© Dignite. 保留部分权利。 由  提供CDN加速。

浙ICP备2023032699号 | 使用 Jekyll 主题 Chirpy