2. 服务调用实现远程控制
任务说明
本案例实现一个最小可复现的ROS2服务调用远程控制闭环:服务端节点模拟机器人底盘,接收速度指令并更新内部状态;客户端节点通过服务请求发送线速度与角速度,实现远程控制。两个节点通过ROS2服务通信,不依赖真实硬件。
环境依赖
- Ubuntu 22.04 + ROS2 Humble(或更高版本)
- 已创建ROS2工作空间(如
ros2_ws/src)
实现步骤
在ros2_ws/src下创建功能包robot_control,包内包含两个Python节点:robot_server.py(服务端)与robot_client.py(客户端)。服务端定义服务接口SetVelocity,客户端通过命令行参数发送目标速度。
关键完整代码
1. 服务接口定义(srv/SetVelocity.srv)
float32 linear_x
float32 angular_z
---
bool success
string message
2. 服务端节点(robot_server.py)
import rclpy
from rclpy.node import Node
from robot_control.srv import SetVelocity
class RobotServer(Node):
def __init__(self):
super().__init__('robot_server')
self.srv = self.create_service(SetVelocity, 'set_velocity', self.callback)
self.current_linear = 0.0
self.current_angular = 0.0
self.get_logger().info('服务端已启动,等待速度指令...')
def callback(self, request, response):
# 模拟底盘限速:线速度最大1.0 m/s,角速度最大2.0 rad/s
if abs(request.linear_x) > 1.0 or abs(request.angular_z) > 2.0:
response.success = False
response.message = '速度超出限制(线速度≤1.0,角速度≤2.0)'
return response
self.current_linear = request.linear_x
self.current_angular = request.angular_z
response.success = True
response.message = f'已更新速度:线速度={self.current_linear:.2f} m/s,角速度={self.current_angular:.2f} rad/s'
self.get_logger().info(response.message)
return response
def main(args=None):
rclpy.init(args=args)
node = RobotServer()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
3. 客户端节点(robot_client.py)
import sys
import rclpy
from rclpy.node import Node
from robot_control.srv import SetVelocity
class RobotClient(Node):
def __init__(self):
super().__init__('robot_client')
self.cli = self.create_client(SetVelocity, 'set_velocity')
while not self.cli.wait_for_service(timeout_sec=1.0):
self.get_logger().info('等待服务端上线...')
self.req = SetVelocity.Request()
def send_request(self, linear_x, angular_z):
self.req.linear_x = linear_x
self.req.angular_z = angular_z
future = self.cli.call_async(self.req)
rclpy.spin_until_future_complete(self, future)
return future.result()
def main(args=None):
rclpy.init(args=args)
if len(sys.argv) != 3:
print('用法: ros2 run robot_control robot_client <线速度> <角速度>')
print('示例: ros2 run robot_control robot_client 0.5 0.2')
rclpy.shutdown()
return
node = RobotClient()
try:
linear = float(sys.argv[1])
angular = float(sys.argv[2])
response = node.send_request(linear, angular)
if response.success:
print(f'[成功] {response.message}')
else:
print(f'[失败] {response.message}')
except ValueError:
print('错误:速度参数必须为数字')
finally:
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
编译与运行
# 在ros2_ws目录下
colcon build --packages-select robot_control
source install/setup.bash
# 终端1:启动服务端
ros2 run robot_control robot_server
# 终端2:启动客户端(发送速度指令)
ros2 run robot_control robot_client 0.5 0.2
验证方法与判定标准
- 正常控制:客户端发送
0.5 0.2,服务端日志显示“已更新速度:线速度=0.50 m/s,角速度=0.20 rad/s”,客户端输出[成功],即通过。 - 超限保护:客户端发送
2.0 0.0(线速度超限),服务端拒绝更新,客户端输出[失败] 速度超出限制,即通过。 - 服务发现:先启动客户端再启动服务端,客户端等待约1秒后自动连接并成功发送请求,即通过。
预期输出(确定性结果)
当输入为0.5 0.2时,服务端日志与客户端输出严格为:
服务端: [INFO] 已更新速度:线速度=0.50 m/s,角速度=0.20 rad/s
客户端: [成功] 已更新速度:线速度=0.50 m/s,角速度=0.20 rad/s