1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
|
%global _empty_manifest_terminate_build 0
Name: python-ruckig
Version: 0.9.2
Release: 1
Summary: Instantaneous Motion Generation for Robots and Machines.
License: MIT
URL: https://www.ruckig.com
Source0: https://mirrors.nju.edu.cn/pypi/web/packages/38/a3/c6f9f5685b4f046fd66582e361a0569e9fad48542cd838ef13bd745e93bd/ruckig-0.9.2.tar.gz
%description
Working | 0
Finished | 1
Error | -1
ErrorInvalidInput | -100
ErrorTrajectoryDuration | -101
ErrorPositionalLimits | -102
ErrorExecutionTimeCalculation | -110
ErrorSynchronizationCalculation | -111
### Output Parameter
The output class includes the new kinematic state and the overall trajectory.
```.cpp
Vector new_position;
Vector new_velocity;
Vector new_acceleration;
Trajectory trajectory; // The current trajectory
double time; // The current, auto-incremented time. Reset to 0 at a new calculation.
size_t new_section; // Index of the section between two (possibly filtered) intermediate positions.
bool did_section_change; // Was a new section reached in the last cycle?
bool new_calculation; // Whether a new calculation was performed in the last cycle
bool was_calculation_interrupted; // Was the trajectory calculation interrupted? (only in Pro Version)
double calculation_duration; // Duration of the calculation in the last cycle [µs]
```
Moreover, the **trajectory** class has a range of useful parameters and methods.
```.cpp
double duration; // Duration of the trajectory
std::array<double, DOFs> independent_min_durations; // Time-optimal profile for each independent DoF
<...> at_time(double time); // Get the kinematic state of the trajectory at a given time
<...> get_position_extrema(); // Returns information about the position extrema and their times
```
Again, we refer to the [API documentation](https://docs.ruckig.com) for the exact signatures.
### Offline Calculation
Ruckig also supports an offline approach for calculating a trajectory:
```.cpp
result = ruckig.calculate(input, trajectory);
```
When only using this method, the `Ruckig` constructor does not need a control cycle (`delta_time`) as an argument. However if given, Ruckig supports stepping through the trajectory with
```.cpp
while (ruckig.update(trajectory, output) == Result::Working) {
// Make use of the new state here!
// e.g. robot->setJointPositions(output.new_position);
}
```
starting from the current `output.time` (currently Ruckig Pro only).
### Tracking Interface
When following an arbitrary signal with position, velocity, acceleration, and jerk-limitation, the straight forward way would be to pass the current state to Ruckig's target state. However, as the resulting trajectory will take time to catch up, this approach will always lag behind the signal. The tracking interface solves this problem by predicting ahead (e.g. with constant acceleration by default) and is therefore able to follow signals very closely in a time-optimal way. This might be very helpful for (general) tracking, robot servoing, or trajectory post-processing applications.
To use the tracking interface, construct
```.cpp
Trackig<1> otg {0.01}; // control cycle
```
and set the current state as well as the kinematic constraints via
```.cpp
input.current_position = {0.0};
input.current_velocity = {0.0};
input.current_acceleration = {0.0};
input.max_velocity = {0.8};
input.max_acceleration = {2.0};
input.max_jerk = {5.0};
```
Then, we can track a signal in an online manner within the real-time control loop
```.cpp
for (double t = 0; t < 10.0; t += otg.delta_time) {
auto target_state = signal(t); // signal returns position, velocity, and acceleration
auto res = otg.update(target_state, input, output);
// Make use of the smooth target motion here (e.g. output.new_position)
output.pass_to_input(input);
}
```
Please find a complete example [here](https://github.com/pantor/ruckig/blob/master/examples/13_tracking.cpp). This functionality can also be used in an offline manner, e.g. when the entire signal is known beforehand. Here, we call the
```.cpp
smooth_trajectory = otg.calculate_trajectory(target_states, input);
```
method with the trajectory given as a `std::vector` of target states. The Tracking interface is available in the Ruckig Pro version.
### Dynamic Number of Degrees of Freedom
So far, we have told Ruckig the number of DoFs as a template parameter. If you don't know the number of DoFs at compile-time, you can set the template parameter to `ruckig::DynamicDOFs` and pass the DoFs to the constructor:
```.cpp
Ruckig<DynamicDOFs> otg {6, 0.001};
InputParameter<DynamicDOFs> input {6};
OutputParameter<DynamicDOFs> output {6};
```
However, we recommend to keep the template parameter when possible: First, it has a performance benefit of a few percent. Second, it is convenient for real-time programming due to its easier handling of memory allocations. When using dynamic degrees of freedom, make sure to allocate the memory of all vectors beforehand.
### Custom Vector Types
Ruckig supports custom vector types to make interfacing with your code even easier and more flexible. Most importantly, you can switch to [Eigen Vectors](https://eigen.tuxfamily.org) simply by including Eigen (3.4 or later) before Ruckig
```.cpp
#include <Eigen/Core> // Version 3.4 or later
#include <ruckig/ruckig.hpp>
```
and then call the constructors with the `ruckig::EigenVector` parameter.
```.cpp
Ruckig<6, EigenVector> otg {0.001};
InputParameter<6, EigenVector> input;
OutputParameter<6, EigenVector> output;
```
Now every in- and output of Ruckig's API (such as `current_position`, `new_position` or `max_jerk`) are Eigen types! To define completely custom vector types, you can pass a C++ [template template parameter](https://en.cppreference.com/w/cpp/language/template_parameters) to the constructor. This template template parameter needs to fulfill a range of template arguments and methods:
```.cpp
template<class Type, size_t DOFs>
struct MinimalVector {
Type operator[](size_t i) const; // Array [] getter
Type& operator[](size_t i); // Array [] setter
size_t size() const; // Current size
bool operator==(const MinimalVector<T, DOFs>& rhs) const; // Equal comparison operator
// Only required in combination with DynamicDOFs, e.g. to allocate memory
void resize(size_t size);
};
```
Note that `DynamicDOFs` corresponds to `DOFs = 0`. We've included a range of examples for using Ruckig with [(10) Eigen](https://github.com/pantor/ruckig/blob/master/examples/10_eigen_vector_type.cpp), [(11) custom vector types](https://github.com/pantor/ruckig/blob/master/examples/11_custom_vector_type.cpp), and [(12) custom types with a dynamic number of DoFs](https://github.com/pantor/ruckig/blob/master/examples/12_custom_vector_type_dynamic_dofs.cpp).
## Tests and Numerical Stability
The current test suite validates over 5.000.000.000 random trajectories as well as many additional edge cases. The numerical exactness is tested for the final position and final velocity to be within `1e-8`, for the final acceleration to be within `1e-10`, and for the velocity, acceleration and jerk limit to be within of a numerical error of `1e-12`. These are absolute values - we suggest to scale your input so that these correspond to your required precision of the system. For example, for most real-world systems we suggest to use input values in `[m]` (instead of e.g. `[mm]`), as `1e-8m` is sufficient precise for practical trajectory generation. Furthermore, all kinematic limits should be below `1e12`. The maximal supported trajectory duration is `7e3`, and you can [scale your input parameter](https://github.com/pantor/ruckig/issues/139#issuecomment-1280730316) to avoid that limitation. Note that Ruckig will also output values outside of this range, there is however no guarantee for correctness.
## Benchmark
We find that Ruckig is more than twice as fast as Reflexxes Type IV for state-to-state motions and well-suited for control cycles as low as 250 microseconds. The Ruckig *Community Version* is in general a more powerful and open-source alternative to the [Reflexxes Type IV](http://reflexxes.ws/) library. In fact, Ruckig is the first Type V trajectory generator for arbitrary target states and even supports directional velocity and acceleration limits, while also being faster on top.

For trajectories with intermediate waypoints, we compare Ruckig to [Toppra](https://github.com/hungpham2511/toppra), a state-of-the-art library for robotic motion planning. Ruckig is able to improve the trajectory duration on average by around 10%, as the path planning and time parametrization are calculated jointly. Moreover, Ruckig is real-time capable and supports jerk-constraints.

## Development
Ruckig is written in C++17. It is continuously tested on `ubuntu-latest`, `macos-latest`, and `windows-latest` against following versions
- Doctest v2.4 (only for testing)
- Pybind11 v2.9 (only for python wrapper)
If you still need to use C++11, you can patch the Ruckig *Community Version* by calling `bash scripts/patch-c++11.sh`. Note that this will result in a performance drop of a few percent. Moreover, the Python module is not supported.
## Used By
Ruckig is used by over hundred research labs, companies, and open-source projects worldwide, including:
- [MoveIt 2](https://moveit.ros.org) for trajectory generation.
- [CoppeliaSim](https://www.coppeliarobotics.com/) starting from version 4.3.
- [Fuzzy Logic Robotics](https://flr.io)
- [Gestalt Robotics](https://www.gestalt-robotics.com)
- [Struckig](https://github.com/stefanbesler/struckig), a port of Ruckig to Structered Text (ST - IEC61131-3) for usage on PLCs.
- [Frankx](https://github.com/pantor/frankx) for controlling the Franka Emika robot arm.
- and many others!
## Citation
```
@article{berscheid2021jerk,
title={Jerk-limited Real-time Trajectory Generation with Arbitrary Target States},
author={Berscheid, Lars and Kr{\"o}ger, Torsten},
journal={Robotics: Science and Systems XVII},
year={2021}
}
```
%package -n python3-ruckig
Summary: Instantaneous Motion Generation for Robots and Machines.
Provides: python-ruckig
BuildRequires: python3-devel
BuildRequires: python3-setuptools
BuildRequires: python3-pip
BuildRequires: python3-cffi
BuildRequires: gcc
BuildRequires: gdb
%description -n python3-ruckig
Working | 0
Finished | 1
Error | -1
ErrorInvalidInput | -100
ErrorTrajectoryDuration | -101
ErrorPositionalLimits | -102
ErrorExecutionTimeCalculation | -110
ErrorSynchronizationCalculation | -111
### Output Parameter
The output class includes the new kinematic state and the overall trajectory.
```.cpp
Vector new_position;
Vector new_velocity;
Vector new_acceleration;
Trajectory trajectory; // The current trajectory
double time; // The current, auto-incremented time. Reset to 0 at a new calculation.
size_t new_section; // Index of the section between two (possibly filtered) intermediate positions.
bool did_section_change; // Was a new section reached in the last cycle?
bool new_calculation; // Whether a new calculation was performed in the last cycle
bool was_calculation_interrupted; // Was the trajectory calculation interrupted? (only in Pro Version)
double calculation_duration; // Duration of the calculation in the last cycle [µs]
```
Moreover, the **trajectory** class has a range of useful parameters and methods.
```.cpp
double duration; // Duration of the trajectory
std::array<double, DOFs> independent_min_durations; // Time-optimal profile for each independent DoF
<...> at_time(double time); // Get the kinematic state of the trajectory at a given time
<...> get_position_extrema(); // Returns information about the position extrema and their times
```
Again, we refer to the [API documentation](https://docs.ruckig.com) for the exact signatures.
### Offline Calculation
Ruckig also supports an offline approach for calculating a trajectory:
```.cpp
result = ruckig.calculate(input, trajectory);
```
When only using this method, the `Ruckig` constructor does not need a control cycle (`delta_time`) as an argument. However if given, Ruckig supports stepping through the trajectory with
```.cpp
while (ruckig.update(trajectory, output) == Result::Working) {
// Make use of the new state here!
// e.g. robot->setJointPositions(output.new_position);
}
```
starting from the current `output.time` (currently Ruckig Pro only).
### Tracking Interface
When following an arbitrary signal with position, velocity, acceleration, and jerk-limitation, the straight forward way would be to pass the current state to Ruckig's target state. However, as the resulting trajectory will take time to catch up, this approach will always lag behind the signal. The tracking interface solves this problem by predicting ahead (e.g. with constant acceleration by default) and is therefore able to follow signals very closely in a time-optimal way. This might be very helpful for (general) tracking, robot servoing, or trajectory post-processing applications.
To use the tracking interface, construct
```.cpp
Trackig<1> otg {0.01}; // control cycle
```
and set the current state as well as the kinematic constraints via
```.cpp
input.current_position = {0.0};
input.current_velocity = {0.0};
input.current_acceleration = {0.0};
input.max_velocity = {0.8};
input.max_acceleration = {2.0};
input.max_jerk = {5.0};
```
Then, we can track a signal in an online manner within the real-time control loop
```.cpp
for (double t = 0; t < 10.0; t += otg.delta_time) {
auto target_state = signal(t); // signal returns position, velocity, and acceleration
auto res = otg.update(target_state, input, output);
// Make use of the smooth target motion here (e.g. output.new_position)
output.pass_to_input(input);
}
```
Please find a complete example [here](https://github.com/pantor/ruckig/blob/master/examples/13_tracking.cpp). This functionality can also be used in an offline manner, e.g. when the entire signal is known beforehand. Here, we call the
```.cpp
smooth_trajectory = otg.calculate_trajectory(target_states, input);
```
method with the trajectory given as a `std::vector` of target states. The Tracking interface is available in the Ruckig Pro version.
### Dynamic Number of Degrees of Freedom
So far, we have told Ruckig the number of DoFs as a template parameter. If you don't know the number of DoFs at compile-time, you can set the template parameter to `ruckig::DynamicDOFs` and pass the DoFs to the constructor:
```.cpp
Ruckig<DynamicDOFs> otg {6, 0.001};
InputParameter<DynamicDOFs> input {6};
OutputParameter<DynamicDOFs> output {6};
```
However, we recommend to keep the template parameter when possible: First, it has a performance benefit of a few percent. Second, it is convenient for real-time programming due to its easier handling of memory allocations. When using dynamic degrees of freedom, make sure to allocate the memory of all vectors beforehand.
### Custom Vector Types
Ruckig supports custom vector types to make interfacing with your code even easier and more flexible. Most importantly, you can switch to [Eigen Vectors](https://eigen.tuxfamily.org) simply by including Eigen (3.4 or later) before Ruckig
```.cpp
#include <Eigen/Core> // Version 3.4 or later
#include <ruckig/ruckig.hpp>
```
and then call the constructors with the `ruckig::EigenVector` parameter.
```.cpp
Ruckig<6, EigenVector> otg {0.001};
InputParameter<6, EigenVector> input;
OutputParameter<6, EigenVector> output;
```
Now every in- and output of Ruckig's API (such as `current_position`, `new_position` or `max_jerk`) are Eigen types! To define completely custom vector types, you can pass a C++ [template template parameter](https://en.cppreference.com/w/cpp/language/template_parameters) to the constructor. This template template parameter needs to fulfill a range of template arguments and methods:
```.cpp
template<class Type, size_t DOFs>
struct MinimalVector {
Type operator[](size_t i) const; // Array [] getter
Type& operator[](size_t i); // Array [] setter
size_t size() const; // Current size
bool operator==(const MinimalVector<T, DOFs>& rhs) const; // Equal comparison operator
// Only required in combination with DynamicDOFs, e.g. to allocate memory
void resize(size_t size);
};
```
Note that `DynamicDOFs` corresponds to `DOFs = 0`. We've included a range of examples for using Ruckig with [(10) Eigen](https://github.com/pantor/ruckig/blob/master/examples/10_eigen_vector_type.cpp), [(11) custom vector types](https://github.com/pantor/ruckig/blob/master/examples/11_custom_vector_type.cpp), and [(12) custom types with a dynamic number of DoFs](https://github.com/pantor/ruckig/blob/master/examples/12_custom_vector_type_dynamic_dofs.cpp).
## Tests and Numerical Stability
The current test suite validates over 5.000.000.000 random trajectories as well as many additional edge cases. The numerical exactness is tested for the final position and final velocity to be within `1e-8`, for the final acceleration to be within `1e-10`, and for the velocity, acceleration and jerk limit to be within of a numerical error of `1e-12`. These are absolute values - we suggest to scale your input so that these correspond to your required precision of the system. For example, for most real-world systems we suggest to use input values in `[m]` (instead of e.g. `[mm]`), as `1e-8m` is sufficient precise for practical trajectory generation. Furthermore, all kinematic limits should be below `1e12`. The maximal supported trajectory duration is `7e3`, and you can [scale your input parameter](https://github.com/pantor/ruckig/issues/139#issuecomment-1280730316) to avoid that limitation. Note that Ruckig will also output values outside of this range, there is however no guarantee for correctness.
## Benchmark
We find that Ruckig is more than twice as fast as Reflexxes Type IV for state-to-state motions and well-suited for control cycles as low as 250 microseconds. The Ruckig *Community Version* is in general a more powerful and open-source alternative to the [Reflexxes Type IV](http://reflexxes.ws/) library. In fact, Ruckig is the first Type V trajectory generator for arbitrary target states and even supports directional velocity and acceleration limits, while also being faster on top.

For trajectories with intermediate waypoints, we compare Ruckig to [Toppra](https://github.com/hungpham2511/toppra), a state-of-the-art library for robotic motion planning. Ruckig is able to improve the trajectory duration on average by around 10%, as the path planning and time parametrization are calculated jointly. Moreover, Ruckig is real-time capable and supports jerk-constraints.

## Development
Ruckig is written in C++17. It is continuously tested on `ubuntu-latest`, `macos-latest`, and `windows-latest` against following versions
- Doctest v2.4 (only for testing)
- Pybind11 v2.9 (only for python wrapper)
If you still need to use C++11, you can patch the Ruckig *Community Version* by calling `bash scripts/patch-c++11.sh`. Note that this will result in a performance drop of a few percent. Moreover, the Python module is not supported.
## Used By
Ruckig is used by over hundred research labs, companies, and open-source projects worldwide, including:
- [MoveIt 2](https://moveit.ros.org) for trajectory generation.
- [CoppeliaSim](https://www.coppeliarobotics.com/) starting from version 4.3.
- [Fuzzy Logic Robotics](https://flr.io)
- [Gestalt Robotics](https://www.gestalt-robotics.com)
- [Struckig](https://github.com/stefanbesler/struckig), a port of Ruckig to Structered Text (ST - IEC61131-3) for usage on PLCs.
- [Frankx](https://github.com/pantor/frankx) for controlling the Franka Emika robot arm.
- and many others!
## Citation
```
@article{berscheid2021jerk,
title={Jerk-limited Real-time Trajectory Generation with Arbitrary Target States},
author={Berscheid, Lars and Kr{\"o}ger, Torsten},
journal={Robotics: Science and Systems XVII},
year={2021}
}
```
%package help
Summary: Development documents and examples for ruckig
Provides: python3-ruckig-doc
%description help
Working | 0
Finished | 1
Error | -1
ErrorInvalidInput | -100
ErrorTrajectoryDuration | -101
ErrorPositionalLimits | -102
ErrorExecutionTimeCalculation | -110
ErrorSynchronizationCalculation | -111
### Output Parameter
The output class includes the new kinematic state and the overall trajectory.
```.cpp
Vector new_position;
Vector new_velocity;
Vector new_acceleration;
Trajectory trajectory; // The current trajectory
double time; // The current, auto-incremented time. Reset to 0 at a new calculation.
size_t new_section; // Index of the section between two (possibly filtered) intermediate positions.
bool did_section_change; // Was a new section reached in the last cycle?
bool new_calculation; // Whether a new calculation was performed in the last cycle
bool was_calculation_interrupted; // Was the trajectory calculation interrupted? (only in Pro Version)
double calculation_duration; // Duration of the calculation in the last cycle [µs]
```
Moreover, the **trajectory** class has a range of useful parameters and methods.
```.cpp
double duration; // Duration of the trajectory
std::array<double, DOFs> independent_min_durations; // Time-optimal profile for each independent DoF
<...> at_time(double time); // Get the kinematic state of the trajectory at a given time
<...> get_position_extrema(); // Returns information about the position extrema and their times
```
Again, we refer to the [API documentation](https://docs.ruckig.com) for the exact signatures.
### Offline Calculation
Ruckig also supports an offline approach for calculating a trajectory:
```.cpp
result = ruckig.calculate(input, trajectory);
```
When only using this method, the `Ruckig` constructor does not need a control cycle (`delta_time`) as an argument. However if given, Ruckig supports stepping through the trajectory with
```.cpp
while (ruckig.update(trajectory, output) == Result::Working) {
// Make use of the new state here!
// e.g. robot->setJointPositions(output.new_position);
}
```
starting from the current `output.time` (currently Ruckig Pro only).
### Tracking Interface
When following an arbitrary signal with position, velocity, acceleration, and jerk-limitation, the straight forward way would be to pass the current state to Ruckig's target state. However, as the resulting trajectory will take time to catch up, this approach will always lag behind the signal. The tracking interface solves this problem by predicting ahead (e.g. with constant acceleration by default) and is therefore able to follow signals very closely in a time-optimal way. This might be very helpful for (general) tracking, robot servoing, or trajectory post-processing applications.
To use the tracking interface, construct
```.cpp
Trackig<1> otg {0.01}; // control cycle
```
and set the current state as well as the kinematic constraints via
```.cpp
input.current_position = {0.0};
input.current_velocity = {0.0};
input.current_acceleration = {0.0};
input.max_velocity = {0.8};
input.max_acceleration = {2.0};
input.max_jerk = {5.0};
```
Then, we can track a signal in an online manner within the real-time control loop
```.cpp
for (double t = 0; t < 10.0; t += otg.delta_time) {
auto target_state = signal(t); // signal returns position, velocity, and acceleration
auto res = otg.update(target_state, input, output);
// Make use of the smooth target motion here (e.g. output.new_position)
output.pass_to_input(input);
}
```
Please find a complete example [here](https://github.com/pantor/ruckig/blob/master/examples/13_tracking.cpp). This functionality can also be used in an offline manner, e.g. when the entire signal is known beforehand. Here, we call the
```.cpp
smooth_trajectory = otg.calculate_trajectory(target_states, input);
```
method with the trajectory given as a `std::vector` of target states. The Tracking interface is available in the Ruckig Pro version.
### Dynamic Number of Degrees of Freedom
So far, we have told Ruckig the number of DoFs as a template parameter. If you don't know the number of DoFs at compile-time, you can set the template parameter to `ruckig::DynamicDOFs` and pass the DoFs to the constructor:
```.cpp
Ruckig<DynamicDOFs> otg {6, 0.001};
InputParameter<DynamicDOFs> input {6};
OutputParameter<DynamicDOFs> output {6};
```
However, we recommend to keep the template parameter when possible: First, it has a performance benefit of a few percent. Second, it is convenient for real-time programming due to its easier handling of memory allocations. When using dynamic degrees of freedom, make sure to allocate the memory of all vectors beforehand.
### Custom Vector Types
Ruckig supports custom vector types to make interfacing with your code even easier and more flexible. Most importantly, you can switch to [Eigen Vectors](https://eigen.tuxfamily.org) simply by including Eigen (3.4 or later) before Ruckig
```.cpp
#include <Eigen/Core> // Version 3.4 or later
#include <ruckig/ruckig.hpp>
```
and then call the constructors with the `ruckig::EigenVector` parameter.
```.cpp
Ruckig<6, EigenVector> otg {0.001};
InputParameter<6, EigenVector> input;
OutputParameter<6, EigenVector> output;
```
Now every in- and output of Ruckig's API (such as `current_position`, `new_position` or `max_jerk`) are Eigen types! To define completely custom vector types, you can pass a C++ [template template parameter](https://en.cppreference.com/w/cpp/language/template_parameters) to the constructor. This template template parameter needs to fulfill a range of template arguments and methods:
```.cpp
template<class Type, size_t DOFs>
struct MinimalVector {
Type operator[](size_t i) const; // Array [] getter
Type& operator[](size_t i); // Array [] setter
size_t size() const; // Current size
bool operator==(const MinimalVector<T, DOFs>& rhs) const; // Equal comparison operator
// Only required in combination with DynamicDOFs, e.g. to allocate memory
void resize(size_t size);
};
```
Note that `DynamicDOFs` corresponds to `DOFs = 0`. We've included a range of examples for using Ruckig with [(10) Eigen](https://github.com/pantor/ruckig/blob/master/examples/10_eigen_vector_type.cpp), [(11) custom vector types](https://github.com/pantor/ruckig/blob/master/examples/11_custom_vector_type.cpp), and [(12) custom types with a dynamic number of DoFs](https://github.com/pantor/ruckig/blob/master/examples/12_custom_vector_type_dynamic_dofs.cpp).
## Tests and Numerical Stability
The current test suite validates over 5.000.000.000 random trajectories as well as many additional edge cases. The numerical exactness is tested for the final position and final velocity to be within `1e-8`, for the final acceleration to be within `1e-10`, and for the velocity, acceleration and jerk limit to be within of a numerical error of `1e-12`. These are absolute values - we suggest to scale your input so that these correspond to your required precision of the system. For example, for most real-world systems we suggest to use input values in `[m]` (instead of e.g. `[mm]`), as `1e-8m` is sufficient precise for practical trajectory generation. Furthermore, all kinematic limits should be below `1e12`. The maximal supported trajectory duration is `7e3`, and you can [scale your input parameter](https://github.com/pantor/ruckig/issues/139#issuecomment-1280730316) to avoid that limitation. Note that Ruckig will also output values outside of this range, there is however no guarantee for correctness.
## Benchmark
We find that Ruckig is more than twice as fast as Reflexxes Type IV for state-to-state motions and well-suited for control cycles as low as 250 microseconds. The Ruckig *Community Version* is in general a more powerful and open-source alternative to the [Reflexxes Type IV](http://reflexxes.ws/) library. In fact, Ruckig is the first Type V trajectory generator for arbitrary target states and even supports directional velocity and acceleration limits, while also being faster on top.

For trajectories with intermediate waypoints, we compare Ruckig to [Toppra](https://github.com/hungpham2511/toppra), a state-of-the-art library for robotic motion planning. Ruckig is able to improve the trajectory duration on average by around 10%, as the path planning and time parametrization are calculated jointly. Moreover, Ruckig is real-time capable and supports jerk-constraints.

## Development
Ruckig is written in C++17. It is continuously tested on `ubuntu-latest`, `macos-latest`, and `windows-latest` against following versions
- Doctest v2.4 (only for testing)
- Pybind11 v2.9 (only for python wrapper)
If you still need to use C++11, you can patch the Ruckig *Community Version* by calling `bash scripts/patch-c++11.sh`. Note that this will result in a performance drop of a few percent. Moreover, the Python module is not supported.
## Used By
Ruckig is used by over hundred research labs, companies, and open-source projects worldwide, including:
- [MoveIt 2](https://moveit.ros.org) for trajectory generation.
- [CoppeliaSim](https://www.coppeliarobotics.com/) starting from version 4.3.
- [Fuzzy Logic Robotics](https://flr.io)
- [Gestalt Robotics](https://www.gestalt-robotics.com)
- [Struckig](https://github.com/stefanbesler/struckig), a port of Ruckig to Structered Text (ST - IEC61131-3) for usage on PLCs.
- [Frankx](https://github.com/pantor/frankx) for controlling the Franka Emika robot arm.
- and many others!
## Citation
```
@article{berscheid2021jerk,
title={Jerk-limited Real-time Trajectory Generation with Arbitrary Target States},
author={Berscheid, Lars and Kr{\"o}ger, Torsten},
journal={Robotics: Science and Systems XVII},
year={2021}
}
```
%prep
%autosetup -n ruckig-0.9.2
%build
%py3_build
%install
%py3_install
install -d -m755 %{buildroot}/%{_pkgdocdir}
if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
pushd %{buildroot}
if [ -d usr/lib ]; then
find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
fi
if [ -d usr/lib64 ]; then
find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
fi
if [ -d usr/bin ]; then
find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
fi
if [ -d usr/sbin ]; then
find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
fi
touch doclist.lst
if [ -d usr/share/man ]; then
find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
fi
popd
mv %{buildroot}/filelist.lst .
mv %{buildroot}/doclist.lst .
%files -n python3-ruckig -f filelist.lst
%dir %{python3_sitearch}/*
%files help -f doclist.lst
%{_docdir}/*
%changelog
* Wed May 10 2023 Python_Bot <Python_Bot@openeuler.org> - 0.9.2-1
- Package Spec generated
|