Skip to content

Latest commit

 

History

History
222 lines (159 loc) · 10.8 KB

File metadata and controls

222 lines (159 loc) · 10.8 KB

MVSim — AI Agent Context

Maintenance rule: Any change to the project (new class, new module, new sensor, refactor, dependency change, etc.) must be reflected in this file to keep it accurate for future AI tools.


Project overview

MultiVehicle Simulator (MVSim) is a lightweight, realistic 2.5D dynamics simulator for mobile robots and multi-agent research. It runs standalone, as a ROS 2 node, or embedded in C++/Python applications. Worlds are fully configured via XML files. Current version: 1.3.0.


Repository layout

mvsim/
├── modules/               # Core C++ library
│   ├── simulator/         # Main simulation engine (libmvsim)
│   ├── comms/             # ZMQ/Protobuf pub-sub communications layer
│   └── msgs/              # Protobuf message definitions (.proto files)
├── mvsim_node_src/        # ROS 2 node wrapper
├── mvsim-cli/             # Command-line tool (mvsim launch/topic/node/server)
├── mvsim-pid-tuner/       # GUI tool for tuning PID controllers
├── mvsim_tutorial/        # Demo world XML files + launch files + RViz configs
├── definitions/           # Reusable vehicle and sensor XML definitions
├── examples_cpp/          # C++ subscriber and service-caller examples
├── examples_python/       # Python API examples
├── docs/                  # Sphinx + RST documentation
├── cmake/                 # CMake helpers and version template
├── .clang-format          # Code style (Google base, Allman braces, 4-space indent, tabs)
└── .clang-tidy            # Linter config (bugprone-*, selected cppcoreguidelines-*)

Module: modules/simulatorlibmvsim

The simulation engine. Headers live in modules/simulator/include/mvsim/.

Key classes

Class Header Role
World World.h Central simulation container. Owns all vehicles, blocks, world elements, Box2D physics world, GUI window, ZMQ comms client. Split across World.cpp, World_gui.cpp, World_load_xml.cpp, World_services.cpp, World_simul.cpp, World_walls.cpp.
Simulable Simulable.h Base interface for anything that steps through simulation time. Provides simul_pre_timestep(), simul_post_timestep(), pose access with shared mutex.
VisualObject VisualObject.h Base interface for anything renderable in the OpenGL GUI.
VehicleBase VehicleBase.h Abstract vehicle. Inherits VisualObject and Simulable. Holds wheels, sensors, friction model, controller, CSV logger. Created via ClassFactory.
Block Block.h Static or dynamic rigid-body obstacle/object in the world.
HumanActor HumanActor.h Pedestrian/human agent with motion model.
Wheel Wheel.h Per-wheel physical state (torque, slip, contact).
SensorBase Sensors/SensorBase.h Base class for all sensors.
WorldElementBase WorldElements/WorldElementBase.h Base class for ground plane, grids, elevation maps, etc.
ControllerBase ControllerBase.h Abstract controller interface.
FrictionBase FrictionModels/FrictionBase.h Abstract friction model.
ClassFactory ClassFactory.h Template factory that maps XML type strings to C++ constructors.
TParameterDefinitions TParameterDefinitions.h Declares XML-readable parameters with DECLARE_PARAMETER_* macros.
Shape2p5 Shape2p5.h 2.5D shape (2D footprint + height interval).
RemoteResourcesManager RemoteResourcesManager.h Downloads and caches remote assets (maps, meshes).
CsvLogger CsvLogger.h Per-vehicle time-series logging to CSV.
PID_Controller PID_Controller.h Generic discrete PID used by controllers.
CollisionShapeCache CollisionShapeCache.h Caches Box2D collision shapes for mesh reuse.

Vehicle dynamics (src/VehicleDynamics/)

File Vehicle type
VehicleDifferential.cpp Differential drive (TurtleBot, Jackal style)
VehicleAckermann.cpp Ackermann (car-like) with kinematic/dynamic control
VehicleAckermann_Drivetrain.cpp Ackermann + realistic mechanical differentials (open/Torsen, 2WD/4WD)

Each vehicle type has companion *_Controller*.cpp files for its controllers (Raw torque, Twist PID, Ideal twist, Front-steer PID).

Sensors (src/Sensors/)

File Sensor
LaserScanner.cpp 2D LiDAR (generic + RPLidar A2)
Lidar3D.cpp 3D LiDAR (Velodyne VLP-16, Ouster OS1, Hesai Helios-32)
CameraSensor.cpp RGB pinhole camera
DepthCameraSensor.cpp RGBD depth + color camera
IMU.cpp / ImuNoiseModel.cpp IMU with Forster 2016 noise model
GNSS.cpp GPS/GNSS with configurable noise

World elements (src/WorldElements/)

OccupancyGridMap, ElevationMap, HorizontalPlane, VerticalPlane, GroundGrid, PointCloud, SkyBox, PropertyRegion (friction zones).

Friction models (src/FrictionModels/)

Default Coulomb, Ward-Iagnemma (off-road), Ellipse (slip angle + slip ratio).


Module: modules/comms — ZMQ/Protobuf communications

Provides a language-agnostic pub-sub and service-call layer using ZeroMQ + Protobuf.

Key headers in modules/comms/include/mvsim/Comms/:

  • Server.h — runs inside World, accepts registrations and forwards messages.
  • Client.h — used by external processes (Python, C++ tools, ROS node) to connect.
  • common.h, ports.h — shared constants and port numbers.

Module: modules/msgs — Protobuf message definitions

.proto files under modules/msgs/proto/. Key messages:

  • RegisterNodeRequest/Answer — node registration handshake
  • AdvertiseTopicRequest / SubscribeRequest — pub-sub setup
  • CallService / GenericAnswer — RPC
  • ObservationLidar2D / GenericObservation — sensor data
  • Pose / TimeStampedPose — pose data
  • SrvGetPose / SrvSetPose / SrvSetControllerTwist / SrvShutdown — services

ROS 2 node (mvsim_node_src/)

  • mvsim_node_main.cpp — entry point
  • mvsim_node.cppMvSimNode class wrapping World, publishing sensor observations as ROS topics, subscribing to cmd_vel, advertising TF transforms and ROS 2 parameters.
  • mvsim_node_src/include/ — node header

CLI tool (mvsim-cli/)

mvsim binary with subcommands:

  • launch <world.xml> — start simulator with GUI
  • server — start headless server
  • topic list/echo/pub — inspect/inject ZMQ topics
  • node list — list connected nodes

World XML format

Worlds are XML files. Root element: <mvsim_world>. Key child elements:

  • <element class="..."> — world elements (occupancy grids, elevation maps, planes)
  • <vehicle class="..." name="..."> — vehicle instances; XML parsed by VehicleBase::factory()
  • <block class="..." name="..."> — rigid blocks
  • <actor class="..." name="..."> — actors (e.g., humans)
  • <include> — file inclusion for reuse
  • <variable> / <for> — flow-control / parameterization
  • <if> / <verbatim> — conditional blocks

Sensor and vehicle definitions can be split into reusable files under definitions/.


Reusable XML definitions (definitions/)

Ready-to-include vehicle and sensor snippets:

  • Vehicles: jackal.vehicle.xml, turtlebot3_burger.vehicle.xml, ackermann.vehicle.xml, small_robot.vehicle.xml, pickup.vehicle.xml, scania_truck.vehicle.xml, agricobiot2.vehicle.xml, jackal-ellipse.vehicle.xml
  • Sensors: velodyne-vlp16.sensor.xml, ouster-os1.sensor.xml, helios-32-FOV-{26,31,70}.sensor.xml, rplidar-a2.sensor.xml, camera.sensor.xml, rgbd_camera.sensor.xml, imu.sensor.xml, gnss.sensor.xml

Demo worlds (mvsim_tutorial/)

demo_warehouse.world.xml, demo_2robots.world.xml, demo_greenhouse.world.xml, demo_elevation_map.world.xml, demo_road_circuit1.world.xml, demo_multistorey.world.xml, demo_logistics_center.world.xml, demo_articulated_vehicle.world.xml, demo_friction_zones.world.xml, demo_camera.world.xml, demo_depth_camera.world.xml, demo_jackal.world.xml, demo_many_robots.world.xml, demo_indoor_outdoor.world.xml, demo_outdoor.world.xml, demo_walls.world.xml, demo_turtlebot_world.world.xml, mvsim_slam.world.xml.


Python API (examples_python/)

Uses ZMQ/Protobuf Client. Examples: subscriber-example.py, mvsim-teleop.py, simple-obstacle-avoidance.py, move-object-example.py, call-shutdown.py, plot-log-files-4-wheels.py.


Key external dependencies

Library Role
MRPT Math, poses, observations, OpenGL GUI (mrpt/gui, mrpt/obs, mrpt/poses, mrpt/opengl)
Box2D 2D rigid-body physics engine
ZeroMQ (optional) Pub-sub communications
Protobuf (optional) Message serialization
pybind11 (optional) Python bindings
ROS 2 (optional) ROS node wrapper
rapidxml XML parsing (header-only, bundled)

Build system

  • CMake 3.9+, C++17.
  • Detects ROS 2 via $ROS_VERSION env var; builds the ROS node and uses ament_cmake when present.
  • Standalone build: cmake .. && make.
  • ROS 2 build: colcon build.
  • Version is read from package.xml and injected into modules/simulator/include/mvsim/mvsim_version.h at configure time.
  • cmake/mvsim_cmake_functions.cmake contains helpers used across targets.
  • Optional features guarded by MVSIM_HAS_ZMQ and MVSIM_HAS_PROTOBUF compile-time defines.

Code style

  • clang-format: Google base style, Allman brace wrapping, 4-space indent width, tabs for indentation, column limit 100, SortIncludes: true. Run via formatter.sh or .circleci/clang_format_codebase.sh.
  • clang-tidy: bugprone-*, selected cppcoreguidelines-*, readability-braces-around-statements, readability-else-after-return. Configured in .clang-tidy.
  • Always use braces for all control-flow statements (if, else, for, while, do), even single-statement bodies. No brace-less single-line statements. This is enforced by readability-braces-around-statements in .clang-tidy.
  • CI enforces clang-format via the check-clang-format GitHub Actions workflow.
  • No trailing comments alignment (disabled in .clang-format).
  • All new C++ code must pass both clang-format and clang-tidy without warnings.

Namespace and conventions

  • All simulator code lives in the mvsim namespace.
  • Protobuf messages are in the mvsim_msgs namespace.
  • Smart pointer alias Ptr = std::shared_ptr<T> defined in every major class.
  • Factory-registered classes use MVSIM_REGISTER_* macros.
  • XML-readable parameters declared with DECLARE_PARAMETER_* macros from TParameterDefinitions.h.
  • File naming: CamelCase.h / CamelCase.cpp for classes; lowercase-hyphenated.cpp for CLI tool files.
  • Header guard style: #pragma once.