1. 程式人生 > >ROS中getCurrentPose()函式呼叫時間過長問題的解決方法

ROS中getCurrentPose()函式呼叫時間過長問題的解決方法

引子

        最近做實驗的時候需要用到夾持器在機械臂基座座標系下的位姿,於是我呼叫了moveit的move_group::getCurrentPose()來獲取末端夾持器位姿,可是很憂傷地發現,實時性達不到要求,下面對如何解決這一問題進行分析與思考。

move_group::getCurrentPose()

        首先來看一下如何使用move_group::getCurrentPose()獲取指定末端關節相對於指定參考系的位姿:

#include <ros/ros.h>
#include <moveit/move_group_interface/move_group.h>
#include <moveit/planning_scene_interface/planning_scene_interface.h> #include <moveit/planning_scene_monitor/planning_scene_monitor.h> int main(int argc, char** argv) { ros::init(argc, argv, "gripper_pose"); ros::NodeHandle nh; moveit::planning_interface::MoveGroup ur5_group("ur5_arm"
); ur5_group.setPoseReferenceFrame("/base"); ros::Rate rate(10); while(ros::ok()) { gripper_pose = ur5_group.getCurrentPose(); rate.sleep(); } return 0; }

        我測試了一下,呼叫getCurrentPose()大概需要1s,這是遠遠達不到我的實時性要求的。為什麼要這麼長時間呢?不就是幾個矩陣連乘麼?
        如果使用tf_echo檢視兩個link之間的相對關係:

rosrun tf tf_echo /base /grasp_link

        其中/base為source_frame,/grasp_link為target_frame。執行結果為:



        從圖中來看的話,我們這裡有多棵tf tree,並且/grasp_link與/base並不在同一棵tf tree中。這一點從/tf話題的訊息中也可以看出來:

rostopic echo /tf

        可以看出來其中有兩組不同的值,整理如下:

第一組:


第二組:


        然後我們使用view_frames指令來檢視整體的tf tree:

rosrun tf view_frames
evince frames.pdf

        因為整張圖比較大,所以我們只用區域性圖進行分析:



        這是整棵tf tree中的一部分,觀察整棵tf tree可以發現,上面兩組tf在這棵樹中是有著各自的規律的:第一組表示的是moveable joints,第二組表示的是static joints。並且,第一組中的Most recent trasform為0.018 sec old,第二組中則為-0.492 sec old。這樣看來,在robot_state_publisher中,moveable joints資訊處理得較頻繁,而static joints則相對較緩慢。不過值得注意的是,在/tf話題中,這兩組資訊的頻率都很高,在我這裡是50Hz。那為什麼結合這兩組transform資訊計算末端link的位姿時,速度卻慢到需要1s呢?我猜,因為robot_state_publisher的開發者對moveable joints與static joints進行了區分,得到了兩組/tf訊息,而moveit的開發者使用的時候基於某些我不知道的考慮,寫出了一個較慢的getCurrentPose()函式……這裡我們就不深究了,還是自己寫一個末端link計算函式吧。

自定義計算函式

        上面我們說到了,兩組/tf資訊的釋出頻率都比較高,達到了50Hz,但是我們並不需要通過message_filters來對兩組訊息進行同步,因為static joints對應的transform是不變的。因此,我們只需要在static joints第一次到來時將其記錄下來,之後就不用再去理會static joints對應的/tf訊息了。
        整體程式碼如下:

#include <ros/ros.h>
#include <std_msgs/Header.h>
#include <tf2_msgs/TFMessage.h>
#include <geometry_msgs/PoseStamped.h>
#include <tf/transform_listener.h>
#include <vector>
#include <time.h>

geometry_msgs::PoseStamped gripper_pose;
ros::Publisher* pubPtr;

bool first_flag = true;
const char* forearm_link_str = "forearm_link";
const char* base_link_str = "base";

// This should be tf::StampedTransform, not tf::Transform, cause lookupTransform func needs this type.
tf::StampedTransform baselink_to_base;
tf::StampedTransform grasplink_to_wrist3link;

// The final transform.
tf::Transform grasplink_to_base;

// Save the transforms of the UR5.
std::vector<tf::Transform> transforms;
int tf_index[6] = {8, 7, 0, 9, 10, 11};

void tfMessageReceived(const tf2_msgs::TFMessage& tf_msg)
{
    const char* source_link_str = tf_msg.transforms[0].child_frame_id.c_str();

    if(first_flag == true && !strcmp(source_link_str, base_link_str))
    {
        first_flag = false;
        tf::TransformListener listener;
        // {0} --> target link (basis), {1} --> source link
        listener.waitForTransform("/base", "/base_link", ros::Time(0), ros::Duration(1));
        listener.lookupTransform("/base", "base_link", ros::Time(0), baselink_to_base);
        listener.lookupTransform("/wrist_3_link", "/grasp_link", ros::Time(0), grasplink_to_wrist3link);
    }


    if(!strcmp(source_link_str, forearm_link_str))
    {
        for(int i = 0; i < 6; i++)
        {
            int temp_index = tf_index[i];
            geometry_msgs::Transform geo_trans = tf_msg.transforms[temp_index].transform;

            // Convert geometry_msgs::Transform to tf::Transform
            tf::Transform temp_transform;
            tf::transformMsgToTF(geo_trans, temp_transform);

            transforms.push_back(temp_transform);
        }

        // The final transform. tf::Transform type.
        grasplink_to_base = baselink_to_base * transforms[0] * transforms[1] * transforms[2] \
                        * transforms[3] * transforms[4] * transforms[5] *  grasplink_to_wrist3link;

        // Convert tf::Transform to geometry_msgs::Transform.
        geometry_msgs::Transform geo_trans_total;
        tf::transformTFToMsg(grasplink_to_base, geo_trans_total);

        // Construct the geometry_msgs::PoseStamped.
        gripper_pose.header.seq++;
        gripper_pose.header.stamp = ros::Time::now();
        gripper_pose.pose.position.x = geo_trans_total.translation.x;
        gripper_pose.pose.position.y = geo_trans_total.translation.y;
        gripper_pose.pose.position.z = geo_trans_total.translation.z;
        gripper_pose.pose.orientation.x = geo_trans_total.rotation.x;
        gripper_pose.pose.orientation.y = geo_trans_total.rotation.y;
        gripper_pose.pose.orientation.z = geo_trans_total.rotation.z;
        gripper_pose.pose.orientation.w = geo_trans_total.rotation.w;
        pubPtr->publish(gripper_pose);
        transforms.clear();
    }
}

int main(int argc, char** argv)
{
    ros::init(argc, argv, "gripper_pose");
    ros::NodeHandle nh;


    pubPtr = new ros::Publisher(nh.advertise<geometry_msgs::PoseStamped>("/ur_pkg_udef/gripper_pose", 1000));

    ros::spin();

    return 0;
}

        在上面的程式碼中,我們要計算的是grasp_link相對於base的位姿,於是我們先將grasp_link相對於wrist_3_link的transform以及base_link相對於base的transform記錄下來,然後再對/tf中的moveable joints訊息進行處理,利用tf::Transform型別的* operator進行計算,從而得到我們所需要的grasplink_to_base。值得注意的是,這只是一個示例,大家需要根據自己的實際情形來對程式碼進行改寫~

        上面這段程式碼可以達到與/tf中的moveable_joints一致的釋出頻率,也即差不多50Hz,這樣我們的目的就達成了~

相關推薦

ROSgetCurrentPose()函式呼叫時間問題的解決方法

引子         最近做實驗的時候需要用到夾持器在機械臂基座座標系下的位姿,於是我呼叫了moveit的move_group::getCurrentPose()來獲取末端夾持器位姿,可是很憂傷地發現,實時性達不到要求,下面對如何解決這一問題進行分析與思考。

關於Hbase的RegionServer的GC持續時間解決辦法

hbase gc 持續時間 問題現象:分析原因:http://www.aboutyun.com/thread-11240-1-1.htmlhttp://blog.csdn.net/wwwxxdddx/article/details/50981089修改方法:只用原有的配置在後面增加 -XX:+

C/C++計算函式執行時間的兩種方法

       在寫程式碼中,有時候我們需要評估某段程式碼或者函式的執行時間;方法就是在該段程式碼或者函式前面,記錄一個時間T1,在程式碼段或函式後面記錄時間T2,那其執行時間就是T2-T1,下面看看具體

mysql連線時間解決方法

從客戶端連線伺服器,時間長達10幾秒,此為mysql的dns的反向解析造成,在區域網內如果都是用ip連線,可以通過在配置檔案中新增skip-name-resolve取消此功能,取消後,就不可以通過類似 localhost連線db 所謂反向解析是這樣的: mysql接收

C#執行緒佔用記憶體解決方法

專案中用到了多執行緒,而且是1000執行緒併發執行,發現記憶體佔用過高,於是對專案裡用到的物件逐個測試,發現是執行緒物件佔用記憶體 Thread[] threads = new Thread[1000]; for(int i = 0; i<threa

oraclefor update語句執行時間的問題

oracle執行查詢語句SELECT s.sid, s.serial# FROM v$locked_object lo, dba_objects ao, v$session s WHERE ao.object_id = lo.object_id AND lo.session_id = s.sid 查出的兩個字

C#客戶端建立webservice的soapclient類物件例項時間

問題描述我寫的一個C/S架構的程式,是Client->WebService->DB方式設計的,程式部署之後,很多人反映程式啟動的時候很慢,有些人電腦上點選程式圖示後要等10-20秒鐘才能顯示主介面。在有些人機器上就很快,一秒鐘不到就進到主介面中了。通過對多臺計算機進行測試,大約有20%到40%的計

EntityFramework的多種記錄日誌方式,記錄錯誤並分析執行時間原因(系列4)

tab parameter height 優化 系統 環境 build ado.net 所有 Entity Framework 延伸系列目錄 今天我們來聊聊EF的日誌記錄. 一個好的數據庫操作記錄不僅僅可以幫你記錄用戶的操作, 更應該可以幫助你獲得效率低下的語句來幫你提高

SecureRandom生成隨機數超慢 導致tomcat啟動時間解決辦法

tails spa centos 7 屬性 gpo org 解決辦法 hang iss 用騰訊雲的CentOS 7.2 CVM 服務器跑Tomcat時發現,Tomcat啟動的特別慢,通過查看日誌,發現時間主要花在實例化SecureRandom對象上了。 由該日誌可以看

網站響應時間的原因及解決方法

網站打不開 網站程序 cas ron height 出口 javascrip 運算 access 遇到過類似問題,我認為有以下幾個原因: 1、網站服務器故障維修(這種情況只能等段

服務器響應時間

服務器響應時間服務器網站響應時間過長的問題解決方法如下: 1、機器的配置。包括服務器端與客戶機端的硬件配置程度,同樣的網絡環境下,雙核的服務器的運算能力肯定要強一些,毫無疑問的,同樣的網絡環境下,用一臺賽揚的機器和奔四雙核處理器的電腦,打開同樣的網頁,速度,也肯定不一樣。 2、服務器軟件。軟件多少、穩定和軟件

關於心跳ajax請求pending狀態(被掛起),stalled時間的問題。涉及tcp連接異常。

.net section 解決 5.1 網絡問題 chrome瀏覽器 time iou 數據包 環境:景安快雲服務器(聽說很垃圾,但是公司買的,我也剛來),CentOS-6.8-x86_64,Apache,MySQL5.1,P

[轉]解決ssh登錄後閑置時間而斷開連接

tao 發送 ring keep wan end keyword com AC 本文轉自: 轉載自博客園wanghetao的博客 我們通過終端連接服務器時,當鼠標和鍵盤長時間不操作,服務器就會自動斷開連接,我們還的需要重新連接,感覺很麻煩,總結一下解決此問題的方法 方

C#VS一個函式呼叫另一個函式的程式碼樣例

//主函式 說明:下面的函式是想求許可證的十六位編號,最後一位是許可編號的校驗碼,是以本體碼("JY" + xukbh)為基礎來計算 entities[0].XuKeZhengBianHao = "JY" + xukbh + xukebianhaojiaoyanma(xukbh);  

使用Ajax同步請求時,等待時間增加頁面提示問題

最近在做專案時,有一個需求是批量列印好多個合同,使用AJAX向後臺傳送資料,等待後臺執行後,需要把生成之後的檔案地址傳送過來。 後臺的處理時間比較長,根據合同的多少可能等待時間比較長,會達到10s左右,這個時候如果不加任何的提示,會導致使用者因為沒有看到是否執行而導致重複的操作,為了增加使用者的體驗感,,以

解決linux登入後總是時間會就斷開(解決ssh登入後閒置時間而斷開連線)

1.vim /etc/ssh/sshd_config 配置如下圖: 2.systemctl reload sshd.service (針對阿里雲centos7(貌似阿里雲的都是這樣) 其他別的伺服器使用:service sshd reload     兩行命令搞定。 &nb

easyUI的treegrid新增節點(append)時間,設定等待(wait)遮罩效果

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

使用 export timeout = -1來免除ssh時間被強制下線的困擾

長時間連線ssh沒有操作,可能會被強制下線,這時候,我們使用以下命令就可以免除次困擾: export timeout = -1,便不再會被強制下線了。 有的人寫攻略說要寫入conf配置檔案裡,這樣確實不用每次登入後都敲一遍命令,但是實際企業環境中不可能讓我們隨意的去修改conf檔案,或者被防

中國電信物聯網4:連線時間,資料傳輸消失,電信平臺顯示延遲

NB-IOT論壇: 華為NB-IOT論壇:https://developer.huawei.com/ict/forum/forum.html 移動物聯網論壇:https://open.iot.10086.cn/bbs/forum.php 電信沒有自己的論壇   一份2017年的部落格(h

關於.Net mvc 專案在本地vs執行響應時間無法訪問時,解決方法

  最近可能是剛升級了電腦使用了window10作業系統,總是遇到了一些以前沒有遇到過的事情! 今早來到公司本來準備寫bug的,但是當我開啟vs執行的時候發現今天的電腦響應的時間明顯的要比之前開啟網頁除錯的時間要長的多,到最後不但沒有開啟,而且還提示了一個這樣的問題! 如圖:    這就蛋