pantor / ruckig

Motion Generation for Robots and Machines. Real-time. Jerk-constrained. Time-optimal.
https://ruckig.com
MIT License
640 stars 155 forks source link

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

Closed Danielxyz123 closed 2 years ago

Danielxyz123 commented 2 years ago

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.

pantor commented 2 years ago

You could use an offline approach by creating a secondary Ruckig instance:

Trajectory<3> traj;
Ruckig<3> otg;
otg.calculate(input, traj);
traj.get_position_extrema();
Danielxyz123 commented 2 years ago

Ok thx, it's working fine. But isn't it the doubled workload?

Danielxyz123 commented 2 years ago

Hi Pantor

After some tests. I'm confused.

The workload isn't as higher as with one instance... Is it a fault in my testprogramm or is there a explanation for that? I've thought that the complete trajectories have to be calculated again from the second instance... So, wheres the fault in my mind?

Furthermore, when could a overshoot appear? I tested some on the fly changes, very close to the end of the trajectories. I changed the targetposition of only one of four dof. Then the axis where i was supposed to get an overshoot went to the target unsychronized. (Better than an overshoot).

But i have seen already overshoots in such situations, so when could this happen?

pantor commented 2 years ago

When creating a secondary Ruckig instance, you could switch to the new instance when checking for position limits was successful. Otherwise you can keep the old instance running, this way you should have as little overhead as possible. Moreover keep in mind that calculating a trajectory is quite fast with around 15µs for 7DoF on my hardware. So I think any doubled overhead will be negligible.

What do you mean by overshooting exactly? Ruckig gives you a time-optimal trajectory to a state including target velocity and acceleration, so it does not overshoot from a control point of view. However when the current trajectory is already (or near) time-optimal, a small change in the target state might lead to a completely different trajectory. This might even be caused by numeric issues - however this is inherent to the time-optimal trajectory generation problem.

The unsynchronized behaviour smells like a bug, can you give the exact InputParameter for that?

Danielxyz123 commented 2 years ago

Hi Pantor,

i've thought about the same practice, but could't detect a higher workload?!... (cyclic change of targetpositions)... Yes the performance of Ruckig is pretty good (!), but most of the PLCs are not that fast as a pc. It takes about 20% workload while calculating 4Dof with cyclic changes in 2ms.

I mean a position overshoot ( Dof >= 2) in case of position changes while ruckig is working. I change only the target positon of one dof(1) for example. The other dof(2) has to be in the end "breaking phase". So, what should the trajectory dof(2) without position change do, to enlarge the movement time? And sure, it is already a time optimal trajectory of dof(2).

Currently i can't reproduce an position overshoot, but the code below shows the unsychronized stop. The unsynchronized behave is good, otherwise there should be an position overshoot oder a reverse movement, or?

`#include

include <ruckig/ruckig.hpp>

using namespace ruckig;

int main() { // Create instances: the ruckig otg as well as input and output parameters Ruckig<2> otg{ 0.002 }; InputParameter<2> input; OutputParameter<2> output; // Set input parameters input.max_velocity = { 300, 300}; input.max_acceleration = { 100, 100 }; input.max_jerk = { 200000, 200000 };

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

input.target_position = { 50, 50 };
input.target_velocity = { 0.0, 0.0 };
input.target_acceleration = { 0.0, 0.0 };

input.enabled = { true,true };

// Generate trajectory
std::cout << "t | p1 | p2 " << std::endl;
while (otg.update(input, output) == Result::Working) {
    otg.update(input, output);

    auto& p = output.new_position;
    auto& v = output.new_velocity;
    auto& a = output.new_acceleration;
    std::cout << "p: " << output.time << " " << p[0] << " " << p[1] << std::endl;
    std::cout << "v: " << output.time << " " << v[0] << " " << v[1] << std::endl;
    std::cout << "a: " << output.time << " " << a[0] << " " << a[1] << std::endl;

    input.current_position = output.new_position;
    input.current_velocity = output.new_velocity;
    input.current_acceleration = output.new_acceleration;

    if (p[0] > 30)
    {
        input.target_position = { 100, 50 };
    }
}

std::cout << "Reached target position in " << output.trajectory.get_duration() << " [s]." << std::endl;

} `

pantor commented 2 years ago

I see. From this perspective, Ruckig might "overshoot" for a non-limiting DoF. In general, Ruckig tries to calculate trajectories for synchronization that minimize the velocity, although this is currently not a strict guarantee. Nonetheless, your case would be a valid trajectory, so I'll close this issue for now.

Danielxyz123 commented 2 years ago

ok thx. But what does „non limiting DoF“ mean.

pantor commented 2 years ago

There is always a limiting axis / DoF that determines the overall trajectory duration. In most cases, this is the slowest DoF. All other DoFs are non-limiting.