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

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

/*
* 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/WeldJointConf.hpp>
#include <PlayRho/Dynamics/Joints/Joint.hpp>
#include <PlayRho/Dynamics/BodyConf.hpp>
#include <PlayRho/Dynamics/World.hpp>
#include <PlayRho/Dynamics/WorldFixture.hpp>
#include <PlayRho/Dynamics/WorldMisc.hpp>
#include <PlayRho/Dynamics/WorldBody.hpp>
#include <PlayRho/Dynamics/WorldJoint.hpp>
#include <PlayRho/Dynamics/StepConf.hpp>
#include <PlayRho/Collision/Shapes/DiskShapeConf.hpp>
using namespace playrho;
using namespace playrho::d2;
TEST(WeldJoint, Traits)
{
}
TEST(WeldJointConf, 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(WeldJointConf), std::size_t(108));
break;
case 8:
EXPECT_EQ(sizeof(WeldJointConf), std::size_t(208));
break;
case 16:
EXPECT_EQ(sizeof(WeldJointConf), std::size_t(416));
break;
default:
FAIL();
break;
}
}
TEST(WeldJointConf, DefaultConstruction)
{
EXPECT_EQ(def.bodyA, InvalidBodyID);
EXPECT_EQ(def.bodyB, InvalidBodyID);
EXPECT_EQ(def.collideConnected, false);
EXPECT_EQ(def.localAnchorA, (Length2{}));
EXPECT_EQ(def.localAnchorB, (Length2{}));
EXPECT_EQ(def.referenceAngle, 0_deg);
EXPECT_EQ(def.frequency, 0_Hz);
EXPECT_EQ(def.dampingRatio, Real(0));
}
TEST(WeldJoint, Construction)
{
Joint joint{def};
EXPECT_EQ(GetType(joint), GetTypeID<WeldJointConf>());
EXPECT_EQ(GetBodyA(joint), def.bodyA);
EXPECT_EQ(GetBodyB(joint), def.bodyB);
EXPECT_EQ(GetCollideConnected(joint), def.collideConnected);
EXPECT_EQ(GetLinearReaction(joint), Momentum2{});
EXPECT_EQ(GetAngularReaction(joint), AngularMomentum{0});
EXPECT_EQ(GetLocalAnchorA(joint), def.localAnchorA);
EXPECT_EQ(GetLocalAnchorB(joint), def.localAnchorB);
EXPECT_EQ(GetReferenceAngle(joint), def.referenceAngle);
EXPECT_EQ(GetFrequency(joint), def.frequency);
EXPECT_EQ(GetDampingRatio(joint), def.dampingRatio);
}
TEST(WeldJoint, GetWeldJointConf)
{
auto world = World{};
const auto bodyA = CreateBody(world);
const auto bodyB = CreateBody(world);
const auto anchor = Length2(2_m, 1_m);
const auto def = GetWeldJointConf(world, bodyA, bodyB, anchor);
Joint joint{def};
ASSERT_EQ(GetType(joint), GetTypeID<WeldJointConf>());
ASSERT_EQ(GetBodyA(joint), def.bodyA);
ASSERT_EQ(GetBodyB(joint), def.bodyB);
ASSERT_EQ(GetCollideConnected(joint), def.collideConnected);
ASSERT_EQ(GetLocalAnchorA(joint), def.localAnchorA);
ASSERT_EQ(GetLocalAnchorB(joint), def.localAnchorB);
ASSERT_EQ(GetReferenceAngle(joint), def.referenceAngle);
ASSERT_EQ(GetFrequency(joint), def.frequency);
ASSERT_EQ(GetDampingRatio(joint), def.dampingRatio);
const auto cdef = GetWeldJointConf(joint);
EXPECT_EQ(cdef.bodyA, bodyA);
EXPECT_EQ(cdef.bodyB, bodyB);
EXPECT_EQ(cdef.collideConnected, false);
EXPECT_EQ(cdef.localAnchorA, anchor);
EXPECT_EQ(cdef.localAnchorB, anchor);
EXPECT_EQ(def.referenceAngle, 0_deg);
EXPECT_EQ(def.frequency, 0_Hz);
EXPECT_EQ(def.dampingRatio, Real(0));
}
TEST(WeldJoint, WithDynamicCircles)
{
const auto circle = Shape{DiskShapeConf{}.UseRadius(0.2_m)};
auto world = World{};
const auto p1 = Length2{-1_m, 0_m};
const auto p2 = Length2{+1_m, 0_m};
const auto b1 = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseLocation(p1));
const auto b2 = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseLocation(p2));
CreateFixture(world, b1, circle);
CreateFixture(world, b2, circle);
const auto anchor = Length2(2_m, 1_m);
const auto jd = GetWeldJointConf(world, b1, b2, anchor);
CreateJoint(world, Joint{jd});
Step(world, 1_s);
EXPECT_NEAR(double(Real{GetX(GetLocation(world, b1)) / Meter}), -1.0, 0.001);
EXPECT_NEAR(double(Real{GetY(GetLocation(world, b1)) / Meter}), 0.0, 0.001);
EXPECT_NEAR(double(Real{GetX(GetLocation(world, b2)) / Meter}), +1.0, 0.01);
EXPECT_NEAR(double(Real{GetY(GetLocation(world, b2)) / Meter}), 0.0, 0.01);
EXPECT_EQ(GetAngle(world, b1), 0_deg);
EXPECT_EQ(GetAngle(world, b2), 0_deg);
}
TEST(WeldJoint, WithDynamicCircles2)
{
const auto circle = Shape{DiskShapeConf{}.UseRadius(0.2_m)};
auto world = World{};
const auto p1 = Length2{-1_m, 0_m};
const auto p2 = Length2{+1_m, 0_m};
const auto b1 = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseLocation(p1));
const auto b2 = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseLocation(p2));
CreateFixture(world, b1, circle);
CreateFixture(world, b2, circle);
const auto anchor = Length2(2_m, 1_m);
const auto jd = GetWeldJointConf(world, b1, b2, anchor).UseFrequency(10_Hz);
const auto joint = CreateJoint(world, Joint{jd});
ASSERT_NE(joint, InvalidJointID);
ASSERT_EQ(GetFrequency(world, joint), 10_Hz);
auto stepConf = StepConf{};
stepConf.doWarmStart = true;
Step(world, stepConf);
EXPECT_NEAR(double(Real{GetX(GetLocation(world, b1)) / Meter}), -1.0, 0.001);
EXPECT_NEAR(double(Real{GetY(GetLocation(world, b1)) / Meter}), 0.0, 0.001);
EXPECT_NEAR(double(Real{GetX(GetLocation(world, b2)) / Meter}), +1.0, 0.01);
EXPECT_NEAR(double(Real{GetY(GetLocation(world, b2)) / Meter}), 0.0, 0.01);
EXPECT_EQ(GetAngle(world, b1), 0_deg);
EXPECT_EQ(GetAngle(world, b2), 0_deg);
stepConf.doWarmStart = false;
Step(world, stepConf);
EXPECT_NEAR(double(Real{GetX(GetLocation(world, b1)) / Meter}), -1.0, 0.001);
EXPECT_NEAR(double(Real{GetY(GetLocation(world, b1)) / Meter}), 0.0, 0.001);
EXPECT_NEAR(double(Real{GetX(GetLocation(world, b2)) / Meter}), +1.0, 0.01);
EXPECT_NEAR(double(Real{GetY(GetLocation(world, b2)) / Meter}), 0.0, 0.01);
EXPECT_EQ(GetAngle(world, b1), 0_deg);
EXPECT_EQ(GetAngle(world, b2), 0_deg);
}
TEST(WeldJoint, GetAnchorAandB)
{
auto world = World{};
const auto loc1 = Length2{+1_m, -3_m};
const auto loc2 = Length2{-2_m, Real(+1.2f) * Meter};
const auto anchor = Length2(2_m, 1_m);
const auto b1 = CreateBody(world, BodyConf{}.UseLocation(loc1));
const auto b2 = CreateBody(world, BodyConf{}.UseLocation(loc2));
auto jd = GetWeldJointConf(world, b1, b2, anchor);
jd.localAnchorA = Length2(4_m, 5_m);
jd.localAnchorB = Length2(6_m, 7_m);
const auto joint = CreateJoint(world, Joint{jd});
ASSERT_NE(joint, InvalidJointID);
ASSERT_EQ(GetLocalAnchorA(world, joint), jd.localAnchorA);
ASSERT_EQ(GetLocalAnchorB(world, joint), jd.localAnchorB);
EXPECT_EQ(GetAnchorA(world, joint), loc1 + jd.localAnchorA);
EXPECT_EQ(GetAnchorB(world, joint), loc2 + jd.localAnchorB);
}
{
auto def = WeldJointConf{};
def.bodyA = BodyID(1u);
def.bodyB = BodyID(2u);
def.localAnchorA = Length2{-2_m, +3_m};
def.localAnchorB = Length2{+2_m, -3_m};
def.referenceAngle = 23_deg;
def.frequency = 44_Hz;
def.dampingRatio = Real(99);
def.impulse = Vec3{Real(1), Real(2), Real(3)};
const auto rotInertia = RotInertia{1_kg * 1_m2 / SquareRadian};
def.gamma = Real(2) / rotInertia;
def.bias = 2_rpm;
def.rA = Length2{3_m, 22_m};
def.rB = Length2{2_m, 22_m};
def.mass = Mat33{Vec3{Real(1), Real(2), Real(3)}, Vec3{Real(4), Real(5), Real(6)},
Vec3{Real(7), Real(8), Real(9)}};
const auto amount = Length2{1_m, 2_m};
const auto copy = def;
EXPECT_FALSE(ShiftOrigin(def, amount));
EXPECT_EQ(def.bodyA, copy.bodyA);
EXPECT_EQ(def.bodyB, copy.bodyB);
EXPECT_EQ(def.collideConnected, copy.collideConnected);
EXPECT_EQ(def.localAnchorA, copy.localAnchorA);
EXPECT_EQ(def.localAnchorB, copy.localAnchorB);
EXPECT_EQ(def.referenceAngle, copy.referenceAngle);
EXPECT_EQ(def.frequency, copy.frequency);
EXPECT_EQ(def.dampingRatio, copy.dampingRatio);
EXPECT_EQ(def.impulse, copy.impulse);
EXPECT_EQ(def.gamma, copy.gamma);
EXPECT_EQ(def.bias, copy.bias);
EXPECT_EQ(def.rA, copy.rA);
EXPECT_EQ(def.rB, copy.rB);
EXPECT_EQ(def.mass, copy.mass);
}
TEST(WeldJointConf, EqualsOperator)
{
EXPECT_TRUE(WeldJointConf() == WeldJointConf());
{
auto conf = WeldJointConf{};
conf.localAnchorA = Length2{1.2_m, -3_m};
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(WeldJointConf() == conf);
}
{
auto conf = WeldJointConf{};
conf.localAnchorB = Length2{1.2_m, -3_m};
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(WeldJointConf() == conf);
}
{
auto conf = WeldJointConf{};
conf.referenceAngle = 12.4_deg;
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(WeldJointConf() == conf);
}
// TODO: test remaining fields.
}
TEST(WeldJointConf, NotEqualsOperator)
{
EXPECT_FALSE(WeldJointConf() != WeldJointConf());
{
auto conf = WeldJointConf{};
conf.frequency = 13_Hz;
EXPECT_FALSE(conf != conf);
EXPECT_TRUE(WeldJointConf() != conf);
}
// TODO: test remaining fields.
}
{
EXPECT_STREQ(GetName(GetTypeID<WeldJointConf>()), "d2::WeldJointConf");
}
TEST(WeldJointConf, SetFrequencyFreeFunction)
{
auto def = WeldJointConf{};
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::BodyType::Static
@ Static
Static body type.
playrho::d2::CreateBody
BodyID CreateBody(World &world, const BodyConf &def)
Creates a rigid body with the given configuration.
Definition: WorldBody.cpp:58
playrho::d2::BodyConf::UseType
constexpr BodyConf & UseType(BodyType t) noexcept
Use the given type.
Definition: BodyConf.hpp:166
playrho::d2::WeldJointConf::rA
Length2 rA
Relative A.
Definition: WeldJointConf.hpp:107
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::WeldJointConf
Weld joint definition.
Definition: WeldJointConf.hpp:51
playrho::InvalidJointID
constexpr auto InvalidJointID
Invalid joint ID value.
Definition: JointID.hpp:33
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::d2::GetName
const char * GetName(Manifold::Type type) noexcept
Gets a unique name for the given manifold type.
Definition: Manifold.cpp:788
playrho::d2::WeldJointConf::UseFrequency
constexpr auto & UseFrequency(NonNegative< Frequency > v) noexcept
Uses the given frequency value.
Definition: WeldJointConf.hpp:70
playrho::d2::WeldJointConf::localAnchorA
Length2 localAnchorA
The local anchor point relative to body A's origin.
Definition: WeldJointConf.hpp:84
playrho::GetX
constexpr auto & GetX(T &value)
Gets the "X" element of the given value - i.e. the first element.
Definition: Math.hpp:66
playrho
Name space for all PlayRho related names.
Definition: AABB.cpp:33
playrho::d2::GetLocalAnchorA
Length2 GetLocalAnchorA(const Joint &object)
Get the anchor point on body-A in local coordinates.
Definition: Joint.cpp:62
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::ShiftOrigin
constexpr bool ShiftOrigin(DistanceJointConf &, Length2) noexcept
Shifts the origin notion of the given configuration.
Definition: DistanceJointConf.hpp:177
playrho::d2::WeldJointConf::bias
AngularVelocity bias
Bias.
Definition: WeldJointConf.hpp:106
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::GetReferenceAngle
Angle GetReferenceAngle(const Joint &object)
Gets the reference angle of the joint if it has one.
Definition: Joint.cpp:215
playrho::d2::BodyConf::UseLocation
constexpr BodyConf & UseLocation(Length2 l) noexcept
Use the given location.
Definition: BodyConf.hpp:172
playrho::Meter
constexpr auto Meter
Meter unit of Length.
Definition: Units.hpp:337
playrho::d2::WeldJointConf::referenceAngle
Angle referenceAngle
The body-B angle minus body-A angle in the reference state (radians).
Definition: WeldJointConf.hpp:90
playrho::d2::WeldJointConf::impulse
Vec3 impulse
Impulse.
Definition: WeldJointConf.hpp:102
playrho::d2::WeldJointConf::frequency
NonNegative< Frequency > frequency
Mass-spring-damper frequency.
Definition: WeldJointConf.hpp:95
playrho::d2::CreateJoint
JointID CreateJoint(WorldImpl &world, const Joint &def)
Creates a new joint.
Definition: WorldImplJoint.cpp:47
playrho::d2::GetLocalAnchorB
Length2 GetLocalAnchorB(const Joint &object)
Get the anchor point on body-B in local coordinates.
Definition: Joint.cpp:96
playrho::IsAddable
Template for determining if the given types are addable.
Definition: Templates.hpp:189
playrho::d2::GetAngle
Angle GetAngle(const UnitVec value)
Gets the angle of the given unit vector.
Definition: Math.hpp:718
playrho::StepConf::doWarmStart
bool doWarmStart
Do warm start.
Definition: StepConf.hpp:269
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::d2::GetAngularReaction
constexpr AngularMomentum GetAngularReaction(const DistanceJointConf &) noexcept
Gets the current angular reaction for the given configuration.
Definition: DistanceJointConf.hpp:170
playrho::d2::CreateFixture
FixtureID CreateFixture(World &world, FixtureConf def, bool resetMassData)
Creates a fixture within the specified world.
Definition: WorldFixture.cpp:48
playrho::Real
float Real
Real-number type.
Definition: Real.hpp:69
playrho::d2::DiskShapeConf::UseRadius
constexpr DiskShapeConf & UseRadius(NonNegative< Length > r) noexcept
Uses the given value as the radius.
Definition: DiskShapeConf.hpp:65
playrho::d2::BodyConf
Configuration for a body.
Definition: BodyConf.hpp:50
playrho::d2::GetLocation
constexpr Length2 GetLocation(const Transformation &value) noexcept
Gets the location information from the given transformation.
Definition: Transformation.hpp:69
playrho::BodyID
detail::IndexingNamedType< BodyCounter, struct BodyIdentifier > BodyID
Identifier for bodies.
Definition: BodyID.hpp:30
playrho::d2::WeldJointConf::rB
Length2 rB
Relative B.
Definition: WeldJointConf.hpp:108
playrho::d2::WeldJointConf::gamma
InvRotInertia gamma
Gamma.
Definition: WeldJointConf.hpp:105
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::GetWeldJointConf
WeldJointConf GetWeldJointConf(const Joint &joint)
Gets the definition data for the given joint.
Definition: WeldJointConf.cpp:101
playrho::SquareRadian
constexpr auto SquareRadian
Square radian unit type.
Definition: Units.hpp:379
playrho::Vector
Vector.
Definition: Vector.hpp:49
playrho::d2::GetAnchorA
Length2 GetAnchorA(const World &world, JointID id)
Get the anchor point on body-A in world coordinates.
Definition: WorldJoint.cpp:208
playrho::d2::GetType
TypeID GetType(const Shape &shape) noexcept
Gets the type info of the use of the given shape.
Definition: Shape.hpp:329
playrho::IsIterable
typename detail::IsIterableImpl< T > IsIterable
Determines whether the given type is an iterable type.
Definition: Templates.hpp:225
playrho::d2::GetLinearReaction
constexpr Momentum2 GetLinearReaction(const DistanceJointConf &object) noexcept
Gets the current linear reaction for the given configuration.
Definition: DistanceJointConf.hpp:163
playrho::RotInertia
PLAYRHO_QUANTITY(boost::units::si::moment_of_inertia) RotInertia
Rotational inertia quantity.
Definition: Units.hpp:274
playrho::d2::WeldJointConf::dampingRatio
Real dampingRatio
Damping ratio.
Definition: WeldJointConf.hpp:99
playrho::d2::Joint
A joint-like constraint on one or more bodies.
Definition: Joint.hpp:144
playrho::d2::JointConf::bodyB
BodyID bodyB
2nd attached body.
Definition: JointConf.hpp:39
playrho::d2::WeldJointConf::mass
Mat33 mass
Mass.
Definition: WeldJointConf.hpp:109
playrho::d2::Shape
Shape.
Definition: Shape.hpp:183
playrho::GetY
constexpr auto & GetY(T &value)
Gets the "Y" element of the given value - i.e. the second element.
Definition: Math.hpp:73
playrho::Length2
Vector2< Length > Length2
2-element vector of Length quantities.
Definition: Vector2.hpp:43
playrho::d2::Step
StepStats Step(WorldImpl &world, const StepConf &conf)
Steps the given world the specified amount.
Definition: WorldImplMisc.cpp:85
playrho::d2::JointConf::collideConnected
bool collideConnected
Collide connected.
Definition: JointConf.hpp:43
playrho::d2::WeldJointConf::localAnchorB
Length2 localAnchorB
The local anchor point relative to body B's origin.
Definition: WeldJointConf.hpp:87
playrho::d2::DiskShapeConf
Disk shape configuration.
Definition: DiskShapeConf.hpp:42