這一篇內(nèi)容的成果大概長這樣侄榴,因?yàn)楸容^簡單雹锣,手寫比較方便。
視頻地址: https://www.bilibili.com/video/av34229434/
關(guān)于urdf的介紹目前看到的最好的一篇介紹應(yīng)該是ROSCon的這篇
https://youtu.be/g9WHxOpAUns
ROSWIKI上有完整的urdf教程蕊爵,你可以根據(jù)教程自己寫一些簡單的機(jī)器人,實(shí)際上相當(dāng)?shù)穆闊┒胰菀壮鲥e桦山,我以前從未想過用這種方法寫一個機(jī)器人的模型出來攒射,還以為和做游戲一樣在Blender或者3dsmax這樣的建模軟件里搞定一切然后直接導(dǎo)出到rviz里就能擺弄了。實(shí)際上urdf也是可以的恒水,但目前好像只有solidworks和matlab有這種插件会放,其中solidworks的插件叫做sw2urdf,我使用了之后發(fā)現(xiàn)還是相當(dāng)方便的钉凌,至少比手寫方便咧最。
catkin_create_pkg <你要創(chuàng)建的package的名字> roscpp tf geometry_msgs urdf rviz xacro
創(chuàng)建好包之后我們來寫urdf,目前好像沒找到帶urdf代碼提示插件的文本編輯器,如果你使用帶ros_qct_plugin的qtcreator的話里面可以新建urdf文件矢沿,但并沒有提示功能滥搭。
下面具體來寫這個簡單的sg90舵機(jī)的urdf文件的過程
首先打開http://wiki.ros.org/urdf/XML
urdf是一種XML格式的文件,參考上面的鏈接找到你需要的東西捣鲸,主要是各種link和joint瑟匆。
上面這個舵機(jī)的模型由兩個link和一個joint組成,下面藍(lán)色的是舵機(jī)本體栽惶,上面紅色的是買舵機(jī)的時候送的配件愁溜,非常便宜,隨處可見媒役。
不能在urdf里直接寫出它們模型,而是選擇mesh型的link宪迟,從別的地方引用一個stl格式的模型酣衷。這里是用Blender簡單的做了一個sg90的外形。
做的時候看了一下比例次泽,Blender里默認(rèn)的box大小是2m2m2m穿仪,在urdf里直接寫一個box型的link,size設(shè)置成“2 2 2”意荤,兩者的大小是一樣的啊片。如果懶得做模型的話直接搞兩個box替代就好了。
<?xml version="1.0"?>
<robot name="my_01">
<link name="base_link">
<visual>
<geometry>
<mesh filename="package://my_robot/meshes/servo_9g.stl" size="1 1 1" />
</geometry>
<material name="blue">
<color rgba="0 31 255 1"/>
</material>
<origin rpy="0 0 0" xyz="0 0 0" />
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://my_robot/meshes/servo_9g.stl" size="1 1 1" />
</geometry>
</collision>
</link>
<joint name="base_link_to_link_01" type="revolute">
<parent link="base_link"/>
<child link="link_01" />
<origin xyz="0.5 0 1.4" />
<axis xyz="0 0 -1" />
<limit effort="2.5" velocity="0.1" lower="-1.57" upper="1.57" />
<!-- <dynamics damping="0" friction="0" /> -->
</joint>
<link name="link_01">
<visual>
<geometry>
<mesh filename="package://my_robot/meshes/servo_9g_bar.stl" size="1 1 1" />
</geometry>
<origin rpy="0 0 0" xyz="0 0 0" />
</visual>
<collision>
<geometry>
<mesh filename="package://my_robot/meshes/servo_9g_bar.stl" size="1 1 1" />
</geometry>
<origin rpy="0 0 0" xyz="0 0 0" />
</collision>
</link>
</robot>
其中joint是比較關(guān)鍵的部分玖像,joint有很多種紫谷,比較常見的有
- continuous 可以一直轉(zhuǎn)下去
- revolute 舵機(jī)一般用這種,可以從一個角度轉(zhuǎn)到另一個角度捐寥,limit里設(shè)置一下就好了
- prismatic 沿著一個導(dǎo)軌平移的東西就用它
- fixed 什么也不干笤昨,只是把兩個link就這么接在一起
這里值得注意的是joint的
<limit effort="2.5" velocity="0.1" lower="-1.57" upper="1.57" />
我一度認(rèn)為effort和velocity就是下圖的torque和speed
然而好像并不是,effort是百分?jǐn)?shù)握恳,velocity是每秒轉(zhuǎn)動的弧度瞒窒。
所以目前填什么其實(shí)都無所謂,現(xiàn)階段arduino只接收position就行了乡洼。
這兩個link實(shí)際上是從外部導(dǎo)入的stl格式的3d模型崇裁,但很多3d模型很復(fù)雜,所以有英偉達(dá)顯卡的話最好能安裝一下驅(qū)動程序束昵,另外要準(zhǔn)備一份低模拔稳,也就是面數(shù)比較低的模型,俗稱low-poly锹雏,作為機(jī)器人的碰撞體collision壳炎,外形和尺寸要和你的用于顯示的高模差不多,origin當(dāng)然也要設(shè)置成一樣的。
另外需要注意的是joint的位置和旋轉(zhuǎn)的軸匿辩,這點(diǎn)在上面那個ROSCon的視頻里有比較直觀的講解腰耙。寫的時候腦子未必能轉(zhuǎn)的過來,需要時不時打開rviz查看模型是否正確铲球,所以這個時候就需要寫一個launch文件來啟動rviz挺庞。這里順便一說atom有一個ros代碼提示的package,可以用來寫launch文件稼病,大概長這樣:
<launch>
<arg name="model" />
<param name="robot_description" textfile="$(find my_robot)/urdf/my01.urdf" />
<param name="use_gui" value="true"/>
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
<node name="rviz" pkg="rviz" type="rviz" />
</launch>
這里值得注意的是joint_state_publisher 和 robot_state_publisher
前者用于發(fā)布joint_state信息选侨,大概長這樣:
Header header
string[] name
float64[] position
float64[] velocity
float64[] effort
http://docs.ros.org/melodic/api/sensor_msgs/html/msg/JointState.html
現(xiàn)階段我們在arduino中訂閱joint_state這個話題就能獲得上面這些信息,比如我們可以將位于"0"的舵機(jī)旋轉(zhuǎn)到msg.position[0]的位置。
當(dāng)初在YouTube上看到了這個視頻
問了作者之后發(fā)現(xiàn)原來只要訂閱joint_state就行了∪蛔撸現(xiàn)在我們稍微修改一下ros_lib里控制舵機(jī)的示例代碼來測試一下這個想法援制。
#if (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#include <Servo.h>
#include <ros.h>
#include <std_msgs/UInt16.h>
#include <sensor_msgs/JointState.h>
ros::NodeHandle nh;
//float pos=0;
Servo servo;
void servo_cb(const sensor_msgs::JointState& msg)
{
float pos=msg.position[0];
servo.write(90-pos*57.3248);
}
ros::Subscriber<sensor_msgs::JointState> sub("joint_states",servo_cb);
void setup(){
//Serial.begin(57600);
nh.initNode();
nh.subscribe(sub);
servo.attach(9); //attach it to pin 9
}
void loop(){
nh.spinOnce();
delay(1);
}
于此同時,在launch文件里啟動joint_state_publisher之外還要設(shè)置參數(shù)
<param name="use_gui" value="true"/>
這樣運(yùn)行的時候就會有GUI你可以用上面的slider來控制之前在joint->limit里設(shè)置的角度芍瑞,這里是從-1.57到1.57晨仑,原因是它是一個180度的舵機(jī)。
然后我們使用剛剛的launch文件進(jìn)入rviz
首先把Fixed Frame設(shè)置成我們的base_link,然后添加RobotModel拆檬,其中Robot Description就是我們剛剛寫的urdf洪己。
滑動剛剛那個slider的話就可以讓上面這個紅色的配件沿著事先設(shè)定好的軸旋轉(zhuǎn),這個在urdf的joint中設(shè)定竟贯。
值得一提的是每個link還有joint都有
<origin rpy="0 0 0" xyz="0 0 0" />
child link的origin實(shí)際上是相對于它的parent link的答捕,如果發(fā)生了問題,比如上面的配件轉(zhuǎn)的莫名奇妙的屑那,那可能是joint的origin和axis沒有設(shè)置好拱镐,這點(diǎn)在從solidworks導(dǎo)出的時候也有可能出現(xiàn)(老年癡呆),所以掌握了手寫urdf的技巧的話就不用重新導(dǎo)出好幾遍了持际。
現(xiàn)在痢站,無論是rviz里的3d模型還是現(xiàn)實(shí)中的sg90舵機(jī)都訂閱了joint_states,它們會同步旋轉(zhuǎn)选酗。
https://www.bilibili.com/video/av34229434/
下一篇可能是講如何使用sw2urdf阵难,直接從solidworks里導(dǎo)出urdf文件(我反正是不想手寫,xacro也不想寫)