pantor / ruckig

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

Soft Terminal constrains? #170

Closed SinaMirrazavi closed 9 months ago

SinaMirrazavi commented 9 months ago

Hello,

Thx for the great package. I was wondering if it is possible to formulate the problem such that we could have a hard constraint on the duration of the motion but soft constraint on the terminal values (e.g. velocity/acceleration or even position)?

Best Regards, Sina

pantor commented 9 months ago

Hi Sina,

we do have the minimum_duration parameter in the InputParameter class. If the target velocity/acceleration is zero and the target is reachable within that duration, the trajectory duration will always be equal to the minimum_duration. With that, you should be able to implement your desired behavior easily.

Best, Lars

SinaMirrazavi commented 9 months ago

Hi Lars,

Thank you for your response. I appreciate your initial clarification regarding the minimum_duration parameter in the InputParameter class.

However, I still have some doubts about whether the proposed solution fully addresses my specific optimization problem. To provide further clarity, let me elaborate on my requirements:

I am dealing with a robot that has initial conditions denoted as P_0, V_0, and A_0. My goal is to reach a target state represented by P_1, V_1, and A_1, but this should occur precisely at a specified time T*. Importantly, there might be scenarios where T* is less than the minimum feasible motion duration for the given problem setup. So this problem by definition is infeasible.

In such cases, I am looking for a way to modify the problem to make it feasible while maintaining a certain level of flexibility. Specifically, I want to enforce a "hard" terminal constraint on the position, meaning that P(T*) = P_1 must be satisfied rigorously. However, I would like to treat the terminal constraints on velocity V(T*) = V_1 and acceleration A(T*) = A_1 as "soft" constraints, allowing some degree of flexibility.

My concern lies in the proposal to artificially set the target velocity and acceleration to zero. I am not fully sure if this new formulation will result in a shorter motion duration in general and also how the desired behavior could be driven from this?

Thx again, Sina

pantor commented 9 months ago

I see. This is indeed a much more complex problem, and my answer above is only for the trivial case where a solution with V_1 = A_1 = 0 exists. Some thoughts:

There exists a minimum time T_min for the time-optimal trajectory of each DoF to P_1 for any V_1, A_1. No solution T* < max(T_min) is possible. T_min is straight-forward to calculate by integrating with maximum limits.

There is the zero-solution from above with T_0 and V(T_0) = A(T_0) = 0. The problem becomes trivial for T* > max(T_0). T_0 is also straight-forward to compute.

There is also a time T_brake where we brake with maximum limits until we hit P_1. Between T_min < T* < min(T_brake), the problem should also become simple, because we can always brake & accelerate a bit to slow down the trajectory.

In between min(T_brake) < T* < max(T_0), things become more complex in particular for multiple DoFs. As the search-space is non-continuous and certain T might not be possible, I'd go for a heuristic-based search and guess V_1 and A_1 so that the trajectory with a minimum duration becomes `T`. For 6-7 DoFs, Ruckig can calculate the duration of a trajectory in around 1-3µs, so you can do a couple of iterations depending on your computation limits.

Or are you only interested in a single DoF?

SinaMirrazavi commented 9 months ago

Thank you so much for the elaborated answer, it was indeed helpful :) I am interested in multi-dof, between 6 to 10 dofs, may I ask if there is a built-in method for rucking to output the duration of a trajectory in 1-3 us? The method I have been using in pybind is

    # Calculate the trajectory in an offline manner
    result = otg.calculate(inp, trajectory)
    if result == Result.ErrorInvalidInput:
        raise Exception('Invalid input!')

    print(f'Trajectory duration: {trajectory.duration:0.4f} [s]')

which usually takes much longer, around 18 to 30us.

pantor commented 9 months ago

Hi Sina,

I just wanted to follow up on this in a DM, but couldn't find your email address. Feel free to reach out to me at info@ruckig.com. Thanks!

Lars