diff --git a/CMakeLists.txt b/CMakeLists.txt
index 45d4ac54..5038e465 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -98,7 +98,6 @@ if (DETECTED_ROS2)
find_package(rclcpp REQUIRED)
- # *** TEMPORARY ***!!!
find_package(ament_cmake REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(nav_msgs REQUIRED)
@@ -193,15 +192,10 @@ endif()
# Dependency: MRPT
# Use the first cmd to set the minimum required version
# ----------------------------------------------------------
-find_package(mrpt-maps REQUIRED)
-find_package(mrpt-tclap REQUIRED)
-find_package(mrpt-gui REQUIRED)
-find_package(mrpt-tfest REQUIRED)
-find_package(mrpt-topography REQUIRED)
-
-if (mrpt-maps_VERSION VERSION_LESS "2.14.1")
- message(FATAL_ERROR "MRPT version 2.14.1 or newer is required, but found ${mrpt-maps_VERSION}")
-endif()
+find_package(mrpt_maps REQUIRED)
+find_package(mrpt_gui REQUIRED)
+find_package(mrpt_tfest REQUIRED)
+find_package(mrpt_topography REQUIRED)
# --------------------------
# Dependency: Box2D
diff --git a/definitions/jackal.vehicle.xml b/definitions/jackal.vehicle.xml
index ea1311c1..e4579a25 100644
--- a/definitions/jackal.vehicle.xml
+++ b/definitions/jackal.vehicle.xml
@@ -30,8 +30,8 @@
- 20
- 10
+ 18.2909
+ 474.48890.0000100
diff --git a/docs/mvsim-pid-tuner.rst b/docs/mvsim-pid-tuner.rst
index d5340015..e80ab33f 100644
--- a/docs/mvsim-pid-tuner.rst
+++ b/docs/mvsim-pid-tuner.rst
@@ -4,8 +4,9 @@ mvsim-pid-tuner
===============
``mvsim-pid-tuner`` is a command-line tool for automatic PID parameter tuning of MVSim
-vehicle controllers. It identifies the vehicle's dynamic response and proposes optimal
-PID gains using the IMC (Internal Model Control) tuning method.
+vehicle controllers. It identifies the vehicle's dynamic response (both linear and
+rotational) and proposes optimal PID gains using the IMC (Internal Model Control)
+tuning method.
.. contents::
:depth: 1
@@ -18,27 +19,38 @@ Overview
Tuning PID controllers for simulated vehicles can be tedious. This tool automates the
process by:
-1. Running an **open-loop step response** test (constant torque applied to wheels)
-2. **Identifying the plant model** as a first-order system: :math:`G(s) = K / (\tau s + 1)`
-3. Computing **optimal PID parameters** using IMC tuning rules
-4. **Validating** the proposed parameters with a closed-loop step-up/step-down simulation
+1. Running **open-loop step response** tests for both linear and rotational motion
+2. **Identifying the plant models** as first-order systems: :math:`G(s) = K / (\tau s + 1)`
+3. Computing **optimal PID parameters** using IMC tuning rules, balanced for both modes
+4. **Validating** the proposed parameters with closed-loop step-up/step-down simulations
+ for both linear velocity and angular velocity
Algorithm
---------
-**Phase 1: Plant Identification**
+**Phase 1a: Linear Plant Identification**
-A constant torque is applied to all wheels (via a ``raw`` controller) and the average
-wheel velocity is recorded over time. The steady-state velocity :math:`v_{ss}` is
-computed from the last 20% of samples, and the plant gain and time constant are:
+A constant torque is applied equally to all wheels (via a ``raw`` controller) and the
+average wheel velocity is recorded over time. The steady-state velocity :math:`v_{ss}`
+is computed from the last 20% of samples, and the plant gain and time constant are:
.. math::
- K = \frac{v_{ss}}{\tau_{applied}}, \quad \tau = \text{time to reach } 63.2\% \text{ of } v_{ss}
+ K_{lin} = \frac{v_{ss}}{\tau_{applied}}, \quad \tau_{lin} = \text{time to reach } 63.2\% \text{ of } v_{ss}
+
+**Phase 1b: Rotation Plant Identification**
+
+Opposite torques are applied to left and right wheels (left forward, right backward)
+to induce pure rotation. The angular velocity :math:`\omega` is recorded from the
+vehicle's odometry estimate. The rotational plant model is identified analogously:
+
+.. math::
+
+ K_{rot} = \frac{\omega_{ss}}{\tau_{applied}}, \quad \tau_{rot} = \text{time to reach } 63.2\% \text{ of } \omega_{ss}
**Phase 2: IMC PID Tuning**
-For a first-order plant, the IMC method yields a PI controller:
+For each first-order plant (linear and rotational), the IMC method yields a PI controller:
.. math::
@@ -47,12 +59,20 @@ For a first-order plant, the IMC method yields a PI controller:
where :math:`\tau_{cl} = \tau \cdot \alpha` is the desired closed-loop time constant and
:math:`\alpha` is the aggressiveness factor (smaller = faster response).
+Since the ``twist_pid`` controller uses the same PID gains for both wheels, the tool
+computes PID parameters for both linear and rotational plants independently, then uses
+the **geometric mean** to balance performance across both modes.
+
The ``max_torque`` is set to 80% of the estimated friction limit to avoid wheel slip.
**Phase 3: Closed-Loop Validation**
-The proposed PID parameters are tested with a step-up to 1.0 m/s (3 seconds) followed
-by a step-down to 0 m/s (3 seconds). The tool reports:
+The proposed PID parameters are validated with two separate tests:
+
+* **Linear test**: step-up to 1.0 m/s (3 seconds) followed by step-down to 0 m/s (3 seconds)
+* **Rotation test**: step-up to 1.0 rad/s (3 seconds) followed by step-down to 0 rad/s (3 seconds)
+
+For each test, the tool reports:
* Rise time (time to 90% of setpoint)
* Settling time (time to enter 2% band)
@@ -111,41 +131,65 @@ Sample output:
MVSim PID Auto-Tuner
======================================
- --- Phase 1: Open-loop plant identification ---
+ --- Phase 1a: Open-loop LINEAR plant identification ---
Vehicle: small_robot (2 wheels)
Wheel 0: pos=(0.000, 0.500) R=0.200 mass=4.00
Wheel 1: pos=(0.000, -0.500) R=0.200 mass=4.00
Chassis mass: 15.0 kg
+ Wheel track: 1.000 m
Estimated max friction torque per wheel: 18.10 Nm (mu=0.8)
- Test torque: 9.05 Nm
+ Test torque: 9.05 Nm (linear)
- === Open-Loop Step Response Analysis ===
+ === Open-Loop Step Response Analysis (linear) ===
Applied torque: 9.050 Nm
Steady-state velocity: 1.2345 m/s
Plant gain K: 0.1364 (m/s)/Nm
- Time constant τ: 0.1500 s
+ Time constant tau: 0.1500 s
+
+ --- Phase 1b: Open-loop ROTATION plant identification ---
+ Test torque: 9.05 Nm (rotation)
+
+ === Open-Loop Step Response Analysis (rotation) ===
+ Applied torque: 9.050 Nm
+ Steady-state omega: 2.5000 rad/s
+ Plant gain K: 0.2762 (rad/s)/Nm
+ Time constant tau: 0.0800 s
--- Phase 2: IMC PID tuning (aggressiveness=0.25) ---
- Proposed PID parameters:
- KP: 29.3200
- KI: 195.4667
+ Linear-only PID: KP=29.3200 KI=195.4667
+ Rotation-only PID: KP=14.4800 KI=181.0000
+
+ Proposed PID parameters (balanced linear + rotation):
+ KP: 20.6000
+ KI: 188.0000
KD: 0.0000
max_torque: 14.48 Nm
--- Phase 3: Closed-loop validation ---
+
+ [Linear] Step-up (1.0 m/s, 3s) then step-down (stop, 3s)...
Step-up (0 -> 1.0 m/s):
+ Rise time (90%): 0.150 s
+ Settling time (2%): 0.300 s
+ Overshoot: 3.2 %
+ Steady-state error: 0.0015 m/s
+ Step-down (1.0 -> 0 m/s):
+ Settling time (2%): 0.350 s
+ Rebound: none
+
+ [Rotation] Step-up (1.0 rad/s, 3s) then step-down (stop, 3s)...
+ Step-up (0 -> 1.0 rad/s):
Rise time (90%): 0.120 s
Settling time (2%): 0.250 s
- Overshoot: 2.5 %
- Steady-state error: 0.0012 m/s
-
- Step-down (1.0 -> 0 m/s):
+ Overshoot: 2.8 %
+ Steady-state error: 0.0020 rad/s
+ Step-down (1.0 -> 0 rad/s):
Settling time (2%): 0.300 s
Rebound: none
--- Assessment ---
- All metrics look good!
+ All metrics look good for both linear and rotation!
The tool prints an XML snippet with the proposed PID values that can be pasted directly
into the vehicle's ```` block.
diff --git a/docs/world_lighting.rst b/docs/world_lighting.rst
index 173cd31e..af224356 100644
--- a/docs/world_lighting.rst
+++ b/docs/world_lighting.rst
@@ -4,23 +4,28 @@ Light and shadows configuration
--------------------------------------------
-At present, the lighting model of ``mrpt-opengl`` defines
-**one directional light source** (i.e. placed at the infinity),
-with one color and three component intensities (ambient, diffuse, and specular).
-See `mrpt::opengl::TLightParameters `_
+The lighting model uses MRPT's multi-light rendering pipeline with
+**hemisphere ambient lighting**, a **directional light source** (placed at infinity)
+that casts shadows, and optional **point** and **spot** light sources.
+See `mrpt::viz::TLightParameters `_
and `mrpt-opengl `_ for further details.
-MVSim offers a number of parameters under the global `` ... `` tag
+MVSim offers a number of parameters under the global `` ... `` tag
to tune the performance and appearance of lights and shadows (all are optional).
-Light control
-================
+Directional light
+===================
+
+The primary directional light (sun-like, infinitely far away, parallel rays) is always present.
+Its direction is controlled via azimuth and elevation angles, and it is the only light that casts shadows.
- ``#ffffff``: The light color (see formatting for :ref:`%color `).
-- ``0.5``: Ambient component of the light (0 to 1).
+- ``0.8``: Diffuse intensity of the directional light (0 to 1).
-- ``45.0`` and ``70.0``:
+- ``0.6``: Specular intensity of the directional light (0 to 1).
+
+- ``45.0`` and ``70.0``:
The orbit-like azimuth and elevation angles (in **degrees**) of the directional light source.
For example, an elevation of ``90`` means a pure vertical (downwards) light.
@@ -29,12 +34,76 @@ Light control
+Ambient lighting
+=================
+
+MVSim uses **hemisphere ambient lighting**: surfaces facing up receive the sky ambient color,
+surfaces facing down receive the ground ambient color, with smooth interpolation for
+surfaces at intermediate angles. This produces a much more natural look than flat ambient,
+especially for outdoor scenes.
+
+- ``0.4``: Overall ambient intensity scale (0 to 1).
+
+- ``#e0e8ff``: The ambient color for upward-facing surfaces.
+ Default is a slight blue tint (``#e0e8ff``), simulating sky light.
+
+- ``#403a30``: The ambient color for downward-facing surfaces.
+ Default is a dark warm brown (``#403a30``), simulating ground-bounce light.
+
+To get flat (non-hemisphere) ambient lighting, set both colors to the same value (e.g. ``#ffffff``).
+
+
+Point lights
+=============
+
+Point lights emit in all directions from a position in world coordinates.
+They do **not** cast shadows. Multiple point lights can be defined by adding
+```` child elements inside ````.
+
+Each ```` supports the following child tags (all optional, shown with defaults):
+
+- ``X Y Z``: Position in world coordinates (default: ``0 0 3``).
+- ``#ffffff``: Light color in ``#RRGGBB[AA]`` format (default: white).
+- ``0.8``: Diffuse intensity (0 to 1).
+- ``0.5``: Specular intensity (0 to 1).
+- ``1.0``: Constant attenuation factor.
+- ``0.09``: Linear attenuation factor.
+- ``0.032``: Quadratic attenuation factor.
+
+The light intensity at distance *d* is: ``1 / (constant + linear*d + quadratic*d²)``.
+
+
+Spot lights
+============
+
+Spot lights emit in a cone from a position along a direction.
+They do **not** cast shadows. Multiple spot lights can be defined by adding
+```` child elements inside ````.
+
+Each ```` supports the following child tags (all optional, shown with defaults):
+
+- ``X Y Z``: Position in world coordinates (default: ``0 0 3``).
+- ``X Y Z``: Direction vector the spot points towards (default: ``0 0 -1``).
+- ``#ffffff``: Light color in ``#RRGGBB[AA]`` format (default: white).
+- ``0.8``: Diffuse intensity (0 to 1).
+- ``0.5``: Specular intensity (0 to 1).
+- ``12.5``: Inner cone half-angle in degrees (full intensity).
+- ``17.5``: Outer cone half-angle in degrees (light fades to zero).
+- ``1.0``: Constant attenuation factor.
+- ``0.09``: Linear attenuation factor.
+- ``0.032``: Quadratic attenuation factor.
+
+.. note::
+
+ Up to 8 simultaneous light sources are supported (including the primary directional light).
+ This limit is defined by the shader pipeline.
+
Shadows control
================
- ``true``. Can be used to disable casting shadows (enabled by default).
- Note that shadows may not be visible on certain ground objects, most notably, occupancy grid maps, so
+ Note that shadows may not be visible on certain ground objects, most notably, occupancy grid maps, so
shadows not being visible on grids is not a bug.
.. raw:: html
@@ -47,7 +116,7 @@ Shadows control
- ``2048``. The resolution of the `shadow map texture `_ in pixels.
Larger values will give more well-defined shadow borders, at the cost of higher GPU usage. Smaller values may slightly improve speed.
-.. list-table::
+.. list-table::
* - .. figure:: https://mrpt.github.io/mvsim-models/screenshots/shadow_map_size-512.png
@@ -67,8 +136,8 @@ Shadows control
shadows, defined by ``light_clip_plane_min``. Ideally, the smaller the range between these two numbers, the more accurate shadows will be.
-- ``1e-5``, ``1e-5``, and
- ``1e-4`` are all ``mrpt-opengl`` heuristic parameters to
+- ``1e-5``, ``1e-5``, and
+ ``1e-4`` are all ``mrpt-opengl`` heuristic parameters to
fight the "Peter-Panning" and "shadow acne" artifacts in shadow casting [Microsoft_Shadows]_.
- ``2.0``: This unitless (meter/meter)
@@ -83,18 +152,46 @@ Shadows control
.. code-block:: xml
- :caption: Light and shadow tuning parameters: example
+ :caption: Complete lighting configuration example
...
-
-
- true
-
-
+
+
160.040.0
-
+ #ffffff
+ 0.8
+ 0.6
+
+
+ 0.4
+ #e0e8ff
+ #403a30
+
+
+ true
+
+
+
+
+ 5.0 3.0 4.0
+ #ffe0a0
+ 0.6
+ 0.3
+ 0.05
+
+
+
+
+ 0.0 0.0 5.0
+ 0.0 0.0 -1.0
+ #ffffff
+ 0.7
+ 15.0
+ 25.0
+
+
...
diff --git a/examples_cpp/mvsim-subscriber-example/CMakeLists.txt b/examples_cpp/mvsim-subscriber-example/CMakeLists.txt
index 55dd0a20..18b6462e 100644
--- a/examples_cpp/mvsim-subscriber-example/CMakeLists.txt
+++ b/examples_cpp/mvsim-subscriber-example/CMakeLists.txt
@@ -3,12 +3,12 @@ project(mvsim-subscriber-example)
find_package(mvsim-comms)
find_package(mvsim-msgs)
-find_package(mrpt-obs)
+find_package(mrpt_obs)
add_executable(${PROJECT_NAME} ${PROJECT_NAME}.cpp)
target_link_libraries(${PROJECT_NAME}
mvsim::mvsim-comms
mvsim::mvsim-msgs
- mrpt::obs
+ mrpt::mrpt_obs
)
diff --git a/modules/comms/CMakeLists.txt b/modules/comms/CMakeLists.txt
index 2eeb043f..4cd28d72 100644
--- a/modules/comms/CMakeLists.txt
+++ b/modules/comms/CMakeLists.txt
@@ -28,9 +28,9 @@ target_link_libraries(${PROJECT_NAME}
${ZeroMQ_LIBRARY}
PUBLIC
${Protobuf_LIBRARIES}
- mrpt::system
- mrpt::io
- mrpt::serialization
+ mrpt::mrpt_system
+ mrpt::mrpt_io
+ mrpt::mrpt_serialization
mvsim::msgs
)
diff --git a/modules/simulator/CMakeLists.txt b/modules/simulator/CMakeLists.txt
index 9c5a69be..048e8b0d 100644
--- a/modules/simulator/CMakeLists.txt
+++ b/modules/simulator/CMakeLists.txt
@@ -150,11 +150,11 @@ target_link_libraries(${PROJECT_NAME}
PRIVATE
${DEP_MVSIM_MSGS_TRG}
PUBLIC
- mrpt::obs
- mrpt::opengl
- mrpt::maps
- mrpt::gui
- mrpt::topography
+ mrpt::mrpt_obs
+ mrpt::mrpt_opengl
+ mrpt::mrpt_maps
+ mrpt::mrpt_gui
+ mrpt::mrpt_topography
${DEP_MVSIM_COMMS_TRG}
${BOX2D_LIBRARIES}
)
diff --git a/modules/simulator/include/mvsim/Block.h b/modules/simulator/include/mvsim/Block.h
index 737a04c7..54d06493 100644
--- a/modules/simulator/include/mvsim/Block.h
+++ b/modules/simulator/include/mvsim/Block.h
@@ -15,10 +15,10 @@
#include
#include
#include
-#include
-#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -47,7 +47,7 @@ enum class GeometryType : int32_t
/** A non-vehicle "actor" for the simulation, typically obstacle blocks.
* \ingroup mvsim_simulator_module
*/
-class Block : public VisualObject, public Simulable
+class Block : public CVisualObject, public Simulable
{
public:
using Ptr = std::shared_ptr;
@@ -143,14 +143,14 @@ class Block : public VisualObject, public Simulable
/// explicitly yet. Used while parsing the shape_from_visual tag.
bool default_block_z_min_max() const;
- VisualObject* meAsVisualObject() override { return this; }
+ CVisualObject* meAsCVisualObject() override { return this; }
std::optional getElevationAt(const mrpt::math::TPoint2D& worldXY) const override;
protected:
virtual void internalGuiUpdate(
- const mrpt::optional_ref& viz,
- const mrpt::optional_ref& physical, bool childrenOnly) override;
+ const mrpt::optional_ref& viz,
+ const mrpt::optional_ref& physical, bool childrenOnly) override;
/** user-supplied index number: must be set/get'ed with setblockIndex()
* getblockIndex() (default=0) */
@@ -213,7 +213,7 @@ class Block : public VisualObject, public Simulable
b2Fixture* fixture_block_;
private:
- void internal_internalGuiUpdate_forces(mrpt::opengl::COpenGLScene& scene);
+ void internal_internalGuiUpdate_forces(mrpt::viz::Scene& scene);
void internal_parseGeometry(const rapidxml::xml_node& xml_geom_node);
@@ -242,8 +242,8 @@ class Block : public VisualObject, public Simulable
GeometryParams geomParams_;
- mrpt::opengl::CSetOfObjects::Ptr gl_block_;
- mrpt::opengl::CSetOfLines::Ptr gl_forces_;
+ mrpt::viz::CSetOfObjects::Ptr gl_block_;
+ mrpt::viz::CSetOfLines::Ptr gl_forces_;
std::mutex force_segments_for_rendering_cs_;
std::vector force_segments_for_rendering_;
@@ -253,7 +253,7 @@ class Block : public VisualObject, public Simulable
* \ingroup mvsim_simulator_module
*
*/
-class DummyInvisibleBlock : public VisualObject, public Simulable
+class DummyInvisibleBlock : public CVisualObject, public Simulable
{
public:
using Ptr = std::shared_ptr;
@@ -301,8 +301,8 @@ class DummyInvisibleBlock : public VisualObject, public Simulable
protected:
void internalGuiUpdate(
- const mrpt::optional_ref& viz,
- const mrpt::optional_ref& physical,
+ const mrpt::optional_ref& viz,
+ const mrpt::optional_ref& physical,
[[maybe_unused]] bool childrenOnly) override;
void registerOnServer(mvsim::Client& c) override
diff --git a/modules/simulator/include/mvsim/CollisionShapeCache.h b/modules/simulator/include/mvsim/CollisionShapeCache.h
index 40a49267..4c9eaf5e 100644
--- a/modules/simulator/include/mvsim/CollisionShapeCache.h
+++ b/modules/simulator/include/mvsim/CollisionShapeCache.h
@@ -7,7 +7,7 @@
| See COPYING |
+-------------------------------------------------------------------------+ */
-#include
+#include
#include
#include