pinocchio  3.9.0
A fast and flexible implementation of Rigid Body Dynamics algorithms and their analytical derivatives
Loading...
Searching...
No Matches
graph-visitor.hpp
1//
2// Copyright (c) 2025 INRIA
3//
4
5#ifndef __pinocchio_parsers_graph_graph_visitor_hpp__
6#define __pinocchio_parsers_graph_graph_visitor_hpp__
7
8#include "pinocchio/macros.hpp"
9
10#include "pinocchio/parsers/graph/fwd.hpp"
11
12#include "pinocchio/multibody/joint/joint-collection.hpp"
13
14#include "pinocchio/parsers/graph/model-graph.hpp"
15#include "pinocchio/parsers/graph/joints.hpp"
16
17#include <Eigen/Core>
18
19#include <boost/graph/depth_first_search.hpp>
20
21#include <boost/variant/static_visitor.hpp>
22#include <boost/variant/apply_visitor.hpp>
23
24#include <utility>
25#include <stdexcept>
26
27namespace pinocchio
28{
29 namespace graph
30 {
31 namespace internal
32 {
33 template<typename Derived>
34 struct UpdateJointGraphPoseVisitorBase : public boost::static_visitor<SE3>
35 {
36 typedef Eigen::Ref<const Eigen::VectorXd> QRefType;
37
38 QRefType q_ref;
39
40 UpdateJointGraphPoseVisitorBase(const QRefType & q_ref)
41 : q_ref(q_ref)
42 {
43 }
44
45 template<typename JointModel>
46 SE3 joint_calc(JointModel jmodel) const
47 {
48 return derived().joint_calc_impl(jmodel);
49 }
50
51 template<typename JointModel>
52 SE3 joint_calc_default(JointModel jmodel) const
53 {
54 if (JointModel::NQ != q_ref.rows())
55 {
56 PINOCCHIO_THROW_PRETTY(
57 std::invalid_argument, "Graph - q_ref mismatch joint configuration space");
58 }
59 jmodel.setIndexes(1, 0, 0);
60 auto jdata = jmodel.createData();
61 jmodel.calc(jdata, q_ref);
62
63 return jdata.M;
64 }
65
66 const Derived & derived() const
67 {
68 return *static_cast<const Derived *>(this);
69 }
70
71 SE3 operator()(const JointFixed & joint) const
72 {
73 return joint.joint_offset;
74 }
75
76 SE3 operator()(const JointRevolute & joint) const
77 {
78 return joint_calc(JointModelRevoluteUnaligned(joint.axis));
79 }
80
81 SE3 operator()(const JointPrismatic & joint) const
82 {
83 return joint_calc(JointModelPrismaticUnaligned(joint.axis));
84 }
85
86 SE3 operator()(const JointRevoluteUnbounded & joint) const
87 {
88 return joint_calc(JointModelRevoluteUnboundedUnaligned(joint.axis));
89 }
90
91 SE3 operator()(const JointHelical & joint) const
92 {
93 return joint_calc(JointModelHelicalUnaligned(joint.axis, joint.pitch));
94 }
95
96 SE3 operator()(const JointUniversal & joint) const
97 {
98 return joint_calc(JointModelUniversal(joint.axis1, joint.axis2));
99 }
100
101 SE3 operator()(const JointFreeFlyer &) const
102 {
103 return joint_calc(JointModelFreeFlyer());
104 }
105
106 SE3 operator()(const JointSpherical &) const
107 {
108 return joint_calc(JointModelSpherical());
109 }
110
111 SE3 operator()(const JointSphericalZYX &) const
112 {
113 return joint_calc(JointModelSphericalZYX());
114 }
115
116 SE3 operator()(const JointEllipsoid &) const
117 {
118 return joint_calc(JointModelEllipsoid());
119 }
120
121 SE3 operator()(const JointPlanar &) const
122 {
123 return joint_calc(JointModelPlanar());
124 }
125
126 SE3 operator()(const JointTranslation &) const
127 {
128 return joint_calc(JointModelTranslation());
129 }
130
131 SE3 operator()(const JointMimic &) const
132 {
133 PINOCCHIO_THROW_PRETTY(
134 std::invalid_argument,
135 "Graph - Joint Mimic cannot have a q_ref. Please use the joint offset directly.");
136 }
137 };
138
141 struct UpdateJointGraphPoseVisitor
142 : public UpdateJointGraphPoseVisitorBase<UpdateJointGraphPoseVisitor>
143 {
144 typedef UpdateJointGraphPoseVisitorBase<UpdateJointGraphPoseVisitor> Base;
145
146 using Base::Base;
147
148 template<typename JointModel>
149 SE3 joint_calc_impl(JointModel jmodel) const
150 {
151 return Base::joint_calc_default(jmodel);
152 }
153
154 using Base::operator();
155 SE3 operator()(JointComposite & joint) const
156 {
157 int index = 0;
158 for (size_t i = 0; i < joint.joints.size(); i++)
159 {
160 int nq_curr =
161 boost::apply_visitor([](const auto & j_) { return j_.nq; }, joint.joints[i]);
162 auto u_temp = UpdateJointGraphPoseVisitor(q_ref.segment(index, nq_curr));
163 SE3 pose_temp = boost::apply_visitor(u_temp, joint.joints[i]);
164 joint.jointsPlacements[i] = joint.jointsPlacements[i] * pose_temp;
165 index += nq_curr;
166 }
167 return SE3::Identity();
168 }
169 };
170
173 struct UpdateJointGraphReversePoseVisitor
174 : public UpdateJointGraphPoseVisitorBase<UpdateJointGraphReversePoseVisitor>
175 {
176 typedef UpdateJointGraphPoseVisitorBase<UpdateJointGraphReversePoseVisitor> Base;
177
178 using Base::Base;
179
180 template<typename JointModel>
181 SE3 joint_calc_impl(JointModel jmodel) const
182 {
183 return Base::joint_calc_default(jmodel).inverse();
184 }
185
186 using Base::operator();
187 SE3 operator()(const JointUniversal & joint) const
188 {
189 return Base::joint_calc_default(JointModelUniversal(-joint.axis2, -joint.axis1))
190 .inverse();
191 }
192
193 SE3 operator()(JointComposite & joint) const
194 {
195 // Here, JointComposite is already reversed.
196 // If we have the following forward composite joint:
197 // [jointsPlacements[0] jointPlacements[1]]
198 // jp0---qref0-----------j0---jp1---qref1----------j1
199 // With jpN is the original jointPlacements[N] and qref[N] the static transform computed
200 // with qref.
201 // We should have the following reversed one:
202 // [jointsPlacements[0] jointPlacements[1]]
203 // I-----------j1---qref^{-1}---xc1^{-1}------j0
204 // And qref0^{-1} should be returned to forward this transformation in
205 // joint_to_target.
206 auto index = q_ref.rows();
207 for (int i = 0; i < static_cast<int>(joint.joints.size()) - 1; i++)
208 {
209 int nq_curr = boost::apply_visitor(
210 [](const auto & j_) { return j_.nq; }, joint.joints[static_cast<size_t>(i)]);
211 index -= nq_curr;
212 auto u_temp = UpdateJointGraphReversePoseVisitor(q_ref.segment(index, nq_curr));
213 SE3 pose_temp = boost::apply_visitor(u_temp, joint.joints[static_cast<size_t>(i)]);
214 joint.jointsPlacements[static_cast<size_t>(i + 1)] =
215 pose_temp * joint.jointsPlacements[static_cast<size_t>(i + 1)];
216 }
217 int nq_curr =
218 boost::apply_visitor([](const auto & j_) { return j_.nq; }, joint.joints.back());
219 index -= nq_curr;
220 auto u_temp = UpdateJointGraphReversePoseVisitor(q_ref.segment(index, nq_curr));
221 SE3 pose_temp = boost::apply_visitor(u_temp, joint.joints.back());
222 return pose_temp;
223 }
224 };
225 } // namespace internal
226 } // namespace graph
227} // namespace pinocchio
228
229#endif // ifndef __pinocchio_parsers_graph_graph_visitor_hpp__
Main pinocchio namespace.
Definition treeview.dox:11
SE3Tpl inverse() const
aXb = bXa.inverse()
Definition se3-tpl.hpp:149