Giter VIP home page Giter VIP logo

ruckig's Introduction

Ruckig

Instantaneous Motion Generation for Robots and Machines.

CI Issues Releases MIT

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, accepted for the Robotics: Science and Systems (RSS), 2021 conference.

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!

Trajectory Profile

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<6> ruckig {0.001}; // Number DoFs; control cycle in [s]

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

InputParameter<6> input; // Number DoFs
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<6> output; // Number DoFs

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.

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 now supports intermediate waypoints via a cloud API. 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<6> otg {0.001, 8};
InputParameter<6> input {8};
OutputParameter<6> output {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 via points by

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

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

input.intermediate_positions = otg.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:

using Vector = std::array<double, DOFs>; // By default

Vector current_position;
Vector current_velocity; // Initialized to zero
Vector current_acceleration; // Initialized to zero

std::vector<Vector> intermediate_positions; // (only in Pro Version)

Vector target_position;
Vector target_velocity; // Initialized to zero
Vector target_acceleration; // Initialized to zero

Vector max_velocity;
Vector max_acceleration;
Vector max_jerk; // Initialized to infinity

std::optional<Vector> min_velocity; // If not given, the negative maximum velocity will be used.
std::optional<Vector> min_acceleration; // If not given, the negative maximum acceleration will be used.

std::optional<Vector> min_position; // (only in Pro Version)
std::optional<Vector> max_position; // (only in Pro Version)

std::array<bool, DOFs> enabled; // Initialized to true
std::optional<double> minimum_duration;
std::optional<double> interrupt_calculation_duration; // [µs], (only in Pro Version)

ControlInterface control_interface; // The default position interface controls the full kinematic state.
Synchronization synchronization; // Synchronization behavior of multiple DoFs
DurationDiscretization duration_discretization; // Whether the duration should be a discrete multiple of the control cycle (off by default)

std::optional<Vector<ControlInterface>> per_dof_control_interface; // Sets the control interface for each DoF individually, overwrites global control_interface
std::optional<Vector<Synchronization>> per_dof_synchronization; // Sets the synchronization for each DoF individually, overwrites global synchronization

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 synchonization) 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<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

Abs(acceleration) <= Sqrt(2 * max_jerk * (max_velocity - Abs(velocity))).

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.

Result Type

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

Output Parameter

The output class includes the new kinematic state and the overall trajectory.

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.

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

Trackig<1> otg {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 += 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. 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 = 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:

Ruckig<DynamicDOFs> otg {6, 0.001};
InputParameter<DynamicDOFs> input {6};
OutputParameter<DynamicDOFs> output {6};

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.

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 simply by including Eigen (3.4 or later) before Ruckig

#include <Eigen/Core> // Version 3.4 or later
#include <ruckig/ruckig.hpp>

and then call the constructors with the ruckig::EigenVector parameter.

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 to the constructor. This template template parameter needs to fulfill a range of template arguments and methods:

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, (11) custom vector types, and (12) custom types with a dynamic number of DoFs.

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 1e9. The maximal supported trajectory duration is 7e3. Note that Ruckig will also output values outside of this range, there is however no guarantee for correctness.

The Ruckig Pro version has additional tools to increase the numerical range and improve reliability. For example, theposition_scale and time_scale parameter of the Calculator class change the internal representation of the input parameters.

Ruckig<1> otg;
// Works also for Trackig<1> otg;

otg.calculator.position_scale = 1e2;  // Scales all positions in the input parameters
otg.calculator.time_scale = 1e3;  // Scale all times in the input parameters

This way, you can easily achieve the requirements above even for very high jerk limits or very long trajectories. Note that the scale parameters don't effect the resulting trajectory - they are for internal calculation only.

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

Benchmark

For trajectories with intermediate waypoints, we compare Ruckig to 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.

Benchmark

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.12 (only for Python wrapper)

A C++11 and C++03 version of Ruckig is also available - please contact us if you're interested.

Used By

Ruckig is used by over hundred research labs, companies, and open-source projects worldwide, including:

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

ruckig's People

Contributors

gavanderhoorn avatar leibrandt-telos avatar lpdon avatar marcbone avatar mathisloge avatar mdhom avatar mosfet80 avatar pantor avatar seehma avatar stefanbesler avatar traversaro avatar v4hn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ruckig's Issues

Allow various numbers of DOFs using python bindings

Currently the python bindings hardcode the number of DOFs to 3. It is a template parameter in C++, so it does need to be set at compile time. I think it should be feasible to compile for various commonly used DOFs (maybe 1 through 10) and let python select which to use at runtime.

There's some details around how to implement this on the python side - i.e. would there be a dictionary of Ruckig/InputParameter/etc for all of the the implemented DOFs, so the user would use Ruckig[DOFs]? Or a factory function that creates a Ruckig instance for the number of DOFs? Or a wrapper for the Ruckig class that takes the number of DOFs as a parameter to the constructor, and internally uses the correct compiled Rucking C++ object.

I'm happy to implement if there is a good way to do this.

Set synchronization and interface for every DOF

Hi Pantor,

it would be nice to deactivate the synchronization for every DOF. It could be usefull for some applications.
Furthermore the same thing with the interface (velocity/position)-mode.
It would be very nice to synchronize for example one of the dofs with velocity and the others with time.

It's not for a "classic" robot application, but i have a lot of use cases where i could need something like this.

What do you think about that.

Thx and many greetings

Daniel

Is it a written error?

Hi, @pantor
Im reading the code, and find a strange thing.
In brake.cpp

const double t_to_v_max = a0/jMax + std::sqrt(a0*a0 + 2 * jMax * (v0 - vMax)) / std::abs(jMax);

This one line of code says that t_to_v_max is the time from v0 to vmax,
t_to_v_max = a0/jMax + std::sqrt(a0*a0 + 2 * jMax * (v0 - vMax)) / std::abs(jMax)
const double t_to_v_min = a0/jMax + std::sqrt(a0*a0 / 2 + jMax * (v0 - vMin)) / std::abs(jMax);

but the time from v0 to vmin, ‘t_to_v_min = a0/jMax + std::sqrt(a0*a0 / 2 + jMax * (v0 - vMin)) / std::abs(jMax)’,is it a written error?

Machine accuracy of used HW - PLC (question)

Hi,

sorry that i bother you with that again. I still have sometimes numeric issues on my realtime plc hw (Probably if the working trajectory is already time optimal and i do only small changes?)

In general it's working fine with a scaling of (factor 0.01).

But in an sensor application where i set cyclic new targetpositions, i often get "ErrorExecutionTimeCalculation"...

I calculated the machine accuracy with the following code. The Result of machEps is 1.0842021724855044E-19. Is it an indicator for you if theres a problem with the accuracy in general on my hw?

`double machEps = 1.0;

do
machEps /= 2.0;
while ((double) (1.0 + (machEps / 2.0)) != 1.0);`

Inverse s->time

Hello,
I have a use case where I need to find the time corresponding to a particular s . s the position variable.
Right now we have getState(time) --> position, but can we have findTime(position) --> time ?
Thanks !

Is position overshoot possible?

Is it possible that the trajectory returned by Ruckig will overshoot the target position P of a target state <p=P, v=0, a=0>?

My understanding from this Reflexxes paper, e.g. section IV.C, is that it is possible, at least in their approach.

If you have a moment to clarify my conceptual understanding, I much appreciate it!

Specific test case yields ErrorExecutionTimeCalculation

I'm trying to bring Ruckig into MoveIt but have had some trouble. Usually the first waypoint fails. I'll give a specific test case here.

The MoveIt PR is here and the Ruckig-related code is here.

A spreadsheet of the parameters that cause this failure is attached. Let me know if any more info is needed to reproduce the issue.

The failure code is -110 (ErrorExecutionTimeCalculation). Currently using the default Time synchronization (have also tried None) and Interface::Position (have also tried Velocity).

I've tried to manually check the input parameters and they seem fine to me ¯_(ツ)_/¯

On the bright side, I have seen a few successful calculations when the target vel/accel are very low.

ruckig_issue.ods

Target state is not reached exactly due to discrete cycle time

hi, I have a question, input parameters as below:

image
and target_velocity and target_acceleration is not zero. when reach the last cycle(time>duration) like described in the code
image
parametre output as below:
image
only target_acceleration is correct. I don't know if I understand it correctly, let me know.
thanks!

Wrong behaviour when changing max_velocity on the fly

Hi,

i was testing around with my python on the fly example (see open PR) and discovered the following behaviour:
image
What is happening: i start a trajectory with target_position=10 and max_velocity=3. After position is greater than 0.7, i update the trajectory with new InputParameters, where max_velocity=1. I would expect, that velocity goes directly down to 1, but instead (as you can see in the trace) the velocity "overshoots" the new target_velocity and goes below 1! I do not understand why it behaves like this, i'd expect it to move along the path painted in red.

I can even create a situation where something totally strange happens, the velocity actually changes its sign for some time (movement direction is reversed), which i think should not happen at all:
image

Can you help me with what i'm doing wrong here?

You can find the example source for that output here.

Python position_extrema seg fault

Hello again,

I tried out the python binding for Trajectory.position_extrema, and was getting a seg fault. I believe this was caused by 0 being passed in for DOFs for the binding, causing the Vector to be size 0. I think I fixed it here ljarin@6bf9303, but I didn't run your tests

RuntimeError: [ruckig] error in step 2 in dof: 0 for t sync: 1.403613 input

Hello, I encountered the following error when I used Ruckig to plan a trajectory. Can anyone help me with this problem?

RuntimeError: [ruckig] error in step 2 in dof: 0 for t sync: 1.403613 input:
inp.current_position = [0.01073568005271233, -0.7002627264230739, 0.08182424814164639, -2.453889055015553, -0.08363270962592464, 1.829417851685384, 0.7163509366199623]
inp.current_velocity = [0.05656281587106524, 1.011281770884991, 0.9677565166950226, 0.9125879855751985, -0.9937611499130723, 0.9963710898160936, -0.8048512544333941]
inp.current_acceleration = [-5.348847133445708, -3.400994300842285, -3.708171844482422, -3.951635360717773, 3.508039474487305, -3.532837390899658, 4.73619270324707]
inp.target_position = [0.0698, 0.6283, 0.6981000000000001, -2.1642, -0.733, 2.5482, 0.5061]
inp.target_velocity = [0, 0, 0, 0, 0, 0, 0]
inp.target_acceleration = [0, 0, 0, 0, 0, 0, 0]
inp.max_velocity = [1, 1, 1, 1, 1, 1, 1]
inp.max_acceleration = [7, 7, 7, 7, 7, 7, 7]
inp.max_jerk = [1000, 1000, 1000, 1000, 1000, 1000, 1000]

Thanks in advance.

Python Example

First of all, thank you very much for this work!

Second, I'm very interested in trying it on python as it would help prototyping but I'm not sure how to use it.
I've run cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_PYTHON_MODULE=ON .. and it seems building went well:

→ cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_PYTHON_MODULE=ON ..
-- The CXX compiler identification is GNU 10.2.1
-- Check for working CXX compiler: /usr/lib64/ccache/c++
-- Check for working CXX compiler: /usr/lib64/ccache/c++ - works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PythonInterp: /usr/bin/python (found version "3.8.7") 
-- Found PythonLibs: /usr/lib64/libpython3.8.so
-- Performing Test HAS_FLTO
-- Performing Test HAS_FLTO - Success
-- Found pybind11: /usr/include (found version "2.6.2" )
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/src/github/ruckig/build

→ make
Scanning dependencies of target ruckig
[  8%] Building CXX object CMakeFiles/ruckig.dir/src/brake.cpp.o
[ 16%] Building CXX object CMakeFiles/ruckig.dir/src/position1.cpp.o
[ 25%] Building CXX object CMakeFiles/ruckig.dir/src/position2.cpp.o
[ 33%] Building CXX object CMakeFiles/ruckig.dir/src/velocity1.cpp.o
[ 41%] Building CXX object CMakeFiles/ruckig.dir/src/velocity2.cpp.o
[ 50%] Linking CXX shared library libruckig.so
[ 50%] Built target ruckig
Scanning dependencies of target otg-test
[ 58%] Building CXX object CMakeFiles/otg-test.dir/test/otg-test.cpp.o
[ 66%] Linking CXX executable otg-test
[ 66%] Built target otg-test
Scanning dependencies of target _ruckig
[ 75%] Building CXX object CMakeFiles/_ruckig.dir/src/python.cpp.o
[ 83%] Linking CXX shared module _ruckig.cpython-38-x86_64-linux-gnu.so
[ 83%] Built target _ruckig
Scanning dependencies of target example-position
[ 91%] Building CXX object CMakeFiles/example-position.dir/examples/position.cpp.o
[100%] Linking CXX executable example-position
[100%] Built target example-position

Could you provide a minimal working example of how I would import and call the library?
I'm ok to work out the details with respect to the C++ API.

Trigger stop

What is the best way to trigger a stop profile. My use case is as follows

  • move 2 axes along a previously computed trajectory
  • the “machine” operator pushes a stop button
  • I want calculate smooth brake trajectory that stops the axes as fast as possible (max_velocity=X, max_acceleration=Y, target_velocity=0, target_acceleration=0)
  • In this case I do not care about the target_position at all, but I can not simply set target_position = current_position

Non-deterministic outputs based on scope of Ruckig data structure

I was testing out Ruckig (nice package BTW), and noticed that I get different results if I recreate the Ruckig data structure for each new problem to solve rather than overwriting the input/target positions, velocities, and accelerations. I'm sorry I can't be more help than that right now It's late here, and I wanted to file this before stopping for the day. I'm sure you could reproduce by running some predetermined set of inputs/outputs in a loop with the Ruckig data structure inside/outside of the loop.

For me, Its as simple as if the for loop below is at the bottom of the snipp or at the top, where I get different results on repeated solves.

   Ruckig<6> otg {0.001};
   InputParameter<6> input;
   OutputParameter<6> output;
   
   // Set input parameters
   input.max_velocity = maxVelocities;
   input.max_acceleration = maxAccelerations;
   input.max_jerk = max_joint_jerk_;

   for (std::size_t ii=0; ii < data.size(); ++ii) {

Bug for phase synchronization trajectory.

I found a bug when using the feature of phase synchronization. The output position of second axis changed from 0 to 200 in one control cycle.

Below is the test case I used:

    Ruckig<2> otg{0.004};
    InputParameter<2> input;
    OutputParameter<2> output;

    input.synchronization = Synchronization::Phase;
    input.duration_discretization = DurationDiscretization::Discrete;

    // Set input parameters
    input.max_velocity = { 1380, 1380 };
    input.max_acceleration = { 3588, 3588 };
    input.min_acceleration = { -6900, -6900 };
    input.max_jerk = { 12420, 12420 };

    input.current_position = { 0.0, 0.0 };
    input.current_velocity = { 0.0, 0.0 };
    input.current_acceleration = { 0.0, 0.0 };

    input.target_position = { 400, 200 };
    input.target_velocity = { 0.0, 0.0 };
    input.target_acceleration = { 0.0, 0.0 };

Figure_1

Question - inequality constraint on the zeroth derivative + polynomial degree

1- I'd like to kindly ask if I can impose and inequality constraint on the zeroth derivative with ruckig. Basically, what I am aiming to do is to prevent the position function to exceed certain value!
2- Would it be possible to increase the degree of the polynomial?
If there's an example that would be highly appreciated

Changing the constraints (ver_max, acc_max or jerk_max) to smaller value causes a suboptimal trajectory

If the contraints are changed online, then the trajectory is not optimal as it should be.
The following image shows the whole trajectory, at t = 2, max_velocity is reduces from 3 to 1, then the velocity goes to negative unexpectedly.
image

On the other hand, if the velocity constraints increases, everything seems to be fine.
image

You could reproduce with the following code:

import ruckig
from copy import copy
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np


def WalkThroughTrajectory(otg, in_param, T):
    dof = otg.degrees_of_freedom
    out_param: ruckig.OutputParameter = ruckig.OutputParameter(dof)
    first_output = None
    ts = []
    xs = []
    dxs = []
    ddxs = []

    t = 0
    res = ruckig.Result.Working
    while res == ruckig.Result.Working:
        res = otg.update(in_param, out_param)
        in_param.current_position = out_param.new_position
        in_param.current_velocity = out_param.new_velocity
        in_param.current_acceleration = out_param.new_acceleration

        ts.append(t)
        xs.append(out_param.new_position)
        dxs.append(out_param.new_velocity)
        ddxs.append(out_param.new_acceleration)
        t += T
        if t > 2 and t < 2 + t:
            in_param.max_velocity = np.asarray([1, 1, 1.]) * 1.

        if not first_output:
            first_output = copy(out_param)

    return first_output, ts, xs, dxs, ddxs


if __name__ == '__main__':
    dof = 3
    in_param = ruckig.InputParameter(dof)
    in_param.current_position = [0, 0, 0]
    in_param.current_velocity = [0., 0, 0]
    in_param.current_acceleration = [0, 0, 0]
    in_param.target_position = [10, 0, 0]
    in_param.target_velocity = [0, 0, 0]
    in_param.target_acceleration = [0, 0, 0]
    in_param.max_velocity = [3, 3, 3]
    in_param.max_acceleration = [5, 5, 5]
    in_param.max_jerk = [10, 10, 10]

    T = 0.004
    otg = ruckig.Ruckig(dof, T)
    # otg = ruckig.Smoothie(dof, T)
    # otg = ruckig.Quintic(dof, T)

    first_output, ts, xs, dxs, ddxs = WalkThroughTrajectory(otg, in_param, T)

    print(
        f'Calculation duration: {first_output.calculation_duration:0.1f} [µs]')
    print(f'Trajectory duration: {first_output.trajectory.duration:0.4f} [s]')

    shape = (2, 2)

    plt.subplots_adjust(hspace=1)
    plt.subplot2grid(shape, loc=(0, 0))
    plt.plot(ts, xs)
    plt.legend(['$D_%i$' % i for i in range(dof)])
    plt.title("$x(t)$")

    plt.subplot2grid(shape, loc=(0, 1))
    plt.plot(ts, dxs)
    plt.legend(['$D_%i$' % i for i in range(dof)])
    plt.title("$\dot x(t)$")

    plt.subplot2grid(shape, loc=(1, 0))
    plt.plot(ts, ddxs)
    plt.legend(['$D_%i$' % i for i in range(dof)])
    plt.title("$\ddot x(t)$")

    xs = np.asarray(xs)
    plt.subplot2grid(shape, loc=(1, 1), projection='3d')
    plt.plot(*xs.T[:2])
    plt.legend(['$D_%i$' % i for i in range(dof)])
    plt.title("$x_1 x_2 x_3$")

    plt.show()

Installation method for python bindings

Currently the bindings get built into a shared library, but that library doesn't end up anywhere that python expects it to be. There are various ways to handle this, each of which has tradeoffs. If there is one that is acceptable to @pantor , I'm happy to make a PR implementing it.

Here are the two options that come to mind:

  1. Use pybind_catkin to build the python bindings, and install with cmake's install macro. This would require building the package using catkin. That seems like a heavy dependency for non-ROS people, but I suspect it is possible to detect whether the user is in a ROS environment and only use catkin in that case. See example here:https://github.com/arturmiller/pybind11_examples/blob/master/function_call/CMakeLists.txt

  2. Add a setup.py and use setuptools to build the bindings. I'm not sure how this will integrate with the cmake process, but there may be a way to hack it to work. Documentation on how to build pybind11 bindings with setuptools: https://pybind11.readthedocs.io/en/stable/compiling.html#building-with-setuptools

There are probably other ways that I don't know about. In general I'm building ruckig with my own code and other 3rd party libraries, and modifying sys.path within my scripts seems a bit hacky. I usually use catkin to handle this, but I realize not everyone wants that as a dependency.

/cc @gavanderhoorn

How to check position extrema with new input parameters while ruckig is working

Hi Pantor,

i want to check the position extrema with new input parameters, while ruckig ist working and velocity & acceleration is not zero.
If there is a position limit fault, ruckig should ignore the new parameters.
How can i handle that? To get the limits, we have to call

"otg.update(input, output);" and then
"output.trajectory.get_position_extrema()" i think.

Then ruckig is working and i cant't abort that.

No fixed control cycle

Hey,
i want to use your library in a non-realtime environment, so i need to get the status of the trajectory at points with flexible distance in time to each other. I am not sure how to use your (python-)library here. I could imagine that using the Trajectory.at_time i could accomplish this, but then i am not sure how to implement changes in target_position, target_velocity on the fly.
My thoughts would generate something like that:

  1. run update on Ruckig instance once with the target values of the beginning
  2. cyclically run at_time as long as target values haven't changed
  3. whenever target values change, run update once
  4. proceed with step 2

Could you give me a little hint how to setup this best?
Thanks!

New target during trajectory generation gets ignored

Hi,

Right now, if the target is changed when update returns both Result::Working and Result::Finished, it gets ignored. It seems the generator keeps tracking the first target given.
Is this the expected behavior ? How can I generate a trajectory to a new target when the previous target is reached or close to be reached ?

Feature: Constrained trajectory or additional intermediate target poses

Hey,
I'm currently working on an application, in which the robot-arm moves around a point, always pointing towards it.
So I need to constraint the trajectory in every step. For me the constraint would be that the orientation of the end-effector is pointing towards this certain point. Do you think it's possible to add like a constraint function to the input parameters?

Another more relaxed idea is to define several intermediate target poses in the input parameters.
I don't want the trajectory to stop at these point just to fly by.

What do you think would be the complexity to add these features? Which parts should I look at?
However I really want to thank you for your work.
Best regards,
Peter

Preprint version of the paper

Hi,

Thanks for this wonderful package. I would like to ask if there is plan to release a preprint version of the academic paper, to popular preprint website like https://arxiv.org ? It would be really helpful for us researchers to understand the technique, and also cite the paper in our research before it is officially published :)

Best Regards,
mq

Benchmark

Hey @pantor

Sorry to bother you with that … I am just implementing a benchmark for my port of rucking to TwinCAT / Codesys. At the moment the performance of the port is slower by a factor of 4, which is the order of magnitude of “worse performance” that I expected (actually I thought it is about a factor 10, haha). Since this is before doing any performance optimization in the port, I am pretty happy with this … I am using the stack way to much right now, which in TwinCAT is pretty bad usually.

Anyway, at the moment I am benchmarking on a virtual machine, which of course is not great for your implementation nor the port. However, since I have core isolation in the VM the jitter I get for the port is still okayish (worst duration for 7 DoF is around 600+/-200us). Because of my setup with the VM the C++ implemention is doing much, much worse in regard to worst-mean duration right now (talking about 15ms +/- 10ms).

In your opinion, is it enough to compare the implementations on a physical pc? Did you run the benchmark on a Standard PC with vanilla Linux/Windows or did you use any kind of RT patch, process priorization, core Isolation (…) to reduce jitter?

trajectory.hpp

Hi,

I just cloned the newest repository because of the dynamic-DoFs input option. Thanks for that.
My previous cloned repository had no compile problems so far except editing some include path for linux:
#include <experimental/optional>

At the moment i just get one compile error.

At line 160 of trajectory.hpp :

any_interval |= t_min.has_value();

I get compile error :
‘class std::experimental::fundamentals_v1::optional’ has no member named ‘has_value’

Could i replace the current text with :
bool val=0;
if(t_min.value()>0){
val=1;
}
any_interval |= val;

Thanks.

P.s. i like your coding style. Only thing is, i never used template classes. Is it possible for you to avoid this setup?
Or do i just need to understand this?

Expression for array subscript out of range

I found an expression when using ruckig. My platform is VS2017 and it run in debug mode.

The lines caused the expression are:

for (size_t i = 0; p.t_brakes[i] > 0 && i < 2; ++i) {
p.p_brakes[i] = p0s[dof];
p.v_brakes[i] = v0s[dof];
p.a_brakes[i] = a0s[dof];
std::tie(p0s[dof], v0s[dof], a0s[dof]) = Profile::integrate(p.t_brakes[i], p0s[dof], v0s[dof], a0s[dof], p.j_brakes[i]);
}

In my opinion, i < 2 should check before p.t_brakes[i] since p.t_brakes[i] is a array of size 2.

Below is the test case I used:

    Ruckig<6> otg{ 0.001 };
    InputParameter<6> input;
    OutputParameter<6> output;

    // Set input parameters
    input.max_velocity = { 1.2, 1.2, 1.2, 0.6, 0.6, 0.6 };
    input.max_acceleration = { 4.0, 4.0, 4.0, 1.5, 1.5, 1.5 };
    input.max_jerk = { 100.0, 100.0, 100.0, 40.0, 40.0, 40.0 };

    input.current_position = { 0.0, -0.1, 0.12, 0.0, 0.3, 0.05 };
    input.current_velocity = { 2., 0.0, 0.2, 0.0, 0.0, 0.0 };
    input.current_acceleration = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };

    input.target_position = { 10.0, 0.52, 0.55, 0.0, -0.13, 0.24 };
    input.target_velocity = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
    input.target_acceleration = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };

Looking forward to your reply!

at_time feature in python

Hi, and thanks for your library!! I am having trouble getting a sample from the trajectory at a specific time, and wanted to ask if I am using the interface correctly. This is an example of how I am calling the library. Thanks in advance.

from ruckig import InputParameter, OutputParameter, Result, Ruckig
import numpy as np

num_dims = 2
start_state = [1, 1, 1, 1, 1, 1]
end_state = [2, 2, 2, 2, 2, 2]
max_state = [100, 100, 100, 100]
t = .3

inp = InputParameter(num_dims)
inp.current_position = start_state[:num_dims]
inp.current_velocity = start_state[num_dims:2 * num_dims]
inp.current_acceleration = start_state[2*num_dims:3 * num_dims]

inp.target_position = end_state[:num_dims]
inp.target_velocity = end_state[num_dims:2 * num_dims]
inp.target_acceleration = end_state[2*num_dims:3 * num_dims]

inp.max_velocity = np.repeat(max_state[1], num_dims)
inp.max_acceleration = np.repeat(max_state[2], num_dims)
inp.max_jerk = np.repeat(max_state[3], num_dims)

ruckig = Ruckig(num_dims, 0.05)
out = OutputParameter(num_dims)
res = ruckig.update(inp, out)
print(res)

output = OutputParameter(num_dims)
out.trajectory.at_time(t, output.new_position, output.new_velocity, output.new_acceleration)
print(output.new_position) # These are all 0
print(output.new_velocity)
print(output.new_acceleration)

Question regarding waypoints/intermediate points

Hi,
First of all: thanks for your work. I am trying to use it to generate trajectories following a previously planned path with respect to velocity, acceleration and jerk constraints in C++. I was wondering if ruckig allows to travel over intermediate waypoints without needing to provide accelerations/velocities for each point. Looking at the "test/otg_multiple.py" it seems that it needs to know the the velocities and accelerations for each waypoint.. Is there any way around that?
Thanks!

How to use Ruckig in C++11

I want to use Ruckig in C++11,and when i build the package,some error occurs.Here are some questions and solutions.

I've done the following:

  1. Using std::optional in a C++11 context:use this header: optional .It is the equivalent of std::optional.When I finished this, it don 't make any mistakes about "std::optional"

  2. lambda auto parameters.

    auto idx_min_it = std::min_element(valid_profiles.cbegin(), valid_profiles.cbegin() + valid_profile_counter, [](auto& a, auto& b) { return a.t_sum[6] + a.t_brake.value_or(0.0) < b.t_sum[6] + b.t_brake.value_or(0.0); });

    I replaced [](auto& a, auto& b)with [](const Profile& a, const Profile& b), and it successfully passed.

If it have any unknown questions and hidden errors, please let me know.Thx!

Not time-optimal result

hi, i compare ruckig and TopiCo, when the condition is below:

Snipaste_2021-07-22_13-38-16

the result is like this:

image

image

obviously, Acceleration is different, and TopiCo is better, is more time saving. I want to know if rucig can do this and how to do ?
thanks!

ErrorExecutionTimeCalculation (-110) errors due to numerical issues

Hi, @pantor

I'm testing Ruckig in a 6 dof robot motion planning, and in this situation the input.target_position and current_position is automatically calculated. I found an extremel case where the current and target position are all zero or infinitely close to zero, and in the case

if (std::abs(pf - p0) < DBL_EPSILON && std::abs(v0) < DBL_EPSILON && std::abs(vf) < DBL_EPSILON && std::abs(a0) < DBL_EPSILON && std::abs(af) < DBL_EPSILON) {

time_none(profile, _vMax, _aMax, _aMin, _jMax);

time_none(profile, _vMax, _aMax, _aMin, _jMax); will execute.
And due to the numerical issue, the current and target position are all zero or infinitely close to zero but in C++ it can be turned into something like this

8335e2119a5583d705af7893ba0a537

pd = pf - p0;

the pd will be less than zero and in function PositionStep1::time_none(), profile.t[0] = std::cbrt(pd / 2*jMax) also will be less than zero so that the -110 error occurs.

Maybe (also in position-step2.cpp)

pd = pf - p0;
can be replaced by

if (std::fabs(pf - p0) < DBL_EPSILON)
{
    pd = 0;
}
else
{
    pd = pf - p0;
}

When I did that, the -110 error didn't happen anymore. If I think wrong, please correct.

Status of Paths in Ruckig?

Sort-of a follow-up to #7: what's the status of ruckig@path?

Not looking for constraint support (as I agree that seems out-of-scope for Ruckig), but processing a path instead of a segment would be very convenient (and the blend distance is really icing on the cake).

Note: I'm certainly not complaining this is not already supported. Ruckig has been splendid so far, so 👍 and my thanks. Just curious whether that branch has been left behind or not :)

No trajectory - (Reached target position in -9.25596e+61 [s].)

There is no trajectory with these input parameters (for example):

Ruckig<1> otg {0.001};
InputParameter<1> input;
OutputParameter<1> output;

// Set input parameters
input.max_velocity = {2000};
input.max_acceleration = {18000};
input.max_jerk = { 190000};

input.current_position = {100};
input.current_velocity = {0};
input.current_acceleration = {0};

input.target_position = { 1000};
input.target_velocity = {0.0};
input.target_acceleration = {0.0};

Numerical issue on PLC (Velocity Mode -> "ErrorSynchronizationCalculation")

Hi Pantor,

with the following Parameters i got an "ErrorSynchronizationCalculation" on my PLC Hardware as in issue #54. But this case is in velocity mode "input.interface = ruckig::Interface::Velocity". The movement should stop..
`
Ruckig<4> otg {0.002};
InputParameter<4> input;
OutputParameter<4> output;
// Set input parameters
input.max_velocity = { 1752, 1593, 1734, 131};
input.max_acceleration = { 17520, 17520, 1738, 1738};
input.max_jerk = { 175204, 175204, 26006, 17383};


input.current_position      = {357.23, 406.96, 0.01, -8.38};
input.current_velocity      = {-1244, -1228, 0.0, -17.01};
input.current_acceleration  = {11816, 11298, 0.0, 0.0};

input.target_position       = {300, 349, 0.01, -10}; //doesnt't matter in velocity-mode
input.target_velocity       = {0.0, 0.0, 0.0, 0.0};
input.target_acceleration   = {0.0, 0.0, 0.0, 0.0};
input.interface             = ruckig::Interface::Velocity;

`
I changed the threshold in the marked line to 1e-10 and it works fine.

grafik

Python bindings function PerDOF::append returns pointer to temporary variable data

I'm trying to play with the library on windows using the bindings for python.
Building was straightforward, but executing examples/position.py, I ran into this error message:
"ImporteError: generic_type: cannot initialize type "": an object with that name"

It ended up being the following function:

template<size_t MAX>
struct PerDOF {
    static const char* append(std::string name, size_t DOFs) {
        return (name.append(std::to_string(DOFs))).c_str();
    }
//...
};

as you can see the variable name is temporary, and the function returns a pointer to its internal storage, that is temporary too, and it get deallocated by the time it gets used.

Bug in found_time_synchronization evaluation

Hi,

I am just integrating some of your commit into the TwinCAT port I am working on. I noticed that the signature of the check Method changed (see b61e999), but is not used correctly in the following code segment

 switch (p.jerk_signs) {
  case Profile::JerkSigns::UDDU: {
      if (!p.check<Profile::JerkSigns::UDDU, Profile::Limits::NONE>(t_profile, new_max_jerk[dof], new_max_velocity[dof], new_max_acceleration[dof], new_min_acceleration[dof])) {
          found_time_synchronization = false;
      }
  } break;
  case Profile::JerkSigns::UDUD: {
      if (!p.check<Profile::JerkSigns::UDUD, Profile::Limits::NONE>(t_profile, new_max_jerk[dof], new_max_velocity[dof], new_max_acceleration[dof], new_min_acceleration[dof])) {
          found_time_synchronization = false;
      }
  } break;
}

I think after new_max_velocity[dof] there should be a parameter vor the new minimum velocity instead of new_max_acceleration, or am I missing something here?

Template makes it difficult to use Ruckig as a class member

I tried to use Ruckig as a class member like this:

std::unique_ptr<ruckig::Ruckig<6 /* num dof */>> ruckig_;

A challenge is, I don't know the "num dof" beforehand. So I had to hard-code it to 6 for now. Could you refactor this somehow so that the constructor takes "num_dof" as an argument?

This issue could make it hard to use Rucking in MoveIt where all numbers of DOF are possible.

Unexpected behavior of `output` when `update` returns `Result::Finished`

Thanks for the great library, I've been enjoying working with it.

I got bit today by some behavior that may be intended, but was surprising to me. I had a loop that looked something like the following:

while (...) {
  if (has_new_setpoint) {
    input.target_position = new_setpoint;
  }
  auto result =  otg.update(input, output);
  if(result == Result::Working || result == result::Done) {
    input.current_position = output.new_position;
    //...
  }  
}

I eventually realized that output.new_position is uninitialized or in an undefined state when result == result::Done. Perhaps this behavior could be documented, or enforced with a runtime error. Or perhaps output's fields should hold meaningful values when result == result::Done.

Recommendations for "position only" robots

This is not really an issue with Ruckig per se, but more a usage question. Seeing as you don't have discussions enabled on this repository, I'm posting it as an issue.

Many (industrial) robots do not provide any state output except their current position, and sometimes even that with (quite) some delay.

What would be your recommendation for Ruckig usage with such robots: simply use derivatives to obtain velocity and acceleration, using full loop-back and 'forwarding' the output.new_position to the real system, a hybrid, something else?

I'd be interested to know what you feel would give the best performance -- or perhaps, less problems :)

Odd trajectory output when used for path following

I've written a path following algorithm around Ruckig to control a robot through a number of waypoints (position, velocity, acceleration) and Ruckig will occasionally give me a suboptimal trajectory that oscillates about the goal position before continuing on course.

Some background: I load Ruckig with the robots initial position (say 0,0 for a 2 DOF), then the target position is loaded with the first waypoint. I iterate ruckig with input=output and target constant until ruckig returns Finished, then I load the next waypoint (input is equal to the last waypoint) and keep on trucking. I've brought plots (position, velocity, acceleration):
vscale-0 8-axis-1
vscale-0 8-axis-2

The second tracks nicely, however the first axis seems to create a sinusoidal trajectory. One thing I've noticed is that the undesirable response comes when I set the planner to use significant amounts of the robot's velocity limit (0.8 in the above example). The same trajectory with a velocity scaling of 0.61 generates a nice trajectory, as seen in the following plots:
vscale-0 61-axis-1
vscale-0 61-axis-2

What can I do to avoid this response? Am I using Ruckig incorrectly, or perhaps is there a bug that I can work around or fix?

I have uploaded the code used to create these trajectories to my area here on github:
https://github.com/BryanStuurman/ruckig_work/blob/main/trajectory.py

pip install fails on Windows

Hey folks,

i am trying to install the python package in my Windows Terminal. When running pip3 install ruckig, the following log occurs:

Collecting ruckig
  Using cached ruckig-0.3.0.tar.gz (7.5 kB)
Using legacy 'setup.py install' for ruckig, since package 'wheel' is not installed.
Installing collected packages: ruckig
    Running setup.py install for ruckig ... error
    ERROR: Command errored out with exit status 1:
     command: 'C:\Users\xxx\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\python.exe' -u -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'C:\\Users\\xxx\\AppData\\Local\\Temp\\pip-install-yl3t984s\\ruckig_dfe9442aa6d744e48538d343aaff7e3c\\setup.py'"'"'; __file__='"'"'C:\\Users\\xxx\\AppData\\Local\\Temp\\pip-install-yl3t984s\\ruckig_dfe9442aa6d744e48538d343aaff7e3c\\setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record 'C:\Users\xxx\AppData\Local\Temp\pip-record-78ac38vs\install-record.txt' --single-version-externally-managed --user --prefix= --compile --install-headers 'C:\Users\xxx\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\Include\ruckig'
         cwd: C:\Users\xxx\AppData\Local\Temp\pip-install-yl3t984s\ruckig_dfe9442aa6d744e48538d343aaff7e3c\
    Complete output (38 lines):
    running install
    running build
    running build_ext
    CMake Error: The source directory "C:/Users/xxx/AppData/Local/Temp/pip-install-yl3t984s/ruckig_dfe9442aa6d744e48538d343aaff7e3c" does not appear to contain CMakeLists.txt.
    Specify --help for usage, or press the help button on the CMake GUI.
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\Users\xxx\AppData\Local\Temp\pip-install-yl3t984s\ruckig_dfe9442aa6d744e48538d343aaff7e3c\setup.py", line 65, in <module>
        setup(
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1520.0_x64__qbz5n2kfra8p0\lib\site-packages\setuptools\__init__.py", line 153, in setup
        return distutils.core.setup(**attrs)
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1520.0_x64__qbz5n2kfra8p0\lib\distutils\core.py", line 148, in setup
        dist.run_commands()
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1520.0_x64__qbz5n2kfra8p0\lib\distutils\dist.py", line 966, in run_commands
        self.run_command(cmd)
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1520.0_x64__qbz5n2kfra8p0\lib\distutils\dist.py", line 985, in run_command
        cmd_obj.run()
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1520.0_x64__qbz5n2kfra8p0\lib\site-packages\setuptools\command\install.py", line 61, in run
        return orig.install.run(self)
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1520.0_x64__qbz5n2kfra8p0\lib\distutils\command\install.py", line 546, in run
        self.run_command('build')
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1520.0_x64__qbz5n2kfra8p0\lib\distutils\cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1520.0_x64__qbz5n2kfra8p0\lib\distutils\dist.py", line 985, in run_command
        cmd_obj.run()
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1520.0_x64__qbz5n2kfra8p0\lib\distutils\command\build.py", line 135, in run
        self.run_command(cmd_name)
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1520.0_x64__qbz5n2kfra8p0\lib\distutils\cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1520.0_x64__qbz5n2kfra8p0\lib\distutils\dist.py", line 985, in run_command
        cmd_obj.run()
      File "C:\Users\xxx\AppData\Local\Temp\pip-install-yl3t984s\ruckig_dfe9442aa6d744e48538d343aaff7e3c\setup.py", line 36, in run
        self.build_extension(ext)
      File "C:\Users\xxx\AppData\Local\Temp\pip-install-yl3t984s\ruckig_dfe9442aa6d744e48538d343aaff7e3c\setup.py", line 61, in build_extension
        subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, cwd=self.build_temp)
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1520.0_x64__qbz5n2kfra8p0\lib\subprocess.py", line 373, in check_call
        raise CalledProcessError(retcode, cmd)
    subprocess.CalledProcessError: Command '['cmake', 'C:\\Users\\xxx\\AppData\\Local\\Temp\\pip-install-yl3t984s\\ruckig_dfe9442aa6d744e48538d343aaff7e3c', '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=C:\\Users\\xxx\\AppData\\Local\\Temp\\pip-install-yl3t984s\\ruckig_dfe9442aa6d744e48538d343aaff7e3c\\build\\lib.win-amd64-3.9\\', '-DPYTHON_EXECUTABLE=C:\\Users\\xxx\\AppData\\Local\\Microsoft\\WindowsApps\\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\\python.exe', '-DEXAMPLE_VERSION_INFO=0.3.0', '-DCMAKE_BUILD_TYPE=Release', '-DBUILD_PYTHON_MODULE=ON', '-DBUILD_SHARED_LIBS=OFF', '-DCMAKE_POSITION_INDEPENDENT_CODE=ON']' returned non-zero exit status 1.
    ----------------------------------------
ERROR: Command errored out with exit status 1: 'C:\Users\xxx\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\python.exe' -u -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'C:\\Users\\xxx\\AppData\\Local\\Temp\\pip-install-yl3t984s\\ruckig_dfe9442aa6d744e48538d343aaff7e3c\\setup.py'"'"'; __file__='"'"'C:\\Users\\xxx\\AppData\\Local\\Temp\\pip-install-yl3t984s\\ruckig_dfe9442aa6d744e48538d343aaff7e3c\\setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record 'C:\Users\xxx\AppData\Local\Temp\pip-record-78ac38vs\install-record.txt' --single-version-externally-managed --user --prefix= --compile --install-headers 'C:\Users\xxx\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\Include\ruckig' Check the logs for full command output.

I previously ran pip3 install cmake because it was complaining that there was no cmake.

Thanks for your help!

Edit just checked: same behaviour in my Debian WSL

Understanding ErrorExecutionTimeCalculation (-110) errors

I'm using Ruckig in a 6-DOF visual servoing application, updating input.target_position at a rate similar to the control cycle.
I find that often when setpoints (updates to target_position) are quite close to each other, Ruckig will return a -110 status. Can you help me understand what causes this error? Are there any workarounds you'd suggest? Thank you.

Numerical issue on plc

Hi Pantor,

i had an issue with some trajectories with higher jerks >100000. (If you need the parameters, tell me)
=> ruckig::Result::ErrorExecutionTimeCalculation

But only on the PLC with GCC 6.3.0... In Visual Studio everything works fine...

This issue appeared in "PositionStep1::time_vel".
The "profile.check" caused this fault in the marked line on the following picture.

grafik

I changed the value to 1e-8, after that it's working fine.
What does ist mean "This is not really needed..."?

Is it ok to change this value?

thx

Daniel

Issue with cpp11 patch

Visual Studio tells me that

"[[maybe_unused]]"
for example in the following line

inline bool check([[maybe_unused]] double tf, double jf, double vMax, double vMin, double aMax, double aMin) {

ist not available for cpp11. Or is it my fault?

Extract version from package manifest (where possible)

With #10, you got one more additional file to update when releasing new versions.

70bc57c shows you now have to edit 4 files to do a simple increment.

In other packages, we've managed to reduce it to just updating package.xml, with things like CMakeLists.txt and setup.py parsing it out of the manifest.

For a CMake example: ros-industrial/abb_robot_driver/abb_egm_hardware_interface/CMakeLists.txt (parsing the name might be a bit much/unneeded in this case).

setup.py would be similar (parse it out using lxml or similar).

That's all still ROS-agnostic btw, so it wouldn't affect non-ROS users.

Long times with jerks

In my testing of Ruckig, I've seen correct values for trajectory times when I have jerk set to something really large, like 1e9, but in many cases anything less, the trajectory times that come out of Ruckig seem very high. I created a little example program that perhaps you could look at and maybe I'm just use Rucking incorrectly (please ignore the otg interval time -- the results are the same with a small interval and a loop on otg.update(), but I was trying for speed with this).

Here is the code:

#include <iostream>

#include <ruckig/ruckig.hpp>

using namespace ruckig;

int main() {
    // Create instances: the ruckig otg as well as input and output parameters
    Ruckig<6> otg {10000};
    InputParameter<6> input;
    OutputParameter<6> output;

    // Set input parameters
    input.max_velocity.fill(5);
    input.max_acceleration.fill(10);

    input.current_position.fill(0);
    input.current_velocity.fill(0);
    input.current_acceleration.fill(0);

    input.target_position.fill(0);
    input.target_velocity.fill(0);
    input.target_acceleration.fill(0);

    input.target_position[2]=2.46012;
    input.target_velocity[2]=-1.17513;
    input.target_acceleration[2]=-8.76144;

    for (std::size_t jj=500; jj >= 100; --jj) {
    
      input.current_position[2]=2.46374;
      input.current_velocity[2]=-1.14621;
      input.current_acceleration[2]=-9.79698;
      
      input.max_jerk.fill(jj);
    
      // Generate trajectory
      if (otg.update(input, output) < 0) {
        std::cerr << "ERROR on jerk "<<jj<<"\n";
      } else {     
        std::cout << "For jerk "<<jj<<".  Reached target position in " << output.trajectory.get_duration() << " [s]." << std::endl;
      }
    }
}

The results show that with high jerk > 350 rad/sec^3, the results are what I expect (and can validate with other software) for "near infinite" jerk. But notice the huge jump from the smoothly increasing times as jerk is lowered at jerk==335. There is a huge jump. The delta acceleration here is 1.03554 (with is starting and ending in the same direction as velocity, which has a delta of -0.02892 rad/sec and a positional change around -4mm). So I can't for the life of me figure out why a jerk of 335 would increase the total trajectory time from ~3ms to >0.5 seconds. Any help you can provide on this is appreciated.

For jerk 500.  Reached target position in 0.00311789 [s].
For jerk 499.  Reached target position in 0.00311789 [s].
For jerk 498.  Reached target position in 0.00311789 [s].
For jerk 497.  Reached target position in 0.00311789 [s].
For jerk 496.  Reached target position in 0.00311789 [s].
For jerk 495.  Reached target position in 0.00311789 [s].
For jerk 494.  Reached target position in 0.0031179 [s].
For jerk 493.  Reached target position in 0.0031179 [s].
For jerk 492.  Reached target position in 0.0031179 [s].
For jerk 491.  Reached target position in 0.0031179 [s].
For jerk 490.  Reached target position in 0.0031179 [s].
For jerk 489.  Reached target position in 0.0031179 [s].
For jerk 488.  Reached target position in 0.0031179 [s].
For jerk 487.  Reached target position in 0.0031179 [s].
For jerk 486.  Reached target position in 0.00311791 [s].
For jerk 485.  Reached target position in 0.00311791 [s].
For jerk 484.  Reached target position in 0.00311791 [s].
For jerk 483.  Reached target position in 0.00311791 [s].
For jerk 482.  Reached target position in 0.00311791 [s].
For jerk 481.  Reached target position in 0.00311791 [s].
For jerk 480.  Reached target position in 0.00311791 [s].
For jerk 479.  Reached target position in 0.00311792 [s].
For jerk 478.  Reached target position in 0.00311792 [s].
For jerk 477.  Reached target position in 0.00311792 [s].
For jerk 476.  Reached target position in 0.00311792 [s].
For jerk 475.  Reached target position in 0.00311792 [s].
For jerk 474.  Reached target position in 0.00311792 [s].
For jerk 473.  Reached target position in 0.00311792 [s].
For jerk 472.  Reached target position in 0.00311793 [s].
For jerk 471.  Reached target position in 0.00311793 [s].
For jerk 470.  Reached target position in 0.00311793 [s].
For jerk 469.  Reached target position in 0.00311793 [s].
For jerk 468.  Reached target position in 0.00311793 [s].
For jerk 467.  Reached target position in 0.00311793 [s].
For jerk 466.  Reached target position in 0.00311793 [s].
For jerk 465.  Reached target position in 0.00311794 [s].
For jerk 464.  Reached target position in 0.00311794 [s].
For jerk 463.  Reached target position in 0.00311794 [s].
For jerk 462.  Reached target position in 0.00311794 [s].
For jerk 461.  Reached target position in 0.00311794 [s].
For jerk 460.  Reached target position in 0.00311794 [s].
For jerk 459.  Reached target position in 0.00311794 [s].
For jerk 458.  Reached target position in 0.00311795 [s].
For jerk 457.  Reached target position in 0.00311795 [s].
For jerk 456.  Reached target position in 0.00311795 [s].
For jerk 455.  Reached target position in 0.00311795 [s].
For jerk 454.  Reached target position in 0.00311795 [s].
For jerk 453.  Reached target position in 0.00311795 [s].
For jerk 452.  Reached target position in 0.00311795 [s].
For jerk 451.  Reached target position in 0.00311796 [s].
For jerk 450.  Reached target position in 0.00311796 [s].
For jerk 449.  Reached target position in 0.00311796 [s].
For jerk 448.  Reached target position in 0.00311796 [s].
For jerk 447.  Reached target position in 0.00311796 [s].
For jerk 446.  Reached target position in 0.00311796 [s].
For jerk 445.  Reached target position in 0.00311796 [s].
For jerk 444.  Reached target position in 0.00311797 [s].
For jerk 443.  Reached target position in 0.00311797 [s].
For jerk 442.  Reached target position in 0.00311797 [s].
For jerk 441.  Reached target position in 0.00311797 [s].
For jerk 440.  Reached target position in 0.00311797 [s].
For jerk 439.  Reached target position in 0.00311797 [s].
For jerk 438.  Reached target position in 0.00311798 [s].
For jerk 437.  Reached target position in 0.00311798 [s].
For jerk 436.  Reached target position in 0.00311798 [s].
For jerk 435.  Reached target position in 0.00311798 [s].
For jerk 434.  Reached target position in 0.00311798 [s].
For jerk 433.  Reached target position in 0.00311798 [s].
For jerk 432.  Reached target position in 0.00311798 [s].
For jerk 431.  Reached target position in 0.00311799 [s].
For jerk 430.  Reached target position in 0.00311799 [s].
For jerk 429.  Reached target position in 0.00311799 [s].
For jerk 428.  Reached target position in 0.00311799 [s].
For jerk 427.  Reached target position in 0.00311799 [s].
For jerk 426.  Reached target position in 0.00311799 [s].
For jerk 425.  Reached target position in 0.003118 [s].
For jerk 424.  Reached target position in 0.003118 [s].
For jerk 423.  Reached target position in 0.003118 [s].
For jerk 422.  Reached target position in 0.003118 [s].
For jerk 421.  Reached target position in 0.003118 [s].
For jerk 420.  Reached target position in 0.003118 [s].
For jerk 419.  Reached target position in 0.003118 [s].
For jerk 418.  Reached target position in 0.00311801 [s].
For jerk 417.  Reached target position in 0.00311801 [s].
For jerk 416.  Reached target position in 0.00311801 [s].
For jerk 415.  Reached target position in 0.00311801 [s].
For jerk 414.  Reached target position in 0.00311801 [s].
For jerk 413.  Reached target position in 0.00311801 [s].
For jerk 412.  Reached target position in 0.00311802 [s].
For jerk 411.  Reached target position in 0.00311802 [s].
For jerk 410.  Reached target position in 0.00311802 [s].
For jerk 409.  Reached target position in 0.00311802 [s].
For jerk 408.  Reached target position in 0.00311802 [s].
For jerk 407.  Reached target position in 0.00311802 [s].
For jerk 406.  Reached target position in 0.00311803 [s].
For jerk 405.  Reached target position in 0.00311803 [s].
For jerk 404.  Reached target position in 0.00311803 [s].
For jerk 403.  Reached target position in 0.00311803 [s].
For jerk 402.  Reached target position in 0.00311803 [s].
For jerk 401.  Reached target position in 0.00311803 [s].
For jerk 400.  Reached target position in 0.00311804 [s].
For jerk 399.  Reached target position in 0.00311804 [s].
For jerk 398.  Reached target position in 0.00311804 [s].
For jerk 397.  Reached target position in 0.00311804 [s].
For jerk 396.  Reached target position in 0.00311804 [s].
For jerk 395.  Reached target position in 0.00311804 [s].
For jerk 394.  Reached target position in 0.00311805 [s].
For jerk 393.  Reached target position in 0.00311805 [s].
For jerk 392.  Reached target position in 0.00311805 [s].
For jerk 391.  Reached target position in 0.00311805 [s].
For jerk 390.  Reached target position in 0.00311805 [s].
For jerk 389.  Reached target position in 0.00311805 [s].
For jerk 388.  Reached target position in 0.00311806 [s].
For jerk 387.  Reached target position in 0.00311806 [s].
For jerk 386.  Reached target position in 0.00311806 [s].
For jerk 385.  Reached target position in 0.00311806 [s].
For jerk 384.  Reached target position in 0.00311806 [s].
For jerk 383.  Reached target position in 0.00311807 [s].
For jerk 382.  Reached target position in 0.00311807 [s].
For jerk 381.  Reached target position in 0.00311807 [s].
For jerk 380.  Reached target position in 0.00311807 [s].
For jerk 379.  Reached target position in 0.00311807 [s].
For jerk 378.  Reached target position in 0.00311807 [s].
For jerk 377.  Reached target position in 0.00311808 [s].
For jerk 376.  Reached target position in 0.00311808 [s].
For jerk 375.  Reached target position in 0.00311808 [s].
For jerk 374.  Reached target position in 0.00311808 [s].
For jerk 373.  Reached target position in 0.00311808 [s].
For jerk 372.  Reached target position in 0.00311809 [s].
For jerk 371.  Reached target position in 0.00311809 [s].
For jerk 370.  Reached target position in 0.00311809 [s].
For jerk 369.  Reached target position in 0.00311809 [s].
For jerk 368.  Reached target position in 0.00311809 [s].
For jerk 367.  Reached target position in 0.00311809 [s].
For jerk 366.  Reached target position in 0.0031181 [s].
For jerk 365.  Reached target position in 0.0031181 [s].
For jerk 364.  Reached target position in 0.0031181 [s].
For jerk 363.  Reached target position in 0.0031181 [s].
For jerk 362.  Reached target position in 0.0031181 [s].
For jerk 361.  Reached target position in 0.00311811 [s].
For jerk 360.  Reached target position in 0.00311811 [s].
For jerk 359.  Reached target position in 0.00311811 [s].
For jerk 358.  Reached target position in 0.00311811 [s].
For jerk 357.  Reached target position in 0.00311811 [s].
For jerk 356.  Reached target position in 0.00311812 [s].
For jerk 355.  Reached target position in 0.00311812 [s].
For jerk 354.  Reached target position in 0.00311812 [s].
For jerk 353.  Reached target position in 0.00311812 [s].
For jerk 352.  Reached target position in 0.00311812 [s].
For jerk 351.  Reached target position in 0.00311813 [s].
For jerk 350.  Reached target position in 0.00311813 [s].
For jerk 349.  Reached target position in 0.00311813 [s].
For jerk 348.  Reached target position in 0.00311813 [s].
For jerk 347.  Reached target position in 0.00311813 [s].
For jerk 346.  Reached target position in 0.00311814 [s].
For jerk 345.  Reached target position in 0.00311814 [s].
For jerk 344.  Reached target position in 0.00311814 [s].
For jerk 343.  Reached target position in 0.00311814 [s].
For jerk 342.  Reached target position in 0.00311814 [s].
For jerk 341.  Reached target position in 0.00311815 [s].
For jerk 340.  Reached target position in 0.00311815 [s].
For jerk 339.  Reached target position in 0.00311815 [s].
For jerk 338.  Reached target position in 0.00311815 [s].
For jerk 337.  Reached target position in 0.00311815 [s].
For jerk 336.  Reached target position in 0.00311816 [s].
For jerk 335.  Reached target position in 0.5786 [s].
For jerk 334.  Reached target position in 0.578951 [s].
For jerk 333.  Reached target position in 0.579305 [s].
For jerk 332.  Reached target position in 0.57966 [s].
For jerk 331.  Reached target position in 0.580018 [s].
For jerk 330.  Reached target position in 0.580378 [s].
For jerk 329.  Reached target position in 0.580741 [s].
For jerk 328.  Reached target position in 0.581105 [s].
For jerk 327.  Reached target position in 0.581472 [s].
For jerk 326.  Reached target position in 0.581841 [s].
For jerk 325.  Reached target position in 0.582212 [s].
For jerk 324.  Reached target position in 0.582586 [s].
For jerk 323.  Reached target position in 0.582961 [s].
For jerk 322.  Reached target position in 0.583339 [s].
For jerk 321.  Reached target position in 0.58372 [s].
For jerk 320.  Reached target position in 0.584103 [s].
For jerk 319.  Reached target position in 0.584488 [s].
For jerk 318.  Reached target position in 0.584876 [s].
For jerk 317.  Reached target position in 0.585266 [s].
For jerk 316.  Reached target position in 0.585659 [s].
For jerk 315.  Reached target position in 0.586054 [s].
For jerk 314.  Reached target position in 0.586451 [s].
For jerk 313.  Reached target position in 0.586852 [s].
For jerk 312.  Reached target position in 0.587254 [s].
For jerk 311.  Reached target position in 0.58766 [s].
For jerk 310.  Reached target position in 0.588068 [s].
For jerk 309.  Reached target position in 0.588478 [s].
For jerk 308.  Reached target position in 0.588891 [s].
For jerk 307.  Reached target position in 0.589307 [s].
For jerk 306.  Reached target position in 0.589726 [s].
For jerk 305.  Reached target position in 0.590147 [s].
For jerk 304.  Reached target position in 0.590571 [s].
For jerk 303.  Reached target position in 0.590998 [s].
For jerk 302.  Reached target position in 0.591428 [s].
For jerk 301.  Reached target position in 0.591861 [s].
For jerk 300.  Reached target position in 0.592296 [s].
For jerk 299.  Reached target position in 0.592735 [s].
For jerk 298.  Reached target position in 0.593176 [s].
For jerk 297.  Reached target position in 0.593621 [s].
For jerk 296.  Reached target position in 0.594068 [s].
For jerk 295.  Reached target position in 0.594518 [s].
For jerk 294.  Reached target position in 0.594972 [s].
For jerk 293.  Reached target position in 0.595428 [s].
For jerk 292.  Reached target position in 0.595888 [s].
For jerk 291.  Reached target position in 0.596351 [s].
For jerk 290.  Reached target position in 0.596817 [s].
For jerk 289.  Reached target position in 0.597286 [s].
For jerk 288.  Reached target position in 0.597759 [s].
For jerk 287.  Reached target position in 0.598234 [s].
For jerk 286.  Reached target position in 0.598713 [s].
For jerk 285.  Reached target position in 0.599196 [s].
For jerk 284.  Reached target position in 0.599682 [s].
For jerk 283.  Reached target position in 0.600171 [s].
For jerk 282.  Reached target position in 0.600664 [s].
For jerk 281.  Reached target position in 0.60116 [s].
For jerk 280.  Reached target position in 0.60166 [s].
For jerk 279.  Reached target position in 0.602163 [s].
For jerk 278.  Reached target position in 0.60267 [s].
For jerk 277.  Reached target position in 0.603181 [s].
For jerk 276.  Reached target position in 0.603695 [s].
For jerk 275.  Reached target position in 0.604214 [s].
For jerk 274.  Reached target position in 0.604735 [s].
For jerk 273.  Reached target position in 0.605261 [s].
For jerk 272.  Reached target position in 0.605791 [s].
For jerk 271.  Reached target position in 0.606324 [s].
For jerk 270.  Reached target position in 0.606862 [s].
For jerk 269.  Reached target position in 0.607403 [s].
For jerk 268.  Reached target position in 0.607949 [s].
For jerk 267.  Reached target position in 0.608498 [s].
For jerk 266.  Reached target position in 0.609052 [s].
For jerk 265.  Reached target position in 0.60961 [s].
For jerk 264.  Reached target position in 0.610172 [s].
For jerk 263.  Reached target position in 0.610738 [s].
For jerk 262.  Reached target position in 0.611309 [s].
For jerk 261.  Reached target position in 0.611884 [s].
For jerk 260.  Reached target position in 0.612464 [s].
For jerk 259.  Reached target position in 0.613047 [s].
For jerk 258.  Reached target position in 0.613636 [s].
For jerk 257.  Reached target position in 0.614229 [s].
For jerk 256.  Reached target position in 0.614827 [s].
For jerk 255.  Reached target position in 0.615429 [s].
For jerk 254.  Reached target position in 0.616036 [s].
For jerk 253.  Reached target position in 0.616648 [s].
For jerk 252.  Reached target position in 0.617265 [s].
For jerk 251.  Reached target position in 0.617887 [s].
For jerk 250.  Reached target position in 0.618513 [s].
For jerk 249.  Reached target position in 0.619145 [s].
For jerk 248.  Reached target position in 0.619782 [s].
For jerk 247.  Reached target position in 0.620424 [s].
For jerk 246.  Reached target position in 0.621071 [s].
For jerk 245.  Reached target position in 0.621723 [s].
For jerk 244.  Reached target position in 0.622381 [s].
For jerk 243.  Reached target position in 0.623044 [s].
For jerk 242.  Reached target position in 0.623713 [s].
For jerk 241.  Reached target position in 0.624387 [s].
For jerk 240.  Reached target position in 0.625067 [s].
For jerk 239.  Reached target position in 0.625753 [s].
For jerk 238.  Reached target position in 0.626444 [s].
For jerk 237.  Reached target position in 0.627141 [s].
For jerk 236.  Reached target position in 0.627844 [s].
For jerk 235.  Reached target position in 0.628553 [s].
For jerk 234.  Reached target position in 0.629268 [s].
For jerk 233.  Reached target position in 0.629989 [s].
For jerk 232.  Reached target position in 0.630717 [s].
For jerk 231.  Reached target position in 0.63145 [s].
For jerk 230.  Reached target position in 0.63219 [s].
For jerk 229.  Reached target position in 0.632937 [s].
For jerk 228.  Reached target position in 0.63369 [s].
For jerk 227.  Reached target position in 0.63445 [s].
For jerk 226.  Reached target position in 0.635216 [s].
For jerk 225.  Reached target position in 0.635989 [s].
For jerk 224.  Reached target position in 0.63677 [s].
For jerk 223.  Reached target position in 0.637557 [s].
For jerk 222.  Reached target position in 0.638351 [s].
For jerk 221.  Reached target position in 0.639152 [s].
For jerk 220.  Reached target position in 0.639961 [s].
For jerk 219.  Reached target position in 0.640777 [s].
For jerk 218.  Reached target position in 0.641601 [s].
For jerk 217.  Reached target position in 0.642432 [s].
For jerk 216.  Reached target position in 0.643271 [s].
For jerk 215.  Reached target position in 0.644117 [s].
For jerk 214.  Reached target position in 0.644972 [s].
For jerk 213.  Reached target position in 0.645835 [s].
For jerk 212.  Reached target position in 0.646705 [s].
For jerk 211.  Reached target position in 0.647584 [s].
For jerk 210.  Reached target position in 0.648472 [s].
For jerk 209.  Reached target position in 0.649367 [s].
For jerk 208.  Reached target position in 0.650272 [s].
For jerk 207.  Reached target position in 0.651185 [s].
For jerk 206.  Reached target position in 0.652107 [s].
For jerk 205.  Reached target position in 0.653038 [s].
For jerk 204.  Reached target position in 0.653978 [s].
For jerk 203.  Reached target position in 0.654928 [s].
For jerk 202.  Reached target position in 0.655887 [s].
For jerk 201.  Reached target position in 0.656855 [s].
For jerk 200.  Reached target position in 0.657833 [s].
For jerk 199.  Reached target position in 0.658821 [s].
For jerk 198.  Reached target position in 0.659819 [s].
For jerk 197.  Reached target position in 0.660827 [s].
For jerk 196.  Reached target position in 0.661845 [s].
For jerk 195.  Reached target position in 0.662873 [s].
For jerk 194.  Reached target position in 0.663913 [s].
For jerk 193.  Reached target position in 0.664963 [s].
For jerk 192.  Reached target position in 0.666024 [s].
For jerk 191.  Reached target position in 0.667096 [s].
For jerk 190.  Reached target position in 0.668179 [s].
For jerk 189.  Reached target position in 0.669274 [s].
For jerk 188.  Reached target position in 0.67038 [s].
For jerk 187.  Reached target position in 0.671499 [s].
For jerk 186.  Reached target position in 0.672629 [s].
For jerk 185.  Reached target position in 0.673772 [s].
For jerk 184.  Reached target position in 0.674927 [s].
For jerk 183.  Reached target position in 0.676094 [s].
For jerk 182.  Reached target position in 0.677274 [s].
For jerk 181.  Reached target position in 0.678468 [s].
For jerk 180.  Reached target position in 0.679675 [s].
For jerk 179.  Reached target position in 0.680895 [s].
For jerk 178.  Reached target position in 0.682129 [s].
For jerk 177.  Reached target position in 0.683376 [s].
For jerk 176.  Reached target position in 0.684638 [s].
For jerk 175.  Reached target position in 0.685915 [s].
For jerk 174.  Reached target position in 0.687206 [s].
For jerk 173.  Reached target position in 0.688512 [s].
For jerk 172.  Reached target position in 0.689833 [s].
For jerk 171.  Reached target position in 0.691169 [s].
For jerk 170.  Reached target position in 0.692522 [s].
For jerk 169.  Reached target position in 0.69389 [s].
For jerk 168.  Reached target position in 0.695275 [s].
For jerk 167.  Reached target position in 0.696676 [s].
For jerk 166.  Reached target position in 0.698094 [s].
For jerk 165.  Reached target position in 0.699529 [s].
For jerk 164.  Reached target position in 0.700982 [s].
For jerk 163.  Reached target position in 0.702452 [s].
For jerk 162.  Reached target position in 0.703941 [s].
For jerk 161.  Reached target position in 0.705448 [s].
For jerk 160.  Reached target position in 0.706974 [s].
For jerk 159.  Reached target position in 0.70852 [s].
For jerk 158.  Reached target position in 0.710084 [s].
For jerk 157.  Reached target position in 0.711669 [s].
For jerk 156.  Reached target position in 0.713274 [s].
For jerk 155.  Reached target position in 0.7149 [s].
For jerk 154.  Reached target position in 0.716546 [s].
For jerk 153.  Reached target position in 0.718215 [s].
For jerk 152.  Reached target position in 0.719905 [s].
For jerk 151.  Reached target position in 0.721618 [s].
For jerk 150.  Reached target position in 0.723353 [s].
For jerk 149.  Reached target position in 0.725112 [s].
For jerk 148.  Reached target position in 0.726894 [s].
For jerk 147.  Reached target position in 0.728701 [s].
For jerk 146.  Reached target position in 0.730533 [s].
For jerk 145.  Reached target position in 0.732389 [s].
For jerk 144.  Reached target position in 0.734272 [s].
For jerk 143.  Reached target position in 0.736181 [s].
For jerk 142.  Reached target position in 0.738116 [s].
For jerk 141.  Reached target position in 0.74008 [s].
For jerk 140.  Reached target position in 0.742071 [s].
For jerk 139.  Reached target position in 0.744091 [s].
For jerk 138.  Reached target position in 0.74614 [s].
For jerk 137.  Reached target position in 0.748219 [s].
For jerk 136.  Reached target position in 0.750328 [s].
For jerk 135.  Reached target position in 0.752469 [s].
For jerk 134.  Reached target position in 0.754642 [s].
For jerk 133.  Reached target position in 0.756847 [s].
For jerk 132.  Reached target position in 0.759086 [s].
For jerk 131.  Reached target position in 0.761359 [s].
For jerk 130.  Reached target position in 0.763667 [s].
For jerk 129.  Reached target position in 0.766011 [s].
For jerk 128.  Reached target position in 0.768391 [s].
For jerk 127.  Reached target position in 0.770809 [s].
For jerk 126.  Reached target position in 0.773265 [s].
For jerk 125.  Reached target position in 0.77576 [s].
For jerk 124.  Reached target position in 0.778296 [s].
For jerk 123.  Reached target position in 0.780873 [s].
For jerk 122.  Reached target position in 0.783492 [s].
For jerk 121.  Reached target position in 0.786154 [s].
For jerk 120.  Reached target position in 0.788861 [s].
For jerk 119.  Reached target position in 0.791613 [s].
For jerk 118.  Reached target position in 0.794412 [s].
For jerk 117.  Reached target position in 0.797259 [s].
For jerk 116.  Reached target position in 0.800154 [s].
For jerk 115.  Reached target position in 0.803101 [s].
For jerk 114.  Reached target position in 0.806098 [s].
For jerk 113.  Reached target position in 0.809149 [s].
For jerk 112.  Reached target position in 0.812254 [s].
For jerk 111.  Reached target position in 0.815415 [s].
For jerk 110.  Reached target position in 0.818634 [s].
For jerk 109.  Reached target position in 0.821912 [s].
For jerk 108.  Reached target position in 0.82525 [s].
For jerk 107.  Reached target position in 0.828651 [s].
For jerk 106.  Reached target position in 0.832116 [s].
For jerk 105.  Reached target position in 0.835646 [s].
For jerk 104.  Reached target position in 0.839245 [s].
For jerk 103.  Reached target position in 0.842914 [s].
For jerk 102.  Reached target position in 0.846654 [s].
For jerk 101.  Reached target position in 0.850469 [s].
For jerk 100.  Reached target position in 0.854359 [s].

Soft Constraints

Regarding #17 and #44, we should introduce an option to interpret the kinematic constraints as "soft" ones. Then, we don't want to get within the kinematic constraints as fast as possible, but to avoid overshooting the limits.

This requires to disable the braking trajectory and to add the UDUD profiles in step 1. I'm not yet sure how to guarantee a solution in this case.

Ruckig fails with lower CutOff Frequencies

My goal is to integrate Ruckig into our research software, which controls our Franka Panda.

Using the default cutoff frequency (franka::kDefaultCutoffFrequency = 100.0) everything works fine and dandy.

However, using a lower cutoff frequency results in a franka::CommandException:

Motion finished commanded, but the robot is still moving! [joint_motion_generator_velocity_discontinuity, joint_motion_generator_acceleration_discontinuity]

Can we somehow account for the cut off frequency in ruckig?
Is there something I am missing?

P.S.: My motion generator is heavily based on "frankx::motion_joint_generator";

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.