Skip to content

Simulator

Overview

OpenMowerNext uses Webots as its simulation backend. Gazebo is no longer maintained in this repository.

The simulation is built around Webots-native resources:

  • worlds/openmower.wbt defines the world, clock source, GPS reference, robot and docking station.
  • protos/OpenMower.proto defines the robot model and stable Webots device names.
  • protos/DockingStation.proto defines the charging dock model.
  • resource/openmower_webots.urdf maps Webots devices to ROS 2 topics and ros2_control.

Getting Started

Install ROS dependencies first:

bash
make deps

Run the simulator from the repository root:

bash
make sim

By default this starts Webots with streaming enabled on port 1234, so another machine on the same LAN can open http://<host>:1234/index.html, for example http://lord.local:1234/index.html. The / endpoint is not a normal HTTP page and may return an empty response; the actual simulation stream is a WebSocket on the same port. If the viewer defaults to ws://localhost:1234, change it to ws://<host>:1234, for example ws://lord.local:1234, and click Connect. Foxglove is intentionally not started by the simulator launch; run it separately with make foxglove when needed.

For headless smoke tests on the development host, run:

bash
WEBOTS_OFFSCREEN=1 ros2 launch open_mower_next sim.launch.py gui:=false mode:=fast

If Webots was installed by webots_ros2_driver, set WEBOTS_HOME=~/.ros/webotsR2025a/webots or use make sim, which sets it automatically when that directory exists. Headless Webots also needs xvfb and libxcb-cursor0 on Ubuntu.

The canonical development flow runs Webots and ROS 2 on the development host. GUI access can be done through Webots streaming, browser/VNC, or SSH forwarding depending on the workstation setup.

ROS Contract

The simulator publishes or serves the same ROS-facing contract used by the rest of the stack:

  • /clock from Ros2Supervisor
  • /gps/fix from the Webots GPS device
  • /imu/data_raw from the Webots IMU plugin
  • /diff_drive_base_controller/odom from diff_drive_controller
  • /power/charger_present, /power/charge_voltage, and /power from sim_node

Velocity commands still flow through twist_mux to /diff_drive_base_controller/cmd_vel.

Current State

  • ✅ Webots world and robot model
  • ✅ Webots ROS 2 driver launch
  • webots_ros2_control integration
  • ✅ GPS device mapping
  • ✅ IMU device mapping
  • ✅ Charging and battery emulation using sim node

World Definition

wbt
#VRML_SIM R2025a utf8

EXTERNPROTO "../protos/OpenMower.proto"
EXTERNPROTO "../protos/DockingStation.proto"

WorldInfo {
  title "OpenMowerNext Webots simulation"
  basicTimeStep 10
  coordinateSystem "ENU"
  gpsCoordinateSystem "WGS84"
  gpsReference -22.9 -43.2 0
}
Viewpoint {
  orientation -0.330491 0.451759 0.828566 1.32217
  position -2.3 -4.4 3.0
  follow "openmower"
}
Background {
  skyColor [
    0.45 0.62 0.85
  ]
}
DirectionalLight {
  direction -0.4 -0.2 -1
  intensity 1
}
Solid {
  translation 0 0 -0.005
  children [
    Shape {
      appearance PBRAppearance {
        baseColor 0.12 0.42 0.12
        roughness 1
        metalness 0
      }
      geometry DEF FLOOR_BOX Box {
        size 20 20 0.01
      }
    }
  ]
  name "grass_floor"
  boundingObject USE FLOOR_BOX
}
OpenMower {
  translation 0 0 0.0925
  rotation 0 0 1 2.0944
  name "openmower"
  controller "<extern>"
}
DockingStation {
  translation 1.5 1.5 0
  name "docking_station"
}
Robot {
  name "Ros2Supervisor"
  controller "<extern>"
  supervisor TRUE
}