跳到正文

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