日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

由浅到深理解ROS URDF教程

發布時間:2023/12/10 编程问答 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 由浅到深理解ROS URDF教程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 創建自己的URDF文件
    1.1創建樹形結構文件
    在這部分教程中要創建的將是下面的圖形所描述的機器人的urdf文件

    圖片中這個機器人是一個樹形結構的。讓我們開始非常簡單的創建這個樹型結構的描述文件,不用擔心維度等的問題。創建一個my_robot.urdf文件,內容如下:
  • <robot name="test_robot"><link name="link1" /><link name="link2" /><link name="link3" /><link name="link4" /><joint name="joint1" type="continuous"><parent link="link1"/><child link="link2"/></joint><joint name="joint2" type="continuous"><parent link="link1"/><child link="link3"/></joint><joint name="joint3" type="continuous"><parent link="link3"/><child link="link4"/></joint> </robot>

    所以,這里是僅僅創建了一個非常簡單的結構。現在我們來看一看我們能否解讀這個文件。可以使用一些簡單的命令行工具,來檢查你的語法是否正確。
    需要安裝urdfdom作為一個上游的ROS獨立包

    sudo apt-get install liburdfdom-tools

    現在運行檢查命令(基于indigo)

    check_urdf my_robot.urdf

    如果一切順利的話,將會看到的是


    1.2添加坐標系(維度)信息
    現在有了一個基本的樹形結構,讓我們來添加合適的坐標系信息。如你在圖片中看到的,每一個連接的參考系都在連接的底部,而且關節的參考系是完全相同的。所以,要添加維度到我們的樹上,我們要確認的就是從一個連接到自己子連接的關機的偏移量。為了完成這一部分,我們將會為每一個關節添加.
    比如,我們來看第二個關節。joint2是link1在Y方向上的偏移,在X軸負方向上有一點點偏移,而且繞Z軸旋轉了90度,所以我們需要添加下面的元素。

    <origin xyz=”-2 5 0” rpy=”0 0 1.57” />

    在每一個關節重復這一改變,這個urdf文件看起來就是這樣子的:

    <robot name="test_robot"><link name="link1" /><link name="link2" /><link name="link3" /><link name="link4" /><joint name="joint1" type="continuous"><parent link="link1"/><child link="link2"/><origin xyz="5 3 0" rpy="0 0 0" /></joint><joint name="joint2" type="continuous"><parent link="link1"/><child link="link3"/><origin xyz="-2 5 0" rpy="0 0 1.57" /></joint><joint name="joint3" type="continuous"><parent link="link3"/><child link="link4"/><origin xyz="5 0 0" rpy="0 0 -1.57" /></joint> </robot>

    更新你的my_robot.urd文件,并通過解析器運行它。

    check_urdf my_robot.urdf

    1.3 完成運動學部分
    我們現在還不確定的部分就是關節繞著哪個軸旋轉。一旦我們添加了這個部分,我們實際上有了這個機器人完整的運動學模型。我們要做的就是添加元素到每一個joint中。axis確定在局部的旋轉軸。
    所以,如果你看joint2,你會看到它是繞著Y軸正方向旋轉。所以,需要簡單添加下面的內容到關節元素中:

    <axis xyz=”0 1 0” />

    相似的,需要向joint1中添加下面的內容:

    <axis xyz=”-0.707 0.707 0” />

    如果向所有關節中添加了這一元素的話,這個urdf文件看起來就是下面這樣的:

    <robot name="test_robot"><link name="link1" /><link name="link2" /><link name="link3" /><link name="link4" /><joint name="joint1" type="continuous"><parent link="link1"/><child link="link2"/><origin xyz="5 3 0" rpy="0 0 0" /><axis xyz="-0.9 0.15 0" /></joint><joint name="joint2" type="continuous"><parent link="link1"/><child link="link3"/><origin xyz="-2 5 0" rpy="0 0 1.57" /><axis xyz="-0.707 0.707 0" /></joint><joint name="joint3" type="continuous"><parent link="link3"/><child link="link4"/><origin xyz="5 0 0" rpy="0 0 -1.57" /><axis xyz="0.707 -0.707 0" /></joint> </robot>

    更新你的my_robot.urdf文件,并用解析器運行它

    check_urdf my_robot.urdf

    到這里為止,你就創建了你的第一個URDF機器人描述。現在你可以嘗試用graphiz將你的URDF可視化。

    urdf_to_graphiz my_robot.urdf

    打開產生的文件,比如用evince test_robot.pdf

  • 解析一個URDF文件
    2.1解析一個URDF文件
    首先,我們創建一個依賴于urdf解析器的包。
  • $ cd ~/catkin_ws/src$ catkin_create_pkg testbot_description urdf$ cd testbot_description

    現在我們來創建一個urdf文件夾來存儲我們剛剛創建的urdf文件。

    mkdir urdf

    按照一般的慣例,urdf文件是在一個名為MYROBOT_description的包中,它的標準的子文件夾還包括有/meshes, /media 和/cd,就像是下面這樣:

    /MYROBOT_descriptionpackage.xmlCMakeLists.txt/urdf/meshes/materials/cad

    接下來,將我們創建的my_robot.urdf拷貝到我們剛剛創建的文件夾中。

    $ cp /path/to/.../testbot_description/urdf/my_robot.urdf

    創建一個src文件夾,并創建src/parser.cpp文件

    #include <urdf/model.h> #include "ros/ros.h"int main(int argc, char** argv){ros::init(argc, argv, "my_parser");if (argc != 2){ROS_ERROR("Need a urdf file as argument");return -1;}std::string urdf_file = argv[1];urdf::Model model;if (!model.initFile(urdf_file)){ROS_ERROR("Failed to parse urdf file");return -1;}ROS_INFO("Successfully parsed urdf file");return 0; }

    真正的動作是發生在 urdf::Model model;
    if (!model.initFile(urdf_file)){這兩行。如果URDF文件能夠成功解析的話initFile方法返回true。
    然后我們來嘗試運行這個程序,首先向CmakeList.txt文件中添加這兩行

    add_executable(parser src/parser.cpp) target_link_libraries(parser ${catkin_LIBRARIES})

    構建你的包,并運行它

    $ catkin_make$ .<path>/parser <path>my_robot.urdf# ./devel/lib/robot_description/parser /src/robot_description/urdf/my_robot.urdf (for example)

    輸出應該看起來是這樣的:

    [ INFO] 1254520129.560927000: Successfully parsed urdf file

    現在,可以看一下code API(http://docs.ros.org/api/urdf/html/)來看看如何使用你剛剛創建的URDF模型。一個很好的URDF模型類的例子在
    https://github.com/ros-visualization/rviz/blob/groovy-devel/src/rviz/robot/robot.cpp
    - 在自己的機器人上使用robot state publisher
    這部分教程將解釋如何使用機器人狀態發布者來發布機器人狀態到tf。
    當你的機器人是有很多關聯坐標系的機器人時,把它們全部發布到tf也是一項相當可觀的任務。robot state publisher是一個可以幫助你處理這項任務的工具。

    robot state publisher幫助你把你的機器人狀態發布到tf轉換庫中。robot state publisher內部有一個機器人的運動學模型,所以給定機器人位置,robot state publisher能夠計算和發布機器人每一個link的3D位姿。
    你可以用robot state publisher作為一個單獨的節點或者一個庫。
    3.1 作為一個單獨的ROS節點運行
    3.1.1 robot_state_publisher
    運行機器人狀態發布者最簡單的方式就是作為一個節點運行。對于一般使用者來說,我們推薦這樣使用。你需要兩樣東西來運行機器人狀態發布者:
    - 一個從Parameter Server下載的urdf xml機器人描述。
    - 一個將關節位置用sensor_msgs/JointState格式發布的源。
    如何為robot_state_publisher配置參數和主題,請閱讀下面的部分。
    3.1.1.1 訂閱的主題:
    joint_states(sensor_msgs/JointState)
    關節位置信息
    3.1.1.2 參數
    robot_description(urdf map)
    urdf xml機器人描述。這可以通過urdf_model::initParam來完成。
    tf_prefix(string)
    為命名空間發布變化設置tf前綴。
    publish_frequency(double)
    狀態發布者的發布頻率,默認50赫茲。
    3.1.2 例子launch文件
    一旦已經設置了XML機器人描述文件和一個關節位置信息源文件,簡單創建一個launch文件如下:

    <launch><node pkg="robot_state_publisher" type="robot_state_publisher" name="rob_st_pub" ><remap from="robot_description" to="different_robot_description" /><remap from="joint_states" to="different_joint_states" /></node></launch>

    3.2 作為一個庫運行
    高級用戶也可以將機器人狀態發布者在他們自己的C++代碼中作為一個庫來使用。在你包含了頭文件之后:

    #include <robot_state_publisher/robot_state_publisher.h>

    你需要的就是一個采用了KDL樹的構造函數:

    RobotStatePublisher(const KDL::Tree& tree);

    現在,每次你想要發布你的機器人狀態,你調用publishTransform函數即可:

    //publish moving joints void publishTransforms(const std::map<std::string, double>& joint_positions, const ros::Time& time): //publish fixed joints void publishFixedTransforms();

    第一個變量是一個關節名稱和關節位置的map,第二個參數是關節位置記錄的時間。如果這個map不包括所有的關節名稱也是沒有問題的。如果這個map包含了一些關節名稱,而這些關節名稱不是運動模型的一部分,也是沒有問題的。要是注意,如果你不告訴關節狀態發布者你運動模型的一些關節,你的tf樹將不能完成。
    4.開始使用KDL解析器
    4.1 構建KDL解析器

    rosdep install kdl_parser

    這條命令將會安裝kdl_parser所有的外部依賴包。構建包,運行:

    rosmake kdl_parser

    4.2 使用你的代碼
    首先,添加KDL解析器作為一個依賴包,到你的package.xml文件中

    <package>...<depend package="kdl_parser" />...</package>

    在你的C++代碼開始階段,添加KDL解析器,包括下面的文件

    #include <kdl_parser/kdl_parser.hpp>

    現在,有不同的方法來繼續進行,你可以從一個urdf用多種方法構建一個KDL樹。
    4.2.1從一個文件

    KDL::Tree my_tree;if (!kdl_parser::treeFromFile("filename", my_tree)){ROS_ERROR("Failed to construct kdl tree");return false;}

    創建PR2的urdf文件,運行下面的命令

    rosrun xacro xacro.py `rospack find pr2_description`/robots/pr2.urdf.xacro > pr2.urdf

    4.2.2 從一個參數服務器

    KDL::Tree my_tree;ros::NodeHandle node;std::string robot_desc_string;node.param("robot_description", robot_desc_string, string());if (!kdl_parser::treeFromString(robot_desc_string, my_tree)){ROS_ERROR("Failed to construct kdl tree");return false;}

    4.2.3 從一個xml元素

    KDL::Tree my_tree;TiXmlDocument xml_doc;xml_doc.Parse(xml_string.c_str());xml_root = xml_doc.FirstChildElement("robot");if (!xml_root){ROS_ERROR("Failed to get robot from xml document");return false;}if (!kdl_parser::treeFromXml(xml_root, my_tree)){ROS_ERROR("Failed to construct kdl tree");return false;}

    4.2.4 從一個URDF模型

    KDL::Tree my_tree;urdf::Model my_model;if (!my_model.initXml(....)){ROS_ERROR("Failed to parse urdf robot model");return false;}if (!kdl_parser::treeFromUrdfModel(my_model, my_tree)){ROS_ERROR("Failed to construct kdl tree");return false;}

    關于更多地細節,可以參考API文檔:
    http://docs.ros.org/api/kdl_parser/html/namespacekdl__parser.html
    5.用robot_state_publisher使用URDF
    這部分教程完整的機器人URDF模型使用robot_state_publisher的例子。首先,我們創建所有URDF模型的需要的部分。然后我們寫一個節點來發布關鍵狀態和轉換信息。最后,我們運行所有的部分。
    5.1 創建URDF文件
    這里有一個7自由度的接近R2-D2的模型。

    <robot name="r2d2"><link name="axis"><inertial><mass value="1"/><inertia ixx="100" ixy="0" ixz="0" iyy="100" iyz="0" izz="100" /><origin/></inertial><visual><origin xyz="0 0 0" rpy="1.57 0 0" /><geometry><cylinder radius="0.01" length=".5" /></geometry><material name="gray"><color rgba=".2 .2 .2 1" /></material></visual><collision><origin xyz="0 0 0" rpy="1.57 0 0" /><geometry><cylinder radius="0.01" length=".5" /></geometry><contact_coefficients mu="0" kp="1000.0" kd="1.0"/></collision> </link><link name="leg1"><inertial><mass value="1"/><inertia ixx="100" ixy="0" ixz="0" iyy="100" iyz="0" izz="100" /><origin/></inertial><visual><origin xyz="0 0 -.3" /><geometry><box size=".20 .10 .8" /></geometry><material name="white"><color rgba="1 1 1 1"/></material></visual><collision><origin xyz="0 0 -.3" /><geometry><box size=".20 .10 .8" /></geometry><contact_coefficients mu="0" kp="1000.0" kd="1.0"/></collision> </link><joint name="leg1connect" type="fixed"><origin xyz="0 .30 0" /><parent link="axis"/><child link="leg1"/> </joint><link name="leg2"><inertial><mass value="1"/><inertia ixx="100" ixy="0" ixz="0" iyy="100" iyz="0" izz="100" /><origin/></inertial><visual><origin xyz="0 0 -.3" /><geometry><box size=".20 .10 .8" /></geometry><material name="white"><color rgba="1 1 1 1"/></material></visual><collision><origin xyz="0 0 -.3" /><geometry><box size=".20 .10 .8" /></geometry><contact_coefficients mu="0" kp="1000.0" kd="1.0"/></collision> </link><joint name="leg2connect" type="fixed"><origin xyz="0 -.30 0" /><parent link="axis"/><child link="leg2"/> </joint><link name="body"><inertial><mass value="1"/><inertia ixx="100" ixy="0" ixz="0" iyy="100" iyz="0" izz="100" /><origin/></inertial><visual><origin xyz="0 0 -0.2" /><geometry><cylinder radius=".20" length=".6"/></geometry><material name="white"/></visual><collision><origin xyz="0 0 0.2" /><geometry><cylinder radius=".20" length=".6"/></geometry><contact_coefficients mu="0" kp="1000.0" kd="1.0"/></collision> </link><joint name="tilt" type="revolute"><parent link="axis"/><child link="body"/><origin xyz="0 0 0" rpy="0 0 0" /><axis xyz="0 1 0" /><limit upper="0" lower="-.5" effort="10" velocity="10" /> </joint><link name="head"><inertial><mass value="1"/><inertia ixx="100" ixy="0" ixz="0" iyy="100" iyz="0" izz="100" /><origin/></inertial><visual><geometry><sphere radius=".4" /></geometry><material name="white" /></visual><collision><origin/><geometry><sphere radius=".4" /></geometry><contact_coefficients mu="0" kp="1000.0" kd="1.0"/></collision> </link><joint name="swivel" type="continuous"><origin xyz="0 0 0.1" /><axis xyz="0 0 1" /><parent link="body"/><child link="head"/> </joint><link name="rod"><inertial><mass value="1"/><inertia ixx="100" ixy="0" ixz="0" iyy="100" iyz="0" izz="100" /><origin/></inertial><visual><origin xyz="0 0 -.1" /><geometry><cylinder radius=".02" length=".2" /></geometry><material name="gray" /></visual><collision><origin/><geometry><cylinder radius=".02" length=".2" /></geometry><contact_coefficients mu="0" kp="1000.0" kd="1.0"/></collision> </link><joint name="periscope" type="prismatic"><origin xyz=".12 0 .15" /><axis xyz="0 0 1" /><limit upper="0" lower="-.5" effort="10" velocity="10" /><parent link="head"/><child link="rod"/> </joint><link name="box"><inertial><mass value="1"/><inertia ixx="100" ixy="0" ixz="0" iyy="100" iyz="0" izz="100" /><origin/></inertial><visual><geometry><box size=".05 .05 .05" /></geometry><material name="blue" ><color rgba="0 0 1 1" /></material></visual><collision><origin/><geometry><box size=".05 .05 .05" /></geometry><contact_coefficients mu="0" kp="1000.0" kd="1.0"/></collision> </link> <joint name="boxconnect" type="fixed"><origin xyz="0 0 0" /><parent link="rod"/><child link="box"/> </joint></robot>

    5.2 發布狀態
    現在我們需要一個方法來確定機器人是在哪個狀態下。為了完成這個目標,我們必須確定所有三個關節和全部的里程。從創建一個包開始:

    cd %TOP_DIR_YOUR_CATKIN_WS%/src catkin_create_pkg r2d2 roscpp rospy tf sensor_msgs std_msgs

    然后打開編輯器,添加下面的內容到src/state_publisher.cpp文件中:

    #include <string> #include <ros/ros.h> #include <sensor_msgs/JointState.h> #include <tf/transform_broadcaster.h>int main(int argc, char** argv) {ros::init(argc, argv, "state_publisher");ros::NodeHandle n;ros::Publisher joint_pub = n.advertise<sensor_msgs::JointState>("joint_states", 1);tf::TransformBroadcaster broadcaster;ros::Rate loop_rate(30);const double degree = M_PI/180;// robot statedouble tilt = 0, tinc = degree, swivel=0, angle=0, height=0, hinc=0.005;// message declarationsgeometry_msgs::TransformStamped odom_trans;sensor_msgs::JointState joint_state;odom_trans.header.frame_id = "odom";odom_trans.child_frame_id = "axis";while (ros::ok()) {//update joint_statejoint_state.header.stamp = ros::Time::now();joint_state.name.resize(3);joint_state.position.resize(3);joint_state.name[0] ="swivel";joint_state.position[0] = swivel;joint_state.name[1] ="tilt";joint_state.position[1] = tilt;joint_state.name[2] ="periscope";joint_state.position[2] = height;// update transform// (moving in a circle with radius=2)odom_trans.header.stamp = ros::Time::now();odom_trans.transform.translation.x = cos(angle)*2;odom_trans.transform.translation.y = sin(angle)*2;odom_trans.transform.translation.z = .7;odom_trans.transform.rotation = tf::createQuaternionMsgFromYaw(angle+M_PI/2);//send the joint state and transformjoint_pub.publish(joint_state);broadcaster.sendTransform(odom_trans);// Create new robot statetilt += tinc;if (tilt<-.5 || tilt>0) tinc *= -1;height += hinc;if (height>.2 || height<0) hinc *= -1;swivel += degree;angle += degree/4;// This will adjust as needed per iterationloop_rate.sleep();}return 0; }

    5.3 Launch文件
    這個launch文件假設你正在使用的包名稱為“r2d2”節點名稱為“state_publisher”,你已經保存了上面的urdf文件到r2d2包中

    <launch><param name="robot_description" command="cat $(find r2d2)/model.xml" /><node name="robot_state_publisher" pkg="robot_state_publisher" type="state_p-ublisher" /><node name="state_publisher" pkg="r2d2" type="state_publisher" /> </launch>

    5.4 查看結果
    首先我們應該編輯一下我們上面的代碼所在的Cmake.txt文件。確認添加tf依賴。

    find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs tf)

    注意roscpp是用來解析我們編寫和產生的state_publisher節點的代碼。也需要添加下面的內容到Cmakelists.txt文件的末尾以用來產生state_publisher節點:

    include_directories(include ${catkin_INCLUDE_DIRS}) add_executable(state_publisher src/state_publisher.cpp) target_link_libraries(state_publisher ${catkin_LIBRARIES})

    現在運行這個包 現在,我們應該到工作空間文件夾下構建包:

    catkin_make roslaunch r2d2 display.launch

    在一個新的終端中運行rviz:

    rosrun rviz rviz

    選擇odom作為你的固定坐標系。然后選擇”Add Display“并添加一個機器人模型顯示和一個TF顯示。

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的由浅到深理解ROS URDF教程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。