Create a simulation of a wheels’ mobile robot with ROS
For this post, I based my work on the tutorial of contructsim.
This tutorial has three parts:
1. Install and create ROS package.
2. Creation of XACRO file of the robot.
3. Creation of yarm files for configuration of controllers of the robot.
The URDF files are very useful because you can probe the different algorithms for your robotic project without the necessity of having a physical robot. The URDF files use an XML language with your own tags. The difference between URDF and XACRO files is that in the XACRO files you can create and reutilize the components of your own tags and the advantage is that code is smaller.
Install and create ROS package
Open a new terminal and install ros-<ros version>-gazebo-ros-control and ros-<ros version>-gazebo-ros-pkgs with that line:
sudo apt-get install ros-<ros version>-gazebo-ros-pkgs ros-<ros version>-gazebo-ros-control
With this packages installed, put the following line for creating the ros package when you has put files of this tutorial:
catkin_create_pkg ros_2wmr
The name of this tutorial package is called ros_2wmr. Create the following folders:
In the config folder, we save the .yarm files, in launch the .launch files, src all c++ or python files, and urdf folder the .urdf or .xacro files.
Creation of XACRO file
First, create the dif.xacro file into the urdf folder, and you have to put the XML tag and the robot tag in this file, inside the robot tag when put the links and joints that the robot has. The document has to see as this example:
<?xml version="1.0" ?>
<robot name="Name of robot" xmlns:xacro="https://www.ros.org/wiki/xacro" > <!-- Links and joints of robot --></robot>
Now, we create a parent link, that represents the chassis or body of the robot:
<link name="link_chassis">
<pose>0 0 0.1 0 0 0</pose>
<inertial>
<mass value="5"/>
<origin rpy="0 0 0" xyz="0 0 0.1"/>
<inertia ixx="0.0395416666667" ixy="0" ixz="0" iyy="0.106208333333" iyz="0" izz="0.106208333333"/>
</inertial>
<collision name="collision_chassis">
<geometry>
<box size="0.5 0.3 0.07"/>
</geometry>
</collision>
<visual>
<origin rpy="0 0 0" xyz="0 0 0"/>
<geometry>
<box size="0.5 0.3 0.07"/>
</geometry>
</visual> <!-- caster front -->
<collision name="caster_front_collision">
<origin rpy=" 0 0 0" xyz="0.35 0 -0.05"/>
<geometry>
<sphere radius="0.05"/>
</geometry>
<surface>
<friction>
<ode>
<mu>0</mu>
<mu2>0</mu2>
<slip1>1.0</slip1>
<slip2>1.0</slip2>
</ode>
</friction>
</surface>
</collision>
<visual name="caster_front_visual">
<origin rpy=" 0 0 0" xyz="0.2 0 -0.05"/>
<geometry>
<sphere radius="0.05"/>
</geometry>
</visual>
</link>
This link has an inertial tag, it is, you can describe the physical parameters of the body’s robot, a collision tag, that describes the properties of the collision, and a visual tag that this the component that you can see in rviz for example. Also, put a caster front that has its own collision and visual tag. If you want more about the tags of URDF and XACRO push here.
Now, I create the children links of the parent, this that an example of the right wheel of the robot:
<link name="link_right_wheel">
<inertial>
<mass value="0.2"/>
<origin rpy="0 1.5707 1.5707" xyz="0 0 0"/>
<inertia ixx="0.00052666666" ixy="0" ixz="0" iyy="0.00052666666" iyz="0" izz="0.001"/>
</inertial>
<collision name="link_right_wheel_collision">
<origin rpy="0 1.5707 1.5707" xyz="0 0 0" />
<geometry>
<cylinder length="0.04" radius="0.1"/>
</geometry>
</collision>
<visual name="link_right_wheel_visual">
<origin rpy="0 1.5707 0" xyz="0 0.02 0"/>
<geometry>
<cylinder length="0.04" radius="0.1"/>
</geometry>
</visual>
</link>
For the left wheel, you can copy the link of the right link and replace the origin data in the visual tag and the right word to left. With the two children's links, we can start with joints. In this example, the robot has two joints that move the wheels. If you want to see about types of joints in URDF files you can push here.
The following code is the joint of the right wheel:
<joint name="joint_right_wheel" type="continuous">
<origin rpy="0 0 0" xyz="-0.05 0.15 0"/>
<child link="link_left_wheel" />
<parent link="link_chassis"/>
<axis rpy="0 0 0" xyz="0 1 0"/>
<limit effort="10000" velocity="1000"/>
<joint_properties damping="1.0" friction="1.0" />
</joint>
As the children links for the left joint you only have to change the origin tagin the position and the right word to left. Next, for the XACRO file of this robot we can put the transmission, it is used to describe the relationship between an actuator and a joint. For more information push here.
The code represents the transmission of the right wheel:
<transmission name="right_wheel_transmission">
<type>transmission_interface/SimpleTransmission</type>
<joint name="joint_right_wheel">
<hardwareInterface>
hardware_interface/VelocityJointInterface
</hardwareInterface>
</joint>
<actuator name="right_wheel_actuator">
<mechanicalReduction>1</mechanicalReduction>
<hardwareInterface>
VelocityJointInterface
</hardwareInterface>
</actuator>
</transmission>
For the left wheel, copy all and only change all that say right in left.
Finally, put the gazebo_ros drive for a differential robot in our robot, only put these lines:
<gazebo>
<plugin name=”gazebo_ros_control” filename= “libgazebo_ros_control.so”>
<robotNamespace>/</robotNamespace> </plugin>
</gazebo>
Creation of yarm files for configuration of controllers of the robot
For this example I configure two controllers, the first is for controlling the joints, only in the config folder create a new file named joint_states.yarm, and only copy the following code:
joint_state_controller:
type: “joint_state_controller/JointStateController”
publish_rate: 50
And the second is for controlling the velocity angular and linear of my robot, create a new file named diferential_controller.yarm and paste this code:
mobile_base_controller:
type : “diff_drive_controller/DiffDriveController”
left_wheel : ‘joint_left_wheel’
right_wheel : ‘joint_right_wheel’
publish_rate: 50.0 # default: 50
pose_covariance_diagonal : [0.001, .001, 1000000., 1000000., 1000000., 1000.]
twist_covariance_diagonal: [0.001, .001, 1000000., 1000000., 1000000., 1000.] # Wheel separation and diameter. These are both optional.
# diff_drive_controller will attempt to read either one or both from the
# URDF if not specified as a parameter
wheel_separation : 0.4
wheel_radius : 0.2 # Wheel separation and radius multipliers
wheel_separation_multiplier: 1.0 # default: 1.0
wheel_radius_multiplier : 1.0 # default: 1.0 # Velocity commands timeout [s], default 0.5
cmd_vel_timeout: 0.25 # Base frame_id
base_frame_id: link_chassis #default: base_link # Velocity and acceleration limits
# Whenever a min_* is unspecified, default to -max_*
linear:
x:
has_velocity_limits : true
max_velocity : 1.0 # m/s
min_velocity : -0.5 # m/s
has_acceleration_limits: true
max_acceleration : 0.8 # m/s²
min_acceleration : -0.4 # m/s²
has_jerk_limits : true
max_jerk : 5.0 # m/s³
angular:
z:
has_velocity_limits : true
max_velocity : 1.7 # rad/s
min_velocity : -1.7 # rad/s
has_acceleration_limits: true
max_acceleration : 1.5 # rad/s²
has_jerk_limits : true
max_jerk : 2.5 # rad/s³
In this file, you configure the parameters for the differential drive of the gazebo of our robot. For testing the configurations in the launch folder create a gazebo.launch with this code:
<launch>
<arg name="paused" default="false"/><arg name="use_sim_time" default="false"/>
<arg name="gui" default="false"/><arg name="headless" default="false"/>
<arg name="debug" default="false"/><arg name="model" default="$(find diferencial)/urdf/dif.xacro"/> <!-- Resume the logic in empty_world.launch -->
<include file="$(find gazebo_ros)/launch/empty_world.launch"><arg name="debug" value="$(arg debug)" />
<arg name="gui" value="$(arg gui)" />
<arg name="paused" value="$(arg paused)"/>
<arg name="use_sim_time" value="$(arg use_sim_time)"/>
<arg name="headless" value="$(arg headless)"/>
</include> <!-- Load the URDF into the ROS Parameter Server -->
<param name="robot_description" command="cat '$(arg model)'" />
<!-- Run a python script to the send a service call to gazebo_ros to spawn a URDF robot -->
<node name="dif" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen" args="-z 1.0 -urdf -model Differential_Drive -param robot_description"/> </launch>
This launch file code configures all gazebo pkg for the example. And finally, create a new file called run_2wmr.launch and put the following code:
<launch>
<arg name=”model” default=”$(find diferencial)/urdf/dif.xacro”/> <!--Launch gazebo-->
<include file=”$(find diferencial)/launch/gazebo.launch”>
<arg name=”model” value=”$(arg model)”/>
</include> <!-- Load joint controller configuration from YAML file to parameter server -->
<rosparam file=”$(find diferencial)/config/state_joints.yaml” command=”load”/>
<rosparam file=”$(find diferencial)/config/diferential_controller.yaml” command=”load”/> <!--load the controllers-->
<node name=”rdif_control_spawner” pkg=”controller_manager” type=”spawner” respawn=”true” output=”screen” args=”joint_state_controller mobile_base_controller”/> <!--convert joint states to TF transforms for rviz-->
<node name=”robot_state_publisher” pkg=”robot_state_publisher” type=”robot_state_publisher” respawn=”false” output=”screen”/> <!--Open rviz-->
<node name=”rviz” pkg=”rviz” type=”rviz”/>
</launch>
Open a terminal and put this line:
roslaunch ros_2wmr run_2wmr.launch
If all is OK, you have to see the robot in rviz.
For testing you can install a teleoperation ros pkg, only put the next line:
pip install teleop_twist_keyboard
And run the teleoperation node with this line:
rosrun teleop_twist_keyboard teleop_twist_keyboard.py cmd_vel:=/mobile_base_controller/cmd_vel
The robot starts to move when you press the letters: (I),(J),(K),(L),(;) of the keyboard.
If you want to see the robot with different colors and textures, I invite you to see my GitHub that has a robot with these characteristics in my XACRO file in the URDF folder.
Thanks for your time reading this post 😃 !!
If you have questions or comments I am happy to answer. For contact with me, you can follow me on my Linkedin.
Can we help you?
We are ready to listen to you. If you need some help for creating the next big thing, you can contact our team on our website or at info@jrtec.io