This guide helps you get started using online generated trajectories within your application. There is also a collection of examples that guide you through the most important features of Ruckig. A time-optimal trajectory for a single degree of freedom is shown in the figure below. We also added plots of the resulting trajectories for all examples. Let's get started!

Ruckig provides three main interface classes: the Ruckig, the InputParameter, and the OutputParameter class.
First, you'll need to create a Ruckig instance with the number of DoFs as a template parameter, and the control cycle (e.g. in seconds) in the constructor.
The input type has 3 blocks of data: the current state, the target state and the corresponding kinematic limits.
If you only want to have a acceleration-constrained trajectory, you can also omit the max_jerk as well as the current and target_acceleration value. Given all input and output resources, we can iterate over the trajectory at each discrete time step. For most applications, this loop must run within a real-time thread and controls the actual hardware.
Within the control loop, you need to update the current state of the input parameter according to the calculated trajectory. Therefore, the pass_to_input method copies the new kinematic state of the output to the current kinematic state of the input parameter. If (in the next step) the current state is not the expected, pre-calculated trajectory, Ruckig will calculate a new trajectory based on the novel input. When the trajectory has reached the target state, the update function will return Result::Finished.
The Ruckig Pro version allows fully local calclulation of trajectories. To allocate the necessary memory for a variable number of waypoints beforehand, we need to pass the maximum number of waypoints to Ruckig via
The InputParameter class takes the number of waypoints as an optional input, however usually you will fill in the values (and therefore reserve its memory) yourself. Then you're ready to set intermediate via points by
As soon as at least one intermediate positions is given, the Ruckig Community Version switches to the mentioned (of course, non real-time capable) cloud API. If you require real-time calculation on your own hardware, please contact us for the Ruckig Pro Version.
When using intermediate positions, both the underlying motion planning problem as well as its calculation changes significantly. In particular, there are some fundamental limitations for jerk-limited online trajectory generation regarding the usage of waypoints. Please find more information about these limitations here, and in general we recommend to use
to filter waypoints according to a (high) threshold distance. Setting interrupt_calculation_duration makes sure to be real-time capable by refining the solution in the next control invocation. Note that this is a soft interruption of the calculation. Currently, no minimum or discrete durations are supported when using intermediate positions.
To go into more detail, the InputParameter type has following members:
On top of the current state, target state, and constraints, Ruckig allows for a few more advanced settings:
ErrorInvalidInput result code. During the trajectory calculation, we then try to stay within the limits. However, in contrast to velocity-, acceleration-, or jerk-limits there is no strict guarantee that a solution within the positional limits exists even after checking the current and target state. In these (rare) cases, we return a ErrorPositionalLimits result code together with the invalid trajectory.per_section_max_velocity.We refer to the API documentation of the enumerations within the ruckig namespace for all available options.
To check that Ruckig is able to generate a trajectory before the actual calculation step,
throws an error with a detailed reason if an input is not valid. You can also set the default template parameter to false via ruckig.validate_input<false>(...) to just return a boolean true or false. The two boolean arguments check that the current or target state are within the limits. The check includes a typical catch of jerk-limited trajectory generation: When the current state is at maximal velocity, any positive acceleration will inevitable lead to a velocity violation at a future timestep. In general, this condition is fulfilled when
If both arguments are set to true, the calculated trajectory is guaranteed to be within the kinematic limits throughout its duration. Also, note that there are range constraints of the input due to numerical reasons, see below for more details.
The update function of the Ruckig class returns a Result type that indicates the current state of the algorithm. This can either be working, finished if the trajectory has finished, or an error type if something went wrong during calculation. The result type can be compared as a standard integer.
| State | Error Code |
|---|---|
| Working | 0 |
| Finished | 1 |
| Error | -1 |
| ErrorInvalidInput | -100 |
| ErrorTrajectoryDuration | -101 |
| ErrorPositionalLimits | -102 |
| ErrorExecutionTimeCalculation | -110 |
| ErrorSynchronizationCalculation | -111 |
The output class includes the new kinematic state and the overall trajectory.
Moreover, the trajectory class has a range of useful parameters and methods.
Again, we refer to the API documentation for the exact signatures.
Ruckig also supports an offline approach for calculating a 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
starting from the current output.time (currently Ruckig Pro only).
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
and set the current state as well as the kinematic constraints via
Then, we can track a signal in an online manner within the real-time control loop
The Trackig interface has two different modes: One optimized for higher quality tracking and one for faster computation time:
Please find a complete example here. This functionality can also be used in an offline manner, e.g. when the entire signal is known beforehand. Here, we call the
method with the trajectory given as a std::vector of target states. The Tracking interface is available in the Ruckig Pro version.
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:
This switches the default Vector from the std::array to the dynamic std::vector type. 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.
Ruckig supports custom vector types to make interfacing with your code even easier and more flexible. Most importantly, you can switch to Eigen Vectors simply by including Eigen (3.4 or later) before Ruckig
and then call the constructors with the ruckig::EigenVector parameter.
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 to the constructor. This template template parameter needs to fulfill a range of template arguments and methods:
Note that DynamicDOFs corresponds to DOFs = 0. We've included a range of examples for using Ruckig with (10) Eigen, (11) custom vector types, and (12) custom types with a dynamic number of DoFs.
You can find a list of all macro (preprocessor) flags in the utils.hpp header.
To use them, define the macros before including the Ruckig header files in your project: