關(guān)于ROS_Contorller的詳解

ROS_Control框架介紹

官方給出的ros_control的框架圖
  1. Controller:一個(gè)機(jī)器人包含多個(gè)controller堤结,類似ros_controllers中現(xiàn)提供的、effort_controllers肉拓、joint_state_controller后频、position_controllersvelocity_controllers暖途、joint_trajectory_controllers卑惜,不同的controller可以完成對不同模塊的控制。例如完成對關(guān)節(jié)力的控制驻售、速度控制等等露久。請求下層的硬件資源,并提供PID控制器欺栗,讀取底層硬件資源的狀態(tài)毫痕,發(fā)送控制指令征峦。
  1. Controller Manager:顧名思義,用來管理和控制各個(gè)controller的管理器消请,其主要提供統(tǒng)一的接口來管理不同的manager栏笆。

  2. Hardware Rescource:為上下兩層提供硬件資源的接口,內(nèi)部有一個(gè)hardware resource manager來完成硬件資源管理臊泰。

  3. RobotHW:硬件抽象層和硬件直接打交道蛉加,通過write和read方法來完成硬件的操作,這一層也包含關(guān)節(jié)限位缸逃、力矩轉(zhuǎn)換针饥、狀態(tài)轉(zhuǎn)換等功能。

  4. Real Robot:實(shí)際的機(jī)器人上也需要有自己的嵌入式控制器需频,接收到命令后需要反映到執(zhí)行器上丁眼,比如接收到位置1的命令后,那就需要讓執(zhí)行器快速昭殉、穩(wěn)定的到達(dá)位置户盯。

contorller_manager

此處我們看一下controller_manager.cpp的源碼,可以看出通過一個(gè)控制機(jī)器加載器工具來進(jìn)行初始化之后饲化,最后再通過訂閱六個(gè)service莽鸭,完成了controller_manager的初始化,六個(gè)service分別是list_controllers吃靠、list_controller_types硫眨、load_controller、unload_controller巢块、switch_controller礁阁、reload_controller_libraries,從其名字的字面意思也不難理解這六個(gè)服務(wù)的作用是什么族奢。

加載控制器時(shí)姥闭,controller_manager將使用控制器名稱作為所有控制器特定參數(shù)的根,最重要的是越走,標(biāo)識(shí)要加載哪個(gè)插件的類型棚品。控制器管理器提供與控制器交互的基礎(chǔ)框架廊敌。根據(jù)你是從啟動(dòng)文件铜跑,命令行還是ROS節(jié)點(diǎn)運(yùn)行控制器,控制器管理器提供不同的工具來運(yùn)行控制器骡澈。

ControllerManager::ControllerManager(hardware_interface::RobotHW *robot_hw, const ros::NodeHandle& nh) :
  robot_hw_(robot_hw),
  root_nh_(nh),
  cm_node_(nh, "controller_manager"),
  start_request_(0),
  stop_request_(0),
  please_switch_(false),
  current_controllers_list_(0),
  used_by_realtime_(-1)
{
  // create controller loader
  controller_loaders_.push_back( 
    ControllerLoaderInterfaceSharedPtr(new ControllerLoader<controller_interface::ControllerBase>("controller_interface",
                                                                                                  "controller_interface::ControllerBase") ) );

  // Advertise services (this should be the last thing we do in init)
  srv_list_controllers_ = cm_node_.advertiseService("list_controllers", &ControllerManager::listControllersSrv, this);
  srv_list_controller_types_ = cm_node_.advertiseService("list_controller_types", &ControllerManager::listControllerTypesSrv, this);
  srv_load_controller_ = cm_node_.advertiseService("load_controller", &ControllerManager::loadControllerSrv, this);
  srv_unload_controller_ = cm_node_.advertiseService("unload_controller", &ControllerManager::unloadControllerSrv, this);
  srv_switch_controller_ = cm_node_.advertiseService("switch_controller", &ControllerManager::switchControllerSrv, this);
  srv_reload_libraries_ = cm_node_.advertiseService("reload_controller_libraries", &ControllerManager::reloadControllerLibrariesSrv, this);
}

可以使用controller_manager腳本從命令行與controller_manager進(jìn)行交互锅纺,command包括:
load: 加載一個(gè)控制器(創(chuàng)建和初始化,但是不啟動(dòng))
unload: 卸載一個(gè)控制器(銷毀)
start: 啟動(dòng)一個(gè)控制器
stop: 停止一個(gè)控制器
spawn: 加載并啟動(dòng)一個(gè)控制器
kill: 停止并卸載一個(gè)控制器

rosrun controller_manager controller_manager <command> <controller_name>

要獲取控制器的狀態(tài)肋殴,command包括:
list: 按照執(zhí)行順序列出所有控制器囤锉,并給出每個(gè)控制器的狀態(tài)
list-types: 列出控制器管理器知道的所有控制器類型坦弟。如果控制器不在此列表中,將無法獲取官地。
reload-libraries: 重新加載所有可用作插件的控制器庫减拭。當(dāng)您開發(fā)控制器并且想要測試新的控制器代碼時(shí),這很方便区丑,而無需每次都重新啟動(dòng)機(jī)器人。而且不會(huì)重新啟動(dòng)之前運(yùn)行的控制器
reload-libraries --restore: 重新加載所有可用作插件的控制器庫修陡,并將所有控制器恢復(fù)到其原始狀態(tài)

rosrun controller_manager controller_manager <command>

還有其他命令行腳本工具來幫住我們完成不同的任務(wù)沧侥,具體的可以參考官網(wǎng)給出的說明,就不在此處進(jìn)行羅列了魄鸦。

我們還可以通過launch文件來啟動(dòng)我們的控制器宴杀,上面的一種是加載并啟動(dòng),第二種是僅加載不啟動(dòng)拾因。

<launch>
   <node pkg="controller_manager"
         type="spawner"
         args="controller_name1 controller_name2" />
 </launch>

<launch>
   <node pkg="controller_manager"
         type="spawner"
         args="--stopped controller_name1 controller_name2" />
 </launch>

還可以通過圖形界面的方式對控制器進(jìn)行操作旺罢,以圖形方式加載,卸載绢记,啟動(dòng)和停止控制器扁达,以及顯示加載的有關(guān)控制器的信息。

rosrun rqt_controller_manager rqt_controller_manager

controller_interface

#ifndef CONTROLLER_INTERFACE_CONTROLLER_H
#define CONTROLLER_INTERFACE_CONTROLLER_H

#include <controller_interface/controller_base.h>
#include <hardware_interface/internal/demangle_symbol.h>
#include <hardware_interface/robot_hw.h>
#include <hardware_interface/hardware_interface.h>
#include <ros/ros.h>


namespace controller_interface
{

/* 
 *具有特定硬件接口的控制器
 * 模板類蠢熄,該控制器使用的硬件接口類型跪解。這強(qiáng)制了控制器與其要控制的硬件之間的語義兼容性。
 */
template <class T>
class Controller: public virtual ControllerBase
{
public:
  Controller()  {state_ = CONSTRUCTED;}
  virtual ~Controller<T>(){}

  /*
   * 調(diào)用init函數(shù)來從非實(shí)時(shí)線程初始化控制器签孔,其中指針指向硬件接口本身叉讥,而不是指向RobotHW的指針
   * 參數(shù) hw 此控制器使用的特定硬件接口
   * 參數(shù)controller_nh命名空間中的NodeHandle,控制器應(yīng)從中讀取其配置饥追,以及應(yīng)在何處設(shè)置其ROS接口
   * 初始化成功返回ture并且做好啟動(dòng)準(zhǔn)備工作
   */
  virtual bool init(T* /*hw*/, ros::NodeHandle& /*controller_nh*/) {return true;};

  /*
   * 參數(shù)controller_nh控制器命名空間中的NodeHandle图仓。這是特定于控制器的配置所在的位置。
   */
  virtual bool init(T* /*hw*/, ros::NodeHandle& /*root_nh*/, ros::NodeHandle& /*controller_nh*/) {return true;};


protected:
  /* 
   * 從RobotHW指針初始化控制器
   * 如果它可以從robot_hw中成功獲取接口但绕,則對控制器的硬件接口進(jìn)行初始化
   */
  virtual bool initRequest(hardware_interface::RobotHW* robot_hw,
                           ros::NodeHandle&             root_nh,
                           ros::NodeHandle&             controller_nh,
                           ClaimedResources&            claimed_resources)
  {
    // check if construction finished cleanly
    if (state_ != CONSTRUCTED){
      ROS_ERROR("Cannot initialize this controller because it failed to be constructed");
      return false;
    }

    // 獲得硬件接口的指針
    T* hw = robot_hw->get<T>();
    if (!hw)
    {
      ROS_ERROR("This controller requires a hardware interface of type '%s'."
                " Make sure this is registered in the hardware_interface::RobotHW class.",
                getHardwareInterfaceType().c_str());
      return false;
    }

    // 返回此控制器聲明的資源
    hw->clearClaims();
    if (!init(hw, controller_nh) || !init(hw, root_nh, controller_nh))
    {
      ROS_ERROR("Failed to initialize the controller");
      return false;
    }
    hardware_interface::InterfaceResources iface_res(getHardwareInterfaceType(), hw->getClaims());
    claimed_resources.assign(1, iface_res);
    hw->clearClaims();

    // success
    state_ = INITIALIZED;
    return true;
  }

  /// 獲取此控制器的硬件接口類型的名稱
  std::string getHardwareInterfaceType() const
  {
    return hardware_interface::internal::demangledTypeName<T>();
  }

private:
  Controller<T>(const Controller<T> &c);
  Controller<T>& operator =(const Controller<T> &c);

};

}
#endif

從上面的源碼中不難看出救崔,contorller通過controlle_interface來完成hardware_interface的初始化。

hardware_interface

最重要的交互接口捏顺,與機(jī)器人硬件完成連接帚豪,我們通過類圖來理清接口之間關(guān)系。


類圖.png

這里需要補(bǔ)充說明的是HardwareResourceManager通過getHandle獲取到不同的handle對應(yīng)到到圖中右側(cè)的不同的HardwareInterface草丧。這個(gè)在類圖上并沒有體現(xiàn)出來狸臣,流程圖如下:


流程圖.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市昌执,隨后出現(xiàn)的幾起案子烛亦,更是在濱河造成了極大的恐慌诈泼,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件煤禽,死亡現(xiàn)場離奇詭異铐达,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)檬果,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門瓮孙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人选脊,你說我怎么就攤上這事杭抠。” “怎么了恳啥?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵偏灿,是天一觀的道長。 經(jīng)常有香客問我钝的,道長翁垂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任硝桩,我火速辦了婚禮沿猜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘碗脊。我一直安慰自己邢疙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布望薄。 她就那樣靜靜地躺著疟游,像睡著了一般。 火紅的嫁衣襯著肌膚如雪痕支。 梳的紋絲不亂的頭發(fā)上颁虐,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天,我揣著相機(jī)與錄音卧须,去河邊找鬼另绩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛花嘶,可吹牛的內(nèi)容都是我干的笋籽。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼椭员,長吁一口氣:“原來是場噩夢啊……” “哼车海!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起隘击,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤侍芝,失蹤者是張志新(化名)和其女友劉穎研铆,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體州叠,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡棵红,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咧栗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逆甜。...
    茶點(diǎn)故事閱讀 38,747評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖致板,靈堂內(nèi)的尸體忽然破棺而出交煞,到底是詐尸還是另有隱情,我是刑警寧澤可岂,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站翰灾,受9級特大地震影響缕粹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜纸淮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一平斩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧咽块,春花似錦绘面、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至亭罪,卻和暖如春瘦馍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背应役。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工情组, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人箩祥。 一個(gè)月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓院崇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親袍祖。 傳聞我的和親對象是個(gè)殘疾皇子底瓣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容