diff --git a/CMakeLists.txt b/CMakeLists.txt
index a261ce51c8..351aa3b631 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR)
#============================================================================
# Initialize the project
#============================================================================
-project(ignition-gazebo6 VERSION 6.1.0)
+project(ignition-gazebo6 VERSION 6.2.0)
#============================================================================
# Find ignition-cmake
@@ -50,7 +50,7 @@ set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
# as protobuf could be find transitively by any dependency
set(protobuf_MODULE_COMPATIBLE TRUE)
-ign_find_package(sdformat12 REQUIRED VERSION 12.1)
+ign_find_package(sdformat12 REQUIRED VERSION 12.3)
set(SDF_VER ${sdformat12_VERSION_MAJOR})
#--------------------------------------
@@ -99,7 +99,7 @@ ign_find_package (Qt5
#--------------------------------------
# Find ignition-physics
-ign_find_package(ignition-physics5
+ign_find_package(ignition-physics5 VERSION 5.1
COMPONENTS
heightmap
mesh
diff --git a/Changelog.md b/Changelog.md
index 917a089b79..b4a2011901 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,104 @@
## Ignition Gazebo 6.x
+### Ignition Gazebo 6.X.X (202X-XX-XX)
+
+### Ignition Gazebo 6.2.0 (2021-11-16)
+
+1. Configurable joint state publisher's topic
+ * [Pull request #1076](https://github.com/ignitionrobotics/ign-gazebo/pull/1076)
+
+1. Thruster plugin: add tests and velocity control
+ * [Pull request #1190](https://github.com/ignitionrobotics/ign-gazebo/pull/1190)
+
+1. Prevent creation of spurious `` elements when saving worlds
+ * [Pull request #1192](https://github.com/ignitionrobotics/ign-gazebo/pull/1192)
+
+1. Add `sdfString` to `ServerConfig`'s copy constructor.
+ * [Pull request #1185](https://github.com/ignitionrobotics/ign-gazebo/pull/1185)
+
+1. Added support for tracked vehicles
+ * [Pull request #869](https://github.com/ignitionrobotics/ign-gazebo/pull/869)
+
+1. Add components to dynamically set joint limits
+ * [Pull request #847](https://github.com/ignitionrobotics/ign-gazebo/pull/847)
+
+1. Remove bounding box when entities are removed
+ * [Pull request #1053](https://github.com/ignitionrobotics/ign-gazebo/pull/1053)
+ * [Pull request #1213](https://github.com/ignitionrobotics/ign-gazebo/pull/1213)
+
+1. Fix updating component from state
+ * [Pull request #1181](https://github.com/ignitionrobotics/ign-gazebo/pull/1181)
+
+1. Extend odom publisher to allow 3D
+ * [Pull request #1180](https://github.com/ignitionrobotics/ign-gazebo/pull/1180)
+
+1. Support copy/paste
+ * [Pull request #1013](https://github.com/ignitionrobotics/ign-gazebo/pull/1013)
+
+1. Tweaks install instructions
+ * [Pull request #1078](https://github.com/ignitionrobotics/ign-gazebo/pull/1078)
+
+1. Publish 10 world stats msgs/sec instead of 5
+ * [Pull request #1163](https://github.com/ignitionrobotics/ign-gazebo/pull/1163)
+
+1. Add functionality to add entities via the entity tree
+ * [Pull request #1101](https://github.com/ignitionrobotics/ign-gazebo/pull/1101)
+
+1. Get updated GUI ECM info when a user presses 'play'
+ * [Pull request #1109](https://github.com/ignitionrobotics/ign-gazebo/pull/1109)
+
+1. Create expanding type header to reduce code duplication
+ * [Pull request #1169](https://github.com/ignitionrobotics/ign-gazebo/pull/1169)
+
+1. `minimal_scene.sdf` example: add `camera_clip` params
+ * [Pull request #1166](https://github.com/ignitionrobotics/ign-gazebo/pull/1166)
+
+1. Sensor systems work if loaded after sensors
+ * [Pull request #1104](https://github.com/ignitionrobotics/ign-gazebo/pull/1104)
+
+1. Support printing sensors using `ign model`
+ * [Pull request #1157](https://github.com/ignitionrobotics/ign-gazebo/pull/1157)
+
+1. Set camera clipping plane distances from the GUI
+ * [Pull request #1162](https://github.com/ignitionrobotics/ign-gazebo/pull/1162)
+
+1. Fix generation of systems library symlinks in build directory
+ * [Pull request #1160](https://github.com/ignitionrobotics/ign-gazebo/pull/1160)
+
+1. Add a default value for `isHeadlessRendering`.
+ * [Pull request #1151](https://github.com/ignitionrobotics/ign-gazebo/pull/1151)
+
+1. Component inspector
+
+ 1. Edit material colors
+ * [Pull request #1123](https://github.com/ignitionrobotics/ign-gazebo/pull/1123)
+ * [Pull request #1186](https://github.com/ignitionrobotics/ign-gazebo/pull/1186)
+
+ 1. Fix integers and floats
+ * [Pull request #1143](https://github.com/ignitionrobotics/ign-gazebo/pull/1143)
+
+ 1. Prevent a segfault when updating
+ * [Pull request #1167](https://github.com/ignitionrobotics/ign-gazebo/pull/1167)
+
+ 1. Use `uint64_t` for Entity IDs
+ * [Pull request #1144](https://github.com/ignitionrobotics/ign-gazebo/pull/1144)
+
+1. Support setting the background color for sensors
+ * [Pull request #1147](https://github.com/ignitionrobotics/ign-gazebo/pull/1147)
+
+1. Select top level entity not visual
+ * [Pull request #1150](https://github.com/ignitionrobotics/ign-gazebo/pull/1150)
+
+1. Update create entity offset on GUI side
+ * [Pull request #1145](https://github.com/ignitionrobotics/ign-gazebo/pull/1145)
+
+1. Update Select Entities GUI plugin to use Entity type
+ * [Pull request #1146](https://github.com/ignitionrobotics/ign-gazebo/pull/1146)
+
+1. Notify other GUI plugins of added/removed entities via GUI events
+ * [Pull request #1138](https://github.com/ignitionrobotics/ign-gazebo/pull/1138)
+ * [Pull request #1213](https://github.com/ignitionrobotics/ign-gazebo/pull/1213)
+
### Ignition Gazebo 6.1.0 (2021-10-25)
1. Updates to camera video record from subt
@@ -267,6 +366,46 @@
## Ignition Gazebo 5.x
+### Ignition Gazebo 5.X.X (202X-XX-XX)
+
+### Ignition Gazebo 5.3.0 (2021-11-12)
+
+1. Prevent creation of spurious elements when saving worlds
+ * [Pull request #1192](https://github.com/ignitionrobotics/ign-gazebo/pull/1192)
+
+1. Added support for tracked vehicles
+ * [Pull request #869](https://github.com/ignitionrobotics/ign-gazebo/pull/869)
+
+1. Add components to dynamically set joint limits
+ * [Pull request #847](https://github.com/ignitionrobotics/ign-gazebo/pull/847)
+
+1. Fix updating component from state
+ * [Pull request #1181](https://github.com/ignitionrobotics/ign-gazebo/pull/1181)
+
+1. Extend odom publisher to allow 3D
+ * [Pull request #1180](https://github.com/ignitionrobotics/ign-gazebo/pull/1180)
+
+1. Fix updating a component's data via SerializedState msg
+ * [Pull request #1131](https://github.com/ignitionrobotics/ign-gazebo/pull/1131)
+
+1. Sensor systems work if loaded after sensors
+ * [Pull request #1104](https://github.com/ignitionrobotics/ign-gazebo/pull/1104)
+
+1. Fix generation of systems library symlinks in build directory
+ * [Pull request #1160](https://github.com/ignitionrobotics/ign-gazebo/pull/1160)
+
+1. Edit material colors in component inspector
+ * [Pull request #1123](https://github.com/ignitionrobotics/ign-gazebo/pull/1123)
+
+1. Support setting the background color for sensors
+ * [Pull request #1147](https://github.com/ignitionrobotics/ign-gazebo/pull/1147)
+
+1. Use `uint64_t` for ComponentInspector Entity IDs
+ * [Pull request #1144](https://github.com/ignitionrobotics/ign-gazebo/pull/1144)
+
+1. Fix integers and floats on component inspector
+ * [Pull request #1143](https://github.com/ignitionrobotics/ign-gazebo/pull/1143)
+
### Ignition Gazebo 5.2.0 (2021-10-22)
1. Fix performance level test flakiness
@@ -437,7 +576,7 @@
1. Fix blender sdf export script and remove .material file from collada light export test
* [Pull request #923](https://github.com/ignitionrobotics/ign-gazebo/pull/923)
-1. Heightmap physics (with DART)
+1. Heightmap physics (with DART)
* [Pull request #661](https://github.com/ignitionrobotics/ign-gazebo/pull/661)
1. Adds Mesh Tutorial
@@ -1324,6 +1463,40 @@
## Ignition Gazebo 3.x
+### Ignition Gazebo 3.X.X (20XX-XX-XX)
+
+### Ignition Gazebo 3.12.0 (2021-11-11)
+
+1. Prevent creation of spurious `` elements when saving worlds
+ * [Pull request #1192](https://github.com/ignitionrobotics/ign-gazebo/pull/1192)
+
+1. Added support for tracked vehicles
+ * [Pull request #869](https://github.com/ignitionrobotics/ign-gazebo/pull/869)
+
+1. Add components to dynamically set joint limits
+ * [Pull request #847](https://github.com/ignitionrobotics/ign-gazebo/pull/847)
+
+1. Fix updating a component's data via SerializedState msg
+ * [Pull request #1149](https://github.com/ignitionrobotics/ign-gazebo/pull/1149)
+
+1. Sensor systems work if loaded after sensors
+ * [Pull request #1104](https://github.com/ignitionrobotics/ign-gazebo/pull/1104)
+
+1. Fix generation of systems library symlinks in build directory
+ * [Pull request #1160](https://github.com/ignitionrobotics/ign-gazebo/pull/1160)
+
+1. Backport gazebo::Util::validTopic() from ign-gazebo4.
+ * [Pull request #1153](https://github.com/ignitionrobotics/ign-gazebo/pull/1153)
+
+1. Support setting the background color for sensors
+ * [Pull request #1147](https://github.com/ignitionrobotics/ign-gazebo/pull/1147)
+
+1. Use uint64_t for ComponentInspector Entity IDs
+ * [Pull request #1144](https://github.com/ignitionrobotics/ign-gazebo/pull/1144)
+
+1. Fix integers and floats on component inspector
+ * [Pull request #1143](https://github.com/ignitionrobotics/ign-gazebo/pull/1143)
+
### Ignition Gazebo 3.11.0 (2021-10-21)
1. Updates to camera video record from subt.
diff --git a/Migration.md b/Migration.md
index 7375f9b33e..4fbe67cda4 100644
--- a/Migration.md
+++ b/Migration.md
@@ -5,6 +5,11 @@ Deprecated code produces compile-time warnings. These warning serve as
notification to users that their code should be upgraded. The next major
release will remove the deprecated code.
+## Ignition Gazebo 6.1 to 6.2
+
+* If no `` is given to the `Thruster` plugin, the namespace now
+ defaults to the model name, instead of an empty string.
+
## Ignition Gazebo 5.x to 6.x
* The ParticleEmitter system is deprecated. Please use the ParticleEmitter2
@@ -68,6 +73,11 @@ since pose information is being logged in the `changed_state` topic.
* The `gui.config` and `server.config` files are now located in a versioned
folder inside `$HOME/.ignition/gazebo`, i.e. `$HOME/.ignition/gazebo/6/gui.config`.
+## Ignition Gazebo 5.2 to 5.3
+
+* If no `` is given to the `Thruster` plugin, the namespace now
+ defaults to the model name, instead of an empty string.
+
## Ignition Gazebo 4.x to 5.x
* Use `cli` component of `ignition-utils1`.
diff --git a/examples/worlds/auv_controls.sdf b/examples/worlds/auv_controls.sdf
index e82596c152..224ed03ef5 100644
--- a/examples/worlds/auv_controls.sdf
+++ b/examples/worlds/auv_controls.sdf
@@ -1,4 +1,30 @@
+
@@ -23,11 +49,6 @@
filename="ignition-gazebo-scene-broadcaster-system"
name="ignition::gazebo::systems::SceneBroadcaster">
-
-
-
@@ -143,4 +164,4 @@
-
\ No newline at end of file
+
diff --git a/examples/worlds/conveyor.sdf b/examples/worlds/conveyor.sdf
new file mode 100644
index 0000000000..4769da875b
--- /dev/null
+++ b/examples/worlds/conveyor.sdf
@@ -0,0 +1,349 @@
+
+
+
+
+
+ 0.004
+ 1.0
+
+
+
+
+
+
+
+
+
+ 1.0 1.0 1.0
+ 0.8 0.8 0.8
+
+
+
+ true
+ 0 0 10 0 0 0
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+ 1000
+ 0.9
+ 0.01
+ 0.001
+
+ -0.5 0.1 -0.9
+
+
+
+
+ 1
+
+ 0 0 0 0 0 0
+
+ 6.06
+
+ 0.002731
+ 0
+ 0
+ 0.032554
+ 1.5e-05
+ 0.031391
+
+
+
+ 0 0 0 0 0 0
+
+
+ 5 0.2 0.1
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+ 2.5 0 0 -1.570796327 0 0
+
+
+ 0.2
+ 0.05
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+ -2.5 0 0 -1.570796327 0 0
+
+
+ 0.2
+ 0.05
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+ 0 0 0 0 0 0
+
+
+ 5 0.2 0.1
+
+
+
+
+ 2.5 0 0 -1.570796327 0 0
+
+
+ 0.2
+ 0.05
+
+
+
+
+ -2.5 0 0 -1.570796327 0 0
+
+
+ 0.2
+ 0.05
+
+
+
+ 1
+ 0
+
+
+
+ base_link
+
+
+
+
+
+
+ 87
+
+
+
+
+
+
+
+ 88
+
+
+
+
+
+
+
+ 83
+
+
+
+
+
+
+ 0 0 1 0 0 0
+
+
+ 1.06
+
+ 0.01
+ 0
+ 0
+ 0.01
+ 0
+ 0.01
+
+
+
+ 0 0 0 0 0 0
+
+
+ 0.1 0.1 0.1
+
+
+
+ 1 1 1 1
+
+
+
+
+
+ 0.1 0.1 0.1
+
+
+ 0 0 0 0 0 0
+
+
+
+
+
+
+
+
+ 3D View
+ false
+ docked
+
+
+ ogre2
+ scene
+ 0.4 0.4 0.4
+ 0.8 0.8 0.8
+ -6 0 6 0 0.5 0
+
+
+
+
+
+ World control
+ false
+ false
+ 72
+ 121
+ 1
+
+ floating
+
+
+
+
+
+
+ true
+ true
+ true
+
+
+
+
+
+
+ World stats
+ false
+ false
+ 110
+ 290
+ 1
+
+ floating
+
+
+
+
+
+
+ true
+ true
+ true
+ true
+
+
+
+
+
+ Transform control
+
+
+
+
+ false
+ 230
+ 50
+ floating
+ false
+ #666666
+
+
+
+
+
+
+
+
+
+
+ false
+ 200
+ 50
+ floating
+ false
+ #666666
+
+
+
+
+
+
+
+
+
+ false
+ 5
+ 5
+ floating
+ false
+
+
+
+
+
+ Visualize Contacts
+
+
+
+
+ false
+ 230
+ 50
+ floating
+ false
+ #ffffff
+
+
+
+
+
diff --git a/examples/worlds/multicopter_velocity_control.sdf b/examples/worlds/multicopter_velocity_control.sdf
index 57e5bed01f..effbeeafff 100644
--- a/examples/worlds/multicopter_velocity_control.sdf
+++ b/examples/worlds/multicopter_velocity_control.sdf
@@ -12,6 +12,10 @@ You can use the velocity controller and command linear velocity and yaw angular
ign topic -t "/X3/gazebo/command/twist" -m ignition.msgs.Twist -p " "
+ Listen to odometry:
+
+ ign topic -e -t "/model/x3/odometry"
+
Send commands to the hexacopter to go straight up:
@@ -20,6 +24,11 @@ You can use the velocity controller and command linear velocity and yaw angular
To hover
ign topic -t "/X4/gazebo/command/twist" -m ignition.msgs.Twist -p " "
+
+ Listen to odometry:
+
+ ign topic -e -t "/model/X4/odometry"
+
-->
@@ -210,6 +219,11 @@ You can use the velocity controller and command linear velocity and yaw angular
+
+ 3
+
0 3 1 0 0 0
@@ -400,6 +414,11 @@ You can use the velocity controller and command linear velocity and yaw angular
+
+ 3
+
diff --git a/examples/worlds/sensors.sdf b/examples/worlds/sensors.sdf
index 8574650335..16e1026ae2 100644
--- a/examples/worlds/sensors.sdf
+++ b/examples/worlds/sensors.sdf
@@ -35,6 +35,10 @@
filename="ignition-gazebo-magnetometer-system"
name="ignition::gazebo::systems::Magnetometer">
+
+
@@ -210,5 +214,71 @@
+
+
+ true
+
+
+
+ 0 0 2.0 0 0 0
+
+
+ 0.100000
+ 0.000000
+ 0.000000
+ 0.100000
+ 0.000000
+ 0.100000
+
+ 10.000000
+
+
+
+
+ 0.100000
+
+
+
+
+ 0 0 -0.75 0 0 0
+
+
+ 0.0100000
+ 1.5
+
+
+
+
+
+
+ 0.100000
+
+
+
+
+
+ world
+ base_plate
+
+
+ base_plate
+ link_1
+ 0 0 -1.5 0 0 0
+
+
+ -1.57079
+ 1.57079
+
+
+ 0.000000
+ 0.000000
+
+ 1.000000 0.000000 0.000000
+
+
+ 10
+
+
+
diff --git a/examples/worlds/tracked_vehicle_simple.sdf b/examples/worlds/tracked_vehicle_simple.sdf
new file mode 100644
index 0000000000..cf9cd29acc
--- /dev/null
+++ b/examples/worlds/tracked_vehicle_simple.sdf
@@ -0,0 +1,1822 @@
+
+
+
+
+ 0.004
+ 1.0
+
+
+
+
+
+ 1 1 1 1
+ 0.8 0.8 0.8 1
+ 1
+
+
+ 1
+ 0 0 10 0 0 0
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+ 1000
+ 0.9
+ 0.01
+ 0.001
+
+ -0.5 0.1 -0.9
+
+
+ 1
+
+
+
+
+ 0 0 1
+ 100 100
+
+
+
+
+
+
+ 0 0 1
+ 100 100
+
+
+
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+ 0.8 0.8 0.8 1
+
+
+
+
+
+ 3 0 0.1 0 0 0
+
+ 0 0 0 0 0 0
+
+ -0.122 0 0.118 1.5708 0 0
+ 13.14
+
+ 0.10019
+ 0
+ 0
+ 0.345043
+ 0
+ 0.302044
+
+
+
+ -0.122 0 0.118 0 0 0
+
+
+ 0.50017 0.24093 0.139
+
+
+
+
+ -0.122 0 0.118 0 0 0
+
+
+ 0.50017 0.24093 0.139
+
+
+
+ 0
+ 1
+ 0
+
+
+ 0 0.1985 0 0 0 0
+
+ 0 0 0.0141 0 0 0
+ 6.06
+
+ 0.002731
+ 0
+ 0
+ 0.032554
+ 1.5e-05
+ 0.031391
+
+
+
+ 0 0 0.01855 1.5708 0 1.5708
+
+
+ 0.09728 0.18094 0.5
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+ 0.25 0 0.01855 1.5708 0 0
+
+
+ 0.09728
+ 0.09047
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+ -0.25 0 0.01855 1.5708 0 0
+
+
+ 0.09728
+ 0.09047
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+ 0 0 0.01855 1.5708 0 1.5708
+
+
+ 0.09728 0.18094 0.5
+
+
+
+
+ 0.25 0 0.01855 1.5708 0 0
+
+
+ 0.09728
+ 0.09047
+
+
+
+
+ -0.25 0 0.01855 1.5708 0 0
+
+
+ 0.09728
+ 0.09047
+
+
+
+ 1
+ 0
+
+
+ left_track
+ base_link
+
+
+ 0 -0.1985 0 0 0 0
+
+ 0 0 0.0141 0 0 0
+ 6.06
+
+ 0.002731
+ 0
+ 0
+ 0.032554
+ 1.5e-05
+ 0.031391
+
+
+
+ 0 0 0.01855 1.5708 0 1.5708
+
+
+ 0.09728 0.18094 0.5
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+ 0.25 0 0.01855 1.5708 0 0
+
+
+ 0.09728
+ 0.09047
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+ -0.25 0 0.01855 1.5708 0 0
+
+
+ 0.09728
+ 0.09047
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+ 0 0 0.01855 1.5708 0 1.5708
+
+
+ 0.09728 0.18094 0.5
+
+
+
+
+ 0.25 0 0.01855 1.5708 0 0
+
+
+ 0.09728
+ 0.09047
+
+
+
+
+ -0.25 0 0.01855 1.5708 0 0
+
+
+ 0.09728
+ 0.09047
+
+
+
+ 1
+ 0
+
+
+ right_track
+ base_link
+
+
+ 0.25 0.272 0.0195 0 -0.5 0
+
+ 0.08 0 0 0 0 0
+ 0.75
+
+ 0.0017491
+ 2.8512e-07
+ 0.0018277
+ 0.012277
+ -3.6288e-07
+ 0.010941
+
+
+
+ 0 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.089
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ 0.33 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.029
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ 0.165 0 0.0325 0 0.184162 0
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ 0.165 0 -0.0325 0 -0.184162 0
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ 0.166 0 0.004 0 -0.02 0
+
+
+ 0.2 0.04981 0.07
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ 0 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.089
+
+
+
+
+ 0.33 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.029
+
+
+
+
+ 0.165 0 0.0325 0 0.184162 0
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+ 0.165 0 -0.0325 0 -0.184162 0
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+ 0.166 0 0.004 0 -0.02 0
+
+
+ 0.2 0.04981 0.07
+
+
+
+ 1
+
+ 1
+ 0
+
+
+ front_left_flipper
+ left_track
+
+ 0 1 0
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+
+
+ 1
+ 1
+
+ 0
+ 0.2
+
+
+
+
+
+ -0.25 0.272 0.0195 3.14159 -0.5 3.14159
+
+ 0.08 0 0 0 0 0
+ 0.75
+
+ 0.0017491
+ 2.8512e-07
+ 0.0018277
+ 0.012277
+ -3.6288e-07
+ 0.010941
+
+
+
+ 0 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.089
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ 0.33 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.029
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ 0.165 0 0.0325 0 0.184162 0
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ 0.165 0 -0.0325 0 -0.184162 0
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ 0.166 0 0.004 0 -0.02 0
+
+
+ 0.2 0.04981 0.07
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ 0 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.089
+
+
+
+
+ 0.33 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.029
+
+
+
+
+ 0.165 0 0.0325 0 0.184162 0
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+ 0.165 0 -0.0325 0 -0.184162 0
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+ 0.166 0 0.004 0 -0.02 0
+
+
+ 0.2 0.04981 0.07
+
+
+
+ 1
+
+ 1
+ 0
+
+
+ rear_left_flipper
+ left_track
+
+ 0 1 0
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+
+
+ 1
+ 1
+
+ 0
+ 0.2
+
+
+
+
+
+ 0.25 -0.272 0.0195 3.14159 0.5 3.14159
+
+ -0.08 0 0 0 0 0
+ 0.75
+
+ 0.0017491
+ 2.8512e-07
+ 0.0018277
+ 0.012277
+ -3.6288e-07
+ 0.010941
+
+
+
+ 0 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.089
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ -0.33 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.029
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ -0.165 0 0.0325 0 0.184162 -3.14159
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ -0.165 0 -0.0325 0 -0.184162 -3.14159
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ -0.166 0 0.004 0 -0.02 -3.14159
+
+
+ 0.2 0.04981 0.07
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ 0 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.089
+
+
+
+
+ -0.33 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.029
+
+
+
+
+ -0.165 0 0.0325 0 0.184162 -3.14159
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+ -0.165 0 -0.0325 0 -0.184162 -3.14159
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+ -0.166 0 0.004 0 -0.02 -3.14159
+
+
+ 0.2 0.04981 0.07
+
+
+
+ 1
+
+ 1
+ 0
+
+
+ front_right_flipper
+ right_track
+
+ 0 1 0
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+
+
+ 1
+ 1
+
+ 0
+ 0.2
+
+
+
+
+
+ -0.25 -0.272 0.0195 0 0.5 0
+
+ -0.08 0 0 0 0 0
+ 0.75
+
+ 0.0017491
+ 2.8512e-07
+ 0.0018277
+ 0.012277
+ -3.6288e-07
+ 0.010941
+
+
+
+ 0 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.089
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ -0.33 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.029
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ -0.165 0 0.0325 0 0.184162 -3.14159
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ -0.165 0 -0.0325 0 -0.184162 -3.14159
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ -0.166 0 0.004 0 -0.02 -3.14159
+
+
+ 0.2 0.04981 0.07
+
+
+
+
+
+ 0.7
+ 150
+ 0 1 0
+
+
+
+
+
+
+ 20
+
+
+ 0 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.089
+
+
+
+
+ -0.33 0 0 1.5708 0 0
+
+
+ 0.04981
+ 0.029
+
+
+
+
+ -0.165 0 0.0325 0 0.184162 -3.14159
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+ -0.165 0 -0.0325 0 -0.184162 -3.14159
+
+
+ 0.33 0.04981 0.055
+
+
+
+
+ -0.166 0 0.004 0 -0.02 -3.14159
+
+
+ 0.2 0.04981 0.07
+
+
+
+ 1
+
+ 1
+ 0
+
+
+ rear_right_flipper
+ right_track
+
+ 0 1 0
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+
+
+ 1
+ 1
+
+ 0
+ 0.2
+
+
+
+
+
+
+ left_track
+ front_left_flipper
+ rear_left_flipper
+ right_track
+ front_right_flipper
+ rear_right_flipper
+ 0.4
+ 0.18094
+ 0.5
+
+
+
+ left_track
+ -1.0
+ 1.0
+
+
+
+ right_track
+ -1.0
+ 1.0
+
+
+ front_left_flipper
+ -1.0
+ 1.0
+
+
+ rear_left_flipper
+ -1.0
+ 1.0
+
+
+ front_right_flipper
+ -1.0
+ 1.0
+
+
+ rear_right_flipper
+ -1.0
+ 1.0
+
+
+
+
+
+ 87
+
+
+
+
+
+
+
+ 88
+
+
+
+
+
+
+
+ 83
+
+
+
+
+
+
+
+ 65
+
+
+
+
+
+
+
+ 68
+
+
+
+
+
+
+
+ 81
+
+
+
+
+
+
+
+ 69
+
+
+
+
+
+
+
+ 90
+
+
+
+
+
+
+
+ 67
+
+
+
+
+
+ 7 0 0 0 0 1.5708
+
+
+ 0 1.6625 0.0375 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 1.6625 0.0375 0 0 0
+
+
+ 0 1.4875 0.1125 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 1.4875 0.1125 0 0 0
+
+
+ 0 1.3125 0.1875 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 1.3125 0.1875 0 0 0
+
+
+ 0 1.1375 0.2625 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 1.1375 0.2625 0 0 0
+
+
+ 0 0.9625 0.3375 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 0.9625 0.3375 0 0 0
+
+
+ 0 0.7875 0.4125 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 0.7875 0.4125 0 0 0
+
+
+ 0 0.6125 0.4875 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 0.6125 0.4875 0 0 0
+
+
+ 0 0.4375 0.5625 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 0.4375 0.5625 0 0 0
+
+
+ 0 0.2625 0.6375 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 0.2625 0.6375 0 0 0
+
+
+ 0 0.0875 0.7125 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 0.0875 0.7125 0 0 0
+
+
+ 0 -0.0875 0.7875 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 -0.0875 0.7875 0 0 0
+
+
+ 0 -0.2625 0.8625 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 -0.2625 0.8625 0 0 0
+
+
+ 0 -0.4375 0.9375 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 -0.4375 0.9375 0 0 0
+
+
+ 0 -0.6125 1.0125 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 -0.6125 1.0125 0 0 0
+
+
+ 0 -0.7875 1.0875 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 -0.7875 1.0875 0 0 0
+
+
+ 0 -0.9625 1.1625 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 -0.9625 1.1625 0 0 0
+
+
+ 0 -1.1375 1.2375 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 -1.1375 1.2375 0 0 0
+
+
+ 0 -1.3125 1.3125 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 -1.3125 1.3125 0 0 0
+
+
+ 0 -1.4875 1.3875 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 -1.4875 1.3875 0 0 0
+
+
+ 0 -1.6625 1.4625 0 0 0
+
+
+ 1 0.175 0.075
+
+
+
+ 1 1 1 1
+
+
+ 0
+
+
+
+
+
+ 1 0.175 0.075
+
+
+ 0 -1.6625 1.4625 0 0 0
+
+
+ 1
+
+
+ 1
+ 0 0 -0.06 0 0 1.5708
+
+
+ 0 0 0 0 1.5708 0
+
+
+ 0.15
+ 0.8
+
+
+
+
+
+ 1
+
+
+
+
+
+ 0 0 0 0 1.5708 0
+
+
+ 0.15
+ 0.8
+
+
+
+
+
+
+ 1
+ 2 2 0.028 1.7821 0 1.5708
+
+
+ 0 0 0 0 0 0
+
+
+ 0.85 0.15 0.5
+
+
+
+
+
+ 1
+
+
+
+
+
+ 0 0 0 0 0 0
+
+
+ 0.85 0.15 0.5
+
+
+
+
+
+
+ pallet
+ 2 -2 0.1 0 0 0
+ https://fuel.ignitionrobotics.org/1.0/openrobotics/models/Euro pallet
+
+
+
+
+
+ 3D View
+ 0
+ docked
+
+ ogre2
+ scene
+ 0.4 0.4 0.4
+ 0.8 0.8 0.8
+ -6 0 6 0 0.5 0
+
+
+
+ World control
+ 0
+ 0
+ 72
+ 121
+ 1
+ floating
+
+
+
+
+
+ 1
+ 1
+ 1
+
+
+
+ World stats
+ 0
+ 0
+ 110
+ 290
+ 1
+ floating
+
+
+
+
+
+ 1
+ 1
+ 1
+ 1
+
+
+
+ Transform control
+
+
+
+
+ 0
+ 230
+ 50
+ floating
+ 0
+ #666666
+
+
+
+
+
+
+
+
+ 0
+ 200
+ 50
+ floating
+ 0
+ #666666
+
+
+
+
+
+
+
+
+ false
+ 5
+ 5
+ floating
+ false
+
+
+
+ 0 0 -9.8
+ 6e-06 2.3e-05 -4.2e-05
+
+
+
\ No newline at end of file
diff --git a/include/ignition/gazebo/Util.hh b/include/ignition/gazebo/Util.hh
index 9b6f83b92a..67e405659f 100644
--- a/include/ignition/gazebo/Util.hh
+++ b/include/ignition/gazebo/Util.hh
@@ -260,7 +260,6 @@ namespace ignition
/// \brief Environment variable holding paths to custom rendering engine
/// plugins.
const std::string kRenderPluginPathEnv{"IGN_GAZEBO_RENDER_ENGINE_PATH"};
-
}
}
}
diff --git a/include/ignition/gazebo/components/Collision.hh b/include/ignition/gazebo/components/Collision.hh
index 9c57c90c4c..f35f0e95d9 100644
--- a/include/ignition/gazebo/components/Collision.hh
+++ b/include/ignition/gazebo/components/Collision.hh
@@ -51,6 +51,15 @@ namespace components
serializers::CollisionElementSerializer>;
IGN_GAZEBO_REGISTER_COMPONENT("ign_gazebo_components.CollisionElement",
CollisionElement)
+
+ /// \brief A component used to enable customization of contact surface for a
+ /// collision. The customization itself is done in callback of event
+ /// CollectContactSurfaceProperties from PhysicsEvents.
+ using EnableContactSurfaceCustomization =
+ Component;
+ IGN_GAZEBO_REGISTER_COMPONENT(
+ "ign_gazebo_components.EnableContactSurfaceCustomization",
+ EnableContactSurfaceCustomization)
}
}
}
diff --git a/include/ignition/gazebo/components/JointEffortLimitsCmd.hh b/include/ignition/gazebo/components/JointEffortLimitsCmd.hh
new file mode 100644
index 0000000000..b8b9217974
--- /dev/null
+++ b/include/ignition/gazebo/components/JointEffortLimitsCmd.hh
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#ifndef IGNITION_GAZEBO_COMPONENTS_JOINTEFFORTLIMITSCMD_HH_
+#define IGNITION_GAZEBO_COMPONENTS_JOINTEFFORTLIMITSCMD_HH_
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace ignition
+{
+namespace gazebo
+{
+// Inline bracket to help doxygen filtering.
+inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
+
+namespace components
+{
+
+/// \brief Command for setting effort limits of a joint. Data are a vector
+/// with a Vector2 for each DOF. The X() component of the Vector2 specifies
+/// the minimum effort limit, the Y() component stands for maximum limit.
+/// Set to +-infinity to disable the limits.
+/// \note It is expected that the physics plugin reads this component and
+/// sets the limit to the dynamics engine. After setting it, the data of this
+/// component will be cleared (i.e. the vector will have length zero).
+using JointEffortLimitsCmd = Component<
+ std::vector,
+ class JointEffortLimitsCmdTag,
+ serializers::VectorSerializer
+>;
+
+IGN_GAZEBO_REGISTER_COMPONENT(
+ "ign_gazebo_components.JointEffortLimitsCmd", JointEffortLimitsCmd)
+}
+
+}
+}
+}
+
+#endif
diff --git a/include/ignition/gazebo/components/JointPositionLimitsCmd.hh b/include/ignition/gazebo/components/JointPositionLimitsCmd.hh
new file mode 100644
index 0000000000..775937fbff
--- /dev/null
+++ b/include/ignition/gazebo/components/JointPositionLimitsCmd.hh
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#ifndef IGNITION_GAZEBO_COMPONENTS_JOINTPOSITIONLIMITSCMD_HH_
+#define IGNITION_GAZEBO_COMPONENTS_JOINTPOSITIONLIMITSCMD_HH_
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace ignition
+{
+namespace gazebo
+{
+// Inline bracket to help doxygen filtering.
+inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
+
+namespace components
+{
+/// \brief Command for setting position limits of a joint. Data are a vector
+/// with a Vector2 for each DOF. The X() component of the Vector2 specifies
+/// the minimum positional limit, the Y() component stands for maximum limit.
+/// Set to +-infinity to disable the limits.
+/// \note It is expected that the physics plugin reads this component and
+/// sets the limit to the dynamics engine. After setting it, the data of this
+/// component will be cleared (i.e. the vector will have length zero).
+using JointPositionLimitsCmd = Component<
+ std::vector,
+ class JointPositionLimitsCmdTag,
+ serializers::VectorSerializer
+>;
+
+IGN_GAZEBO_REGISTER_COMPONENT(
+ "ign_gazebo_components.JointPositionLimitsCmd", JointPositionLimitsCmd)
+}
+}
+}
+}
+
+#endif
diff --git a/include/ignition/gazebo/components/JointVelocityLimitsCmd.hh b/include/ignition/gazebo/components/JointVelocityLimitsCmd.hh
new file mode 100644
index 0000000000..e85905095f
--- /dev/null
+++ b/include/ignition/gazebo/components/JointVelocityLimitsCmd.hh
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#ifndef IGNITION_GAZEBO_COMPONENTS_JOINTVELOCITYLIMITSCMD_HH_
+#define IGNITION_GAZEBO_COMPONENTS_JOINTVELOCITYLIMITSCMD_HH_
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace ignition
+{
+namespace gazebo
+{
+// Inline bracket to help doxygen filtering.
+inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
+
+namespace components
+{
+/// \brief Command for setting velocity limits of a joint. Data are a vector
+/// with a Vector2 for each DOF. The X() component of the Vector2 specifies
+/// the minimum velocity limit, the Y() component stands for maximum limit.
+/// Set to +-infinity to disable the limits.
+/// \note It is expected that the physics plugin reads this component and
+/// sets the limit to the dynamics engine. After setting it, the data of this
+/// component will be cleared (i.e. the vector will have length zero).
+using JointVelocityLimitsCmd = Component<
+ std::vector,
+ class JointVelocityLimitsCmdTag,
+ serializers::VectorSerializer
+>;
+
+IGN_GAZEBO_REGISTER_COMPONENT(
+ "ign_gazebo_components.JointVelocityLimitsCmd", JointVelocityLimitsCmd)
+}
+}
+}
+}
+
+#endif
diff --git a/include/ignition/gazebo/components/Serialization.hh b/include/ignition/gazebo/components/Serialization.hh
index fd2b6a5303..7ef0dd6639 100644
--- a/include/ignition/gazebo/components/Serialization.hh
+++ b/include/ignition/gazebo/components/Serialization.hh
@@ -226,6 +226,40 @@ namespace serializers
return _in;
}
};
+
+ template
+ class VectorSerializer
+ {
+ /// \brief Serialization for `std::vector` with serializable T.
+ /// \param[in] _out Output stream.
+ /// \param[in] _data The data to stream.
+ /// \return The stream.
+ public: static std::ostream &Serialize(std::ostream &_out,
+ const std::vector &_data)
+ {
+ _out << _data.size();
+ for (const auto& datum : _data)
+ _out << " " << datum;
+ return _out;
+ }
+
+ /// \brief Deserialization for `std::vector` with serializable T.
+ /// \param[in] _in Input stream.
+ /// \param[out] _data The data to populate.
+ /// \return The stream.
+ public: static std::istream &Deserialize(std::istream &_in,
+ std::vector &_data)
+ {
+ size_t size;
+ _in >> size;
+ _data.resize(size);
+ for (size_t i = 0; i < size; ++i)
+ {
+ _in >> _data[i];
+ }
+ return _in;
+ }
+ };
}
}
}
diff --git a/include/ignition/gazebo/components/VisualCmd.hh b/include/ignition/gazebo/components/VisualCmd.hh
new file mode 100644
index 0000000000..794057aabb
--- /dev/null
+++ b/include/ignition/gazebo/components/VisualCmd.hh
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#ifndef IGNITION_GAZEBO_COMPONENTS_VISUALCMD_HH_
+#define IGNITION_GAZEBO_COMPONENTS_VISUALCMD_HH_
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+namespace ignition
+{
+namespace gazebo
+{
+// Inline bracket to help doxygen filtering.
+inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
+namespace components
+{
+ /// \brief A component type that contains commanded visual of an
+ /// entity in the world frame represented by msgs::Visual.
+ using VisualCmd = Component;
+ IGN_GAZEBO_REGISTER_COMPONENT("ign_gazebo_components.VisualCmd",
+ VisualCmd)
+}
+}
+}
+}
+#endif
diff --git a/include/ignition/gazebo/gui/GuiEvents.hh b/include/ignition/gazebo/gui/GuiEvents.hh
index 353a85e805..5cb571e883 100644
--- a/include/ignition/gazebo/gui/GuiEvents.hh
+++ b/include/ignition/gazebo/gui/GuiEvents.hh
@@ -26,6 +26,8 @@
#include
#include
#include
+#include
+#include "ignition/gazebo/gui/Export.hh"
#include "ignition/gazebo/Entity.hh"
#include "ignition/gazebo/config.hh"
@@ -41,7 +43,7 @@ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
namespace events
{
/// \brief Event that notifies when new entities have been selected.
- class EntitiesSelected : public QEvent
+ class IGNITION_GAZEBO_GUI_VISIBLE EntitiesSelected : public QEvent
{
/// \brief Constructor
/// \param[in] _entities All the selected entities
@@ -79,7 +81,7 @@ namespace events
};
/// \brief Event that notifies when all entities have been deselected.
- class DeselectAllEntities : public QEvent
+ class IGNITION_GAZEBO_GUI_VISIBLE DeselectAllEntities : public QEvent
{
/// \brief Constructor
/// \param[in] _fromUser True if the event was directly generated by the
@@ -103,68 +105,60 @@ namespace events
private: bool fromUser{false};
};
- /// \brief Event that contains newly created and removed entities
- class AddedRemovedEntities : public QEvent
+ /// \brief Event that contains entities newly created or removed from the
+ /// GUI, but that aren't present on the server yet.
+ /// \sa NewRemovedEntities
+ class IGNITION_GAZEBO_GUI_VISIBLE GuiNewRemovedEntities : public QEvent
{
/// \brief Constructor
/// \param[in] _newEntities Set of newly created entities
/// \param[in] _removedEntities Set of recently removed entities
- public: AddedRemovedEntities(const std::set &_newEntities,
- const std::set &_removedEntities)
- : QEvent(kType), newEntities(_newEntities),
- removedEntities(_removedEntities)
- {
- }
+ public: GuiNewRemovedEntities(const std::set &_newEntities,
+ const std::set &_removedEntities);
/// \brief Get the set of newly created entities
- public: const std::set &NewEntities() const
- {
- return this->newEntities;
- }
+ public: const std::set &NewEntities() const;
/// \brief Get the set of recently removed entities
- public: const std::set &RemovedEntities() const
- {
- return this->removedEntities;
- }
+ public: const std::set &RemovedEntities() const;
/// \brief Unique type for this event.
static const QEvent::Type kType = QEvent::Type(QEvent::User + 3);
- /// \brief Set of newly created entities
- private: std::set newEntities;
-
- /// \brief Set of recently removed entities
- private: std::set removedEntities;
+ /// \internal
+ /// \brief Private data pointer
+ IGN_UTILS_IMPL_PTR(dataPtr)
};
- /// \brief Event that notifies when new entities have been removed.
- class RemovedEntities : public QEvent
+ /// \brief Event that notifies when new entities have been created or removed
+ /// on the server. This is a duplication of what `GuiSystem`s would get from
+ /// `EachNew` / `EachRemoved` ECM calls.
+ /// \sa GuiNewRemovedEntities
+ class IGNITION_GAZEBO_GUI_VISIBLE NewRemovedEntities : public QEvent
{
/// \brief Constructor
- /// \param[in] _entities All the removed entities
- public: explicit RemovedEntities(const std::vector &_entities)
- : QEvent(kType), entities(_entities)
- {
- }
+ /// \param[in] _newEntities Set of newly created entities
+ /// \param[in] _removedEntities Set of recently removed entities
+ public: NewRemovedEntities(const std::set &_newEntities,
+ const std::set &_removedEntities);
- /// \brief Get the data sent with the event.
- /// \return The entities being removed.
- public: std::vector Data() const
- {
- return this->entities;
- }
+ /// \brief Get the set of newly created entities
+ public: const std::set &NewEntities() const;
+
+ /// \brief Get the set of recently removed entities
+ public: const std::set &RemovedEntities() const;
/// \brief Unique type for this event.
static const QEvent::Type kType = QEvent::Type(QEvent::User + 4);
- /// \brief The removed entities.
- private: std::vector entities;
+ /// \internal
+ /// \brief Private data pointer
+ IGN_UTILS_IMPL_PTR(dataPtr)
};
/// \brief True if a transform control is currently active (translate /
/// rotate / scale). False if we're in selection mode.
- class TransformControlModeActive : public QEvent
+ class IGNITION_GAZEBO_GUI_VISIBLE TransformControlModeActive : public QEvent
{
/// \brief Constructor
/// \param[in] _tranformModeActive is the transform control mode active
diff --git a/include/ignition/gazebo/physics/Events.hh b/include/ignition/gazebo/physics/Events.hh
new file mode 100644
index 0000000000..668e19a2ad
--- /dev/null
+++ b/include/ignition/gazebo/physics/Events.hh
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_GAZEBO_PHYSICS_EVENTS_HH_
+#define IGNITION_GAZEBO_PHYSICS_EVENTS_HH_
+
+#include
+
+#include
+
+#include
+
+#include "ignition/gazebo/config.hh"
+#include "ignition/gazebo/Entity.hh"
+
+#include
+
+namespace ignition
+{
+ namespace gazebo
+ {
+ // Inline bracket to help doxygen filtering.
+ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
+
+ namespace events
+ {
+ using Policy = physics::FeaturePolicy3d;
+
+ /// \brief This event is called when the physics engine needs to collect
+ /// what customizations it should do to the surface of a contact point. It
+ /// is called during the Update phase after collision checking has been
+ /// finished and before the physics update has happened. The event
+ /// subscribers are expected to change the `params` argument.
+ using CollectContactSurfaceProperties = ignition::common::EventT<
+ void(
+ const Entity& /* collision1 */,
+ const Entity& /* collision2 */,
+ const math::Vector3d & /* point */,
+ const std::optional /* force */,
+ const std::optional /* normal */,
+ const std::optional /* depth */,
+ const size_t /* numContactsOnCollision */,
+ physics::SetContactPropertiesCallbackFeature::
+ ContactSurfaceParams& /* params */
+ ),
+ struct CollectContactSurfacePropertiesTag>;
+ }
+ } // namespace events
+ } // namespace gazebo
+} // namespace ignition
+
+#endif // IGNITION_GAZEBO_PHYSICS_EVENTS_HH_
diff --git a/include/ignition/gazebo/rendering/RenderUtil.hh b/include/ignition/gazebo/rendering/RenderUtil.hh
index 49a4a5557e..ef10b2d93e 100644
--- a/include/ignition/gazebo/rendering/RenderUtil.hh
+++ b/include/ignition/gazebo/rendering/RenderUtil.hh
@@ -113,11 +113,13 @@ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
/// \param[in] _scene Pointer to the scene.
public: void SetScene(const rendering::ScenePtr &_scene);
- /// \brief Set background color of render window
+ /// \brief Set background color of render window. This will override
+ /// other sources, such as from SDF.
/// \param[in] _color Color of render window background
public: void SetBackgroundColor(const math::Color &_color);
- /// \brief Set ambient light of render window
+ /// \brief Set ambient light of render window. This will override
+ /// other sources, such as from SDF.
/// \param[in] _ambient Color of ambient light
public: void SetAmbientLight(const math::Color &_ambient);
diff --git a/src/EntityComponentManager.cc b/src/EntityComponentManager.cc
index 5b0f482811..021368dd4f 100644
--- a/src/EntityComponentManager.cc
+++ b/src/EntityComponentManager.cc
@@ -1719,6 +1719,8 @@ void EntityComponentManager::SetState(
// Get Component
auto comp = this->ComponentImplementation(entity, type);
+ std::istringstream istr(compMsg.component());
+
// Create if new
if (nullptr == comp)
{
@@ -1729,14 +1731,12 @@ void EntityComponentManager::SetState(
<< compMsg.type() << "]" << std::endl;
continue;
}
- std::istringstream istr(compMsg.component());
newComp->Deserialize(istr);
this->CreateComponentImplementation(entity, type, newComp.get());
}
// Update component value
else
{
- std::istringstream istr(compMsg.component());
comp->Deserialize(istr);
this->dataPtr->AddModifiedComponent(entity);
}
diff --git a/src/LevelManager.cc b/src/LevelManager.cc
index 6aa156dacc..81fa242484 100644
--- a/src/LevelManager.cc
+++ b/src/LevelManager.cc
@@ -201,7 +201,7 @@ void LevelManager::ReadLevelPerformerInfo()
sdf::ElementPtr pluginElem;
// Get the ignition::gazebo plugin element
- for (auto plugin = worldElem->GetElement("plugin"); plugin;
+ for (auto plugin = worldElem->FindElement("plugin"); plugin;
plugin = plugin->GetNextElement("plugin"))
{
if (plugin->Get("name") == kPluginName)
diff --git a/src/Primitives.cc b/src/Primitives.cc
index e83880008a..9e34eac618 100644
--- a/src/Primitives.cc
+++ b/src/Primitives.cc
@@ -53,9 +53,9 @@ constexpr const char * kBoxSdf = R"(
- 0.8 0.8 0.8 1
- 0.8 0.8 0.8 1
- 0.8 0.8 0.8 1
+ 0.3 0.3 0.3 1
+ 0.7 0.7 0.7 1
+ 1 1 1 1
@@ -94,9 +94,9 @@ constexpr const char * kSphereSdf = R"(
- 0.8 0.8 0.8 1
- 0.8 0.8 0.8 1
- 0.8 0.8 0.8 1
+ 0.3 0.3 0.3 1
+ 0.7 0.7 0.7 1
+ 1 1 1 1
@@ -137,9 +137,9 @@ constexpr const char * kCylinderSdf = R"(
- 0.8 0.8 0.8 1
- 0.8 0.8 0.8 1
- 0.8 0.8 0.8 1
+ 0.3 0.3 0.3 1
+ 0.7 0.7 0.7 1
+ 1 1 1 1
@@ -180,9 +180,9 @@ constexpr const char * kCapsuleSdf = R"(
- 0.8 0.8 0.8 1
- 0.8 0.8 0.8 1
- 0.8 0.8 0.8 1
+ 0.3 0.3 0.3 1
+ 0.7 0.7 0.7 1
+ 1 1 1 1
@@ -221,9 +221,9 @@ constexpr const char *kEllipsoidSdf = R"(
- 0.8 0.8 0.8 1
- 0.8 0.8 0.8 1
- 0.8 0.8 0.8 1
+ 0.3 0.3 0.3 1
+ 0.7 0.7 0.7 1
+ 1 1 1 1
diff --git a/src/SdfGenerator.cc b/src/SdfGenerator.cc
index e2ca63bfc1..9f8b9286c2 100644
--- a/src/SdfGenerator.cc
+++ b/src/SdfGenerator.cc
@@ -26,12 +26,37 @@
#include
#include "ignition/gazebo/Util.hh"
+#include "ignition/gazebo/components/AirPressureSensor.hh"
+#include "ignition/gazebo/components/Altimeter.hh"
+#include "ignition/gazebo/components/Camera.hh"
+#include "ignition/gazebo/components/ChildLinkName.hh"
+#include "ignition/gazebo/components/ContactSensor.hh"
+#include "ignition/gazebo/components/DepthCamera.hh"
+#include "ignition/gazebo/components/ForceTorque.hh"
+#include "ignition/gazebo/components/GpuLidar.hh"
+#include "ignition/gazebo/components/Imu.hh"
+#include "ignition/gazebo/components/Inertial.hh"
+#include "ignition/gazebo/components/Joint.hh"
+#include "ignition/gazebo/components/JointAxis.hh"
+#include "ignition/gazebo/components/JointType.hh"
#include "ignition/gazebo/components/Light.hh"
+#include "ignition/gazebo/components/Link.hh"
+#include "ignition/gazebo/components/LogicalCamera.hh"
+#include "ignition/gazebo/components/Magnetometer.hh"
#include "ignition/gazebo/components/Model.hh"
#include "ignition/gazebo/components/Name.hh"
#include "ignition/gazebo/components/ParentEntity.hh"
+#include "ignition/gazebo/components/ParentLinkName.hh"
#include "ignition/gazebo/components/Pose.hh"
+#include "ignition/gazebo/components/RgbdCamera.hh"
+#include "ignition/gazebo/components/SelfCollide.hh"
+#include "ignition/gazebo/components/Sensor.hh"
#include "ignition/gazebo/components/SourceFilePath.hh"
+#include "ignition/gazebo/components/SegmentationCamera.hh"
+#include "ignition/gazebo/components/Static.hh"
+#include "ignition/gazebo/components/ThermalCamera.hh"
+#include "ignition/gazebo/components/ThreadPitch.hh"
+#include "ignition/gazebo/components/WindMode.hh"
#include "ignition/gazebo/components/World.hh"
@@ -277,7 +302,7 @@ namespace sdf_generator
// First remove child entities of whose names can be changed during
// simulation (eg. models). Then we add them back from the data in the
// ECM.
- // TODO(addisu) Remove actors and lights
+ // TODO(addisu) Remove actors
std::vector toRemove;
if (_elem->HasElement("model"))
{
@@ -287,6 +312,15 @@ namespace sdf_generator
toRemove.push_back(modelElem);
}
}
+ if (_elem->HasElement("light"))
+ {
+ for (auto lightElem = _elem->GetElement("light"); lightElem;
+ lightElem = lightElem->GetNextElement("light"))
+ {
+ toRemove.push_back(lightElem);
+ }
+ }
+
for (const auto &e : toRemove)
{
_elem->RemoveChild(e);
@@ -294,6 +328,7 @@ namespace sdf_generator
auto worldDir = common::parentPath(worldSdf->Data().Element()->FilePath());
+ // models
_ecm.Each(
[&](const Entity &_modelEntity, const components::Model *,
const components::ModelSdf *_modelSdf)
@@ -386,6 +421,21 @@ namespace sdf_generator
return true;
});
+ // lights
+ _ecm.Each(
+ [&](const Entity &_lightEntity,
+ const components::Light *,
+ const components::ParentEntity *_parent) -> bool
+ {
+ if (_parent->Data() != _entity)
+ return true;
+
+ auto lightElem = _elem->AddElement("light");
+ updateLightElement(lightElem, _ecm, _lightEntity);
+
+ return true;
+ });
+
return true;
}
@@ -397,10 +447,12 @@ namespace sdf_generator
if (!copySdf(_ecm.Component(_entity), _elem))
return false;
- // Update sdf based current components. Here are the list of components to
- // be updated:
+ // Update sdf based on current components. Here are the list of components
+ // to be updated:
// - Name
// - Pose
+ // - Static
+ // - SelfCollide
// This list is to be updated as other components become updateable during
// simulation
auto *nameComp = _ecm.Component(_entity);
@@ -421,19 +473,463 @@ namespace sdf_generator
}
poseElem->Set(poseComp->Data());
+ // static
+ auto *staticComp = _ecm.Component(_entity);
+ if (staticComp)
+ _elem->GetElement("static")->Set(staticComp->Data());
+
+ // self collide
+ auto *selfCollideComp = _ecm.Component(_entity);
+ if (selfCollideComp)
+ _elem->GetElement("self_collide")->Set(selfCollideComp->Data());
+
const auto *pathComp =
_ecm.Component(_entity);
- if (_elem->HasElement("link") && nullptr != pathComp)
+ if (_elem->HasElement("link"))
+ {
+ if (nullptr != pathComp)
+ {
+ // Update relative URIs to use absolute paths. Relative URIs work fine
+ // in included models, but they have to be converted to absolute URIs
+ // when the included model is expanded.
+ relativeToAbsoluteUri(_elem, common::parentPath(pathComp->Data()));
+ }
+
+ // update links
+ sdf::ElementPtr linkElem = _elem->GetElement("link");
+ while (linkElem)
+ {
+ std::string linkName = linkElem->Get("name");
+ auto linkEnt = _ecm.EntityByComponents(
+ components::ParentEntity(_entity), components::Name(linkName));
+ if (linkEnt != kNullEntity)
+ updateLinkElement(linkElem, _ecm, linkEnt);
+ linkElem = linkElem->GetNextElement("link");
+ }
+ }
+
+ if (_elem->HasElement("joint"))
+ {
+ // update joints
+ sdf::ElementPtr jointElem = _elem->GetElement("joint");
+ while (jointElem)
+ {
+ std::string jointName = jointElem->Get("name");
+ auto jointEnt = _ecm.EntityByComponents(
+ components::ParentEntity(_entity), components::Name(jointName));
+ if (jointEnt != kNullEntity)
+ updateJointElement(jointElem, _ecm, jointEnt);
+ jointElem = jointElem->GetNextElement("joint");
+ }
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////
+ bool updateLinkElement(const sdf::ElementPtr &_elem,
+ const EntityComponentManager &_ecm,
+ const Entity &_entity)
+ {
+ // Update sdf based on current components. Here are the list of components
+ // to be updated:
+ // - Name
+ // - Pose
+ // - Inertial
+ // - WindMode
+ // This list is to be updated as other components become updateable during
+ // simulation
+ auto *nameComp = _ecm.Component(_entity);
+ _elem->GetAttribute("name")->Set(nameComp->Data());
+
+ auto *poseComp = _ecm.Component(_entity);
+
+ auto poseElem = _elem->GetElement("pose");
+
+ // Remove all attributes of poseElem
+ for (const auto *attrName : {"relative_to", "degrees", "rotation_format"})
+ {
+ sdf::ParamPtr attr = poseElem->GetAttribute(attrName);
+ if (nullptr != attr)
+ {
+ attr->Reset();
+ }
+ }
+ poseElem->Set(poseComp->Data());
+
+ // inertial
+ auto inertialComp = _ecm.Component(_entity);
+ if (inertialComp)
{
- // Update relative URIs to use absolute paths. Relative URIs work fine in
- // included models, but they have to be converted to absolute URIs when
- // the included model is expanded.
- relativeToAbsoluteUri(_elem, common::parentPath(pathComp->Data()));
+ math::Inertiald inertial = inertialComp->Data();
+ sdf::ElementPtr inertialElem = _elem->GetElement("inertial");
+ inertialElem->GetElement("pose")->Set(inertial.Pose());
+ const math::MassMatrix3d &massMatrix = inertial.MassMatrix();
+ inertialElem->GetElement("mass")->Set(massMatrix.Mass());
+ sdf::ElementPtr inertiaElem = inertialElem->GetElement("inertia");
+ inertiaElem->GetElement("ixx")->Set(massMatrix.Ixx());
+ inertiaElem->GetElement("ixy")->Set(massMatrix.Ixy());
+ inertiaElem->GetElement("ixz")->Set(massMatrix.Ixz());
+ inertiaElem->GetElement("iyy")->Set(massMatrix.Iyy());
+ inertiaElem->GetElement("iyz")->Set(massMatrix.Iyz());
+ inertiaElem->GetElement("izz")->Set(massMatrix.Izz());
}
+
+ // wind mode
+ auto windModeComp = _ecm.Component(_entity);
+ if (windModeComp)
+ {
+ bool windMode = windModeComp->Data();
+ _elem->GetElement("enable_wind")->Set(windMode);
+ }
+
+ // update sensors
+ if (_elem->HasElement("sensor"))
+ {
+ sdf::ElementPtr sensorElem = _elem->GetElement("sensor");
+ while (sensorElem)
+ {
+ std::string sensorName = sensorElem->Get("name");
+ auto sensorEnt = _ecm.EntityByComponents(
+ components::ParentEntity(_entity), components::Name(sensorName));
+ if (sensorEnt != kNullEntity)
+ updateSensorElement(sensorElem, _ecm, sensorEnt);
+ sensorElem = sensorElem->GetNextElement("sensor");
+ }
+ }
+
+ // update lights
+ if (_elem->HasElement("light"))
+ {
+ sdf::ElementPtr lightElem = _elem->GetElement("light");
+ while (lightElem)
+ {
+ std::string lightName = lightElem->Get("name");
+ auto lightEnt = _ecm.EntityByComponents(
+ components::ParentEntity(_entity), components::Name(lightName));
+ if (lightEnt != kNullEntity)
+ updateLightElement(lightElem, _ecm, lightEnt);
+ lightElem = lightElem->GetNextElement("light");
+ }
+ }
+
return true;
}
+ /////////////////////////////////////////////////
+ bool updateSensorElement(sdf::ElementPtr _elem,
+ const EntityComponentManager &_ecm,
+ const Entity &_entity)
+ {
+ // Update sdf based on current components.
+ // This list is to be updated as other components become updateable during
+ // simulation
+ auto updateSensorNameAndPose = [&]
+ {
+ // override name and pose sdf element using values from ECM
+ auto *nameComp = _ecm.Component(_entity);
+ _elem->GetAttribute("name")->Set(nameComp->Data());
+
+ auto *poseComp = _ecm.Component(_entity);
+ auto poseElem = _elem->GetElement("pose");
+
+ // Remove all attributes of poseElem
+ for (const auto *attrName : {"relative_to", "degrees", "rotation_format"})
+ {
+ sdf::ParamPtr attr = poseElem->GetAttribute(attrName);
+ if (nullptr != attr)
+ {
+ attr->Reset();
+ }
+ }
+ poseElem->Set(poseComp->Data());
+ return true;
+ };
+
+ // camera
+ auto camComp = _ecm.Component(_entity);
+ if (camComp)
+ {
+ const sdf::Sensor &sensor = camComp->Data();
+ _elem->Copy(sensor.ToElement());
+ return updateSensorNameAndPose();
+ }
+ // depth camera
+ auto depthCamComp = _ecm.Component(_entity);
+ if (depthCamComp)
+ {
+ const sdf::Sensor &sensor = depthCamComp->Data();
+ _elem->Copy(sensor.ToElement());
+ return updateSensorNameAndPose();
+ }
+ // thermal camera
+ auto thermalCamComp = _ecm.Component(_entity);
+ if (thermalCamComp)
+ {
+ const sdf::Sensor &sensor = thermalCamComp->Data();
+ _elem->Copy(sensor.ToElement());
+ return updateSensorNameAndPose();
+ }
+ // logical camera
+ auto logicalCamComp = _ecm.Component(_entity);
+ if (logicalCamComp)
+ {
+ // components::LogicalCamera holds an sdf::ElementPtr instead of an
+ // sdf::Sensor
+ _elem = logicalCamComp->Data();
+ return updateSensorNameAndPose();
+ }
+ // segmentation camera
+ auto segmentationCamComp =
+ _ecm.Component(_entity);
+ if (segmentationCamComp)
+ {
+ const sdf::Sensor &sensor = segmentationCamComp->Data();
+ _elem->Copy(sensor.ToElement());
+ return updateSensorNameAndPose();
+ }
+
+ // gpu lidar
+ auto gpuLidarComp = _ecm.Component(_entity);
+ if (gpuLidarComp)
+ {
+ const sdf::Sensor &sensor = gpuLidarComp->Data();
+ _elem->Copy(sensor.ToElement());
+ return updateSensorNameAndPose();
+ }
+ // altimeter
+ auto altimeterComp = _ecm.Component(_entity);
+ if (altimeterComp)
+ {
+ const sdf::Sensor &sensor = altimeterComp->Data();
+ _elem->Copy(sensor.ToElement());
+ return updateSensorNameAndPose();
+ }
+ // contact
+ auto contactComp = _ecm.Component(_entity);
+ if (contactComp)
+ {
+ // components::ContactSensor holds an sdf::ElementPtr instead of an
+ // sdf::Sensor
+ _elem = contactComp->Data();
+ return updateSensorNameAndPose();
+ }
+ // air pressure
+ auto airPressureComp =
+ _ecm.Component(_entity);
+ if (airPressureComp)
+ {
+ const sdf::Sensor &sensor = airPressureComp->Data();
+ _elem->Copy(sensor.ToElement());
+ return updateSensorNameAndPose();
+ }
+ // force torque
+ auto forceTorqueComp = _ecm.Component(_entity);
+ if (forceTorqueComp)
+ {
+ const sdf::Sensor &sensor = forceTorqueComp->Data();
+ _elem->Copy(sensor.ToElement());
+ return updateSensorNameAndPose();
+ }
+ // imu
+ auto imuComp = _ecm.Component(_entity);
+ if (imuComp)
+ {
+ const sdf::Sensor &sensor = imuComp->Data();
+ _elem->Copy(sensor.ToElement());
+ return updateSensorNameAndPose();
+ }
+ // magnetometer
+ auto magnetometerComp =
+ _ecm.Component(_entity);
+ if (magnetometerComp)
+ {
+ const sdf::Sensor &sensor = magnetometerComp->Data();
+ _elem->Copy(sensor.ToElement());
+ return updateSensorNameAndPose();
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////
+ bool updateLightElement(sdf::ElementPtr _elem,
+ const EntityComponentManager &_ecm,
+ const Entity &_entity)
+ {
+ // Update sdf based on the light component
+ auto updateLightNameAndPose = [&]
+ {
+ // override name and pose sdf element using values from ECM
+ auto *nameComp = _ecm.Component(_entity);
+ _elem->GetAttribute("name")->Set(nameComp->Data());
+
+ auto *poseComp = _ecm.Component(_entity);
+ auto poseElem = _elem->GetElement("pose");
+
+ // Remove all attributes of poseElem
+ for (const auto *attrName : {"relative_to", "degrees", "rotation_format"})
+ {
+ sdf::ParamPtr attr = poseElem->GetAttribute(attrName);
+ if (nullptr != attr)
+ {
+ attr->Reset();
+ }
+ }
+ poseElem->Set(poseComp->Data());
+ return true;
+ };
+
+ // light
+ auto lightComp = _ecm.Component(_entity);
+ if (lightComp)
+ {
+ const sdf::Light &light = lightComp->Data();
+ _elem->Copy(light.ToElement());
+ return updateLightNameAndPose();
+ }
+ return true;
+ }
+
+ /////////////////////////////////////////////////
+ bool updateJointElement(sdf::ElementPtr _elem,
+ const EntityComponentManager &_ecm,
+ const Entity &_entity)
+ {
+ // Update sdf based on the joint component
+ auto updateJointNameAndPose = [&]
+ {
+ // override name and pose sdf element using values from ECM
+ auto *nameComp = _ecm.Component(_entity);
+ _elem->GetAttribute("name")->Set(nameComp->Data());
+
+ auto *poseComp = _ecm.Component(_entity);
+ auto poseElem = _elem->GetElement("pose");
+
+ // Remove all attributes of poseElem
+ for (const auto *attrName : {"relative_to", "degrees", "rotation_format"})
+ {
+ sdf::ParamPtr attr = poseElem->GetAttribute(attrName);
+ if (nullptr != attr)
+ {
+ attr->Reset();
+ }
+ }
+ poseElem->Set(poseComp->Data());
+ return true;
+ };
+
+ // joint
+ auto jointComp = _ecm.Component(_entity);
+ if (!jointComp)
+ {
+ return false;
+ }
+
+ // joint type
+ auto jointTypeComp = _ecm.Component(_entity);
+ sdf::JointType jointType = jointTypeComp->Data();
+ if (jointTypeComp)
+ {
+ std::string jointTypeStr = "invalid";
+ switch (jointType)
+ {
+ case sdf::JointType::BALL:
+ jointTypeStr = "ball";
+ break;
+ case sdf::JointType::CONTINUOUS:
+ jointTypeStr = "continuous";
+ break;
+ case sdf::JointType::FIXED:
+ jointTypeStr = "fixed";
+ break;
+ case sdf::JointType::PRISMATIC:
+ jointTypeStr = "prismatic";
+ break;
+ case sdf::JointType::GEARBOX:
+ jointTypeStr = "gearbox";
+ break;
+ case sdf::JointType::REVOLUTE:
+ jointTypeStr = "revolute";
+ break;
+ case sdf::JointType::REVOLUTE2:
+ jointTypeStr = "revolute2";
+ break;
+ case sdf::JointType::SCREW:
+ jointTypeStr = "screw";
+ break;
+ case sdf::JointType::UNIVERSAL:
+ jointTypeStr = "universal";
+ break;
+ default:
+ break;
+ }
+ _elem->GetAttribute("type")->Set(jointTypeStr);
+ }
+
+ // parent
+ auto parentLinkNameComp =
+ _ecm.Component(_entity);
+ if (parentLinkNameComp)
+ {
+ _elem->GetElement("parent")->Set(parentLinkNameComp->Data());
+ }
+ // child
+ auto childLinkNameComp = _ecm.Component(_entity);
+ if (childLinkNameComp)
+ {
+ _elem->GetElement("child")->Set(childLinkNameComp->Data());
+ }
+ // thread pitch
+ auto threadPitchComp = _ecm.Component(_entity);
+ if (threadPitchComp && jointType == sdf::JointType::SCREW)
+ {
+ _elem->GetElement("thread_pitch")->Set(threadPitchComp->Data());
+ }
+ // axis
+ auto jointAxisComp = _ecm.Component(_entity);
+ if (jointAxisComp)
+ {
+ const sdf::JointAxis axis = jointAxisComp->Data();
+ _elem->GetElement("axis")->Copy(axis.ToElement());
+ }
+ // axis2
+ auto jointAxis2Comp = _ecm.Component(_entity);
+ if (jointAxis2Comp)
+ {
+ const sdf::JointAxis axis2 = jointAxis2Comp->Data();
+ _elem->GetElement("axis2")->Copy(axis2.ToElement(1u));
+ }
+
+ // sensors
+ // remove existing ones in sdf element and add new ones from ECM.
+ std::vector toRemove;
+ if (_elem->HasElement("sensor"))
+ {
+ for (auto sensorElem = _elem->GetElement("sensor"); sensorElem;
+ sensorElem = sensorElem->GetNextElement("sensor"))
+ {
+ toRemove.push_back(sensorElem);
+ }
+ }
+ for (const auto &e : toRemove)
+ {
+ _elem->RemoveChild(e);
+ }
+
+ auto sensorEntities = _ecm.EntitiesByComponents(
+ components::ParentEntity(_entity), components::Sensor());
+
+ for (const auto &sensorEnt : sensorEntities)
+ {
+ sdf::ElementPtr sensorElem = _elem->AddElement("sensor");
+ updateSensorElement(sensorElem, _ecm, sensorEnt);
+ }
+
+ return updateJointNameAndPose();
+ }
+
/////////////////////////////////////////////////
/// \brief Checks if a string is a number
/// \param[in] _str The string to check
diff --git a/src/SdfGenerator.hh b/src/SdfGenerator.hh
index e580fe53e8..83a7844c29 100644
--- a/src/SdfGenerator.hh
+++ b/src/SdfGenerator.hh
@@ -99,6 +99,49 @@ namespace sdf_generator
const EntityComponentManager &_ecm,
const Entity &_entity, const std::string &_uri);
+ /// \brief Update an sdf::Element of a link.
+ /// Intended for internal use.
+ /// \input[in, out] _elem sdf::Element to update
+ /// \input[in] _ecm Immutable reference to the Entity Component Manager
+ /// \input[in] _entity Link entity
+ /// \returns true if update succeeded.
+ IGNITION_GAZEBO_VISIBLE
+ bool updateLinkElement(const sdf::ElementPtr &_elem,
+ const EntityComponentManager &_ecm,
+ const Entity &_entity);
+
+ /// \brief Update an sdf::Element of a sensor.
+ /// Intended for internal use.
+ /// \input[in, out] _elem sdf::Element to update
+ /// \input[in] _ecm Immutable reference to the Entity Component Manager
+ /// \input[in] _entity Sensor entity
+ /// \returns true if update succeeded.
+ IGNITION_GAZEBO_VISIBLE
+ bool updateSensorElement(sdf::ElementPtr _elem,
+ const EntityComponentManager &_ecm,
+ const Entity &_entity);
+
+ /// \brief Update an sdf::Element of a light.
+ /// Intended for internal use.
+ /// \input[in, out] _elem sdf::Element to update
+ /// \input[in] _ecm Immutable reference to the Entity Component Manager
+ /// \input[in] _entity Light entity
+ /// \returns true if update succeeded.
+ IGNITION_GAZEBO_VISIBLE
+ bool updateLightElement(sdf::ElementPtr _elem,
+ const EntityComponentManager &_ecm,
+ const Entity &_entity);
+
+ /// \brief Update an sdf::Element of a joint.
+ /// Intended for internal use.
+ /// \input[in, out] _elem sdf::Element to update
+ /// \input[in] _ecm Immutable reference to the Entity Component Manager
+ /// \input[in] _entity joint entity
+ /// \returns true if update succeeded.
+ IGNITION_GAZEBO_VISIBLE
+ bool updateJointElement(sdf::ElementPtr _elem,
+ const EntityComponentManager &_ecm,
+ const Entity &_entity);
} // namespace sdf_generator
} // namespace IGNITION_GAZEBO_VERSION_NAMESPACE
} // namespace gazebo
diff --git a/src/SdfGenerator_TEST.cc b/src/SdfGenerator_TEST.cc
index aace52588f..3599fda3ef 100644
--- a/src/SdfGenerator_TEST.cc
+++ b/src/SdfGenerator_TEST.cc
@@ -117,6 +117,43 @@ static testing::AssertionResult isSubset(const sdf::ElementPtr &_elemA,
<< "'";
}
}
+ else if (valA->GetTypeName() == "double")
+ {
+ double dblA, dblB;
+ valA->Get(dblA);
+ valB->Get(dblB);
+ if (!math::equal(dblA, dblB))
+ {
+ return testing::AssertionFailure()
+ << "Mismatch in value as double: '" << dblA << "' vs '"
+ << dblB << "'";
+ }
+ }
+ else if (valA->GetTypeName() == "float")
+ {
+ float fltA, fltB;
+ valA->Get(fltA);
+ valB->Get(fltB);
+ if (!math::equal(fltA, fltB))
+ {
+ return testing::AssertionFailure()
+ << "Mismatch in value as float: '" << fltA << "' vs '"
+ << fltB << "'";
+ }
+ }
+ else if (valA->GetTypeName() == "bool")
+ {
+ bool boolA, boolB;
+ valA->Get(boolA);
+ valB->Get(boolB);
+ if (boolA != boolB)
+ {
+ return testing::AssertionFailure()
+ << "Mismatch in value as bool: '" << boolA << "' vs '"
+ << boolB << "'";
+ }
+
+ }
else if (valA->GetAsString() != valB->GetAsString())
{
return testing::AssertionFailure()
@@ -148,6 +185,27 @@ static testing::AssertionResult isSubset(const sdf::ElementPtr &_elemA,
if (!result)
{
+ // Ignore missing pose values if the pose is zero.
+ sdf::ParamPtr childValA = childElemA->GetValue();
+ if (childValA->GetTypeName() == "pose")
+ {
+ math::Pose3d childValPose;
+ childValA->Get(childValPose);
+ if (childValPose == math::Pose3d::Zero)
+ return testing::AssertionSuccess();
+ }
+ else if (childValA->GetTypeName() == "bool")
+ {
+ bool childValBool;
+ childValA->Get(childValBool);
+ if (!childValBool && (childElemA->GetName() == "static" ||
+ childElemA->GetName() == "self_collide" ||
+ childElemA->GetName() == "enable_wind" ))
+ {
+ return testing::AssertionSuccess();
+ }
+ }
+
return testing::AssertionFailure()
<< "No matching child element in element B for child element '"
<< childElemA->GetName() << "' in element A";
@@ -163,15 +221,15 @@ TEST(CompareElements, CompareWithDuplicateElements)
const std::string m1Sdf = R"(
- 0 0 0 0 0 0
+ 1 0 0 0 0 0
)";
const std::string m1CompTestSdf = R"(
- 0 0 0 0 0 0
- 0 0 0 0 0 0
+ 1 0 0 0 0 0
+ 0 1 0 0 0 0
)";
@@ -271,7 +329,7 @@ class ModelElementFixture : public ElementUpdateFixture
auto elem = std::make_shared();
sdf::initFile("model.sdf", elem);
- updateModelElement(elem, this->ecm, model);
+ EXPECT_TRUE(updateModelElement(elem, this->ecm, model));
return elem;
}
diff --git a/src/ServerConfig.cc b/src/ServerConfig.cc
index 90570dc844..fb0d9fdace 100644
--- a/src/ServerConfig.cc
+++ b/src/ServerConfig.cc
@@ -220,6 +220,7 @@ class ignition::gazebo::ServerConfigPrivate
public: explicit ServerConfigPrivate(
const std::unique_ptr &_cfg)
: sdfFile(_cfg->sdfFile),
+ sdfString(_cfg->sdfString),
updateRate(_cfg->updateRate),
useLevels(_cfg->useLevels),
useLogRecord(_cfg->useLogRecord),
diff --git a/src/SimulationRunner.cc b/src/SimulationRunner.cc
index ee7e06515e..e5e84bfe15 100644
--- a/src/SimulationRunner.cc
+++ b/src/SimulationRunner.cc
@@ -1022,7 +1022,7 @@ void SimulationRunner::LoadLoggingPlugins(const ServerConfig &_config)
void SimulationRunner::LoadPlugins(const Entity _entity,
const sdf::ElementPtr &_sdf)
{
- sdf::ElementPtr pluginElem = _sdf->GetElement("plugin");
+ sdf::ElementPtr pluginElem = _sdf->FindElement("plugin");
while (pluginElem)
{
auto filename = pluginElem->Get("filename");
@@ -1030,8 +1030,7 @@ void SimulationRunner::LoadPlugins(const Entity _entity,
// No error message for the 'else' case of the following 'if' statement
// because SDF create a default element even if it's not
// specified. An error message would result in spamming
- // the console. \todo(nkoenig) Fix SDF should so that elements are not
- // automatically added.
+ // the console.
if (filename != "__default__" && name != "__default__")
{
this->LoadPlugin(_entity, filename, name, pluginElem);
diff --git a/src/SimulationRunner_TEST.cc b/src/SimulationRunner_TEST.cc
index c77cfaafc7..fbcb8d19af 100644
--- a/src/SimulationRunner_TEST.cc
+++ b/src/SimulationRunner_TEST.cc
@@ -1569,6 +1569,52 @@ TEST_P(SimulationRunnerTest, GenerateWorldSdf)
EXPECT_EQ(5u, world->ModelCount());
}
+/////////////////////////////////////////////////
+/// Helper function to recursively check for plugins with filename and name
+/// attributes set to "__default__"
+testing::AssertionResult checkForSpuriousPlugins(sdf::ElementPtr _elem)
+{
+ auto plugin = _elem->FindElement("plugin");
+ if (nullptr != plugin &&
+ plugin->Get("filename") == "__default__" &&
+ plugin->Get("name") == "__default__")
+ {
+ return testing::AssertionFailure() << _elem->ToString("");
+ }
+ for (auto child = _elem->GetFirstElement(); child;
+ child = child->GetNextElement())
+ {
+ auto result = checkForSpuriousPlugins(child);
+ if (!result)
+ return result;
+ }
+ return testing::AssertionSuccess();
+}
+
+/////////////////////////////////////////////////
+TEST_P(SimulationRunnerTest, GeneratedSdfHasNoSpuriousPlugins)
+{
+ // Load SDF file
+ sdf::Root root;
+ root.Load(common::joinPaths(PROJECT_SOURCE_PATH,
+ "test", "worlds", "shapes.sdf"));
+
+ ASSERT_EQ(1u, root.WorldCount());
+
+ // Create simulation runner
+ auto systemLoader = std::make_shared();
+ SimulationRunner runner(root.WorldByIndex(0), systemLoader);
+
+ msgs::SdfGeneratorConfig req;
+ msgs::StringMsg genWorldSdf;
+ EXPECT_TRUE(runner.GenerateWorldSdf(req, genWorldSdf));
+ EXPECT_FALSE(genWorldSdf.data().empty());
+
+ sdf::Root newRoot;
+ newRoot.LoadSdfString(genWorldSdf.data());
+ EXPECT_TRUE(checkForSpuriousPlugins(newRoot.Element()));
+}
+
// Run multiple times. We want to make sure that static globals don't cause
// problems.
INSTANTIATE_TEST_SUITE_P(ServerRepeat, SimulationRunnerTest,
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index fa9d276b0f..ae0de7d3da 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -1,6 +1,7 @@
set (gui_sources
AboutDialogHandler.cc
Gui.cc
+ GuiEvents.cc
GuiFileHandler.cc
GuiRunner.cc
PathManager.cc
@@ -8,6 +9,7 @@ set (gui_sources
set (gtest_sources
Gui_TEST.cc
+ GuiEvents_TEST.cc
)
add_subdirectory(plugins)
diff --git a/src/gui/GuiEvents.cc b/src/gui/GuiEvents.cc
new file mode 100644
index 0000000000..dd89de306f
--- /dev/null
+++ b/src/gui/GuiEvents.cc
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include "ignition/gazebo/gui/GuiEvents.hh"
+
+class ignition::gazebo::gui::events::GuiNewRemovedEntities::Implementation
+{
+ /// \brief Set of newly created entities
+ public: std::set newEntities;
+
+ /// \brief Set of recently removed entities
+ public: std::set removedEntities;
+};
+
+class ignition::gazebo::gui::events::NewRemovedEntities::Implementation
+{
+ /// \brief Set of newly created entities
+ public: std::set newEntities;
+
+ /// \brief Set of recently removed entities
+ public: std::set removedEntities;
+};
+
+using namespace ignition;
+using namespace gazebo;
+using namespace gui;
+using namespace events;
+
+/////////////////////////////////////////////////
+GuiNewRemovedEntities::GuiNewRemovedEntities(
+ const std::set &_newEntities,
+ const std::set &_removedEntities)
+ : QEvent(kType), dataPtr(utils::MakeImpl())
+{
+ this->dataPtr->newEntities = _newEntities;
+ this->dataPtr->removedEntities = _removedEntities;
+}
+
+/////////////////////////////////////////////////
+const std::set &GuiNewRemovedEntities::NewEntities() const
+{
+ return this->dataPtr->newEntities;
+}
+
+/////////////////////////////////////////////////
+const std::set &GuiNewRemovedEntities::RemovedEntities() const
+{
+ return this->dataPtr->removedEntities;
+}
+
+/////////////////////////////////////////////////
+NewRemovedEntities::NewRemovedEntities(
+ const std::set &_newEntities,
+ const std::set &_removedEntities)
+ : QEvent(kType), dataPtr(utils::MakeImpl())
+{
+ this->dataPtr->newEntities = _newEntities;
+ this->dataPtr->removedEntities = _removedEntities;
+}
+
+/////////////////////////////////////////////////
+const std::set &NewRemovedEntities::NewEntities() const
+{
+ return this->dataPtr->newEntities;
+}
+
+/////////////////////////////////////////////////
+const std::set &NewRemovedEntities::RemovedEntities() const
+{
+ return this->dataPtr->removedEntities;
+}
diff --git a/src/gui/GuiEvents_TEST.cc b/src/gui/GuiEvents_TEST.cc
new file mode 100644
index 0000000000..cb0bebc999
--- /dev/null
+++ b/src/gui/GuiEvents_TEST.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include
+
+#include "ignition/gazebo/test_config.hh"
+#include "ignition/gazebo/gui/GuiEvents.hh"
+
+using namespace ignition;
+using namespace gazebo;
+using namespace gui;
+
+/////////////////////////////////////////////////
+TEST(GuiEventsTest, GuiNewRemovedEntities)
+{
+ events::GuiNewRemovedEntities event({1, 2, 3}, {4, 5});
+
+ EXPECT_LT(QEvent::User, event.type());
+
+ auto addedEntities = event.NewEntities();
+ EXPECT_EQ(3u, addedEntities.size());
+ EXPECT_NE(addedEntities.find(1), addedEntities.end());
+ EXPECT_NE(addedEntities.find(2), addedEntities.end());
+ EXPECT_NE(addedEntities.find(3), addedEntities.end());
+ EXPECT_EQ(addedEntities.find(100), addedEntities.end());
+
+ auto removedEntities = event.RemovedEntities();
+ EXPECT_EQ(2u, removedEntities.size());
+ EXPECT_NE(removedEntities.find(4), removedEntities.end());
+ EXPECT_NE(removedEntities.find(5), removedEntities.end());
+ EXPECT_EQ(removedEntities.find(6), removedEntities.end());
+}
+
+/////////////////////////////////////////////////
+TEST(GuiEventsTest, NewRemovedEntities)
+{
+ events::NewRemovedEntities event({1, 2, 3}, {4, 5});
+
+ EXPECT_LT(QEvent::User, event.type());
+
+ auto addedEntities = event.NewEntities();
+ EXPECT_EQ(3u, addedEntities.size());
+ EXPECT_NE(addedEntities.find(1), addedEntities.end());
+ EXPECT_NE(addedEntities.find(2), addedEntities.end());
+ EXPECT_NE(addedEntities.find(3), addedEntities.end());
+ EXPECT_EQ(addedEntities.find(100), addedEntities.end());
+
+ auto removedEntities = event.RemovedEntities();
+ EXPECT_EQ(2u, removedEntities.size());
+ EXPECT_NE(removedEntities.find(4), removedEntities.end());
+ EXPECT_NE(removedEntities.find(5), removedEntities.end());
+ EXPECT_EQ(removedEntities.find(6), removedEntities.end());
+}
diff --git a/src/gui/plugins/component_inspector/ComponentInspector.cc b/src/gui/plugins/component_inspector/ComponentInspector.cc
index 8334f40508..cb29338b8d 100644
--- a/src/gui/plugins/component_inspector/ComponentInspector.cc
+++ b/src/gui/plugins/component_inspector/ComponentInspector.cc
@@ -21,6 +21,7 @@
#include
#include
+#include
#include
#include
#include
@@ -32,12 +33,15 @@
#include "ignition/gazebo/components/Actor.hh"
#include "ignition/gazebo/components/AngularAcceleration.hh"
#include "ignition/gazebo/components/AngularVelocity.hh"
+#include "ignition/gazebo/components/BatterySoC.hh"
#include "ignition/gazebo/components/CastShadows.hh"
+#include "ignition/gazebo/components/CenterOfVolume.hh"
#include "ignition/gazebo/components/ChildLinkName.hh"
#include "ignition/gazebo/components/Collision.hh"
#include "ignition/gazebo/components/Factory.hh"
#include "ignition/gazebo/components/Gravity.hh"
#include "ignition/gazebo/components/Joint.hh"
+#include "ignition/gazebo/components/LaserRetro.hh"
#include "ignition/gazebo/components/Level.hh"
#include "ignition/gazebo/components/Light.hh"
#include "ignition/gazebo/components/LightCmd.hh"
@@ -47,6 +51,7 @@
#include "ignition/gazebo/components/LinearVelocitySeed.hh"
#include "ignition/gazebo/components/Link.hh"
#include "ignition/gazebo/components/MagneticField.hh"
+#include "ignition/gazebo/components/Material.hh"
#include "ignition/gazebo/components/Model.hh"
#include "ignition/gazebo/components/Name.hh"
#include "ignition/gazebo/components/ParentEntity.hh"
@@ -64,7 +69,10 @@
#include "ignition/gazebo/components/SourceFilePath.hh"
#include "ignition/gazebo/components/SphericalCoordinates.hh"
#include "ignition/gazebo/components/Static.hh"
+#include "ignition/gazebo/components/ThreadPitch.hh"
+#include "ignition/gazebo/components/Transparency.hh"
#include "ignition/gazebo/components/Visual.hh"
+#include "ignition/gazebo/components/Volume.hh"
#include "ignition/gazebo/components/WindMode.hh"
#include "ignition/gazebo/components/World.hh"
#include "ignition/gazebo/EntityComponentManager.hh"
@@ -287,6 +295,13 @@ void ignition::gazebo::setData(QStandardItem *_item, const int &_data)
_item->setData(_data, ComponentsModel::RoleNames().key("data"));
}
+//////////////////////////////////////////////////
+template<>
+void ignition::gazebo::setData(QStandardItem *_item, const Entity &_data)
+{
+ setData(_item, static_cast(_data));
+}
+
//////////////////////////////////////////////////
template<>
void ignition::gazebo::setData(QStandardItem *_item, const double &_data)
@@ -314,6 +329,39 @@ void ignition::gazebo::setData(QStandardItem *_item, const sdf::Physics &_data)
}), ComponentsModel::RoleNames().key("data"));
}
+//////////////////////////////////////////////////
+template<>
+void ignition::gazebo::setData(QStandardItem *_item,
+ const sdf::Material &_data)
+{
+ if (nullptr == _item)
+ return;
+
+ _item->setData(QString("Material"),
+ ComponentsModel::RoleNames().key("dataType"));
+ _item->setData(QList({
+ QVariant(_data.Ambient().R() * 255),
+ QVariant(_data.Ambient().G() * 255),
+ QVariant(_data.Ambient().B() * 255),
+ QVariant(_data.Ambient().A() * 255),
+ QVariant(_data.Diffuse().R() * 255),
+ QVariant(_data.Diffuse().G() * 255),
+ QVariant(_data.Diffuse().B() * 255),
+ QVariant(_data.Diffuse().A() * 255),
+ QVariant(_data.Specular().R() * 255),
+ QVariant(_data.Specular().G() * 255),
+ QVariant(_data.Specular().B() * 255),
+ QVariant(_data.Specular().A() * 255),
+ QVariant(_data.Emissive().R() * 255),
+ QVariant(_data.Emissive().G() * 255),
+ QVariant(_data.Emissive().B() * 255),
+ QVariant(_data.Emissive().A() * 255)
+ }), ComponentsModel::RoleNames().key("data"));
+
+ // TODO(anyone) Only shows colors of material,
+ // need to add others (e.g., pbr)
+}
+
//////////////////////////////////////////////////
template<>
void ignition::gazebo::setData(QStandardItem *_item,
@@ -433,6 +481,7 @@ ComponentInspector::ComponentInspector()
: GuiSystem(), dataPtr(std::make_unique())
{
qRegisterMetaType();
+ qRegisterMetaType("Entity");
}
/////////////////////////////////////////////////
@@ -628,6 +677,13 @@ void ComponentInspector::Update(const UpdateInfo &_info,
if (comp)
setData(item, comp->Data());
}
+ else if (typeId == components::BatterySoC::typeId)
+ {
+ auto comp = _ecm.Component(
+ this->dataPtr->entity);
+ if (comp)
+ setData(item, comp->Data());
+ }
else if (typeId == components::CastShadows::typeId)
{
auto comp = _ecm.Component(
@@ -635,6 +691,16 @@ void ComponentInspector::Update(const UpdateInfo &_info,
if (comp)
setData(item, comp->Data());
}
+ else if (typeId == components::CenterOfVolume::typeId)
+ {
+ auto comp = _ecm.Component(
+ this->dataPtr->entity);
+ if (comp)
+ {
+ setData(item, comp->Data());
+ setUnit(item, "m");
+ }
+ }
else if (typeId == components::ChildLinkName::typeId)
{
auto comp = _ecm.Component(
@@ -651,6 +717,12 @@ void ComponentInspector::Update(const UpdateInfo &_info,
setUnit(item, "m/s\u00B2");
}
}
+ else if (typeId == components::LaserRetro::typeId)
+ {
+ auto comp = _ecm.Component(this->dataPtr->entity);
+ if (comp)
+ setData(item, comp->Data());
+ }
else if (typeId == components::LinearAcceleration::typeId)
{
auto comp = _ecm.Component(
@@ -802,6 +874,33 @@ void ComponentInspector::Update(const UpdateInfo &_info,
if (comp)
setData(item, comp->Data());
}
+ else if (typeId == components::ThreadPitch::typeId)
+ {
+ auto comp = _ecm.Component(
+ this->dataPtr->entity);
+ if (comp)
+ {
+ setData(item, comp->Data());
+ setUnit(item, "m");
+ }
+ }
+ else if (typeId == components::Transparency::typeId)
+ {
+ auto comp = _ecm.Component(
+ this->dataPtr->entity);
+ if (comp)
+ setData(item, comp->Data());
+ }
+ else if (typeId == components::Volume::typeId)
+ {
+ auto comp = _ecm.Component(
+ this->dataPtr->entity);
+ if (comp)
+ {
+ setData(item, comp->Data());
+ setUnit(item, "m\u00B3");
+ }
+ }
else if (typeId == components::WindMode::typeId)
{
auto comp = _ecm.Component(this->dataPtr->entity);
@@ -818,6 +917,16 @@ void ComponentInspector::Update(const UpdateInfo &_info,
setUnit(item, "rad/s\u00B2");
}
}
+ else if (typeId == components::WorldAngularVelocity::typeId)
+ {
+ auto comp = _ecm.Component(
+ this->dataPtr->entity);
+ if (comp)
+ {
+ setData(item, comp->Data());
+ setUnit(item, "rad/s");
+ }
+ }
else if (typeId == components::WorldLinearVelocity::typeId)
{
auto comp = _ecm.Component(
@@ -851,6 +960,15 @@ void ComponentInspector::Update(const UpdateInfo &_info,
if (comp)
setData(item, comp->Data());
}
+ else if (typeId == components::Material::typeId)
+ {
+ auto comp = _ecm.Component(this->dataPtr->entity);
+ if (comp)
+ {
+ this->SetType("material");
+ setData(item, comp->Data());
+ }
+ }
else if (this->dataPtr->componentCreators.find(typeId) !=
this->dataPtr->componentCreators.end())
{
@@ -930,13 +1048,13 @@ bool ComponentInspector::eventFilter(QObject *_obj, QEvent *_event)
}
/////////////////////////////////////////////////
-int ComponentInspector::Entity() const
+Entity ComponentInspector::GetEntity() const
{
return this->dataPtr->entity;
}
/////////////////////////////////////////////////
-void ComponentInspector::SetEntity(const int &_entity)
+void ComponentInspector::SetEntity(const Entity &_entity)
{
// If nothing is selected, display world properties
if (_entity == kNullEntity)
@@ -1110,6 +1228,96 @@ void ComponentInspector::OnPhysics(double _stepSize, double _realTimeFactor)
this->dataPtr->node.Request(physicsCmdService, req, cb);
}
+/////////////////////////////////////////////////
+void ComponentInspector::OnMaterialColor(
+ double _rAmbient, double _gAmbient, double _bAmbient, double _aAmbient,
+ double _rDiffuse, double _gDiffuse, double _bDiffuse, double _aDiffuse,
+ double _rSpecular, double _gSpecular, double _bSpecular, double _aSpecular,
+ double _rEmissive, double _gEmissive, double _bEmissive, double _aEmissive,
+ QString _type, QColor _currColor)
+{
+ // when type is not empty, open qt color dialog
+ std::string type = _type.toStdString();
+ if (!type.empty())
+ {
+ QColor newColor = QColorDialog::getColor(
+ _currColor, nullptr, "Pick a color",
+ {QColorDialog::DontUseNativeDialog, QColorDialog::ShowAlphaChannel});
+
+ // returns if the user hits cancel
+ if (!newColor.isValid())
+ return;
+
+ if (type == "ambient")
+ {
+ _rAmbient = newColor.red();
+ _gAmbient = newColor.green();
+ _bAmbient = newColor.blue();
+ _aAmbient = newColor.alpha();
+ }
+ else if (type == "diffuse")
+ {
+ _rDiffuse = newColor.red();
+ _gDiffuse = newColor.green();
+ _bDiffuse = newColor.blue();
+ _aDiffuse = newColor.alpha();
+ }
+ else if (type == "specular")
+ {
+ _rSpecular = newColor.red();
+ _gSpecular = newColor.green();
+ _bSpecular = newColor.blue();
+ _aSpecular = newColor.alpha();
+ }
+ else if (type == "emissive")
+ {
+ _rEmissive = newColor.red();
+ _gEmissive = newColor.green();
+ _bEmissive = newColor.blue();
+ _aEmissive = newColor.alpha();
+ }
+ else
+ {
+ ignerr << "Invalid material type: " << type << std::endl;
+ return;
+ }
+ }
+
+ std::function cb =
+ [](const ignition::msgs::Boolean &/*_rep*/, const bool _result)
+ {
+ if (!_result)
+ ignerr << "Error setting material color configuration"
+ << " on visual" << std::endl;
+ };
+
+ msgs::Visual req;
+ req.set_id(this->dataPtr->entity);
+
+ msgs::Set(req.mutable_material()->mutable_ambient(),
+ math::Color(_rAmbient / 255.0, _gAmbient / 255.0,
+ _bAmbient / 255.0, _aAmbient / 255.0));
+ msgs::Set(req.mutable_material()->mutable_diffuse(),
+ math::Color(_rDiffuse / 255.0, _gDiffuse / 255.0,
+ _bDiffuse / 255.0, _aDiffuse / 255.0));
+ msgs::Set(req.mutable_material()->mutable_specular(),
+ math::Color(_rSpecular / 255.0, _gSpecular / 255.0,
+ _bSpecular / 255.0, _aSpecular / 255.0));
+ msgs::Set(req.mutable_material()->mutable_emissive(),
+ math::Color(_rEmissive / 255.0, _gEmissive / 255.0,
+ _bEmissive / 255.0, _aEmissive / 255.0));
+
+ auto materialCmdService = "/world/" + this->dataPtr->worldName
+ + "/visual_config";
+ materialCmdService = transport::TopicUtils::AsValidTopic(materialCmdService);
+ if (materialCmdService.empty())
+ {
+ ignerr << "Invalid material command service topic provided" << std::endl;
+ return;
+ }
+ this->dataPtr->node.Request(materialCmdService, req, cb);
+}
+
/////////////////////////////////////////////////
void ComponentInspector::OnSphericalCoordinates(QString _surface,
double _latitude, double _longitude, double _elevation,
diff --git a/src/gui/plugins/component_inspector/ComponentInspector.hh b/src/gui/plugins/component_inspector/ComponentInspector.hh
index 12fc3caac5..1c23dddf1a 100644
--- a/src/gui/plugins/component_inspector/ComponentInspector.hh
+++ b/src/gui/plugins/component_inspector/ComponentInspector.hh
@@ -22,6 +22,7 @@
#include
#include
+#include
#include
#include
@@ -123,6 +124,13 @@ namespace gazebo
template<>
void setData(QStandardItem *_item, const std::ostream &_data);
+ /// \brief Specialized to set material data.
+ /// \param[in] _item Item whose data will be set.
+ /// \param[in] _data Data to set.
+ template<>
+ void setData(QStandardItem *_item, const sdf::Material &_data);
+
+
/// \brief Set the unit of a given item.
/// \param[in] _item Item whose unit will be set.
/// \param[in] _unit Unit to be displayed, such as 'm' for meters.
@@ -172,8 +180,8 @@ namespace gazebo
/// \brief Entity
Q_PROPERTY(
- int entity
- READ Entity
+ Entity entity
+ READ GetEntity
WRITE SetEntity
NOTIFY EntityChanged
)
@@ -283,6 +291,35 @@ namespace gazebo
public: Q_INVOKABLE void OnPhysics(double _stepSize,
double _realTimeFactor);
+ // \brief Callback in Qt thread when material color changes for a visual
+ /// \param[in] _rAmbient ambient red
+ /// \param[in] _gAmbient ambient green
+ /// \param[in] _bAmbient ambient blue
+ /// \param[in] _aAmbient ambient alpha
+ /// \param[in] _rDiffuse diffuse red
+ /// \param[in] _gDiffuse diffuse green
+ /// \param[in] _bDiffuse diffuse blue
+ /// \param[in] _aDiffuse diffuse alpha
+ /// \param[in] _rSpecular specular red
+ /// \param[in] _gSpecular specular green
+ /// \param[in] _bSpecular specular blue
+ /// \param[in] _aSpecular specular alpha
+ /// \param[in] _rEmissive emissive red
+ /// \param[in] _gEmissive emissive green
+ /// \param[in] _bEmissive emissive blue
+ /// \param[in] _aEmissive emissive alpha
+ /// \param[in] _type if type is not empty, opens QColorDialog.
+ /// The possible types are ambient, diffuse, specular, or emissive.
+ /// \param[in] _currColor used for QColorDialog to show the current color
+ /// in the open dialog.
+ public: Q_INVOKABLE void OnMaterialColor(
+ double _rAmbient, double _gAmbient, double _bAmbient,
+ double _aAmbient, double _rDiffuse, double _gDiffuse,
+ double _bDiffuse, double _aDiffuse, double _rSpecular,
+ double _gSpecular, double _bSpecular, double _aSpecular,
+ double _rEmissive, double _gEmissive, double _bEmissive,
+ double _aEmissive, QString _type, QColor _currColor);
+
/// \brief Callback in Qt thread when spherical coordinates change.
/// \param[in] _surface Surface model
/// \param[in] _latitude Latitude in degrees
@@ -305,11 +342,11 @@ namespace gazebo
/// \brief Get the entity currently inspected.
/// \return Entity ID.
- public: Q_INVOKABLE int Entity() const;
+ public: Q_INVOKABLE Entity GetEntity() const;
/// \brief Set the entity currently inspected.
/// \param[in] _entity Entity ID.
- public: Q_INVOKABLE void SetEntity(const int &_entity);
+ public: Q_INVOKABLE void SetEntity(const Entity &_entity);
/// \brief Notify that entity has changed.
signals: void EntityChanged();
diff --git a/src/gui/plugins/component_inspector/ComponentInspector.qml b/src/gui/plugins/component_inspector/ComponentInspector.qml
index ea95e6e838..9e25fb8c93 100644
--- a/src/gui/plugins/component_inspector/ComponentInspector.qml
+++ b/src/gui/plugins/component_inspector/ComponentInspector.qml
@@ -142,6 +142,22 @@ Rectangle {
ComponentInspector.OnPhysics(_stepSize, _realTimeFactor)
}
+ /**
+ * Forward material color changes to C++
+ */
+ function onMaterialColor(_rAmbient, _gAmbient, _bAmbient, _aAmbient,
+ _rDiffuse, _gDiffuse, _bDiffuse, _aDiffuse,
+ _rSpecular, _gSpecular, _bSpecular, _aSpecular,
+ _rEmissive, _gEmissive, _bEmissive, _aEmissive,
+ _type, _currColor) {
+ ComponentInspector.OnMaterialColor(
+ _rAmbient, _gAmbient, _bAmbient, _aAmbient,
+ _rDiffuse, _gDiffuse, _bDiffuse, _aDiffuse,
+ _rSpecular, _gSpecular, _bSpecular, _aSpecular,
+ _rEmissive, _gEmissive, _bEmissive, _aEmissive,
+ _type, _currColor)
+ }
+
/*
* Forward spherical coordinate changes to C++
*/
diff --git a/src/gui/plugins/component_inspector/ComponentInspector.qrc b/src/gui/plugins/component_inspector/ComponentInspector.qrc
index 6146914e7d..d3f1739982 100644
--- a/src/gui/plugins/component_inspector/ComponentInspector.qrc
+++ b/src/gui/plugins/component_inspector/ComponentInspector.qrc
@@ -5,12 +5,15 @@
Boolean.qml
ComponentInspector.qml
ExpandingTypeHeader.qml
+ Float.qml
Imu.qml
+ Integer.qml
JointType.qml
Lidar.qml
LidarScan.qml
Light.qml
Magnetometer.qml
+ Material.qml
NoData.qml
Noise.qml
Physics.qml
diff --git a/src/gui/plugins/component_inspector/Float.qml b/src/gui/plugins/component_inspector/Float.qml
index a72d7801be..f01cfb8e35 100644
--- a/src/gui/plugins/component_inspector/Float.qml
+++ b/src/gui/plugins/component_inspector/Float.qml
@@ -38,6 +38,9 @@ Rectangle {
// Maximum spinbox value
property double spinMax: 1000000
+ // Unit
+ property string unit: model && model.unit != undefined ? model.unit : ''
+
RowLayout {
anchors.fill: parent
@@ -55,13 +58,20 @@ Rectangle {
id: typeHeader
}
- IgnSpinBox {
+ // TODO(anyone) Support write mode
+ Text {
id: content
- value: model.data
- minimumValue: -spinMax
- maximumValue: spinMax
- decimals: xSpin.width < 100 ? 2 : 6
Layout.fillWidth: true
+ horizontalAlignment: Text.AlignRight
+ color: Material.theme == Material.Light ? "black" : "white"
+ font.pointSize: 12
+ text: {
+ var decimals = getDecimals(content.width)
+ var valueText = model.data.toFixed(decimals)
+ if (unit !== '')
+ valueText += ' ' + unit
+ return valueText
+ }
}
Item {
diff --git a/src/gui/plugins/component_inspector/Integer.qml b/src/gui/plugins/component_inspector/Integer.qml
index 316c2b2e7c..12c9b5174e 100644
--- a/src/gui/plugins/component_inspector/Integer.qml
+++ b/src/gui/plugins/component_inspector/Integer.qml
@@ -38,7 +38,10 @@ Rectangle {
// Maximum spinbox value
property double spinMax: 1000000
- Row {
+ // Unit
+ property string unit: model && model.unit != undefined ? model.unit : ''
+
+ RowLayout {
anchors.fill: parent
Item {
@@ -55,12 +58,19 @@ Rectangle {
id: typeHeader
}
- IgnSpinBox {
+ // TODO(anyone) Support write mode
+ Text {
id: content
- value: model.data
- minimumValue: -spinMax
- maximumValue: spinMax
Layout.fillWidth: true
+ horizontalAlignment: Text.AlignRight
+ color: Material.theme == Material.Light ? "black" : "white"
+ font.pointSize: 12
+ text: {
+ var valueText = model.data
+ if (unit !== '')
+ valueText += ' ' + unit
+ return valueText
+ }
}
Item {
diff --git a/src/gui/plugins/component_inspector/Material.qml b/src/gui/plugins/component_inspector/Material.qml
new file mode 100644
index 0000000000..a7d82cc6c8
--- /dev/null
+++ b/src/gui/plugins/component_inspector/Material.qml
@@ -0,0 +1,606 @@
+/*
+ * Copyright (C) 2021 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+import QtQuick 2.9
+import QtQuick.Controls 1.4
+import QtQuick.Controls 2.2
+import QtQuick.Controls.Material 2.1
+import QtQuick.Dialogs 1.0
+import QtQuick.Layouts 1.3
+import QtQuick.Controls.Styles 1.4
+import "qrc:/ComponentInspector"
+import "qrc:/qml"
+
+// Item displaying material color information
+Rectangle {
+ height: header.height + content.height
+ width: componentInspector.width
+ color: index % 2 == 0 ? lightGrey : darkGrey
+
+ // Left indentation
+ property int indentation: 10
+
+ // Horizontal margins
+ property int margin: 5
+
+ property int iconWidth: 20
+ property int iconHeight: 20
+
+ // Loaded items for ambient red, green, blue, alpha
+ property var rAmbientItem: {}
+ property var gAmbientItem: {}
+ property var bAmbientItem: {}
+ property var aAmbientItem: {}
+
+ // Loaded items for diffuse red, green, blue, alpha
+ property var rDiffuseItem: {}
+ property var gDiffuseItem: {}
+ property var bDiffuseItem: {}
+ property var aDiffuseItem: {}
+
+ // Loaded items for specular red, green, blue, alpha
+ property var rSpecularItem: {}
+ property var gSpecularItem: {}
+ property var bSpecularItem: {}
+ property var aSpecularItem: {}
+
+ // Loaded items for emissive red, green, blue, alpha
+ property var rEmissiveItem: {}
+ property var gEmissiveItem: {}
+ property var bEmissiveItem: {}
+ property var aEmissiveItem: {}
+
+ // send new material color data to C++
+ function sendMaterialColor(_type, _currColor) {
+ componentInspector.onMaterialColor(
+ rAmbientItem.value,
+ gAmbientItem.value,
+ bAmbientItem.value,
+ aAmbientItem.value,
+ rDiffuseItem.value,
+ gDiffuseItem.value,
+ bDiffuseItem.value,
+ aDiffuseItem.value,
+ rSpecularItem.value,
+ gSpecularItem.value,
+ bSpecularItem.value,
+ aSpecularItem.value,
+ rEmissiveItem.value,
+ gEmissiveItem.value,
+ bEmissiveItem.value,
+ aEmissiveItem.value,
+ _type,
+ _currColor
+ );
+ }
+
+ // Get button color from model.data, related start indices
+ // 0 = ambient
+ // 4 = diffuse
+ // 8 = specular
+ // 12 = emissive
+ function getButtonColor(_start_index, _isFillColor)
+ {
+ if (_isFillColor) {
+ // fill color (of object in the scene)
+ return Qt.rgba(model.data[_start_index],
+ model.data[_start_index + 1],
+ model.data[_start_index + 2],
+ model.data[_start_index + 3])
+ } else {
+ // border color's alpha set to 1 incase fill color is 0
+ return Qt.rgba(model.data[_start_index],
+ model.data[_start_index + 1],
+ model.data[_start_index + 2],
+ 1.0)
+ }
+ }
+
+ FontMetrics {
+ id: fontMetrics
+ font.family: "Roboto"
+ }
+
+ // Used to create rgba spin boxes
+ Component {
+ id: spinBoxMaterialColor
+ IgnSpinBox {
+ id: writableSpin
+ value: writableSpin.activeFocus ? writableSpin.value : numberValue
+ minimumValue: 0
+ maximumValue: 255
+ decimals: 0
+ onEditingFinished: {
+ // sending empty params to not open color dialog
+ sendMaterialColor("", Qt.rgba(0, 0, 0, 0))
+ }
+ }
+ }
+
+ Column {
+ anchors.fill: parent
+
+ // Header
+ Rectangle {
+ id: header
+ width: parent.width
+ height: typeHeader.height
+ color: "transparent"
+
+ RowLayout {
+ anchors.fill: parent
+ Item {
+ width: margin
+ }
+ Image {
+ id: icon
+ sourceSize.height: indentation
+ sourceSize.width: indentation
+ fillMode: Image.Pad
+ Layout.alignment : Qt.AlignVCenter
+ source: content.show ?
+ "qrc:/Gazebo/images/minus.png" : "qrc:/Gazebo/images/plus.png"
+ }
+ TypeHeader {
+ id: typeHeader
+ }
+ Item {
+ Layout.fillWidth: true
+ }
+ }
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ onClicked: {
+ content.show = !content.show
+ }
+ onEntered: {
+ header.color = highlightColor
+ }
+ onExited: {
+ header.color = "transparent"
+ }
+ }
+ }
+
+ // Content
+ Rectangle {
+ id: content
+ property bool show: false
+ width: parent.width
+ height: show ? grid.height : 0
+ clip: true
+ color: "transparent"
+
+ Behavior on height {
+ NumberAnimation {
+ duration: 200
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ ColumnLayout {
+ id: grid
+ width: parent.width
+ spacing: 20
+
+ GridLayout {
+ width: parent.width
+ columns: 6
+
+ // rgba headers
+ Text {
+ text: "Red "
+ color: Material.theme == Material.Light ? "#444444" : "#bbbbbb"
+ font.pointSize: 12
+ Layout.row: 1
+ Layout.column: 3
+ }
+ Text {
+ text: "Green"
+ color: Material.theme == Material.Light ? "#444444" : "#bbbbbb"
+ font.pointSize: 12
+ Layout.row: 1
+ Layout.column: 4
+ }
+ Text {
+ text: "Blue "
+ color: Material.theme == Material.Light ? "#444444" : "#bbbbbb"
+ font.pointSize: 12
+ Layout.row: 1
+ Layout.column: 5
+ }
+ Text {
+ text: "Alpha"
+ color: Material.theme == Material.Light ? "#444444" : "#bbbbbb"
+ font.pointSize: 12
+ Layout.row: 1
+ Layout.column: 6
+ }
+
+ // Ambient
+ Text {
+ text: " Ambient"
+ color: Material.theme == Material.Light ? "#444444" : "#bbbbbb"
+ Layout.row: 2
+ Layout.column: 1
+ }
+ // Ambient color dialog
+ Button {
+ id: ambientButton
+ Layout.row: 2
+ Layout.column: 2
+ ToolTip.text: "Open color dialog"
+ ToolTip.visible: hovered
+ ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
+ background: Rectangle {
+ implicitWidth: 40
+ implicitHeight: 40
+ radius: 5
+ border.color: getButtonColor(0, false)
+ border.width: 2
+ color: getButtonColor(0, true)
+ }
+ onClicked: {
+ sendMaterialColor("ambient", getButtonColor(0, true))
+ }
+ }
+ // Ambient red
+ Item {
+ Layout.row: 2
+ Layout.column: 3
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: rAmbientLoader
+ anchors.fill: parent
+ property double numberValue: model.data[0]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ rAmbientItem = rAmbientLoader.item
+ }
+ }
+ }
+ // Ambient green
+ Item {
+ Layout.row: 2
+ Layout.column: 4
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: gAmbientLoader
+ anchors.fill: parent
+ property double numberValue: model.data[1]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ gAmbientItem = gAmbientLoader.item
+ }
+ }
+ }
+ // Ambient blue
+ Item {
+ Layout.row: 2
+ Layout.column: 5
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: bAmbientLoader
+ anchors.fill: parent
+ property double numberValue: model.data[2]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ bAmbientItem = bAmbientLoader.item
+ }
+ }
+ }
+ // Ambient alpha
+ Item {
+ Layout.row: 2
+ Layout.column: 6
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: aAmbientLoader
+ anchors.fill: parent
+ property double numberValue: model.data[3]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ aAmbientItem = aAmbientLoader.item
+ }
+ }
+ } // end Ambient
+
+ // Diffuse
+ Text {
+ text: " Diffuse"
+ color: Material.theme == Material.Light ? "#444444" : "#bbbbbb"
+ Layout.row: 3
+ Layout.column: 1
+ }
+ // Diffuse color dialog
+ Button {
+ id: diffuseButton
+ Layout.row: 3
+ Layout.column: 2
+ ToolTip.text: "Open color dialog"
+ ToolTip.visible: hovered
+ ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
+ background: Rectangle {
+ implicitWidth: 40
+ implicitHeight: 40
+ radius: 5
+ border.color: getButtonColor(4, false)
+ border.width: 2
+ color: getButtonColor(4, true)
+ }
+ onClicked: {
+ sendMaterialColor("diffuse", getButtonColor(4, true))
+ }
+ }
+ // Diffuse red
+ Item {
+ Layout.row: 3
+ Layout.column: 3
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: rDiffuseLoader
+ anchors.fill: parent
+ property double numberValue: model.data[4]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ rDiffuseItem = rDiffuseLoader.item
+ }
+ }
+ }
+ // Diffuse green
+ Item {
+ Layout.row: 3
+ Layout.column: 4
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: gDiffuseLoader
+ anchors.fill: parent
+ property double numberValue: model.data[5]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ gDiffuseItem = gDiffuseLoader.item
+ }
+ }
+ }
+ // Diffuse blue
+ Item {
+ Layout.row: 3
+ Layout.column: 5
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: bDiffuseLoader
+ anchors.fill: parent
+ property double numberValue: model.data[6]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ bDiffuseItem = bDiffuseLoader.item
+ }
+ }
+ }
+ // Diffuse alpha
+ Item {
+ Layout.row: 3
+ Layout.column: 6
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: aDiffuseLoader
+ anchors.fill: parent
+ property double numberValue: model.data[7]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ aDiffuseItem = aDiffuseLoader.item
+ }
+ }
+ } // end Diffuse
+
+ // Specular
+ Text {
+ text: " Specular"
+ color: Material.theme == Material.Light ? "#444444" : "#bbbbbb"
+ Layout.row: 4
+ Layout.column: 1
+ }
+ // Specular color dialog
+ Button {
+ id: specularButton
+ Layout.row: 4
+ Layout.column: 2
+ ToolTip.text: "Open color dialog"
+ ToolTip.visible: hovered
+ ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
+ background: Rectangle {
+ implicitWidth: 40
+ implicitHeight: 40
+ radius: 5
+ border.color: getButtonColor(8, false)
+ border.width: 2
+ color: getButtonColor(8, true)
+ }
+ onClicked: {
+ sendMaterialColor("specular", getButtonColor(8, true))
+ }
+ }
+ // Specular red
+ Item {
+ Layout.row: 4
+ Layout.column: 3
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: rSpecularLoader
+ anchors.fill: parent
+ property double numberValue: model.data[8]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ rSpecularItem = rSpecularLoader.item
+ }
+ }
+ }
+ // Specular green
+ Item {
+ Layout.row: 4
+ Layout.column: 4
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: gSpecularLoader
+ anchors.fill: parent
+ property double numberValue: model.data[9]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ gSpecularItem = gSpecularLoader.item
+ }
+ }
+ }
+ // Specular blue
+ Item {
+ Layout.row: 4
+ Layout.column: 5
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: bSpecularLoader
+ anchors.fill: parent
+ property double numberValue: model.data[10]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ bSpecularItem = bSpecularLoader.item
+ }
+ }
+ }
+ // Specular alpha
+ Item {
+ Layout.row: 4
+ Layout.column: 6
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: aSpecularLoader
+ anchors.fill: parent
+ property double numberValue: model.data[11]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ aSpecularItem = aSpecularLoader.item
+ }
+ }
+ } // end Specular
+
+ // Emissive
+ Text {
+ text: " Emissive"
+ color: Material.theme == Material.Light ? "#444444" : "#bbbbbb"
+ Layout.row: 5
+ Layout.column: 1
+ }
+ // Emissive color dialog
+ Button {
+ id: emissiveButton
+ Layout.row: 5
+ Layout.column: 2
+ ToolTip.text: "Open color dialog"
+ ToolTip.visible: hovered
+ ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
+ background: Rectangle {
+ implicitWidth: 40
+ implicitHeight: 40
+ radius: 5
+ border.color: getButtonColor(12, false)
+ border.width: 2
+ color: getButtonColor(12, true)
+ }
+ onClicked: {
+ sendMaterialColor("emissive", getButtonColor(12, true))
+ }
+ }
+ // Emissive red
+ Item {
+ Layout.row: 5
+ Layout.column: 3
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: rEmissiveLoader
+ anchors.fill: parent
+ property double numberValue: model.data[12]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ rEmissiveItem = rEmissiveLoader.item
+ }
+ }
+ }
+ // Emissive green
+ Item {
+ Layout.row: 5
+ Layout.column: 4
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: gEmissiveLoader
+ anchors.fill: parent
+ property double numberValue: model.data[13]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ gEmissiveItem = gEmissiveLoader.item
+ }
+ }
+ }
+ // Emissive blue
+ Item {
+ Layout.row: 5
+ Layout.column: 5
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: bEmissiveLoader
+ anchors.fill: parent
+ property double numberValue: model.data[14]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ bEmissiveItem = bEmissiveLoader.item
+ }
+ }
+ }
+ // Emissive alpha
+ Item {
+ Layout.row: 5
+ Layout.column: 6
+ Layout.fillWidth: true
+ height: 40
+ Loader {
+ id: aEmissiveLoader
+ anchors.fill: parent
+ property double numberValue: model.data[15]
+ sourceComponent: spinBoxMaterialColor
+ onLoaded: {
+ aEmissiveItem = aEmissiveLoader.item
+ }
+ }
+ } // end Emissive
+ } // end GridLayout
+ } // end ColumnLayout (id: grid)
+ } // Rectangle (id: content)
+ }
+}
diff --git a/src/gui/plugins/entity_tree/EntityTree.cc b/src/gui/plugins/entity_tree/EntityTree.cc
index 20aa36916a..38a80a9557 100644
--- a/src/gui/plugins/entity_tree/EntityTree.cc
+++ b/src/gui/plugins/entity_tree/EntityTree.cc
@@ -555,13 +555,15 @@ bool EntityTree::eventFilter(QObject *_obj, QEvent *_event)
}
}
else if (_event->type() ==
- ignition::gazebo::gui::events::AddedRemovedEntities::kType)
+ ignition::gazebo::gui::events::GuiNewRemovedEntities::kType)
{
std::lock_guard lock(this->dataPtr->newRemovedEntityMutex);
auto addedRemovedEvent =
- reinterpret_cast(_event);
+ reinterpret_cast(_event);
if (addedRemovedEvent)
{
+ // TODO(chapulina) Make these entities visually different from entities
+ // created from the server.
for (auto entity : addedRemovedEvent->NewEntities())
this->dataPtr->newEntities.insert(entity);
diff --git a/src/gui/plugins/scene_manager/GzSceneManager.cc b/src/gui/plugins/scene_manager/GzSceneManager.cc
index baf5e8a1b0..6014d14b9d 100644
--- a/src/gui/plugins/scene_manager/GzSceneManager.cc
+++ b/src/gui/plugins/scene_manager/GzSceneManager.cc
@@ -18,7 +18,7 @@
#include "GzSceneManager.hh"
-#include
+#include
#include
#include
@@ -104,16 +104,25 @@ void GzSceneManager::Update(const UpdateInfo &_info,
this->dataPtr->renderUtil.UpdateFromECM(_info, _ecm);
- // Emit entities removed event
- std::vector removed;
+ // Emit entities created / removed event for gui::Plugins which don't have
+ // direct access to the ECM.
+ std::set created;
+ _ecm.EachNew(
+ [&](const Entity &_entity, const components::Name *)->bool
+ {
+ created.insert(_entity);
+ return true;
+ });
+ std::set removed;
_ecm.EachRemoved(
[&](const Entity &_entity, const components::Name *)->bool
{
- removed.push_back(_entity);
+ removed.insert(_entity);
return true;
});
- ignition::gazebo::gui::events::RemovedEntities removedEvent(removed);
+ ignition::gazebo::gui::events::NewRemovedEntities removedEvent(
+ created, removed);
ignition::gui::App()->sendEvent(
ignition::gui::App()->findChild(),
&removedEvent);
diff --git a/src/gui/plugins/select_entities/SelectEntities.cc b/src/gui/plugins/select_entities/SelectEntities.cc
index c08dc0963b..d3513888f7 100644
--- a/src/gui/plugins/select_entities/SelectEntities.cc
+++ b/src/gui/plugins/select_entities/SelectEntities.cc
@@ -574,13 +574,13 @@ bool SelectEntities::eventFilter(QObject *_obj, QEvent *_event)
}
}
else if (_event->type() ==
- ignition::gazebo::gui::events::RemovedEntities::kType)
+ ignition::gazebo::gui::events::NewRemovedEntities::kType)
{
if (!this->dataPtr->wireBoxes.empty())
{
- auto removedEvent =
- reinterpret_cast(_event);
- for (auto &entity : removedEvent->Data())
+ auto event =
+ reinterpret_cast(_event);
+ for (auto &entity : event->RemovedEntities())
{
auto wireBoxIt = this->dataPtr->wireBoxes.find(entity);
if (wireBoxIt != this->dataPtr->wireBoxes.end())
diff --git a/src/gui/plugins/view_angle/ViewAngle.qml b/src/gui/plugins/view_angle/ViewAngle.qml
index 9f7213f488..bdf494d73c 100644
--- a/src/gui/plugins/view_angle/ViewAngle.qml
+++ b/src/gui/plugins/view_angle/ViewAngle.qml
@@ -233,8 +233,8 @@ ColumnLayout {
Layout.row: 0
Layout.column: 1
value: ViewAngle.camPose[0]
- maximumValue: 1000000
- minimumValue: -1000000
+ maximumValue: Number.MAX_VALUE
+ minimumValue: -Number.MAX_VALUE
decimals: 6
stepSize: 0.01
onEditingFinished: ViewAngle.SetCamPose(x.value, y.value, z.value, roll.value, pitch.value, yaw.value)
@@ -252,8 +252,8 @@ ColumnLayout {
Layout.row: 1
Layout.column: 1
value: ViewAngle.camPose[1]
- maximumValue: 1000000
- minimumValue: -1000000
+ maximumValue: Number.MAX_VALUE
+ minimumValue: -Number.MAX_VALUE
decimals: 6
stepSize: 0.01
onEditingFinished: ViewAngle.SetCamPose(x.value, y.value, z.value, roll.value, pitch.value, yaw.value)
@@ -271,8 +271,8 @@ ColumnLayout {
Layout.row: 2
Layout.column: 1
value: ViewAngle.camPose[2]
- maximumValue: 1000000
- minimumValue: -1000000
+ maximumValue: Number.MAX_VALUE
+ minimumValue: -Number.MAX_VALUE
decimals: 6
stepSize: 0.01
onEditingFinished: ViewAngle.SetCamPose(x.value, y.value, z.value, roll.value, pitch.value, yaw.value)
@@ -383,7 +383,7 @@ ColumnLayout {
Layout.row: 0
Layout.column: 3
value: ViewAngle.camClipDist[1]
- maximumValue: 1000000
+ maximumValue: Number.MAX_VALUE
minimumValue: nearClip.value
decimals: 6
stepSize: 0.01
diff --git a/src/rendering/RenderUtil.cc b/src/rendering/RenderUtil.cc
index 4a70ac7b36..3df544c588 100644
--- a/src/rendering/RenderUtil.cc
+++ b/src/rendering/RenderUtil.cc
@@ -85,6 +85,7 @@
#include "ignition/gazebo/components/Transparency.hh"
#include "ignition/gazebo/components/Visibility.hh"
#include "ignition/gazebo/components/Visual.hh"
+#include "ignition/gazebo/components/VisualCmd.hh"
#include "ignition/gazebo/components/World.hh"
#include "ignition/gazebo/EntityComponentManager.hh"
@@ -205,11 +206,15 @@ class ignition::gazebo::RenderUtilPrivate
//// \brief True to enable sky in the scene
public: bool skyEnabled = false;
- /// \brief Scene background color
- public: math::Color backgroundColor = math::Color::Black;
+ /// \brief Scene background color. This is optional because a is
+ /// always present, which has a default background color value. This
+ /// backgroundColor variable is used to override the value.
+ public: std::optional backgroundColor = math::Color::Black;
- /// \brief Ambient color
- public: math::Color ambientLight = math::Color(1.0, 1.0, 1.0, 1.0);
+ /// \brief Ambient color. This is optional because an is always
+ /// present, which has a default ambient light value. This ambientLight
+ /// variable is used to override the value.
+ public: std::optional ambientLight;
/// \brief Scene manager
public: SceneManager sceneManager;
@@ -294,6 +299,25 @@ class ignition::gazebo::RenderUtilPrivate
/// \brief A map of entity ids and light updates.
public: std::vector entityLightsCmdToDelete;
+ /// \brief A map of entity ids and visual updates.
+ public: std::map entityVisuals;
+
+ /// \brief A vector of entity ids of VisualCmds to delete
+ public: std::vector entityVisualsCmdToDelete;
+
+ /// \brief Visual material equality comparision function
+ /// TODO(anyone) Currently only checks for material colors equality,
+ /// need to extend to others (e.g., PbrMaterial)
+ public: std::function
+ materialEql { [](const sdf::Material &_a, const sdf::Material &_b)
+ {
+ return
+ _a.Ambient() == _b.Ambient() &&
+ _a.Diffuse() == _b.Diffuse() &&
+ _a.Specular() == _b.Specular() &&
+ _a.Emissive() == _b.Emissive();
+ }};
+
/// \brief A map of entity ids and actor transforms.
public: std::map>
actorTransforms;
@@ -694,6 +718,41 @@ void RenderUtil::UpdateECM(const UpdateInfo &/*_info*/,
}
return true;
});
+
+ // visual commands
+ {
+ auto olderEntityVisualsCmdToDelete
+ = std::move(this->dataPtr->entityVisualsCmdToDelete);
+ this->dataPtr->entityVisualsCmdToDelete.clear();
+
+ // TODO(anyone) Currently only updates material colors,
+ // need to extend to others
+ _ecm.Each(
+ [&](const Entity &_entity,
+ const components::VisualCmd *_visualCmd) -> bool
+ {
+ this->dataPtr->entityVisuals[_entity] = _visualCmd->Data();
+ this->dataPtr->entityVisualsCmdToDelete.push_back(_entity);
+
+ auto materialComp = _ecm.Component(_entity);
+ if (materialComp)
+ {
+ msgs::Material materialMsg = _visualCmd->Data().material();
+ sdf::Material sdfMaterial = convert(materialMsg);
+
+ auto state =
+ materialComp->SetData(sdfMaterial, this->dataPtr->materialEql) ?
+ ComponentState::OneTimeChange : ComponentState::NoChange;
+ _ecm.SetChanged(_entity, components::Material::typeId, state);
+ }
+ return true;
+ });
+
+ for (const auto entity : olderEntityVisualsCmdToDelete)
+ {
+ _ecm.RemoveComponent(entity);
+ }
+ }
}
//////////////////////////////////////////////////
@@ -979,6 +1038,7 @@ void RenderUtil::Update()
auto removeEntities = std::move(this->dataPtr->removeEntities);
auto entityPoses = std::move(this->dataPtr->entityPoses);
auto entityLights = std::move(this->dataPtr->entityLights);
+ auto entityVisuals = std::move(this->dataPtr->entityVisuals);
auto updateJointParentPoses =
std::move(this->dataPtr->updateJointParentPoses);
auto trajectoryPoses = std::move(this->dataPtr->trajectoryPoses);
@@ -1007,6 +1067,7 @@ void RenderUtil::Update()
this->dataPtr->removeEntities.clear();
this->dataPtr->entityPoses.clear();
this->dataPtr->entityLights.clear();
+ this->dataPtr->entityVisuals.clear();
this->dataPtr->updateJointParentPoses.clear();
this->dataPtr->trajectoryPoses.clear();
this->dataPtr->actorTransforms.clear();
@@ -1035,8 +1096,16 @@ void RenderUtil::Update()
// extend the sensor system to support mutliple scenes in the future
for (auto &scene : newScenes)
{
- this->dataPtr->scene->SetAmbientLight(scene.Ambient());
- this->dataPtr->scene->SetBackgroundColor(scene.Background());
+ // Only set the ambient color if the RenderUtil::SetBackgroundColor
+ // was not called.
+ if (!this->dataPtr->ambientLight)
+ this->dataPtr->scene->SetAmbientLight(scene.Ambient());
+
+ // Only set the background color if the RenderUtil::SetBackgroundColor
+ // was not called.
+ if (!this->dataPtr->backgroundColor)
+ this->dataPtr->scene->SetBackgroundColor(scene.Background());
+
if (scene.Grid() && !this->dataPtr->enableSensors)
this->ShowGrid();
if (scene.Sky())
@@ -1454,6 +1523,66 @@ void RenderUtil::Update()
}
this->dataPtr->UpdateThermalCamera(thermalCameraData);
+
+ // update visuals
+ // TODO(anyone) currently updates material colors of visual only,
+ // need to extend to other updates
+ {
+ IGN_PROFILE("RenderUtil::Update Visuals");
+ for (const auto &visual : entityVisuals)
+ {
+ if (!visual.second.has_material())
+ continue;
+
+ auto node = this->dataPtr->sceneManager.NodeById(visual.first);
+ if (!node)
+ continue;
+
+ auto vis = std::dynamic_pointer_cast(node);
+ if (vis)
+ {
+ msgs::Material matMsg = visual.second.material();
+
+ // Geometry material
+ for (auto g = 0u; g < vis->GeometryCount(); ++g)
+ {
+ rendering::GeometryPtr geom = vis->GeometryByIndex(g);
+ rendering::MaterialPtr geomMat = geom->Material();
+ if (!geomMat)
+ continue;
+
+ math::Color color;
+ if (matMsg.has_ambient())
+ {
+ color = msgs::Convert(matMsg.ambient());
+ if (geomMat->Ambient() != color)
+ geomMat->SetAmbient(color);
+ }
+
+ if (matMsg.has_diffuse())
+ {
+ color = msgs::Convert(matMsg.diffuse());
+ if (geomMat->Diffuse() != color)
+ geomMat->SetDiffuse(color);
+ }
+
+ if (matMsg.has_specular())
+ {
+ color = msgs::Convert(matMsg.specular());
+ if (geomMat->Specular() != color)
+ geomMat->SetSpecular(color);
+ }
+
+ if (matMsg.has_emissive())
+ {
+ color = msgs::Convert(matMsg.emissive());
+ if (geomMat->Emissive() != color)
+ geomMat->SetEmissive(color);
+ }
+ }
+ }
+ }
+ }
}
//////////////////////////////////////////////////
@@ -2349,8 +2478,17 @@ void RenderUtil::Init()
this->dataPtr->engine->CreateScene(this->dataPtr->sceneName);
if (this->dataPtr->scene)
{
- this->dataPtr->scene->SetAmbientLight(this->dataPtr->ambientLight);
- this->dataPtr->scene->SetBackgroundColor(this->dataPtr->backgroundColor);
+ if (this->dataPtr->ambientLight)
+ {
+ this->dataPtr->scene->SetAmbientLight(
+ *this->dataPtr->ambientLight);
+ }
+
+ if (this->dataPtr->backgroundColor)
+ {
+ this->dataPtr->scene->SetBackgroundColor(
+ *this->dataPtr->backgroundColor);
+ }
this->dataPtr->scene->SetSkyEnabled(this->dataPtr->skyEnabled);
}
}
diff --git a/src/systems/CMakeLists.txt b/src/systems/CMakeLists.txt
index c5e7770470..c00277aadf 100644
--- a/src/systems/CMakeLists.txt
+++ b/src/systems/CMakeLists.txt
@@ -80,8 +80,9 @@ function(gz_add_system system_name)
"$"
"$/${unversioned}")
else()
- EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E create_symlink ${versioned} ${unversioned})
- INSTALL(FILES ${PROJECT_BINARY_DIR}/${unversioned} DESTINATION ${IGNITION_GAZEBO_PLUGIN_INSTALL_DIR})
+ file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
+ EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E create_symlink ${versioned} ${unversioned} WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
+ INSTALL(FILES ${PROJECT_BINARY_DIR}/lib/${unversioned} DESTINATION ${IGNITION_GAZEBO_PLUGIN_INSTALL_DIR})
endif()
endfunction()
@@ -129,6 +130,8 @@ add_subdirectory(sensors)
add_subdirectory(thermal)
add_subdirectory(thruster)
add_subdirectory(touch_plugin)
+add_subdirectory(track_controller)
+add_subdirectory(tracked_vehicle)
add_subdirectory(triggered_publisher)
add_subdirectory(user_commands)
add_subdirectory(velocity_control)
diff --git a/src/systems/air_pressure/AirPressure.cc b/src/systems/air_pressure/AirPressure.cc
index c3e45a81ec..10db4bff00 100644
--- a/src/systems/air_pressure/AirPressure.cc
+++ b/src/systems/air_pressure/AirPressure.cc
@@ -56,6 +56,20 @@ class ignition::gazebo::systems::AirPressurePrivate
/// \brief Ign-sensors sensor factory for creating sensors
public: sensors::SensorFactory sensorFactory;
+ /// True if the rendering component is initialized
+ public: bool initialized = false;
+
+ /// \brief Create sensor
+ /// \param[in] _ecm Mutable reference to ECM.
+ /// \param[in] _entity Entity of the IMU
+ /// \param[in] _airPressure AirPressureSensor component.
+ /// \param[in] _parent Parent entity component.
+ public: void AddAirPressure(
+ EntityComponentManager &_ecm,
+ const Entity _entity,
+ const components::AirPressureSensor *_airPressure,
+ const components::ParentEntity *_parent);
+
/// \brief Create air pressure sensor
/// \param[in] _ecm Mutable reference to ECM.
public: void CreateAirPressureEntities(EntityComponentManager &_ecm);
@@ -119,55 +133,80 @@ void AirPressure::PostUpdate(const UpdateInfo &_info,
}
//////////////////////////////////////////////////
-void AirPressurePrivate::CreateAirPressureEntities(EntityComponentManager &_ecm)
+void AirPressurePrivate::AddAirPressure(
+ EntityComponentManager &_ecm,
+ const Entity _entity,
+ const components::AirPressureSensor *_airPressure,
+ const components::ParentEntity *_parent)
{
- IGN_PROFILE("AirPressurePrivate::CreateAirPressureEntities");
- // Create air pressure sensors
- _ecm.EachNew(
- [&](const Entity &_entity,
- const components::AirPressureSensor *_airPressure,
- const components::ParentEntity *_parent)->bool
- {
- // create sensor
- std::string sensorScopedName =
- removeParentScope(scopedName(_entity, _ecm, "::", false), "::");
- sdf::Sensor data = _airPressure->Data();
- data.SetName(sensorScopedName);
- // check topic
- if (data.Topic().empty())
- {
- std::string topic = scopedName(_entity, _ecm) + "/air_pressure";
- data.SetTopic(topic);
- }
- std::unique_ptr sensor =
- this->sensorFactory.CreateSensor<
- sensors::AirPressureSensor>(data);
- if (nullptr == sensor)
- {
- ignerr << "Failed to create sensor [" << sensorScopedName << "]"
- << std::endl;
- return true;
- }
+ // create sensor
+ std::string sensorScopedName =
+ removeParentScope(scopedName(_entity, _ecm, "::", false), "::");
+ sdf::Sensor data = _airPressure->Data();
+ data.SetName(sensorScopedName);
+ // check topic
+ if (data.Topic().empty())
+ {
+ std::string topic = scopedName(_entity, _ecm) + "/air_pressure";
+ data.SetTopic(topic);
+ }
+ std::unique_ptr sensor =
+ this->sensorFactory.CreateSensor<
+ sensors::AirPressureSensor>(data);
+ if (nullptr == sensor)
+ {
+ ignerr << "Failed to create sensor [" << sensorScopedName << "]"
+ << std::endl;
+ return;
+ }
- // set sensor parent
- std::string parentName = _ecm.Component(
- _parent->Data())->Data();
- sensor->SetParent(parentName);
+ // set sensor parent
+ std::string parentName = _ecm.Component(
+ _parent->Data())->Data();
+ sensor->SetParent(parentName);
- // The WorldPose component was just created and so it's empty
- // We'll compute the world pose manually here
- // set sensor world pose
- math::Pose3d sensorWorldPose = worldPose(_entity, _ecm);
- sensor->SetPose(sensorWorldPose);
+ // The WorldPose component was just created and so it's empty
+ // We'll compute the world pose manually here
+ // set sensor world pose
+ math::Pose3d sensorWorldPose = worldPose(_entity, _ecm);
+ sensor->SetPose(sensorWorldPose);
- // Set topic
- _ecm.CreateComponent(_entity, components::SensorTopic(sensor->Topic()));
+ // Set topic
+ _ecm.CreateComponent(_entity, components::SensorTopic(sensor->Topic()));
- this->entitySensorMap.insert(
- std::make_pair(_entity, std::move(sensor)));
+ this->entitySensorMap.insert(
+ std::make_pair(_entity, std::move(sensor)));
+}
- return true;
- });
+//////////////////////////////////////////////////
+void AirPressurePrivate::CreateAirPressureEntities(EntityComponentManager &_ecm)
+{
+ IGN_PROFILE("AirPressurePrivate::CreateAirPressureEntities");
+ if (!this->initialized)
+ {
+ // Create air pressure sensors
+ _ecm.Each(
+ [&](const Entity &_entity,
+ const components::AirPressureSensor *_airPressure,
+ const components::ParentEntity *_parent)->bool
+ {
+ AddAirPressure(_ecm, _entity, _airPressure, _parent);
+ return true;
+ });
+ this->initialized = true;
+ }
+ else
+ {
+ // Create air pressure sensors
+ _ecm.EachNew(
+ [&](const Entity &_entity,
+ const components::AirPressureSensor *_airPressure,
+ const components::ParentEntity *_parent)->bool
+ {
+ AddAirPressure(_ecm, _entity, _airPressure, _parent);
+ return true;
+ });
+ }
}
//////////////////////////////////////////////////
diff --git a/src/systems/altimeter/Altimeter.cc b/src/systems/altimeter/Altimeter.cc
index 65744608a6..ca77a04077 100644
--- a/src/systems/altimeter/Altimeter.cc
+++ b/src/systems/altimeter/Altimeter.cc
@@ -58,6 +58,20 @@ class ignition::gazebo::systems::AltimeterPrivate
/// \brief Ign-sensors sensor factory for creating sensors
public: sensors::SensorFactory sensorFactory;
+ /// True if the rendering component is initialized
+ public: bool initialized = false;
+
+ /// \brief Create sensor
+ /// \param[in] _ecm Mutable reference to ECM.
+ /// \param[in] _entity Entity of the IMU
+ /// \param[in] _altimeter Altimeter component.
+ /// \param[in] _parent Parent entity component.
+ public: void AddAltimeter(
+ EntityComponentManager &_ecm,
+ const Entity _entity,
+ const components::Altimeter *_altimeter,
+ const components::ParentEntity *_parent);
+
/// \brief Create altimeter sensor
/// \param[in] _ecm Mutable reference to ECM.
public: void CreateAltimeterEntities(EntityComponentManager &_ecm);
@@ -120,56 +134,81 @@ void Altimeter::PostUpdate(const UpdateInfo &_info,
}
//////////////////////////////////////////////////
-void AltimeterPrivate::CreateAltimeterEntities(EntityComponentManager &_ecm)
+void AltimeterPrivate::AddAltimeter(
+ EntityComponentManager &_ecm,
+ const Entity _entity,
+ const components::Altimeter *_altimeter,
+ const components::ParentEntity *_parent)
{
- IGN_PROFILE("Altimeter::CreateAltimeterEntities");
- // Create altimeters
- _ecm.EachNew(
- [&](const Entity &_entity,
- const components::Altimeter *_altimeter,
- const components::ParentEntity *_parent)->bool
- {
- // create sensor
- std::string sensorScopedName =
- removeParentScope(scopedName(_entity, _ecm, "::", false), "::");
- sdf::Sensor data = _altimeter->Data();
- data.SetName(sensorScopedName);
- // check topic
- if (data.Topic().empty())
- {
- std::string topic = scopedName(_entity, _ecm) + "/altimeter";
- data.SetTopic(topic);
- }
- std::unique_ptr sensor =
- this->sensorFactory.CreateSensor<
- sensors::AltimeterSensor>(data);
- if (nullptr == sensor)
- {
- ignerr << "Failed to create sensor [" << sensorScopedName << "]"
- << std::endl;
- return true;
- }
+ // create sensor
+ std::string sensorScopedName =
+ removeParentScope(scopedName(_entity, _ecm, "::", false), "::");
+ sdf::Sensor data = _altimeter->Data();
+ data.SetName(sensorScopedName);
+ // check topic
+ if (data.Topic().empty())
+ {
+ std::string topic = scopedName(_entity, _ecm) + "/altimeter";
+ data.SetTopic(topic);
+ }
+ std::unique_ptr sensor =
+ this->sensorFactory.CreateSensor<
+ sensors::AltimeterSensor>(data);
+ if (nullptr == sensor)
+ {
+ ignerr << "Failed to create sensor [" << sensorScopedName << "]"
+ << std::endl;
+ return;
+ }
- // set sensor parent
- std::string parentName = _ecm.Component(
- _parent->Data())->Data();
- sensor->SetParent(parentName);
+ // set sensor parent
+ std::string parentName = _ecm.Component(
+ _parent->Data())->Data();
+ sensor->SetParent(parentName);
- // Get initial pose of sensor and set the reference z pos
- // The WorldPose component was just created and so it's empty
- // We'll compute the world pose manually here
- double verticalReference = worldPose(_entity, _ecm).Pos().Z();
- sensor->SetVerticalReference(verticalReference);
- sensor->SetPosition(verticalReference);
+ // Get initial pose of sensor and set the reference z pos
+ // The WorldPose component was just created and so it's empty
+ // We'll compute the world pose manually here
+ double verticalReference = worldPose(_entity, _ecm).Pos().Z();
+ sensor->SetVerticalReference(verticalReference);
+ sensor->SetPosition(verticalReference);
- // Set topic
- _ecm.CreateComponent(_entity, components::SensorTopic(sensor->Topic()));
+ // Set topic
+ _ecm.CreateComponent(_entity, components::SensorTopic(sensor->Topic()));
- this->entitySensorMap.insert(
- std::make_pair(_entity, std::move(sensor)));
+ this->entitySensorMap.insert(
+ std::make_pair(_entity, std::move(sensor)));
+}
- return true;
- });
+//////////////////////////////////////////////////
+void AltimeterPrivate::CreateAltimeterEntities(EntityComponentManager &_ecm)
+{
+ IGN_PROFILE("Altimeter::CreateAltimeterEntities");
+ if (!this->initialized)
+ {
+ // Create altimeters
+ _ecm.Each(
+ [&](const Entity &_entity,
+ const components::Altimeter *_altimeter,
+ const components::ParentEntity *_parent)->bool
+ {
+ AddAltimeter(_ecm, _entity, _altimeter, _parent);
+ return true;
+ });
+ this->initialized = true;
+ }
+ else
+ {
+ // Create altimeters
+ _ecm.EachNew(
+ [&](const Entity &_entity,
+ const components::Altimeter *_altimeter,
+ const components::ParentEntity *_parent)->bool
+ {
+ AddAltimeter(_ecm, _entity, _altimeter, _parent);
+ return true;
+ });
+ }
}
//////////////////////////////////////////////////
diff --git a/src/systems/buoyancy/Buoyancy.cc b/src/systems/buoyancy/Buoyancy.cc
index ff91c83471..fc544941b3 100644
--- a/src/systems/buoyancy/Buoyancy.cc
+++ b/src/systems/buoyancy/Buoyancy.cc
@@ -441,11 +441,6 @@ void Buoyancy::PreUpdate(const ignition::gazebo::UpdateInfo &_info,
{
auto newPose = enableComponent(_ecm, _entity);
newPose |= enableComponent(_ecm, _entity);
- if (newPose)
- {
- // Skip entity if WorldPose and inertial are not yet ready
- return true;
- }
// World pose of the link.
math::Pose3d linkWorldPose = worldPose(_entity, _ecm);
@@ -477,6 +472,13 @@ void Buoyancy::PreUpdate(const ignition::gazebo::UpdateInfo &_info,
else if (this->dataPtr->buoyancyType
== BuoyancyPrivate::BuoyancyType::GRADED_BUOYANCY)
{
+ if (newPose)
+ {
+ // Skip entity if WorldPose and inertial are not yet ready
+ // TODO(arjo): Find a way of disabling gravity effects for
+ // this first iteration.
+ return true;
+ }
std::vector collisions = _ecm.ChildrenByComponents(
_entity, components::Collision());
this->dataPtr->buoyancyForces.clear();
@@ -521,12 +523,13 @@ void Buoyancy::PreUpdate(const ignition::gazebo::UpdateInfo &_info,
}
}
}
- }
- auto [force, torque] = this->dataPtr->ResolveForces(
+ auto [force, torque] = this->dataPtr->ResolveForces(
link.WorldInertialPose(_ecm).value());
- // Apply the wrench to the link. This wrench is applied in the
- // Physics System.
- link.AddWorldWrench(_ecm, force, torque);
+ // Apply the wrench to the link. This wrench is applied in the
+ // Physics System.
+ link.AddWorldWrench(_ecm, force, torque);
+ }
+
return true;
});
}
diff --git a/src/systems/force_torque/ForceTorque.cc b/src/systems/force_torque/ForceTorque.cc
index 56f78a4e21..e1668fbf71 100644
--- a/src/systems/force_torque/ForceTorque.cc
+++ b/src/systems/force_torque/ForceTorque.cc
@@ -136,8 +136,7 @@ void ForceTorque::PostUpdate(const UpdateInfo &_info,
for (auto &it : this->dataPtr->entitySensorMap)
{
- // Update measurement time
- it.second->Update(_info.simTime);
+ it.second.get()->sensors::Sensor::Update(_info.simTime, false);
}
}
diff --git a/src/systems/joint_state_publisher/JointStatePublisher.cc b/src/systems/joint_state_publisher/JointStatePublisher.cc
index 9830edfbd7..f19b1b155e 100644
--- a/src/systems/joint_state_publisher/JointStatePublisher.cc
+++ b/src/systems/joint_state_publisher/JointStatePublisher.cc
@@ -31,6 +31,7 @@
#include "ignition/gazebo/components/JointVelocity.hh"
#include "ignition/gazebo/components/ParentEntity.hh"
#include "ignition/gazebo/components/Pose.hh"
+#include "ignition/gazebo/Util.hh"
using namespace ignition;
using namespace gazebo;
@@ -89,6 +90,14 @@ void JointStatePublisher::Configure(
this->CreateComponents(_ecm, joint);
}
}
+
+ // Advertise the state topic
+ // Sets to provided topic if available
+ if (_sdf->HasElement("topic"))
+ {
+ this->topic = _sdf->Get("topic");
+ }
+
}
//////////////////////////////////////////////////
@@ -142,11 +151,26 @@ void JointStatePublisher::PostUpdate(const UpdateInfo &_info,
worldName = _ecm.Component(
parentEntity->Data())->Data();
- // Advertise the state topic
- std::string topic = std::string("/world/") + worldName + "/model/"
- + this->model.Name(_ecm) + "/joint_state";
+ // if topic not set it will be empty
+ std::vector topics;
+ // this helps avoid unecesarry invalid topic error
+ if (!this->topic.empty())
+ {
+ topics.push_back(this->topic);
+ }
+ topics.push_back(std::string("/world/") + worldName + "/model/"
+ + this->model.Name(_ecm) + "/joint_state");
+
+ this->topic = validTopic(topics);
+ if (this->topic.empty())
+ {
+ ignerr << "No valid topics for JointStatePublisher could be found."
+ << "Make sure World/Model name does'nt contain invalid characters.\n";
+ return;
+ }
+
this->modelPub = std::make_unique(
- this->node.Advertise(topic));
+ this->node.Advertise(this->topic));
}
}
diff --git a/src/systems/joint_state_publisher/JointStatePublisher.hh b/src/systems/joint_state_publisher/JointStatePublisher.hh
index 352137edae..75c13f15a7 100644
--- a/src/systems/joint_state_publisher/JointStatePublisher.hh
+++ b/src/systems/joint_state_publisher/JointStatePublisher.hh
@@ -20,6 +20,7 @@
#include
#include
+#include
#include
#include
#include
@@ -82,6 +83,9 @@ namespace systems
/// \brief The joints that will be published.
private: std::set joints;
+
+ /// \brief The topic
+ private: std::string topic;
};
}
}
diff --git a/src/systems/logical_camera/LogicalCamera.cc b/src/systems/logical_camera/LogicalCamera.cc
index 9a16fcf40c..f9d2ac6215 100644
--- a/src/systems/logical_camera/LogicalCamera.cc
+++ b/src/systems/logical_camera/LogicalCamera.cc
@@ -59,6 +59,20 @@ class ignition::gazebo::systems::LogicalCameraPrivate
/// \brief Ign-sensors sensor factory for creating sensors
public: sensors::SensorFactory sensorFactory;
+ /// True if the rendering component is initialized
+ public: bool initialized = false;
+
+ /// \brief Create sensor
+ /// \param[in] _ecm Mutable reference to ECM.
+ /// \param[in] _entity Entity of the IMU
+ /// \param[in] _logicalCamera LogicalCamera component.
+ /// \param[in] _parent Parent entity component.
+ public: void AddLogicalCamera(
+ EntityComponentManager &_ecm,
+ const Entity _entity,
+ const components::LogicalCamera *_logicalCamera,
+ const components::ParentEntity *_parent);
+
/// \brief Create logicalCamera sensor
/// \param[in] _ecm Mutable reference to ECM.
public: void CreateLogicalCameraEntities(EntityComponentManager &_ecm);
@@ -121,55 +135,81 @@ void LogicalCamera::PostUpdate(const UpdateInfo &_info,
this->dataPtr->RemoveLogicalCameraEntities(_ecm);
}
+//////////////////////////////////////////////////
+void LogicalCameraPrivate::AddLogicalCamera(
+ EntityComponentManager &_ecm,
+ const Entity _entity,
+ const components::LogicalCamera *_logicalCamera,
+ const components::ParentEntity *_parent)
+{
+ // create sensor
+ std::string sensorScopedName =
+ removeParentScope(scopedName(_entity, _ecm, "::", false), "::");
+ auto data = _logicalCamera->Data()->Clone();
+ data->GetAttribute("name")->Set(sensorScopedName);
+ // check topic
+ if (!data->HasElement("topic"))
+ {
+ std::string topic = scopedName(_entity, _ecm) + "/logical_camera";
+ data->GetElement("topic")->Set(topic);
+ }
+ std::unique_ptr sensor =
+ this->sensorFactory.CreateSensor<
+ sensors::LogicalCameraSensor>(data);
+ if (nullptr == sensor)
+ {
+ ignerr << "Failed to create sensor [" << sensorScopedName << "]"
+ << std::endl;
+ return;
+ }
+
+ // set sensor parent
+ std::string parentName = _ecm.Component(
+ _parent->Data())->Data();
+ sensor->SetParent(parentName);
+
+ // set sensor world pose
+ math::Pose3d sensorWorldPose = worldPose(_entity, _ecm);
+ sensor->SetPose(sensorWorldPose);
+
+ // Set topic
+ _ecm.CreateComponent(_entity, components::SensorTopic(sensor->Topic()));
+
+ this->entitySensorMap.insert(
+ std::make_pair(_entity, std::move(sensor)));
+}
+
//////////////////////////////////////////////////
void LogicalCameraPrivate::CreateLogicalCameraEntities(
EntityComponentManager &_ecm)
{
IGN_PROFILE("LogicalCameraPrivate::CreateLogicalCameraEntities");
- // Create logicalCameras
- _ecm.EachNew(
- [&](const Entity &_entity,
- const components::LogicalCamera *_logicalCamera,
- const components::ParentEntity *_parent)->bool
- {
- // create sensor
- std::string sensorScopedName =
- removeParentScope(scopedName(_entity, _ecm, "::", false), "::");
- auto data = _logicalCamera->Data()->Clone();
- data->GetAttribute("name")->Set(sensorScopedName);
- // check topic
- if (!data->HasElement("topic"))
- {
- std::string topic = scopedName(_entity, _ecm) + "/logical_camera";
- data->GetElement("topic")->Set(topic);
- }
- std::unique_ptr sensor =
- this->sensorFactory.CreateSensor<
- sensors::LogicalCameraSensor>(data);
- if (nullptr == sensor)
+ if (!this->initialized)
+ {
+ // Create logicalCameras
+ _ecm.Each(
+ [&](const Entity &_entity,
+ const components::LogicalCamera *_logicalCamera,
+ const components::ParentEntity *_parent)->bool
{
- ignerr << "Failed to create sensor [" << sensorScopedName << "]"
- << std::endl;
+ AddLogicalCamera(_ecm, _entity, _logicalCamera, _parent);
return true;
- }
-
- // set sensor parent
- std::string parentName = _ecm.Component(
- _parent->Data())->Data();
- sensor->SetParent(parentName);
-
- // set sensor world pose
- math::Pose3d sensorWorldPose = worldPose(_entity, _ecm);
- sensor->SetPose(sensorWorldPose);
-
- // Set topic
- _ecm.CreateComponent(_entity, components::SensorTopic(sensor->Topic()));
+ });
+ this->initialized = true;
- this->entitySensorMap.insert(
- std::make_pair(_entity, std::move(sensor)));
-
- return true;
- });
+ }
+ else
+ {
+ // Create logicalCameras
+ _ecm.EachNew(
+ [&](const Entity &_entity,
+ const components::LogicalCamera *_logicalCamera,
+ const components::ParentEntity *_parent)->bool
+ {
+ AddLogicalCamera(_ecm, _entity, _logicalCamera, _parent);
+ return true;
+ });
+ }
}
//////////////////////////////////////////////////
diff --git a/src/systems/magnetometer/Magnetometer.cc b/src/systems/magnetometer/Magnetometer.cc
index 227558414b..62ce17a608 100644
--- a/src/systems/magnetometer/Magnetometer.cc
+++ b/src/systems/magnetometer/Magnetometer.cc
@@ -56,6 +56,22 @@ class ignition::gazebo::systems::MagnetometerPrivate
/// \brief Ign-sensors sensor factory for creating sensors
public: sensors::SensorFactory sensorFactory;
+ /// True if the rendering component is initialized
+ public: bool initialized = false;
+
+ /// \brief Create sensor
+ /// \param[in] _ecm Mutable reference to ECM.
+ /// \param[in] _entity Entity of the IMU
+ /// \param[in] _magnetometer Magnetometer component.
+ /// \param[in] _worldField MagneticField component.
+ /// \param[in] _parent Parent entity component.
+ public: void AddMagnetometer(
+ EntityComponentManager &_ecm,
+ const Entity _entity,
+ const components::Magnetometer *_magnetometer,
+ const components::MagneticField *_worldField,
+ const components::ParentEntity *_parent);
+
/// \brief Create magnetometer sensor
/// \param[in] _ecm Mutable reference to ECM.
public: void CreateMagnetometerEntities(EntityComponentManager &_ecm);
@@ -118,6 +134,57 @@ void Magnetometer::PostUpdate(const UpdateInfo &_info,
this->dataPtr->RemoveMagnetometerEntities(_ecm);
}
+//////////////////////////////////////////////////
+void MagnetometerPrivate::AddMagnetometer(
+ EntityComponentManager &_ecm,
+ const Entity _entity,
+ const components::Magnetometer *_magnetometer,
+ const components::MagneticField *_worldField,
+ const components::ParentEntity *_parent)
+{
+ // create sensor
+ std::string sensorScopedName =
+ removeParentScope(scopedName(_entity, _ecm, "::", false), "::");
+ sdf::Sensor data = _magnetometer->Data();
+ data.SetName(sensorScopedName);
+ // check topic
+ if (data.Topic().empty())
+ {
+ std::string topic = scopedName(_entity, _ecm) + "/magnetometer";
+ data.SetTopic(topic);
+ }
+ std::unique_ptr sensor =
+ this->sensorFactory.CreateSensor<
+ sensors::MagnetometerSensor>(data);
+ if (nullptr == sensor)
+ {
+ ignerr << "Failed to create sensor [" << sensorScopedName << "]"
+ << std::endl;
+ return;
+ }
+
+ // set sensor parent
+ std::string parentName = _ecm.Component