JSim 2026.06.01-p(1)
Loading...
Searching...
No Matches
double_differential.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#include <limits>
10#include <utility>
11
12namespace frcsim {
13
21 public:
23 struct Limits {
24 double min_yaw_rad{-std::numeric_limits<double>::infinity()};
25 double max_yaw_rad{std::numeric_limits<double>::infinity()};
26 double min_pitch_rad{-std::numeric_limits<double>::infinity()};
27 double max_pitch_rad{std::numeric_limits<double>::infinity()};
28 };
29
31 struct Config {
32 // Mapping from motor shaft position [a, b] to joint coordinates [yaw,
33 // pitch]. yaw = m00 * a + m01 * b pitch = m10 * a + m11 * b
34 double m00{0.5};
35 double m01{0.5};
36 double m10{0.5};
37 double m11{-0.5};
38
39 // Optional multiplicative scale factors after matrix mapping.
40 double yaw_scale{1.0};
41 double pitch_scale{1.0};
42
44 double singularity_epsilon{1e-9};
45 };
46
48 struct MotorState {
53 };
54
56 struct JointState {
57 double yaw_rad{0.0};
58 double pitch_rad{0.0};
59 double yaw_velocity_radps{0.0};
61 };
62
68 bool valid{true};
69 };
70
72
74 : config_(config) {}
75
78 const Config& config() const { return config_; }
81 void setConfig(const Config& config) { config_ = config; }
82
88 JointState forward(const MotorState& motor_state) const {
89 JointState out{};
90 out.yaw_rad =
91 config_.yaw_scale * (config_.m00 * motor_state.motor_a_position_rad +
92 config_.m01 * motor_state.motor_b_position_rad);
93 out.pitch_rad =
94 config_.pitch_scale * (config_.m10 * motor_state.motor_a_position_rad +
95 config_.m11 * motor_state.motor_b_position_rad);
96
98 config_.yaw_scale * (config_.m00 * motor_state.motor_a_velocity_radps +
99 config_.m01 * motor_state.motor_b_velocity_radps);
101 config_.pitch_scale *
102 (config_.m10 * motor_state.motor_a_velocity_radps +
103 config_.m11 * motor_state.motor_b_velocity_radps);
104
105 applyLimits(out);
106 return out;
107 }
108
114 InverseResult inverse(const JointState& desired_joint_state) const {
115 InverseResult result{};
116
117 const double a11 = config_.yaw_scale * config_.m00;
118 const double a12 = config_.yaw_scale * config_.m01;
119 const double a21 = config_.pitch_scale * config_.m10;
120 const double a22 = config_.pitch_scale * config_.m11;
121
122 const double det = a11 * a22 - a12 * a21;
123 if (std::abs(det) <= config_.singularity_epsilon) {
124 result.valid = false;
125 return result;
126 }
127
128 const double inv11 = a22 / det;
129 const double inv12 = -a12 / det;
130 const double inv21 = -a21 / det;
131 const double inv22 = a11 / det;
132
133 const JointState clamped = clampedToLimits(desired_joint_state);
134
136 inv11 * clamped.yaw_rad + inv12 * clamped.pitch_rad;
138 inv21 * clamped.yaw_rad + inv22 * clamped.pitch_rad;
139
141 inv11 * clamped.yaw_velocity_radps +
142 inv12 * clamped.pitch_velocity_radps;
144 inv21 * clamped.yaw_velocity_radps +
145 inv22 * clamped.pitch_velocity_radps;
146
147 return result;
148 }
149
156 JointState out = state;
157 applyLimits(out);
158 return out;
159 }
160
161 private:
162 void applyLimits(JointState& state) const {
163 state.yaw_rad = std::clamp(state.yaw_rad, config_.limits.min_yaw_rad,
164 config_.limits.max_yaw_rad);
165 state.pitch_rad = std::clamp(state.pitch_rad, config_.limits.min_pitch_rad,
166 config_.limits.max_pitch_rad);
167 }
168
169 Config config_{};
170};
171
172} // namespace frcsim
DoubleDifferentialMechanism(const Config &config)
Definition double_differential.hpp:73
JointState forward(const MotorState &motor_state) const
Computes joint state from motor state via forward mapping.
Definition double_differential.hpp:88
InverseResult inverse(const JointState &desired_joint_state) const
Solves inverse mapping from desired joint state to motor state.
Definition double_differential.hpp:114
JointState clampedToLimits(const JointState &state) const
Returns a copy of state clamped to configured joint limits.
Definition double_differential.hpp:155
const Config & config() const
Returns current mapping configuration.
Definition double_differential.hpp:78
void setConfig(const Config &config)
Replaces mapping configuration.
Definition double_differential.hpp:81
Definition vector.hpp:13
Mapping coefficients and inversion thresholds.
Definition double_differential.hpp:31
double m11
Definition double_differential.hpp:37
double m01
Definition double_differential.hpp:35
double m10
Definition double_differential.hpp:36
double m00
Definition double_differential.hpp:34
Limits limits
Definition double_differential.hpp:43
double yaw_scale
Definition double_differential.hpp:40
double singularity_epsilon
Definition double_differential.hpp:44
double pitch_scale
Definition double_differential.hpp:41
Result from inverse kinematics solve.
Definition double_differential.hpp:64
bool valid
Definition double_differential.hpp:68
MotorState motor_state
Definition double_differential.hpp:66
Output state for mechanism yaw/pitch joints.
Definition double_differential.hpp:56
double yaw_rad
Definition double_differential.hpp:57
double pitch_velocity_radps
Definition double_differential.hpp:60
double yaw_velocity_radps
Definition double_differential.hpp:59
double pitch_rad
Definition double_differential.hpp:58
Optional soft limits applied to joint coordinates.
Definition double_differential.hpp:23
double max_pitch_rad
Definition double_differential.hpp:27
double min_yaw_rad
Definition double_differential.hpp:24
double min_pitch_rad
Definition double_differential.hpp:26
double max_yaw_rad
Definition double_differential.hpp:25
Input state for the two drive motors.
Definition double_differential.hpp:48
double motor_b_velocity_radps
Definition double_differential.hpp:52
double motor_a_velocity_radps
Definition double_differential.hpp:51
double motor_a_position_rad
Definition double_differential.hpp:49
double motor_b_position_rad
Definition double_differential.hpp:50