Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] defects, contacts, implicit constraints, multinode constraints with cx_intermediates, ... #946

Open
wants to merge 117 commits into
base: master
Choose a base branch
from

Conversation

EveCharbie
Copy link
Collaborator

@EveCharbie EveCharbie commented Mar 24, 2025

This change is Reviewable

@EveCharbie EveCharbie changed the title [TO DISCUSS] merge [WIP] defects, contacts, implicit constraints, multinode constraints with cx_intermediates, ... Mar 25, 2025
Copy link
Member

@pariterre pariterre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 79 of 133 files at r1, all commit messages.
Reviewable status: 79 of 133 files reviewed, 33 unresolved discussions


bioptim/dynamics/dynamics_functions.py line 151 at r1 (raw file):

        dxdt, defects = None, None
        if not isinstance(nlp.ode_solver, OdeSolver.COLLOCATION):

Reverse the condition (if ...)

EDIT: Actually compare the ".defects_type" with a single if-else level


bioptim/dynamics/dynamics_functions.py line 159 at r1 (raw file):

                dxdt = nlp.cx(nlp.states.shape, ddq.shape[1])
                dxdt[nlp.states["q"].index, :] = horzcat(*[dq for _ in range(ddq.shape[1])])
                dxdt[nlp.states["qdot"].index, :] = ddq

You are allowed to break fatigue by removing this "if"


bioptim/dynamics/dynamics_functions.py line 177 at r1 (raw file):

                if fatigue is not None and "tau" in fatigue:
                    derivative = fatigue["tau"].dynamics(derivative, nlp, states, controls)

You are allowed to break "fatigue"


bioptim/dynamics/dynamics_functions.py line 266 at r1 (raw file):

        dxdt, defects = None, None
        if not isinstance(nlp.ode_solver, OdeSolver.COLLOCATION):

same


bioptim/dynamics/dynamics_functions.py line 352 at r1 (raw file):

        dxdt, defects = None, None
        if not isinstance(nlp.ode_solver, OdeSolver.COLLOCATION):

Same


bioptim/dynamics/dynamics_functions.py line 436 at r1 (raw file):

        dxdt, defects = None, None
        if not isinstance(nlp.ode_solver, OdeSolver.COLLOCATION):

Same


bioptim/dynamics/dynamics_functions.py line 578 at r1 (raw file):

        )

        dxdt, defects = None, None

Same


bioptim/dynamics/dynamics_functions.py line 662 at r1 (raw file):

        dxdt, defects = None, None
        if not isinstance(nlp.ode_solver, OdeSolver.COLLOCATION):

Same


bioptim/dynamics/dynamics_functions.py line 893 at r1 (raw file):

        dxdt, defects = None, None
        if not isinstance(nlp.ode_solver, OdeSolver.COLLOCATION):

Same


bioptim/dynamics/dynamics_functions.py line 1031 at r1 (raw file):

        dxdt, defects = None, None
        if not isinstance(nlp.ode_solver, OdeSolver.COLLOCATION):

Same


bioptim/dynamics/dynamics_functions.py line 1343 at r1 (raw file):

        dxdt, defects = None, None
        if not isinstance(nlp.ode_solver, OdeSolver.COLLOCATION):

Same


bioptim/dynamics/configure_problem.py line 194 at r1 (raw file):

        """

        _check_contacts_in_biorbd_model(contact_type, nlp.model, nlp.phase_idx)

list of "contact_type"


bioptim/dynamics/configure_problem.py line 202 at r1 (raw file):

        ConfigureProblem.configure_qddot(ocp, nlp, as_states=False, as_controls=False, as_states_dot=True)

        if contact_type == ContactType.RIGID_IMPLICIT:

Since for now, they are mutually exclusive, raise if len(contact_types) > 1

if contact_types in ...


bioptim/dynamics/configure_problem.py line 211 at r1 (raw file):

                as_states_dot=False,
            )
        elif contact_type == ContactType.RIGID_EXPLICIT:

not elif


bioptim/dynamics/configure_problem.py line 289 at r1 (raw file):

        )

        name_q_joints = [str(i) for i in range(nb_root, nb_q)]

Revert?


bioptim/dynamics/configure_problem.py line 370 at r1 (raw file):

        contact_type: ContactType = ContactType.NONE,
        with_friction: bool = False,
        with_cholesky: bool = False,

Consider using "DynamicOptions"?


bioptim/dynamics/configure_problem.py line 394 at r1 (raw file):

            A list of values to pass to the dynamics at each node. Experimental external forces should be included here.
        """
        with_contact = contact_type == ContactType.RIGID_EXPLICIT

Do as torque_driven


bioptim/dynamics/configure_problem.py line 548 at r1 (raw file):

        """
        with_contact = contact_type == ContactType.RIGID_EXPLICIT

Do as torque_driven


bioptim/dynamics/configure_problem.py line 549 at r1 (raw file):

        """
        with_contact = contact_type == ContactType.RIGID_EXPLICIT
        _check_contacts_in_biorbd_model(contact_type, nlp.model, nlp.phase_idx)

..._in_biomodel


bioptim/dynamics/configure_problem.py line 620 at r1 (raw file):

            A list of values to pass to the dynamics at each node. Experimental external forces should be included here.
        """
        with_contact = contact_type == ContactType.RIGID_EXPLICIT

Do as ForwardDynamics


bioptim/dynamics/configure_problem.py line 624 at r1 (raw file):

        ConfigureProblem.configure_q(ocp, nlp, True, False)
        ConfigureProblem.configure_qdot(ocp, nlp, True, False, as_states_dot=True)

remove the "as_states_dot" argument and consider it as always "True"


bioptim/dynamics/configure_problem.py line 625 at r1 (raw file):

        ConfigureProblem.configure_q(ocp, nlp, True, False)
        ConfigureProblem.configure_qdot(ocp, nlp, True, False, as_states_dot=True)
        ConfigureProblem.configure_qddot(ocp, nlp, False, False, as_states_dot=True)

Please add "as_states=False", "as_controls=False"


bioptim/dynamics/configure_problem.py line 1061 at r1 (raw file):

        dynamics_defects = dynamics_eval.defects
        if isinstance(dynamics_defects, (list, tuple)):
            dynamics_defects = vertcat(*dynamics_defects)

Consider outputting only "dynamics" from here, effectively removing the if block below (remove implicit_dynamics_func)


bioptim/dynamics/configure_problem.py line 1748 at r1 (raw file):

            name in nlp.variable_mappings
            and nlp.variable_mappings["m"].to_first.map_idx != nlp.variable_mappings["m"].to_second.map_idx
        ):

If useful :
Class Bimaping:
is_unary?


bioptim/dynamics/configure_problem.py line 2150 at r1 (raw file):

def _check_contacts_in_biorbd_model(contact_type: ContactType, model: BioModel, phase_idx: int):

bimodel


bioptim/__init__.py line 224 at r1 (raw file):

    PhaseDynamics,
    OnlineOptim,
    ContactType,

Is this really mutually exclusive?


bioptim/dynamics/ode_solvers.py line 124 at r1 (raw file):

            polynomial_degree: int = 4,
            method: str = "legendre",
            defects_type: DefectType = DefectType.QDDOT_EQUALS_FORWARD_DYNAMICS,

QDDOT_IS_FORWARD_DYNAMICS?


bioptim/dynamics/ode_solvers.py line 282 at r1 (raw file):

            t = [self.t_ode(nlp)[0], self.t_ode(nlp)[1] - self.t_ode(nlp)[0]]
            dynamics_func = nlp.dynamics_func if not is_extra_dynamics else nlp.extra_dynamics_func[dynamics_index]
            implicit_dynamics_func = (

Not needed anymore


bioptim/examples/getting_started/how_to_plot.py line 20 at r1 (raw file):

# --- Plot the reintegration to confirm dynamics consistency --- #

Clean this


bioptim/dynamics/ode_solver_base.py line 192 at r1 (raw file):

            The index of the node currently initialized
        is_implicit
            If the dynamics is implicit or not

Remove


bioptim/examples/stochastic_optimal_control/arm_reaching_torque_driven_collocations.py line 193 at r1 (raw file):

        expand_dynamics=True,
        with_friction=True,
        ode_solver=OdeSolver.COLLOCATION,  # This will be overwritten by the SocpType

Should not?


bioptim/examples/getting_started/custom_dynamics.py line 82 at r1 (raw file):

    dxdt, defects = None, None
    if not isinstance(nlp.ode_solver, OdeSolver.COLLOCATION):

reverse


bioptim/examples/getting_started/custom_dynamics.py line 92 at r1 (raw file):

        defects = vertcat(slope_q, slope_qdot) * nlp.dt - vertcat(dq, ddq) * nlp.dt

    return DynamicsEvaluation(dxdt=dxdt, defects=defects)

REVERT FROM WHAT WAS SAID BEFORE

DynamicsEvaluation is actually necessary

Add a not why dxdt can or can be not declared when using COLLOCATION

Copy link
Collaborator Author

@EveCharbie EveCharbie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 58 of 134 files reviewed, 33 unresolved discussions (waiting on @pariterre)


bioptim/__init__.py line 224 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Is this really mutually exclusive?

Waiting on ipuch to answer this


bioptim/dynamics/configure_problem.py line 194 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

list of "contact_type"

Done.


bioptim/dynamics/configure_problem.py line 202 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Since for now, they are mutually exclusive, raise if len(contact_types) > 1

if contact_types in ...

Done.


bioptim/dynamics/configure_problem.py line 211 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

not elif

Done.


bioptim/dynamics/configure_problem.py line 289 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Revert?

Done.


bioptim/dynamics/configure_problem.py line 370 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Consider using "DynamicOptions"?

Didn't change it for now


bioptim/dynamics/configure_problem.py line 394 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Do as torque_driven

Done.


bioptim/dynamics/configure_problem.py line 548 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Do as torque_driven

Done.


bioptim/dynamics/configure_problem.py line 549 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

..._in_biomodel

Done.


bioptim/dynamics/configure_problem.py line 620 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Do as ForwardDynamics

Done.


bioptim/dynamics/configure_problem.py line 624 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

remove the "as_states_dot" argument and consider it as always "True"

Done.


bioptim/dynamics/configure_problem.py line 625 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Please add "as_states=False", "as_controls=False"

Done.


bioptim/dynamics/configure_problem.py line 1061 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Consider outputting only "dynamics" from here, effectively removing the if block below (remove implicit_dynamics_func)

We decided not to do that


bioptim/dynamics/configure_problem.py line 1748 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

If useful :
Class Bimaping:
is_unary?

Done.


bioptim/dynamics/configure_problem.py line 2150 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

bimodel

Done.


bioptim/dynamics/dynamics_functions.py line 151 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Reverse the condition (if ...)

EDIT: Actually compare the ".defects_type" with a single if-else level

We dicided to keep dxdt ans defects


bioptim/dynamics/dynamics_functions.py line 159 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

You are allowed to break fatigue by removing this "if"

Done.


bioptim/dynamics/dynamics_functions.py line 177 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

You are allowed to break "fatigue"

Done.


bioptim/dynamics/dynamics_functions.py line 266 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

same

Done.


bioptim/dynamics/dynamics_functions.py line 352 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Same

Done.


bioptim/dynamics/dynamics_functions.py line 436 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Same

Done.


bioptim/dynamics/dynamics_functions.py line 578 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Same

Done.


bioptim/dynamics/dynamics_functions.py line 662 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Same

Done.


bioptim/dynamics/dynamics_functions.py line 893 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Same

Done.


bioptim/dynamics/dynamics_functions.py line 1031 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Same

Done.


bioptim/dynamics/dynamics_functions.py line 1343 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Same

Done.


bioptim/dynamics/ode_solver_base.py line 192 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Remove

We decided to keep dxdt ans defects


bioptim/dynamics/ode_solvers.py line 124 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

QDDOT_IS_FORWARD_DYNAMICS?

I prefer EQUALS


bioptim/dynamics/ode_solvers.py line 282 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Not needed anymore

We decided to keep dxdt and defects, I renamed it though


bioptim/examples/getting_started/custom_dynamics.py line 82 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

reverse

Done.


bioptim/examples/getting_started/custom_dynamics.py line 92 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

REVERT FROM WHAT WAS SAID BEFORE

DynamicsEvaluation is actually necessary

Add a not why dxdt can or can be not declared when using COLLOCATION

Done.


bioptim/examples/stochastic_optimal_control/arm_reaching_torque_driven_collocations.py line 193 at r1 (raw file):

Previously, pariterre (Pariterre) wrote…

Should not?

It is the only case where ode_solver in StochasticOptimalProgram would have made more sense :/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants