1use crate::{
9 continuous::JointModelContinuous, fixed::JointModelFixed, joint_data::JointDataWrapper,
10 prismatic::JointModelPrismatic, revolute::JointModelRevolute,
11};
12use dynamics_spatial::{configuration::Configuration, force::SpatialForce, motion::SpatialMotion};
13use rand::rngs::ThreadRng;
14
15#[derive(Clone, Debug)]
16enum JointModelImpl {
22 Continuous(JointModelContinuous),
23 Prismatic(JointModelPrismatic),
24 Revolute(JointModelRevolute),
25 Fixed(JointModelFixed),
26}
27
28#[derive(Clone, Debug)]
29pub struct JointWrapper {
35 inner: JointModelImpl,
36}
37
38impl JointWrapper {
39 pub fn continuous(joint: JointModelContinuous) -> Self {
41 JointWrapper {
42 inner: JointModelImpl::Continuous(joint),
43 }
44 }
45
46 pub fn prismatic(joint: JointModelPrismatic) -> Self {
48 JointWrapper {
49 inner: JointModelImpl::Prismatic(joint),
50 }
51 }
52
53 pub fn revolute(joint: JointModelRevolute) -> Self {
55 JointWrapper {
56 inner: JointModelImpl::Revolute(joint),
57 }
58 }
59
60 pub fn fixed(joint: JointModelFixed) -> Self {
62 JointWrapper {
63 inner: JointModelImpl::Fixed(joint),
64 }
65 }
66}
67
68impl JointModel for JointWrapper {
70 fn get_joint_type(&self) -> JointType {
71 match &self.inner {
72 JointModelImpl::Continuous(joint) => joint.get_joint_type(),
73 JointModelImpl::Prismatic(joint) => joint.get_joint_type(),
74 JointModelImpl::Revolute(joint) => joint.get_joint_type(),
75 JointModelImpl::Fixed(joint) => joint.get_joint_type(),
76 }
77 }
78
79 fn nq(&self) -> usize {
80 match &self.inner {
81 JointModelImpl::Continuous(joint) => joint.nq(),
82 JointModelImpl::Prismatic(joint) => joint.nq(),
83 JointModelImpl::Revolute(joint) => joint.nq(),
84 JointModelImpl::Fixed(joint) => joint.nq(),
85 }
86 }
87
88 fn nv(&self) -> usize {
89 match &self.inner {
90 JointModelImpl::Continuous(joint) => joint.nv(),
91 JointModelImpl::Prismatic(joint) => joint.nv(),
92 JointModelImpl::Revolute(joint) => joint.nv(),
93 JointModelImpl::Fixed(joint) => joint.nv(),
94 }
95 }
96
97 fn neutral(&self) -> Configuration {
98 match &self.inner {
99 JointModelImpl::Continuous(joint) => joint.neutral(),
100 JointModelImpl::Prismatic(joint) => joint.neutral(),
101 JointModelImpl::Revolute(joint) => joint.neutral(),
102 JointModelImpl::Fixed(joint) => joint.neutral(),
103 }
104 }
105
106 fn create_joint_data(&self) -> JointDataWrapper {
107 match &self.inner {
108 JointModelImpl::Continuous(joint) => joint.create_joint_data(),
109 JointModelImpl::Prismatic(joint) => joint.create_joint_data(),
110 JointModelImpl::Revolute(joint) => joint.create_joint_data(),
111 JointModelImpl::Fixed(joint) => joint.create_joint_data(),
112 }
113 }
114
115 fn random_configuration(&self, rng: &mut ThreadRng) -> Configuration {
116 match &self.inner {
117 JointModelImpl::Continuous(joint) => joint.random_configuration(rng),
118 JointModelImpl::Prismatic(joint) => joint.random_configuration(rng),
119 JointModelImpl::Revolute(joint) => joint.random_configuration(rng),
120 JointModelImpl::Fixed(joint) => joint.random_configuration(rng),
121 }
122 }
123
124 fn get_axis(&self) -> Vec<SpatialMotion> {
125 match &self.inner {
126 JointModelImpl::Continuous(joint) => joint.get_axis(),
127 JointModelImpl::Prismatic(joint) => joint.get_axis(),
128 JointModelImpl::Revolute(joint) => joint.get_axis(),
129 JointModelImpl::Fixed(joint) => joint.get_axis(),
130 }
131 }
132
133 fn subspace(&self, v: &Configuration) -> SpatialMotion {
134 match &self.inner {
135 JointModelImpl::Continuous(joint) => joint.subspace(v),
136 JointModelImpl::Prismatic(joint) => joint.subspace(v),
137 JointModelImpl::Revolute(joint) => joint.subspace(v),
138 JointModelImpl::Fixed(joint) => joint.subspace(v),
139 }
140 }
141
142 fn subspace_dual(&self, f: &SpatialForce) -> Configuration {
143 match &self.inner {
144 JointModelImpl::Continuous(joint) => joint.subspace_dual(f),
145 JointModelImpl::Prismatic(joint) => joint.subspace_dual(f),
146 JointModelImpl::Revolute(joint) => joint.subspace_dual(f),
147 JointModelImpl::Fixed(joint) => joint.subspace_dual(f),
148 }
149 }
150
151 fn bias(&self) -> SpatialMotion {
152 match &self.inner {
153 JointModelImpl::Continuous(joint) => joint.bias(),
154 JointModelImpl::Prismatic(joint) => joint.bias(),
155 JointModelImpl::Revolute(joint) => joint.bias(),
156 JointModelImpl::Fixed(joint) => joint.bias(),
157 }
158 }
159}
160
161pub trait JointModel {
166 fn get_joint_type(&self) -> JointType;
168
169 fn nq(&self) -> usize;
171
172 fn nv(&self) -> usize;
174
175 fn neutral(&self) -> Configuration;
177
178 fn create_joint_data(&self) -> JointDataWrapper;
180
181 fn get_axis(&self) -> Vec<SpatialMotion>; fn random_configuration(&self, rng: &mut ThreadRng) -> Configuration;
186
187 fn subspace(&self, v: &Configuration) -> SpatialMotion;
189
190 fn subspace_dual(&self, f: &SpatialForce) -> Configuration;
192
193 fn bias(&self) -> SpatialMotion;
195}
196
197#[cfg_attr(feature = "python", pyo3::prelude::pyclass)]
199#[derive(Clone, Copy, Debug, PartialEq, Eq)]
200pub enum JointType {
201 Continuous,
202 Fixed,
203 Prismatic,
204 Revolute,
205}
206
207pub type JointBias = SpatialMotion;