Demo worlds
This page describes the worlds provided as examples ready to run within MVSim.
Note
The 3D models used in these demos belong to either the MVSim main repository or the mvsim-models repository (and downloaded automatically via Remote resources notation). In any case, each model is accompanied by its corresponding LICENSE and attribution to the author(s).
demo_friction_zones
Demonstrates per-region friction overrides using PropertyRegion elements.
A flat open area contains two zones with different ground properties:
Ice patch (left): Very low friction coefficient (
friction_mu = 0.15), causing the robot to slip.Sand patch (right): High rolling resistance (
friction_C_rr = 0.08), causing the robot to decelerate.
Each zone is visually marked with a distinct ground texture. Drive the Jackal robot over the patches to observe the effects.
mvsim launch mvsim_tutorial/demo_friction_zones.world.xml
World XML code
File: mvsim_tutorial/demo_friction_zones.world.xml
<?xml version="1.0"?>
<mvsim_world version="1.0">
<!--
Friction Zones Demo
Demonstrates per-region friction overrides using PropertyRegion elements.
A flat open area with two distinct zones:
- Ice patch (low friction coefficient, mu=0.15)
- Sand patch (high rolling resistance, C_rr=0.08)
Drive the Jackal robot over the patches to observe slipping on ice
and deceleration on sand.
-->
<simul_timestep>0</simul_timestep>
<joystick_enabled>true</joystick_enabled>
<!-- GUI options -->
<gui>
<ortho>false</ortho>
<show_forces>true</show_forces>
<cam_distance>25</cam_distance>
<fov_deg>60</fov_deg>
<refresh_fps>40</refresh_fps>
</gui>
<!-- Light parameters -->
<lights>
<enable_shadows>true</enable_shadows>
<light_azimuth_deg>-75.0</light_azimuth_deg>
<light_elevation_deg>50.0</light_elevation_deg>
</lights>
<!-- A SkyBox decoration -->
<element class='skybox'>
<textures>https://mrpt.github.io/mvsim-models/skyboxes/SunSet.zip/SunSet/SunSet%s.jpg</textures>
</element>
<!-- ================================================================
GROUND PLANE
================================================================ -->
<!-- Main grass ground -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>-25</x_min>
<y_min>-25</y_min>
<x_max>25</x_max>
<y_max>25</y_max>
<z>0.0</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/Grass01_1K_BaseColor.png</texture>
<texture_size_x>2.0</texture_size_x>
<texture_size_y>2.0</texture_size_y>
</element>
<!-- ================================================================
ICE PATCH (4x4m, centered at x=-5, y=0)
Low friction coefficient: mu=0.15
================================================================ -->
<!-- Visual: light blue surface slightly above ground -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>-7</x_min>
<y_min>-2</y_min>
<x_max>1</x_max>
<y_max>6</y_max>
<z>0.01</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/StopRoadMarking01_1K_BaseColor.png</texture>
<texture_size_x>4.0</texture_size_x>
<texture_size_y>4.0</texture_size_y>
</element>
<!-- Property region: low friction mu -->
<element class="property_region">
<property_name>friction_mu</property_name>
<value_double>0.15</value_double>
<x_min>-7</x_min>
<y_min>-2</y_min>
<z_min>-1.0</z_min>
<x_max>1</x_max>
<y_max>6</y_max>
<z_max>2.0</z_max>
</element>
<!-- ================================================================
SAND PATCH (4x4m, centered at x=5, y=0)
High rolling resistance: C_rr=0.08
================================================================ -->
<!-- Visual: sandy surface slightly above ground -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>3</x_min>
<y_min>-2</y_min>
<x_max>7</x_max>
<y_max>2</y_max>
<z>0.01</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/WhiteGravel02_512_BaseColor.png</texture>
<texture_size_x>1.0</texture_size_x>
<texture_size_y>1.0</texture_size_y>
</element>
<!-- Property region: high rolling resistance -->
<element class="property_region">
<property_name>friction_C_rr</property_name>
<value_double>0.08</value_double>
<x_min>3</x_min>
<y_min>-2</y_min>
<z_min>-1.0</z_min>
<x_max>7</x_max>
<y_max>2</y_max>
<z_max>2.0</z_max>
</element>
<!-- ================================================================
DECORATION: Palm trees
================================================================ -->
<block:class name="palm_tree">
<static>true</static>
<zmin>0.0</zmin>
<zmax>8.0</zmax>
<shape_from_visual/>
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/TropicPalmTree.zip/TropicPalmTree/free_palm.dae</model_uri>
<model_roll>90.0</model_roll>
</visual>
</block:class>
<block class="palm_tree"> <init_pose>-12 8 30</init_pose> </block>
<block class="palm_tree"> <init_pose>10 -9 60</init_pose> </block>
<block class="palm_tree"> <init_pose>-10 -10 120</init_pose> </block>
<block class="palm_tree"> <init_pose>14 7 15</init_pose> </block>
<!-- ================================================================
VEHICLE
================================================================ -->
<include file="../definitions/jackal.vehicle.xml"
default_sensors="false"
controller="twist_pid"
/>
<!-- Jackal starting position: between the two patches -->
<vehicle name="robot" class="jackal">
<init_pose>0 -6 0</init_pose>
</vehicle>
</mvsim_world>
demo_warehouse
Example of a 3D Lidar Jackal robot in a warehouse. The XML illustrates how to animate an object to make it to follow a given trajectory in a loop.
roslaunch mvsim ros1_warehouse.launch
ros2 launch mvsim demo_warehouse.launch.py
Assuming you compiled MVSim in the directory MVSIM_ROOT,
with cmake build directory build-Release, run:
cd MVSIM_ROOT
build-Release/bin/mvsim launch mvsim_tutorial/demo_warehouse.world.xml
World XML code
File: mvsim_tutorial/demo_warehouse.world.xml
<mvsim_world version="1.0">
<!-- General simulation options -->
<simul_timestep>0</simul_timestep> <!-- Simulation fixed-time interval for numerical integration [seconds] or 0 to autodetermine -->
<joystick_enabled>true</joystick_enabled>
<save_to_rawlog>$env{MVSIM_SAVE_RAWLOG_FILENAME|}</save_to_rawlog>
<!-- Optional: save all sensor data into an MRPT .rawlog dataset file: -->
<!-- <save_to_rawlog>warehouse_dataset.rawlog</save_to_rawlog> -->
<!-- If save_to_rawlog is enabled, this defines the rate in Hz to generate odometry observations -->
<!-- <rawlog_odometry_rate>20.0</rawlog_odometry_rate> -->
<!-- <save_ground_truth_trajectory>warehouse_dataset_gt.txt</save_ground_truth_trajectory> -->
<!-- GUI options -->
<gui>
<ortho>false</ortho>
<show_forces>false</show_forces> <force_scale>0.01</force_scale>
<cam_distance>15</cam_distance>
<fov_deg>60</fov_deg>
<refresh_fps>40</refresh_fps>
<cam_azimuth>170</cam_azimuth>
<cam_elevation>30</cam_elevation>
<!-- <follow_vehicle>r1</follow_vehicle> -->
</gui>
<!-- Light parameters -->
<lights>
<enable_shadows>true</enable_shadows>
<light_azimuth_deg>60.0</light_azimuth_deg>
<light_elevation_deg>75.0</light_elevation_deg>
<!-- <eye_distance_to_shadow_map_extension>2</eye_distance_to_shadow_map_extension> -->
<!-- <minimum_shadow_map_extension_ratio>0.005</minimum_shadow_map_extension_ratio> -->
</lights>
<variable name="CEILING_HEIGHT" value="6.0"></variable>
<!-- ========================
Scenario definition
======================== -->
<!-- ground -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>-15</x_min> <y_min>-13</y_min>
<x_max> 20</x_max> <y_max> 13</y_max>
<z>0.0</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/concrete-ground-1.jpg</texture>
<texture_size_x>2.0</texture_size_x>
<texture_size_y>2.0</texture_size_y>
</element>
<!-- ceiling -->
<element class="horizontal_plane">
<cull_face>FRONT</cull_face>
<x_min>-15</x_min> <y_min>-13</y_min>
<x_max> 20</x_max> <y_max> 13</y_max>
<z>$f{CEILING_HEIGHT}</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/BathroomTiles03_1K_BaseColor.png</texture>
<texture_size_x>3.0</texture_size_x>
<texture_size_y>3.0</texture_size_y>
</element>
<!-- perimeter walls: -->
<element class="vertical_plane">
<cull_face>FRONT</cull_face>
<x0>-15</x0> <y0>13</y0>
<x1>-15</x1> <y1>-13</y1>
<z>0.0</z> <height>$f{CEILING_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>3.0</texture_size_x>
<texture_size_y>3.0</texture_size_y>
</element>
<element class="vertical_plane">
<cull_face>FRONT</cull_face>
<x0> 20</x0> <y0>13</y0>
<x1>-15</x1> <y1>13</y1>
<z>0.0</z> <height>$f{CEILING_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>3.0</texture_size_x>
<texture_size_y>3.0</texture_size_y>
</element>
<element class="vertical_plane">
<cull_face>FRONT</cull_face>
<x0> 20</x0> <y0>-13</y0>
<x1> 20</x1> <y1>13</y1>
<z>0.0</z> <height>$f{CEILING_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>3.0</texture_size_x>
<texture_size_y>3.0</texture_size_y>
</element>
<element class="vertical_plane">
<cull_face>FRONT</cull_face>
<x0>-15</x0> <y0>-13</y0>
<x1> 20</x1> <y1>-13</y1>
<z>0.0</z> <height>$f{CEILING_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>3.0</texture_size_x>
<texture_size_y>3.0</texture_size_y>
</element>
<!-- =============================
Vehicle classes definition
============================= -->
<include file="../definitions/jackal.vehicle.xml"
default_sensors="true"
lidar2d_raytrace="true"
/>
<!-- lidar2d_raytrace: Use accurate 3D raytrace mode for the 2D lidar sensor too -->
<!-- ========================
Vehicle(s) definition
======================== -->
<vehicle name="r1" class="jackal">
<init_pose>0 0 0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
</vehicle>
<!-- ======================================
Object types
====================================== -->
<block:class name="shelf">
<static>true</static> <!-- Does not move -->
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model. 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/shelf_big_moveai.zip/shelf_big_moveai/shelf_big_movai.dae</model_uri>
<model_roll>90.0</model_roll>
</visual>
</block:class>
<block:class name="stairs">
<static>true</static> <!-- Does not move -->
<zmin>0.0</zmin> <zmax>0.5</zmax>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model. 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/metal-stairs.dae</model_uri>
<model_offset_z>4.31</model_offset_z>
<model_roll>90.0</model_roll>
</visual>
</block:class>
<block:class name="tote">
<mass>6</mass> <ground_friction>0.1</ground_friction>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model. 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/tote.dae</model_uri>
<model_roll>90.0</model_roll>
</visual>
</block:class>
<block:class name="pallet">
<mass>2</mass> <ground_friction>0.1</ground_friction>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model. 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/pallet.zip/pallet/pallet.dae</model_uri>
<model_roll>90.0</model_roll>
</visual>
</block:class>
<block:class name="pallet_jack">
<mass>20</mass> <ground_friction>1.0</ground_friction>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model. 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/pallet_jack.zip/pallet_jack/pallet_jack.dae</model_uri>
<model_roll>90.0</model_roll>
</visual>
</block:class>
<block:class name="chair_x3">
<mass>6</mass> <ground_friction>0.1</ground_friction>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model. 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/chair_x3.dae</model_uri>
<model_roll>90.0</model_roll>
</visual>
</block:class>
<block:class name="extinguisher">
<static>true</static> <!-- Does not move -->
<mass>2</mass> <ground_friction>1</ground_friction>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model. 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/extinguisher.zip/extinguisher/extinguisher.dae</model_uri>
<model_roll>90.0</model_roll>
</visual>
</block:class>
<block:class name="my_ramp">
<static>true</static> <!-- Does not move -->
<intangible>true</intangible> <!-- Does not generate collisions -->
<color>#707070</color>
<shape_from_visual/> <!-- automatic collision shape from 3D model -->
<geometry type="ramp" lx="2.0" ly="1.0" lz="0.25" />
</block:class>
<block:class name="my_bump">
<static>true</static> <!-- Does not move -->
<intangible>true</intangible> <!-- Does not generate collisions -->
<color>#707070</color>
<zmin>0</zmin> <zmax>0.02</zmax>
<shape_from_visual/> <!-- automatic collision shape from 3D model -->
<geometry type="semi_cylinder_bump" lx="1.0" ly="0.20" lz="0.02" />
</block:class>
<!-- ======================================
Object instances
====================================== -->
<!-- You can assign an optional custom name to each object, as an attribute to block, like name="shelf_001", etc. -->
<!-- All coordinates are global coords:
SE(2) <init_pose>x y yaw(deg)</init_pose> or
SE(3) <init_pose3d>x y z yaw(deg) pitch(deg) roll(deg)</init_pose3d>
-->
<block class="shelf"> <init_pose>0 5 0</init_pose> </block>
<block class="shelf"> <init_pose>0 9 180</init_pose> </block>
<block class="shelf"> <init_pose>0 -5 0</init_pose> </block>
<block class="shelf"> <init_pose>0 -9 180</init_pose> </block>
<block class="shelf"> <init_pose>12 0 90</init_pose> </block>
<block class="shelf"> <init_pose>17 0 -90</init_pose> </block>
<block class="pallet_jack"> <init_pose>3 3 0</init_pose> </block>
<block class="pallet_jack"> <init_pose>-12.5 11.5 -10</init_pose> </block>
<block class="pallet_jack"> <init_pose>-11 12 80</init_pose> </block>
<!-- <block class="my_ramp"> <init_pose>2 2 0</init_pose> </block>
<block class="my_ramp"> <init_pose>6 2 180</init_pose> </block> -->
<!-- <block class="my_bump"> <init_pose>4 0 90</init_pose> </block> -->
<block class="stairs"> <init_pose>-12 -11.5 -90</init_pose> </block>
<block class="stairs"> <init_pose> 15 11.5 90</init_pose> </block>
<block class="tote"> <init_pose>-2 3 -40</init_pose> </block>
<block class="tote"> <init_pose> 2 3 10</init_pose> </block>
<block class="pallet"> <init_pose>10.4 -1.1 85</init_pose> </block>
<block class="pallet"> <init_pose>10.3 -2.3 91</init_pose> </block>
<block class="pallet"> <init_pose>10.5 1.15 80</init_pose> </block>
<block class="pallet"> <init_pose>10.2 0.1 86</init_pose> </block>
<for var="iX" from="0" to="2">
<for var="iY" from="0" to="1">
<block class="pallet">
<init_pose>$f{-7.9+iX*1.3} $f{0.9*iY+2} 0</init_pose>
</block>
</for>
</for>
<block class="chair_x3"> <init_pose>-14.5 1 90</init_pose> </block>
<block class="chair_x3"> <init_pose>-14.5 3 90</init_pose> </block>
<block class="extinguisher"> <init_pose3d>-14.8 12 1.1 90 0 0</init_pose3d> </block>
<block class="extinguisher"> <init_pose3d> 6.5 12.9 1.1 0 0 0</init_pose3d> </block>
<block class="extinguisher"> <init_pose3d> 2.5 -12.9 1.1 180 0 0</init_pose3d> </block>
<!-- A Pallet that moves on its own on a corridor -->
<block class="pallet_jack">
<init_pose>0 0 0</init_pose>
<animation type="keyframes">
<time_pose>0.0 -9.4 12 0</time_pose>
<time_pose>10.0 5 12 0</time_pose>
<time_pose>11.0 5 12 0</time_pose>
<time_pose>14.0 5 12 180</time_pose>
<time_pose>24.0 -9.4 12 180</time_pose>
<time_pose>25.0 -9.4 12 180</time_pose>
<time_pose>26.0 -9.4 12 0</time_pose>
</animation>
</block>
<!-- A human actor moving around in the scene, demonstrating animation features -->
<actor:class name="pedestrian">
<walking_speed>1.4</walking_speed>
<running_speed>3.5</running_speed>
<height>1.75</height>
<collision_radius>0.3</collision_radius>
<animation_idle>HumanArmature|Man_Idle</animation_idle>
<animation_walk>HumanArmature|Man_Walk</animation_walk>
<animation_run>HumanArmature|Man_Run</animation_run>
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/AnimatedMenCharacters.zip/FBX/Male_Shirt.fbx</model_uri>
<model_scale>0.0027</model_scale>
<model_roll>90.0</model_roll>
<model_yaw>90.0</model_yaw>
</visual>
</actor:class>
<actor name="person1" class="pedestrian">
<init_pose>-7.8 -3.3 90</init_pose>
<path loop="true">
<!-- x y yaw_deg -->
<waypoint pause="2.0">-7.8 -3.3 -90</waypoint>
<waypoint pause="3.0" animation="run">-3.1 -3.2 -90</waypoint>
<waypoint pause="3.0">3.8 -3.3 -90</waypoint>
<waypoint pause="2.0" animation="run">6.7 3.6 90</waypoint>
<waypoint pause="3.0">1.1 -3.2 -90</waypoint>
</path>
</actor>
</mvsim_world>
demo_road_circuit1
Example of two Jackal robots with cameras and 3D LiDARs in a 2.5 world, including ramps, road bumps, and a bridge.
For ROS, note that having multiple robots uses namespaces even for /tf, hence the remappings (see the launch file)
needed for RViz to show the sensors and send /cmd_vel commands.
ros2 launch mvsim demo_road_circuit1.launch.py
Assuming you compiled MVSim in the directory MVSIM_ROOT,
with cmake build directory build-Release, run:
cd MVSIM_ROOT
build-Release/bin/mvsim launch mvsim_tutorial/demo_road_circuit1.world.xml
World XML code
File: mvsim_tutorial/demo_road_circuit1.world.xml
<mvsim_world version="1.0">
<!-- General simulation options -->
<simul_timestep>0</simul_timestep> <!-- Simulation fixed-time interval for numerical integration [seconds] or 0 to autodetermine -->
<!-- GUI options -->
<gui>
<ortho>false</ortho>
<show_forces>false</show_forces> <force_scale>0.01</force_scale>
<cam_distance>50</cam_distance>
<cam_azimuth>150</cam_azimuth>
<cam_elevation>75</cam_elevation>
<fov_deg>80</fov_deg>
<!-- <follow_vehicle>r1</follow_vehicle> -->
</gui>
<!-- Light parameters -->
<lights>
<enable_shadows>true</enable_shadows>
<light_azimuth_deg>-25.0</light_azimuth_deg>
<light_elevation_deg>40.0</light_elevation_deg>
</lights>
<!-- ========================
Scenario definition
======================== -->
<!-- ForestFloor01_1K_BaseColor
ForestGround01_1K_BaseColor
Grass01_1K_BaseColor
Pebbles02_512_BaseColor
https://mrpt.github.io/mvsim-models/textures-cgbookcase/TwoLaneRoadCracks01_1K_BaseColor.png
https://mrpt.github.io/mvsim-models/textures-cgbookcase/TwoLaneRoadCracks01_1K_Turn90_BaseColor.png
-->
<element class='elevation_map'>
<resolution>4.0</resolution>
<elevation_data_matrix>[3e-2 3e-2; 2e-2 1e-2;1e-2 2e-2;4e-2 2e-2;3e-2 1e-2;5e-2 2e-2;3e-2 1e-2;3e-2 1e-2;1e-2 5e-2;1e-2 2e-2;1e-2 2e-2;1e-2 2e-2;1e-2 1e-2]</elevation_data_matrix>
<texture_image>https://mrpt.github.io/mvsim-models/textures-cgbookcase/TwoLaneRoadCracks01_1K_BaseColor.png</texture_image>
<texture_image_rotate>-90</texture_image_rotate>
<texture_extension_x>8.0</texture_extension_x>
<texture_extension_y>4.0</texture_extension_y>
<corner_min_x>-24</corner_min_x>
<corner_min_y>-2</corner_min_y>
<model_split_size>3.0</model_split_size> <!-- See docs. Required for correct z-order rendering if there are transparent objects in the world (e.g. trees with leaves) -->
</element>
<element class='elevation_map'>
<resolution>4.0</resolution>
<elevation_data_matrix>[1e-2 1e-2; 1e-2 1e-2]</elevation_data_matrix>
<texture_image>https://mrpt.github.io/mvsim-models/textures-cgbookcase/TwoLaneRoadCracks01_1K_Turn90_BaseColor.png</texture_image>
<texture_image_rotate>-90</texture_image_rotate>
<texture_extension_x>4.0</texture_extension_x>
<texture_extension_y>4.0</texture_extension_y>
<corner_min_x>24</corner_min_x>
<corner_min_y>-2</corner_min_y>
</element>
<element class='elevation_map'>
<resolution>4.0</resolution>
<elevation_data_matrix>[1e-2 1e-2 2e-2 1e-2 1e-2 1e-2 4e-2 4e-2 1e-2; 1e-2 3e-2 2e-2 1e-2 4e-2 1e-2 1e-2 1e-2 1e-2]</elevation_data_matrix>
<texture_image>https://mrpt.github.io/mvsim-models/textures-cgbookcase/TwoLaneRoadCracks01_1K_BaseColor.png</texture_image>
<texture_image_rotate>0</texture_image_rotate>
<texture_extension_x>4.0</texture_extension_x>
<texture_extension_y>8.0</texture_extension_y>
<corner_min_x>24</corner_min_x>
<corner_min_y>2</corner_min_y>
<model_split_size>3.0</model_split_size> <!-- See docs. Required for correct z-order rendering if there are transparent objects in the world (e.g. trees with leaves) -->
</element>
<element class='elevation_map'>
<resolution>4.0</resolution>
<elevation_data_matrix>[1e-2 1e-2; 1e-2 1e-2]</elevation_data_matrix>
<texture_image>https://mrpt.github.io/mvsim-models/textures-cgbookcase/TwoLaneRoadCracks01_1K_Turn90_BaseColor.png</texture_image>
<texture_image_rotate>0</texture_image_rotate>
<texture_extension_x>4.0</texture_extension_x>
<texture_extension_y>4.0</texture_extension_y>
<corner_min_x>24</corner_min_x>
<corner_min_y>34</corner_min_y>
</element>
<element class='elevation_map'>
<resolution>4.0</resolution>
<elevation_data_matrix>[3e-2 3e-2; 2e-2 1e-2;1e-2 2e-2;4e-2 2e-2;3e-2 1e-2;5e-2 2e-2;3e-2 1e-2;3e-2 1e-2;1e-2 5e-2;1e-2 2e-2;1e-2 2e-2;1e-2 2e-2;1e-2 1e-2]</elevation_data_matrix>
<texture_image>https://mrpt.github.io/mvsim-models/textures-cgbookcase/TwoLaneRoadCracks01_1K_BaseColor.png</texture_image>
<texture_image_rotate>-90</texture_image_rotate>
<texture_extension_x>8.0</texture_extension_x>
<texture_extension_y>4.0</texture_extension_y>
<corner_min_x>-24</corner_min_x>
<corner_min_y>34</corner_min_y>
<model_split_size>3.0</model_split_size> <!-- See docs. Required for correct z-order rendering if there are transparent objects in the world (e.g. trees with leaves) -->
</element>
<element class='elevation_map'>
<resolution>4.0</resolution>
<elevation_data_matrix>[1e-2 1e-2 2e-2 1e-2 1e-2 1e-2 4e-2 4e-2 1e-2; 1e-2 3e-2 2e-2 1e-2 4e-2 1e-2 1e-2 1e-2 1e-2]</elevation_data_matrix>
<texture_image>https://mrpt.github.io/mvsim-models/textures-cgbookcase/TwoLaneRoadCracks01_1K_BaseColor.png</texture_image>
<texture_image_rotate>0</texture_image_rotate>
<texture_extension_x>4.0</texture_extension_x>
<texture_extension_y>8.0</texture_extension_y>
<corner_min_x>-28</corner_min_x>
<corner_min_y>2</corner_min_y>
<model_split_size>3.0</model_split_size> <!-- See docs. Required for correct z-order rendering if there are transparent objects in the world (e.g. trees with leaves) -->
</element>
<element class='elevation_map'>
<resolution>4.0</resolution>
<elevation_data_matrix>[1e-2 1e-2; 1e-2 1e-2]</elevation_data_matrix>
<texture_image>https://mrpt.github.io/mvsim-models/textures-cgbookcase/TwoLaneRoadCracks01_1K_Turn90_BaseColor.png</texture_image>
<texture_image_rotate>180</texture_image_rotate>
<texture_extension_x>4.0</texture_extension_x>
<texture_extension_y>4.0</texture_extension_y>
<corner_min_x>-28</corner_min_x>
<corner_min_y>-2</corner_min_y>
</element>
<element class='elevation_map'>
<resolution>4.0</resolution>
<elevation_data_matrix>[1e-2 1e-2; 1e-2 1e-2]</elevation_data_matrix>
<texture_image>https://mrpt.github.io/mvsim-models/textures-cgbookcase/TwoLaneRoadCracks01_1K_Turn90_BaseColor.png</texture_image>
<texture_image_rotate>90</texture_image_rotate>
<texture_extension_x>4.0</texture_extension_x>
<texture_extension_y>4.0</texture_extension_y>
<corner_min_x>-28</corner_min_x>
<corner_min_y>34</corner_min_y>
</element>
<element class="horizontal_plane">
<x_min>2</x_min> <y_min>26</y_min>
<x_max>6</x_max> <y_max>46</y_max>
<z>4.02</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/PavingStone11_1K_BaseColor.png</texture>
<texture_size_x>1.0</texture_size_x>
<texture_size_y>1.0</texture_size_y>
</element>
<!-- Disabled: TODO: fix collisions at different heights
<block>
<static>true</static>
<color>#e0e0e0</color>
<zmin>0.10</zmin> <zmax>1.0</zmax>
<shape_from_visual/>
<geometry type="box" lx="0.07" ly="20.0" lz="0.75"/>
<init_pose3d>2.0 26.0 3.9 0 0 0</init_pose3d>
<skip_elevation_adjust>true</skip_elevation_adjust>
</block>
<block>
<static>true</static>
<color>#e0e0e0</color>
<zmin>0.10</zmin> <zmax>1.0</zmax>
<shape_from_visual/>
<geometry type="box" lx="0.07" ly="20.0" lz="0.75"/>
<init_pose3d>6.0 26.0 3.9 0 0 0</init_pose3d>
<skip_elevation_adjust>true</skip_elevation_adjust>
</block>
-->
<element class='elevation_map'>
<resolution>8.0</resolution>
<elevation_data_matrix>
[0 0.05 0 0.05 0;
0.05 0.8 1.5 2 0.05;
0 0.7 2.5 3 0;
0 1 3 4 0;
0 0.7 2.9 4 0;
0.05 1.5 0.5 2 0.05;
0 0.02 0 0.05 0
]</elevation_data_matrix>
<texture_image>https://mrpt.github.io/mvsim-models/textures-cgbookcase/Dirt02_1K_BaseColor.png</texture_image>
<texture_image_rotate>0</texture_image_rotate>
<texture_extension_x>3.0</texture_extension_x>
<texture_extension_y>3.0</texture_extension_y>
<corner_min_x>-24</corner_min_x>
<corner_min_y>2</corner_min_y>
<model_split_size>3.0</model_split_size> <!-- See docs. Required for correct z-order rendering if there are transparent objects in the world (e.g. trees with leaves) -->
</element>
<element class='elevation_map'>
<resolution>4.0</resolution>
<elevation_data_matrix>
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
2 2.5 3.2 3.9 3 3.2 3.5 3.8 2.8 3.1 2.3 3.7 4.5 3.4 2.8 3.7 2.9 4.0 0 0;
3 4.3 4.7 5 3.4 4.8 4.9 5.5 4.2 4.4 3.8 5.8 5.4 4.5 3.9 4.3 4.1 5.2 0 1
]</elevation_data_matrix>
<texture_image>https://mrpt.github.io/mvsim-models/textures-cgbookcase/Pebbles02_512_BaseColor.png</texture_image>
<texture_image_rotate>0</texture_image_rotate>
<texture_extension_x>3.0</texture_extension_x>
<texture_extension_y>3.0</texture_extension_y>
<corner_min_x>-44</corner_min_x>
<corner_min_y>-36</corner_min_y>
<model_split_size>3.0</model_split_size> <!-- See docs. Required for correct z-order rendering if there are transparent objects in the world (e.g. trees with leaves) -->
</element>
<element class='elevation_map'>
<resolution>8.0</resolution>
<elevation_data_matrix>
[0 1 4 30;
0 3 3 25;
0 3 3 25;
0 3 3 25;
0 3 3 25;
0 4 2.5 28;
0 4 3 30;
0 4 2.9 29;
0 1 0 27;
0 1 0 27;
0 1 0 27;
0 1 5.4 27;
1 1 5.8 25
]</elevation_data_matrix>
<texture_image>https://mrpt.github.io/mvsim-models/textures-cgbookcase/Dirt02_1K_BaseColor.png</texture_image>
<texture_image_rotate>0</texture_image_rotate>
<texture_extension_x>3.0</texture_extension_x>
<texture_extension_y>3.0</texture_extension_y>
<corner_min_x>-44</corner_min_x>
<corner_min_y>38</corner_min_y>
<model_split_size>3.0</model_split_size> <!-- See docs. Required for correct z-order rendering if there are transparent objects in the world (e.g. trees with leaves) -->
</element>
<block:class name="support_column">
<static>true</static> <!-- Does not move -->
<color>#606060</color>
<zmin>0</zmin> <zmax>4.0</zmax>
<shape_from_visual/> <!-- automatic collision shape from 3D model -->
<geometry type="cylinder" radius="0.10" length="4.0" vertex_count="16"/>
<skip_elevation_adjust>true</skip_elevation_adjust>
</block:class>
<block class="support_column"> <init_pose>2.1 41 0</init_pose> </block>
<block class="support_column"> <init_pose>2.1 32 0</init_pose> </block>
<block class="support_column"> <init_pose>5.9 41 0</init_pose> </block>
<block class="support_column"> <init_pose>5.9 32 0</init_pose> </block>
<!-- A SkyBox decoration -->
<element class='skybox'>
<!-- Provide the URI printf-like "pattern" to the six texture files,
such that replacing "%s" with the following strings gives the path
to the files: "Up", "Right", "Left", "Front", "Down", "Back".
-->
<textures>https://mrpt.github.io/mvsim-models/skyboxes/TropicalSunnyDay.zip/TropicalSunnyDay/TropicalSunnyDay%s.jpg</textures>
</element>
<!-- =============================
Vehicle classes definition
============================= -->
<include file="../definitions/jackal.vehicle.xml"
default_sensors="false"
/>
<!-- ========================
Vehicle(s) definition
======================== -->
<vehicle name="r1" class="jackal">
<init_pose>0 -1 0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/robot-agricobiot2/mast.dae</model_uri>
<model_offset_x>0</model_offset_z>
<model_offset_y>0</model_offset_y>
<model_offset_z>0.10</model_offset_z>
<model_yaw>180.0</model_yaw>
<model_pitch>0.0</model_pitch>
<model_roll>90.0</model_roll>
</visual>
<!-- Sensors -->
<include file="../definitions/velodyne-vlp16.sensor.xml"
sensor_x="-0.08" sensor_y="0" sensor_z="0.97" sensor_yaw="0"
sensor_std_noise="0.005"
sensor_publish="false"
sensor_name="lidar1"
sensor_rpm="600"
horz_resolution_factor="2.0"
vert_resolution_factor="2.0"
/>
<include file="../definitions/camera.sensor.xml"
sensor_x="0.03" sensor_z="0.83"
ncols="800" nrows="600"
cx="400" cy="300"
sensor_period_sec="0.10"
/>
</vehicle>
<vehicle name="r2" class="jackal">
<init_pose>10 37 -180</init_pose> <!-- In global coords: x,y, yaw(deg) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/robot-agricobiot2/mast.dae</model_uri>
<model_offset_x>0</model_offset_z>
<model_offset_y>0</model_offset_y>
<model_offset_z>0.10</model_offset_z>
<model_yaw>180.0</model_yaw>
<model_pitch>0.0</model_pitch>
<model_roll>90.0</model_roll>
</visual>
<!-- Sensors -->
<include file="../definitions/velodyne-vlp16.sensor.xml"
sensor_x="-0.08" sensor_y="0" sensor_z="0.97" sensor_yaw="0"
sensor_std_noise="0.005"
sensor_publish="false"
sensor_name="lidar1"
sensor_rpm="600"
horz_resolution_factor="2.0"
vert_resolution_factor="2.0"
/>
<include file="../definitions/camera.sensor.xml"
sensor_x="0.03" sensor_z="0.83"
ncols="800" nrows="600"
cx="400" cy="300"
sensor_period_sec="0.10"
/>
</vehicle>
<!-- ======================================
Obstacle blocks classes definition
====================================== -->
<block:class name="rock_01">
<static>true</static> <!-- Does not move -->
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<zmin>0.0</zmin> <zmax>2.5</zmax> <!-- Only count collisions in this height range -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/rock01.zip/rock01/FallingRock01.dae</model_uri>
<model_scale>3.0</model_scale>
</visual>
</block:class>
<block:class name="rock_02">
<static>true</static> <!-- Does not move -->
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<zmin>0.0</zmin> <zmax>2.5</zmax> <!-- Only count collisions in this height range -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/rock02.zip/rock02/FallingRock02.dae</model_uri>
<model_scale>2.6</model_scale>
</visual>
</block:class>
<block:class name="palm_tree_01">
<static>true</static> <!-- Does not move -->
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<zmin>0.0</zmin> <zmax>0.5</zmax> <!-- Only count collisions in this height range -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/TropicPalmTree.zip/TropicPalmTree/free_palm.dae</model_uri>
<model_roll>90</model_roll>
<model_split_size>1.50</model_split_size> <!-- See docs. Required for transparent leaves -->
</visual>
</block:class>
<block:class name="construction_cone">
<static>false</static>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<zmin>0.0</zmin> <zmax>0.5</zmax> <!-- Only count collisions in this height range -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/ConstructionCone.zip/ConstructionCone/construction_cone.dae</model_uri>
<model_roll>90</model_roll>
<model_scale>5</model_scale>
</visual>
</block:class>
<block:class name="police_station">
<static>true</static>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/PoliceStation.zip/PoliceStation/police_station.dae</model_uri>
<model_roll>90</model_roll>
</visual>
</block:class>
<block:class name="radio_tower">
<static>true</static>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/RadioTower.zip/RadioTower/radio_tower.dae</model_uri>
<model_roll>90</model_roll>
<model_scale>0.8</model_scale>
</visual>
<skip_elevation_adjust>true</skip_elevation_adjust>
</block:class>
<block:class name="my_bump">
<static>true</static> <!-- Does not move -->
<intangible>true</intangible> <!-- Does not generate collisions -->
<color>#707070</color>
<zmin>0</zmin> <zmax>0.02</zmax>
<shape_from_visual/> <!-- automatic collision shape from 3D model -->
<geometry type="semi_cylinder_bump" lx="2.0" ly="0.20" lz="0.02" />
</block:class>
<!-- ========================
Obstacle blocks
======================== -->
<block class="construction_cone"> <init_pose3d>6 -2.5 0 0 0 0</init_pose3d> </block>
<block class="construction_cone"> <init_pose3d>28 -3 0 0 0 0</init_pose3d> </block>
<block class="my_bump"> <init_pose3d>8 -1 0.01 90 0 0</init_pose3d> </block>
<block class="police_station"> <init_pose3d>30 -18 0.01 0 0 0</init_pose3d> </block>
<block class="radio_tower"> <init_pose3d>40 15 0.01 0 0 0</init_pose3d> </block>
<block class="palm_tree_01"> <init_pose3d>-5 -10 20 30 0 0</init_pose3d> </block>
<block class="palm_tree_01"> <init_pose3d>39 -2 20 10 0 0</init_pose3d> </block>
<block class="palm_tree_01"> <init_pose3d>37 3 20 30 0 0</init_pose3d> </block>
<block class="palm_tree_01"> <init_pose3d>38 -6 20 -50 0 0</init_pose3d> </block>
<block class="palm_tree_01"> <init_pose3d>41 40 20 -30 0 0</init_pose3d> </block>
<block class="palm_tree_01"> <init_pose3d>44 43 20 -30 0 0</init_pose3d> </block>
<block class="palm_tree_01"> <init_pose3d>-1 50 20 20 0 0</init_pose3d> </block>
<block class="palm_tree_01"> <init_pose3d>4 51 20 90 0 0</init_pose3d> </block>
<block class="palm_tree_01"> <init_pose3d>-33 35 20 80 0 0</init_pose3d> </block>
<block class="palm_tree_01"> <init_pose3d>-38 31 20 50 0 0</init_pose3d> </block>
<block class="palm_tree_01"> <init_pose3d>-31 27 20 10 0 0</init_pose3d> </block>
<variable name="ROCKS_SPREAD_X" value="2.0"></variable>
<variable name="ROCKS_SPREAD_Y" value="35.0"></variable>
<variable name="ROCKS_SPREAD_Z" value="1.0"></variable>
<!-- ensure reproducible randomized numbers from the same seed -->
<variable name="dummy" value="$f{randomize(2)}"></variable>
<for var="i" from="1" to="20">
<block class="rock_01"> <init_pose3d>$f{(-0.5+rand())*ROCKS_SPREAD_X+49.3} $f{-35+i*4.2+rand()*1.3} 6 $f{-180+rand()*360} 0 0</init_pose3d> </block>
</for>
<for var="i" from="1" to="10">
<block class="rock_01"> <init_pose3d>$f{rand()*60-40} $f{rand()*25-30} 16 $f{-180+rand()*360} 0 0</init_pose3d> </block>
</for>
<for var="i" from="1" to="8">
<block class="rock_02"> <init_pose3d>$f{rand()*40-20} $f{rand()*15+7} 16 $f{-180+rand()*360} 0 0</init_pose3d> </block>
</for>
</mvsim_world>
demo_indoor_outdoor
Example of a 3D Lidar Jackal robot in a world mixing indoor and outdoor scenarios. The GNSS sensor only works while outdoors.
ros2 launch mvsim demo_indoor_outdoor.launch.py
Assuming you compiled MVSim in the directory MVSIM_ROOT,
with cmake build directory build-Release, run:
cd MVSIM_ROOT
build-Release/bin/mvsim launch mvsim_tutorial/demo_indoor_outdoor.world.xml
World XML code
File: mvsim_tutorial/demo_indoor_outdoor.world.xml
<?xml version="1.0"?>
<mvsim_world version="1.0">
<!--
Sensor Fusion Testing World
This world is designed for testing sensor fusion algorithms in challenging scenarios:
- Large outdoor terrain with asymmetric hills at corners
- Central indoor room with furniture and windows
- Two corridors: one straight (15m), one with 90-degree turn
- GNSS-denied areas in corridors and indoor room
- Tests: 2D lidar, 3D lidar, GNSS, IMU, odometry
Features:
- Terrain with asymmetric elevation changes at corners
- Palm trees and sparse vegetation for visual features
- Transparent ceiling for light penetration
- Proper wall thickness (0.2m)
-->
<simul_timestep>0</simul_timestep>
<joystick_enabled>true</joystick_enabled>
<save_to_rawlog>$env{MVSIM_SAVE_RAWLOG_FILENAME|}</save_to_rawlog>
<!-- Georeference for GNSS simulation -->
<georeference>
<latitude>40.1234</latitude>
<longitude>-74.5678</longitude>
<height>100.0</height>
<world_to_enu_rotation_deg>0.0</world_to_enu_rotation_deg>
</georeference>
<!-- GUI options -->
<gui>
<ortho>false</ortho>
<show_forces>false</show_forces>
<cam_distance>50</cam_distance>
<fov_deg>60</fov_deg>
<refresh_fps>40</refresh_fps>
</gui>
<!-- Light parameters -->
<lights>
<enable_shadows>true</enable_shadows>
<light_azimuth_deg>45.0</light_azimuth_deg>
<light_elevation_deg>60.0</light_elevation_deg>
</lights>
<!-- Variables for easy configuration -->
<variable name="WALL_THICKNESS" value="0.2"></variable>
<variable name="WALL_HEIGHT" value="2.5"></variable>
<variable name="INDOOR_ROOM_SIZE" value="10.0"></variable>
<variable name="CORRIDOR_STRAIGHT_LENGTH" value="20.0"></variable>
<variable name="CORRIDOR_WIDTH" value="1.6"></variable>
<variable name="TERRAIN_RANGE" value="37.5"></variable>
<variable name="TERRAIN_HILL_HEIGHT" value="2.5"></variable>
<!-- A SkyBox decoration -->
<element class='skybox'>
<!-- Provide the URI printf-like "pattern" to the six texture files,
such that replacing "%s" with the following strings gives the path
to the files: "Up", "Right", "Left", "Front", "Down", "Back".
-->
<textures>https://mrpt.github.io/mvsim-models/skyboxes/SunSet.zip/SunSet/SunSet%s.jpg</textures>
</element>
<!-- ================================================================
OUTDOOR TERRAIN (75x75 meters)
================================================================ -->
<!-- Terrain elevation map with asymmetric hills at corners -->
<!-- PNG elevation map: grayscale image where pixel value represents height -->
<!-- Value range: 0-255 mapped to 0-10 meters elevation -->
<element class="elevation_map">
<elevation_image>sensor_fusion_terrain.png</elevation_image>
<elevation_image_min_z>0.0</elevation_image_min_z>
<elevation_image_max_z>4.0</elevation_image_max_z>
<texture_image>https://mrpt.github.io/mvsim-models/textures-cgbookcase/Grass01_1K_BaseColor.png</texture_image>
<texture_size_x>1.5</texture_size_x>
<texture_size_y>1.5</texture_size_y>
<corner_min_x>-37.5</corner_min_x>
<corner_min_y>-37.5</corner_min_y>
<model_split_size>3.0</model_split_size>
</element>
<block:class name="radio_tower">
<static>true</static>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/RadioTower.zip/RadioTower/radio_tower.dae</model_uri>
<model_roll>90</model_roll>
<model_scale>0.4</model_scale>
</visual>
<skip_elevation_adjust>true</skip_elevation_adjust>
</block:class>
<block class="radio_tower"> <init_pose3d>1 20 0.01 0 0 0</init_pose3d> </block>
<!-- ================================================================
OUTDOOR VEGETATION
================================================================ -->
<!-- Palm tree class -->
<block:class name="palm_tree">
<static>true</static>
<zmin>0.0</zmin>
<zmax>8.0</zmax>
<shape_from_visual/>
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/TropicPalmTree.zip/TropicPalmTree/free_palm.dae</model_uri>
<model_roll>90.0</model_roll>
</visual>
</block:class>
<block class="palm_tree"> <init_pose3d>-30 -29 5.0 10 0 0</init_pose3d> </block>
<block class="palm_tree"> <init_pose3d>-31 -19 5.0 45 0 0</init_pose3d> </block>
<block class="palm_tree"> <init_pose3d>-26 -25 5.0 30 0 0</init_pose3d> </block>
<block class="palm_tree"> <init_pose3d>-15 -14 5.0 80 0 0</init_pose3d> </block>
<block class="palm_tree"> <init_pose3d>-20 15 5.0 90 0 0</init_pose3d> </block>
<block class="palm_tree"> <init_pose3d>-34 34 5.0 20 0 0</init_pose3d> </block>
<block class="palm_tree"> <init_pose3d> 17 30 5.0 -20 0 0</init_pose3d> </block>
<block class="palm_tree"> <init_pose3d> 2 -22 5.0 33 0 0</init_pose3d> </block>
<block class="palm_tree"> <init_pose3d>31 -21 5.0 94 0 0</init_pose3d> </block>
<block class="palm_tree"> <init_pose3d>34 -20 5.0 2 0 0</init_pose3d> </block>
<!-- ================================================================
INDOOR ROOM (15x15) AT CENTER
================================================================ -->
<!-- Indoor floor -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>-$f{0.5*INDOOR_ROOM_SIZE}</x_min>
<y_min>-$f{0.5*INDOOR_ROOM_SIZE}</y_min>
<x_max>$f{0.5*INDOOR_ROOM_SIZE}</x_max>
<y_max>$f{0.5*INDOOR_ROOM_SIZE}</y_max>
<z>0.02</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/BathroomTiles03_1K_BaseColor.png</texture>
<texture_size_x>2.0</texture_size_x>
<texture_size_y>2.0</texture_size_y>
</element>
<!-- Transparent ceiling (FRONT cull_face allows light through from below) -->
<element class="horizontal_plane">
<cull_face>FRONT</cull_face>
<x_min>-$f{0.5*INDOOR_ROOM_SIZE}</x_min>
<y_min>-$f{0.5*INDOOR_ROOM_SIZE}</y_min>
<x_max>$f{0.5*INDOOR_ROOM_SIZE}</x_max>
<y_max>$f{0.5*INDOOR_ROOM_SIZE}</y_max>
<z>$f{WALL_HEIGHT}</z>
</element>
<!-- ================================================================
INDOOR ROOM WALLS
================================================================ -->
<!-- West wall with door to corridor A (straight) -->
<element class="vertical_plane">
<x0>-$f{0.5*INDOOR_ROOM_SIZE}</x0>
<y0>-$f{0.5*INDOOR_ROOM_SIZE}</y0>
<x1>-$f{0.5*INDOOR_ROOM_SIZE}</x1>
<y1>$f{0.5*INDOOR_ROOM_SIZE}</y1>
<z>0.0</z>
<height>$f{WALL_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>2.5</texture_size_x>
<texture_size_y>2.5</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness>
<!-- Door to corridor A at center -->
<door position="0.5" width="1.2" z_min="0.0" z_max="2.1" name="door_corridor_a" />
</element>
<!-- East wall with door to corridor B (with turn) -->
<element class="vertical_plane">
<x0>$f{0.5*INDOOR_ROOM_SIZE}</x0>
<y0>-$f{0.5*INDOOR_ROOM_SIZE}</y0>
<x1>$f{0.5*INDOOR_ROOM_SIZE}</x1>
<y1>$f{0.5*INDOOR_ROOM_SIZE}</y1>
<z>0.0</z>
<height>$f{WALL_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>2.5</texture_size_x>
<texture_size_y>2.5</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness>
<!-- Door to corridor B at center -->
<door position="0.5" width="1.2" z_min="0.0" z_max="2.1" name="door_corridor_b" />
</element>
<!-- North wall with windows -->
<element class="vertical_plane">
<x0>-$f{0.5*INDOOR_ROOM_SIZE}</x0>
<y0>$f{0.5*INDOOR_ROOM_SIZE}</y0>
<x1>$f{0.5*INDOOR_ROOM_SIZE}</x1>
<y1>$f{0.5*INDOOR_ROOM_SIZE}</y1>
<z>0.0</z>
<height>$f{WALL_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/ConcreteWall02_1K_BaseColor.png</texture>
<texture_size_x>2.5</texture_size_x>
<texture_size_y>2.5</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness>
<!-- Windows on north wall -->
<window position="0.3" width="1.2" z_min="1.0" z_max="2.3" name="window_north_left" />
<window position="0.7" width="1.2" z_min="1.0" z_max="2.3" name="window_north_right" />
</element>
<!-- South wall with windows -->
<element class="vertical_plane">
<x0>$f{0.5*INDOOR_ROOM_SIZE}</x0>
<y0>-$f{0.5*INDOOR_ROOM_SIZE}</y0>
<x1>-$f{0.5*INDOOR_ROOM_SIZE}</x1>
<y1>-$f{0.5*INDOOR_ROOM_SIZE}</y1>
<z>0.0</z>
<height>$f{WALL_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-concrete-01.jpg</texture>
<texture_size_x>2.5</texture_size_x>
<texture_size_y>2.5</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness>
<!-- Windows on south wall -->
<window position="0.3" width="1.2" z_min="1.0" z_max="2.3" name="window_south_left" />
<window position="0.7" width="1.2" z_min="1.0" z_max="2.3" name="window_south_right" />
</element>
<!-- ================================================================
INDOOR FURNITURE
================================================================ -->
<block:class name="table">
<mass>30</mass>
<static>true</static>
<zmin>0.0</zmin>
<zmax>$f{0.5*CORRIDOR_WIDTH}</zmax>
<shape_from_visual/>
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/OfficeDesk.zip/OfficeDesk/desk.dae</model_uri>
<model_roll>90.0</model_roll>
</visual>
</block:class>
<block:class name="chair">
<mass>5</mass>
<zmin>0.0</zmin>
<zmax>$f{0.5*CORRIDOR_WIDTH}</zmax>
<shape_from_visual/>
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/OfficeChair.zip/OfficeChair/officechair.dae</model_uri>
<model_roll>90.0</model_roll>
</visual>
</block:class>
<!-- Furniture placement -->
<block class="table"> <init_pose>-3 3.5 -90</init_pose> </block>
<block class="chair"> <init_pose>-3.6 2.6 -5</init_pose> </block>
<block class="chair"> <init_pose>-2.6 2.55 120</init_pose> </block>
<block class="table"> <init_pose>3 -3.2 90</init_pose> </block>
<block class="chair"> <init_pose>3.2 -2.3 110</init_pose> </block>
<!-- ================================================================
CORRIDOR A (STRAIGHT, 15m length on West side)
================================================================ -->
<!-- Corridor A floor -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>-$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH}</x_min>
<y_min>$f{-0.5*CORRIDOR_WIDTH}</y_min>
<x_max>-$f{0.5*INDOOR_ROOM_SIZE}</x_max>
<y_max>$f{0.5*CORRIDOR_WIDTH}</y_max>
<z>0.02</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/concrete-ground-1.jpg</texture>
<texture_size_x>2.0</texture_size_x>
<texture_size_y>2.0</texture_size_y>
</element>
<!-- Corridor A ceiling -->
<element class="horizontal_plane">
<cull_face>FRONT</cull_face>
<x_min>-$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH}</x_min>
<y_min>$f{-0.5*CORRIDOR_WIDTH}</y_min>
<x_max>-$f{0.5*INDOOR_ROOM_SIZE}</x_max>
<y_max>$f{0.5*CORRIDOR_WIDTH}</y_max>
<z>$f{WALL_HEIGHT}</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/BathroomTiles03_1K_BaseColor.png</texture>
<texture_size_x>2.0</texture_size_x>
<texture_size_y>2.0</texture_size_y>
</element>
<!-- Corridor A north wall -->
<element class="vertical_plane">
<x0>-$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH}</x0>
<y0>$f{0.5*CORRIDOR_WIDTH}</y0>
<x1>-$f{0.5*INDOOR_ROOM_SIZE}</x1>
<y1>$f{0.5*CORRIDOR_WIDTH}</y1>
<z>0.0</z>
<height>$f{WALL_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>2.5</texture_size_x>
<texture_size_y>2.5</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness>
</element>
<!-- Corridor A south wall -->
<element class="vertical_plane">
<x0>-$f{0.5*INDOOR_ROOM_SIZE}</x0>
<y0>$f{-0.5*CORRIDOR_WIDTH}</y0>
<x1>-$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH}</x1>
<y1>$f{-0.5*CORRIDOR_WIDTH}</y1>
<z>0.0</z>
<height>$f{WALL_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>2.5</texture_size_x>
<texture_size_y>2.5</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness>
</element>
<!-- ================================================================
CORRIDOR B (WITH 90-DEGREE TURN on East side)
================================================================ -->
<!-- Corridor B - Part 1 (horizontal segment, 15m length) -->
<!-- Corridor B Part 1 floor -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>$f{0.5*INDOOR_ROOM_SIZE}</x_min>
<y_min>$f{-0.5*CORRIDOR_WIDTH}</y_min>
<x_max>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH+0.5*CORRIDOR_WIDTH}</x_max>
<y_max>$f{0.5*CORRIDOR_WIDTH}</y_max>
<z>0.02</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/concrete-ground-1.jpg</texture>
<texture_size_x>2.0</texture_size_x>
<texture_size_y>2.0</texture_size_y>
</element>
<!-- Corridor B Part 1 ceiling -->
<element class="horizontal_plane">
<cull_face>FRONT</cull_face>
<x_min>$f{0.5*INDOOR_ROOM_SIZE}</x_min>
<y_min>$f{-0.5*CORRIDOR_WIDTH}</y_min>
<x_max>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH+0.5*CORRIDOR_WIDTH}</x_max>
<y_max>$f{0.5*CORRIDOR_WIDTH}</y_max>
<z>$f{WALL_HEIGHT}</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/BathroomTiles03_1K_BaseColor.png</texture>
<texture_size_x>2.0</texture_size_x>
<texture_size_y>2.0</texture_size_y>
</element>
<!-- Corridor B Part 1 north wall -->
<element class="vertical_plane">
<x0>$f{0.5*INDOOR_ROOM_SIZE}</x0>
<y0>$f{0.5*CORRIDOR_WIDTH}</y0>
<x1>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH-0.5*CORRIDOR_WIDTH}</x1>
<y1>$f{0.5*CORRIDOR_WIDTH}</y1>
<z>0.0</z>
<height>$f{WALL_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>2.5</texture_size_x>
<texture_size_y>2.5</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness>
</element>
<!-- Corridor B Part 1 south wall -->
<element class="vertical_plane">
<x0>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH+0.5*CORRIDOR_WIDTH}</x0>
<y0>$f{-0.5*CORRIDOR_WIDTH}</y0>
<x1>$f{0.5*INDOOR_ROOM_SIZE}</x1>
<y1>$f{-0.5*CORRIDOR_WIDTH}</y1>
<z>0.0</z>
<height>$f{WALL_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>2.5</texture_size_x>
<texture_size_y>2.5</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness>
</element>
<!-- Corridor B - Part 2 (vertical segment after 90-degree turn, 15m length) -->
<!-- Corridor B Part 2 floor -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH-0.8}</x_min>
<y_min>$f{0.5*CORRIDOR_WIDTH}</y_min>
<x_max>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH+0.8}</x_max>
<y_max>$f{0.8+CORRIDOR_STRAIGHT_LENGTH}</y_max>
<z>0.02</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/concrete-ground-1.jpg</texture>
<texture_size_x>2.0</texture_size_x>
<texture_size_y>2.0</texture_size_y>
</element>
<!-- Corridor B Part 2 ceiling -->
<element class="horizontal_plane">
<cull_face>FRONT</cull_face>
<x_min>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH-0.8}</x_min>
<y_min>$f{0.5*CORRIDOR_WIDTH}</y_min>
<x_max>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH+0.8}</x_max>
<y_max>$f{0.8+CORRIDOR_STRAIGHT_LENGTH}</y_max>
<z>$f{WALL_HEIGHT}</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/BathroomTiles03_1K_BaseColor.png</texture>
<texture_size_x>2.0</texture_size_x>
<texture_size_y>2.0</texture_size_y>
</element>
<!-- Corridor B Part 2 east wall (right side) -->
<element class="vertical_plane">
<x0>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH+0.8}</x0>
<y0>$f{-0.5*CORRIDOR_WIDTH}</y0>
<x1>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH+0.8}</x1>
<y1>$f{0.8+CORRIDOR_STRAIGHT_LENGTH}</y1>
<z>0.0</z>
<height>$f{WALL_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>2.5</texture_size_x>
<texture_size_y>2.5</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness>
</element>
<!-- Corridor B Part 2 west wall (left side) -->
<element class="vertical_plane">
<x0>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH-0.8}</x0>
<y0>$f{0.8+CORRIDOR_STRAIGHT_LENGTH}</y0>
<x1>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH-0.8}</x1>
<y1>$f{0.5*CORRIDOR_WIDTH}</y1>
<z>0.0</z>
<height>$f{WALL_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>2.5</texture_size_x>
<texture_size_y>2.5</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness>
</element>
<!-- ================================================================
GNSS-DENIED REGIONS (PropertyRegion elements)
================================================================ -->
<!-- Indoor room GNSS-denied zone -->
<element class="property_region">
<property_name>gps_no_coverage</property_name>
<value_bool>true</value_bool>
<x_min>-8.0</x_min>
<y_min>-8.0</y_min>
<z_min>-1.0</z_min>
<x_max>8.0</x_max>
<y_max>8.0</y_max>
<z_max>3.0</z_max>
</element>
<!-- Corridor A GNSS-denied zone -->
<element class="property_region">
<property_name>gps_no_coverage</property_name>
<value_bool>true</value_bool>
<x_min>-$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH+0.5}</x_min>
<y_min>-1.5</y_min>
<z_min>-1.0</z_min>
<x_max>-7.0</x_max>
<y_max>1.5</y_max>
<z_max>3.0</z_max>
</element>
<!-- Corridor B Part 1 GNSS-denied zone -->
<element class="property_region">
<property_name>gps_no_coverage</property_name>
<value_bool>true</value_bool>
<x_min>7.0</x_min>
<y_min>-1.5</y_min>
<z_min>-1.0</z_min>
<x_max>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH+0.5}</x_max>
<y_max>1.5</y_max>
<z_max>3.0</z_max>
</element>
<!-- Corridor B Part 2 GNSS-denied zone -->
<element class="property_region">
<property_name>gps_no_coverage</property_name>
<value_bool>true</value_bool>
<x_min>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH-1.5}</x_min>
<y_min>0.3</y_min>
<z_min>-1.0</z_min>
<x_max>$f{0.5*INDOOR_ROOM_SIZE+CORRIDOR_STRAIGHT_LENGTH+1.5}</x_max>
<y_max>$f{0.8+CORRIDOR_STRAIGHT_LENGTH+0.5}</y_max>
<z_max>3.0</z_max>
</element>
<!-- ================================================================
VEHICLE AND SENSORS
================================================================ -->
<!-- Include vehicle definition with all sensors -->
<include file="../definitions/jackal.vehicle.xml"
default_sensors="true"
lidar2d_raytrace="true"
lidar2d_fov_degrees="360"
/>
<!-- Robot starting position at outdoor area -->
<vehicle name="robot" class="jackal">
<init_pose>$f{-CORRIDOR_STRAIGHT_LENGTH-0.5*INDOOR_ROOM_SIZE-5} 0 0</init_pose>
<include file="../definitions/gnss.sensor.xml"
sensor_x="0.0" sensor_y="0.0" sensor_z="0.25"
sensor_period_sec="1.0"
sensor_name="gps1"
sensor_horizontal_std_noise="1.5"
sensor_vertical_std_noise="2.5"
/>
<!-- IMU -->
<include file="../definitions/imu.sensor.xml"
sensor_x="0.0" sensor_y="0.0" sensor_z="0.5" sensor_yaw="0"
sensor_name="imu"
sensor_measure_orientation="true"
sensor_period_sec="$f{1/200.0}"
sensor_angular_velocity_white_noise_std_noise="1.7e-4"
sensor_linear_acceleration_white_noise_std_noise="5.88e-3"
sensor_angular_velocity_random_walk_std_noise="1.0e-5"
sensor_linear_acceleration_random_walk_std_noise="3.0e-4"
/>
</vehicle>
</mvsim_world>
demo_walls
Example of how to define textured walls, with doors and windows.
mvsim launch mvsim_tutorial/demo_walls.world.xml
World XML code
File: mvsim_tutorial/demo_walls.world.xml
<?xml version="1.0"?>
<mvsim_world version="1.0">
<!-- Example world demonstrating doors and windows in vertical planes -->
<!-- All walls and ground use textures from the mvsim-models repository -->
<simul_timestep>0</simul_timestep>
<save_to_rawlog>$env{MVSIM_SAVE_RAWLOG_FILENAME|}</save_to_rawlog>
<gui>
<ortho>false</ortho>
<show_forces>false</show_forces>
<cam_distance>20</cam_distance>
<fov_deg>60</fov_deg>
<refresh_fps>40</refresh_fps>
</gui>
<!-- Light parameters -->
<lights>
<enable_shadows>true</enable_shadows>
<light_azimuth_deg>60.0</light_azimuth_deg>
<light_elevation_deg>75.0</light_elevation_deg>
</lights>
<variable name="WALL_THICKNESS" value="$env{MVSIM_WALL_THICKNESS|0.30}"></variable>
<!-- Ground plane with concrete texture -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>-15</x_min> <y_min>-15</y_min>
<x_max> 15</x_max> <y_max> 15</y_max>
<z>0.0</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/concrete-ground-1.jpg</texture>
<texture_size_x>3.0</texture_size_x>
<texture_size_y>3.0</texture_size_y>
</element>
<!-- ================================================================
EXAMPLE 1: Wall with a single door (allows passage)
Red brick texture - West wall
================================================================ -->
<element class="vertical_plane">
<x0>-10</x0> <y0>-10</y0>
<x1>-10</x1> <y1>10</y1>
<z>0.0</z> <height>3.0</height>
<cull_face>NONE</cull_face>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>2.5</texture_size_x>
<texture_size_y>2.5</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness> <!-- Wall thickness in meters -->
<!-- Door at 50% position (middle of wall), 1.2m wide, standard height -->
<door>
<position>0.5</position> <!-- 0.0 = start point, 1.0 = end point -->
<width>1.2</width> <!-- meters -->
<z_min>0.0</z_min> <!-- bottom of door -->
<z_max>2.1</z_max> <!-- top of door -->
<name>main_entrance</name>
</door>
</element>
<!-- ================================================================
EXAMPLE 2: Wall with multiple windows (collision enabled)
Brown brick texture - East wall
================================================================ -->
<element class="vertical_plane">
<x0>10</x0> <y0>-10</y0>
<x1>10</x1> <y1>10</y1>
<z>0.0</z> <height>3.0</height>
<cull_face>NONE</cull_face>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-02.png</texture>
<texture_size_x>2.5</texture_size_x>
<texture_size_y>2.5</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness> <!-- Wall thickness in meters -->
<!-- First window -->
<window>
<position>0.25</position>
<width>1.5</width>
<z_min>1.0</z_min> <!-- 1m from ground -->
<z_max>2.5</z_max> <!-- 2.5m from ground -->
<name>window_left</name>
</window>
<!-- Second window -->
<window>
<position>0.75</position>
<width>1.5</width>
<z_min>1.0</z_min>
<z_max>2.5</z_max>
<name>window_right</name>
</window>
</element>
<!-- ================================================================
EXAMPLE 3: Wall with door and windows (textured)
Concrete wall texture - North wall
================================================================ -->
<element class="vertical_plane">
<x0>-10</x0> <y0>10</y0>
<x1>10</x1> <y1>10</y1>
<z>0.0</z> <height>3.0</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/ConcreteWall02_1K_BaseColor.png</texture>
<texture_size_x>3.0</texture_size_x>
<texture_size_y>3.0</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness> <!-- Wall thickness in meters -->
<!-- Door near left end -->
<door position="0.15" width="1.0" z_min="0.0" z_max="2.1" />
<!-- Windows above eye level -->
<window position="0.4" width="1.2" z_min="2.0" z_max="2.8" />
<window position="0.6" width="1.2" z_min="2.0" z_max="2.8" />
<window position="0.85" width="1.2" z_min="2.0" z_max="2.8" />
</element>
<!-- ================================================================
EXAMPLE 4: Wall with door at different position
Concrete texture - South wall
================================================================ -->
<element class="vertical_plane">
<x0>-10</x0> <y0>-10</y0>
<x1>10</x1> <y1>-10</y1>
<z>0.0</z> <height>3.0</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-concrete-01.jpg</texture>
<texture_size_x>2.0</texture_size_x>
<texture_size_y>2.0</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness> <!-- Wall thickness in meters -->
<!-- Door at 30% position from start -->
<door>
<position>0.3</position>
<width>1.5</width>
<z_min>0.0</z_min>
<z_max>2.2</z_max>
<name>side_door</name>
</door>
<!-- High window for ventilation -->
<window>
<position>0.7</position>
<width>2.0</width>
<z_min>2.3</z_min>
<z_max>2.9</z_max>
<name>ventilation_window</name>
</window>
</element>
<!-- ================================================================
EXAMPLE 5: Interior wall with double doors
Wooden planks texture - Interior divider
================================================================ -->
<element class="vertical_plane">
<x0>0</x0> <y0>-5</y0>
<x1>0</x1> <y1>5</y1>
<z>0.0</z> <height>2.5</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/WoodenPlanks01_1K_BaseColor.png</texture>
<texture_size_x>1.5</texture_size_x>
<texture_size_y>1.5</texture_size_y>
<thickness>${WALL_THICKNESS}</thickness> <!-- Wall thickness in meters -->
<!-- Left door of double door -->
<door position="0.4" width="0.9" z_min="0.0" z_max="2.1" name="double_door_left" />
<!-- Right door of double door -->
<door position="0.6" width="0.9" z_min="0.0" z_max="2.1" name="double_door_right" />
<!-- Note: These doors will be merged in collision handling since they overlap -->
</element>
<!-- ======================================
Walls from external 3D model
====================================== -->
<!--<walls>
<color>#505050</color>
<model_uri>testWalls.dae</model_uri>
<wallThickness>0.10</wallThickness>
</walls> -->
<!-- Add a vehicle to test navigation through doors -->
<include file="../definitions/jackal.vehicle.xml" default_sensors="true" />
<vehicle name="robot1" class="jackal">
<init_pose>-8 0 0</init_pose>
</vehicle>
</mvsim_world>
demo_1robot
A simple 2D world defined via an occupancy grid map and a robot equipped with 2D lidars.
roslaunch mvsim ros1_1robot.launch
ros2 launch mvsim demo_1robot.launch.py
Assuming you compiled MVSim in the directory MVSIM_ROOT,
with cmake build directory build-Release, run:
cd MVSIM_ROOT
build-Release/bin/mvsim launch mvsim_tutorial/demo_1robot.world.xml
World XML code
File: mvsim_tutorial/demo_1robot.world.xml
<mvsim_world version="1.0">
<!-- General simulation options -->
<simul_timestep>0</simul_timestep> <!-- Simulation fixed-time interval for numerical integration [seconds] or 0 to autodetermine -->
<!-- GUI options -->
<gui>
<ortho>false</ortho>
<show_forces>true</show_forces> <force_scale>0.01</force_scale>
<cam_distance>35</cam_distance>
<fov_deg>60</fov_deg>
<refresh_fps>20</refresh_fps>
<!-- <follow_vehicle>r1</follow_vehicle> -->
</gui>
<!-- Light parameters -->
<lights>
</lights>
<!-- ========================
Scenario definition
======================== -->
<element class="occupancy_grid">
<!-- File can be an image or an MRPT .gridmap file -->
<file>uma_campus.gridmap.gz</file>
<!--<show_collisions>true</show_collisions>-->
</element>
<!-- ground grid (for visual reference) -->
<element class="ground_grid">
<floating>true</floating>
</element>
<!-- =============================
Vehicle classes definition
============================= -->
<include file="../definitions/ackermann.vehicle.xml" />
<!-- ========================
Vehicle(s) definition
======================== -->
<vehicle name="r1" class="car_ackermann">
<init_pose>0 0 0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
<init_vel>0 0 0</init_vel> <!-- In local coords: vx,vy, omega(deg/s) -->
<!-- Sensors -->
<include file="../definitions/lidar2d.sensor.xml" sensor_x="1.7" sensor_z="1.01" sensor_yaw="0" max_range="70.0" sensor_name="laser1" />
<include file="../definitions/lidar2d.sensor.xml" sensor_x="-0.5" sensor_z="1.01" sensor_yaw="180" max_range="70.0" sensor_name="laser2" />
</vehicle>
</mvsim_world>
demo_2robots
A world with 2 simple robots and a couple of custom “blocks” (furniture).
roslaunch mvsim ros1_2robots.launch
ros2 launch mvsim demo_2robots.launch.py
Assuming you compiled MVSim in the directory MVSIM_ROOT,
with cmake build directory build-Release, run:
cd MVSIM_ROOT
build-Release/bin/mvsim launch mvsim_tutorial/demo_2robots.world.xml
World XML code
File: mvsim_tutorial/demo_2robots.world.xml
<mvsim_world version="1.0">
<!-- General simulation options -->
<simul_timestep>0</simul_timestep> <!-- Simulation fixed-time interval for numerical integration [seconds] or 0 to autodetermine -->
<!-- GUI options -->
<gui>
<ortho>false</ortho>
<show_forces>true</show_forces> <force_scale>0.01</force_scale>
<cam_distance>35</cam_distance>
<fov_deg>60</fov_deg>
<refresh_fps>20</refresh_fps>
<!-- <follow_vehicle>r1</follow_vehicle> -->
</gui>
<!-- Light parameters -->
<lights>
</lights>
<!-- ========================
Scenario definition
======================== -->
<!-- ground -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>-20</x_min>
<y_min>-20</y_min>
<x_max> 20</x_max>
<y_max> 20</y_max>
<z>0.0</z>
</element>
<!-- ground grid (for visual reference) -->
<element class="ground_grid">
<!--<floating>true</floating>-->
</element>
<!-- =============================
Vehicle classes definition
============================= -->
<include file="../definitions/ackermann.vehicle.xml" />
<include file="../definitions/small_robot.vehicle.xml" />
<!-- ========================
Vehicle(s) definition
======================== -->
<vehicle name="r1" class="small_robot">
<init_pose>17 0 90.0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
<init_vel>0 0 0</init_vel> <!-- In local coords: vx,vy, omega(deg/s) -->
<publish>
<publish_pose_topic>/${NAME}/pose</publish_pose_topic>
<publish_pose_period>50e-3</publish_pose_period>
</publish>
<!-- Sensors -->
<include file="../definitions/lidar2d.sensor.xml"
sensor_x="0.5" sensor_y="0" sensor_z="0.70" sensor_yaw="0" sensor_name="laser1" raytrace_3d="true"
sensor_publish="true"
/>
<include file="../definitions/rgbd_camera.sensor.xml"
sensor_x="0.6" sensor_y="0" sensor_z="0.65"
/>
</vehicle>
<vehicle name="r2" class="car_ackermann">
<init_pose>-10.0 0 0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
<init_vel>0 0 0</init_vel> <!-- In local coords: vx,vy, omega(deg/s) -->
<publish>
<publish_pose_topic>/${NAME}/pose</publish_pose_topic>
<publish_pose_period>50e-3</publish_pose_period>
</publish>
<!-- Sensors -->
<include file="../definitions/lidar2d.sensor.xml"
raytrace_3d="true" sensor_x="1.7" sensor_z="1.01" sensor_yaw="0" sensor_name="laser1"
sensor_publish="true"
/>
<!-- Sensors -->
<include file="../definitions/camera.sensor.xml"
sensor_x="1.9" sensor_z="0.5"
sensor_publish="true"
/>
</vehicle>
<!-- ======================================
Obstacle blocks classes definition
====================================== -->
<block:class name="square_obstacle">
<mass>20</mass>
<color>#0080ff</color>
<zmax>1.5</zmax>
<ground_friction>0.3</ground_friction>
<shape>
<pt>-1.0 -0.6</pt>
<pt>-1.0 0.6</pt>
<pt> 1.0 0.5</pt>
<pt> 1.0 -0.5</pt>
</shape>
</block:class>
<block:class name="nurse_station">
<mass>300</mass>
<color>#0080ff</color>
<ground_friction>100.0</ground_friction>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model -->
<!-- 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/aws_robomaker_hospital_nursesstation_01.zip/aws_robomaker_hospital_nursesstation_01/aws_robomaker_hospital_nursesstation_01_visual.dae</model_uri>
</visual>
</block:class>
<!-- ========================
Obstacle blocks
======================== -->
<block class="square_obstacle">
<init_pose>6 5 0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
<publish>
<publish_pose_topic>/${NAME}/pose</publish_pose_topic>
<publish_pose_period>50e-3</publish_pose_period>
</publish>
</block>
<!-- Example intangible block, used as a reference for relative pose sensing -->
<block name="blockSensor1">
<shape>
<pt>-0.05 -0.05</pt>
<pt>-0.05 0.05</pt>
<pt> 0.05 0.05</pt>
<pt> 0.05 -0.05</pt>
</shape>
<intangible>true</intangible>
<zmin>0.0</zmin>
<zmax>0.2</zmax>
<init_pose>2.5 -12 0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
<publish>
<publish_pose_period>100e-3</publish_pose_period>
<!-- Comma separated list of objects, robots, etc. to sense and publish relative poses -->
<publish_relative_pose_objects>r1, r2</publish_relative_pose_objects>
<publish_relative_pose_topic>/relative_pose_readings</publish_relative_pose_topic>
</publish>
</block>
<!-- ========================================================
Standalone sensors (placed freely on the environment)
======================================================== -->
<sensor class="laser" name="proximitySensor1">
<pose>1.3 -18.3 90.0 </pose>
<fov_degrees>30</fov_degrees>
<nrays>5</nrays>
<range_std_noise>0.01</range_std_noise>
<angle_std_noise_deg>0.01</angle_std_noise_deg>
<publish>
<publish_topic>/${NAME}</publish_topic>
</publish>
</sensor>
<block class="nurse_station">
<init_pose>15 2 30</init_pose> <!-- In global coords: x,y, yaw(deg) -->
</block>
</mvsim_world>
demo_camera
Example of a robot with a camera sensor (RGB).
roslaunch mvsim ros1_camera.launch
ros2 launch mvsim demo_camera.launch.py
Assuming you compiled MVSim in the directory MVSIM_ROOT,
with cmake build directory build-Release, run:
cd MVSIM_ROOT
build-Release/bin/mvsim launch mvsim_tutorial/demo_camera.world.xml
World XML code
File: mvsim_tutorial/demo_camera.world.xml
<mvsim_world version="1.0">
<!-- General simulation options -->
<simul_timestep>0</simul_timestep> <!-- Simulation fixed-time interval for numerical integration [seconds] or 0 to autodetermine -->
<!-- GUI options -->
<gui>
<ortho>false</ortho>
<show_forces>true</show_forces> <force_scale>0.01</force_scale>
<cam_distance>35</cam_distance>
<fov_deg>60</fov_deg>
<refresh_fps>20</refresh_fps>
<!-- <follow_vehicle>r1</follow_vehicle> -->
</gui>
<!-- ========================
Scenario definition
======================== -->
<!-- ground -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>-20</x_min>
<y_min>-20</y_min>
<x_max> 20</x_max>
<y_max> 20</y_max>
<z>0.0</z>
</element>
<!-- =============================
Vehicle classes definition
============================= -->
<include file="../definitions/small_robot.vehicle.xml" />
<!-- ========================
Vehicle(s) definition
======================== -->
<vehicle name="r1" class="small_robot">
<init_pose>0 0 0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
<init_vel>0 0 0</init_vel> <!-- In local coords: vx,vy, omega(deg/s) -->
<publish>
<publish_pose_topic>/${NAME}/pose</publish_pose_topic>
<publish_pose_period>50e-3</publish_pose_period>
</publish>
<!-- Sensors -->
<include file="../definitions/camera.sensor.xml"
sensor_x="0.6" sensor_y="0" sensor_z="0.65"
sensor_period_sec="0.10"
/>
</vehicle>
<!-- ======================================
Obstacle blocks classes definition
====================================== -->
<block:class name="square_obstacle">
<mass>20</mass>
<color>#0080ff</color>
<zmax>1.5</zmax>
<ground_friction>0.3</ground_friction>
<shape>
<pt>-1.0 -0.6</pt>
<pt>-1.0 0.6</pt>
<pt> 1.0 0.5</pt>
<pt> 1.0 -0.5</pt>
</shape>
</block:class>
<block:class name="nurse_station">
<static>true</static> <!-- Does not move -->
<color>#0080ff</color>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model -->
<!-- 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/aws_robomaker_hospital_nursesstation_01.zip/aws_robomaker_hospital_nursesstation_01/aws_robomaker_hospital_nursesstation_01_visual.dae</model_uri>
</visual>
</block:class>
<!-- ========================
Obstacle blocks
======================== -->
<block class="square_obstacle">
<init_pose>6 5 0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
<publish>
<publish_pose_topic>/${NAME}/pose</publish_pose_topic>
<publish_pose_period>50e-3</publish_pose_period>
</publish>
</block>
<block class="nurse_station">
<init_pose>10 0 -90</init_pose> <!-- In global coords: x,y, yaw(deg) -->
</block>
</mvsim_world>
demo_depth_camera
Example of a robot with a depth camera sensor (RGB+D).
roslaunch mvsim ros1_depth_camera.launch
ros2 launch mvsim demo_depth_camera.launch.py
Assuming you compiled MVSim in the directory MVSIM_ROOT,
with cmake build directory build-Release, run:
cd MVSIM_ROOT
build-Release/bin/mvsim launch mvsim_tutorial/demo_depth_camera.world.xml
World XML code
File: mvsim_tutorial/demo_depth_camera.world.xml
<mvsim_world version="1.0">
<!-- General simulation options -->
<simul_timestep>0</simul_timestep> <!-- Simulation fixed-time interval for numerical integration [seconds] or 0 to autodetermine -->
<!-- GUI options -->
<gui>
<ortho>false</ortho>
<show_forces>true</show_forces> <force_scale>0.01</force_scale>
<cam_distance>35</cam_distance>
<fov_deg>60</fov_deg>
<refresh_fps>20</refresh_fps>
<!-- <follow_vehicle>r1</follow_vehicle> -->
</gui>
<!-- Light parameters -->
<lights>
</lights>
<!-- ========================
Scenario definition
======================== -->
<!-- ground -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>-20</x_min>
<y_min>-20</y_min>
<x_max> 20</x_max>
<y_max> 20</y_max>
<z>0.0</z>
</element>
<!-- =============================
Vehicle classes definition
============================= -->
<include file="../definitions/small_robot.vehicle.xml" />
<!-- ========================
Vehicle(s) definition
======================== -->
<vehicle name="r1" class="small_robot">
<init_pose>0 0 0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
<init_vel>0 0 0</init_vel> <!-- In local coords: vx,vy, omega(deg/s) -->
<publish>
<publish_pose_topic>/${NAME}/pose</publish_pose_topic>
<publish_pose_period>50e-3</publish_pose_period>
</publish>
<!-- Sensors -->
<include file="../definitions/lidar2d.sensor.xml"
sensor_x="0.5" sensor_y="0" sensor_z="0.70" sensor_yaw="0" sensor_name="laser1" raytrace_3d="true"
sensor_period_sec="0.10"
/>
<include file="../definitions/rgbd_camera.sensor.xml"
sensor_x="0.6" sensor_y="0" sensor_z="0.65"
sensor_period_sec="0.10"
show_3d_pointcloud="true"
/>
</vehicle>
<!-- ======================================
Obstacle blocks classes definition
====================================== -->
<block:class name="square_obstacle">
<mass>20</mass>
<color>#0080ff</color>
<zmax>1.5</zmax>
<ground_friction>0.3</ground_friction>
<shape>
<pt>-1.0 -0.6</pt>
<pt>-1.0 0.6</pt>
<pt> 1.0 0.5</pt>
<pt> 1.0 -0.5</pt>
</shape>
</block:class>
<block:class name="nurse_station">
<static>true</static> <!-- Does not move -->
<color>#0080ff</color>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model -->
<!-- 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/aws_robomaker_hospital_nursesstation_01.zip/aws_robomaker_hospital_nursesstation_01/aws_robomaker_hospital_nursesstation_01_visual.dae</model_uri>
</visual>
</block:class>
<!-- ========================
Obstacle blocks
======================== -->
<block class="square_obstacle">
<init_pose>6 5 0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
<publish>
<publish_pose_topic>/${NAME}/pose</publish_pose_topic>
<publish_pose_period>50e-3</publish_pose_period>
</publish>
</block>
<block class="nurse_station">
<init_pose>10 0 -90</init_pose> <!-- In global coords: x,y, yaw(deg) -->
</block>
</mvsim_world>
demo_elevation_map
Example of a 3D Lidar robot in a “2.5D” world defined by an elevation map.
roslaunch mvsim ros1_elevation_map.launch
ros2 launch mvsim demo_elevation_map.launch.py
Assuming you compiled MVSim in the directory MVSIM_ROOT,
with cmake build directory build-Release, run:
cd MVSIM_ROOT
build-Release/bin/mvsim launch mvsim_tutorial/demo_elevation_map.world.xml
World XML code
File: mvsim_tutorial/demo_elevation_map.world.xml
<mvsim_world version="1.0">
<!-- General simulation options -->
<!-- With ramps and elevation maps, it's better to manually set a small time step
to improve the physics simulation and achieve more realistic frictions/sliding
when on ramps -->
<simul_timestep>2e-3</simul_timestep> <!-- Simulation fixed-time interval for numerical integration [seconds] or 0 to autodetermine -->
<save_to_rawlog>$env{MVSIM_SAVE_RAWLOG_FILENAME|}</save_to_rawlog>
<!-- Define georeferenced coordinates to the world so GNSS/GPS sensors can be properly simulated -->
<georeference>
<latitude>36.894718</latitude>
<longitude>-2.316988</longitude>
<height>200.0</height>
<world_to_enu_rotation_deg>5.0</world_to_enu_rotation_deg>
</georeference>
<!-- GUI options -->
<gui>
<ortho>false</ortho>
<show_forces>false</show_forces> <force_scale>0.01</force_scale>
<cam_distance>5</cam_distance>
<cam_azimuth>150</cam_azimuth>
<cam_elevation>15</cam_elevation>
<fov_deg>80</fov_deg>
<!-- <follow_vehicle>r1</follow_vehicle> -->
</gui>
<!-- Light parameters -->
<lights>
<enable_shadows>true</enable_shadows>
<light_azimuth_deg>-25.0</light_azimuth_deg>
<light_elevation_deg>10.0</light_elevation_deg>
</lights>
<!-- ========================
Scenario definition
======================== -->
<element class='elevation_map'>
<!-- File can be an image or a .txt matrix -->
<resolution>0.5</resolution>
<elevation_image>elevation_mesh1.png</elevation_image>
<elevation_image_min_z>-1.0</elevation_image_min_z>
<elevation_image_max_z>2.0</elevation_image_max_z>
<texture_image>https://mrpt.github.io/mvsim-models/textures-cgbookcase/Pebbles02_512_BaseColor.png</texture_image>
<texture_extension_x>1.5</texture_extension_x>
<texture_extension_y>1.5</texture_extension_y>
<model_split_size>3.0</model_split_size> <!-- See docs. Required for correct z-order rendering if there are transparent objects in the world (e.g. trees with leaves) -->
<mesh_color>#a0e0a0</mesh_color> <!-- Used only if mesh_image is not provided -->
</element>
<!-- A SkyBox decoration -->
<element class='skybox'>
<!-- Provide the URI printf-like "pattern" to the six texture files,
such that replacing "%s" with the following strings gives the path
to the files: "Up", "Right", "Left", "Front", "Down", "Back".
-->
<textures>https://mrpt.github.io/mvsim-models/skyboxes/SunSet.zip/SunSet/SunSet%s.jpg</textures>
</element>
<!-- =============================
Vehicle classes definition
============================= -->
<include file="../definitions/jackal.vehicle.xml"
default_sensors="false"
/>
<!-- ========================
Vehicle(s) definition
======================== -->
<vehicle name="r1" class="jackal">
<init_pose>4 -8 0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
<!-- Sensors -->
<include file="../definitions/velodyne-vlp16.sensor.xml"
sensor_x="0.15" sensor_y="0" sensor_z="0.38" sensor_yaw="0"
sensor_std_noise="0.005"
sensor_publish="false"
sensor_name="lidar1"
sensor_rpm="600"
horz_resolution_factor="2.0"
vert_resolution_factor="2.0"
/>
<include file="../definitions/rgbd_camera.sensor.xml"
sensor_x="0.22" sensor_z="0.29"
sensor_period_sec="0.10"
show_3d_pointcloud="false"
/>
<include file="../definitions/gnss.sensor.xml"
sensor_x="0.0" sensor_y="0.0" sensor_z="0.25"
sensor_period_sec="1.0"
sensor_name="gps1"
sensor_horizontal_std_noise="1.5"
sensor_vertical_std_noise="2.5"
/>
</vehicle>
<!-- ======================================
Obstacle blocks classes definition
====================================== -->
<block:class name="rock_01">
<static>true</static> <!-- Does not move -->
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<zmin>0.0</zmin> <zmax>2.5</zmax> <!-- Only count collisions in this height range -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/rock01.zip/rock01/FallingRock01.dae</model_uri>
</visual>
</block:class>
<block:class name="rock_02">
<static>true</static> <!-- Does not move -->
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<zmin>0.0</zmin> <zmax>2.5</zmax> <!-- Only count collisions in this height range -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/rock02.zip/rock02/FallingRock02.dae</model_uri>
</visual>
</block:class>
<block:class name="oak_tree_01">
<static>true</static> <!-- Does not move -->
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<zmin>0.0</zmin> <zmax>0.5</zmax> <!-- Only count collisions in this height range -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/OakTree.zip/OakTree/Oak_tree_2.dae</model_uri>
<model_split_size>1.50</model_split_size> <!-- See docs. Required for transparent leaves -->
</visual>
</block:class>
<block:class name="palm_tree_01">
<static>true</static> <!-- Does not move -->
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<zmin>0.0</zmin> <zmax>0.5</zmax> <!-- Only count collisions in this height range -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/TropicPalmTree.zip/TropicPalmTree/free_palm.dae</model_uri>
<model_roll>90</model_roll>
<model_split_size>1.50</model_split_size> <!-- See docs. Required for transparent leaves -->
</visual>
</block:class>
<!-- ========================
Obstacle blocks
======================== -->
<variable name="ROCKS_SPREAD_X" value="35.0"></variable>
<variable name="ROCKS_SPREAD_Y" value="35.0"></variable>
<variable name="ROCKS_SPREAD_Z" value="1.0"></variable>
<variable name="TREES_SPREAD_X" value="20.0"></variable>
<variable name="TREES_SPREAD_Y" value="20.0"></variable>
<variable name="TREES_SPREAD_Z" value="0"></variable>
<for var="i" from="1" to="12">
<block class="rock_01">
<!-- In global coords: x,y,z, yaw(deg),pitch(deg),roll(deg) -->
<init_pose3d>$f{(-0.5+rand())*ROCKS_SPREAD_X} $f{(-0.5+rand())*ROCKS_SPREAD_Y} $f{(-0.5+rand())*ROCKS_SPREAD_Z} $f{-180+rand()*360} 0 0</init_pose3d>
</block>
</for>
<for var="i" from="1" to="5">
<block class="palm_tree_01">
<!-- In global coords: x,y,z, yaw(deg),pitch(deg),roll(deg) -->
<init_pose3d>$f{(-0.5+rand())*TREES_SPREAD_X} $f{(-0.5+rand())*TREES_SPREAD_Y} $f{(-0.5+rand())*TREES_SPREAD_Z} $f{-180+rand()*360} 0 0</init_pose3d>
</block>
</for>
</mvsim_world>
demo_greenhouse
Example of a 3D Lidar robot in a greenhouse. The XML illustrates features such as XML-level variables, XML-for loops for repetitive patterns of objects, slightly randomized-perturbations in plant poses, etc.
roslaunch mvsim ros1_greenhouse.launch
ros2 launch mvsim demo_greenhouse.launch.py
Assuming you compiled MVSim in the directory MVSIM_ROOT,
with cmake build directory build-Release, run:
cd MVSIM_ROOT
build-Release/bin/mvsim launch mvsim_tutorial/demo_greenhouse.world.xml
World XML code
File: mvsim_tutorial/demo_greenhouse.world.xml
<mvsim_world version="1.0">
<!-- General simulation options -->
<simul_timestep>0</simul_timestep> <!-- Simulation fixed-time interval for numerical integration [seconds] or 0 to autodetermine -->
<joystick_enabled>true</joystick_enabled>
<!-- <save_to_rawlog>my_dataset.rawlog</save_to_rawlog> --> <!-- If present, all sensor observations are saved to a rawlog file -->
<!-- Define georeferenced coordinates to the world so GNSS/GPS sensors can be properly simulated -->
<georeference>
<latitude>36.863636</latitude>
<longitude>-2.283397</longitude>
<height>100.0</height>
<world_to_enu_rotation_deg>45.0</world_to_enu_rotation_deg>
</georeference>
<!-- GUI options -->
<gui>
<ortho>false</ortho>
<show_forces>false</show_forces> <force_scale>0.01</force_scale>
<cam_distance>10</cam_distance>
<fov_deg>60</fov_deg>
<refresh_fps>15</refresh_fps>
<cam_point_to>1.5 13</cam_point_to>
<!-- <follow_vehicle>r1</follow_vehicle> -->
</gui>
<!-- Light parameters -->
<lights>
<enable_shadows>true</enable_shadows>
<!-- <shadow_map_size>1024</shadow_map_size> -->
<light_azimuth_deg>160.0</light_azimuth_deg>
<light_elevation_deg>40.0</light_elevation_deg>
</lights>
<variable name="NUM_TILTED_BEAMS_X" value="21"></variable>
<variable name="NUM_TILTED_BEAMS_Y" value="10"></variable>
<variable name="NUM_CORRIDORS_X" value="5"></variable>
<variable name="NUM_PLANTS_CORRIDOR_SOUTH" value="5"></variable>
<variable name="NUM_PLANTS_CORRIDOR_NORTH" value="6"></variable>
<variable name="NUM_POLES_X" value="8"></variable>
<variable name="NUM_POLES_Y" value="8"></variable>
<variable name="PLANTS_RAND_XY" value="0.35"></variable>
<!-- Variability of plant scale (1 sigma of normally distributed scale additional term to sum on top of 1.0) -->
<variable name="PLANTS_RAND_SIZE_STD" value="0.20" />
<variable name="CEILING_HEIGHT" value="3.0"></variable>
<!-- ========================
Scenario definition
======================== -->
<!-- ground -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>0</x_min> <y_min>0</y_min>
<x_max>46</x_max> <y_max>28.6</y_max>
<z>0.0</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/Dirt01_512_BaseColor.png</texture>
<texture_size_x>1.5</texture_size_x>
<texture_size_y>1.5</texture_size_y>
</element>
<!-- ceiling -->
<element class="horizontal_plane">
<cull_face>FRONT</cull_face>
<x_min>0</x_min> <y_min>0</y_min>
<x_max>46</x_max> <y_max>28.6</y_max>
<z>$f{CEILING_HEIGHT}</z>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/BathroomTiles03_1K_BaseColor.png</texture>
<texture_size_x>3.0</texture_size_x>
<texture_size_y>3.0</texture_size_y>
</element>
<!-- perimeter walls: -->
<!--<element class="vertical_plane">
<cull_face>FRONT</cull_face>
<x0>-15</x0> <y0>13</y0>
<x1>-15</x1> <y1>-13</y1>
<z>0.0</z> <height>$f{CEILING_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>3.0</texture_size_x>
<texture_size_y>3.0</texture_size_y>
</element>
<element class="vertical_plane">
<cull_face>FRONT</cull_face>
<x0> 20</x0> <y0>13</y0>
<x1>-15</x1> <y1>13</y1>
<z>0.0</z> <height>$f{CEILING_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>3.0</texture_size_x>
<texture_size_y>3.0</texture_size_y>
</element>
<element class="vertical_plane">
<cull_face>FRONT</cull_face>
<x0> 20</x0> <y0>-13</y0>
<x1> 20</x1> <y1>13</y1>
<z>0.0</z> <height>$f{CEILING_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>3.0</texture_size_x>
<texture_size_y>3.0</texture_size_y>
</element>
<element class="vertical_plane">
<cull_face>FRONT</cull_face>
<x0>-15</x0> <y0>-13</y0>
<x1> 20</x1> <y1>-13</y1>
<z>0.0</z> <height>$f{CEILING_HEIGHT}</height>
<texture>https://mrpt.github.io/mvsim-models/textures-cgbookcase/wall-bricks-01.png</texture>
<texture_size_x>3.0</texture_size_x>
<texture_size_y>3.0</texture_size_y>
</element>
-->
<!-- =============================
Vehicle classes definition
============================= -->
<include file="../definitions/agricobiot2.vehicle.xml" />
<!-- ========================
Vehicle(s) definition
======================== -->
<vehicle name="r1" class="agricobiot2">
<init_pose>1.5 13 0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
<!--<publish>
<publish_pose_topic>/${NAME}/pose</publish_pose_topic>
<publish_pose_period>50e-3</publish_pose_period>
</publish>-->
<!-- Sensors -->
<!-- <include file="../definitions/lidar2d.sensor.xml"
sensor_x="-0.15" sensor_z="0.25" sensor_yaw="180"
sensor_period_sec="0.10"
raytrace_3d="false"
sensor_name="scanner1"
/>-->
<!-- velodyne-vlp16.sensor.xml -->
<!-- helios-32.sensor.xml -->
<include file="../definitions/velodyne-vlp16.sensor.xml"
sensor_x="-0.34" sensor_y="0.01" sensor_z="1.53" sensor_yaw="180"
sensor_std_noise="0.005"
sensor_publish="false"
sensor_name="lidar1"
sensor_rpm="600"
horz_resolution_factor="1.5"
vert_resolution_factor="1.0"
/>
<!--<include file="../definitions/camera.sensor.xml"
sensor_x="0.9" sensor_y="0" sensor_z="0.75"
sensor_period_sec="0.20"
/>-->
<include file="../definitions/rgbd_camera.sensor.xml"
sensor_x="0.9" sensor_y="0" sensor_z="0.75"
sensor_period_sec="0.20"
sensor_name="cam1"
show_3d_pointcloud="false"
publish_ros_depth_image="true"
publish_ros_colored_pointcloud="true"
/>
<include file="../definitions/gnss.sensor.xml"
sensor_x="0.9" sensor_y="0.2" sensor_z="0.75"
sensor_period_sec="1.0"
sensor_name="gps1"
sensor_horizontal_std_noise="1.5"
sensor_vertical_std_noise="2.5"
/>
<!-- IMU -->
<include file="../definitions/imu.sensor.xml"
sensor_x="0.0" sensor_y="0.0" sensor_z="0.5" sensor_yaw="0"
sensor_period_sec="0.05"
sensor_name="imu"
sensor_measure_orientation="true"
/>
</vehicle>
<!-- ======================================
Object types
====================================== -->
<block:class name="pole_tilted">
<static>true</static> <!-- Does not move -->
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model. 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/greenhouse.zip/greenhouse/pole_tilted_he120e.stl</model_uri>
<model_offset_z>1.2</model_offset_z>
<model_roll>90.0</model_roll>
</visual>
</block:class>
<block:class name="pole_009">
<static>true</static> <!-- Does not move -->
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model. 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/greenhouse.zip/greenhouse/pole_009.stl</model_uri>
<model_offset_z>1.2</model_offset_z>
</visual>
</block:class>
<block:class name="pole_004">
<static>true</static> <!-- Does not move -->
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model. 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/greenhouse.zip/greenhouse/pole_004.stl</model_uri>
<model_offset_z>1.2</model_offset_z>
</visual>
</block:class>
<block:class name="plant_tomato">
<static>true</static> <!-- Does not move -->
<mass>5</mass>
<shape_from_visual/> <!-- automatic shape,zmin,zmax from 3D mesh-->
<!-- Custom visualization model. 3D model filename to load (local or remote http://uri ) -->
<visual>
<model_uri>https://mrpt.github.io/mvsim-models/greenhouse.zip/greenhouse/tomato_plant_240cm.dae</model_uri>
<model_roll>90.0</model_roll>
<model_offset_z>-0.05</model_offset_z>
</visual>
</block:class>
<!-- ======================================
Object instances
====================================== -->
<!-- You can assign an optional custom name to each object, as an attribute to block, like name="shelf_001", etc. -->
<!-- All coordinates are global coords:
SE(2) <init_pose>x y yaw(deg)</init_pose> or
SE(3) <init_pose3d>x y z yaw(deg) pitch(deg) roll(deg)</init_pose3d>
-->
<!-- H-beams along the X axis -->
<for var="iX" from="0" to="$f{NUM_TILTED_BEAMS_X-1}">
<block class="pole_tilted">
<init_pose>$f{3.95+2*iX} 1.35 180</init_pose>
</block>
<block class="pole_tilted">
<init_pose>$f{3.95+2*iX} $f{28.6-1.35} 0</init_pose>
</block>
</for>
<!-- H-beams along the Y axis -->
<for var="iY" from="0" to="$f{NUM_TILTED_BEAMS_Y-1}">
<block class="pole_tilted">
<init_pose>1.30 $f{3.9+2*iY} 90</init_pose>
</block>
<block class="pole_tilted">
<init_pose>$f{46-1.30} $f{3.9+2*iY} -90</init_pose>
</block>
</for>
<!-- Thick poles -->
<for var="iX" from="0" to="4">
<for var="iY" from="0" to="10">
<if condition="$f{if(iY<=3 or iY>=6, 1, 0)}">
<block class="pole_009">
<init_pose>$f{4+8*iX} $f{3.9+2*iY} 0</init_pose>
</block>
</if>
</for>
</for>
<!-- Thin poles -->
<for var="iX" from="0" to="4">
<for var="iY" from="0" to="10">
<if condition="$f{if(iY<=3 or iY>=6, 1, 0)}">
<block class="pole_004">
<init_pose>$f{4+4+8*iX} $f{3.9+2*iY} 0</init_pose>
</block>
</if>
</for>
</for>
<!-- Plants -->
<for var="iX" from="0" to="$f{NUM_CORRIDORS_X-1}">
<for var="iY" from="0" to="$f{NUM_PLANTS_CORRIDOR_SOUTH-1}">
<block class="plant_tomato">
<init_pose>$f{3.95+4*iX+rand()*PLANTS_RAND_XY} $f{3.0+iY*(9/NUM_PLANTS_CORRIDOR_SOUTH)+rand()*PLANTS_RAND_XY} $f{rand()*360}</init_pose>
<visual_scale>$f{1.0+PLANTS_RAND_SIZE_STD*randn()}</visual_scale>
</block>
<block class="plant_tomato">
<init_pose>$f{3.95+4*iX+3.0+rand()*PLANTS_RAND_XY} $f{3.0+iY*(9/NUM_PLANTS_CORRIDOR_SOUTH)+rand()*PLANTS_RAND_XY} $f{rand()*360}</init_pose>
<visual_scale>$f{1.0+PLANTS_RAND_SIZE_STD*randn()}</visual_scale>
</block>
</for>
<for var="iY" from="0" to="$f{NUM_PLANTS_CORRIDOR_NORTH-1}">
<block class="plant_tomato">
<init_pose>$f{3.95+4*iX+rand()*PLANTS_RAND_XY} $f{15.0+iY*(12/NUM_PLANTS_CORRIDOR_NORTH)+rand()*PLANTS_RAND_XY} $f{rand()*360}</init_pose>
<visual_scale>$f{1.0+PLANTS_RAND_SIZE_STD*randn()}</visual_scale>
</block>
<block class="plant_tomato">
<init_pose>$f{3.95+4*iX+3.0+rand()*PLANTS_RAND_XY} $f{15.0+iY*(12/NUM_PLANTS_CORRIDOR_NORTH)+rand()*PLANTS_RAND_XY} $f{rand()*360}</init_pose>
<visual_scale>$f{1.0+PLANTS_RAND_SIZE_STD*randn()}</visual_scale>
</block>
</for>
</for>
</mvsim_world>
demo_turtlebot_world
The MVSim port of the classic ROS “turtlebot world” scenario.
The XML illustrates how to define obstacle blocks with basic geometric shapes without
external .dae or .stl files.
roslaunch mvsim ros1_turtlebot_world.launch
ros2 launch mvsim demo_turtlebot_world.launch.py
Assuming you compiled MVSim in the directory MVSIM_ROOT,
with cmake build directory build-Release, run:
cd MVSIM_ROOT
build-Release/bin/mvsim launch mvsim_tutorial/demo_turtlebot_world.world.xml
World XML code
File: mvsim_tutorial/demo_turtlebot_world.world.xml
<!--
This "Turtlebot world" world file is intended to mimic
ROS2 Gazebo world that is launched with:
ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py
-->
<mvsim_world version="1.0">
<!-- General simulation options -->
<simul_timestep>0</simul_timestep> <!-- Simulation fixed-time interval for numerical integration [seconds] or 0 to autodetermine -->
<!-- <joystick_enabled>true</joystick_enabled> -->
<!-- GUI options -->
<gui>
<ortho>false</ortho>
<show_forces>false</show_forces> <force_scale>0.01</force_scale>
<cam_distance>10</cam_distance>
<cam_azimuth>180</cam_azimuth>
<cam_elevation>70</cam_elevation>
<fov_deg>60</fov_deg>
<refresh_fps>60</refresh_fps>
<!-- <follow_vehicle>r1</follow_vehicle> -->
</gui>
<!-- Light parameters -->
<lights>
<enable_shadows>true</enable_shadows>
<!-- <shadow_map_size>4096</shadow_map_size> -->
<light_azimuth_deg>-20.0</light_azimuth_deg>
<light_elevation_deg>70.0</light_elevation_deg>
<!-- clip planes for shadow calculation -->
<light_clip_plane_min>0.1</light_clip_plane_min>
<light_clip_plane_max>100</light_clip_plane_max>
<!-- Tuning parameters for shadow rendering anti acne corrections. These should change if light_clip_* change -->
<shadow_bias>1e-5</shadow_bias>
<shadow_bias_cam2frag>1e-5</shadow_bias_cam2frag>
<shadow_bias_normal>1e-3</shadow_bias_normal>
</lights>
<!-- ========================
Scenario definition
======================== -->
<!-- ground -->
<element class="horizontal_plane">
<cull_face>BACK</cull_face>
<x_min>-20</x_min>
<y_min>-20</y_min>
<x_max> 20</x_max>
<y_max> 20</y_max>
<z>0.0</z>
</element>
<!-- =============================
Vehicle classes definition
============================= -->
<include file="../definitions/turtlebot3_burger.vehicle.xml"
default_sensors="true"
/>
<!-- ========================
Vehicle(s) definition
======================== -->
<vehicle name="r1" class="turtlebot3_burger">
<init_pose>-2 -0.5 0</init_pose> <!-- In global coords: x,y, yaw(deg) -->
</vehicle>
<!-- ======================================
World
====================================== -->
<walls>
<color>#404040</color>
<wallThickness>0.3</wallThickness>
<wallHeight>1.0</wallHeight>
<!-- Walls shape must contain pairs of <pt>s defining wall segments -->
<shape>
<pt>-3 0</pt> <pt>-2 -2.75</pt>
<pt>-2 -2.75</pt> <pt>2 -2.75</pt>
<pt>2 -2.75</pt> <pt>3.5 0</pt>
<pt>3.5 0</pt> <pt>2 2.75</pt>
<pt>2 2.75</pt> <pt>-2 2.75</pt>
<pt>-2 2.75</pt> <pt>-3 0</pt>
</shape>
</walls>
<block:class name="green_column_small">
<static>true</static> <!-- Does not move -->
<color>#00ff00</color>
<zmin>0</zmin> <zmax>2</zmax>
<shape_from_visual/> <!-- automatic collision shape from 3D model -->
<geometry type="cylinder" radius="0.75" length="2.0" vertex_count="6"/>
</block:class>
<block:class name="green_column_large">
<static>true</static> <!-- Does not move -->
<color>#00ff00</color>
<zmin>0</zmin> <zmax>2</zmax>
<shape_from_visual/> <!-- automatic collision shape from 3D model -->
<geometry type="cylinder" radius="1.25" length="2.0" vertex_count="6"/>
</block:class>
<!-- obstacle columns: radius=0.15m height=0.5m -->
<block:class name="white_column">
<static>true</static> <!-- Does not move -->
<color>#e0e0e0</color>
<zmin>0</zmin> <zmax>0.5</zmax>
<shape_from_visual/> <!-- automatic collision shape from 3D model -->
<geometry type="cylinder" radius="0.15" length="0.5" vertex_count="16"/>
</block:class>
<block class="green_column_small"> <init_pose>-2 -2.75 0</init_pose> </block>
<block class="green_column_small"> <init_pose>+2 -2.75 0</init_pose> </block>
<block class="green_column_small"> <init_pose>-2 +2.75 0</init_pose> </block>
<block class="green_column_small"> <init_pose>+2 +2.75 0</init_pose> </block>
<block class="green_column_large"> <init_pose>3 0 0</init_pose> </block>
<for var="iX" from="0" to="2">
<for var="iY" from="0" to="2">
<block class="white_column">
<init_pose>$f{1.1*(iX-1)} $f{1.1*(iY-1)} 0</init_pose>
</block>
</for>
</for>
</mvsim_world>