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

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

/*
* 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/GearJointConf.hpp>
#include <PlayRho/Dynamics/Joints/DistanceJointConf.hpp>
#include <PlayRho/Dynamics/Joints/RevoluteJointConf.hpp>
#include <PlayRho/Dynamics/Joints/PrismaticJointConf.hpp>
#include <PlayRho/Dynamics/Joints/Joint.hpp>
#include <PlayRho/Dynamics/BodyConf.hpp>
#include <PlayRho/Dynamics/World.hpp>
#include <PlayRho/Dynamics/WorldJoint.hpp>
#include <PlayRho/Dynamics/WorldBody.hpp>
#include <PlayRho/Dynamics/WorldFixture.hpp>
#include <PlayRho/Dynamics/WorldMisc.hpp>
#include <PlayRho/Collision/Shapes/DiskShapeConf.hpp>
#include <type_traits>
using namespace playrho;
using namespace playrho::d2;
TEST(GearJointConf, 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:
#if defined(_WIN32)
#if defined(_WIN64)
EXPECT_EQ(sizeof(GearJointConf), std::size_t(136));
#else
EXPECT_EQ(sizeof(GearJointConf), std::size_t(124));
#endif
#else
EXPECT_EQ(sizeof(GearJointConf), std::size_t(136));
#endif
break;
case 8:
EXPECT_EQ(sizeof(GearJointConf), std::size_t(240));
break;
case 16:
EXPECT_EQ(sizeof(GearJointConf), std::size_t(448));
break;
default:
FAIL();
break;
}
}
#if 0
TEST(GearJointConf, ConstructionRequiresNonNullJoints)
{
}
TEST(GearJoint, IsOkay)
{
auto world = World{};
const auto b1 = CreateBody(world);
const auto b2 = CreateBody(world);
const auto b3 = CreateBody(world);
const auto b4 = CreateBody(world);
const auto dj = CreateJoint(world, DistanceJointConf{b1, b2});
EXPECT_FALSE(GearJoint::IsOkay(GearJointConf{dj, dj}));
const auto rj1 = CreateJoint(world, GetRevoluteJointConf(world, b1, b2, Length2{}));
const auto rj2 = CreateJoint(world, GetRevoluteJointConf(world, b3, b4, Length2{}));
EXPECT_TRUE(GearJoint::IsOkay(GearJointConf{rj1, rj2}));
EXPECT_FALSE(GearJoint::IsOkay(GearJointConf{rj1, rj1}));
}
#endif
TEST(GearJoint, Creation)
{
auto world = World{};
const auto body0 = CreateBody(world);
const auto body1 = CreateBody(world);
const auto body2 = CreateBody(world);
const auto body3 = CreateBody(world);
const auto rdef0 = GetRevoluteJointConf(world, body0, body1, Length2{});
const auto rdef1 = GetRevoluteJointConf(world, body2, body3, Length2{});
const auto revJoint1 = CreateJoint(world, rdef0);
const auto revJoint2 = CreateJoint(world, rdef1);
const auto def = GetGearJointConf(world, revJoint1, revJoint2);
ASSERT_EQ(def.type1, GetTypeID<RevoluteJointConf>());
ASSERT_EQ(def.type2, GetTypeID<RevoluteJointConf>());
const auto joint = CreateJoint(world, def);
EXPECT_EQ(GetType(world, joint), GetTypeID<GearJointConf>());
EXPECT_EQ(GetBodyA(world, joint), def.bodyA);
EXPECT_EQ(GetBodyB(world, joint), def.bodyB);
EXPECT_EQ(GetCollideConnected(world, joint), def.collideConnected);
EXPECT_EQ(GetLinearReaction(world, joint), Momentum2{});
EXPECT_EQ(GetAngularReaction(world, joint), AngularMomentum{0});
EXPECT_EQ(GetLocalAnchorA(world, joint), GetLocalAnchorB(world, revJoint1));
EXPECT_EQ(GetLocalAnchorB(world, joint), GetLocalAnchorB(world, revJoint2));
EXPECT_EQ(GetRatio(world, joint), def.ratio);
const auto djoint = CreateJoint(world, DistanceJointConf{body0, body1});
EXPECT_THROW(CreateJoint(world, GetGearJointConf(world, djoint, revJoint2)), InvalidArgument);
}
TEST(GearJoint, ShiftOrigin)
{
auto world = World{};
const auto body0 = CreateBody(world);
const auto body1 = CreateBody(world);
const auto body2 = CreateBody(world);
const auto body3 = CreateBody(world);
const auto rdef1 = GetRevoluteJointConf(world, body0, body1, Length2{});
const auto rdef2 = GetRevoluteJointConf(world, body2, body3, Length2{});
const auto revJoint1 = CreateJoint(world, rdef1);
const auto revJoint2 = CreateJoint(world, rdef2);
const auto def = GetGearJointConf(world, revJoint1, revJoint2);
const auto joint = CreateJoint(world, def);
const auto newOrigin = Length2{1_m, 1_m};
EXPECT_FALSE(ShiftOrigin(world, joint, newOrigin));
}
TEST(GearJoint, SetRatio)
{
auto world = World{};
const auto body0 = CreateBody(world);
const auto body1 = CreateBody(world);
const auto body2 = CreateBody(world);
const auto body3 = CreateBody(world);
auto rdef1 = GetRevoluteJointConf(world, body0, body1, Length2{});
auto rdef2 = GetRevoluteJointConf(world, body2, body3, Length2{});
const auto revJoint1 = CreateJoint(world, rdef1);
const auto revJoint2 = CreateJoint(world, rdef2);
auto def = GetGearJointConf(world, revJoint1, revJoint2);
const auto joint = CreateJoint(world, def);
ASSERT_EQ(GetRatio(world, joint), Real(1));
auto conf = TypeCast<GearJointConf>(GetJoint(world, joint));
EXPECT_NO_THROW(SetRatio(conf, Real(2)));
EXPECT_EQ(GetRatio(conf), Real(2));
EXPECT_NO_THROW(SetJoint(world, joint, conf));
EXPECT_EQ(GetRatio(world, joint), Real(2));
}
TEST(GearJoint, GetGearJointConf)
{
auto world = World{};
const auto body0 = CreateBody(world);
const auto body1 = CreateBody(world);
const auto body2 = CreateBody(world);
const auto body3 = CreateBody(world);
auto rdef1 = GetRevoluteJointConf(world, body0, body1, Length2{});
auto rdef2 = GetRevoluteJointConf(world, body2, body3, Length2{});
const auto revJoint1 = CreateJoint(world, rdef1);
const auto revJoint2 = CreateJoint(world, rdef2);
const auto def = GetGearJointConf(world, revJoint1, revJoint2);
const auto joint = CreateJoint(world, def);
ASSERT_EQ(GetType(world, joint), GetTypeID<GearJointConf>());
ASSERT_EQ(GetBodyA(world, joint), def.bodyA);
ASSERT_EQ(GetBodyB(world, joint), def.bodyB);
ASSERT_EQ(GetCollideConnected(world, joint), def.collideConnected);
ASSERT_EQ(GetLocalAnchorA(world, joint), GetLocalAnchorB(world, revJoint1));
ASSERT_EQ(GetLocalAnchorB(world, joint), GetLocalAnchorB(world, revJoint2));
auto conf = TypeCast<GearJointConf>(GetJoint(world, joint));
ASSERT_EQ(GetType1(conf), GetTypeID<decltype(rdef1)>());
ASSERT_EQ(GetType2(conf), GetTypeID<decltype(rdef2)>());
ASSERT_EQ(GetRatio(world, joint), def.ratio);
const auto cdef = GetGearJointConf(GetJoint(world, joint));
EXPECT_EQ(cdef.bodyA, def.bodyA);
EXPECT_EQ(cdef.bodyB, def.bodyB);
EXPECT_EQ(cdef.collideConnected, false);
EXPECT_EQ(cdef.type1, GetTypeID<decltype(rdef1)>());
EXPECT_EQ(cdef.type2, GetTypeID<decltype(rdef2)>());
EXPECT_EQ(cdef.ratio, Real(1));
}
TEST(GearJoint, WithDynamicCirclesAndRevoluteJoints)
{
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 p3 = Length2{+2_m, 0_m};
const auto p4 = Length2{+3_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));
const auto b3 = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseLocation(p3));
const auto b4 = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseLocation(p4));
CreateFixture(world, b1, circle);
CreateFixture(world, b2, circle);
const auto def =
GetGearJointConf(world, CreateJoint(world, GetRevoluteJointConf(world, b1, b2, Length2{})),
CreateJoint(world, GetRevoluteJointConf(world, b4, b3, Length2{})));
const auto joint = CreateJoint(world, def);
ASSERT_NE(joint, InvalidJointID);
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(GearJoint, WithDynamicCirclesAndPrismaticJoints)
{
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 p3 = Length2{+2_m, 0_m};
const auto p4 = Length2{+3_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));
const auto b3 = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseLocation(p3));
const auto b4 = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseLocation(p4));
CreateFixture(world, b1, circle);
CreateFixture(world, b2, circle);
const auto def = GetGearJointConf(
world,
const auto joint = CreateJoint(world, def);
ASSERT_NE(joint, InvalidJointID);
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(GearJoint, GetAnchorAandB)
{
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 p3 = Length2{+2_m, 0_m};
const auto p4 = Length2{+3_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));
const auto b3 = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseLocation(p3));
const auto b4 = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseLocation(p4));
CreateFixture(world, b1, circle);
CreateFixture(world, b2, circle);
const auto def =
GetGearJointConf(world, CreateJoint(world, GetRevoluteJointConf(world, b1, b2, Length2{})),
CreateJoint(world, GetRevoluteJointConf(world, b4, b3, Length2{})));
const auto joint = CreateJoint(world, def);
ASSERT_NE(joint, InvalidJointID);
const auto anchorA =
GetWorldPoint(world, GetBodyA(world, joint), GetLocalAnchorA(world, joint));
const auto anchorB =
GetWorldPoint(world, GetBodyB(world, joint), GetLocalAnchorB(world, joint));
EXPECT_EQ(GetAnchorA(world, joint), anchorA);
EXPECT_EQ(GetAnchorB(world, joint), anchorB);
}
TEST(GearJointConf, EqualsOperator)
{
EXPECT_TRUE(GearJointConf() == GearJointConf());
{
auto conf = GearJointConf{};
conf.localAnchorA = Length2{1.2_m, -3_m};
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(GearJointConf() == conf);
}
{
auto conf = GearJointConf{};
conf.localAnchorB = Length2{1.2_m, -3_m};
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(GearJointConf() == conf);
}
{
auto conf = GearJointConf{};
conf.referenceAngle1 = 23_deg;
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(GearJointConf() == conf);
}
{
auto conf = GearJointConf{};
conf.referenceAngle2 = 19_deg;
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(GearJointConf() == conf);
}
// TODO: test remaining fields.
}
TEST(GearJointConf, NotEqualsOperator)
{
EXPECT_FALSE(GearJointConf() != GearJointConf());
{
auto conf = GearJointConf{};
conf.mass = Real(3.4);
EXPECT_FALSE(conf != conf);
EXPECT_TRUE(GearJointConf() != conf);
}
// TODO: test remaining fields.
}
{
EXPECT_STREQ(GetName(GetTypeID<GearJointConf>()), "d2::GearJointConf");
}
playrho::BodyType::Static
@ Static
Static body type.
playrho::d2::GearJointConf::localAnchorA
Length2 localAnchorA
Local anchor A.
Definition: GearJointConf.hpp:85
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::UnitVec::GetTop
static constexpr UnitVec GetTop() noexcept
Gets the top-ward oriented unit vector.
Definition: UnitVec.hpp:80
playrho::d2
Name space for 2-dimensionally related PlayRho names.
Definition: AABB.cpp:34
playrho::InvalidJointID
constexpr auto InvalidJointID
Invalid joint ID value.
Definition: JointID.hpp:33
playrho::d2::GetName
const char * GetName(Manifold::Type type) noexcept
Gets a unique name for the given manifold type.
Definition: Manifold.cpp:788
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::GetJoint
const Joint & GetJoint(const WorldImpl &world, JointID id)
Gets the identified joint's value.
Definition: WorldImplJoint.cpp:57
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::GearJointConf
Gear joint definition.
Definition: GearJointConf.hpp:55
playrho::d2::GetType1
constexpr auto GetType1(const GearJointConf &object) noexcept
Free function for getting joint 1 type value of the given configuration.
Definition: GearJointConf.hpp:226
playrho::d2::GearJointConf::referenceAngle2
Angle referenceAngle2
Reference angle of joint 2. Used when type2 is Revolute.
Definition: GearJointConf.hpp:94
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::GearJointConf::localAnchorB
Length2 localAnchorB
Local anchor B.
Definition: GearJointConf.hpp:86
playrho::d2::GetBodyA
BodyID GetBodyA(const Contact &contact) noexcept
Gets the body A ID of the given contact.
Definition: Contact.hpp:581
playrho::Meter
constexpr auto Meter
Meter unit of Length.
Definition: Units.hpp:337
playrho::d2::GearJointConf::referenceAngle1
Angle referenceAngle1
Reference angle of joint 1. Used when type1 is Revolute.
Definition: GearJointConf.hpp:93
playrho::d2::CreateJoint
JointID CreateJoint(WorldImpl &world, const Joint &def)
Creates a new joint.
Definition: WorldImplJoint.cpp:47
playrho::d2::SetJoint
void SetJoint(WorldImpl &world, JointID id, const Joint &def)
Sets the identified joint's new value.
Definition: WorldImplJoint.cpp:62
playrho::d2::GetLocalAnchorB
Length2 GetLocalAnchorB(const Joint &object)
Get the anchor point on body-B in local coordinates.
Definition: Joint.cpp:96
playrho::d2::GetAngle
Angle GetAngle(const UnitVec value)
Gets the angle of the given unit vector.
Definition: Math.hpp:718
playrho::d2::GetWorldPoint
Length2 GetWorldPoint(const Body &body, const Length2 localPoint) noexcept
Gets the world coordinates of a point given in coordinates relative to the body's origin.
Definition: Body.hpp:1208
playrho::d2::GetType2
constexpr auto GetType2(const GearJointConf &object) noexcept
Free function for getting joint 2 type value of the given configuration.
Definition: GearJointConf.hpp:233
playrho::AngularMomentum
PLAYRHO_QUANTITY(boost::units::si::angular_momentum) AngularMomentum
Angular momentum quantity.
Definition: Units.hpp:304
playrho::d2::GetRatio
constexpr auto GetRatio(const GearJointConf &object) noexcept
Free function for getting the ratio value of the given configuration.
Definition: GearJointConf.hpp:205
playrho::GetTypeID
constexpr TypeID GetTypeID()
Gets the type ID for the template parameter type.
Definition: TypeInfo.hpp:113
playrho::InvalidArgument
Invalid argument logic error.
Definition: InvalidArgument.hpp:33
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::d2::GearJointConf::mass
Real mass
Either linear mass or angular mass.
Definition: GearJointConf.hpp:113
playrho::d2::DistanceJointConf
Distance joint definition.
Definition: DistanceJointConf.hpp:52
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::d2::GetLinearReaction
constexpr Momentum2 GetLinearReaction(const DistanceJointConf &object) noexcept
Gets the current linear reaction for the given configuration.
Definition: DistanceJointConf.hpp:163
playrho::d2::SetRatio
constexpr auto SetRatio(GearJointConf &object, Real value) noexcept
Free function for setting the ratio value of the given configuration.
Definition: GearJointConf.hpp:212
playrho::d2::GetRevoluteJointConf
RevoluteJointConf GetRevoluteJointConf(const Joint &joint)
Gets the definition data for the given joint.
Definition: RevoluteJointConf.cpp:102
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::NonNull
std::enable_if_t< std::is_pointer< T >::value, CheckedValue< T, NonZeroChecker< T > >> NonNull
Non-null constrained value type.
Definition: NonZero.hpp:55
playrho::d2::Step
StepStats Step(WorldImpl &world, const StepConf &conf)
Steps the given world the specified amount.
Definition: WorldImplMisc.cpp:85
playrho::d2::GetGearJointConf
GearJointConf GetGearJointConf(const Joint &joint) noexcept
Gets the definition data for the given joint.
Definition: GearJointConf.cpp:74
playrho::d2::GetPrismaticJointConf
PrismaticJointConf GetPrismaticJointConf(const Joint &joint)
Gets the definition data for the given joint.
Definition: PrismaticJointConf.cpp:126
playrho::d2::DiskShapeConf
Disk shape configuration.
Definition: DiskShapeConf.hpp:42