Skip to content
Alex Lucas edited this page Mar 24, 2022 · 4 revisions

MDK: Advanced Features

Quick Links

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 use 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.

There are two methods to start Gazebo with an exposed ROS bridge:

  1. By modifying ./launch_sim.sh
    The default way to start the simulator in the MDK is to use the ./launch_sim.sh command (or its short-hand version miro_sim). If you open BASH for it script in a text editor, the last line should look like this:
  gazebo worlds/$WORLD.world $@

Here, Gazebo is called as a stand-alone application and it loads one of the worlds in the mdk/sim/worlds folder. In order to enable ROS Bridge, that lines needs to be modified to start with rosrun like so:

rosrun gazebo_ros gazebo --verbose worlds/$WORLD.world $@

Here, --verbose is an optional flag that tells Gazebo to output more information, which can be useful for debugging. A you can download the modified version of the file here. It is useful to keep both versions of the file, and run ROS Bridge only when required, as it does incur some overhead. 2. By using roslaunch
The COM3528_examples code repo contains an example launch file, called sim_move_ball.launch, that launches Gazebo with ROS bridge enabled and runs a sample script, called ball_mover.py that moves the blue ball in the arena in an oscillating motion. You can update your examples repo by doing a git pull to have all the latest codes, and doing a catkin build afterwards. Then, you can launch all the required processes with a one-liner:

roslaunch com3528_examples sim_move_ball.launch

(no more roscore and miro_sim, yay!)

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.

  1. 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)" />
  1. 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"/>
  1. 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

<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.

=====

Navigating This Wiki:
← Week 2: Working with the Real MiRos |