Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functions to enable velocity and acceleration checks on Link #935

Merged
merged 6 commits into from
Jul 30, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 27 additions & 9 deletions include/ignition/gazebo/Link.hh
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,9 @@ namespace ignition
/// body-fixed frame. If no offset is given, the velocity at the origin of
/// the Link frame will be returned.
/// \param[in] _ecm Entity-component manager.
/// \return Linear velocity of the link or nullopt if the link does not
/// have components components::WorldPose.
/// \return Linear velocity of the link or nullopt if the velocity checks
/// aren't enabled.
/// \sa EnableVelocityChecks
public: std::optional<math::Vector3d> WorldLinearVelocity(
const EntityComponentManager &_ecm) const;

Expand All @@ -195,28 +196,45 @@ namespace ignition
/// \param[in] _ecm Entity-component manager.
/// \param[in] _offset Offset of the point from the origin of the Link
/// frame, expressed in the body-fixed frame.
/// \return Linear velocity of the point on the body or nullopt if the
/// link does not have components components::WorldPose,
/// components::WorldLinearVelocity and components::WorldAngularVelocity.
/// \return Linear velocity of the point on the body or nullopt if
/// velocity checks aren't enabled.
/// \sa EnableVelocityChecks
public: std::optional<math::Vector3d> WorldLinearVelocity(
const EntityComponentManager &_ecm,
const math::Vector3d &_offset) const;

/// \brief Get the angular velocity of the link in the world frame
/// \param[in] _ecm Entity-component manager.
/// \return Angular velocity of the link or nullopt if the link does not
/// have a components::WorldAngularVelocity component.
/// \return Angular velocity of the link or nullopt if velocity checks
/// aren't enabled.
/// \sa EnableVelocityChecks
public: std::optional<math::Vector3d> WorldAngularVelocity(
const EntityComponentManager &_ecm) const;

/// \brief By default, Gazebo will not report velocities for a link, so
/// functions like `WorldLinearVelocity` will return nullopt. This
/// function can be used to enable all velocity checks.
/// \param[in] _ecm Mutable reference to the ECM.
/// \param[in] _enable True to enable checks, false to disable.
public: void EnableVelocityChecks(EntityComponentManager &_ecm,
bool _enable) const;

/// \brief Get the linear acceleration of the body in the world frame.
/// \param[in] _ecm Entity-component manager.
/// \return Linear acceleration of the body in the world frame or nullopt
/// if the link does not have a components::WorldLinearAcceleration
/// component.
/// if acceleration checks aren't enabled.
/// \sa EnableAccelerationChecks
public: std::optional<math::Vector3d> WorldLinearAcceleration(
const EntityComponentManager &_ecm) const;

/// \brief By default, Gazebo will not report accelerations for a link, so
/// functions like `WorldLinearAcceleration` will return nullopt. This
/// function can be used to enable all acceleration checks.
/// \param[in] _ecm Mutable reference to the ECM.
/// \param[in] _enable True to enable checks, false to disable.
public: void EnableAccelerationChecks(EntityComponentManager &_ecm,
bool _enable) const;

/// \brief Get the inertia matrix in the world frame.
/// \param[in] _ecm Entity-component manager.
/// \return Inertia matrix in world frame, returns nullopt if link
Expand Down
27 changes: 27 additions & 0 deletions include/ignition/gazebo/Util.hh
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,33 @@ namespace ignition
const Entity &_entity,
const EntityComponentManager &_ecm);

/// \brief Helper function to "enable" a component (i.e. create it if it
/// doesn't exist) or "disable" a component (i.e. remove it if it exists).
/// \param[in] _ecm Mutable reference to the ECM
/// \param[in] _entity Entity whose component is being enabled
/// \param[in] _enable True to enable (create), false to disable (remove).
/// \return True if a component was created or removed, false if nothing
/// changed.
template <class ComponentType>
bool IGNITION_GAZEBO_VISIBLE enableComponent(EntityComponentManager &_ecm,
Entity _entity, bool _enable)
chapulina marked this conversation as resolved.
Show resolved Hide resolved
{
bool changed{false};

auto exists = _ecm.Component<ComponentType>(_entity);
if (_enable && !exists)
{
_ecm.CreateComponent(_entity, ComponentType());
changed = true;
}
else if (!_enable && exists)
{
_ecm.RemoveComponent<ComponentType>(_entity);
changed = true;
}
return changed;
}

/// \brief Environment variable holding resource paths.
const std::string kResourcePathEnv{"IGN_GAZEBO_RESOURCE_PATH"};

Expand Down
27 changes: 27 additions & 0 deletions src/Link.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "ignition/gazebo/components/Pose.hh"
#include "ignition/gazebo/components/Visual.hh"
#include "ignition/gazebo/components/WindMode.hh"
#include "ignition/gazebo/Util.hh"

#include "ignition/gazebo/Link.hh"

Expand Down Expand Up @@ -228,6 +229,22 @@ std::optional<math::Vector3d> Link::WorldAngularVelocity(
this->dataPtr->id);
}

//////////////////////////////////////////////////
void Link::EnableVelocityChecks(EntityComponentManager &_ecm, bool _enable)
const
{
enableComponent<components::WorldLinearVelocity>(_ecm, this->dataPtr->id,
_enable);
enableComponent<components::WorldAngularVelocity>(_ecm, this->dataPtr->id,
_enable);
enableComponent<components::LinearVelocity>(_ecm, this->dataPtr->id,
_enable);
enableComponent<components::AngularVelocity>(_ecm, this->dataPtr->id,
_enable);
enableComponent<components::WorldPose>(_ecm, this->dataPtr->id,
_enable);
}

//////////////////////////////////////////////////
std::optional<math::Vector3d> Link::WorldLinearAcceleration(
const EntityComponentManager &_ecm) const
Expand All @@ -236,6 +253,16 @@ std::optional<math::Vector3d> Link::WorldLinearAcceleration(
this->dataPtr->id);
}

//////////////////////////////////////////////////
void Link::EnableAccelerationChecks(EntityComponentManager &_ecm, bool _enable)
const
{
enableComponent<components::WorldLinearAcceleration>(_ecm, this->dataPtr->id,
_enable);
enableComponent<components::LinearAcceleration>(_ecm, this->dataPtr->id,
_enable);
}

//////////////////////////////////////////////////
std::optional<math::Matrix3d> Link::WorldInertiaMatrix(
const EntityComponentManager &_ecm) const
Expand Down
25 changes: 25 additions & 0 deletions src/Util_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -557,3 +557,28 @@ TEST(UtilTest, TopLevelModel)
// the world should have no top level model
EXPECT_EQ(kNullEntity, topLevelModel(worldEntity, ecm));
}

/////////////////////////////////////////////////
TEST(UtilTest, EnableComponent)
{
EntityComponentManager ecm;

auto entity1 = ecm.CreateEntity();
EXPECT_EQ(nullptr, ecm.Component<components::Name>(entity1));

// Enable
EXPECT_TRUE(enableComponent<components::Name>(ecm, entity1, true));
EXPECT_NE(nullptr, ecm.Component<components::Name>(entity1));

// Enabling again makes no changes
EXPECT_FALSE(enableComponent<components::Name>(ecm, entity1, true));
EXPECT_NE(nullptr, ecm.Component<components::Name>(entity1));

// Disable
EXPECT_TRUE(enableComponent<components::Name>(ecm, entity1, false));
EXPECT_EQ(nullptr, ecm.Component<components::Name>(entity1));

// Disabling again makes no changes
EXPECT_FALSE(enableComponent<components::Name>(ecm, entity1, false));
EXPECT_EQ(nullptr, ecm.Component<components::Name>(entity1));
}
37 changes: 4 additions & 33 deletions src/systems/kinetic_energy_monitor/KineticEnergyMonitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,40 +127,11 @@ void KineticEnergyMonitor::Configure(const Entity &_entity,
transport::Node node;
this->dataPtr->pub = node.Advertise<msgs::Double>(topic);

if (!_ecm.Component<components::WorldPose>(this->dataPtr->linkEntity))
{
_ecm.CreateComponent(this->dataPtr->linkEntity,
components::WorldPose());
}
Link link(this->dataPtr->linkEntity);
link.EnableVelocityChecks(_ecm, true);

if (!_ecm.Component<components::Inertial>(this->dataPtr->linkEntity))
{
_ecm.CreateComponent(this->dataPtr->linkEntity, components::Inertial());
}

// Create a world linear velocity component if one is not present.
if (!_ecm.Component<components::WorldLinearVelocity>(
this->dataPtr->linkEntity))
{
_ecm.CreateComponent(this->dataPtr->linkEntity,
components::WorldLinearVelocity());
}

// Create an angular velocity component if one is not present.
if (!_ecm.Component<components::AngularVelocity>(
this->dataPtr->linkEntity))
{
_ecm.CreateComponent(this->dataPtr->linkEntity,
components::AngularVelocity());
}

// Create an angular velocity component if one is not present.
if (!_ecm.Component<components::WorldAngularVelocity>(
this->dataPtr->linkEntity))
{
_ecm.CreateComponent(this->dataPtr->linkEntity,
components::WorldAngularVelocity());
}
// Create a default inertia in case the link doesn't have it
enableComponent<components::Inertial>(_ecm, this->dataPtr->linkEntity, true);
}

//////////////////////////////////////////////////
Expand Down
20 changes: 2 additions & 18 deletions src/systems/lift_drag/LiftDrag.cc
Original file line number Diff line number Diff line change
Expand Up @@ -498,24 +498,8 @@ void LiftDrag::PreUpdate(const UpdateInfo &_info, EntityComponentManager &_ecm)

if (this->dataPtr->validConfig)
{
if (!_ecm.Component<components::WorldPose>(this->dataPtr->linkEntity))
{
_ecm.CreateComponent(this->dataPtr->linkEntity,
components::WorldPose());
}

if (!_ecm.Component<components::WorldLinearVelocity>(
this->dataPtr->linkEntity))
{
_ecm.CreateComponent(this->dataPtr->linkEntity,
components::WorldLinearVelocity());
}
if (!_ecm.Component<components::WorldAngularVelocity>(
this->dataPtr->linkEntity))
{
_ecm.CreateComponent(this->dataPtr->linkEntity,
components::WorldAngularVelocity());
}
Link link(this->dataPtr->linkEntity);
link.EnableVelocityChecks(_ecm, true);

if ((this->dataPtr->controlJointEntity != kNullEntity) &&
!_ecm.Component<components::JointPosition>(
Expand Down
13 changes: 2 additions & 11 deletions src/systems/wind_effects/WindEffects.cc
Original file line number Diff line number Diff line change
Expand Up @@ -547,17 +547,8 @@ void WindEffects::PreUpdate(const UpdateInfo &_info,
{
if (_windMode->Data())
{
// Create a WorldLinearVelocity component on the link so that
// physics can populate it
if (!_ecm.Component<components::WorldLinearVelocity>(_entity))
{
_ecm.CreateComponent(_entity,
components::WorldLinearVelocity());
}
if (!_ecm.Component<components::WorldPose>(_entity))
{
_ecm.CreateComponent(_entity, components::WorldPose());
}
Link link(_entity);
link.EnableVelocityChecks(_ecm, true);
}
return true;
});
Expand Down
46 changes: 39 additions & 7 deletions test/integration/link.cc
Original file line number Diff line number Diff line change
Expand Up @@ -256,17 +256,28 @@ TEST_F(LinkIntegrationTest, LinkVelocities)

ASSERT_TRUE(link.Valid(ecm));

// Before we add components, velocity functions should return nullopt
// Before enabling, velocity functions should return nullopt
EXPECT_EQ(std::nullopt, link.WorldLinearVelocity(ecm));
EXPECT_EQ(std::nullopt, link.WorldAngularVelocity(ecm));

// After enabling, velocity functions should return default values
link.EnableVelocityChecks(ecm, true);

EXPECT_NE(nullptr, ecm.Component<components::WorldPose>(eLink));
EXPECT_NE(nullptr, ecm.Component<components::WorldLinearVelocity>(eLink));
EXPECT_NE(nullptr, ecm.Component<components::WorldAngularVelocity>(eLink));

EXPECT_EQ(math::Vector3d::Zero, link.WorldLinearVelocity(ecm));
EXPECT_EQ(math::Vector3d::Zero, link.WorldAngularVelocity(ecm));

// With custom velocities
math::Pose3d pose;
pose.Set(0, 0, 0, IGN_PI_2, 0, 0);
math::Vector3d linVel{1.0, 0.0, 0.0};
math::Vector3d angVel{0.0, 0.0, 2.0};
ecm.CreateComponent(eLink, components::WorldPose(pose));
ecm.CreateComponent(eLink, components::WorldLinearVelocity(linVel));
ecm.CreateComponent(eLink, components::WorldAngularVelocity(angVel));
ecm.SetComponentData<components::WorldPose>(eLink, pose);
ecm.SetComponentData<components::WorldLinearVelocity>(eLink, linVel);
ecm.SetComponentData<components::WorldAngularVelocity>(eLink, angVel);

EXPECT_EQ(linVel, link.WorldLinearVelocity(ecm));
EXPECT_EQ(angVel, link.WorldAngularVelocity(ecm));
Expand All @@ -276,6 +287,16 @@ TEST_F(LinkIntegrationTest, LinkVelocities)
math::Vector3d angVelBody = pose.Rot().RotateVectorReverse(angVel);
auto expLinVel = linVel + pose.Rot().RotateVector(angVelBody.Cross(offset));
EXPECT_EQ(expLinVel, link.WorldLinearVelocity(ecm, offset));

// Disabling velocities goes back to nullopt
link.EnableVelocityChecks(ecm, false);

EXPECT_EQ(std::nullopt, link.WorldLinearVelocity(ecm));
EXPECT_EQ(std::nullopt, link.WorldAngularVelocity(ecm));
EXPECT_EQ(std::nullopt, link.WorldLinearVelocity(ecm, offset));
EXPECT_EQ(nullptr, ecm.Component<components::WorldPose>(eLink));
EXPECT_EQ(nullptr, ecm.Component<components::WorldLinearVelocity>(eLink));
EXPECT_EQ(nullptr, ecm.Component<components::WorldAngularVelocity>(eLink));
}

//////////////////////////////////////////////////
Expand All @@ -293,14 +314,25 @@ TEST_F(LinkIntegrationTest, LinkAccelerations)

ASSERT_TRUE(link.Valid(ecm));

// Before we add components, velocity functions should return nullopt
// Before we enable acceleration, acceleration should return nullopt
EXPECT_EQ(std::nullopt, link.WorldLinearAcceleration(ecm));

// After enabling, they should return default values
link.EnableAccelerationChecks(ecm, true);
EXPECT_EQ(math::Vector3d::Zero, link.WorldLinearAcceleration(ecm));
EXPECT_NE(nullptr, ecm.Component<components::WorldLinearAcceleration>(eLink));

// After setting acceleration, we get the value
math::Vector3d linAccel{1.0, 0.0, 0.0};
math::Vector3d angAccel{0.0, 0.0, 2.0};
ecm.CreateComponent(eLink, components::WorldLinearAcceleration(linAccel));
ecm.SetComponentData<components::WorldLinearAcceleration>(eLink, linAccel);

EXPECT_EQ(linAccel, link.WorldLinearAcceleration(ecm));

// Disabling accelerations goes back to nullopt
link.EnableAccelerationChecks(ecm, false);

EXPECT_EQ(std::nullopt, link.WorldLinearAcceleration(ecm));
EXPECT_EQ(nullptr, ecm.Component<components::WorldLinearAcceleration>(eLink));
}

//////////////////////////////////////////////////
Expand Down