Skip to content

Commit 21d6c7d

Browse files
gabrielfpachecoGabriel Pacheco
authored andcommitted
Fix initialization of world components when enabling velocity checks (#2777)
Retain already initialized world component values when enabling velocity checks and adjust expectations accordingly in mesh_inertia_calulation integration tests. Signed-off-by: Gabriel Pacheco <[email protected]> Co-authored-by: Gabriel Pacheco <[email protected]> (cherry picked from commit 4ae75e5)
1 parent f8dac72 commit 21d6c7d

File tree

5 files changed

+126
-19
lines changed

5 files changed

+126
-19
lines changed

include/gz/sim/Util.hh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,18 +250,22 @@ namespace gz
250250
/// \param[in] _entity Entity whose component is being enabled
251251
/// \param[in] _enable True to enable (create), false to disable (remove).
252252
/// Defaults to true.
253+
/// \param[in] _comp The component to create if neeeded. Defaults to a
254+
/// default-constructed component.
253255
/// \return True if a component was created or removed, false if nothing
254256
/// changed.
255257
template <class ComponentType>
256258
bool enableComponent(EntityComponentManager &_ecm,
257-
Entity _entity, bool _enable = true)
259+
Entity _entity,
260+
bool _enable = true,
261+
const ComponentType &_comp = ComponentType())
258262
{
259263
bool changed{false};
260264

261265
auto exists = _ecm.Component<ComponentType>(_entity);
262266
if (_enable && !exists)
263267
{
264-
_ecm.CreateComponent(_entity, ComponentType());
268+
_ecm.CreateComponent(_entity, _comp);
265269
changed = true;
266270
}
267271
else if (!_enable && exists)

src/Link.cc

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -284,16 +284,37 @@ std::optional<math::Vector3d> Link::WorldAngularVelocity(
284284
void Link::EnableVelocityChecks(EntityComponentManager &_ecm, bool _enable)
285285
const
286286
{
287-
enableComponent<components::WorldLinearVelocity>(_ecm, this->dataPtr->id,
288-
_enable);
289-
enableComponent<components::WorldAngularVelocity>(_ecm, this->dataPtr->id,
290-
_enable);
291-
enableComponent<components::LinearVelocity>(_ecm, this->dataPtr->id,
292-
_enable);
293-
enableComponent<components::AngularVelocity>(_ecm, this->dataPtr->id,
294-
_enable);
295-
enableComponent<components::WorldPose>(_ecm, this->dataPtr->id,
296-
_enable);
287+
auto defaultWorldPose = math::Pose3d::Zero;
288+
if (_enable)
289+
{
290+
defaultWorldPose = sim::worldPose(this->dataPtr->id, _ecm);
291+
}
292+
293+
enableComponent(_ecm, this->dataPtr->id,
294+
_enable, components::LinearVelocity());
295+
enableComponent(_ecm, this->dataPtr->id,
296+
_enable, components::AngularVelocity());
297+
enableComponent(_ecm, this->dataPtr->id,
298+
_enable, components::WorldPose(defaultWorldPose));
299+
300+
auto defaultWorldLinVel = math::Vector3d::Zero;
301+
auto defaultWorldAngVel = math::Vector3d::Zero;
302+
if (_enable)
303+
{
304+
// The WorldPose component is guaranteed to exist at this point
305+
auto worldPose = this->WorldPose(_ecm).value();
306+
307+
// Compute the default world linear and angular velocities
308+
defaultWorldLinVel = worldPose.Rot().RotateVector(
309+
_ecm.Component<components::LinearVelocity>(this->dataPtr->id)->Data());
310+
defaultWorldAngVel = worldPose.Rot().RotateVector(
311+
_ecm.Component<components::AngularVelocity>(this->dataPtr->id)->Data());
312+
}
313+
314+
enableComponent(_ecm, this->dataPtr->id,
315+
_enable, components::WorldLinearVelocity(defaultWorldLinVel));
316+
enableComponent(_ecm, this->dataPtr->id,
317+
_enable, components::WorldAngularVelocity(defaultWorldAngVel));
297318
}
298319

299320
//////////////////////////////////////////////////

src/Link_TEST.cc

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,14 @@
1919

2020
#include "gz/sim/EntityComponentManager.hh"
2121
#include "gz/sim/Link.hh"
22+
#include "gz/sim/Util.hh"
23+
#include "gz/sim/components/AngularVelocity.hh"
24+
#include "gz/sim/components/LinearVelocity.hh"
2225
#include "gz/sim/components/Link.hh"
26+
#include "gz/sim/components/Model.hh"
2327
#include "gz/sim/components/Name.hh"
2428
#include "gz/sim/components/ParentEntity.hh"
29+
#include "gz/sim/components/Pose.hh"
2530
#include "gz/sim/components/Sensor.hh"
2631

2732
/////////////////////////////////////////////////
@@ -139,3 +144,67 @@ TEST(LinkTest, Sensors)
139144
EXPECT_EQ(0u, linkC.Sensors(ecm).size());
140145
EXPECT_EQ(gz::sim::kNullEntity, linkC.SensorByName(ecm, "invalid"));
141146
}
147+
148+
TEST(LinkTest, EnableVelocityChecksCreatesAdequateWorldComponents)
149+
{
150+
gz::sim::EntityComponentManager ecm;
151+
152+
gz::math::Pose3d modelWorldPose(-1.2, -3.4, -5.6, 0.1, 0.2, 0.3);
153+
gz::math::Vector3d linkWorldLinvel(0.1, 0.2, -0.3);
154+
gz::math::Vector3d linkWorldAngvel(0.04, -0.05, 0.06);
155+
156+
auto bodyLinvel = modelWorldPose.Rot().RotateVectorReverse(linkWorldLinvel);
157+
auto bodyAngvel = modelWorldPose.Rot().RotateVectorReverse(linkWorldAngvel);
158+
159+
// Create a model with a child link
160+
gz::sim::Entity modelEntity = ecm.CreateEntity();
161+
162+
ecm.CreateComponent(modelEntity,
163+
gz::sim::components::Model());
164+
ecm.CreateComponent(modelEntity,
165+
gz::sim::components::Name("model_name"));
166+
ecm.CreateComponent(modelEntity,
167+
gz::sim::components::Pose(modelWorldPose));
168+
169+
gz::sim::Entity linkEntity = ecm.CreateEntity();
170+
171+
ecm.CreateComponent(linkEntity,
172+
gz::sim::components::Link());
173+
ecm.CreateComponent(linkEntity,
174+
gz::sim::components::Name("link_name"));
175+
ecm.CreateComponent(linkEntity,
176+
gz::sim::components::ParentEntity(modelEntity));
177+
ecm.CreateComponent(linkEntity,
178+
gz::sim::components::Pose());
179+
ecm.CreateComponent(linkEntity,
180+
gz::sim::components::LinearVelocity(bodyLinvel));
181+
ecm.CreateComponent(linkEntity,
182+
gz::sim::components::AngularVelocity(bodyAngvel));
183+
184+
// The link's world pose should be correctly resolved
185+
EXPECT_EQ(modelWorldPose, gz::sim::worldPose(linkEntity, ecm));
186+
187+
gz::sim::Link link(linkEntity);
188+
189+
// Body velocities should be preserved since they were in the ECM already
190+
EXPECT_EQ(bodyLinvel,
191+
ecm.Component<gz::sim::components::LinearVelocity>(linkEntity)->Data());
192+
EXPECT_EQ(bodyAngvel,
193+
ecm.Component<gz::sim::components::AngularVelocity>(linkEntity)->Data());
194+
EXPECT_EQ(modelWorldPose, link.WorldPose(ecm).value());
195+
196+
// Enable velocity checks should provide the correct world components
197+
// if they have not been computed and inserted in the ECM yet
198+
link.EnableVelocityChecks(ecm, true);
199+
200+
EXPECT_EQ(bodyLinvel,
201+
ecm.Component<gz::sim::components::LinearVelocity>(linkEntity)->Data());
202+
EXPECT_EQ(bodyAngvel,
203+
ecm.Component<gz::sim::components::AngularVelocity>(linkEntity)->Data());
204+
EXPECT_EQ(modelWorldPose,
205+
link.WorldPose(ecm).value());
206+
EXPECT_EQ(linkWorldLinvel,
207+
link.WorldLinearVelocity(ecm).value());
208+
EXPECT_EQ(linkWorldAngvel,
209+
link.WorldAngularVelocity(ecm).value());
210+
}

src/Util_TEST.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,16 @@ TEST_F(UtilTest, EnableComponent)
726726
// Disabling again makes no changes
727727
EXPECT_FALSE(enableComponent<components::Name>(ecm, entity1, false));
728728
EXPECT_EQ(nullptr, ecm.Component<components::Name>(entity1));
729+
730+
// Creates a component with a specified value
731+
EXPECT_TRUE(enableComponent<components::Name>(ecm, entity1, true,
732+
components::Name("name")));
733+
EXPECT_EQ("name", ecm.Component<components::Name>(entity1)->Data());
734+
735+
// Disabling with a dedicated value should have the same effect
736+
EXPECT_TRUE(enableComponent<components::Name>(ecm, entity1, false,
737+
components::Name("name")));
738+
EXPECT_EQ(nullptr, ecm.Component<components::Name>(entity1));
729739
}
730740

731741
/////////////////////////////////////////////////

test/integration/mesh_inertia_calculation.cc

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <gz/sim/Model.hh>
2727
#include <gz/sim/Entity.hh>
2828
#include <gz/sim/EntityComponentManager.hh>
29+
#include <gz/sim/Util.hh>
2930

3031
#include <gz/sim/components/Inertial.hh>
3132
#include <gz/sim/components/Model.hh>
@@ -151,9 +152,11 @@ void cylinderColladaMeshInertiaCalculation(
151152
EXPECT_TRUE(
152153
link.WorldInertiaMatrix(*ecm).value().Equal(inertiaMatrix, 0.005));
153154

154-
// Check the Inertial Pose and Link Pose
155-
EXPECT_EQ(link.WorldPose(*ecm).value(), gz::math::Pose3d::Zero);
156-
EXPECT_EQ(link.WorldInertialPose(*ecm).value(), gz::math::Pose3d::Zero);
155+
// Check the Inertial Pose and Link Pose. Their world poses should be the
156+
// same since the inertial pose relative to the link is zero.
157+
EXPECT_EQ(link.WorldPose(*ecm).value(), worldPose(linkEntity, *ecm));
158+
EXPECT_EQ(link.WorldInertialPose(*ecm).value(),
159+
worldPose(linkEntity, *ecm) * gz::math::Pose3d::Zero);
157160
}
158161

159162
// Tests are disabled on Windows
@@ -242,12 +245,12 @@ void cylinderColladaMeshWithNonCenterOriginInertiaCalculation(
242245
link.WorldInertiaMatrix(*ecm).value().Equal(inertiaMatrix, 0.005));
243246

244247
// Check the Inertial Pose and Link Pose
245-
EXPECT_EQ(link.WorldPose(*ecm).value(), gz::math::Pose3d::Zero);
248+
EXPECT_EQ(link.WorldPose(*ecm).value(), worldPose(linkEntity, *ecm));
246249

247250
// Since the height of cylinder is 2m and origin is at center of bottom face
248251
// the center of mass (inertial pose) will be 1m above the ground
249252
EXPECT_EQ(link.WorldInertialPose(*ecm).value(),
250-
gz::math::Pose3d(0, 0, 1, 0, 0, 0));
253+
worldPose(linkEntity, *ecm) * gz::math::Pose3d(0, 0, 1, 0, 0, 0));
251254
}
252255

253256
// Tests are disabled on Windows
@@ -348,9 +351,9 @@ void cylinderColladaOptimizedMeshInertiaCalculation(
348351
EXPECT_TRUE(actualIxyxzyz.Equal(
349352
meshInertial.MassMatrix().OffDiagonalMoments(), 3.5));
350353
// Check the Inertial Pose and Link Pose
351-
EXPECT_EQ(link.WorldPose(*ecm).value(), gz::math::Pose3d::Zero);
354+
EXPECT_EQ(link.WorldPose(*ecm).value(), worldPose(linkEntity, *ecm));
352355
EXPECT_TRUE(link.WorldInertialPose(*ecm).value().Equal(
353-
gz::math::Pose3d::Zero, 1e-2));
356+
worldPose(linkEntity, *ecm) * gz::math::Pose3d::Zero, 1e-2));
354357
}
355358

356359
// Tests are disabled on Windows

0 commit comments

Comments
 (0)