第一步: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.
第二步: 創建差速輪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.
我們將“增量式“的來建立我們的機器人,並在RVIZ里面進行顯示。
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. 建立底盤模型(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>
這里建立一個一個長方體的模型,原點是在零點(0, 0, 0),0.5m的長度是均分在x方向,即正負方向的值是+0.25m, -0.25m,同理,y方向也是如此,從后面的圖中你也可以發現,這個長方體的重心是在(0, 0, 0)上。使用check_urdf命令來檢測模型文件的正確性
check_urdf dd_robot.urdf
得到如下結果
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)
模型正確,下面來寫一個launch程序來把這個模型顯示在rviz里面
3. 編寫launch顯示程序
在ros_robotic下新建一個launch文件夾,在文件夾內新建dd_rviz.launch文件,內容如下
<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>
這個roslaunch 文件的主要作用有下面三個:
1 通過命令行輸入的數據來導入詳細模型到參數服務器
2 通過節點發布JointState和坐標變換
3 通過配置urdf.rviz來開啟rviz可視化,這個urdf.rviz是打開了rviz后提示你保存的。
使用如下命令來啟動rviz,查看機器人模型
roslaunch ros_robotic dd_rviz.launch model:=dd_robot.urdf
此時,不出意外,打開的是一個空白的rviz,因為一開始是沒有urdf.rviz這個模型的
這個時候需要手動點擊左下角的+號,然后選擇RobotModel,這個時候,rviz里面才會有模型,如下
但是這里並沒有顯示顏色等信息,且左邊的Display欄目還有有紅色的錯誤提示,這個時候,繼續點擊add,添加TF,同時在Displays下面的Fixed frame輸入base_link,出現如下所示
關閉rviz,點擊保存,細心的你會發現在包ros_robotic下面有一個urdf.rviz,有了這個,下次執行roslaunch
roslaunch ros_robotic dd_rviz.launch model:=dd_robot.urdf
的時候,一開打就能看見這個robot_chasis。注意,這個的模型正中心就是在零點上。
4. 添加輪子
現在,讓我們在機器人上添加車輪的shapes和links。 將links元素添加到URDF文件時,必須添加關節joint以描述links之間的關系。關節joint元素定義關節是靈活的(可移動的)還是不靈活的(固定的)。 對於撓性接頭,URDF描述了接頭的運動學和動力學以及其安全極限。 在URDF中,有六種可能的關節類型,如下所示:
fixed 固定的關節,不能移動 revolute 能夠繞一個軸旋轉,有角度限制 continuous 能夠繞一個軸旋轉,無角度限制 prismatic 滑動副 floating 浮動,無約束的 planar 可以在垂直於軸的平面內運動
很明顯,我們的輪子和機體之間的關節是一個連續轉動無角度限制的,也就是continuous,這個關節,實際上就是電機,因為實際中是電機帶動輪子來轉動的,就像下面圖里一樣。
在dd_robot.urdf文件里繼續添加如下代碼,添加電機和右側輪子
<!--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>
效果如圖
另外一點還是需要說一下,是rviz里面的方向,x y z都朝向什么方向得弄清楚,通過設置左邊的透明值Alpha為0.5,可以發現base_link透明了,如下圖。
在rviz中,默認紅色代表x方向,綠色代表y方向,藍色代表Z方向,記憶起來就是RGB-> XYZ(似乎solidworks里面也是,我們后面再討論,現在這里埋下一個疑問)。輪的坐標其實是相對綠色的轉動了90度,從代碼上看,這是體現在輪的joint上面的,所以,輪的joint代碼是這個樣子:
<!--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 的type是continuous,parent link為底盤,這個joint 的子link連接着輪子,即child link="right_wheel"
輪的joint原點(即電機),在-x方向,0.30m處,-y方向0.1m出,z方向和中心一樣,rpy="0.0 1.570795 0.0",代表從y正方向看,繞y轉動了90度,用弧度表示為1.570795,這里的r p y,是row, pitch, yaw的縮寫,中文意思是滾轉,俯仰,偏航。
這句話定義輪子的旋轉軸,這里我選擇了y軸,但是一看是有問題的,應該是相對藍色的軸轉動,這個我們在后面調整。
輪子的代碼
<!--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>
輪子為一個圓柱體cylinder,半徑0.2,高度0.1,注意,在rviz里面默認的圓柱體是垂直地面創建的,為了驗證,我們把dd_robot.urdf文件中的base_link和right_wheel_joint的代碼都刪掉,再在rviz中打開,看效果。
看看零點在什么位置。
和之前說的長方體一樣,零點還是在正中心,你可以理解為重心的地方。這個地方你就理解了,為什么我把電機的joint放在-0.3的位置了,因為這樣看起來輪子剛好是連在地盤上的,0.25+0.05剛好是旋轉之后輪子重心的位置。
對於左邊的電機和輪子,也是同樣的分析道理,下面直接上代碼和效果。
<!--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>
運行roslaunch 命令
hou@houROS:~/catkin_ws $ roslaunch ros_robotic dd_rviz.launch model:=dd_robot.urdf
效果:
這樣的輪子會倒,在前面加上一個球形萬向輪,作為支撐,代碼為:
<!--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. 添加碰撞及慣性參數
添加collision屬性
接下來,我們將
<!--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>
注意,是在每個Link里面添加這個collision屬性,由於本次模型簡單,collison里面的尺寸參數和visual里面是一樣的。
其他的link也是類似,這里就不再詳細闡述,可以參閱最終的代碼。
添加慣性inertial參數
慣性參數直接反映了機器人的重量以及實際運動學方面的特性,舉個例子來說,大慣量的物體,啟動起來就比較慢,這個你可以理解為靈活性的一種表示了。
<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>
運行roslaunch ros_robotic dd_rviz.launch model:=dd_robot.urdf 效果如下
此時,可以通過滑動滑桿來操作輪子轉動,我們來試一下。
尷尬,大型翻車現場,回到上文(飛機模型下面提到的)這個axis的設置有問題,我們看一下,當前兩個輪子的旋轉是
<!--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>
將兩個Joint的
<axis xyz="0.0 0 1.0"/>
再次運行查看效果
OK,就是這個效果,現在可以通過滑桿來讓輪子轉動了。既然輪子可以轉動,那么機器人就可以在rviz里面運動了,
how?
6. 添加運動控制器
ArbotiX控制器可以用來控制差動輪,配合rviz搭建仿真環境,
1. 安裝ArbotiX
在當前工作空間的src下面的文件夾內使用如下命令,將ArbotiX的源碼從github上下載克隆到本地
git clone https://github.com/vanadiumlabs/arbotix_ros.git
下載成功后,回到工作空間根目錄,使用catkin_make編譯
2. 配置ArbotiX控制器
這里只需要創建一個啟動ArbotiX的節點的launch文件即可
在launch文件夾下創建一個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>
同時在ros_robotic包文件夾下,新建config目錄,新建fake_robot_arbotix.yaml配置文件,內容為
controllers: {
base_controller: {type: diff_controller, base_frame_id: base_link, base_width: 0.5, ticks_meter: 400, Kp: 12, Kd: 12, Ki: 0, Ko: 50, accel_limit: 1.0 }
}
運行launch文件
roslaunch ros_robotic dd_robot_with_arbotix.launch model:=dd_robot.urdf
效果如下,這個時候其實看不出什么效果,動起來才能看的見:
7. 使用鍵盤來控制機器人
安裝teleop_twist_key功能包,
在src下面使用如下命令
git clone https://github.com/ros-teleop/teleop_twist_keyboard.git
然后,回到src的上級目錄,執行
catkin_make
然后,source一下當前的工作空間
source devel/setup.bash
此時,運行teleop_twist_keyboard功能包節點
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
此時將兩個窗口並排放置,如圖
按動I鍵,動起來吧!
翻車again!
本來是前進的,結果橫向移動了。why?
這里是方向錯了,我們來解釋。
第一,I鍵給的指令是x方向的速度,而我們機器人地盤上x方向是橫向的,當i給一個x速度的時候,就平移了,現在是綠色的箭頭(y方向)是地盤的正方向,其實,我們給y發速度就行了,看看
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"
看怎么走?
此時命令回車之后,顯示
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
並咩有動,我們后面有空研究咋回事。
這里,我將urdf里面的長寬改變過來.
<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內重新加載
roslaunch ros_robotic dd_robot_with_arbotix.launch model:=dd_robot.urdf
動起來了,非常爽!
8. 使用游戲手柄來控制機器人
1.安裝手柄驅動:
modprobe joydev
2.安裝手柄測試軟件:
sudo apt-get install joystick (joystick校准手柄)
3.測試手柄:
jstest /dev/input/js0
搞清楚對應的是那個按鍵
下載teleop_twist_joy功能包,在工作空間下編譯,打開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>
同時,在config文件夾下面的新建一個手柄配置文件,我這里使用的是北通手柄,這里新建一個beitong.config.yaml,內容為
axis_linear: 1
scale_linear: 1
scale_linear_turbo: 0
axis_angular: 0
scale_angular: 0.4
enable_button: 4
enable_turbo_button: 5
運行
roslaunch teleop_twist_joy teleop.launch
非常爽,這里用左邊的搖桿來控制前進和轉向,和我之前使用的無人機有點不同,這里讓左邊搖桿來控制前進,右邊搖桿來控制轉彎,只需要將配置文件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. 使用手機app來控制
下載ros_control app,如圖:
新建機器人,連接上當前電腦的ip地址,在高級設置里面設置好速度話題為/cmd_vel,如果你用來控制小烏龜的話,就把這個地方改成/turtle1/cmd_vel,進入界面,移動觸干,小車動起來了,爽!
不過有個問題,同時使用遙控器和APP來控制,再將APP關閉之后,用手柄控制起來就顯得有點卡頓了,具體原因再找。使用rosnode kill把APP節點干掉之后,不再卡頓。
rosnode kill /android/robot_controller
killing /android/robot_controller
killed
總 結
本文一步步搭建了自己的小車,並通過鍵盤、手柄、App來實現了控制,對urdf模型的建立、rviz的基礎認識有了一個更進一步的體會。但是手寫urdf真的是太費勁了,后面我將用solidworks和xacro來實現,同時也會將rviz里面的機器人搬到gazebo里面來跑。
很爽,奧里給!