GCC Code Coverage Report


Directory: ./
File: src/tasks/task-two-frames-equality.cpp
Date: 2024-08-26 20:29:39
Exec Total Coverage
Lines: 0 98 0.0%
Branches: 0 284 0.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2023 MIPT
3 //
4 // This file is part of tsid
5 // tsid is free software: you can redistribute it
6 // and/or modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation, either version
8 // 3 of the License, or (at your option) any later version.
9 // tsid is distributed in the hope that it will be
10 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
11 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Lesser Public License for more details. You should have
13 // received a copy of the GNU Lesser General Public License along with
14 // tsid If not, see
15 // <http://www.gnu.org/licenses/>.
16 //
17
18 #include "tsid/math/utils.hpp"
19 #include "tsid/tasks/task-two-frames-equality.hpp"
20 #include "tsid/robots/robot-wrapper.hpp"
21
22 namespace tsid {
23 namespace tasks {
24 using namespace std;
25 using namespace math;
26 using namespace trajectories;
27 using namespace pinocchio;
28
29 TaskTwoFramesEquality::TaskTwoFramesEquality(const std::string& name,
30 RobotWrapper& robot,
31 const std::string& frameName1,
32 const std::string& frameName2)
33 : TaskMotion(name, robot),
34 m_frame_name1(frameName1),
35 m_frame_name2(frameName2),
36 m_constraint(name, 6, robot.nv()) {
37 assert(m_robot.model().existFrame(frameName1));
38 assert(m_robot.model().existFrame(frameName2));
39 m_frame_id1 = m_robot.model().getFrameId(frameName1);
40 m_frame_id2 = m_robot.model().getFrameId(frameName2);
41
42 m_v_ref.setZero();
43 m_a_ref.setZero();
44 m_wMl1.setIdentity();
45 m_wMl2.setIdentity();
46 m_p_error_vec.setZero(6);
47 m_v_error_vec.setZero(6);
48 m_p.resize(12);
49 m_v.resize(6);
50 m_p_ref.resize(12);
51 m_v_ref_vec.resize(6);
52 m_Kp.setZero(6);
53 m_Kd.setZero(6);
54 m_a_des.setZero(6);
55 m_J1.setZero(6, robot.nv());
56 m_J2.setZero(6, robot.nv());
57 m_J1_rotated.setZero(6, robot.nv());
58 m_J2_rotated.setZero(6, robot.nv());
59
60 m_mask.resize(6);
61 m_mask.fill(1.);
62 setMask(m_mask);
63 }
64
65 void TaskTwoFramesEquality::setMask(math::ConstRefVector mask) {
66 TaskMotion::setMask(mask);
67 int n = dim();
68 m_constraint.resize(n, (unsigned int)m_J1.cols());
69 m_p_error_masked_vec.resize(n);
70 m_v_error_masked_vec.resize(n);
71 m_drift_masked.resize(n);
72 m_a_des_masked.resize(n);
73 }
74
75 int TaskTwoFramesEquality::dim() const { return (int)m_mask.sum(); }
76
77 const Vector& TaskTwoFramesEquality::Kp() const { return m_Kp; }
78
79 const Vector& TaskTwoFramesEquality::Kd() const { return m_Kd; }
80
81 void TaskTwoFramesEquality::Kp(ConstRefVector Kp) {
82 assert(Kp.size() == 6);
83 m_Kp = Kp;
84 }
85
86 void TaskTwoFramesEquality::Kd(ConstRefVector Kd) {
87 assert(Kd.size() == 6);
88 m_Kd = Kd;
89 }
90
91 const Vector& TaskTwoFramesEquality::position_error() const {
92 return m_p_error_masked_vec;
93 }
94
95 const Vector& TaskTwoFramesEquality::velocity_error() const {
96 return m_v_error_masked_vec;
97 }
98
99 const Vector& TaskTwoFramesEquality::getDesiredAcceleration() const {
100 return m_a_des_masked;
101 }
102
103 Vector TaskTwoFramesEquality::getAcceleration(ConstRefVector dv) const {
104 return m_constraint.matrix() * dv + m_drift_masked;
105 }
106
107 Index TaskTwoFramesEquality::frame_id1() const { return m_frame_id1; }
108
109 Index TaskTwoFramesEquality::frame_id2() const { return m_frame_id2; }
110
111 const ConstraintBase& TaskTwoFramesEquality::getConstraint() const {
112 return m_constraint;
113 }
114
115 const ConstraintBase& TaskTwoFramesEquality::compute(const double,
116 ConstRefVector,
117 ConstRefVector,
118 Data& data) {
119 // Calculating task with formulation: [J1 - J2 0 0] dv = [-J1dot*v +
120 // J2dot*v]
121
122 SE3 oMi1, oMi2;
123 Motion v_frame1, v_frame2;
124 Motion m_drift1, m_drift2;
125 m_robot.framePosition(data, m_frame_id1, oMi1);
126 m_robot.framePosition(data, m_frame_id2, oMi2);
127 m_robot.frameVelocity(data, m_frame_id1, v_frame1);
128 m_robot.frameVelocity(data, m_frame_id2, v_frame2);
129 m_robot.frameClassicAcceleration(data, m_frame_id1, m_drift1);
130 m_robot.frameClassicAcceleration(data, m_frame_id2, m_drift2);
131
132 // Transformations from local to local-world-aligned frame (thus only rotation
133 // is used)
134 m_wMl1.rotation(oMi1.rotation());
135 m_wMl2.rotation(oMi2.rotation());
136
137 m_robot.frameJacobianLocal(data, m_frame_id1, m_J1);
138 m_robot.frameJacobianLocal(data, m_frame_id2, m_J2);
139
140 // Doing all calculations in local-world-aligned frame
141 errorInSE3(oMi1, oMi2, m_p_error); // pos err in local oMi1 frame
142 m_p_error_vec = m_wMl1.toActionMatrix() *
143 m_p_error.toVector(); // pos err in local-world-aligned frame
144
145 m_v_error = m_wMl2.act(v_frame2) -
146 m_wMl1.act(v_frame1); // vel err in local-world-aligned frame
147
148 // desired acc in local-world-aligned frame
149 m_a_des = m_Kp.cwiseProduct(m_p_error_vec) +
150 m_Kd.cwiseProduct(m_v_error.toVector());
151
152 m_v_error_vec = m_v_error.toVector();
153
154 m_drift = (m_wMl1.act(m_drift1) - m_wMl2.act(m_drift2));
155
156 m_J1_rotated.noalias() =
157 m_wMl1.toActionMatrix() *
158 m_J1; // Use an explicit temporary m_J_rotated to avoid allocations
159 m_J1 = m_J1_rotated;
160
161 m_J2_rotated.noalias() = m_wMl2.toActionMatrix() * m_J2;
162 m_J2 = m_J2_rotated;
163
164 int idx = 0;
165 for (int i = 0; i < 6; i++) {
166 if (m_mask(i) != 1.) continue;
167
168 m_constraint.matrix().row(idx) = m_J1.row(i) - m_J2.row(i);
169 m_constraint.vector().row(idx) = (m_a_des - m_drift.toVector()).row(i);
170 m_a_des_masked(idx) = m_a_des(i);
171 m_drift_masked(idx) = m_drift.toVector()(i);
172 m_p_error_masked_vec(idx) = m_p_error_vec(i);
173 m_v_error_masked_vec(idx) = m_v_error_vec(i);
174
175 idx += 1;
176 }
177
178 return m_constraint;
179 }
180 } // namespace tasks
181 } // namespace tsid
182