Wiki
状态接口与命令接口源码
接口句柄是这套框架最容易“能用却说不清”的部分。本节沿着变量地址理解控制器与硬件如何共享数据。
1.示例 1:普通 C++ 中的最小句柄
保存为 /tmp/interface_handle.cpp:
#include <iostream>
struct Handle {
double * value;
double get_value() const {return *value;}
void set_value(double input) {*value = input;}
};
int main()
{
double command = 0.0;
Handle hardware_handle{&command};
Handle controller_handle = hardware_handle;
controller_handle.set_value(0.5);
std::cout << "hardware sees " << hardware_handle.get_value() << '\n';
}
g++ -std=c++17 /tmp/interface_handle.cpp -o /tmp/interface_handle
/tmp/interface_handle
1.1.运行输出
hardware sees 0.5
复制句柄没有复制底层 command 变量。两个句柄都引用同一个地址。这个小程序只解释共享存储,不包含框架的资源借用和生命周期管理。
2.示例 2:回到 MiniSystem 的导出函数
从零编写模拟硬件插件这一行把成员元素地址交给接口:
result.emplace_back(info_.joints[i].name, "position", &command_[i]);
接口全名由关节名和接口类型组成,例如 joint1/position。控制器通过借出的命令句柄执行 set_value,最终改变 command_[i];write 再读取 command_[i]。
controller.command_interfaces_[k]
→ LoanedCommandInterface
→ CommandInterface
→ 指向 MiniSystem::command_[i] 的地址
2.1.为什么不能返回局部变量地址
函数返回以后局部变量生命周期结束,句柄保存的地址失效。之后可能读到随机值、崩溃,或者偶尔看起来正常。
2.2.为什么 vector 不能随意扩容
vector 扩容可能搬迁元素。旧地址仍留在句柄里,成员对象本身还活着也不能保证旧地址有效。因此本教程只在 on_init 分配大小;配置与激活阶段通过逐元素复制更新值。
3.示例 3:观察接口借用与释放
保持 mini.launch.py 运行,在另一个终端执行:
ros2 control list_hardware_interfaces
ros2 control set_controller_state forward_position_controller inactive
ros2 control list_hardware_interfaces
ros2 control set_controller_state forward_position_controller active
ros2 control list_hardware_interfaces
3.1.预期现象
停用前命令接口 claimed;停用后接口释放;重新激活后再次 claimed。状态接口可以供多个读取者使用,而同一个命令接口通常只能交给一个控制器写入。
注意:释放控制器句柄不等于物理设备已经断电。设备怎样停止属于硬件实现与驱动器协议。
4.关键类型与函数
| 类型或函数 | 作用 |
|---|---|
| StateInterface | 反馈接口的名字和存储位置 |
| CommandInterface | 命令接口的名字和存储位置 |
| LoanedCommandInterface | 带资源归还机制的借用句柄 |
| get_value() | 读取句柄关联的值 |
| set_value(value) | 写入命令句柄关联的值 |
| claim_command_interface(key) | 按完整名称申请独占命令资源 |
这些访问不通过 ROS Topic 传送每一个 double。硬件插件和控制器通常处在同一个管理器进程中,以接口句柄交换数据。
5.对应底层源码
依次阅读 ros2_control/hardware_interface/include/hardware_interface/handle.hpp、ros2_control/hardware_interface/include/hardware_interface/loaned_command_interface.hpp、ros2_control/hardware_interface/src/resource_manager.cpp 中的 claim_command_interface()。注意资源归还回调与接口占用记录。
返回 Humble 总览 · 上一篇:从零编写模拟硬件插件 · 下一篇:硬件与控制器生命周期