Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
2943d90
Bug fixes for holonomic contraints with robotics
Sep 25, 2025
0e5b565
Merge branch 'HolonomicForRobotics'
Feb 11, 2026
71770fb
Fix: biais vector
EveCharbie Feb 16, 2026
17fce15
Update holonomic constraints
Ipuch Feb 5, 2026
2232466
rigid contact biais
Ipuch Feb 5, 2026
77c5d96
documentation ++
Ipuch Feb 5, 2026
cc01d66
..
Feb 16, 2026
4c489c7
Unstash examples
Feb 16, 2026
8603fab
Unstash examples
Feb 16, 2026
592ee98
Unstash examples
Feb 16, 2026
20f2456
Unstash examples
Feb 16, 2026
7b85eb9
Fix display of lagrange multipliers
Feb 20, 2026
51eb234
Track algebraic state
Mar 3, 2026
e7734bc
Mayer Track algebraic state
Mar 3, 2026
8c65762
WIP on holonomic alignment constraint
Apr 3, 2026
4748864
Cleaned constraints file
Apr 3, 2026
c43751d
Added example for generalized version of constraint
Apr 13, 2026
a2f6e51
Merge remote-tracking branch 'pyomeca/master' into AlignmentContraint…
Apr 13, 2026
11484cb
Added tests, RTR
Apr 13, 2026
e6ed671
Merge branch 'master' into AlignmentContraintExamples_andBugFixes
Apr 13, 2026
33f98e4
Fixing after merging branch from ipuch
Apr 13, 2026
22cd82e
.
Aug 4, 2025
03501aa
reducing memorie consumption and speed up solution building for large oc
Aug 19, 2025
2e516b8
quick fix
Nov 7, 2025
d9de29e
Require NumPy 2.4 in env and CI
mickaelbegon May 6, 2026
b853430
Fix SelectionMapping for NumPy 2
mickaelbegon May 6, 2026
c769ce0
Target biorbd 1.12 in default environment
mickaelbegon May 6, 2026
5798954
Fixed an unstable test
pariterre Jun 2, 2026
a1bcbf8
Typo
pariterre Jun 2, 2026
a8de7a3
Enable macOS online plotting via multiprocess server
mickaelbegon Apr 9, 2026
a31418d
Harden macOS plotting example fallbacks
mickaelbegon Apr 9, 2026
dbaef69
Fixed test
pariterre Jun 2, 2026
64fb533
test_fatigable_effort_torque_split only on Darwin
pariterre Jun 2, 2026
e4c56b1
Small refactor
pariterre Jun 3, 2026
6177ce8
Fix lambda function for OnlineCallbackMultiprocess
pariterre Jun 3, 2026
1a6c05c
Add optional Pinocchio model backend
mickaelbegon May 6, 2026
0c57033
Document Pinocchio equivalents and derivative hooks
mickaelbegon May 6, 2026
1b6cf20
Better install of pinocchio
pariterre Jun 2, 2026
31c6086
Made SERVER_MULTIPROCESS default on linux
pariterre Jun 2, 2026
f5d4bc2
First working example of a pinocchio model
pariterre Jun 2, 2026
024a3aa
Added actual tests for pinocchio
pariterre Jun 2, 2026
94faa7e
Reinstated parameters test as it works now
pariterre Jun 2, 2026
3001da7
Blacked (and updated doc for black)
pariterre Jun 2, 2026
23c57da
Augmented tests for biorbd_model and pinocchio_model
pariterre Jun 3, 2026
ad34885
Better vscode launch file
pariterre Jun 3, 2026
c73e58f
Removed a useless test
pariterre Jun 3, 2026
469e47c
Removed pinocchio sensitive test values
pariterre Jun 3, 2026
441c659
Balancing tests to save time on CI
pariterre Jun 3, 2026
6175aef
Balancing yet again
pariterre Jun 3, 2026
d74c096
Final balancing
pariterre Jun 4, 2026
b9e6c34
WIP on PR comments
Jul 22, 2026
c94a5e4
Working through comments on the PR
Jul 22, 2026
45c75a6
Updated tests
Jul 22, 2026
60e89a5
Minor clean for test
Jul 22, 2026
cdbc576
Merge remote-tracking branch 'pyomeca/master' into AlignmentContraint…
Aug 27, 2026
b4117f0
name change
Aug 27, 2026
cf38280
Dummy commit to run tests
Aug 31, 2026
ec9bf67
Modified values to pass test
p-shg Sep 4, 2026
5d86f18
Merge branch 'master' into AlignmentContraintExamples_andBugFixes
p-shg Sep 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 57 additions & 18 deletions bioptim/dynamics/configure_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
from typing import Callable, Any

import numpy as np
from casadi import DM, vertcat, Function
from casadi import DM, vertcat, Function, horzcat

from .configure_new_variable import NewVariableConfiguration
from .fatigue.fatigue_dynamics import FatigueList
from ..misc.enums import PlotType, ContactType
from ..misc.enums import PlotType, ContactType, ControlType
from ..misc.fcn_enum import FcnEnum
from ..misc.mapping import BiMapping, Mapping
from ..models.protocols.stochastic_biomodel import StochasticBioModel
Expand Down Expand Up @@ -1204,20 +1204,31 @@ def configure_qv(ocp, nlp, **extra_params) -> None:

time_span_sym = vertcat(nlp.time_cx, nlp.dt)

nlp.q_v_function = Function(
sym_qv = (
nlp.controls.scaled.cx
if nlp.control_type == ControlType.CONSTANT
else nlp.cx.sym("linear_continuous_compatible_controls", nlp.controls.scaled.cx.shape[0], 2)
)
qv_init_w_algebraic = (
nlp.algebraic_states["q_v"].cx
if "q_v" in nlp.algebraic_states.keys()
else DM.zeros(nlp.model.nb_dependent_joints, 1)
)

q_v_plot_function = Function(
"qv_function",
[
time_span_sym,
nlp.states.cx,
nlp.controls.cx,
nlp.parameters.cx,
nlp.algebraic_states.cx,
nlp.states.scaled.cx,
sym_qv,
nlp.parameters.scaled.cx,
nlp.algebraic_states.scaled.cx,
nlp.numerical_timeseries.cx,
],
[
nlp.model.compute_q_v()(
nlp.states["q_u"].cx,
DM.zeros(nlp.model.nb_dependent_joints, 1),
qv_init_w_algebraic,
)
],
["t_span", "x", "u", "p", "a", "d"],
Expand All @@ -1239,7 +1250,7 @@ def configure_qv(ocp, nlp, **extra_params) -> None:
)

nlp.plot["q_v"] = CustomPlot(
lambda t0, phases_dt, node_idx, x, u, p, a, d: nlp.q_v_function(
lambda t0, phases_dt, node_idx, x, u, p, a, d: q_v_plot_function(
np.concatenate([t0, t0 + phases_dt[nlp.phase_idx]]), x, u, p, a, d
),
plot_type=PlotType.INTEGRATED,
Expand All @@ -1261,12 +1272,24 @@ def configure_qdotv(ocp, nlp, **extra_params) -> None:
"""

time_span_sym = vertcat(nlp.time_cx, nlp.dt)
nlp.q_v_function = Function(

sym_qv = (
nlp.controls.scaled.cx
if nlp.control_type == ControlType.CONSTANT
else nlp.cx.sym("new_control", nlp.controls.scaled.cx.shape[0], 2)
)
qv_init_w_algebraic = (
nlp.algebraic_states["q_v"].cx
if "q_v" in nlp.algebraic_states.keys()
else DM.zeros(nlp.model.nb_dependent_joints, 1)
)

qdot_v_plot_function = Function(
"qdot_v_function",
[
time_span_sym,
nlp.states.scaled.cx,
nlp.controls.scaled.cx,
sym_qv,
nlp.parameters.scaled.cx,
nlp.algebraic_states.scaled.cx,
nlp.numerical_timeseries.cx,
Expand All @@ -1275,7 +1298,7 @@ def configure_qdotv(ocp, nlp, **extra_params) -> None:
nlp.model._compute_qdot_v()(
nlp.states.scaled["q_u"].cx,
nlp.states.scaled["qdot_u"].cx,
DM.zeros(nlp.model.nb_dependent_joints, 1),
qv_init_w_algebraic,
)
],
["t_span", "x", "u", "p", "a", "d"],
Expand All @@ -1297,7 +1320,7 @@ def configure_qdotv(ocp, nlp, **extra_params) -> None:
)

nlp.plot["qdot_v"] = CustomPlot(
lambda t0, phases_dt, node_idx, x, u, p, a, d: nlp.q_v_function(
lambda t0, phases_dt, node_idx, x, u, p, a, d: qdot_v_plot_function(
np.concatenate([t0, t0 + phases_dt[nlp.phase_idx]]), x, u, p, a, d
),
plot_type=PlotType.INTEGRATED,
Expand All @@ -1319,12 +1342,25 @@ def configure_lagrange_multipliers_function(ocp, nlp: NpArrayDictOptional, **ext
"""

time_span_sym = vertcat(nlp.time_cx, nlp.dt)
nlp.lagrange_multipliers_function = Function(

sym_qv = (
nlp.controls.scaled.cx
if nlp.control_type == ControlType.CONSTANT
else nlp.cx.sym("linear_continuous_compatible_controls", nlp.controls.scaled.cx.shape[0], 2)
)
ctrl_cx = sym_qv[:, 1] if nlp.control_type == ControlType.LINEAR_CONTINUOUS else nlp.controls.scaled.cx
qv_init_w_algebraic = (
nlp.algebraic_states["q_v"].cx
if "q_v" in nlp.algebraic_states.keys()
else DM.zeros(nlp.model.nb_dependent_joints, 1)
)

lagrange_multipliers_plot_function = Function(
"lagrange_multipliers_function",
[
time_span_sym,
nlp.states.scaled.cx,
nlp.controls.scaled.cx,
sym_qv,
nlp.parameters.scaled.cx,
nlp.algebraic_states.scaled.cx,
nlp.numerical_timeseries.cx,
Expand All @@ -1333,8 +1369,11 @@ def configure_lagrange_multipliers_function(ocp, nlp: NpArrayDictOptional, **ext
nlp.model.compute_the_lagrangian_multipliers()(
nlp.states.scaled["q_u"].cx,
nlp.states.scaled["qdot_u"].cx,
DM.zeros(nlp.model.nb_dependent_joints, 1),
DynamicsFunctions.get(nlp.controls["tau"], nlp.controls.scaled.cx),
qv_init_w_algebraic,
DynamicsFunctions.get(
nlp.controls["tau"],
ctrl_cx,
),
)
],
["t_span", "x", "u", "p", "a", "d"],
Expand All @@ -1360,7 +1399,7 @@ def configure_lagrange_multipliers_function(ocp, nlp: NpArrayDictOptional, **ext
)

nlp.plot["lagrange_multipliers"] = CustomPlot(
lambda t0, phases_dt, node_idx, x, u, p, a, d: nlp.lagrange_multipliers_function(
lambda t0, phases_dt, node_idx, x, u, p, a, d: lagrange_multipliers_plot_function(
np.concatenate([t0, t0 + phases_dt[nlp.phase_idx]]), x, u, p, a, d
),
plot_type=PlotType.INTEGRATED,
Expand Down
160 changes: 160 additions & 0 deletions bioptim/examples/models/two_cubes_lagrange2D_6DOF.bioMod
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
version 1.0

gravity 0 0 -9.81

segment root

marker root_origin
parent root
position 0 0 0
endmarker

endsegment

segment cube0
parent root
RTinMatrix 0
RT pi/7 -pi/8 -pi/6 xyz 0 0 0
mass 1.0
com 0 0 0
inertia 1 0 0
0 1 0
0 0 1
mesh 0 -1 -1
mesh 0 0 -1
mesh 0 0 0
mesh 0 -1 0
mesh 0 -1 -1
mesh 1 -1 -1
mesh 1 0 -1
mesh 0 0 -1
mesh 1 0 -1
mesh 1 0 0
mesh 0 0 0
mesh 1 0 0
mesh 1 -1 0
mesh 0 -1 0
mesh 1 -1 0
mesh 1 -1 -1

rotations xyz
translations xyz
rangesQ
-4*pi 4*pi
-4*pi 4*pi
-4*pi 4*pi
-100 100
-100 100
-100 100
endsegment

marker cube0_1
parent cube0
position 0 0 0
endmarker


segment cube1
parent root
RTinMatrix 0
RT 0 0 0 xyz 0 2 0
mass 1.0
com 0.1 0.2 0.3
inertia 1 0 0
0 1 0
0 0 1
mesh 0 -1 -1
mesh 0 0 -1
mesh 0 0 0
mesh 0 -1 0
mesh 0 -1 -1
mesh 1 -1 -1
mesh 1 0 -1
mesh 0 0 -1
mesh 1 0 -1
mesh 1 0 0
mesh 0 0 0
mesh 1 0 0
mesh 1 -1 0
mesh 0 -1 0
mesh 1 -1 0
mesh 1 -1 -1

rotations xyz
translations xyz

rangesQ
-4*pi 4*pi
-4*pi 4*pi
-4*pi 4*pi
-100 100
-100 100
-100 100
endsegment

marker cube1_1
parent cube1
position 0 0 0
endmarker

segment new_frame
parent cube1
RTinMatrix 0
RT 1 0 0 xyz 0 0 0
endsegment

segment new_frame2
parent cube1
RTinMatrix 1
RT
1.000000 0.000000 0.000000 0.000000
0.000000 0.000000 -1.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 0.000000 1.000000
endsegment

segment new_frame3
parent cube1
RTinMatrix 1
RT
0.7500000 -0.4330127 0.5000000 0
0.6495190 0.6250000 -0.4330127 0
-0.1250000 0.6495190 0.7500000 0
0.000000 0.000000 0.000000 1.000000
endsegment

segment new_frame4
parent cube1
RTinMatrix 1
RT
1 0 0 0
0 -0.5000000 -0.8660254 0
0 0.8660254 -0.5000000 0
0.000000 0.000000 0.000000 1.000000
endsegment

segment new_frame5
parent cube1
RTinMatrix 1
RT
-0.000000 -0.070711 -0.997497 0
-0.124294 0.989762 -0.070163 0
0.992245 0.123983 -0.008789 0
0.000000 0.000000 0.000000 1.000000
endsegment

segment new_frame6
parent cube1
RTinMatrix 1
RT
0 1 0 0
0 0 1 0
1 0 0 0
0.000000 0.000000 0.000000 1.000000
endsegment

segment new_frame7
parent cube1
RTinMatrix 0
RT 0 pi/2 pi/2 xyz 0 0 0
endsegment
76 changes: 76 additions & 0 deletions bioptim/examples/models/two_cubes_lagrange2D_outofplane.bioMod
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
version 1.0

gravity 0 0 0.0001

segment root

marker root_origin
parent root
position 0 0 0
endmarker

endsegment

segment cube0
parent root
RTinMatrix 0
RT pi/7 -pi/8 -pi/6 xyz 0 0 0
mass 1.0
com 0 0 0
inertia 1 0 0
0 1 0
0 0 1
mesh 0 -1 -1
mesh 0 0 -1
mesh 0 0 0
mesh 0 -1 0
mesh 0 -1 -1
mesh 1 -1 -1
mesh 1 0 -1
mesh 0 0 -1
mesh 1 0 -1
mesh 1 0 0
mesh 0 0 0
mesh 1 0 0
mesh 1 -1 0
mesh 0 -1 0
mesh 1 -1 0
mesh 1 -1 -1

rotations x
rangesQ
-4*pi 4*pi
endsegment

segment cube1
parent root
RTinMatrix 0
RT 0 0 0 xyz 0 2 0
mass 1.0
com 0 0 0
inertia 1 0 0
0 1 0
0 0 1
mesh 0 -1 -1
mesh 0 0 -1
mesh 0 0 0
mesh 0 -1 0
mesh 0 -1 -1
mesh 1 -1 -1
mesh 1 0 -1
mesh 0 0 -1
mesh 1 0 -1
mesh 1 0 0
mesh 0 0 0
mesh 1 0 0
mesh 1 -1 0
mesh 0 -1 0
mesh 1 -1 0
mesh 1 -1 -1

rotations xyz
rangesQ
-4*pi 4*pi
-4*pi 4*pi
-4*pi 4*pi
endsegment
Loading
Loading