使用Deepseek 编译ros2 rolling 的接口和节点 ----综合案例
问DeepSeek : ros2 rolling 使用python 编写一个 pkg_robot_control 和 pkg_robot_interfaces 。pkg_robot_control内有自己编写的python module实现PID
下面是一个完整的ROS2 Rolling项目,包含两个包:pkg_robot_interfaces(定义消息/服务)和pkg_robot_control(实现PID控制器)。请按照以下步骤操作:
1. 创建接口包
ros2 pkg create pkg_robot_interfaces \
--build-type ament_cmake \
--dependencies std_msgs
添加消息和服务定义:
文件:pkg_robot_interfaces/msg/PIDParams.msg
float64 kp
float64 ki
float64 kd
float64 set_point
文件:pkg_robot_interfaces/srv/SetPID.srv
float64 kp
float64 ki
float64 kd
float64 set_point
---
bool success
修改 pkg_robot_interfaces/CMakeLists.txt
在 find_package 后添加:
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/PIDParams.msg"
"srv/SetPID.srv"
)
修改 pkg_robot_interfaces/package.xml
添加:
<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
2. 创建控制包
注意自己编写的接口包也作为依赖项。
ros2 pkg create pkg_robot_control \
--build-type ament_python \
--dependencies rclpy pkg_robot_interfaces std_msgs
实现PID模块
文件:pkg_robot_control/pkg_robot_control/pid_controller.py
class PIDController:
def __init__(self, kp=0.0, ki=0.0, kd=0.0, set_point=0.0):
self.kp = kp
self.ki = ki
self.kd = kd
self.set_point = set_point
self.prev_error = 0.0
self.integral = 0.0
def update(self, current_value, dt):
error = self.set_point - current_value
self.integral += error * dt
derivative = (error - self.prev_error) / dt
output = (self.kp * error) + (self.ki * self.integral) + (self.kd * derivative)
self.prev_error = error
return output
def set_params(self, kp, ki, kd, set_point):
self.kp = kp
self.ki = ki
self.kd = kd
self.set_point = set_point
self.integral = 0.0 # Reset integral on parameter change
self.prev_error = 0.0
实现ROS节点
文件:pkg_robot_control/pkg_robot_control/robot_pid_node.py
import rclpy
from rclpy.node import Node
from std_msgs.msg import Float64
from pkg_robot_interfaces.msg import PIDParams
from pkg_robot_interfaces.srv import SetPID
from .pid_controller import PIDController
class RobotPIDNode(Node):
def __init__(self):
super().__init__('robot_pid_node')
# 初始化PID参数(可从参数服务器加载)
self.declare_parameters(
namespace='',
parameters=[
('kp', 1.0),
('ki', 0.0),
('kd', 0.1),
('set_point', 5.0)
]
)
# 创建PID控制器实例
self.pid = PIDController(
kp=self.get_parameter('kp').value,
ki=self.get_parameter('ki').value,
kd=self.get_parameter('kd').value,
set_point=self.get_parameter('set_point').value
)
# 创建话题发布者(控制输出)
self.control_pub = self.create_publisher(Float64, 'control_output', 10)
# 创建话题订阅者(模拟传感器输入)
self.sensor_sub = self.create_subscription(
Float64,
'sensor_input',
self.sensor_callback,
10
)
# 创建服务(动态修改PID参数)
self.srv = self.create_service(
SetPID,
'set_pid_params',
self.set_pid_callback
)
# 创建定时器(定期发布PID参数)
self.timer = self.create_timer(1.0, self.publish_pid_params)
self.params_pub = self.create_publisher(PIDParams, 'pid_params', 10)
self.get_logger().info("PID节点已启动")
def sensor_callback(self, msg):
# 模拟控制周期(0.1秒)
control_value = self.pid.update(msg.data, dt=0.1)
# 发布控制指令
out_msg = Float64()
out_msg.data = control_value
self.control_pub.publish(out_msg)
def set_pid_callback(self, request, response):
self.pid.set_params(
request.kp,
request.ki,
request.kd,
request.set_point
)
response.success = True
self.get_logger().info(f"PID参数更新: Kp={request.kp}, Ki={request.ki}, Kd={request.kd}, SP={request.set_point}")
return response
def publish_pid_params(self):
msg = PIDParams()
msg.kp = self.pid.kp
msg.ki = self
