Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
R

ruckig

> 编程语言
Open source

Motion Generation for Robots and Machines. Real-time. Jerk-constrained. Time-optimal.

1.3K stars0 likes0 views
WebsiteGitHub

About

Motion Generation for Robots and Machines. Real-time. Jerk-constrained. Time-optimal.

Ruckig generates trajectories on-the-fly, allowing robots and machines to react instantaneously to sensor input. Ruckig calculates a trajectory to a target waypoint (with position, velocity, and acceleration) starting from any initial state limited by velocity, acceleration, and jerk constraints. Besides the target state, Ruckig allows to define intermediate positions for waypoint following. For state-to-state motions, Ruckig guarantees a time-optimal solution. With intermediate waypoints, Ruckig calculates the path and its time parametrization jointly, resulting in significantly faster trajectories compared to traditional methods.

More information can be found at ruckig.com and in the corresponding paper Jerk-limited Real-time Trajectory Generation with Arbitrary Target States. Documentation is published at docs.ruckig.com.

Installation

Ruckig has no dependencies (except for testing). To build Ruckig using CMake, just run

mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make

To install Ruckig in a system-wide directory, you can either use (sudo) make install or install it as debian package using cpack by running

cpack
sudo dpkg -i ruckig*.deb

An example of using Ruckig in your CMake project is given by examples/CMakeLists.txt. However, you can also include Ruckig as a directory within your project and call add_subdirectory(ruckig) in your parent CMakeLists.txt.

Ruckig is also available as a Python module, in particular for development or debugging purposes. The Ruckig Community Version can be installed from PyPI via

pip install ruckig

When using CMake, the Python module can be built using the BUILD_PYTHON_MODULE flag. If you're only interested in the Python module (and not in the C++ library), you can build and install Ruckig via pip install ..

Tutorial

Furthermore, we will explain the basics to get started with 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!

Waypoint-based Trajectory Generation

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.

Ruckig ruckig {6, 0.001}; // Degrees of freedom; control cycle in [s]

The input type has 3 blocks of data: the current state, the target state and the corresponding kinematic limits.

InputParameter input {6}; // Degrees of freedom
input.current_position = {0.2, ...};
input.current_velocity = {0.1, ...};
input.current_acceleration = {0.1, ...};
input.target_position = {0.5, ...};
input.target_velocity = {-0.1, ...};
input.target_acceleration = {0.2, ...};
input.max_velocity = {0.4, ...};
input.max_acceleration = {1.0, ...};
input.max_jerk = {4.0, ...};

OutputParameter output {6}; // Degrees of freedom

If you only want to have an 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.

while (ruckig.update(input, output) == Result::Working) {
  // Make use of the new state here!
  // e.g. robot->setJointPositions(output.new_position);

  output.pass_to_input(input); // Don't forget this!
}

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.

Intermediate Waypoints

The Ruckig Community Version includes built-in support for intermediate waypoints, using our cloud API for remote calculation. Of course, the Ruckig Pro version is fully local. To allocate the necessary memory for a variable number of waypoints beforehand, we need to pass the maximum number of waypoints to Ruckig via

Ruckig ruckig {6, 0.001, 8};
InputParameter input {6, 8};
OutputParameter output {6, 8};

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 waypoints by

input.intermediate_positions = {
  {0.2, ...},
  {0.8, ...},
};

As soon as intermediate positions are 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

input.intermediate_positions = ruckig.filter_intermediate_positions(input.intermediate_positions, {0.1, ...});

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.

Input Parameter

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:

  • A minimum velocity and acceleration can be specified - these should be a negative number. If they are not given, the negative maximum velocity or acceleration will be used (similar to the jerk limit). For example, this might be useful in human robot collaboration settings with a different velocity limit towards a human. Or, when switching between different moving coordinate frames like picking from a conveyer belt.
  • You can overwrite the global kinematic limits to specify limits for each section between two waypoints separately by using e.g. per_section_max_velocity.
  • If a DoF is not enabled, it will be ignored in the calculation. Ruckig will output a trajectory with constant acceleration for those DoFs.
  • A minimum duration can be optionally given. Note that Ruckig can not guarantee an exact, but only a minimum duration of the trajectory.
  • The control interface (position or velocity control) can be switched easily. For example, a stop trajectory or visual servoing can be easily implemented with the velocity interface.
  • Different synchronization behaviors (i.a. phase, time, or no synchronization) are implemented. Phase synchronization results in straight-line motions.
  • The trajectory duration might be constrained to a multiple of the control cycle. This way, the exact state can be reached at a control loop execution.

We refer to the API documentation of the enumerations within the ruckig namespace for all available options.

Input Validation

To check that Ruckig is able to generate a trajectory before the actual calculation step,

ruckig.validate_input(input, check_current_state_within_limits=false, check_target_state_within_limits=true);
// returns true or throws

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(...) 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 inevitably lead to a velocity violation at a future timestep. In general, this condition is fulfilled when

Abs(acceleration)  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
void get_position_extrema(Vector& position_extrema); // Passes information about the position extrema and their times

Again, we refer to the API documentation for the exact signatures.

Offline Calculation

Ruckig also supports an offline approach for calculating a trajectory:

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

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 straightforward 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

Trackig trackig {1, 0.01};  // control cycle

and set the current state as well as the kinematic constraints via

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

for (double t = 0; t < 10.0; t += trackig.delta_time) {
  auto target_state = signal(t); // signal returns position, velocity, and acceleration
  auto res = trackig.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. This functionality can also be used in an offline manner, e.g. when the entire signal is known beforehand. Here, we call the

smooth_trajectory = trackig.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.

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

GitHub Issues· 0 open

View all on GitHub

No open issues yet, or sync has not completed.

Highlights

  • •You can overwrite the global kinematic limits to specify limits for each section between two waypoints separately by using e.g. per_section_max_velocity.
  • •If a DoF is not *enabled*, it will be ignored in the calculation. Ruckig will output a trajectory with constant acceleration for those DoFs.
  • •A *minimum duration* can be optionally given. Note that Ruckig can not guarantee an exact, but only a minimum duration of the trajectory.
  • •Different synchronization behaviors (i.a. phase, time, or no synchronization) are implemented. Phase synchronization results in straight-line motions.
  • •The trajectory duration might be constrained to a multiple of the control cycle. This way, the *exact* state can be reached at a control loop execution.

> Tags

C++jerk-constrainedmotion-planningoptimal-controlrobot-arm

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言