@@ -28,8 +28,7 @@ class TargetCalculator {
28
28
29
29
constexpr static double eps {std::numeric_limits<double >::epsilon ()};
30
30
31
- Vector<double > new_max_jerk; // For phase synchronization
32
- Vector<double > pd;
31
+ Vector<double > new_max_jerk, pd; // For phase synchronization
33
32
VectorIntervals<double > possible_t_syncs;
34
33
VectorIntervals<size_t > idx;
35
34
@@ -41,49 +40,76 @@ class TargetCalculator {
41
40
42
41
// ! Is the trajectory (in principle) phase synchronizable?
43
42
bool is_input_collinear (const InputParameter<DOFs>& inp, const Vector<double >& jMax, Profile::Direction limiting_direction, size_t limiting_dof) {
44
- // Get scaling factor of first DoF
45
- bool pd_found_nonzero {false };
46
- double v0_scale, a0_scale, vf_scale, af_scale;
47
- for (size_t dof = 0 ; dof < pd.size (); ++dof) {
43
+ // Check that vectors pd, v0, a0, vf, af are collinear
44
+ for (size_t dof = 0 ; dof < degrees_of_freedom; ++dof) {
45
+ pd[dof] = inp.target_position [dof] - inp.current_position [dof];
46
+ }
47
+
48
+ const Vector<double >* scale_vector = nullptr ;
49
+ std::optional<size_t > scale_dof; // Need to find a scale DOF because limiting DOF might not be phase synchronized
50
+ for (size_t dof = 0 ; dof < degrees_of_freedom; ++dof) {
48
51
if (inp_per_dof_synchronization[dof] != Synchronization::Phase) {
49
52
continue ;
50
53
}
51
54
52
- pd[dof] = inp.target_position [dof] - inp.current_position [dof];
53
-
54
- if (!pd_found_nonzero && std::abs (pd[dof]) > eps) {
55
- v0_scale = inp.current_velocity [dof] / pd[dof];
56
- a0_scale = inp.current_acceleration [dof] / pd[dof];
57
- vf_scale = inp.target_velocity [dof] / pd[dof];
58
- af_scale = inp.target_acceleration [dof] / pd[dof];
59
- pd_found_nonzero = true ;
55
+ if (inp_per_dof_control_interface[dof] == ControlInterface::Position && std::abs (pd[dof]) > eps) {
56
+ scale_vector = &pd;
57
+ scale_dof = dof;
58
+ break ;
59
+
60
+ } else if (std::abs (inp.current_velocity [dof]) > eps) {
61
+ scale_vector = &inp.current_velocity ;
62
+ scale_dof = dof;
63
+ break ;
64
+
65
+ } else if (std::abs (inp.current_acceleration [dof]) > eps) {
66
+ scale_vector = &inp.current_acceleration ;
67
+ scale_dof = dof;
68
+ break ;
69
+
70
+ } else if (std::abs (inp.target_velocity [dof]) > eps) {
71
+ scale_vector = &inp.target_velocity ;
72
+ scale_dof = dof;
73
+ break ;
74
+
75
+ } else if (std::abs (inp.target_acceleration [dof]) > eps) {
76
+ scale_vector = &inp.target_acceleration ;
77
+ scale_dof = dof;
78
+ break ;
60
79
}
61
80
}
62
81
63
- if (!pd_found_nonzero ) { // position difference is zero everywhere...
64
- return false ;
82
+ if (!scale_dof ) {
83
+ return false ; // Zero everywhere is in theory collinear, but that trivial case is better handled elsewhere
65
84
}
66
85
86
+ const double scale = scale_vector->operator [](*scale_dof);
87
+ const double pd_scale = pd[*scale_dof] / scale;
88
+ const double v0_scale = inp.current_velocity [*scale_dof] / scale;
89
+ const double vf_scale = inp.target_velocity [*scale_dof] / scale;
90
+ const double a0_scale = inp.current_acceleration [*scale_dof] / scale;
91
+ const double af_scale = inp.target_acceleration [*scale_dof] / scale;
92
+
93
+ const double scale_limiting = scale_vector->operator [](limiting_dof);
67
94
const double max_jerk_limiting = (limiting_direction == Profile::Direction::UP) ? jMax[limiting_dof] : -jMax[limiting_dof];
68
- constexpr double eps_colinear {10 * eps};
69
95
70
- for (size_t dof = 0 ; dof < pd. size () ; ++dof) {
71
- if (dof == limiting_dof || inp_per_dof_synchronization[dof] != Synchronization::Phase) {
96
+ for (size_t dof = 0 ; dof < degrees_of_freedom ; ++dof) {
97
+ if (inp_per_dof_synchronization[dof] != Synchronization::Phase) {
72
98
continue ;
73
99
}
74
100
75
- // Are the vectors collinear?
101
+ const double current_scale = scale_vector-> operator [](dof);
76
102
if (
77
- std::abs (inp.current_velocity [dof] - v0_scale * pd[dof]) > eps_colinear
78
- || std::abs (inp.current_acceleration [dof] - a0_scale * pd[dof]) > eps_colinear
79
- || std::abs (inp.target_velocity [dof] - vf_scale * pd[dof]) > eps_colinear
80
- || std::abs (inp.target_acceleration [dof] - af_scale * pd[dof]) > eps_colinear
103
+ (inp_per_dof_control_interface[dof] == ControlInterface::Position && std::abs (pd[dof] - pd_scale * current_scale) > eps)
104
+ || std::abs (inp.current_velocity [dof] - v0_scale * current_scale) > eps
105
+ || std::abs (inp.current_acceleration [dof] - a0_scale * current_scale) > eps
106
+ || std::abs (inp.target_velocity [dof] - vf_scale * current_scale) > eps
107
+ || std::abs (inp.target_acceleration [dof] - af_scale * current_scale) > eps
81
108
) {
82
109
return false ;
83
110
}
84
111
85
- const double scale = pd[dof] / pd[limiting_dof];
86
- new_max_jerk[dof] = scale * max_jerk_limiting;
112
+ new_max_jerk[dof] = max_jerk_limiting * current_scale / scale_limiting;
87
113
}
88
114
89
115
return true ;
@@ -232,7 +258,7 @@ class TargetCalculator {
232
258
case ControlInterface::Velocity: {
233
259
p.brake .get_velocity_brake_trajectory (inp.current_acceleration [dof], inp.max_acceleration [dof], inp_min_acceleration[dof], inp.max_jerk [dof]);
234
260
// p.accel.get_velocity_brake_trajectory(inp.target_acceleration[dof], inp.max_acceleration[dof], inp_min_acceleration[dof], inp.max_jerk[dof]);
235
- p.set_boundary (inp.current_position [dof], inp.current_velocity [dof], inp.current_acceleration [dof], inp.target_velocity [dof], inp.target_acceleration [dof]);
261
+ p.set_boundary_for_velocity (inp.current_position [dof], inp.current_velocity [dof], inp.current_acceleration [dof], inp.target_velocity [dof], inp.target_acceleration [dof]);
236
262
} break ;
237
263
}
238
264
@@ -304,7 +330,7 @@ class TargetCalculator {
304
330
}
305
331
306
332
// Phase Synchronization
307
- if (!discrete_duration && limiting_dof && std::any_of (inp_per_dof_synchronization.begin (), inp_per_dof_synchronization.end (), [](Synchronization s){ return s == Synchronization::Phase; }) && std::all_of (inp_per_dof_control_interface. begin (), inp_per_dof_control_interface. end (), [](ControlInterface s){ return s == ControlInterface::Position ; })) {
333
+ if (limiting_dof && std::any_of (inp_per_dof_synchronization.begin (), inp_per_dof_synchronization.end (), [](Synchronization s){ return s == Synchronization::Phase; })) {
308
334
const Profile& p_limiting = traj.profiles [0 ][limiting_dof.value ()];
309
335
if (is_input_collinear (inp, inp.max_jerk , p_limiting.direction , limiting_dof.value ())) {
310
336
bool found_time_synchronization {true };
@@ -320,15 +346,33 @@ class TargetCalculator {
320
346
p.jerk_signs = p_limiting.jerk_signs ;
321
347
322
348
// Profile::Limits::NONE is a small hack, as there is no specialization for that in the check function
323
- switch (p.jerk_signs ) {
324
- case Profile::JerkSigns::UDDU: {
325
- if (!p.check_with_timing <Profile::JerkSigns::UDDU, Profile::Limits::NONE>(t_profile, new_max_jerk[dof], inp.max_velocity [dof], inp_min_velocity[dof], inp.max_acceleration [dof], inp_min_acceleration[dof], inp.max_jerk [dof])) {
326
- found_time_synchronization = false ;
349
+ switch (inp_per_dof_control_interface[dof]) {
350
+ case ControlInterface::Position: {
351
+ switch (p.jerk_signs ) {
352
+ case Profile::JerkSigns::UDDU: {
353
+ if (!p.check_with_timing <Profile::JerkSigns::UDDU, Profile::Limits::NONE>(t_profile, new_max_jerk[dof], inp.max_velocity [dof], inp_min_velocity[dof], inp.max_acceleration [dof], inp_min_acceleration[dof], inp.max_jerk [dof])) {
354
+ found_time_synchronization = false ;
355
+ }
356
+ } break ;
357
+ case Profile::JerkSigns::UDUD: {
358
+ if (!p.check_with_timing <Profile::JerkSigns::UDUD, Profile::Limits::NONE>(t_profile, new_max_jerk[dof], inp.max_velocity [dof], inp_min_velocity[dof], inp.max_acceleration [dof], inp_min_acceleration[dof], inp.max_jerk [dof])) {
359
+ found_time_synchronization = false ;
360
+ }
361
+ } break ;
327
362
}
328
363
} break ;
329
- case Profile::JerkSigns::UDUD: {
330
- if (!p.check_with_timing <Profile::JerkSigns::UDUD, Profile::Limits::NONE>(t_profile, new_max_jerk[dof], inp.max_velocity [dof], inp_min_velocity[dof], inp.max_acceleration [dof], inp_min_acceleration[dof], inp.max_jerk [dof])) {
331
- found_time_synchronization = false ;
364
+ case ControlInterface::Velocity: {
365
+ switch (p.jerk_signs ) {
366
+ case Profile::JerkSigns::UDDU: {
367
+ if (!p.check_for_velocity_with_timing <Profile::JerkSigns::UDDU, Profile::Limits::NONE>(t_profile, new_max_jerk[dof], inp.max_acceleration [dof], inp_min_acceleration[dof], inp.max_jerk [dof])) {
368
+ found_time_synchronization = false ;
369
+ }
370
+ } break ;
371
+ case Profile::JerkSigns::UDUD: {
372
+ if (!p.check_for_velocity_with_timing <Profile::JerkSigns::UDUD, Profile::Limits::NONE>(t_profile, new_max_jerk[dof], inp.max_acceleration [dof], inp_min_acceleration[dof], inp.max_jerk [dof])) {
373
+ found_time_synchronization = false ;
374
+ }
375
+ } break ;
332
376
}
333
377
} break ;
334
378
}
0 commit comments