Skip to content

Tutorial 2: Inserting a Model

Milan Jelisavcic edited this page Feb 21, 2019 · 23 revisions

In the previous tutorial, we learned how to make a simple Revolve manager in Python. Now we will see how to insert a model into a world. A model can be any object - a sphere, a block, a cylinder, but also any 3D mesh that we define in STL or Collada format. Let's start easy and use a simple sphere.

Quickstart with SDF

Gazebo uses SDFormat, an XML file format, for defining environments and models. The SDF specification defines all the XML elements for describing world and models. You can accurately describe all aspects of a model using SDF, whether the model is a simple chassis with wheels or a humanoid robot. For example, if we want to insert a simple sphere, this is the SDF that we need to inject into the simulation:

<sdf version="1.5">
   <model name="sphere">
      <pose>1 0 0 0 0 0</pose>
      <link name="link">
         <pose>0 0 .5 0 0 0</pose>
         <collision name="collision">
            <geometry>
               <sphere><radius>0.5</radius></sphere>
            </geometry>
         </collision>
         <visual name="visual">
            <geometry>
               <sphere><radius>0.5</radius></sphere>
            </geometry>
         </visual>
      </link>
   </model>
</sdf>

It seem very confusing! Dont worry, the following is the explanation. There are top-level elements of <sdf> that should be noted:

  • <world>: The world element encapsulates an entire world description including: models, scene, physics, joints, and plugins;
  • <model>: The model element defines a complete robot or any other physical object;
  • <actor>: A special kind of model which can have a scripted motion. This includes both global waypoint type animations and skeleton animations;
  • <light>: The light element describes a light source.

It is important to note that that every SDF can be considered an array of one or more of elements. This mean that in one SDF we can define the <world> environment and one or more <model> objects.

In order to make a <model> object, child elements are used to define it:

  • <static>: If set to true, the model is immovable. Otherwise the model is simulated in the dynamics engine;
  • <model>: A nested model element;
  • <pose>: A position(x, y, z) and orientation(roll, pitch yaw) with respect to the specified frame;
  • <link>: A physical link with inertia, collision, and visual properties. A link must be a child of a model, and any number of links may exist in a model;
  • <joint>: A joint connections two links with kinematic and dynamic properties;
  • <plugin>: A plugin is a dynamically loaded chunk of code. It can exist as a child of world, model, and sensor.

There are others, but these are the most prominent ones Revolve uses.

Finally, we should mention briefly important part of <link> element:

  • <pose>: A position(x, y, z) and orientation(roll, pitch yaw) with respect to the specified frame;
  • <inertial>: The inertial properties of the link;
  • <collision>: The collision properties of a link. Note that this can be different from the visual properties of a link, for example, simpler collision models are often used to reduce computation time;
  • <visual>: The visual properties of the link. This element specifies the shape of the object (box, cylinder, etc.) for visualization purposes;
  • <sensor>: The sensor tag describes the type and properties of a sensor.

Take another look on our SDF example above. Now it is starting to make sense! OK, let's insert it now in the simulator and see how it looks.

Step 1: Inserting a model

Presuming you are writing within Revolve project

  1. Withing the project root create an empty file tutorial2.py.

  2. Make sure it is executable:

    sudo chmod +x tutorial2.py
  3. Open the file with a text editor, add the following piece of code to the script, and save it:

    #!/usr/bin/env python3
    import asyncio
    import os
    import sys
    
    here = os.path.dirname(os.path.abspath(__file__))
    rvpath = os.path.abspath(os.path.join(here, '..', 'revolve'))
    sys.path.append(os.path.dirname(os.path.abspath(__file__)))
    
    from pyrevolve.gazebo.manage import WorldManager as World
    
    
    async def run():
    
        world = await World.create()
        if world:
            print("Connected to the simulator world.")
    
        sdf_model = """
        <sdf version ='1.5'>
            <model name ='sphere'>
                <pose>1 0 0 0 0 0</pose>
                <link name ='link'>
                    <pose>0 0 .5 0 0 0</pose>
                    <collision name ='collision'>
                        <geometry>
                            <sphere>
                                <radius>0.5</radius>
                            </sphere>
                        </geometry>
                    </collision>
                    <visual name ='visual'>
                        <geometry>
                            <sphere>
                                <radius>0.5</radius>
                            </sphere>
                        </geometry>
                    </visual>
                </link>
            </model>
        </sdf>"""
    
        await world.insert_model(sdf_model)
        await world.pause(True)
    
        while True:
            await asyncio.sleep(10.0)
    
    
    def main():
        loop = asyncio.get_event_loop()
        loop.run_until_complete(run())
    
    
    if __name__ == "__main__":
        main()
  4. Create Python virtual environment:

    virtualenv .venv
    source .venv/bin/activate
    (.venv) pip install -r requirements.txt

NOTE: When the virtual environment is activated, you will see (.venv) designation appearing on the active line within your terminal window. Revolve works within this environment in order to keep your installed Python isolated from unexpected changes. Otherwise, if you feel proficient enough, you can install Revolve as part of your system. For now, we will show examples from the virtual environment.

  1. Run the script:
    (.venv) ./revolve.py --simulator-cmd=gazebo --manager ./tutorial2.py

The output should be:

We can see that it accuratelly renders the sphere in the world. However, it can be a tedious and erroneous task to write this SDF models manually. That is why Revolve can define this elements for you. In the next step we will see how to do that in Python.

Step 2: Inserting a model programatically

To create SDF models, Revolve has sdfbuilder submodule. It defines all of the mentioned elements and makes it easy to define and nest them.

  1. Replace with the following piece of code to the script:

    #!/usr/bin/env python3
    import asyncio
    import os
    import sys
    
    here = os.path.dirname(os.path.abspath(__file__))
    rvpath = os.path.abspath(os.path.join(here, '..', 'revolve'))
    sys.path.append(os.path.dirname(os.path.abspath(__file__)))
    
    from pyrevolve.gazebo.manage import WorldManager as World
    from pyrevolve.sdfbuilder import Model, Link, SDF
    from pyrevolve.sdfbuilder.math import Vector3
    
    
    async def run():
    
        world = await World.create()
        if world:
            print("Connected to the simulator world.")
        
        model = Model(
                name='sdf_model',
                static=True,
        )
        model.set_position(position=Vector3(0, 0, 1))
        link = Link('sdf_link')
        link.make_sphere(
                mass=10e10,
                radius=0.5,
        )
        link.make_color(0.7, 0.2, 0.0, 1.0)
        
        model.add_element(link)
        sdf_model = SDF(elements=[model])
        
        await world.insert_model(sdf_model)
        await world.pause(True)
        
        while True:
            await asyncio.sleep(10.0)
    
    
    def main():
        loop = asyncio.get_event_loop()
        loop.run_until_complete(run())
    
    
    if __name__ == "__main__":
        main()
  2. Make sure you are using the virtual environment (.venv).

  3. Run the script:

    (.venv) ./revolve.py --simulator-cmd=gazebo --manager ./tutorial2.py

The output should be:

We can see that it is not the same sphere as above. We changed the position and the colour. Take a look in the code on how it is done.

Final script

The final script should look like:

#!/usr/bin/env python3
import asyncio
import os
import sys

here = os.path.dirname(os.path.abspath(__file__))
rvpath = os.path.abspath(os.path.join(here, '..', 'revolve'))
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

from pygazebo.pygazebo import DisconnectError

from pyrevolve.gazebo.manage import WorldManager as World
from pyrevolve.sdfbuilder import Model, Link, SDF
from pyrevolve.sdfbuilder.math import Vector3


async def run():
    world = await World.create()
    if world:
        print("Connected to the simulator world.")

    model = Model(
            name='sdf_model',
            static=True,
    )
    model.set_position(position=Vector3(0, 0, 1))
    link = Link('sdf_link')
    link.make_sphere(
            mass=10e10,
            radius=0.5,
    )
    link.make_color(0.7, 0.2, 0.0, 1.0)

    model.add_element(link)
    sdf_model = SDF(elements=[model])

    await world.insert_model(sdf_model)
    await world.pause(True)
    while True:
        await asyncio.sleep(10.0)


def main():
    def handler(loop, context):
        exc = context['exception']
        if isinstance(exc, DisconnectError) \
                or isinstance(exc, ConnectionResetError):
            print("Got disconnect / connection reset - shutting down.")
            sys.exit(0)
        raise context['exception']

    try:
        loop = asyncio.get_event_loop()
        loop.set_exception_handler(handler)
        loop.run_until_complete(run())
    except KeyboardInterrupt:
        print("Got Ctrl+C, shutting down.")


if __name__ == "__main__":
    main()

You can find this example with other tutorial scripts within Revolve experiments/examples directory.

This tutorial gives you some basic idea of how it all works. Now, let us insert some robots into the world!


See next: Tutorial 3: Inserting a Robot


_________________
/ Premature      \
| optimization   |
| is the root of |
| all evil.      |
|                |
\ -- D.E. Knuth  /
-----------------
    \   ^__^
     \  (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||
Clone this wiki locally