Skip to content

Tutorial 1: Make Your First Script

Jie Luo edited this page Aug 12, 2021 · 3 revisions

Revolve is a wrapper for Gazebo, a multi-purpose robotics simulator. It was designed with an idea of simplifying the process of running the experiments related to the Triangle of Life project. Here, we will learn how to write a script that runs Gazebo. Now, let's make our first script!

Test this out with checking out git checkout tutorial and you can find the tutorial code in the tutorial folder located in the root of the repository.

Step 1: Writing the script

Presuming you are writing within Revolve project

  1. Within the project root create an empty file tutorial1.py.

  2. Make sure it is executable:

    sudo chmod +x tutorial1.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 os
    import sys
    from pyrevolve.custom_logging.logger import logger
    
    async def run():
        logger.info('Hello World!')
  4. Create Python virtual environment:

    virtualenv --python python3 .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=tutorial/tutorial1.py

The output should be:

...

[2019-09-19 13:19:45,266 revolve] INFO Hello World!

...

This means that rvpath points to the revolve absolute directory path with usage of os.path.abspath(os.path.join(here, '..', 'revolve')) command. Why is this important? Well, in the next step we will import Revolve-specific parts. It will search for the Revolve classes within the search paths that we set, so it is important to know where our script is positioned.

Step 2: Connecting to the simulator

The revolve.py takes care of starting the simulator, but you can connect to it, insert and delete models from your script.

  1. Let's introduce a Revolve class and connect our script to the simulator world. Insert the following code:

    #!/usr/bin/env python3
    import asyncio
    import os
    from pyrevolve.custom_logging.logger import logger
    from pyrevolve.gazebo.manage import WorldManager as World
    from pyrevolve.util.supervisor.supervisor_multi import DynamicSimSupervisor
    
    
    async def run():
        logger.info('Hello World!')
    
        # Start Simulator
        simulator_supervisor = DynamicSimSupervisor(
            world_file='worlds/plane.world',
            simulator_cmd='gazebo',
            simulator_args=["--verbose"],
            plugins_dir_path=os.path.join('.', 'build', 'lib'),
            models_dir_path=os.path.join('.', 'models'),
            simulator_name='gazebo'
        )
        await simulator_supervisor.launch_simulator()
        await asyncio.sleep(0.1)
    
        connection = await World.create()
        if connection:
            logger.info("Connected to the simulator world.")
            await asynctio.sleep(5)
  2. Run the script:

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

The output should be:

[manager] Hello World!`

[manager] Connected to the simulator world.

Program 'manager' exited normally

Terminating processes...

What changed!? Well, several things:

  • First, we introduced WorldManager. It is a Python class that takes care of connecting to the simulator world and making changes during the simulation.
  • Second, you may notice that we imported asyncio library, and that def run(): now has a special prefix async. Also, run() is not called directly anymore, but through Asyncio event loop. This is because all communication with the simulator is done through asynchronous message passing. For Gazebo, there is no direct communication with Python, so we use PyGazebo library to communicate. The implementation details are hidden within WorldManager class.
  • Third, we managed to connect to the Gazebo world. But that is not enough. We want to send some commands to the world, so this is what we will do in the next step.

Step 3: Control the world

  1. Now, we will add the code to pause the simulated world. Insert the following code:

    #!/usr/bin/env python3
    import asyncio
    import os
    import sys
    from pyrevolve.custom_logging.logger import logger
    from pyrevolve.gazebo.manage import WorldManager as World
    from pyrevolve.util.supervisor.supervisor_multi import DynamicSimSupervisor
    
    
    async def run():
        logger.info('Hello World!')
    
        # Start Simulator
        simulator_supervisor = DynamicSimSupervisor(
            world_file='worlds/plane.world',
            simulator_cmd='gazebo',
            simulator_args=["--verbose"],
            plugins_dir_path=os.path.join('.', 'build', 'lib'),
            models_dir_path=os.path.join('.', 'models'),
            simulator_name='gazebo'
        )
        await simulator_supervisor.launch_simulator()
        await asyncio.sleep(0.1)
    
        connection = await World.create()
        if connection:
            logger.info("Connected to the simulator world.")
    
        await connection.pause(True)
    
        while True:
            await asyncio.sleep(10.0)
  2. Run the script:

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

The result of this command should be the same in the terminal as before. However, something changed. If you take a look at your Gazebo simulator, in the lower left corner you can see the button instead of . This means that the world is currently paused.

What did we change now!?

  • First, we have sent a command to the simulator from our WorldManager with await world.pause(True).
  • Second, we added an asynchronous sleep so that the script does not exit instantly.

Final script

The final script should look like:

#!/usr/bin/env python3
import asyncio
import os
import sys
import time
from pyrevolve import parser
from pyrevolve.custom_logging.logger import logger
from pyrevolve.gazebo.manage import WorldManager as World
from pyrevolve.util.supervisor.supervisor_multi import DynamicSimSupervisor


async def run():
    logger.info('Hello World!')
    settings = parser.parse_args()

    # Start Simulator
    if settings.simulator_cmd != 'debug':
        simulator_supervisor = DynamicSimSupervisor(
            world_file=settings.world,
            simulator_cmd=settings.simulator_cmd,
            simulator_args=["--verbose"],
            plugins_dir_path=os.path.join('.', 'build', 'lib'),
            models_dir_path=os.path.join('.', 'models'),
            simulator_name='gazebo'
        )
        await simulator_supervisor.launch_simulator(port=settings.port_start)
        await asyncio.sleep(0.1)
    
    connection = await World.create()
    if connection:
        logger.info("Connected to the simulator world.")

    await connection.pause(True)

    while True:
        await asyncio.sleep(10.0)

In the final script, you can see that we also added some guardian code to execute our program. Also, keyboard handler is added so we can stop the script running from infinite execution.

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

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


See next: Tutorial 2: Insert a Model


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