一步一步制作自己的ROS仿真机器人-键盘+手柄+App控制
第一步:create ROS package
>mkdir-p ~/catkin_ws/src
>cd ~/catkin_ws/src
>catkin_init_workspace
>cd ..
>catkin_make
>source devel/setup.bash
>catkin_create_pkg ros_robotic
hou@houROS:~/catkin_ws/src $ catkin_create_pkg ros_robotic
Created file ros_robotic/CMakeLists.txt
Created file ros_robotic/package.xml
Successfully created files in /home/hou/catkin_ws/src/ros_robotic. Please adjust the values in package.xml.
第二步: 創(chuàng)建差速輪URDF
URDF is an XML format specifically defined to represent robot models down to their
component level. These URDF files can become long and cumbersome on complex
robot systems. Xacro (XML Macros) is an XML macro language created to make
these robot description files easier to read and maintain. Xacro helps you reduce
the duplication of information within the file.
我們將“增量式“的來(lái)建立我們的機(jī)器人,并在RVIZ里面進(jìn)行顯示。
1. 建立ros_robotic下面的urdf文件夾
hou@houROS:~/catkin_ws/src $ cd ros_robotic/
hou@houROS:~/catkin_ws/src/ros_robotic $ mkdir urdf
hou@houROS:~/catkin_ws/src/ros_robotic $ cd urdf/
hou@houROS:~/catkin_ws/src/ros_robotic/urdf
2. 建立底盤(pán)模型(robot chassis)urdf文件
vim dd_robot.urdf
<?xml version="1.0"?>
<robot name ="dd_robot">
<!--Base link-->
<link name="base_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0 "/>
<geometry>
<box size="0.5 0.4 0.25" />
</geometry>
<material name="yellow">
<color rgba="1 0.4 0 1"/>
</material>
</visual>
</link>
</robot>
這里建立一個(gè)一個(gè)長(zhǎng)方體的模型,原點(diǎn)是在零點(diǎn)(0, 0, 0),0.5m的長(zhǎng)度是均分在x方向,即正負(fù)方向的值是+0.25m, -0.25m,同理,y方向也是如此,從后面的圖中你也可以發(fā)現(xiàn),這個(gè)長(zhǎng)方體的重心是在(0, 0, 0)上。使用check_urdf命令來(lái)檢測(cè)模型文件的正確性
check_urdf dd_robot.urdf
得到如下結(jié)果
hou@houROS:~/catkin_ws/src/ros_robotic/urdf $ check_urdf dd_robot.urdf
robot name is: dd_robot
---------- Successfully Parsed XML ---------------
root Link: base_link has 0 child(ren)
模型正確,下面來(lái)寫(xiě)一個(gè)launch程序來(lái)把這個(gè)模型顯示在rviz里面
3. 編寫(xiě)launch顯示程序
在ros_robotic下新建一個(gè)launch文件夾,在文件夾內(nèi)新建dd_rviz.launch文件,內(nèi)容如下
<launch>
<!--Set these parameters on Parameter Server-->
<param name="robot_description"
textfile="$(find ros_robotic)/urdf/$(arg model)"/>
<!--Start 3 nodes: joint_state_publisher
robot_state_publisher and rviz-->
<node name="joint_state_publisher_gui" pkg="joint_state_publisher_gui" type="joint_state_publisher_gui"/>
<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher"/>
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find ros_robotic)/urdf.rviz" required="true"/>
</launch>
這個(gè)roslaunch 文件的主要作用有下面三個(gè):
? 1 通過(guò)命令行輸入的數(shù)據(jù)來(lái)導(dǎo)入詳細(xì)模型到參數(shù)服務(wù)器
? 2 通過(guò)節(jié)點(diǎn)發(fā)布JointState和坐標(biāo)變換
? 3 通過(guò)配置urdf.rviz來(lái)開(kāi)啟rviz可視化,這個(gè)urdf.rviz是打開(kāi)了rviz后提示你保存的。
使用如下命令來(lái)啟動(dòng)rviz,查看機(jī)器人模型
roslaunch ros_robotic dd_rviz.launch model:=dd_robot.urdf
此時(shí),不出意外,打開(kāi)的是一個(gè)空白的rviz,因?yàn)橐婚_(kāi)始是沒(méi)有urdf.rviz這個(gè)模型的
這個(gè)時(shí)候需要手動(dòng)點(diǎn)擊左下角的+號(hào),然后選擇RobotModel,這個(gè)時(shí)候,rviz里面才會(huì)有模型,如下
但是這里并沒(méi)有顯示顏色等信息,且左邊的Display欄目還有有紅色的錯(cuò)誤提示,這個(gè)時(shí)候,繼續(xù)點(diǎn)擊add,添加TF,同時(shí)在Displays下面的Fixed frame輸入base_link,出現(xiàn)如下所示
關(guān)閉rviz,點(diǎn)擊保存,細(xì)心的你會(huì)發(fā)現(xiàn)在包ros_robotic下面有一個(gè)urdf.rviz,有了這個(gè),下次執(zhí)行roslaunch
roslaunch ros_robotic dd_rviz.launch model:=dd_robot.urdf
的時(shí)候,一開(kāi)打就能看見(jiàn)這個(gè)robot_chasis。注意,這個(gè)的模型正中心就是在零點(diǎn)上。
4. 添加輪子
現(xiàn)在,讓我們?cè)跈C(jī)器人上添加車(chē)輪的shapes和links。 將links元素添加到URDF文件時(shí),必須添加關(guān)節(jié)joint以描述links之間的關(guān)系。關(guān)節(jié)joint元素定義關(guān)節(jié)是靈活的(可移動(dòng)的)還是不靈活的(固定的)。 對(duì)于撓性接頭,URDF描述了接頭的運(yùn)動(dòng)學(xué)和動(dòng)力學(xué)以及其安全極限。 在URDF中,有六種可能的關(guān)節(jié)類(lèi)型,如下所示:
fixed 固定的關(guān)節(jié),不能移動(dòng) revolute 能夠繞一個(gè)軸旋轉(zhuǎn),有角度限制 continuous 能夠繞一個(gè)軸旋轉(zhuǎn),無(wú)角度限制 prismatic 滑動(dòng)副 floating 浮動(dòng),無(wú)約束的 planar 可以在垂直于軸的平面內(nèi)運(yùn)動(dòng)
很明顯,我們的輪子和機(jī)體之間的關(guān)節(jié)是一個(gè)連續(xù)轉(zhuǎn)動(dòng)無(wú)角度限制的,也就是continuous,這個(gè)關(guān)節(jié),實(shí)際上就是電機(jī),因?yàn)閷?shí)際中是電機(jī)帶動(dòng)輪子來(lái)轉(zhuǎn)動(dòng)的,就像下面圖里一樣。
在dd_robot.urdf文件里繼續(xù)添加如下代碼,添加電機(jī)和右側(cè)輪子
<!--joint_right_wheel-->
<joint name="joint_right_wheel" type="continuous">
<parent link="base_link"/>
<child link="right_wheel"/>
<origin xyz="-0.30 -0.1 0.0" rpy="0.0 1.570795 0.0"/>
<axis xyz="0.0 1 0.0"/>
</joint>
<!--right link-->
<link name="right_wheel">
<visual>
<origin xyz="0 0 0" rpy="0 0 0 "/>
<geometry>
<cylinder radius="0.2" length="0.1"/>
</geometry>
<material name="red">
<color rgba="1 0 0 1"/>
</material>
</visual>
</link>
效果如圖
另外一點(diǎn)還是需要說(shuō)一下,是rviz里面的方向,x y z都朝向什么方向得弄清楚,通過(guò)設(shè)置左邊的透明值A(chǔ)lpha為0.5,可以發(fā)現(xiàn)base_link透明了,如下圖。
在rviz中,默認(rèn)紅色代表x方向,綠色代表y方向,藍(lán)色代表Z方向,記憶起來(lái)就是RGB-> XYZ(似乎solidworks里面也是,我們后面再討論,現(xiàn)在這里埋下一個(gè)疑問(wèn))。輪的坐標(biāo)其實(shí)是相對(duì)綠色的轉(zhuǎn)動(dòng)了90度,從代碼上看,這是體現(xiàn)在輪的joint上面的,所以,輪的joint代碼是這個(gè)樣子:
<!--joint_right_wheel-->
<joint name="joint_right_wheel" type="continuous">
<parent link="base_link"/>
<child link="right_wheel"/>
<origin xyz="-0.30 -0.1 0.0" rpy="0.0 1.570795 0.0"/>
<axis xyz="0.0 1 0.0"/>
</joint>
電機(jī)是連續(xù)轉(zhuǎn)動(dòng)的,所以joint 的type是continuous,parent link為底盤(pán),這個(gè)joint 的子link連接著輪子,即child link="right_wheel"
輪的joint原點(diǎn)(即電機(jī)),在-x方向,0.30m處,-y方向0.1m出,z方向和中心一樣,rpy="0.0 1.570795 0.0",代表從y正方向看,繞y轉(zhuǎn)動(dòng)了90度,用弧度表示為1.570795,這里的r p y,是row, pitch, yaw的縮寫(xiě),中文意思是滾轉(zhuǎn),俯仰,偏航。
這句話定義輪子的旋轉(zhuǎn)軸,這里我選擇了y軸,但是一看是有問(wèn)題的,應(yīng)該是相對(duì)藍(lán)色的軸轉(zhuǎn)動(dòng),這個(gè)我們?cè)诤竺嬲{(diào)整。
輪子的代碼
<!--right link-->
<link name="right_wheel">
<visual>
<origin xyz="0 0 0" rpy="0 0 0 "/>
<geometry>
<cylinder radius="0.2" length="0.1"/>
</geometry>
<material name="red">
<color rgba="1 0 0 1"/>
</material>
</visual>
</link>
輪子為一個(gè)圓柱體cylinder,半徑0.2,高度0.1,注意,在rviz里面默認(rèn)的圓柱體是垂直地面創(chuàng)建的,為了驗(yàn)證,我們把dd_robot.urdf文件中的base_link和right_wheel_joint的代碼都刪掉,再在rviz中打開(kāi),看效果。
看看零點(diǎn)在什么位置。
和之前說(shuō)的長(zhǎng)方體一樣,零點(diǎn)還是在正中心,你可以理解為重心的地方。這個(gè)地方你就理解了,為什么我把電機(jī)的joint放在-0.3的位置了,因?yàn)檫@樣看起來(lái)輪子剛好是連在地盤(pán)上的,0.25+0.05剛好是旋轉(zhuǎn)之后輪子重心的位置。
對(duì)于左邊的電機(jī)和輪子,也是同樣的分析道理,下面直接上代碼和效果。
<!--joint_left_wheel-->
<joint name="joint_left_wheel" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin xyz="0.30 -0.1 0.0" rpy="0.0 1.570795 0.0"/>
<axis xyz="0.0 1 0.0"/>
</joint>
<!--left link-->
<link name="left_wheel">
<visual>
<origin xyz="0 0 0" rpy="0 0 0 "/>
<geometry>
<cylinder radius="0.2" length="0.1"/>
</geometry>
<material name="red">
<color rgba="1 0 0 1"/>
</material>
</visual>
</link>
</robot>
運(yùn)行roslaunch 命令
hou@houROS:~/catkin_ws $ roslaunch ros_robotic dd_rviz.launch model:=dd_robot.urdf
效果:
這樣的輪子會(huì)倒,在前面加上一個(gè)球形萬(wàn)向輪,作為支撐,代碼為:
<!--front_castor_joint-->
<joint name="front_castor_joint" type="fixed">
<parent link="base_link"/>
<child link="front_castor_link"/>
<origin xyz="0 0.1625 -0.1625" rpy="0.0 0.0 0.0"/>
<axis xyz="0.0 1 0.0"/>
</joint>
<!--front castor link-->
<link name="front_castor_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0 "/>
<geometry>
<sphere radius="0.0375"/>
</geometry>
<material name="red">
<color rgba="1 0 0 1"/>
</material>
</visual>
</link>
效果如圖:
5. 添加碰撞及慣性參數(shù)
添加collision屬性
接下來(lái),我們將屬性添加到每個(gè)元素中。 即使我們已經(jīng)定義了元素的視覺(jué)屬性,Gazebo的碰撞檢測(cè)引擎仍會(huì)使用碰撞屬性來(lái)識(shí)別對(duì)象的邊界。 如果對(duì)象具有復(fù)雜的視覺(jué)屬性(例如網(wǎng)格),則應(yīng)定義簡(jiǎn)化的碰撞屬性,以提高碰撞檢測(cè)性能。
<!--Base link-->
<link name="base_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0 "/>
<geometry>
<box size="0.5 0.4 0.25" />
</geometry>
<material name="yellow">
<color rgba="1 0.4 0 1"/>
</material>
</visual>
<!--base link collsion-->
<collision>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/>
<geometry>
<box size="0.5 0.4 0.25" />
</geometry>
</collision>
</link>
注意,是在每個(gè)Link里面添加這個(gè)collision屬性,由于本次模型簡(jiǎn)單,collison里面的尺寸參數(shù)和visual里面是一樣的。
其他的link也是類(lèi)似,這里就不再詳細(xì)闡述,可以參閱最終的代碼。
添加慣性inertial參數(shù)
慣性參數(shù)直接反映了機(jī)器人的重量以及實(shí)際運(yùn)動(dòng)學(xué)方面的特性,舉個(gè)例子來(lái)說(shuō),大慣量的物體,啟動(dòng)起來(lái)就比較慢,這個(gè)你可以理解為靈活性的一種表示了。
參數(shù)主要包含兩個(gè)方面,一個(gè)是重量mass,另外一個(gè)就是慣量了。下面直接上代碼。
<inertial>
<mass value="0.5"/>
<inertia ixx="0.01" ixy="0.0" ixz="0.0"
iyy="0.005" iyz="0.0" izz="0.005"/>
</inertial>
運(yùn)行roslaunch ros_robotic dd_rviz.launch model:=dd_robot.urdf 效果如下
此時(shí),可以通過(guò)滑動(dòng)滑桿來(lái)操作輪子轉(zhuǎn)動(dòng),我們來(lái)試一下。
尷尬,大型翻車(chē)現(xiàn)場(chǎng),回到上文(飛機(jī)模型下面提到的)這個(gè)axis的設(shè)置有問(wèn)題,我們看一下,當(dāng)前兩個(gè)輪子的旋轉(zhuǎn)是
<!--joint_right_wheel-->
<joint name="joint_right_wheel" type="continuous">
<parent link="base_link"/>
<child link="right_wheel"/>
<origin xyz="-0.30 -0.1 0.0" rpy="0.0 1.570795 0.0"/>
<axis xyz="0.0 1 0.0"/>
</joint>
-----
<!--joint_left_wheel-->
<joint name="joint_left_wheel" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin xyz="0.30 -0.1 0.0" rpy="0.0 1.570795 0.0"/>
<axis xyz="0.0 1 0.0"/>
</joint>
將兩個(gè)Joint的改成
<axis xyz="0.0 0 1.0"/>
再次運(yùn)行查看效果
OK,就是這個(gè)效果,現(xiàn)在可以通過(guò)滑桿來(lái)讓輪子轉(zhuǎn)動(dòng)了。既然輪子可以轉(zhuǎn)動(dòng),那么機(jī)器人就可以在rviz里面運(yùn)動(dòng)了,
how?
6. 添加運(yùn)動(dòng)控制器
ArbotiX控制器可以用來(lái)控制差動(dòng)輪,配合rviz搭建仿真環(huán)境,
1. 安裝ArbotiX
在當(dāng)前工作空間的src下面的文件夾內(nèi)使用如下命令,將ArbotiX的源碼從github上下載克隆到本地
git clone https://github.com/vanadiumlabs/arbotix_ros.git
下載成功后,回到工作空間根目錄,使用catkin_make編譯
2. 配置ArbotiX控制器
這里只需要?jiǎng)?chuàng)建一個(gè)啟動(dòng)ArbotiX的節(jié)點(diǎn)的launch文件即可
在launch文件夾下創(chuàng)建一個(gè)dd_robot_with_arbotix.launch
<launch>
<arg name="model"/>
<param name="/use_sim_time" value="false" />
<!--Set these parameters on Parameter Server-->
<param name="robot_description"
textfile="$(find ros_robotic)/urdf/$(arg model)"/>
<node name="arbotix" pkg="arbotix_python" type="arbotix_driver" output="screen">
<rosparam file="$(find ros_robotic)/config/fake_robot_arbotix.yaml" command="load" />
<param name="sim" value="true"/>
</node>
<!--Start 3 nodes: joint_state_publisher
robot_state_publisher and rviz-->
<node name="joint_state_publisher_gui" pkg="joint_state_publisher_gui" type="joint_state_publisher_gui"/>
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher">
<param name="publish_frequency" type="double" value="20.0" />
</node>
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find ros_robotic)/urdf.rviz" required="true"/>
</launch>
同時(shí)在ros_robotic包文件夾下,新建config目錄,新建fake_robot_arbotix.yaml配置文件,內(nèi)容為
controllers: {
base_controller: {type: diff_controller, base_frame_id: base_link, base_ 0.5, ticks_meter: 400, Kp: 12, Kd: 12, Ki: 0, Ko: 50, accel_limit: 1.0 }
}
運(yùn)行l(wèi)aunch文件
roslaunch ros_robotic dd_robot_with_arbotix.launch model:=dd_robot.urdf
效果如下,這個(gè)時(shí)候其實(shí)看不出什么效果,動(dòng)起來(lái)才能看的見(jiàn):
7. 使用鍵盤(pán)來(lái)控制機(jī)器人
安裝teleop_twist_key功能包,
在src下面使用如下命令
git clone https://github.com/ros-teleop/teleop_twist_keyboard.git
然后,回到src的上級(jí)目錄,執(zhí)行
catkin_make
然后,source一下當(dāng)前的工作空間
source devel/setup.bash
此時(shí),運(yùn)行teleop_twist_keyboard功能包節(jié)點(diǎn)
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
Reading from the keyboard and Publishing to Twist!
---------------------------
Moving around:
u i o
j k l
m , .
For Holonomic mode (strafing), hold down the shift key:
---------------------------
U I O
J K L
M < >
t : up (+z)
b : down (-z)
anything else : stop
q/z : increase/decrease max speeds by 10%
w/x : increase/decrease only linear speed by 10%
e/c : increase/decrease only angular speed by 10%
CTRL-C to quit
currently: speed 0.5 turn 1.0
此時(shí)將兩個(gè)窗口并排放置,如圖
按動(dòng)I鍵,動(dòng)起來(lái)吧!
翻車(chē)again!
本來(lái)是前進(jìn)的,結(jié)果橫向移動(dòng)了。why?
這里是方向錯(cuò)了,我們來(lái)解釋。
第一,I鍵給的指令是x方向的速度,而我們機(jī)器人地盤(pán)上x(chóng)方向是橫向的,當(dāng)i給一個(gè)x速度的時(shí)候,就平移了,現(xiàn)在是綠色的箭頭(y方向)是地盤(pán)的正方向,其實(shí),我們給y發(fā)速度就行了,看看
hou@houROS:~ $ rostopic pub /cmd_vel geometry_msgs/Twist "linear:
x: 0.0
y: 1.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.0"
看怎么走?
此時(shí)命令回車(chē)之后,顯示
hou@houROS:~ $ $ rtopic pub /cmd_vel geometry_msgs/Twist "linear:
x: 0.0
y: 1.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.0"
publishing and latching message. Press ctrl-C to terminate
并咩有動(dòng),我們后面有空研究咋回事。
這里,我將urdf里面的長(zhǎng)寬改變過(guò)來(lái).
<box size="0.5 0.4 0.25" />
改為
<box size="0.4 0.5 0.25" />
right joint和left joint改為
origin xyz="-0.1 -0.30 0.0" rpy="1.570795 0 0"/>
支撐輪改為
<origin xyz=" 0.1625 0 -0.1625" rpy="0.0 0.0 0.0"/>
OK,在rviz內(nèi)重新加載
roslaunch ros_robotic dd_robot_with_arbotix.launch model:=dd_robot.urdf
動(dòng)起來(lái)了,非常爽!
8. 使用游戲手柄來(lái)控制機(jī)器人
1.安裝手柄驅(qū)動(dòng):
modprobe joydev
2.安裝手柄測(cè)試軟件:
sudo apt-get install joystick (joystick校準(zhǔn)手柄)
3.測(cè)試手柄:
jstest /dev/input/js0
搞清楚對(duì)應(yīng)的是那個(gè)按鍵
下載teleop_twist_joy功能包,在工作空間下編譯,打開(kāi)launch文件夾下的teleop.launch,修改
<launch>
<arg name="joy_config" default="beitong" />
<arg name="joy_dev" default="/dev/input/js0" />
<arg name="config_filepath" default="$(find teleop_twist_joy)/config/$(arg joy_config).config.yaml" />
<node pkg="joy" type="joy_node" name="joy_node">
<param name="dev" value="$(arg joy_dev)" />
<param name="deadzone" value="0.05" />
<param name="autorepeat_rate" value="0.0" />
</node>
<node pkg="teleop_twist_joy" name="teleop_twist_joy" type="teleop_node">
<rosparam command="load" file="$(arg config_filepath)" />
</node>
</launch>
同時(shí),在config文件夾下面的新建一個(gè)手柄配置文件,我這里使用的是北通手柄,這里新建一個(gè)beitong.config.yaml,內(nèi)容為
axis_linear: 1
scale_linear: 1
scale_linear_turbo: 0
axis_angular: 0
scale_angular: 0.4
enable_button: 4
enable_turbo_button: 5
運(yùn)行
roslaunch teleop_twist_joy teleop.launch
非常爽,這里用左邊的搖桿來(lái)控制前進(jìn)和轉(zhuǎn)向,和我之前使用的無(wú)人機(jī)有點(diǎn)不同,這里讓左邊搖桿來(lái)控制前進(jìn),右邊搖桿來(lái)控制轉(zhuǎn)彎,只需要將配置文件beitong.config.yaml,更改成:
axis_linear: 1
scale_linear: 1
scale_linear_turbo: 0
axis_angular: 2
scale_angular: 0.4
enable_button: 4
enable_turbo_button: 5
OK,非常給力。
9. 使用手機(jī)app來(lái)控制
下載ros_control app,如圖:
新建機(jī)器人,連接上當(dāng)前電腦的ip地址,在高級(jí)設(shè)置里面設(shè)置好速度話題為/cmd_vel,如果你用來(lái)控制小烏龜?shù)脑挘桶堰@個(gè)地方改成/turtle1/cmd_vel,進(jìn)入界面,移動(dòng)觸干,小車(chē)動(dòng)起來(lái)了,爽!
不過(guò)有個(gè)問(wèn)題,同時(shí)使用遙控器和APP來(lái)控制,再將APP關(guān)閉之后,用手柄控制起來(lái)就顯得有點(diǎn)卡頓了,具體原因再找。使用rosnode kill把APP節(jié)點(diǎn)干掉之后,不再卡頓。
rosnode kill /android/robot_controller
killing /android/robot_controller
killed
總 結(jié)
本文一步步搭建了自己的小車(chē),并通過(guò)鍵盤(pán)、手柄、App來(lái)實(shí)現(xiàn)了控制,對(duì)urdf模型的建立、rviz的基礎(chǔ)認(rèn)識(shí)有了一個(gè)更進(jìn)一步的體會(huì)。但是手寫(xiě)urdf真的是太費(fèi)勁了,后面我將用solidworks和xacro來(lái)實(shí)現(xiàn),同時(shí)也會(huì)將rviz里面的機(jī)器人搬到gazebo里面來(lái)跑。
很爽,奧里給!
總結(jié)
以上是生活随笔為你收集整理的一步一步制作自己的ROS仿真机器人-键盘+手柄+App控制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Django forms组件
- 下一篇: Navicat新建查询快捷键