基于ROS2的话题通讯控制大疆EP
1.什么是ROS2
ros(Robot Operation System)机器人操作系统,机器人操作系统 (ROS) 是一组用于构建机器人应用程序的软件库和工具。从驱动程序到最先进的算法,再加上强大的开发人员工具,ROS 拥有您下一个机器人项目所需的一切,而且都是开源的。ROS是一种基于匿名发布/订阅机制的中间件,允许不同ROS进程之间的消息传递。在任何ROS 2系统的核心是ROS图。ROS图是指ROS系统中的节点网络和它们之间的连接。所以,对于使用过ROS的人来说,在先进的ROS2中,是可以不用启动之前所必要的roscore的,不过这只是ROS2县对于ROS一个很小的改变的表现,ROS2的改变可以说是翻天覆地的,所以,让我们开始学习这一优秀的机器人操作系统吧,ROS2就是ROS1的升级版,但是唯一缺点就是资料太少,ROS1已经用了好多年,资料比较多,案例也比较多,ROS1只能用Ubuntu Linux,但是ROS2试用于Windows,macOS,RHEL,Ubuntu Linux多平台安装ROS2,我用的平台是ubuntu20.04双系统,采用了Python语言编写。
2.如何安装ROS2
请参考https://docs.ros.org/en/rolling/Installation.html,我们用官网安装的时候会报错密钥不对,把文件的密钥全部删除,如何在添加的好了。
3.创建工作区
3.1创建新目录
mkdir -p ~/dev_ws/src
cd ~/dev_ws/src
会出现一个dev_ws的文件夹,里面包含了src文件夹。
3.2使用colcon构建工作区
// An highlighted block
colcon build
控制台将返回以下消息:
Summary: 0 packages finished [0.52s]
工作区会出现几个新的文件夹
3.3来源覆盖
在采用覆盖层之前,打开一个新终端非常重要,与您构建工作区的终端分开。在您构建的同一终端中采购覆盖层,或者同样构建覆盖层的来源,可能会产生复杂的问题。在新的终端中,将你的主要 ROS 2 环境作为“底层”,这样你就可以在它的“之上”构建叠加层:
source /opt/ros/rolling/setup.bash
进入工作区的根目录:
cd ~/dev_ws
在根目录中,获取您的叠加层:
. install/local_setup.bash
4.创建ROS2包
4.1 什么是 ROS 2 包?
一个包可以被认为是你的 ROS 2 代码的容器。如果您希望能够安装您的代码或与他人共享它,那么您需要将其组织在一个包中。使用包,您可以发布您的 ROS 2 工作,并允许其他人轻松构建和使用它。
ROS 2 中的包创建使用 ament 作为其构建系统和 colcon 作为其构建工具。您可以使用官方支持的 CMake 或 Python 创建包,但确实存在其他构建类型。
4.2 ROS2包由什么组成
package.xml 包含有关包的元信息的文件
setup.py 包含有关如何安装软件包的说明
setup.cfg当包具有可执行文件时需要,因此可以找到它们ros2 run
/<package_name> - 一个与你的包同名的目录,由 ROS 2 工具用来查找你的包,包含 __init__.py
最简单的包可能具有如下所示的文件结构:
my_package/
setup.py
package.xml
resource/my_package
4.3创建一个包
cd ~/dev_ws/src
ros2 pkg create --build-type ament_python py_pubsub
going to create a new package
package name: py_pubsub
destination directory: /home/guobaobao/dev_ws/src
package format: 3
version: 0.0.0
description: TODO: Package description
maintainer: ['guobaobao <guobaobao@todo.todo>']
licenses: ['TODO: License declaration']
build type: ament_python
dependencies: []
creating folder ./py_pubsub
creating ./py_pubsub/package.xml
creating source folder
creating folder ./py_pubsub/py_pubsub
creating ./py_pubsub/setup.py
creating ./py_pubsub/setup.cfg
creating folder ./py_pubsub/resource
creating ./py_pubsub/resource/py_pubsub
creating ./py_pubsub/py_pubsub/__init__.py
creating folder ./py_pubsub/test
creating ./py_pubsub/test/test_copyright.py
creating ./py_pubsub/test/test_flake8.py
creating ./py_pubsub/test/test_pep257.py
创建成功
4.4编写发布者
导航到dev_ws/src/py_pubsub/py_pubsub,创建一个名称为publisher_member_function.py的Python文件。
gedit publisher_member_function.py
将一下代码复制到该py文件中。
import rclpy
from rclpy.node import Node#导入rclpy以便node可以使用它的类
from std_msgs.msg import String#导入内置的字符串消息类型,节点使用该类型来构造它在主题上传递数据
class MinimalPublisher(Node):#MinimalPublisher创建类,该类继承自(或者是其子类)Node
def __init__(self):
super().__init__('minimal_publisher')#调用Node类的构造函数并为其提供节点名称
self.publisher_ = self.create_publisher(String, 'topic', 10)#声明节点在名为 的主题上发布类型String(从std_msgs.msg模块导入)的消息topic,并且“队列大小”为 10。
timer_period = 0.5 # seconds
self.timer = self.create_timer(timer_period, self.timer_callback)
self.i = 0#self.i是回调中使用的计数器
def timer_callback(self):#创建一个附加了计数器值的消息,并将其发布到控制台get_logger().info
msg = String()
msg.data=input() #获取电脑输入信息
self.publisher_.publish(msg) #发布信息
self.get_logger().info('发布信息内容: "%s"' % msg.data)
print("发布次数:“%s”" % self.i)
self.i += 1
def main(args=None):#首先rclpy初始化库,然后创建节点,然后“旋转”节点以调用其回调
rclpy.init(args=args)
minimal_publisher = MinimalPublisher()
rclpy.spin(minimal_publisher)
minimal_publisher.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
4.5添加依赖
导航一个级别回dev_ws/src/py_pubsub目录,在那里setup.py,setup.cfg和package.xml文件已为您创建。package.xml用你的文本编辑器打开。确保填写,和标签
<description>Examples of minimal publisher/subscriber using rclpy</description>
<maintainer email="you@email.com">Your Name</maintainer>
<license>Apache License 2.0</license>
在上面几行之后,添加以下与您节点的导入语句相对应的依赖项:
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
这声明了包的需要rclpy以及std_msgs它的代码何时执行。
4.6添加入口点
打开setup.py文件。同样,匹配maintainer,maintainer_email,description和license字段您package.xml:
maintainer='YourName',
maintainer_email='you@email.com',
description='Examples of minimal publisher/subscriber using rclpy',
license='Apache License 2.0',
console_scripts在entry_points字段的括号内添加以下行:
entry_points={
'console_scripts': [
'talker = py_pubsub.publisher_member_function:main',
],
},
4.7编写订阅者节点
返回dev_ws/src/py_pubsub/py_pubsub创建下一个节点。在终端中输入以下代码:
gedit subscriber_member_function.py
将一下代码复制到py文件中。
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
from robomaster import robot
class MinimalSubscriber(Node):
def __init__(self):
self.ep_robot = robot.Robot()#连接EP
self.ep_robot.initialize(conn_type="ap")
self.ep_chassis = self.ep_robot.chassis
super().__init__('minimal_subscriber')
self.subscription = self.create_subscription(
String,
'topic',
self.listener_callback,
10)
self.subscription # prevent unused variable warning
def listener_callback(self, msg):
self.get_logger().info('I heard: "%s"' % msg.data)
self.msgs=str(msg.data)
self.command()
def command(self):
print(self.msgs)
if self.msgs =="w":#判断如果是w,就控制底盘向前移动
self.ep_chassis.move(x=0.5, y=0, z=0, xy_speed=0.7).wait_for_completed()
if self.msgs =="a":
self.ep_chassis.move(x=0, y=-0.5, z=0, xy_speed=0.7).wait_for_completed()
def main(args=None):
rclpy.init(args=args)
minimal_subscriber = MinimalSubscriber()
rclpy.spin(minimal_subscriber)
# Destroy the node explicitly
# (optional - otherwise it will be done automatically
# when the garbage collector destroys the node object)
minimal_subscriber.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
4.8 添加入口点
重新打开setup.py并在发布者的入口点下方添加订阅者节点的入口点。该entry_points字段现在应如下所示:
entry_points={
'console_scripts': [
'talker = py_pubsub.publisher_member_function:main',
'listener = py_pubsub.subscriber_member_function:main',
],
},
确保保存文件,然后您的发布/订阅系统应该可以使用了。
4.9 构建和运行
仍然在您工作区的根目录中dev_ws,构建您的新包:
colcon build --packages-select py_pubsub
打开一个新终端,导航到dev_ws并获取安装文件
. install/setup.bash
现在运行talker节点
ros2 run py_pubsub talker
打开另一个终端,dev_ws再次从内部获取安装文件,然后启动侦听器节点
ros2 run py_pubsub listener
输入w和a
EP就动起来了,文章就这里结束啦,有什么问题可以联系我,微信:13580449720