MDK: Advanced Features¶
Introduction¶
Here you will learn some of the more advanced features of the MDK that will help you in development of your biomimetic project. You can treat page as an updating FAQ, as not every team will need to learn every topic on this page.
Gazebo and ROS bridge¶
So far, we have covered how to control MiRo in the simulation using the MDK interface. You might also remember from COM1005 and COM2009 how to manipulate other objects via the Gazebo GUI. However, in some scenarios it may be required to control other objects in the environment programmatically, for example in order to implement dynamic objects. In such cases, it is useful to launch Gazebo with a running ROS Bridge. The ROS Bridge in Gazebo is part of the API that lets the user control the simulator directly through ROS topics, as seen on the screenshot below.
In order to start Gazebo with an exposed ROS bridge use the ./launch_full.sh
script inside the ~/mdk/sim
Example: moving the toy ball programmatically¶
You can see how having access to Gazebo-ROS bridge can be used in practice by running the following code:
In this example, a dedicated ROS node, called ball_mover
, subscribes to the /set_model_state
topic (as seen above) and then changes the pose of the MiRo's toy ball, to make it oscillate in front of MiRo.
The node's source code is located at com3528_examples/scripts/ball_mover.py
, if you want to inspect it in more detail.
Roslaunch
file structure in MDK¶
It is useful to have a look at a typical launch file in more detail, as there are some parameters that haven't been covered in COM2009.
The following are snippets from sim_move_ball.launch
.
- Since some of the assets in MDK live in their own dedicated folder, it is necessary to inform ROS where those assets are. One of the easiest ways of doing this is to set up the paths as environment variables inside the launch file:
<!-- Add custom Gazebo paths -->
<env name="GAZEBO_MODEL_PATH"
value="$(find com3528_examples)/models:$(optenv MIRO_DIR_MDK)/sim/models:$(optenv GAZEBO_MODEL_PATH)" />
<env name="GAZEBO_RESOURCE_PATH"
value="$(optenv MIRO_DIR_MDK)/sim:$(optenv GAZEBO_RESOURCE_PATH)" />
<env name="GAZEBO_PLUGIN_PATH"
value="$(optenv MIRO_DIR_MDK)/bin/${MIRO_SYSTEM}:$(optenv GAZEBO_PLUGIN_PATH)" />
- In order to tell Gazebo which world to load, a special argument needs to be set that would find the world file by its name in the dedicated
worlds
folder:
<!-- Specify which .world file to load -->
<arg name="world" default="$(optenv MIRO_DIR_MDK)/sim/worlds/miro.world"/>
- The rest should be familiar, but it is important to note that here the Gazebo server and the Gazebo GUI client are loaded separately; such setup provides more flexibility and robustness.
Note
All the Gazebo topics in such setup are prefixed with a namespace that can be set manually.
<!-- Set the name for Gazebo -->
<arg name="gazebo_ns" default="gazebo_server" doc="Gazebo namespace, typically 'gazebo' or 'gazebo_server'" />
<!-- start Gazebo server with exposed ROS interface-->
<node name="$(arg gazebo_ns)"
pkg="gazebo_ros"
type="gzserver"
respawn="false"
required="true"
args="--physics ode --verbose $(arg world)"
/>
<!-- Start Gazebo client -->
<node name="gazebo_gui"
pkg="gazebo_ros"
type="gzclient"
respawn="true"
/>
Controlling multiple MiRos in simulation¶
In some projects you will need to control more than one MiRo in simulation.
This section will explain how to do this with the help of roslaunch files and ROS namespaces.
The COM3528 examples repo has a template launch file for this purpose, called sim_football.launch
. Launching this file will start Gazebo with three MiRos placed on the football pitch, with the MiRos named sequentially as miro01
, miro02
and miro03
. The relevant snippet from the football_pitch.world
is given below```xml
<include>
<name>miro01</name>
<uri>model://miro_model</uri>
<pose>0 0 0 0 0 0</pose>
</include>
<include>
<name>miro02</name>
<uri>model://miro_model</uri>
<pose>-0.5 0.2 0.05 0 0 0.5</pose>
</include>
<include>
<name>miro03</name>
<uri>model://miro_model</uri>
<pose>0.5 0.2 0.05 0 0 -0.5</pose>
</include>
Once the world loads, the kick_blue_ball.py
script will launch to control each MiRo independently.
This is gonna get messy! 😀
So how is this done? Let's have a look at the relevant part of sim_football.launch
:
<!-- MiRo1 behaviour -->
<env name="MIRO_ROBOT_NAME" value="miro01" />
<node ns="miro01" name="kick_blue_ball_01" pkg="com3528_examples" type="kick_blue_ball.py" />
<!-- MiRo2 behaviour -->
<env name="MIRO_ROBOT_NAME" value="miro02" />
<node ns="miro02" name="kick_blue_ball_02" pkg="com3528_examples" type="kick_blue_ball.py" />
<!-- MiRo3 behaviour -->
<env name="MIRO_ROBOT_NAME" value="miro03" />
<node ns="miro03" name="kick_blue_ball_03" pkg="com3528_examples" type="kick_blue_ball.py" />
The key principle here is to temporarily change the value of the MIRO_ROBOT_NAME
environment variable using the <env>
tag and feed that value to the kick_blue_ball.py
node.
Recall that we use that robot's name in the script's initialisation
# Individual robot name acts as ROS topic prefix
topic_base_name = "/" + os.getenv("MIRO_ROBOT_NAME")
and thus we can separate the three MiRos into distinct namespaces.
Now run rostopic list
to check how the topics look like in this case.
Note
All you have to remember in such a setting is to prefix all the topics for your publishers and subscribers with the correct MiRo name.
MiRo Bridge Flags¶
MiRo bridge allows the user to change certain flags that are linked to the various features on-board MiRo and in the simulator.
These includes features such as blinking the LEDs to identify errors in MiRo's control board, disabling the cliff reflex or even translational movement in the MiRo.
A list of all the flags can be found in the ~/mdk/share/python/miro2/constants.py
.
We provided a small utility, located in nodes/publisher_flags.py
that can be used to disable the following common flags:
Flag | Constant Variable to Disable |
---|---|
Disabling Status LED | miro.constants.PLATFORM_D_FLAG_DISABLE_STATUS_LEDS |
Disabling Speakers | miro.constants.PLATFORM_D_FLAG_DISABLE_SPEAKER |
Disabling Wheel Control | miro.constants.PLATFORM_D_FLAG_DISABLE_WHEEL_CONTROL |
Disabling Opto (Feedback) | miro.constants.PLATFORM_D_FLAG_DISABLE_OPTO |
Disabling Servo Power | miro.constants.PLATFORM_D_FLAG_DISABLE_SERVO_POWER |
Disabling I2C Fail Warn | miro.constants.PLATFORM_D_FLAG_DISABLE_I2C_FAIL_WARN |
Disabling Cliff Reflex | miro.constants.PLATFORM_D_FLAG_DISABLE_CLIFF_REFLEX |
Disabling Kinematic Idle | miro.constants.PLATFORM_D_FLAG_DISABLE_KIN_IDLE |
Disabling Translation | miro.constants.PLATFORM_D_FLAG_DISABLE_TRANSLATION |
=====
This completes the tutorial for the Week 3 lab session.