JSim 2026.06.01-p(1)
Loading...
Searching...
No Matches
joint_math.hpp
Go to the documentation of this file.
1// Copyright (c) JSim contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the LGPLv3 license file in the root directory of this project.
4
5#pragma once
6
7#include <algorithm>
8#include <cmath>
9
11
12namespace frcsim::detail {
13
14constexpr double kJointEpsilon = 1e-9;
15inline const double kPi = std::acos(-1.0);
16
25inline Vector3 worldAnchor(const RigidBody* body,
26 const Vector3& local_anchor) {
27 return body->position() + body->orientation().rotate(local_anchor);
28}
29
37inline double clampValue(double value, double min_value, double max_value) {
38 return std::max(min_value, std::min(value, max_value));
39}
40
55inline void applyPositionCorrection(RigidBody* body_a, RigidBody* body_b,
56 const Vector3& error, double gain) {
57 const double inv_a =
58 body_a->flags().is_kinematic ? 0.0 : body_a->inverseMass();
59 const double inv_b =
60 body_b->flags().is_kinematic ? 0.0 : body_b->inverseMass();
61 const double total_inv = inv_a + inv_b;
62 if (total_inv <= kJointEpsilon)
63 return;
64
65 const Vector3 correction_a = error * (gain * (inv_a / total_inv));
66 const Vector3 correction_b = error * (gain * (inv_b / total_inv));
67
68 if (!body_a->flags().is_kinematic) {
69 body_a->setPosition(body_a->position() + correction_a);
70 }
71 if (!body_b->flags().is_kinematic) {
72 body_b->setPosition(body_b->position() - correction_b);
73 }
74}
75
89inline void applyVelocityCorrection(RigidBody* body_a, RigidBody* body_b,
90 const Vector3& relative_velocity,
91 double gain) {
92 const double inv_a =
93 body_a->flags().is_kinematic ? 0.0 : body_a->inverseMass();
94 const double inv_b =
95 body_b->flags().is_kinematic ? 0.0 : body_b->inverseMass();
96 const double total_inv = inv_a + inv_b;
97 if (total_inv <= kJointEpsilon)
98 return;
99
100 const Vector3 correction_a = relative_velocity * (gain * (inv_a / total_inv));
101 const Vector3 correction_b = relative_velocity * (gain * (inv_b / total_inv));
102
103 if (!body_a->flags().is_kinematic) {
104 body_a->setLinearVelocity(body_a->linearVelocity() + correction_a);
105 }
106 if (!body_b->flags().is_kinematic) {
107 body_b->setLinearVelocity(body_b->linearVelocity() - correction_b);
108 }
109}
110
121 const Vector3& local_axis,
122 const Vector3& fallback_axis) {
123 Vector3 axis_world = body->orientation().rotate(local_axis).normalized();
124 return axis_world.isZero() ? fallback_axis : axis_world;
125}
126
152inline double signedTwistAngleRad(const Quaternion& qa, const Quaternion& qb,
153 const Vector3& axis_world) {
154 Quaternion q_rel = qb * qa.inverse();
155 q_rel.normalizeIfNeeded();
156
157 Vector3 axis_err;
158 double angle = 0.0;
159 q_rel.toAxisAngle(axis_err, angle);
160 if (angle > kPi) {
161 angle = 2.0 * kPi - angle;
162 axis_err = -axis_err;
163 }
164 return angle * axis_err.dot(axis_world.normalized());
165}
166
167} // namespace frcsim::detail
Simulated rigid body with translational/angular dynamics and optional aero metadata.
Definition rigid_body.hpp:44
BodyFlags & flags()
Mutable access to runtime body flags.
Definition rigid_body.hpp:244
const Vector3 & linearVelocity() const
Returns world linear velocity in meters per second.
Definition rigid_body.hpp:163
void setLinearVelocity(const Vector3 &velocity_mps)
Sets world linear velocity in meters per second.
Definition rigid_body.hpp:168
const Quaternion & orientation() const
Returns body orientation as a unit quaternion.
Definition rigid_body.hpp:153
double inverseMass() const
Returns inverse mass in 1/kg.
Definition rigid_body.hpp:108
void setPosition(const Vector3 &position_m)
Sets world-space position in meters.
Definition rigid_body.hpp:124
const Vector3 & position() const
Returns world position in meters.
Definition rigid_body.hpp:119
Definition joint_math.hpp:12
constexpr double kJointEpsilon
Definition joint_math.hpp:14
void applyVelocityCorrection(RigidBody *body_a, RigidBody *body_b, const Vector3 &relative_velocity, double gain)
Applies a velocity-space correction split across two bodies by mass.
Definition joint_math.hpp:89
void applyPositionCorrection(RigidBody *body_a, RigidBody *body_b, const Vector3 &error, double gain)
Applies a positional correction split across two bodies by mass.
Definition joint_math.hpp:55
double signedTwistAngleRad(const Quaternion &qa, const Quaternion &qb, const Vector3 &axis_world)
Computes the signed twist between two orientations about an axis.
Definition joint_math.hpp:152
Vector3 worldAxisOrFallback(const RigidBody *body, const Vector3 &local_axis, const Vector3 &fallback_axis)
Rotates a local axis into world space and falls back if needed.
Definition joint_math.hpp:120
const double kPi
Definition joint_math.hpp:15
Vector3 worldAnchor(const RigidBody *body, const Vector3 &local_anchor)
Converts a body-local anchor point into world space.
Definition joint_math.hpp:25
double clampValue(double value, double min_value, double max_value)
Clamps a scalar into a closed range.
Definition joint_math.hpp:37
bool is_kinematic
Definition body_flags.hpp:26
Unit-quaternion rotation representation and rotation algebra helpers.
Definition quaternion.hpp:25
void toAxisAngle(Vector3 &axis, double &angleRad) const noexcept
Definition quaternion.hpp:85
Quaternion inverse() const noexcept
Definition quaternion.hpp:150
void normalizeIfNeeded(double eps=1e-12) noexcept
Definition quaternion.hpp:62
Vector3 rotate(const Vector3 &v) const noexcept
Definition quaternion.hpp:179
3D vector utility used throughout JSim physics.
Definition vector.hpp:22
Vector3 normalized() const noexcept
Returns the normalized direction vector.
Definition vector.hpp:119
constexpr double dot(const Vector3 &o) const noexcept
Returns dot product with o.
Definition vector.hpp:168
constexpr bool isZero(double eps=1e-12) const noexcept
Checks whether the vector is near zero magnitude.
Definition vector.hpp:128