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

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

/*
* 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/FrictionJointConf.hpp>
#include <PlayRho/Dynamics/Joints/Joint.hpp>
#include <PlayRho/Collision/Shapes/DiskShapeConf.hpp>
#include <PlayRho/Dynamics/World.hpp>
#include <PlayRho/Dynamics/WorldBody.hpp>
#include <PlayRho/Dynamics/WorldFixture.hpp>
#include <PlayRho/Dynamics/WorldJoint.hpp>
#include <PlayRho/Dynamics/WorldMisc.hpp>
#include <PlayRho/Dynamics/BodyConf.hpp>
#include <PlayRho/Dynamics/StepConf.hpp>
using namespace playrho;
using namespace playrho::d2;
TEST(FrictionJointConf, 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(FrictionJointConf), std::size_t(80));
break;
case 8:
EXPECT_EQ(sizeof(FrictionJointConf), std::size_t(152));
break;
case 16:
EXPECT_EQ(sizeof(FrictionJointConf), std::size_t(304));
break;
default:
FAIL();
break;
}
}
TEST(FrictionJointConf, 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.maxForce, 0_N);
EXPECT_EQ(def.maxTorque, 0_Nm);
}
TEST(FrictionJointConf, InitializingConstructor)
{
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));
const auto anchor = Length2{0_m, 0_m};
const auto def = GetFrictionJointConf(world, b1, b2, anchor);
EXPECT_EQ(def.bodyA, b1);
EXPECT_EQ(def.bodyB, b2);
EXPECT_EQ(def.localAnchorA, GetLocalPoint(world, b1, anchor));
EXPECT_EQ(def.localAnchorB, GetLocalPoint(world, b2, anchor));
}
TEST(FrictionJoint, Construction)
{
auto world = World{};
const auto b0 = CreateBody(world);
const auto b1 = CreateBody(world);
auto def = GetFrictionJointConf(world, b0, b1, Length2{});
const auto joint = Joint{def};
EXPECT_EQ(GetType(joint), GetTypeID<FrictionJointConf>());
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(GetMaxForce(joint), def.maxForce);
EXPECT_EQ(GetMaxTorque(joint), def.maxTorque);
}
TEST(FrictionJoint, GetFrictionJointConf)
{
auto world = World{};
const auto b0 = CreateBody(world);
const auto b1 = CreateBody(world);
auto def = GetFrictionJointConf(world, b0, b1, Length2{});
const auto joint = Joint{def};
ASSERT_EQ(GetType(joint), GetTypeID<FrictionJointConf>());
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(GetMaxForce(joint), def.maxForce);
ASSERT_EQ(GetMaxTorque(joint), def.maxTorque);
const auto cdef = GetFrictionJointConf(joint);
EXPECT_EQ(cdef.bodyA, b0);
EXPECT_EQ(cdef.bodyB, b1);
EXPECT_EQ(cdef.collideConnected, false);
EXPECT_EQ(cdef.localAnchorA, (Length2{}));
EXPECT_EQ(cdef.localAnchorB, (Length2{}));
EXPECT_EQ(cdef.maxForce, 0_N);
EXPECT_EQ(cdef.maxTorque, 0_Nm);
}
TEST(FrictionJoint, WithDynamicCircles)
{
const auto circle = DiskShapeConf{}.UseRadius(0.2_m);
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, Shape{circle});
CreateFixture(world, b2, Shape{circle});
auto jd = FrictionJointConf{};
jd.bodyA = b1;
jd.bodyB = b2;
ASSERT_NE(CreateJoint(world, Joint{jd}), InvalidJointID);
auto stepConf = StepConf{};
stepConf.doWarmStart = true;
Step(world, stepConf);
EXPECT_NEAR(double(Real{GetX(GetLocation(world, b1)) / 1_m}), -1.0, 0.001);
EXPECT_NEAR(double(Real{GetY(GetLocation(world, b1)) / 1_m}), 0.0, 0.001);
EXPECT_NEAR(double(Real{GetX(GetLocation(world, b2)) / 1_m}), +1.0, 0.01);
EXPECT_NEAR(double(Real{GetY(GetLocation(world, b2)) / 1_m}), 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)) / 1_m}), -1.0, 0.001);
EXPECT_NEAR(double(Real{GetY(GetLocation(world, b1)) / 1_m}), 0.0, 0.001);
EXPECT_NEAR(double(Real{GetX(GetLocation(world, b2)) / 1_m}), +1.0, 0.01);
EXPECT_NEAR(double(Real{GetY(GetLocation(world, b2)) / 1_m}), 0.0, 0.01);
EXPECT_EQ(GetAngle(world, b1), 0_deg);
EXPECT_EQ(GetAngle(world, b2), 0_deg);
}
{
auto def = FrictionJointConf{};
def.bodyA = BodyID(1u);
def.bodyB = BodyID(2u);
def.localAnchorA = Length2{-2_m, +3_m};
def.localAnchorB = Length2{+2_m, -3_m};
def.maxForce = 2_N;
def.maxTorque = 3_Nm;
def.linearImpulse = Momentum2{1_Ns, 2_Ns};
def.angularImpulse = AngularMomentum{};
def.rA = Length2{3_m, 22_m};
def.rB = Length2{2_m, 22_m};
def.linearMass = Mass22{Vector2<Mass>{1_kg, 2_kg}, Vector2<Mass>{3_kg, 4_kg}};
def.angularMass = RotInertia{};
const auto copy = def;
const auto amount = Length2{1_m, 2_m};
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.maxForce, copy.maxForce);
EXPECT_EQ(def.maxTorque, copy.maxTorque);
EXPECT_EQ(def.linearImpulse, copy.linearImpulse);
EXPECT_EQ(def.angularImpulse, copy.angularImpulse);
EXPECT_EQ(def.rA, copy.rA);
EXPECT_EQ(def.rB, copy.rB);
EXPECT_EQ(def.linearMass, copy.linearMass);
EXPECT_EQ(def.angularMass, copy.angularMass);
}
TEST(FrictionJointConf, GetMotorSpeedThrows)
{
const auto joint = Joint{FrictionJointConf{}};
EXPECT_THROW(GetMotorSpeed(joint), std::invalid_argument);
}
TEST(FrictionJointConf, SetMotorSpeedThrows)
{
auto joint = Joint{FrictionJointConf{}};
EXPECT_THROW(SetMotorSpeed(joint, 1_rpm), std::invalid_argument);
}
{
auto conf = FrictionJointConf{};
conf.angularMass = RotInertia{2_m2 * 3_kg / SquareRadian}; // L^2 M QP^-2
auto rotInertia = RotInertia{};
EXPECT_NO_THROW(rotInertia = GetAngularMass(Joint{conf}));
EXPECT_EQ(conf.angularMass, rotInertia);
}
TEST(FrictionJointConf, EqualsOperator)
{
EXPECT_TRUE(FrictionJointConf() == FrictionJointConf());
{
auto conf = FrictionJointConf{};
conf.localAnchorA = Length2{1.2_m, -3_m};
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(FrictionJointConf() == conf);
}
{
auto conf = FrictionJointConf{};
conf.localAnchorB = Length2{1.2_m, -3_m};
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(FrictionJointConf() == conf);
}
{
auto conf = FrictionJointConf{};
conf.maxForce = 2.4_N;
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(FrictionJointConf() == conf);
}
{
auto conf = FrictionJointConf{};
conf.maxTorque = 1.5_Nm;
EXPECT_TRUE(conf == conf);
EXPECT_FALSE(FrictionJointConf() == conf);
}
// TODO: test remaining fields.
}
TEST(FrictionJointConf, NotEqualsOperator)
{
EXPECT_FALSE(FrictionJointConf() != FrictionJointConf());
{
auto conf = FrictionJointConf{};
conf.rB = Length2{-1_m, 0.4_m};
EXPECT_FALSE(conf != conf);
EXPECT_TRUE(FrictionJointConf() != conf);
}
// TODO: test remaining fields.
}
{
EXPECT_STREQ(GetName(GetTypeID<FrictionJointConf>()), "d2::FrictionJointConf");
}
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::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
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::FrictionJointConf::localAnchorA
Length2 localAnchorA
Local anchor point relative to body A's origin.
Definition: FrictionJointConf.hpp:77
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::d2::FrictionJointConf::angularMass
RotInertia angularMass
Angular mass.
Definition: FrictionJointConf.hpp:96
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::FrictionJointConf::maxForce
NonNegative< Force > maxForce
Maximum friction force.
Definition: FrictionJointConf.hpp:83
playrho::d2::ShiftOrigin
constexpr bool ShiftOrigin(DistanceJointConf &, Length2) noexcept
Shifts the origin notion of the given configuration.
Definition: DistanceJointConf.hpp:177
playrho::d2::FrictionJointConf::maxTorque
NonNegative< Torque > maxTorque
Maximum friction torque.
Definition: FrictionJointConf.hpp:86
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::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::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::d2::FrictionJointConf::localAnchorB
Length2 localAnchorB
Local anchor point relative to body B's origin.
Definition: FrictionJointConf.hpp:80
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::GetMotorSpeed
AngularVelocity GetMotorSpeed(const Joint &object)
Gets the given joint's motor speed if its type supports that.
Definition: Joint.cpp:254
playrho::d2::GetAngularMass
RotInertia GetAngularMass(const Joint &object)
Gets the given joint's angular mass.
Definition: Joint.cpp:287
playrho::d2::GetLocalPoint
Length2 GetLocalPoint(const Body &body, const Length2 worldPoint) noexcept
Gets a local point relative to the body's origin given a world point.
Definition: Body.hpp:1235
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::SquareRadian
constexpr auto SquareRadian
Square radian unit type.
Definition: Units.hpp:379
playrho::d2::SetMotorSpeed
void SetMotorSpeed(Joint &object, AngularVelocity value)
Sets the given joint's motor speed if its type supports that.
Definition: Joint.cpp:269
playrho::d2::GetMaxTorque
constexpr auto GetMaxTorque(const FrictionJointConf &object) noexcept
Free function for getting the max torque value of the given configuration.
Definition: FrictionJointConf.hpp:191
playrho::Vector
Vector.
Definition: Vector.hpp:49
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::RotInertia
PLAYRHO_QUANTITY(boost::units::si::moment_of_inertia) RotInertia
Rotational inertia quantity.
Definition: Units.hpp:274
playrho::d2::Joint
A joint-like constraint on one or more bodies.
Definition: Joint.hpp:144
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::d2::FrictionJointConf
Friction joint definition.
Definition: FrictionJointConf.hpp:49
playrho::d2::FrictionJointConf::rB
Length2 rB
Relative B.
Definition: FrictionJointConf.hpp:94
playrho::d2::Step
StepStats Step(WorldImpl &world, const StepConf &conf)
Steps the given world the specified amount.
Definition: WorldImplMisc.cpp:85
playrho::d2::GetFrictionJointConf
FrictionJointConf GetFrictionJointConf(const Joint &joint) noexcept
Gets the definition data for the given joint.
Definition: FrictionJointConf.cpp:64
playrho::d2::DiskShapeConf
Disk shape configuration.
Definition: DiskShapeConf.hpp:42