1. 创建工作空间
打开终端,创建一个新的工作空间:
mkdir -p ~/project/src
cd ~/project/
初始化工作空间:
colcon build --packages-select std_msgs
这个命令会初始化工作空间并构建std_msgs
包,它是ROS2中用于标准消息类型的一个包。
2. 创建一个包
配置当前终端会话的环境变量,否则ros2命令可能不能用(不同容器的setup.bash路径可能并不一致,要在opt目录中逐级查看):
source /opt/ros/eloquent/setup.bash
如果你打开一个新的终端窗口,需要再次运行这个命令来设置环境变量,除非你将这行命令添加到你的启动脚本中(比如.bashrc
或.bash_profile
)。
在你的工作空间中创建一个新的包:
cd src
ros2 pkg create --build-type ament_python demo_package
这个命令创建了一个名为demo_package
的新包。
3. 编写服务节点
进入新创建的包目录,创建一个发布者节点:
cd demo_package/demo_package
touch server.py
编辑server.py
文件,添加以下内容:
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
from std_srvs.srv import Trigger
class Server(Node):
def __init__(self):
super().__init__('server')
self.publisher_ = self.create_publisher(String, 'chatter', 10)
self.srv = self.create_service(Trigger, 'trigger_server', self.trigger_server_callback)
self.get_logger().info('Service is ready.')
def trigger_server_callback(self, request, response):
msg = String()
msg.data = '调上了'
self.publisher_.publish(msg)
self.get_logger().info(msg.data)
response.success = True
response.message = 'Service response'
return response
def main(args=None):
rclpy.init(args=args)
server = Server()
rclpy.spin(server)
server.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
4. 编写调用节点
接下来,创建一个调用节点:
touch caller.py
编辑caller.py
文件,添加以下内容:
import sys
import rclpy
from rclpy.node import Node
from std_srvs.srv import Trigger
class ServiceClient(Node):
def __init__(self):
super().__init__('service_client')
self.client = self.create_client(Trigger, 'trigger_server')
while not self.client.wait_for_service(timeout_sec=1.0):
self.get_logger().info('还没好,等会儿')
self.req = Trigger.Request()
def send_request(self):
self.future = self.client.call_async(self.req)
def main(args=None):
rclpy.init(args=args)
service_client = ServiceClient()
service_client.send_request()
while rclpy.ok():
rclpy.spin_once(service_client)
if service_client.future.done():
try:
response = service_client.future.result()
except Exception as e:
service_client.get_logger().info(
'调用失败: %r' % (e,))
else:
service_client.get_logger().info(
'服务响应: %r' % (response,))
break
service_client.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
5. 编译包
在demo_package
目录下,存在一个setup.py
文件,这是构建Python包所必需的(主要修改入口点entry_points):
from setuptools import setup
setup(
name='demo_package',
version='0.0.0',
packages=['demo_package'],
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='your_name',
maintainer_email='your_email',
description='Examples of ROS2 publisher and subscriber in Python.',
license='Apache License 2.0',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'server = demo_package.server:main',
'caller = demo_package.caller:main',
],
},
)
6. 构建和测试
回到工作空间目录,构建你的包:
cd ~/project
# 构建指定包
colcon build --packages-select demo_package
# 构建全部包
colcon build
设置环境变量,才能够运行节点:
. install/setup.bash
在终端中运行服务:
ros2 run demo_package server
在新终端中运行调用程序(不要忘记步骤2中配置当前终端会话的环境变量):
ros2 run demo_package caller
正常你能够在终端看到服务返回的消息。