PlayRho  1.1.0
An Interactive Real-Time-Oriented C++ Physics Engine & Library
TargetJoint.cpp

This is the googletest based unit testing file for the interfaces to playrho::d2::TargetJointConf.

/*
* Copyright (c) 2020 Louis Langholtz https://github.com/louis-langholtz/PlayRho
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include "UnitTests.hpp"
#include <PlayRho/Dynamics/Joints/TargetJointConf.hpp>
#include <PlayRho/Dynamics/Joints/Joint.hpp>
#include <PlayRho/Dynamics/Contacts/ConstraintSolverConf.hpp>
#include <PlayRho/Dynamics/Contacts/BodyConstraint.hpp>
#include <PlayRho/Dynamics/StepConf.hpp>
#include <PlayRho/Dynamics/World.hpp>
#include <stdexcept>
using namespace playrho;
using namespace playrho::d2;
TEST(TargetJointConf, UseTarget)
{
const auto value = Length2(19_m, -9_m);
EXPECT_NE(TargetJointConf{}.target, value);
EXPECT_EQ(TargetJointConf{}.UseTarget(value).target, value);
}
TEST(TargetJointConf, UseMaxForce)
{
const auto value = Force(19_N);
EXPECT_NE(TargetJointConf{}.maxForce, value);
EXPECT_EQ(TargetJointConf{}.UseMaxForce(value).maxForce, value);
}
TEST(TargetJointConf, UseFrequency)
{
const auto value = 19_Hz;
EXPECT_NE(TargetJointConf{}.frequency, value);
EXPECT_EQ(TargetJointConf{}.UseFrequency(value).frequency, value);
}
TEST(TargetJointConf, UseDampingRatio)
{
const auto value = Real(0.4);
EXPECT_NE(TargetJointConf{}.dampingRatio, value);
EXPECT_EQ(TargetJointConf{}.UseDampingRatio(value).dampingRatio, value);
}
TEST(TargetJointConf, ByteSize)
{
// Check size at test runtime instead of compile-time via static_assert to avoid stopping
// builds and to report actual size rather than just reporting that expected size is wrong.
switch (sizeof(Real)) {
case 4:
EXPECT_EQ(sizeof(TargetJointConf), std::size_t(80));
break;
case 8:
EXPECT_EQ(sizeof(TargetJointConf), std::size_t(152));
break;
case 16:
EXPECT_EQ(sizeof(TargetJointConf), std::size_t(304));
break;
default:
FAIL();
break;
}
}
#if 0
TEST(TargetJoint, IsOkay)
{
auto def = TargetJointConf{};
ASSERT_FALSE(Joint::IsOkay(def));
def.bodyA = static_cast<BodyID>(1u);
def.bodyB = static_cast<BodyID>(2u);
ASSERT_TRUE(Joint::IsOkay(def));
EXPECT_TRUE(TargetJoint::IsOkay(def));
def.bodyA = InvalidBodyID;
EXPECT_TRUE(TargetJoint::IsOkay(def));
def.target = GetInvalid<decltype(def.target)>();
EXPECT_FALSE(TargetJoint::IsOkay(def));
}
#endif
TEST(TargetJoint, DefaultInitialized)
{
const auto def = TargetJointConf{};
auto joint = Joint{def};
EXPECT_EQ(GetBodyA(joint), def.bodyA);
EXPECT_EQ(GetBodyB(joint), def.bodyB);
EXPECT_EQ(GetLocalAnchorB(joint), def.localAnchorB);
// EXPECT_FALSE(IsValid(joint.GetAnchorB()));
EXPECT_EQ(GetLinearReaction(joint), Momentum2{});
EXPECT_EQ(GetAngularReaction(joint), AngularMomentum{0});
EXPECT_FALSE(GetCollideConnected(joint));
// EXPECT_FALSE(IsValid(GetLocalAnchorB(joint)));
EXPECT_EQ(GetMaxForce(joint), def.maxForce);
EXPECT_EQ(GetFrequency(joint), def.frequency);
EXPECT_EQ(GetDampingRatio(joint), def.dampingRatio);
}
TEST(TargetJoint, GetLocalAnchorB)
{
auto world = World{};
const auto bA = world.CreateBody();
const auto bB = world.CreateBody();
ASSERT_NE(bA, InvalidBodyID);
ASSERT_NE(bB, InvalidBodyID);
auto def = TargetJointConf{};
def.bodyA = bA;
def.bodyB = bB;
def.localAnchorB = Length2(-1.4_m, -2_m);
def.maxForce = 3_N;
def.frequency = 67_Hz;
def.dampingRatio = Real(0.8);
const auto joint = Joint{def};
EXPECT_EQ(GetLocalAnchorB(joint), def.localAnchorB);
}
TEST(TargetJoint, GetAnchorB)
{
auto world = World{};
const auto bA = world.CreateBody();
const auto bB = world.CreateBody();
ASSERT_NE(bA, InvalidBodyID);
ASSERT_NE(bB, InvalidBodyID);
auto def = TargetJointConf{};
def.bodyA = bA;
def.bodyB = bB;
def.localAnchorB = Length2(-1.4_m, -2_m);
def.maxForce = 3_N;
def.frequency = 67_Hz;
def.dampingRatio = Real(0.8);
const auto joint = Joint{def};
ASSERT_EQ(GetLocalAnchorB(joint), def.localAnchorB);
}
TEST(TargetJoint, ShiftOrigin)
{
auto world = World{};
const auto bA = world.CreateBody(BodyConf{}.UseLocation(Length2(-1.4_m, -2_m)));
const auto bB = world.CreateBody();
ASSERT_NE(bA, InvalidBodyID);
ASSERT_NE(bB, InvalidBodyID);
auto def = TargetJointConf{};
def.bodyA = bA;
def.bodyB = bB;
def.target = Length2(-1.4_m, -2_m);
auto joint = Joint{def};
ASSERT_EQ(GetTarget(joint), def.target);
const auto newOrigin = Length2{1_m, 1_m};
EXPECT_TRUE(ShiftOrigin(joint, newOrigin));
EXPECT_EQ(GetTarget(joint), def.target - newOrigin);
}
TEST(TargetJointConf, GetTargetJointDefFreeFunction)
{
World world;
const auto bA = world.CreateBody();
ASSERT_NE(bA, InvalidBodyID);
const auto bB = world.CreateBody();
ASSERT_NE(bB, InvalidBodyID);
auto def = TargetJointConf{};
def.bodyA = bA;
def.bodyB = bB;
def.target = Length2(-1.4_m, -2_m);
def.localAnchorB = Length2(+2.0_m, -1_m);
def.maxForce = 3_N;
def.frequency = 67_Hz;
def.dampingRatio = Real(0.8);
const auto joint = Joint{def};
const auto got = GetTargetJointConf(joint);
EXPECT_EQ(def.bodyA, got.bodyA);
EXPECT_EQ(def.bodyB, got.bodyB);
EXPECT_EQ(def.target, got.target);
EXPECT_EQ(def.localAnchorB, got.localAnchorB);
EXPECT_EQ(def.maxForce, got.maxForce);
EXPECT_EQ(def.frequency, got.frequency);
EXPECT_EQ(def.dampingRatio, got.dampingRatio);
}
{
auto def = TargetJointConf{};
auto mass = Mass22{};
EXPECT_NO_THROW(mass = GetEffectiveMassMatrix(def, BodyConstraint{}));
EXPECT_EQ(mass[0][0], 0_kg);
EXPECT_EQ(mass[0][1], 0_kg);
EXPECT_EQ(mass[1][0], 0_kg);
EXPECT_EQ(mass[1][1], 0_kg);
}
TEST(TargetJointConf, InitVelocityThrows)
{
std::vector<BodyConstraint> bodies;
auto step = StepConf{};
auto conf = ConstraintSolverConf{};
auto def = TargetJointConf{};
EXPECT_THROW(InitVelocity(def, bodies, step, conf), std::out_of_range);
}
TEST(TargetJointConf, InitVelocityUpdatesGamma)
{
auto invMass = InvMass{};
auto invRotI = InvRotInertia{};
auto localCenter = Length2{};
auto position = Position{};
auto velocity = Velocity{};
std::vector<BodyConstraint> bodies;
bodies.push_back(BodyConstraint{invMass, invRotI, localCenter, position, velocity});
auto step = StepConf{};
auto conf = ConstraintSolverConf{};
auto def = TargetJointConf{};
def.bodyA = BodyID(0u);
def.bodyB = BodyID(0u);
def.frequency = 0_Hz;
def.gamma = Real(5) / 1_kg;
EXPECT_NO_THROW(InitVelocity(def, bodies, step, conf));
EXPECT_EQ(def.gamma, Real(0) / 1_kg);
def.frequency = 1_Hz;
def.gamma = Real(5) / 1_kg;
EXPECT_NO_THROW(InitVelocity(def, bodies, step, conf));
EXPECT_EQ(def.gamma, Real(0) / 1_kg);
}
TEST(TargetJointConf, SolveVelocityThrows)
{
std::vector<BodyConstraint> bodies;
auto step = StepConf{};
auto def = TargetJointConf{};
EXPECT_THROW(SolveVelocity(def, bodies, step), std::out_of_range);
}
TEST(TargetJointConf, SolvePositionThrows)
{
std::vector<BodyConstraint> bodies;
auto conf = ConstraintSolverConf{};
auto def = TargetJointConf{};
auto result = false;
EXPECT_NO_THROW(result = SolvePosition(def, bodies, conf));
EXPECT_EQ(result, true);
}
TEST(TargetJointConf, EqualsOperator)
{
EXPECT_TRUE(TargetJointConf() == TargetJointConf());
{
auto conf = TargetJointConf{};
conf.target = Length2{1.2_m, -3_m};
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(TargetJointConf() == conf);
}
{
auto conf = TargetJointConf{};
conf.localAnchorB = Length2{1.2_m, -3_m};
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(TargetJointConf() == conf);
}
{
auto conf = TargetJointConf{};
conf.maxForce = 12_N;
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(TargetJointConf() == conf);
}
// TODO: test remaining fields.
}
TEST(TargetJointConf, NotEqualsOperator)
{
EXPECT_FALSE(TargetJointConf() != TargetJointConf());
{
auto conf = TargetJointConf{};
conf.frequency = 13_Hz;
EXPECT_FALSE(conf != conf);
EXPECT_TRUE(TargetJointConf() != conf);
}
// TODO: test remaining fields.
}
{
EXPECT_STREQ(GetName(GetTypeID<TargetJointConf>()), "d2::TargetJointConf");
}
TEST(TargetJointConf, SetFrequencyFreeFunction)
{
auto def = TargetJointConf{};
const auto frequencyA = 67_Hz;
const auto frequencyB = 2_Hz;
def.frequency = frequencyA;
auto joint = Joint(def);
EXPECT_EQ(GetFrequency(joint), frequencyA);
EXPECT_NO_THROW(SetFrequency(joint, frequencyB));
EXPECT_EQ(GetFrequency(joint), frequencyB);
}
playrho::d2::TargetJointConf::UseMaxForce
constexpr auto & UseMaxForce(NonNegative< Force > v) noexcept
Use value for max force.
Definition: TargetJointConf.hpp:80
playrho::d2::GetMaxForce
constexpr auto GetMaxForce(const FrictionJointConf &object) noexcept
Free function for getting the max force value of the given configuration.
Definition: FrictionJointConf.hpp:177
playrho::d2::World::CreateBody
BodyID CreateBody(const BodyConf &def=GetDefaultBodyConf())
Creates a rigid body with the given configuration.
Definition: World.cpp:161
playrho::d2
Name space for 2-dimensionally related PlayRho names.
Definition: AABB.cpp:34
playrho::d2::JointConf::bodyA
BodyID bodyA
1st attached body.
Definition: JointConf.hpp:36
playrho::d2::TargetJointConf::localAnchorB
Length2 localAnchorB
Anchor point.
Definition: TargetJointConf.hpp:105
playrho::d2::SetFrequency
constexpr void SetFrequency(DistanceJointConf &object, NonNegative< Frequency > value) noexcept
Free function for setting the frequency value of the given configuration.
Definition: DistanceJointConf.hpp:205
playrho::Force
PLAYRHO_QUANTITY(boost::units::si::force) Force
Force quantity.
Definition: Units.hpp:244
playrho::d2::GetName
const char * GetName(Manifold::Type type) noexcept
Gets a unique name for the given manifold type.
Definition: Manifold.cpp:788
playrho::d2::BodyConstraint
Constraint for a body.
Definition: BodyConstraint.hpp:36
playrho::d2::SolvePosition
bool SolvePosition(const DistanceJointConf &object, std::vector< BodyConstraint > &bodies, const ConstraintSolverConf &conf)
Solves the position constraint.
Definition: DistanceJointConf.cpp:194
playrho
Name space for all PlayRho related names.
Definition: AABB.cpp:33
playrho::ConstraintSolverConf
Constraint solver configuration data.
Definition: ConstraintSolverConf.hpp:33
playrho::d2::TargetJointConf::dampingRatio
NonNegative< Real > dampingRatio
The damping ratio. 0 = no damping, 1 = critical damping.
Definition: TargetJointConf.hpp:121
playrho::d2::World
Definition of an independent and simulatable "world".
Definition: World.hpp:129
playrho::d2::GetAnchorB
Length2 GetAnchorB(const World &world, JointID id)
Get the anchor point on body-B in world coordinates.
Definition: WorldJoint.cpp:216
playrho::d2::GetEffectiveMassMatrix
Mass22 GetEffectiveMassMatrix(const TargetJointConf &object, const BodyConstraint &body) noexcept
Gets the effective mass matrix for the given configuration and body information.
Definition: TargetJointConf.cpp:51
playrho::d2::ShiftOrigin
constexpr bool ShiftOrigin(DistanceJointConf &, Length2) noexcept
Shifts the origin notion of the given configuration.
Definition: DistanceJointConf.hpp:177
playrho::d2::GetBodyB
BodyID GetBodyB(const Contact &contact) noexcept
Gets the body B ID of the given contact.
Definition: Contact.hpp:588
playrho::d2::GetCollideConnected
bool GetCollideConnected(const Joint &object) noexcept
Gets collide connected.
Definition: Joint.hpp:293
playrho::d2::GetBodyA
BodyID GetBodyA(const Contact &contact) noexcept
Gets the body A ID of the given contact.
Definition: Contact.hpp:581
playrho::d2::BodyConf::UseLocation
constexpr BodyConf & UseLocation(Length2 l) noexcept
Use the given location.
Definition: BodyConf.hpp:172
playrho::d2::SolveVelocity
bool SolveVelocity(DistanceJointConf &object, std::vector< BodyConstraint > &bodies, const StepConf &)
Solves velocity constraint.
Definition: DistanceJointConf.cpp:164
playrho::d2::TargetJointConf::target
Length2 target
The initial world target point. This is assumed to coincide with the body anchor initially.
Definition: TargetJointConf.hpp:102
playrho::d2::GetLocalAnchorB
Length2 GetLocalAnchorB(const Joint &object)
Get the anchor point on body-B in local coordinates.
Definition: Joint.cpp:96
playrho::d2::TargetJointConf::maxForce
NonNegative< Force > maxForce
Max force.
Definition: TargetJointConf.hpp:113
playrho::d2::TargetJointConf::UseFrequency
constexpr auto & UseFrequency(NonNegative< Frequency > v) noexcept
Use value for frequency.
Definition: TargetJointConf.hpp:87
playrho::d2::GetTarget
Length2 GetTarget(const Joint &object)
Gets the given joint's target property if it has one.
Definition: Joint.cpp:459
playrho::d2::TargetJointConf::frequency
NonNegative< Frequency > frequency
Frequency.
Definition: TargetJointConf.hpp:118
playrho::InvalidBodyID
constexpr auto InvalidBodyID
Invalid body ID value.
Definition: BodyID.hpp:33
playrho::AngularMomentum
PLAYRHO_QUANTITY(boost::units::si::angular_momentum) AngularMomentum
Angular momentum quantity.
Definition: Units.hpp:304
playrho::StepConf
Step configuration.
Definition: StepConf.hpp:42
playrho::d2::GetFrequency
Frequency GetFrequency(const Joint &object)
Gets the frequency of the joint if it has this property.
Definition: Joint.cpp:407
playrho::InvRotInertia
PLAYRHO_QUANTITY(playrho::units::si::inverse_moment_of_inertia) InvRotInertia
Inverse rotational inertia quantity.
Definition: Units.hpp:282
playrho::d2::GetAngularReaction
constexpr AngularMomentum GetAngularReaction(const DistanceJointConf &) noexcept
Gets the current angular reaction for the given configuration.
Definition: DistanceJointConf.hpp:170
playrho::Real
float Real
Real-number type.
Definition: Real.hpp:69
playrho::d2::BodyConf
Configuration for a body.
Definition: BodyConf.hpp:50
playrho::d2::GetTargetJointConf
TargetJointConf GetTargetJointConf(const Joint &joint)
Gets the definition data for the given joint.
Definition: TargetJointConf.cpp:46
playrho::BodyID
detail::IndexingNamedType< BodyCounter, struct BodyIdentifier > BodyID
Identifier for bodies.
Definition: BodyID.hpp:30
playrho::d2::Velocity
2-D velocity related data structure.
Definition: Velocity.hpp:38
playrho::d2::GetDampingRatio
Real GetDampingRatio(const Joint &object)
Gets the given joint's damping ratio property if it has one.
Definition: Joint.cpp:389
playrho::d2::Position
2-D positional data structure.
Definition: Position.hpp:37
playrho::Vector
Vector.
Definition: Vector.hpp:49
playrho::d2::TargetJointConf::UseDampingRatio
constexpr auto & UseDampingRatio(NonNegative< Real > v) noexcept
Use value for damping ratio.
Definition: TargetJointConf.hpp:94
playrho::d2::InitVelocity
void InitVelocity(DistanceJointConf &object, std::vector< BodyConstraint > &bodies, const StepConf &step, const ConstraintSolverConf &)
Initializes velocity constraint data based on the given solver data.
Definition: DistanceJointConf.cpp:80
playrho::d2::TargetJointConf
Target joint definition.
Definition: TargetJointConf.hpp:48
playrho::d2::GetLinearReaction
constexpr Momentum2 GetLinearReaction(const DistanceJointConf &object) noexcept
Gets the current linear reaction for the given configuration.
Definition: DistanceJointConf.hpp:163
playrho::detail::IndexingNamedType< BodyCounter, struct BodyIdentifier >
playrho::GetInvalid
constexpr d2::AABB GetInvalid() noexcept
Gets an invalid AABB value.
Definition: AABB.hpp:484
playrho::InvMass
PLAYRHO_QUANTITY(playrho::units::si::inverse_mass) InvMass
Inverse mass quantity.
Definition: Units.hpp:191
playrho::d2::TargetJointConf::UseTarget
constexpr auto & UseTarget(Length2 v) noexcept
Use value for target.
Definition: TargetJointConf.hpp:62
playrho::d2::Joint
A joint-like constraint on one or more bodies.
Definition: Joint.hpp:144
playrho::Length2
Vector2< Length > Length2
2-element vector of Length quantities.
Definition: Vector2.hpp:43