rby1-sdk
Loading...
Searching...
No Matches
trapezoidal_motion_generator.h
1#pragma once
2
3#include <Eigen/Core>
4#include <cstdlib>
5#include <iostream>
6
7#include "rby1-sdk/export.h"
8
9namespace rb {
10
11template <int N>
13 public:
14 struct Input {
15 Eigen::Vector<double, N> current_position;
16 Eigen::Vector<double, N> current_velocity;
17
18 Eigen::Vector<double, N> target_position;
19 Eigen::Vector<double, N> velocity_limit;
20 Eigen::Vector<double, N> acceleration_limit;
21 double minimum_time;
22 };
23
24 struct Output {
25 Eigen::Vector<double, N> position;
26 Eigen::Vector<double, N> velocity;
27 Eigen::Vector<double, N> acceleration;
28 };
29
30 struct Coeff {
31 double start_t;
32 double end_t;
33 double init_p;
34 double init_v;
35 double a;
36 };
37
38 explicit TrapezoidalMotionGenerator(unsigned int max_iter = 30) : max_iter_(max_iter) {}
39
40 void Update(const Input& input) {
41 n_joints_ = input.target_position.size();
42
43 if (input.acceleration_limit.size() != n_joints_ || input.velocity_limit.size() != n_joints_ ||
44 input.current_position.size() != n_joints_ || input.current_velocity.size() != n_joints_) {
45 throw std::invalid_argument("Optimal control input argument size inconsistent");
46 }
47
48 last_input_ = input;
49
50 Eigen::Vector<double, N> l_v, r_v, m_v;
51 l_v.resize(n_joints_);
52 r_v.resize(n_joints_);
53 m_v.resize(n_joints_);
54 l_v.setZero();
55 r_v = input.velocity_limit;
56 m_v = input.velocity_limit;
57 Eigen::Array<Coeff, N, 4> spline_coeffs;
58 Eigen::Array<Coeff, N, 4> ans_spline_coeffs;
59 spline_coeffs.resize(n_joints_, 4);
60 ans_spline_coeffs.resize(n_joints_, 4);
61
62 Eigen::Vector<bool, N> check;
63 check.resize(n_joints_);
64 check.fill(false);
65
66 double max = input.minimum_time;
67
68 bool first = true;
69 for (int it = 0; it < max_iter_; it++) {
70 for (int i = 0; i < n_joints_; i++) {
71 if (check[i])
72 continue;
73
74 double cp = input.current_position[i];
75 double cv = input.current_velocity[i];
76
77 double tp = input.target_position[i];
78 double v_max = m_v[i];
79 double a_max = input.acceleration_limit[i];
80
81 bool dir = tp > cp;
82
83 double t = 0;
84 if (dir) {
85 if (cv > 0) {
86 if (cp + 0.5 * cv * cv / a_max < tp) {
87 if (cv < v_max) {
88 Coeff coeff; // TODO
89 coeff.start_t = 0;
90 coeff.end_t = 0;
91 coeff.init_p = cp;
92 coeff.init_v = cv;
93 coeff.a = -a_max;
94 spline_coeffs(i, 0) = coeff;
95 t = -cv / a_max;
96 cp -= 0.5 * cv * cv / a_max;
97 cv = 0;
98 } else {
99 spline_coeffs(i, 0) = {0, (cv - v_max) / a_max, cp, cv, -a_max};
100 t = (cv - v_max) / a_max - v_max / a_max;
101 cp += 0.5 * (cv + v_max) * (cv - v_max) / a_max - 0.5 * v_max * v_max / a_max;
102 cv = 0;
103 }
104 } else {
105 spline_coeffs(i, 0) = {0, cv / a_max, cp, cv, -a_max};
106 t = cv / a_max;
107 cp += 0.5 * cv * cv / a_max;
108 cv = 0;
109 dir = false;
110 }
111 } else {
112 spline_coeffs(i, 0) = {0, -cv / a_max, cp, cv, a_max};
113 t = -cv / a_max;
114 cp -= 0.5 * cv * cv / a_max;
115 cv = 0;
116 }
117 } else {
118 if (cv > 0) {
119 spline_coeffs(i, 0) = {0, cv / a_max, cp, cv, -a_max};
120 t = cv / a_max;
121 cp += 0.5 * cv * cv / a_max;
122 cv = 0;
123 } else {
124 if (cp - 0.5 * cv * cv / a_max > tp) {
125 if (cv > -v_max) {
126 spline_coeffs(i, 0) = {0, 0, cp, cv, a_max};
127 t = cv / a_max;
128 cp += 0.5 * cv * cv / a_max;
129 cv = 0;
130 } else {
131 spline_coeffs(i, 0) = {0, (-cv - v_max) / a_max, cp, cv, a_max};
132 t = (-cv - v_max) / a_max - v_max / a_max;
133 cp -= 0.5 * (cv + v_max) * (cv - v_max) / a_max - 0.5 * v_max * v_max / a_max;
134 cv = 0;
135 }
136 } else {
137 spline_coeffs(i, 0) = {0, -cv / a_max, cp, cv, a_max};
138 t = -cv / a_max;
139 cp -= 0.5 * cv * cv / a_max;
140 cv = 0;
141 dir = true;
142 }
143 }
144 }
145
146 if (dir) {
147 double remain_p = tp - cp;
148 if (remain_p > v_max * v_max / a_max) {
149 double t2 = (remain_p - v_max * v_max / a_max) / v_max;
150
151 spline_coeffs(i, 1) = {t, t + v_max / a_max, cp, cv, a_max};
152 t += v_max / a_max;
153 cp += 0.5 * v_max * v_max / a_max;
154 cv = v_max;
155
156 spline_coeffs(i, 2) = {t, t + t2, cp, cv, 0};
157 t += t2;
158 cp += v_max * t2;
159
160 spline_coeffs(i, 3) = {t, t + v_max / a_max, cp, cv, -a_max};
161 t += v_max / a_max;
162 cp += 0.5 * v_max * v_max / a_max;
163 cv = 0;
164 } else {
165 double t1 = std::sqrt(remain_p / a_max);
166
167 spline_coeffs(i, 1) = {t, t + t1, cp, cv, a_max};
168 t += t1;
169 cp += 0.5 * a_max * t1 * t1;
170 cv += a_max * t1;
171
172 spline_coeffs(i, 2) = {t, t, cp, cv, 0};
173
174 spline_coeffs(i, 3) = {t, t + t1, cp, cv, -a_max};
175 t += t1;
176 cp += 0.5 * a_max * t1 * t1;
177 cv = 0;
178 }
179 } else {
180 double remain_p = tp - cp;
181 if (-remain_p > v_max * v_max / a_max) {
182 double t2 = (-remain_p - v_max * v_max / a_max) / v_max;
183
184 spline_coeffs(i, 1) = {t, t + v_max / a_max, cp, cv, -a_max};
185 t += v_max / a_max;
186 cp -= 0.5 * v_max * v_max / a_max;
187 cv = -v_max;
188
189 spline_coeffs(i, 2) = {t, t + t2, cp, cv, 0};
190 cp -= v_max * t2;
191 t += t2;
192
193 spline_coeffs(i, 3) = {t, t + v_max / a_max, cp, cv, a_max};
194 t += v_max / a_max;
195 cp -= 0.5 * v_max * v_max / a_max;
196 cv = 0;
197 } else {
198 double t1 = std::sqrt(-remain_p / a_max);
199
200 spline_coeffs(i, 1) = {t, t + t1, cp, cv, -a_max};
201 t += t1;
202 cp -= 0.5 * a_max * t1 * t1;
203 cv -= a_max * t1;
204
205 spline_coeffs(i, 2) = {t, t, cp, cv, 0};
206
207 spline_coeffs(i, 3) = {t, t + t1, cp, cv, a_max};
208 t += t1;
209 cp -= 0.5 * a_max * t1 * t1;
210 cv = 0;
211 }
212 }
213
214 if (first) {
215 if (max < spline_coeffs(i, 3).end_t) {
216 max = spline_coeffs(i, 3).end_t;
217 }
218 }
219 }
220 if (first) {
221 total_time_ = max;
222 first = false;
223 }
224 for (int i = 0; i < n_joints_; i++) {
225 if (std::fabs(spline_coeffs(i, 3).end_t - total_time_) < 1e-5) {
226 ans_spline_coeffs.row(i) = spline_coeffs.row(i);
227 check[i] = true;
228 continue;
229 } else if (total_time_ < spline_coeffs(i, 3).end_t) {
230 l_v(i) = m_v(i);
231 } else {
232 ans_spline_coeffs.row(i) = spline_coeffs.row(i);
233 r_v(i) = m_v(i);
234 }
235 m_v(i) = (l_v(i) + r_v(i)) / 2.;
236 }
237 }
238 spline_coeffs_ = ans_spline_coeffs;
239 }
240
241 Input GetLastInput() const { return last_input_; }
242
243 bool IsReached(double t) { return t >= total_time_; }
244
245 [[nodiscard]] double GetTotalTime() const { return total_time_; }
246
247 Output operator()(double t) { return at_time(t); }
248
249 Output at_time(double t) {
250 if (n_joints_ == 0) {
251 throw std::runtime_error("Not initialized problem");
252 }
253
254 Output out;
255 out.position.resize(n_joints_);
256 out.position.fill(0.);
257 out.velocity.resize(n_joints_);
258 out.velocity.fill(0.);
259 out.acceleration.resize(n_joints_);
260 out.acceleration.fill(0.);
261
262 if (IsReached(t)) {
263 out.position = last_input_.target_position;
264 out.velocity.setZero();
265 out.acceleration.setZero();
266 } else {
267 for (int i = 0; i < n_joints_; i++) {
268 double stretch = (spline_coeffs_(i, 3).end_t / total_time_);
269 double local_t = t * stretch;
270 double p = last_input_.target_position(i);
271 double v = 0;
272 double a = 0;
273 double dt = 0;
274 for (int j = 0; j < 4; j++) {
275 if (local_t < spline_coeffs_(i, j).end_t) {
276 p = spline_coeffs_(i, j).init_p;
277 v = spline_coeffs_(i, j).init_v;
278 a = spline_coeffs_(i, j).a;
279 dt = local_t - spline_coeffs_(i, j).start_t;
280 break;
281 }
282 }
283 out.position(i) = p + v * dt + 0.5 * a * dt * dt;
284 out.velocity(i) = (v + a * dt) * stretch;
285 out.acceleration(i) = a;
286 }
287 }
288
289 return out;
290 }
291
292 private:
293 unsigned int max_iter_;
294
295 unsigned int n_joints_{0};
296 Input last_input_;
297 Eigen::Array<Coeff, N, 4> spline_coeffs_; // [0] =0 속도로 감속
298 // [1] = v_max 속도로 가속
299 // [2] =v_max 속도 유지
300 // [3] = 0 속도로 감속
301 double total_time_{};
302};
303
304} // namespace rb
Definition trapezoidal_motion_generator.h:12
Definition trapezoidal_motion_generator.h:30
Definition trapezoidal_motion_generator.h:14
Definition trapezoidal_motion_generator.h:24