Wiki
ros2_control整體工作過程
約 3 分鐘閱讀
本文由簡體中文內容確定性轉換,並受版本化術語表保護。
本節先用一個普通程序看控制週期,不接 ROS、不接串口。先理解數據,再記類名。
1.示例 1:普通 main() 中模擬控制週期
1.1.程序目標
每 10 ms 執行一次:讀反饋、計算命令、應用命令。目標位置為 0.5 rad。
把下面代碼保存為 /tmp/control_cycle.cpp:
#include <chrono>
#include <cmath>
#include <iostream>
#include <thread>
int main()
{
double position = 0.0;
double command = 0.0;
double applied = 0.0;
const double goal = 0.5;
const double dt = 0.01;
auto next = std::chrono::steady_clock::now();
for (int cycle = 0; cycle < 100; ++cycle) {
// read:模拟读取设备在上一轮命令作用后的反馈。
position += (1.0 - std::exp(-dt / 0.2)) * (applied - position);
// update:这个控制器只转发目标位置。
command = goal;
// write:把本轮命令交给模拟设备。
applied = command;
if (cycle % 20 == 0) {
std::cout << cycle << " q=" << position << " command=" << command << '\n';
}
next += std::chrono::milliseconds(10);
std::this_thread::sleep_until(next);
}
}
g++ -std=c++17 /tmp/control_cycle.cpp -o /tmp/control_cycle
/tmp/control_cycle
1.2.運行輸出與時間順序
輸出應顯示位置逐漸接近 0.5。第一輪位置仍是 0,因為第一次 read 發生在第一次 write 之前。具體打印的小數以運行結果為準。
第 0 轮 read:读取初始反馈 0
第 0 轮 update:命令变为 0.5
第 0 轮 write:设备接受 0.5
第 1 轮 read:读到变化后的反馈
1.3.為什麼命令和反饋不是同一個變量
command 表示希望設備做到什麼;position 表示實際讀到了什麼。真實設備有延遲、慣性、故障和限幅,因此二者可能長期不相等。直接把命令當成反饋,會掩蓋設備未運動的問題。
這裏的一階公式是教學模型,不能證明真實機械臂的物理性能。
2.把變量對應到框架組件
| 本程序中的內容 | ros2_control 中的對應部分 |
|---|---|
| 循環及週期安排 | ros2_control_node / ControllerManager |
| 管理硬件、接口和生命週期 | ResourceManager |
| position 等反饋變量 | 硬件插件成員變量,經 StateInterface 導出 |
| command 等目標變量 | 硬件插件成員變量,經 CommandInterface 導出 |
| update 中的算法 | ControllerInterface 的派生控制器 |
| 獲取設備反饋、下發命令 | 硬件插件 read / write |
3.示例 2:收到 ROS 消息以後發生什麼
ROS Executor 调用订阅回调
→ 回调保存最新目标
控制线程执行下一轮 update
→ 读取保存的目标
→ 修改命令接口
控制线程继续执行 write
→ 将命令交给设备
訂閲回調與控制週期是兩條執行路徑。消息到達頻率不等於控制週期頻率;沒有新消息時,控制器也可能繼續使用已有目標。
3.1.本示例需要注意的點
- ros2_control 是控制集成框架,不會替所有設備自動設計 PID。
position、velocity、effort是接口語義;對應單位通常為 rad、rad/s、N·m,直線關節採用 m、m/s、N。update_rate: 100是調度目標,不能據此宣稱每輪都精確耗時 10 ms。- RViz 是顯示工具;Gazebo 才在後續章節引入物理引擎。
4.對應底層源碼
從 ros2_control/controller_manager/src/ros2_control_node.cpp 的 main() 開始,找到控制線程和 cm->read()、cm->update()、cm->write()。本程序刻意保留相同順序,後面再解釋 ROS 時間與實際週期。
返回 Humble 總覽 · 上一篇:環境準備與源碼地圖 · 下一篇:運行第一個RRBot實例