Hey ROS Developers!
In this 5th post of the series, we will expand the controllers to all the joints of our manipulator! Before finishing the post, you will be able to control and calibrate the controllers using graphical tools such as RQT Publisher and RQT Reconfigure. Let’s start!
Step 0 – Introduction
We need to do the same steps we have done in the previous post, but for many joints. Instead of repeating ourselves, let’s take advantage on xacro resources. We are going to use the MACRO we created before to configure the controllers!
Step 1 – Configuring controllers on MACRO
We have to change just a single MACRO, the one called m_joint , in order to apply controllers to all our robots. It is the necessary element, transmission , we have created manually to the first two joints in the previous post. The MACRO will look like below:
<xacro:macro name="m_joint" params="name type axis_xyz origin_rpy origin_xyz parent child limit_e limit_l limit_u limit_v">
<joint name="${name}" type="${type}">
<axis xyz="${axis_xyz}" />
<limit effort="${limit_e}" lower="${limit_l}" upper="${limit_u}" velocity="${limit_v}" />
<origin rpy="${origin_rpy}" xyz="${origin_xyz}" />
<parent link="${parent}" />
<child link="${child}" />
</joint>
<transmission name="trans_${name}">
<type>transmission_interface/SimpleTransmission</type>
<joint name="${name}">
<hardwareInterface>hardware_interface/EffortJointInterface</hardwareInterface>
</joint>
<actuator name="motor_${name}">
<hardwareInterface>hardware_interface/EffortJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
</xacro:macro>
Then.. we replace the transmissions by the macro and some new parameters. The m_joint tags of our mrm.xacro file will look like:
!Be careful, we are only showing the m_joint tags!
<m_joint name="${link_00_name}__${link_01_name}" type="revolute"
axis_xyz="0 0 1"
origin_rpy="0 0 0" origin_xyz="0 0 0.5"
parent="base_link" child="link_01"
limit_e="1000" limit_l="-3.14" limit_u="3.14" limit_v="0.5" />
<m_joint name="${link_01_name}__${link_02_name}" type="revolute"
axis_xyz="0 1 0"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
parent="link_01" child="link_02"
limit_e="1000" limit_l="0" limit_u="0.5" limit_v="0.5" />
<m_joint name="${link_02_name}__${link_03_name}" type="revolute"
axis_xyz="0 1 0"
origin_rpy="0 0 0" origin_xyz="0 0 0.8"
parent="link_02" child="link_03"
limit_e="1000" limit_l="0" limit_u="0.75" limit_v="0.5" />
<m_joint name="${link_03_name}__${link_04_name}" type="revolute"
axis_xyz="0 1 0"
origin_rpy="0 0 0" origin_xyz="0 0 0.8"
parent="link_03" child="link_04"
limit_e="1000" limit_l="0" limit_u="0.75" limit_v="0.5" />
<m_joint name="${link_04_name}__${link_05_name}" type="revolute"
axis_xyz="0 0 1"
origin_rpy="0 0 0" origin_xyz="0 0 0.8"
parent="link_04" child="link_05"
limit_e="1000" limit_l="-3.14" limit_u="3.14" limit_v="0.5" />
Step 2 – Configuring YAML and Launch files
Almost there.. we need to configure the new controllers. At this point, we are basically repeating the same processes for the first 2 joints. (No MACROs here)
# Publish all joint states -----------------------------------
joint_state_controller:
type: joint_state_controller/JointStateController
publish_rate: 50
# Position Controllers ---------------------------------------
joint1_position_controller:
type: effort_controllers/JointPositionController
joint: base_link__link_01
pid: {p: 2000.0, i: 100, d: 500.0}
joint2_position_controller:
type: effort_controllers/JointPositionController
joint: link_01__link_02
pid: {p: 50000.0, i: 100, d: 2000.0}
joint3_position_controller:
type: effort_controllers/JointPositionController
joint: link_02__link_03
pid: {p: 20000.0, i: 50, d: 1000.0}
joint4_position_controller:
type: effort_controllers/JointPositionController
joint: link_03__link_04
pid: {p: 2000.0, i: 50, d: 200.0}
joint5_position_controller:
type: effort_controllers/JointPositionController
joint: link_04__link_05
pid: {p: 700.0, i: 50, d: 70.0}
And the launch file:
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<group ns="/mrm">
<!-- Robot model -->
<param name="robot_description" command="$(find xacro)/xacro --inorder '$(find mrm_description)/urdf/mrm.xacro'" />
<arg name="x" default="0"/>
<arg name="y" default="0"/>
<arg name="z" default="0.5"/>
<!-- Spawn the robot model -->
<node name="mybot_spawn" pkg="gazebo_ros" type="spawn_model" output="screen"
args="-urdf -param robot_description -model mrm -x $(arg x) -y $(arg y) -z $(arg z)" />
<!-- Load controllers -->
<rosparam command="load" file="$(find mrm_description)/config/joints.yaml" />
<!-- Controllers -->
<node name="controller_spawner" pkg="controller_manager" type="spawner"
respawn="false" output="screen" ns="/mrm"
args="--namespace=/mrm
joint_state_controller
joint1_position_controller
joint2_position_controller
joint3_position_controller
joint4_position_controller
joint5_position_controller
--timeout 60">
</node>
<!-- rqt -->
<node name="rqt_reconfigure" pkg="rqt_reconfigure" type="rqt_reconfigure" />
<node name="rqt_publisher" pkg="rqt_publisher" type="rqt_publisher" />
</group>
</launch>
Great! Let’s launch it!
Step 3 – Launch!
Run an empty simulation, like we did before, and spawn the robot using a terminal:
roslaunch mrm_description spawn.launch
You must have the full robot just performing “freeze!”.
Open the Graphical Tools . Let’s check what we have there.
There you can check RQT Publisher. Add some topics and change the values, in order to see the robot moving!
The other window is the RQT Reconfigure, where you can change/tune the PID parameters of the controller!
Step 4 – Conclusion
We have finished the controllers for our robot. We didn’t include (yet) a tuning process in order to have a good performance on the movement of the robot.
Remember, if you lost any of the steps, you can always get a copy of the result: http://www.rosject.io/l/c89d265/
See you in the next posts!
Related courses
URDF for Robot Modeling
ROS Manipulation
ROS for Industrial Robots
URDF/Transmission + Gazebo Controllers
Hey ROS developers! In this post, we will make our robot able to be spawned into Gazebo simulator. Based on the YouTube video series , we’ll show in this format the steps to achieve the final result of the series!
In this post number #4, I’m gonna create the Transmissions and controllers to some of our joints using the same XACROs files we have been working with. Up to the end of the post, we’ll have part of our model controllers by gazebo controllers!
Step 1 – Simplifying the robot
It turns out we have a very complex robot, with 6 links and 5 joints. I want to make it simpler in order to show how to use gazebo controller plugin.
Let’s start opening the file mrm.xacro and comment leave only the first links of the robot (the rest, we will comment). It will look like below:
<?xml version="1.0" ?>
<robot name="mrm" xmlns:xacro="http://www.ros.org/wiki/xacro">
<!-- BGN - Include -->
<xacro:include filename="$(find mrm_description)/urdf/links_joints.xacro" />
<xacro:include filename="$(find mrm_description)/urdf/robot_parameters.xacro" />
<!-- END - Include -->
<!-- BGN - Robot description -->
<m_link_box name="${link_00_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0"
mass="1024"
ixx="170.667" ixy="0" ixz="0"
iyy="170.667" iyz="0"
izz="170.667"
size="1 1 1" />
<m_joint name="${link_00_name}__${link_01_name}" type="revolute"
axis_xyz="0 0 1"
origin_rpy="0 0 0" origin_xyz="0 0 0.5"
parent="${link_00_name}" child="${link_01_name}" />
<m_link_cylinder name="${link_01_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.2"
mass="157.633"
ixx="13.235" ixy="0" ixz="0"
iyy="13.235" iyz="0"
izz="9.655"
length="0.4" radius="0.35" />
<m_joint name="${link_01_name}__${link_02_name}" type="revolute"
axis_xyz="0 1 0"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
parent="${link_01_name}" child="${link_02_name}" />
<m_link_cylinder name="${link_02_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
mass="57.906"
ixx="12.679" ixy="0" ixz="0"
iyy="12.679" iyz="0"
izz="0.651"
radius="0.15" length="0.8" />
<!--
<m_joint name="${link_02_name}__${link_03_name}" type="revolute"
axis_xyz="0 1 0"
origin_rpy="0 0 0" origin_xyz="0 0 0.8"
parent="${link_02_name}" child="${link_03_name}" />
<m_link_cylinder name="${link_03_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
mass="57.906"
ixx="12.679" ixy="0" ixz="0"
iyy="12.679" iyz="0"
izz="0.651"
radius="0.15" length="0.8" />
<m_joint name="${link_03_name}__${link_04_name}" type="revolute"
axis_xyz="0 1 0"
origin_rpy="0 0 0" origin_xyz="0 0 0.8"
parent="${link_03_name}" child="${link_04_name}" />
<m_link_cylinder name="${link_04_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
mass="57.906"
ixx="12.679" ixy="0" ixz="0"
iyy="12.679" iyz="0"
izz="0.651"
radius="0.15" length="0.8" />
<m_joint name="${link_04_name}__${link_05_name}" type="revolute"
axis_xyz="0 0 1"
origin_rpy="0 0 0" origin_xyz="0 0 0.8"
parent="${link_04_name}" child="${link_05_name}" />
<m_link_cylinder name="${link_05_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.125"
mass="18.056"
ixx="0.479" ixy="0" ixz="0"
iyy="0.479" iyz="0"
izz="0.204"
radius="0.15" length="0.25" />
-->
<!-- END - Robot description -->
</robot>
Start an empty world simulation and launch the robot from a web shell:
roslaunch mrm_description spawn.launch
Great! These are the parts we are going to control!
Step 2 – Adding gazebo controller dependencies
We need to modify two of our package files, in order to include the dependencies. They are:
CMakeLists.txt
In the command find_package , let’s add some new values:
find_package(catkin REQUIRED COMPONENTS
urdf
controller_manager
joint_state_controller
robot_state_publisher
)
And in the package.xml file, make sure you have the following instructions:
<build_depend>urdf</build_depend>
<build_depend>controller_manager</build_depend>
<build_depend>joint_state_controller</build_depend>
<build_depend>robot_state_publisher</build_depend>
<build_export_depend>urdf</build_export_depend>
<build_export_depend>controller_manager</build_export_depend>
<build_export_depend>joint_state_controller</build_export_depend>
<build_export_depend>robot_state_publisher</build_export_depend>
<exec_depend>urdf</exec_depend>
<exec_depend>controller_manager</exec_depend>
<exec_depend>joint_state_controller</exec_depend>
<exec_depend>robot_state_publisher</exec_depend>
Step 3 – Adding transmissions to the robot model
Next thing, we need some transmissions elements in our robot model.
Let’s get back to the URDF file: mrm.xacro
<m_link_box name="${link_00_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0"
mass="1024"
ixx="170.667" ixy="0" ixz="0"
iyy="170.667" iyz="0"
izz="170.667"
size="1 1 1" />
<m_joint name="${link_00_name}__${link_01_name}" type="revolute"
axis_xyz="0 0 1"
origin_rpy="0 0 0" origin_xyz="0 0 0.5"
parent="${link_00_name}" child="${link_01_name}" />
<transmission name="trans_${link_00_name}__${link_01_name}">
<type>transmission_interface/SimpleTransmission</type>
<joint name="${link_00_name}__${link_01_name}">
<hardwareInterface>hardware_interface/EffortJointInterface</hardwareInterface>
</joint>
<actuator name="motor_${link_00_name}__${link_01_name}">
<hardwareInterface>hardware_interface/EffortJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
<m_link_cylinder name="${link_01_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.2"
mass="157.633"
ixx="13.235" ixy="0" ixz="0"
iyy="13.235" iyz="0"
izz="9.655"
length="0.4" radius="0.35" />
<m_joint name="${link_01_name}__${link_02_name}" type="revolute"
axis_xyz="0 1 0"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
parent="${link_01_name}" child="${link_02_name}" />
<transmission name="trans_${link_01_name}__${link_02_name}">
<type>transmission_interface/SimpleTransmission</type>
<joint name="${link_01_name}__${link_02_name}">
<hardwareInterface>hardware_interface/EffortJointInterface</hardwareInterface>
</joint>
<actuator name="motor_${link_01_name}__${link_02_name}">
<hardwareInterface>hardware_interface/EffortJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
<m_link_cylinder name="${link_02_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
mass="57.906"
ixx="12.679" ixy="0" ixz="0"
iyy="12.679" iyz="0"
izz="0.651"
radius="0.15" length="0.8" />
You can notice we have added a new element with the transmission tag.
What are we describing there?
First, we have a transmission for each joint . Then we define the type of the transmission, which in this case is just a SimpleTransmission.
Then, the joint we are referencing with the transmission.
Further, the actuator type , which is an Effort Joint Interface , in this case. And the mechanical reduction .
We do this for both joints we have left (in this simplified version of the robot).
Step 4 – Setup gazebo controllers on URDF model
Still on the same file, let’s add to the end of the description the tags related to gazebo controller plugin .
Just simple as below, append to the end of the file, just before the </robot> :
<gazebo>
<plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
</plugin>
</gazebo>
Step 5 – Describe controller YAML file
This is something necessary for the gazebo controller, we must define some control variables (PID) to apply to our transmissions.
In order to do that, let’s create a new file: ~/simulation_ws/src/mrm_description/config/joints.yaml
It goes like that:
# Publish all joint states -----------------------------------
joint_state_controller:
type: joint_state_controller/JointStateController
publish_rate: 50
# Position Controllers ---------------------------------------
joint1_position_controller:
type: effort_controllers/JointPositionController
joint: base_link__link_01
pid: {p: 2000.0, i: 100, d: 500.0}
joint2_position_controller:
type: effort_controllers/JointPositionController
joint: link_01__link_02
pid: {p: 50000.0, i: 100, d: 2000.0}
We are defining the joint_state_publisher as reference.
Then tuning each one of the transmissions we have defined in our model. We need again the name , type , joint name and the PID values
Step 6 – Launch Gazebo Controllers
Now, let’s modify our launch file .
It goes like:
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<group ns="/mrm">
<!-- Robot model -->
<param name="robot_description" command="$(find xacro)/xacro --inorder '$(find mrm_description)/urdf/mrm.xacro'" />
<arg name="x" default="0" />
<arg name="y" default="0" />
<arg name="z" default="0.5" />
<!-- Spawn the robot model -->
<node name="mybot_spawn" pkg="gazebo_ros" type="spawn_model" output="screen"
args="-urdf -param robot_description -model mrm -x $(arg x) -y $(arg y) -z $(arg z)" />
<!-- Load controllers -->
<rosparam command="load" file="$(find mrm_description)/config/joints.yaml" />
<node name="controller_spawner" pkg="controller_manager" type="spawner"
respawn="false" output="screen" ns="/mrm"
args="--namespace=/mrm
joint_state_controller
joint1_position_controller
joint2_position_controller
--timeout 60">
</node>
</group>
</launch>
First main modification is the group tag, where we define a namespace (mrm) for our robot processes. Everything inside this tag inherits the namespace. It’s necessary for the controller plugin.
Then, in the secion Load controllers we have a new parameter, that loads the config.yml file we have just created.
Finally, a new node to run the controller process.
Step 7 – Testing!
Great! Now we have already configured the controllers, you can spawn the robot again! Same commands as before, but this time you will notice the last link won’t fall down! This is very important to achieve since the controllers are already actuating.
Check the shell, you can see the controllers being loaded in the logs!
process[mrm/mybot_spawn-1]: started with pid [4817]
process[mrm/controller_spawner-2]: started with pid [4822]
[INFO] [1567187158.002693, 0.000000]: Controller Spawner: Waiting for service /mrm/controller_manager/load_controller
the rosdep view is empty: call 'sudo rosdep init' and 'rosdep update'
SpawnModel script started
[INFO] [1567187165.292282, 0.000000]: Loading model XML from ros parameter
[INFO] [1567187165.303925, 0.000000]: Waiting for service /gazebo/spawn_urdf_model
[INFO] [1567187165.312998, 0.000000]: Calling service /gazebo/spawn_urdf_model
[INFO] [1567187165.504207, 904.010000]: Spawn status: SpawnModel: Successfullyspawned entity
[mrm/mybot_spawn-1] process has finished cleanly
log file: /home/user/.ros/log/cfa21f58-cb4b-11e9-9ca9-0a2504d14030/mrm-mybot_spawn-1*.log
[INFO] [1567187166.829017, 904.050000]: Controller Spawner: Waiting for service /mrm/controller_manager/switch_controller
[INFO] [1567187166.831181, 904.050000]: Controller Spawner: Waiting for service /mrm/controller_manager/unload_controller
[INFO] [1567187166.848968, 904.070000]: Loading controller: joint_state_controller
[INFO] [1567187167.000380, 904.220000]: Loading controller: joint1_position_controller
[INFO] [1567187167.268639, 904.500000]: Loading controller: joint2_position_controller
[INFO] [1567187167.345849, 904.570000]: Controller Spawner: Loaded controllers: joint_state_controller, joint1_position_controller, joint2_position_controller
[INFO] [1567187167.355672, 904.590000]: Started controllers: joint_state_controller, joint1_position_controller, joint2_position_controller
We have also new ROS topics related to the controllers:
user:~$ rostopic list
/clock
/gazebo/link_states
/gazebo/model_states
/gazebo/parameter_descriptions
/gazebo/parameter_updates
/gazebo/set_link_state
/gazebo/set_model_state
/mrm/joint1_position_controller/command
/mrm/joint1_position_controller/pid/parameter_descriptions
/mrm/joint1_position_controller/pid/parameter_updates
/mrm/joint1_position_controller/state
/mrm/joint2_position_controller/command
/mrm/joint2_position_controller/pid/parameter_descriptions
/mrm/joint2_position_controller/pid/parameter_updates
/mrm/joint2_position_controller/state
/mrm/joint_states
/rosout
/rosout_agg
As a final test, let’s send a reference to the second joint:
rostopic pub -1 /mrm/joint2_position_controller/command std_msgs/Float64 "data: 0.7"
You must have the robot like:
In order to put it back to the original position, execute the command below:
rostopic pub -1 /mrm/joint2_position_controller/command std_msgs/Float64 "data: 0.0"
Related courses
URDF for Robot Modeling
ROS Manipulation
ROS for Industrial Robots
Step 8 – Conclusion
Great! If you missed any of the steps or something just didn’t work, you can check the original project just clicking on the link: http://www.rosject.io/l/c1ed2ee/
See you in the next post!
In this video we are going to set a .STL mesh file to one of the links of our robot using its URDF code. From the URDF model used in the previous videos, we are going to define a new XML MACRO to use mesh files for a given link. Up to the end of the video, we will be able to see the mesh in RViz and Gazebo simulator.
Repositories:
Robot description: https://bitbucket.org/theconstructcore/my-robotic-manipulator/src
URDF Course: https://goo.gl/PNEgCX
Robot Ignite Academy: https://goo.gl/1bg1UV
ROS Development Studio: https://goo.gl/wL5Mxz
Step 1. Meshes
Create e folder called meshes under the mrm_description directory and drag the .stl file you want into it.
Step 2. Modify the .xarco file
For easier test and debug, let’s comment out the other links in the mrm.xarco file.
<!--
<m_joint name="${link_01_name}__${link_02_name}" type="revolute"
axis_xyz="0 1 0"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
parent="link_01" child="link_02"
limit_e="1000" limit_l="0" limit_u="0.5" limit_v="0.5" />
<m_link_cylinder name="${link_02_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
mass="57.906"
ixx="12.679" ixy="0" ixz="0"
iyy="12.679" iyz="0"
izz="0.651"
radius="0.15" length="0.8" />
<m_joint name="${link_02_name}__${link_03_name}" type="revolute"
axis_xyz="0 1 0"
origin_rpy="0 0 0" origin_xyz="0 0 0.8"
parent="link_02" child="link_03"
limit_e="1000" limit_l="0" limit_u="0.75" limit_v="0.5" />
<m_link_cylinder name="${link_03_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
mass="57.906"
ixx="12.679" ixy="0" ixz="0"
iyy="12.679" iyz="0"
izz="0.651"
radius="0.15" length="0.8" />
<m_joint name="${link_03_name}__${link_04_name}" type="revolute"
axis_xyz="0 1 0"
origin_rpy="0 0 0" origin_xyz="0 0 0.8"
parent="link_03" child="link_04"
limit_e="1000" limit_l="0" limit_u="0.75" limit_v="0.5" />
<m_link_cylinder name="${link_04_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
mass="57.906"
ixx="12.679" ixy="0" ixz="0"
iyy="12.679" iyz="0"
izz="0.651"
radius="0.15" length="0.8" />
<m_joint name="${link_04_name}__${link_05_name}" type="revolute"
axis_xyz="0 0 1"
origin_rpy="0 0 0" origin_xyz="0 0 0.8"
parent="link_04" child="link_05"
limit_e="1000" limit_l="-3.14" limit_u="3.14" limit_v="0.5" />
<m_link_cylinder name="${link_05_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.125"
mass="18.056"
ixx="0.479" ixy="0" ixz="0"
iyy="0.479" iyz="0"
izz="0.204"
radius="0.15" length="0.25" />
-->
Then we define a new mesh called m_link_mesh in the links_joints.xarco with the following content
<xacro:macro name="m_link_mesh" params="name origin_xyz origin_rpy meshfile meshscale mass ixx ixy ixz iyy iyz izz">
<link name="${name}">
<inertial>
<mass value="${mass}" />
<origin rpy="${origin_rpy}" xyz="${origin_xyz}" />
<inertia ixx="${ixx}" ixy="${ixy}" ixz="${ixz}" iyy="${iyy}" iyz="${iyz}" izz="${izz}" />
</inertial>
<collision>
<origin rpy="${origin_rpy}" xyz="${origin_xyz}" />
<geometry>
<mesh filename="${meshfile}" scale="${meshscale}"/>
</geometry>
</collision>
<visual>
<origin rpy="${origin_rpy}" xyz="${origin_xyz}" />
<geometry>
<mesh filename="${meshfile}" scale="${meshscale}"/>
</geometry>
<material name="light_black"/>
</visual>
</link>
</xacro:macro>
Please notice that in the params, we added two new property called meshfile and meshscale.
Since we are now using the mesh instead of a cylinder, let’s go back to the mrm.xarco and change it.
<m_link_mesh name="${link_01_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.2"
mass="157.633"
ixx="13.235" ixy="0" ixz="0"
iyy="13.235" iyz="0"
izz="9.655"
meshfile="package://mrm_description/meshes/Link1-v2.stl"
meshscale="0.001 0.001 0.001" />
Please make sure the meshscale is correct for your .stl file. In the simulation, the scale is in m. We change the meshscale to 0.001 because the stl file is done on the scale of mm.
Step 2. Modify the launch file
Since we only use one joint, we’ll only need the controller for one joint. Let’s change this part in the /launch/spawn.launch
<!-- Controllers -->
<node name="controller_spawner" pkg="controller_manager" type="spawner"
respawn="false" output="screen" ns="/mrm"
args="--namespace=/mrm
joint_state_controller
joint1_position_controller
--timeout 60">
</node>
Step 3. Launch the description in RViz and Gazebo
You can launch the RViz with the following command. After launching, please go to tools->graphical tool. You will see the RViz is open.
roslaunch mrm_description rviz.launch
After launching, we noticed that the link is not in the correct position, let’s go back to the mrm.xarco file and give it a proper offset.
<m_link_mesh name="${link_01_name}"
origin_rpy="0 0 0" origin_xyz="0 0 -0.1"
mass="157.633"
ixx="13.235" ixy="0" ixz="0"
iyy="13.235" iyz="0"
izz="9.655"
meshfile="package://mrm_description/meshes/Link1-v2.stl"
meshscale="0.001 0.001 0.001" />
You can also spawn the robot in gazebo, please go to Simulations->Empty to open a simulation the run the following command to spawn the robot
roslaunch mrm_description spawn.launch
Edit by: Tony Huang
This is a series of posts. If you didn’t follow up, you can find the previous post here. In this 5th video of the robotic manipulator series, we will expand the ROS controllers to all joints of our robot using XACRO. At the end of the video we’ll have a full controlled robot through ROS topics. We are also going to use RQT Publisher and RQT Reconfigure to do some experiments with the robot.
Step 0. Create a project in ROS Development Studio(ROSDS)
ROSDS helps you follow our tutorial in a fast pace without dealing without setting up an environment locally. If you haven’t had an account yet, you can create a free account here . We’ll start the project for the previous video – manipulator_video_no4.
Step 1. Configure controller
In order to use controllers for our robot. The first step is we need to add transmission definitions for each joint in the links_joints.xarco and add limitation for each joint in the mrm.xarco file. The most important thing is to add the gazebo plugin in the mrm.xarco file.
...
<xacro:macro name="m_joint" params="name type axis_xyz origin_rpy origin_xyz parent child limit_e limit_l limit_u limit_v">
<joint name="${name}" type="${type}">
<axis xyz="${axis_xyz}" />
<limit effort="${limit_e}" lower="${limit_l}" upper="${limit_u}" velocity="${limit_v}" />
<origin rpy="${origin_rpy}" xyz="${origin_xyz}" />
<parent link="${parent}" />
<child link="${child}" />
</joint>
<transmission name="trans_${name}">
<type>transmission_interface/SimpleTransmission</type>
<joint name="${name}">
<hardwareInterface>hardware_interface/EffortJointInterface</hardwareInterface>
</joint>
<actuator name="motor_${name}">
<hardwareInterface>hardware_interface/EffortJointInterface</hardwareInterface>
<mechanicalReduction>1</mechanicalReduction>
</actuator>
</transmission>
</xacro:macro>
...
...
<m_joint name="${link_01_name}__${link_02_name}" type="revolute"
axis_xyz="0 1 0"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
parent="link_01" child="link_02"
limit_e="1000" limit_l="0" limit_u="0.5" limit_v="0.5" />
<m_link_cylinder name="${link_02_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
mass="57.906"
ixx="12.679" ixy="0" ixz="0"
iyy="12.679" iyz="0"
izz="0.651"
radius="0.15" length="0.8" />
<m_joint name="${link_02_name}__${link_03_name}" type="revolute"
axis_xyz="0 1 0"
origin_rpy="0 0 0" origin_xyz="0 0 0.8"
parent="link_02" child="link_03"
limit_e="1000" limit_l="0" limit_u="0.75" limit_v="0.5" />
<m_link_cylinder name="${link_03_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
mass="57.906"
ixx="12.679" ixy="0" ixz="0"
iyy="12.679" iyz="0"
izz="0.651"
radius="0.15" length="0.8" />
<m_joint name="${link_03_name}__${link_04_name}" type="revolute"
axis_xyz="0 1 0"
origin_rpy="0 0 0" origin_xyz="0 0 0.8"
parent="link_03" child="link_04"
limit_e="1000" limit_l="0" limit_u="0.75" limit_v="0.5" />
<m_link_cylinder name="${link_04_name}"
origin_rpy="0 0 0" origin_xyz="0 0 0.4"
mass="57.906"
ixx="12.679" ixy="0" ixz="0"
iyy="12.679" iyz="0"
izz="0.651"
radius="0.15" length="0.8" />
<m_joint name="${link_04_name}__${link_05_name}" type="revolute"
axis_xyz="0 0 1"
origin_rpy="0 0 0" origin_xyz="0 0 0.8"
parent="link_04" child="link_05"
limit_e="1000" limit_l="-3.14" limit_u="3.14" limit_v="0.5" />
<gazebo>
<plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
</plugin>
</gazebo>
...
Then we create a file called joints.yaml file in the config folder which defines the parameters for controllers.
# Publish all joint states -----------------------------------
joint_state_controller:
type: joint_state_controller/JointStateController
publish_rate: 50
# Position Controllers ---------------------------------------
joint1_position_controller:
type: effort_controllers/JointPositionController
joint: base_link__link_01
pid: {p: 2000.0, i: 100, d: 500.0}
joint2_position_controller:
type: effort_controllers/JointPositionController
joint: link_01__link_02
pid: {p: 50000.0, i: 100, d: 2000.0}
joint3_position_controller:
type: effort_controllers/JointPositionController
joint: link_02__link_03
pid: {p: 20000.0, i: 50, d: 1000.0}
joint4_position_controller:
type: effort_controllers/JointPositionController
joint: link_03__link_04
pid: {p: 2000.0, i: 50, d: 200.0}
joint5_position_controller:
type: effort_controllers/JointPositionController
joint: link_04__link_05
pid: {p: 700.0, i: 50, d: 70.0}
This file defines the type of the controller and the pid parameters for each controller.
The last step is to modify the launch file in order to launch the gazebo plugin for the controller in the spawn.launch file.
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<group ns="/mrm">
<!-- Robot model -->
<param name="robot_description" command="$(find xacro)/xacro --inorder '$(find mrm_description)/urdf/mrm.xacro'" />
<arg name="x" default="0"/>
<arg name="y" default="0"/>
<arg name="z" default="0.5"/>
<!-- Spawn the robot model -->
<node name="mybot_spawn" pkg="gazebo_ros" type="spawn_model" output="screen"
args="-urdf -param robot_description -model mrm -x $(arg x) -y $(arg y) -z $(arg z)" />
<!-- Load controllers -->
<rosparam command="load" file="$(find mrm_description)/config/joints.yaml" />
<!-- Controllers -->
<node name="controller_spawner" pkg="controller_manager" type="spawner"
respawn="false" output="screen" ns="/mrm"
args="--namespace=/mrm
joint_state_controller
joint1_position_controller
joint2_position_controller
joint3_position_controller
joint4_position_controller
joint5_position_controller
--timeout 60">
</node>
<!-- rqt -->
<node name="rqt_reconfigure" pkg="rqt_reconfigure" type="rqt_reconfigure" />
<node name="rqt_publisher" pkg="rqt_publisher" type="rqt_publisher" />
</group>
</launch>
Then you can open an empty simulation from Simulations->Empty and launch it with the following command
roslaunch mrm_description spawn.launch
After you see the robot appear in the simulation, you can open the graphical tool from Tools->graphical tool
By using the rqt tool, you can send parameter to topics control the joint movement(e.g mrm/joint4_position_controller/command/dara) to move the robot.
The PID parameters are not well tuned yet, we’ll do it in the next post. But the robot is moving(with some oscillation) now.
Want to learn more?
If you want to learn more about how to create manipulator simulation in ROS, please check our Robot Creation with URDF ROS and ROS Control 101 course.
Edit by: Tony Huang
RELATED LINKS & RESOURCES
Did you like the video? If you did please give us a thumbs up and remember to subscribe to our channel and press the bell for a new video every day. Either you like it or not, please share your thoughts and questions in the comments area. See you!
[irp posts=”9549″ name=”My Robotic Manipulator – #Part 4 – ROS + URDF/Transmission + Gazebo Controllers”]
In this video we are going to set up in our robotic manipulator a new URDF element: Transmissions. After that, we are able to integrate ROS and gazebo simulation using ROS controllers. We’ll use a simplified model of the robot to see how it works. At the end of the video we’ll be able to send joint position commands to the robot publishing to some ROS topics.
Find a complete course about ROS controllers and URDF
Robot Ignite Academy:
https://goo.gl/93gmxz
—–
ROS Development Studio:
https://goo.gl/jWEZ5c
—–
Project repository:
https://bitbucket.org/theconstructcore/my-robotic-manipulator
URDF Transmission reference:
http://wiki.ros.org/urdf/XML/Transmission