跳到正文

Wiki

狀態接口與命令接口源碼

約 5 分鐘閱讀

本文由簡體中文內容確定性轉換,並受版本化術語表保護。

接口句柄是這套框架最容易“能用卻説不清”的部分。本節沿着變量地址理解控制器與硬件如何共享數據。

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 總覽 · 上一篇:從零編寫模擬硬件插件 · 下一篇:硬件與控制器生命週期