bioptim icon indicating copy to clipboard operation
bioptim copied to clipboard

create an example of single shooting - parametric optim

Open mickaelbegon opened this issue 2 years ago • 1 comments

idea: Implement single shooting parametric approach of Yeadon as an example that use no control and

nshooting = 1 integrator RK4 with several steps control = none params = transition time and value for quintic splines (idem with quartic spline of Bessonnet.)

e.g. 3 phases for 1 DoF params = [t1, t2, t3, Q1, Q2, Q3]

warning: in case of yeadon's quintic function qdot=0 at start and end

params of quintic function give the kinematic q, qdot and qddot of joints. root integrated according to free-fall acceleration driven equations:

\begin{aligned}
     \begin{pmatrix} \qddot_B \\ \qddot_J \end{pmatrix} = f_{\text{full,fd}}(\states,\controls)
     = &
      M(\q)^{-1} \left(\begin{pmatrix} \bm{0} \\ \btau_J \end{pmatrix}  -  N(\q,\qdot)\right) \\
     = &
    \begin{bmatrix} M_{BB}(\q) & M_{BJ}(\q)\\ M_{JB}(\q) & M_{JJ}(\q) \end{bmatrix}^{-1}
    \begin{pmatrix} \bm{0}-N_B(\q,\qdot) \\ \btau_J -  N_J(\q,\qdot)\end{pmatrix},
\end{aligned}

where $M(\q)$ is the mass matrix, $N(\q,\qdot)$ is the nonlinear effects vector and gravity effects, and $\btau_J$ are the joint torques. With this equation, states are $\states=[\q_B ; \q_J ; \qdot_B ; \qdot_J]^\top$ and controls are $\controls=\btau_J$. The reduced equation of motion, namely FFBD is:

\begin{equation}
     \qddot_B
     = f_{\text{base,fd}}(\states,\controls)
     = -M_{BB}(\q)^{-1} \; \left( M_{BJ}(\q) \; \qddot_J + N_B(\q, \qdot)\right),
\end{equation}

with $\states=[\q_B ; \q_J ; \qdot_B ; \qdot_J]^\top$ and controls $\controls=\qddot_J$.

Find a way to avoid if loop to generate the kinematics: trajectory is the sum of n quintic functions but all but one are zeros according to t.

T = [0] + param[:nb_phases] for in range(nb_phases): add = t > T[i] && t < T[i+1] ... qd[joint] += add* (Qi + tp3 * tp2)

#quintic polynomial of Yeadon.

def trajectory(t):

qd = np.zeros(ws['NDDL'])
qdotd = np.zeros(ws['NDDL'])
qddotd = np.zeros(ws['NDDL'])

for joint in ws['q2']: # TQ was 3D ... change for a vector or do a function to reshape the params
    T = TQ[0, :, qi]
    Q = TQ[1, :, qi]
    
    i = 1
    n = len(T)
    while i < n and t > T[i]:
        i += 1
    
    Ti = T[i - 1]
    Tj = T[i]
    Qi = Q[i - 1]
    Qj = Q[i]
    
    # function quintic
    if t < Ti:
        t = Ti
    elif t > Tj:
        t = Tj
    
    tp0 = Tj - Ti
    tp1 = (t - Ti) / tp0
    tp2 = tp1**3 * (6 * tp1**2 - 15 * tp1 + 10)
    tp3 = Qj - Qi
    tp4 = t - Ti
    tp5 = Tj - t
    
    qd[qi] = Qi + tp3 * tp2
    qdotd[qi] = 30 * tp3 * tp4**2 * tp5**2 / tp0**5
    qddotd[qi] = 60 * tp3 * tp4 * tp5 * (Tj + Ti - 2 * t) / tp0**5

return qd, qdotd, qddotd

mickaelbegon avatar Aug 18 '23 11:08 mickaelbegon

I was thinking about this problem and the coming refactor on PhaseParameters @pariterre. With a discussion we have, it would be relevant to have:

  • VariableContainer, would refer to time series, could be renamed TimeSeriesContainer
  • PhaseParameterContainer, would refer to parameters only relevant per phase
  • GlobalParameterContainer, (or ModelParameterContainer) ? It would refer to decision variables that could change over multiple phases.

And VariableContainer outputs may be extended to be expressed as a function of PhaseParameters, to get parametric time series.

Ipuch avatar Aug 22 '23 13:08 Ipuch