Purpose

This page details the system architecture for Gazebo v1.0.

Requirements

  1. Speed

    1. Simulate indoor environments with multi-robots in real time
      1. Environments with: multi-room (~3), multiple objects, 1 PR2, multiple Turtlebots
      2. Physics requirements: Manipulate household objects while maintaining stability
  2. Usability

    1. Graphically create worlds: XML editing should not be required
      1. Import common meshes (tables, chairs, etc), such as from 3D Warehouse.
      2. Create models: create joints, set physical properties
      3. Create environments: click+drag to build walls, rooms, and place objects
    2. Controls
      1. Manipulate joints graphically
      2. Apply forces and torques to models
      3. Position objects intelligently: snap to ground, other objects, or a grid
    3. Visualization & Debugging: These features have performance implications, but are disabled by default

      1. Show sensor output: lasers, camera rendering, contacts
      2. Hooks for user generated visualization markers, similar to rviz
      3. Built in performance diagnostics
        1. Hooks for Hudson plot plugin

        2. Plot performance of key components at run time
  3. Programmatic control

    1. Create, modify and control bodies and joints at runtime.
      1. Interface provided via: ROS, custom plugin, or communication through Gazebo communication system
    2. Scriptable objects
      1. Attach scripts to objects in the environment
      2. Will support event triggers, and manipulation of dynamic objects (doors, people, lights)
  4. Portability

    1. Run on any laptop regardless of hardware and OS (linux, mac, windows)
      1. Step 1: Support visualization on alternative platforms
      2. Step 2: Support physics simulation on alternative platforms

Current Implementation

The current version of Gazebo is a monolithic implementation that glues together a physics engine (ODE), a rendering engine (OGRE), and a GUI (QT4). User access to sensors and controllers are provided via a shared memory interface.

Two threads run in Gazebo. The first manages the GUI and rendering engine, and the second thread manages the physics engine. With this setup it is possible to step the physics engine multiple times between rendering updates.

Issues

These issues are in relation to the speed and flexibility of Gazebo. The user interface requirements can be addressed independently of the underlying architecture.

  1. Generating camera sensor data forces the physics engine to pause
    1. This prevents a truly decoupled system where sensor generation can take place independently of physics simulation
  2. Difficult to use individual parts of Gazebo (just physics, or sensor generation)
  3. Difficult to run remotely if user also wants GUI
  4. Can't take advantage of distributed systems
    1. Monolithic architecture is less flexible

Proposed System

In order to address the requirements and resolve the current issues with Gazebo, we propose a distributed architecture. Gazebo will be broken into libraries for physics simulation, rendering, user interface, communication, and sensor generation. Three different processes will be provided: physics_sim, sensor_gen, gui, and a master for coordination.

Communication Between Processes

Communication between each process will use a combination of google::protobufs and sockets. The communication architecture will mimic that of ROS nodes. A simulated world will publish body pose updates, and sensor generation and GUI will consume these messages to produce output.

This mechanism will allow for introspection of a running simulation, and provide a convenient mechanism to control aspects of Gazebo.

Why google::protobufs instead of ROS messages

Gazebo is a standalone application, just as OpenCV and PCL are libraries independent of ROS. In order to use ROS messages, Gazebo would have to exist within the ROS eco-system. Until it's possible to link against specific parts of ROS, it's more practical to use google::protobufs.

Benefits

  1. Speed
    1. Decoupling of physics, sensor generation, and gui into separate processes which can be run independently
  2. Modularity
    1. User can pick and choose which processes to run and where to run them
    2. Each library has a simple API for potential use outside of gazebo
    3. Internal API allow for swapping of physics and collision engines
    4. Communication system allows a user to develop applications with minimal dependencies
      1. example: A render_server that server just images is trivial to implement

      2. example: A web server can potentially interact with a running simulation
  3. Portability
    1. User can run complete sim on cluster and run gui on local machine

Potential Complications

  1. Synchronization between processes
    1. We will use timestamped messages or give user complete control via run_once functionality

  2. Network traffic can become a potential bottleneck
  3. More difficult to run
    1. We can establish scripts for common situations
  4. Development and maintenance:
    1. Complexity leads to a longer debugging process

System Architecture

gazebo_dependency_graph.png

Gazebo Master

This is a stripped down clone of the ROS master. It provides namelookup, and topic management. A single master can handle multiple physics simulations, sensor generators, and GUIs.

Communication Library

  • Dependencies: Protobuf and boost::ASIO

  • External API:

    • bool get_master_uri(std::string &master_host, unsigned short &master_port);

      • Get URI of the gazebo master, as defined by the GAZEBO_MASTER_URI
      • master_host: Gets set to the master hostname
      • master_port: Gets set to the master port
      • Return true on success
    • bool init(const std::string &master_host="", unsigned short master_port=0);

      • Initialize the communication system
      • master_host: Hostname of the master, leave empty to use the default
      • master_port: Port of the master, leave empty to use the default
      • Return true on success
    • void set_topic_namespace(const std::string &space);

      • Set the namespace for all topics ( /gazebo/<space>/ )

      • space: Name of the topic namespace
    • transport::PublisherPtr advertise(const std::string &topic);

      • Advertise a new topic
      • topic: Name of the topic
      • Return a pointer to a publisher
    • transport::SubscriberPtr subscribe(const std::string &topic, void(T::*fp)(const boost::shared_ptr<M const> &), T *obj);

      • Subscribe to a topic
      • topic: Name of the topic
      • fp: Calback function pointer
      • obj: Object containing the callback function
      • Return a Subscriber pointer
    • transport::SubscriberPtr subscribe(const std::string &topic, void(*fp)(const boost::shared_ptr<M const> &));

      • Subscribe to a topic
      • fp: A function pointer callback
      • Return a Subscriber pointer
  • Internal API: None

  • Advertised Topics: None

  • Subscribed Topics: None

This library is used by almost all subsequent libraries. It acts as the communication and transport mechanism for Gazebo. It currently supports only publish/subscribe, but it's possible to use RPC with minimal effort.

Protobuf Messages

  • Point { double:x, double:y, double:z }
  • Quaternion { double:x, double:y, double:z, double:u }
  • Pose { Point:position, Quaternion:orientation }

  • Twist { Point:linear_velocity, Point:euler_angle_velocity }

  • Wrench { Point:force, Point:torque }

  • Time {uint32:seconds, uint32:nanoseconds}
  • Mass {double:mass, double[]:inertia}
  • EntityState { string:entity_name, Pose:pose, Twist:twist, Wrench:wrench }

  • WorldStatistics {Time:sim_time, Time:pause_time, Time:real_time, uint32:iterations, int32:model_count}

  • WorldState { EntityState[]:entity_states, WorldStatistics:stats, Point:gravity, double:time_step}

Physics Library

  • Dependencies: Dynamics engine, and Collision Library

  • External API: Provides a simple and generic interface to physics simulation

    • bool init();

      • Initialize the physics engine
      • Return True if successful
    • WorldPtr create_world_from_file(const std::string &filename);

      • Create a world based on a configuration file
      • filename: The name of the configuration file
      • Return a pointer to the world
    • WorldPtr create_world_from_string(const std::string &xml_string);

      • Create a world based on a configuration string
      • filename: The name of the configuration string
      • Return a pointer to the world
    • void run();

      • Run all the worlds, this blocks
    • void run_once();

      • Run all the worlds one step
  • Internal API: Defines a fundamental interface to the physics library for 3rd party dynamic engines.

  • Advertised Topics:

    • /gazebo/<world_name>/entity_state_update : Update of the entity states. Only those entities that have changed will be published

    • /gazebo/<world_name>/state : The current state of the entire world. Published when a new subscriber connects to the world

    • /gazebo/<world_name>/world_stats: Publish statistics about the physics simulation

  • Subscribed Topics:

    • /gazebo/<world_name>/control : Provides external users with control over the running simulation

    • /gazebo/<world_name>/set_entity_prop : Set the properties of an entity

      • Msg Type: EntityProp { string:entity_name, Mass:mass, double:velocity_damping, double:friction_coefficient }

    • /gazebo/<world_name>/set_entity_state : Set the state of an entity

      • Msg Type: EntityState { string:entity_name, Pose:pose, Twist:twist, Wrench:wrench }

    • /gazebo/<world_name>/set_joint_property : Set the properties of a joint

      • Msg Type: JointProp { string:joint_name, double:damping, Point:offset, double:max_force, double[]:lower_limits, double[]:upper_limits }

    • /gazebo/<world_name>/set_joint_state: Set the state of a joint

      • Msg Type: JointState { string:joint_name, double[]:angle, double[]:velocity, double[]:effort }

    • /gazebo/<world_name>/insert_entity : Allows new entities to be inserted into the simulation

      • Msg Type: Entity { string:entity_name, Pose:pose, Mass:mass, CollisionObj:coll, Visual:vis }

The physics library can use any dynamic engine that conforms to the internal API (TBD). It also presents a simple external interface in order to establish a work physics simulation.

Collision Library

  • Dependencies: 3rd party collision engine

  • External API: TBD

  • Internal API: Generic interface for collision engines

  • Advertised Topics: None

  • Subscribed Topics: None

This is an abstraction library to handle different collision engines, and provide a simple external interface to the user.

Rendering Library

  • Dependencies: OGRE

  • External API: Allows for loading, initialization, and scene creation

    • bool init(const std::string &world_name, bool no_gui);

      • Initialize the rendering engine
      • world_name: The world which is performing physics sim
      • no_gui: Set to true if a GUI is not present or if the rendering engine should not expect an external render window
    • bool load_from_file(const std::string &filename);

      • Load the rendering engine from a file.
      • filename: Filename containing XML configuration
      • Return True if load was successful
    • bool load_from_string(const std::string &xml_string);

      • Load the rendering engine from a file.
      • xml_string: A string containing the XML configuration specification
      • Return True if load was successful
  • Internal API: None, we are going to use only OGRE.

  • Advertised Topics: None

  • Subscribed Topics:

    • /gazebo/<world_name>/state : Get the current state of the entire world

    • /gazebo/<world_name>/entity_state_update : Get the entity updates and change the scene appropriately

The rendering library provides a simple interface to both the GUI and sensor generation. We are currently sticking with OGRE since we don't have a better alternative. It will be possible to write plugins for the rendering engine.

Note on RVE

Significant work has been done on RVE, and we believe there may be potential to combine our efforts. In the next few days/weeks we will hash out this possibility, and how to proceed.

Sensor Generation

  • Dependencies: Rendering Library, Collision Library

  • External API: Provide functionality to initialize and run a set of sensors

    • bool sensors::init(const std::string &world_name);

      • Initialize the sensor library
      • world_name: The name of the world in which to simulate the sensors
      • Return True if initialization was successful
    • SensorPtr sensors::create_sensor(const std::string &type);

      • Create a sensor of a certain type.
      • type: A string name that defines the type of sensor, ex: camera, laser
      • Return a pointer to the new sensor.
    • void sensors::run();

      • Update all the sensors, this blocks.
    • void sensors::run_once(bool force=true);

      • Update all the sensors once
      • force: If true, all sensors will be updated regardless of their Hz rate.
  • Internal API: TBD

  • Advertised Topics: This depends on the sensors that are created.

  • Subscribed Topics:

    • /gazebo/<world_name>/state : Get the current state of the entire world

    • /gazebo/<world_name>/entity_state_update : Get the entity updates and change the scene appropriately

The sensor generation library implements all the various types of sensors, listens to world state updates from a physics simulator and produces output specified by the instantiated sensors.

GUI

  • Dependencies: Rendering Library, QT4

  • External API: TBD

  • Internal API: TBD

  • Advertised Topics:

    • /gazebo/<world_name>/set_entity_prop : Set the properties of an entity

      • Msg Type: EntityProp { string:entity_name, Mass:mass, double:velocity_damping, double:friction_coefficient }

    • /gazebo/<world_name>/set_entity_state : Set the state of an entity

      • Msg Type: EntityState { string:entity_name, Pose:pose, Twist:twist, Wrench:wrench }

    • /gazebo/<world_name>/set_joint_property : Set the properties of a joint

      • Msg Type: JointProp { string:joint_name, double:damping, Point:offset, double:max_force, double[]:lower_limits, double[]:upper_limits }

    • /gazebo/<world_name>/set_joint_state: Set the state of a joint

      • Msg Type: JointState { string:joint_name, double[]:angle, double[]:velocity, double[]:effort }

    • /gazebo/<world_name>/insert_entity : Allows new entities to be inserted into the simulation

      • Msg Type: Entity { string:entity_name, Pose:pose, Mass:mass, CollisionObj:coll, Visual:vis }

  • Subscribed Topics:

    • /gazebo/<world_name>/entity_state_update : Update of the entity states. Only those entities that have changed will be published

The primary function of the GUI involves displaying the current state of the simulation and providing a convenient means for user input. There is no need for an internal or external API since we are sticking with wxWidgets.

Plugins

The physics, sensor, and rendering libraries will support plugins. These plugins will provide users with access to the respective libraries without using the communication system.

Wiki: gazebo/Version_1.0_Design_Specification (last edited 2012-09-24 21:15:34 by hsu)