15 Eigen::Vector<double, N> current_position;
16 Eigen::Vector<double, N> current_velocity;
18 Eigen::Vector<double, N> target_position;
19 Eigen::Vector<double, N> velocity_limit;
20 Eigen::Vector<double, N> acceleration_limit;
25 Eigen::Vector<double, N> position;
26 Eigen::Vector<double, N> velocity;
27 Eigen::Vector<double, N> acceleration;
40 void Update(
const Input& input) {
41 n_joints_ = input.target_position.size();
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");
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_);
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);
62 Eigen::Vector<bool, N> check;
63 check.resize(n_joints_);
66 double max = input.minimum_time;
69 for (
int it = 0; it < max_iter_; it++) {
70 for (
int i = 0; i < n_joints_; i++) {
74 double cp = input.current_position[i];
75 double cv = input.current_velocity[i];
77 double tp = input.target_position[i];
78 double v_max = m_v[i];
79 double a_max = input.acceleration_limit[i];
86 if (cp + 0.5 * cv * cv / a_max < tp) {
94 spline_coeffs(i, 0) = coeff;
96 cp -= 0.5 * cv * cv / a_max;
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;
105 spline_coeffs(i, 0) = {0, cv / a_max, cp, cv, -a_max};
107 cp += 0.5 * cv * cv / a_max;
112 spline_coeffs(i, 0) = {0, -cv / a_max, cp, cv, a_max};
114 cp -= 0.5 * cv * cv / a_max;
119 spline_coeffs(i, 0) = {0, cv / a_max, cp, cv, -a_max};
121 cp += 0.5 * cv * cv / a_max;
124 if (cp - 0.5 * cv * cv / a_max > tp) {
126 spline_coeffs(i, 0) = {0, 0, cp, cv, a_max};
128 cp += 0.5 * cv * cv / a_max;
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;
137 spline_coeffs(i, 0) = {0, -cv / a_max, cp, cv, a_max};
139 cp -= 0.5 * cv * cv / a_max;
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;
151 spline_coeffs(i, 1) = {t, t + v_max / a_max, cp, cv, a_max};
153 cp += 0.5 * v_max * v_max / a_max;
156 spline_coeffs(i, 2) = {t, t + t2, cp, cv, 0};
160 spline_coeffs(i, 3) = {t, t + v_max / a_max, cp, cv, -a_max};
162 cp += 0.5 * v_max * v_max / a_max;
165 double t1 = std::sqrt(remain_p / a_max);
167 spline_coeffs(i, 1) = {t, t + t1, cp, cv, a_max};
169 cp += 0.5 * a_max * t1 * t1;
172 spline_coeffs(i, 2) = {t, t, cp, cv, 0};
174 spline_coeffs(i, 3) = {t, t + t1, cp, cv, -a_max};
176 cp += 0.5 * a_max * t1 * t1;
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;
184 spline_coeffs(i, 1) = {t, t + v_max / a_max, cp, cv, -a_max};
186 cp -= 0.5 * v_max * v_max / a_max;
189 spline_coeffs(i, 2) = {t, t + t2, cp, cv, 0};
193 spline_coeffs(i, 3) = {t, t + v_max / a_max, cp, cv, a_max};
195 cp -= 0.5 * v_max * v_max / a_max;
198 double t1 = std::sqrt(-remain_p / a_max);
200 spline_coeffs(i, 1) = {t, t + t1, cp, cv, -a_max};
202 cp -= 0.5 * a_max * t1 * t1;
205 spline_coeffs(i, 2) = {t, t, cp, cv, 0};
207 spline_coeffs(i, 3) = {t, t + t1, cp, cv, a_max};
209 cp -= 0.5 * a_max * t1 * t1;
215 if (max < spline_coeffs(i, 3).end_t) {
216 max = spline_coeffs(i, 3).end_t;
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);
229 }
else if (total_time_ < spline_coeffs(i, 3).end_t) {
232 ans_spline_coeffs.row(i) = spline_coeffs.row(i);
235 m_v(i) = (l_v(i) + r_v(i)) / 2.;
238 spline_coeffs_ = ans_spline_coeffs;
241 Input GetLastInput()
const {
return last_input_; }
243 bool IsReached(
double t) {
return t >= total_time_; }
245 [[nodiscard]]
double GetTotalTime()
const {
return total_time_; }
247 Output operator()(
double t) {
return at_time(t); }
249 Output at_time(
double t) {
250 if (n_joints_ == 0) {
251 throw std::runtime_error(
"Not initialized problem");
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.);
263 out.position = last_input_.target_position;
264 out.velocity.setZero();
265 out.acceleration.setZero();
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);
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;
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;
293 unsigned int max_iter_;
295 unsigned int n_joints_{0};
297 Eigen::Array<Coeff, N, 4> spline_coeffs_;
301 double total_time_{};