这一篇内容的成果大概长这样,因为比较简单,手写比较方便。
视频地址: https://www.bilibili.com/video/av34229434/
关于urdf的介绍目前看到的最好的一篇介绍应该是ROSCon的这篇
https://youtu.be/g9WHxOpAUns
ROSWIKI上有完整的urdf教程,你可以根据教程自己写一些简单的机器人,实际上相当的麻烦而且容易出错,我以前从未想过用这种方法写一个机器人的模型出来,还以为和做游戏一样在Blender或者3dsmax这样的建模软件里搞定一切然后直接导出到rviz里就能摆弄了。实际上urdf也是可以的,但目前好像只有solidworks和matlab有这种插件,其中solidworks的插件叫做sw2urdf,我使用了之后发现还是相当方便的,至少比手写方便。
catkin_create_pkg <你要创建的package的名字> roscpp tf geometry_msgs urdf rviz xacro
创建好包之后我们来写urdf,目前好像没找到带urdf代码提示插件的文本编辑器,如果你使用带ros_qct_plugin的qtcreator的话里面可以新建urdf文件,但并没有提示功能。
下面具体来写这个简单的sg90舵机的urdf文件的过程
首先打开http://wiki.ros.org/urdf/XML
urdf是一种XML格式的文件,参考上面的链接找到你需要的东西,主要是各种link和joint。
上面这个舵机的模型由两个link和一个joint组成,下面蓝色的是舵机本体,上面红色的是买舵机的时候送的配件,非常便宜,随处可见。
不能在urdf里直接写出它们模型,而是选择mesh型的link,从别的地方引用一个stl格式的模型。这里是用Blender简单的做了一个sg90的外形。
做的时候看了一下比例,Blender里默认的box大小是2m2m2m,在urdf里直接写一个box型的link,size设置成“2 2 2”,两者的大小是一样的。如果懒得做模型的话直接搞两个box替代就好了。
其中joint是比较关键的部分,joint有很多种,比较常见的有
- continuous 可以一直转下去
- revolute 舵机一般用这种,可以从一个角度转到另一个角度,limit里设置一下就好了
- prismatic 沿着一个导轨平移的东西就用它
- fixed 什么也不干,只是把两个link就这么接在一起
这里值得注意的是joint的
我一度认为effort和velocity就是下图的torque和speed
然而好像并不是,effort是百分数,velocity是每秒转动的弧度。
所以目前填什么其实都无所谓,现阶段arduino只接收position就行了。
这两个link实际上是从外部导入的stl格式的3d模型,但很多3d模型很复杂,所以有英伟达显卡的话最好能安装一下驱动程序,另外要准备一份低模,也就是面数比较低的模型,俗称low-poly,作为机器人的碰撞体collision,外形和尺寸要和你的用于显示的高模差不多,origin当然也要设置成一样的。
另外需要注意的是joint的位置和旋转的轴,这点在上面那个ROSCon的视频里有比较直观的讲解。写的时候脑子未必能转的过来,需要时不时打开rviz查看模型是否正确,所以这个时候就需要写一个launch文件来启动rviz。这里顺便一说atom有一个ros代码提示的package,可以用来写launch文件,大概长这样:
这里值得注意的是joint_state_publisher 和 robot_state_publisher
前者用于发布joint_state信息,大概长这样:
Header header
string[] name
float64[] position
float64[] velocity
float64[] effort
http://docs.ros.org/melodic/api/sensor_msgs/html/msg/JointState.html
现阶段我们在arduino中订阅joint_state这个话题就能获得上面这些信息,比如我们可以将位于"0"的舵机旋转到msg.position[0]的位置。
当初在YouTube上看到了这个视频
问了作者之后发现原来只要订阅joint_state就行了。现在我们稍微修改一下ros_lib里控制舵机的示例代码来测试一下这个想法。
#if (ARDUINO >= 100)
#include
#else
#include
#endif
#include
#include
#include
#include
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 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之外还要设置参数
这样运行的时候就会有GUI你可以用上面的slider来控制之前在joint->limit里设置的角度,这里是从-1.57到1.57,原因是它是一个180度的舵机。
然后我们使用刚刚的launch文件进入rviz
首先把Fixed Frame设置成我们的base_link,然后添加RobotModel,其中Robot Description就是我们刚刚写的urdf。
滑动刚刚那个slider的话就可以让上面这个红色的配件沿着事先设定好的轴旋转,这个在urdf的joint中设定。
值得一提的是每个link还有joint都有
child link的origin实际上是相对于它的parent link的,如果发生了问题,比如上面的配件转的莫名奇妙的,那可能是joint的origin和axis没有设置好,这点在从solidworks导出的时候也有可能出现(老年痴呆),所以掌握了手写urdf的技巧的话就不用重新导出好几遍了。
现在,无论是rviz里的3d模型还是现实中的sg90舵机都订阅了joint_states,它们会同步旋转。
https://www.bilibili.com/video/av34229434/
下一篇可能是讲如何使用sw2urdf,直接从solidworks里导出urdf文件(我反正是不想手写,xacro也不想写)