由浅到深理解ROS URDF教程
1.1創建樹形結構文件
在這部分教程中要創建的將是下面的圖形所描述的機器人的urdf文件
圖片中這個機器人是一個樹形結構的。讓我們開始非常簡單的創建這個樹型結構的描述文件,不用擔心維度等的問題。創建一個my_robot.urdf文件,內容如下:
所以,這里是僅僅創建了一個非常簡單的結構。現在我們來看一看我們能否解讀這個文件。可以使用一些簡單的命令行工具,來檢查你的語法是否正確。
需要安裝urdfdom作為一個上游的ROS獨立包
現在運行檢查命令(基于indigo)
check_urdf my_robot.urdf如果一切順利的話,將會看到的是
1.2添加坐標系(維度)信息
現在有了一個基本的樹形結構,讓我們來添加合適的坐標系信息。如你在圖片中看到的,每一個連接的參考系都在連接的底部,而且關節的參考系是完全相同的。所以,要添加維度到我們的樹上,我們要確認的就是從一個連接到自己子連接的關機的偏移量。為了完成這一部分,我們將會為每一個關節添加.
比如,我們來看第二個關節。joint2是link1在Y方向上的偏移,在X軸負方向上有一點點偏移,而且繞Z軸旋轉了90度,所以我們需要添加下面的元素。
在每一個關節重復這一改變,這個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.urdf1.3 完成運動學部分
我們現在還不確定的部分就是關節繞著哪個軸旋轉。一旦我們添加了這個部分,我們實際上有了這個機器人完整的運動學模型。我們要做的就是添加元素到每一個joint中。axis確定在局部的旋轉軸。
所以,如果你看joint2,你會看到它是繞著Y軸正方向旋轉。所以,需要簡單添加下面的內容到關節元素中:
相似的,需要向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
2.1解析一個URDF文件
首先,我們創建一個依賴于urdf解析器的包。
現在我們來創建一個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文件中添加這兩行
構建你的包,并運行它
$ 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文件如下:
3.2 作為一個庫運行
高級用戶也可以將機器人狀態發布者在他們自己的C++代碼中作為一個庫來使用。在你包含了頭文件之后:
你需要的就是一個采用了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解析器
這條命令將會安裝kdl_parser所有的外部依賴包。構建包,運行:
rosmake kdl_parser4.2 使用你的代碼
首先,添加KDL解析器作為一個依賴包,到你的package.xml文件中
在你的C++代碼開始階段,添加KDL解析器,包括下面的文件
#include <kdl_parser/kdl_parser.hpp>現在,有不同的方法來繼續進行,你可以從一個urdf用多種方法構建一個KDL樹。
4.2.1從一個文件
創建PR2的urdf文件,運行下面的命令
rosrun xacro xacro.py `rospack find pr2_description`/robots/pr2.urdf.xacro > pr2.urdf4.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的模型。
5.2 發布狀態
現在我們需要一個方法來確定機器人是在哪個狀態下。為了完成這個目標,我們必須確定所有三個關節和全部的里程。從創建一個包開始:
然后打開編輯器,添加下面的內容到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包中
5.4 查看結果
首先我們應該編輯一下我們上面的代碼所在的Cmake.txt文件。確認添加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教程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 再也不用找停车位了?百度首创一体化停车引
- 下一篇: 挤掉1500元水分 AMD的RX 660