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

[RTM after next push] SOCP: Making the noise dependant on the states + controls #809

Merged
merged 73 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
256a70e
made all penalty accessible by root, joints
EveCharbie Nov 12, 2023
271300d
modified example to test the new implementation
EveCharbie Nov 12, 2023
350fb65
blacked
EveCharbie Nov 12, 2023
71576ea
animation ok
EveCharbie Nov 12, 2023
76f404c
tested dynamincs + adjusted forces
EveCharbie Nov 13, 2023
342416b
models
EveCharbie Nov 13, 2023
6a1d695
added example + tested the example
EveCharbie Nov 13, 2023
18b58c8
blacked
EveCharbie Nov 13, 2023
e0c7a0b
fixed some tests
EveCharbie Nov 13, 2023
67c5e93
beginning of SOCP free_floating_base
EveCharbie Nov 15, 2023
92e399d
added controller.tau
EveCharbie Nov 15, 2023
b6e29ce
blacked
EveCharbie Nov 15, 2023
ac9a6ea
added get_var_from_states_or_controls to nlp
EveCharbie Nov 15, 2023
689279c
circular import
EveCharbie Nov 15, 2023
de8a058
generalized to quaternions
EveCharbie Nov 15, 2023
416e207
improoved quaternion free floating base example
EveCharbie Nov 15, 2023
84a3889
fixed example + test
EveCharbie Nov 15, 2023
18ae33b
blacked
EveCharbie Nov 15, 2023
afbb8b7
fixed some tests
EveCharbie Nov 15, 2023
bb119bc
woups forgot to change test values
EveCharbie Nov 16, 2023
d720fed
blacked
EveCharbie Nov 16, 2023
7ddd28d
tried to make test stable
EveCharbie Nov 16, 2023
c43bfd3
blacked
EveCharbie Nov 16, 2023
f67120e
again
EveCharbie Nov 16, 2023
37f632e
blacked
EveCharbie Nov 16, 2023
9ac6cf9
beginning of SOCP free_floating_base
EveCharbie Nov 15, 2023
465e605
cov is now n_q not n_joints (think it is more accurate)
EveCharbie Nov 17, 2023
5ea62be
blacked
EveCharbie Nov 17, 2023
eaba494
Merge remote-tracking branch 'origin/free_floating_base_SOCP' into fr…
EveCharbie Nov 17, 2023
deb2bd3
small fixes
EveCharbie Nov 19, 2023
5d5634c
test values + forgotten error message
EveCharbie Nov 19, 2023
861b33e
blacked
EveCharbie Nov 19, 2023
c7b3492
This is becoming even sketchier :/
EveCharbie Nov 20, 2023
bec2404
first thoughts
EveCharbie Nov 21, 2023
fb42a71
homeogeneous matrices (biorbd)
EveCharbie Nov 22, 2023
dc696fc
added segment orientation
EveCharbie Nov 22, 2023
8de9003
leaving the reference responsability to the user
EveCharbie Nov 22, 2023
b78852a
fixed some tests
EveCharbie Nov 22, 2023
613ff7c
blacked
EveCharbie Nov 22, 2023
8dc6459
first thoughts on auto intialization
EveCharbie Nov 22, 2023
12fc08f
auto initialization through get_..._init
EveCharbie Nov 23, 2023
e21d2c4
blacked
EveCharbie Nov 23, 2023
b4bf7a9
Fixed initialization problems (SIGN TBD!!)
EveCharbie Nov 24, 2023
968253e
tested auto initialization (not working properly for multi-thread)
EveCharbie Nov 24, 2023
95aa1eb
blacked
EveCharbie Nov 24, 2023
4beefbc
surprizing behavior (BUG FIX)
EveCharbie Nov 27, 2023
e16096f
small fixes ?
EveCharbie Nov 28, 2023
082eb90
TEMPO COMMIT FOR MB
EveCharbie Nov 29, 2023
656ee16
Revert "TEMPO COMMIT FOR MB"
EveCharbie Nov 29, 2023
373166b
Merge remote-tracking branch 'pyomeca/master' into variable_noise_SOCP
pariterre Jan 12, 2024
c4d914b
Fixing some merging errors
pariterre Jan 12, 2024
d7597e5
fixed some issues
EveCharbie Jan 24, 2024
1275b10
fixed collocation still an issue with implicit
EveCharbie Jan 24, 2024
71ef02c
auto_initialization test fails (pariterre plz)
EveCharbie Jan 25, 2024
6e1332e
fixing some issues with variable noise
EveCharbie Jan 25, 2024
33225a1
blacked
EveCharbie Jan 25, 2024
3ad5ba1
name changes and some modif requested
EveCharbie Jan 26, 2024
7c9d0ee
requested by MICK
EveCharbie Jan 30, 2024
7f9afcb
updated values test print cost (-.2f)
EveCharbie Jan 31, 2024
b8dcaae
fixed merge problem + cleaned test
EveCharbie Jan 31, 2024
002d2e4
changed implicit values in test
EveCharbie Jan 31, 2024
b409881
blacked
EveCharbie Jan 31, 2024
7871b12
made requested changes
EveCharbie Jan 31, 2024
4fae633
blacked
EveCharbie Jan 31, 2024
a6a3d67
updated black
EveCharbie Jan 31, 2024
5f0f3d6
fixed the name problem with new raise
EveCharbie Jan 31, 2024
e2725f0
Merge remote-tracking branch 'pyomeca/master' into variable_noise_SOCP
EveCharbie Jan 31, 2024
e64bcc5
made requested changes
EveCharbie Feb 2, 2024
0cea469
added tests for error messages (codecov)
EveCharbie Feb 2, 2024
cc355f7
blacked
EveCharbie Feb 2, 2024
be20ae6
Merge remote-tracking branch 'pyomeca/master' into variable_noise_SOCP
EveCharbie Feb 2, 2024
3c1e939
removed False False False
EveCharbie Feb 2, 2024
c02d206
blacked
EveCharbie Feb 2, 2024
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2098,7 +2098,7 @@ Let us take a look at the structure of the code. First, tau_min, tau_max, and ta
to -1, 1 and 0 if the integer `actuator_type` (a parameter of the `prepare_ocp` function) equals 1.
In this case, the dynamics function used is `DynamicsFcn.TORQUE_ACTIVATIONS_DRIVEN`.

### The [trampo_quaternions.py](./bioptim/examples/torque_driven_ocp/trampo_quaternions.py) file
### The [example_quaternions.py](./bioptim/examples/torque_driven_ocp/example_quaternions.py) file
This example uses a representation of a human body by a trunk_leg segment and two arms.
It is designed to show how to use a model that has quaternions in their degrees of freedom.

Expand Down
1 change: 1 addition & 0 deletions bioptim/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
from .limits.path_conditions import BoundsList, InitialGuessList
from .limits.fatigue_path_conditions import FatigueBounds, FatigueInitialGuess
from .limits.penalty_controller import PenaltyController
from .limits.penalty_helpers import PenaltyHelpers
from .misc.enums import (
Axis,
Node,
Expand Down
42 changes: 24 additions & 18 deletions bioptim/dynamics/configure_new_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,11 @@ def _declare_cx_and_plot(self):
)
if not self.skip_plot:
self.nlp.plot[f"{self.name}_states"] = CustomPlot(
lambda t0, phases_dt, node_idx, x, u, p, a: x[self.nlp.states.key_index(self.name), :]
if x.any()
else np.ndarray((cx[0][0].shape[0], 1)) * np.nan,
lambda t0, phases_dt, node_idx, x, u, p, a: (
x[self.nlp.states.key_index(self.name), :]
if x.any()
else np.ndarray((cx[0][0].shape[0], 1)) * np.nan
),
plot_type=PlotType.INTEGRATED,
axes_idx=self.axes_idx,
legend=self.legend,
Expand Down Expand Up @@ -453,15 +455,19 @@ def _declare_cx_and_plot(self):
plot_type = PlotType.PLOT if self.nlp.control_type == ControlType.LINEAR_CONTINUOUS else PlotType.STEP
if not self.skip_plot:
self.nlp.plot[f"{self.name}_controls"] = CustomPlot(
lambda t0, phases_dt, node_idx, x, u, p, a: u[self.nlp.controls.key_index(self.name), :]
if u.any()
else np.ndarray((cx[0][0].shape[0], 1)) * np.nan,
lambda t0, phases_dt, node_idx, x, u, p, a: (
u[self.nlp.controls.key_index(self.name), :]
if u.any()
else np.ndarray((cx[0][0].shape[0], 1)) * np.nan
),
plot_type=plot_type,
axes_idx=self.axes_idx,
legend=self.legend,
combine_to=f"{self.name}_states"
if self.as_states and self.combine_state_control_plot
else self.combine_name,
combine_to=(
f"{self.name}_states"
if self.as_states and self.combine_state_control_plot
else self.combine_name
),
)

if self.as_states_dot:
Expand Down Expand Up @@ -601,9 +607,9 @@ def _manage_fatigue_to_new_variable(
var_names_with_suffix[-1], name_elements, ocp, nlp, as_states, as_controls, skip_plot=True
)
nlp.plot[f"{var_names_with_suffix[-1]}_controls"] = CustomPlot(
lambda t0, phases_dt, node_idx, x, u, p, a, key: u[nlp.controls.key_index(key), :]
if u.any()
else np.ndarray((len(name_elements), 1)) * np.nan,
lambda t0, phases_dt, node_idx, x, u, p, a, key: (
u[nlp.controls.key_index(key), :] if u.any() else np.ndarray((len(name_elements), 1)) * np.nan
),
plot_type=PlotType.STEP,
combine_to=control_plot_name,
key=var_names_with_suffix[-1],
Expand All @@ -612,9 +618,9 @@ def _manage_fatigue_to_new_variable(
elif i == 0:
NewVariableConfiguration(f"{name}", name_elements, ocp, nlp, as_states, as_controls, skip_plot=True)
nlp.plot[f"{name}_controls"] = CustomPlot(
lambda t0, phases_dt, node_idx, x, u, p, a, key: u[nlp.controls.key_index(key), :]
if u.any()
else np.ndarray((len(name_elements), 1)) * np.nan,
lambda t0, phases_dt, node_idx, x, u, p, a, key: (
u[nlp.controls.key_index(key), :] if u.any() else np.ndarray((len(name_elements), 1)) * np.nan
),
plot_type=PlotType.STEP,
combine_to=control_plot_name,
key=f"{name}",
Expand All @@ -625,9 +631,9 @@ def _manage_fatigue_to_new_variable(
name_tp = f"{var_names_with_suffix[-1]}_{params}"
NewVariableConfiguration(name_tp, name_elements, ocp, nlp, True, False, skip_plot=True)
nlp.plot[name_tp] = CustomPlot(
lambda t0, phases_dt, node_idx, x, u, p, a, key, mod: mod * x[nlp.states.key_index(key), :]
if x.any()
else np.ndarray((len(name_elements), 1)) * np.nan,
lambda t0, phases_dt, node_idx, x, u, p, a, key, mod: (
mod * x[nlp.states.key_index(key), :] if x.any() else np.ndarray((len(name_elements), 1)) * np.nan
),
plot_type=PlotType.INTEGRATED,
combine_to=fatigue_plot_name,
key=name_tp,
Expand Down
219 changes: 217 additions & 2 deletions bioptim/dynamics/configure_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,18 +298,157 @@
phase=nlp.phase_idx,
)

@staticmethod
def torque_driven_free_floating_base(
ocp,
nlp,
with_contact: bool = False,
with_passive_torque: bool = False,
with_ligament: bool = False,
with_friction: bool = False,
external_forces: list = None,
):
"""
Configure the dynamics for a torque driven program with a free floating base.
This version of the torque driven dynamics avoids defining a mapping to force the root to generate null forces and torques.
(states are q_root, q_joints, qdot_root, and qdot_joints, controls are tau_joints)
Please note that it was not meant to be used with quaternions yet.

Parameters
----------
ocp: OptimalControlProgram
A reference to the ocp
nlp: NonLinearProgram
A reference to the phase
with_contact: bool
If the dynamic with contact should be used
with_passive_torque: bool
If the dynamic with passive torque should be used
with_ligament: bool
If the dynamic with ligament should be used
with_friction: bool
If the dynamic with joint friction should be used (friction = coefficients * qdot)
external_forces: list[Any]
A list of external forces
"""

_check_contacts_in_biorbd_model(with_contact, nlp.model.nb_contacts, nlp.phase_idx)
_check_external_forces_format(external_forces, nlp.ns, nlp.phase_idx)
_check_external_forces_and_phase_dynamics(external_forces, nlp.phase_dynamics, nlp.phase_idx)

nb_q = nlp.model.nb_q
nb_qdot = nlp.model.nb_qdot
nb_root = nlp.model.nb_root

# Declared rigidbody states and controls
name_q_roots = [str(i) for i in range(nb_root)]
ConfigureProblem.configure_new_variable(
"q_roots",
name_q_roots,
ocp,
nlp,
as_states=True,
as_controls=False,
as_states_dot=False,
)

name_q_joints = [str(i) for i in range(nb_root, nb_q)]
ConfigureProblem.configure_new_variable(
"q_joints",
name_q_joints,
ocp,
nlp,
as_states=True,
as_controls=False,
as_states_dot=False,
)

ConfigureProblem.configure_new_variable(
"qdot_roots",
name_q_roots,
ocp,
nlp,
as_states=True,
as_controls=False,
as_states_dot=True,
)

name_qdot_joints = [str(i) for i in range(nb_root, nb_qdot)]
ConfigureProblem.configure_new_variable(
"qdot_joints",
name_qdot_joints,
ocp,
nlp,
as_states=True,
as_controls=False,
as_states_dot=True,
)

ConfigureProblem.configure_new_variable(
"qddot_roots",
name_q_roots,
ocp,
nlp,
as_states=False,
as_controls=False,
as_states_dot=True,
)

ConfigureProblem.configure_new_variable(
"qddot_joints",
name_qdot_joints,
ocp,
nlp,
as_states=False,
as_controls=False,
as_states_dot=True,
)

ConfigureProblem.configure_new_variable(
"tau_joints",
name_qdot_joints,
ocp,
nlp,
as_states=False,
as_controls=True,
as_states_dot=False,
)

# TODO: add implicit constraints + soft contacts + fatigue

# Configure the actual ODE of the dynamics
if nlp.dynamics_type.dynamic_function:
ConfigureProblem.configure_dynamics_function(ocp, nlp, DynamicsFunctions.custom)

Check warning on line 421 in bioptim/dynamics/configure_problem.py

View check run for this annotation

Codecov / codecov/patch

bioptim/dynamics/configure_problem.py#L421

Added line #L421 was not covered by tests
else:
ConfigureProblem.configure_dynamics_function(
ocp,
nlp,
DynamicsFunctions.torque_driven_free_floating_base,
with_contact=with_contact,
with_passive_torque=with_passive_torque,
with_ligament=with_ligament,
with_friction=with_friction,
external_forces=external_forces,
)

# Configure the contact forces
if with_contact:
ConfigureProblem.configure_contact_function(
ocp, nlp, DynamicsFunctions.forces_from_torque_driven, external_forces=external_forces
)

@staticmethod
def stochastic_torque_driven(
ocp,
nlp,
problem_type,
with_contact: bool = False,
with_friction: bool = True,
with_friction: bool = False,
with_cholesky: bool = False,
initial_matrix: DM = None,
):
"""
Configure the dynamics for a torque driven program (states are q and qdot, controls are tau)
Configure the dynamics for a torque driven stochastic program (states are q and qdot, controls are tau)

Parameters
----------
Expand Down Expand Up @@ -375,6 +514,80 @@
with_friction=with_friction,
)

@staticmethod
def stochastic_torque_driven_free_floating_base(
ocp,
nlp,
problem_type,
with_contact: bool = False,
with_friction: bool = False,
with_cholesky: bool = False,
initial_matrix: DM = None,
):
"""
Configure the dynamics for a stochastic torque driven program with a free floating base.
(states are q_roots, q_joints, qdot_roots, and qdot_joints, controls are tau_joints)

Parameters
----------
ocp: OptimalControlProgram
A reference to the ocp
nlp: NonLinearProgram
A reference to the phase
with_contact: bool
If the dynamic with contact should be used
with_friction: bool
If the dynamic with joint friction should be used (friction = coefficient * qdot)
"""
n_noised_tau = nlp.model.n_noised_controls
n_noise = nlp.model.motor_noise_magnitude.shape[0] + nlp.model.sensory_noise_magnitude.shape[0]
n_noised_states = nlp.model.n_noised_states

Check warning on line 544 in bioptim/dynamics/configure_problem.py

View check run for this annotation

Codecov / codecov/patch

bioptim/dynamics/configure_problem.py#L542-L544

Added lines #L542 - L544 were not covered by tests

# Stochastic variables
ConfigureProblem.configure_stochastic_k(

Check warning on line 547 in bioptim/dynamics/configure_problem.py

View check run for this annotation

Codecov / codecov/patch

bioptim/dynamics/configure_problem.py#L547

Added line #L547 was not covered by tests
ocp, nlp, n_noised_controls=n_noised_tau, n_references=nlp.model.n_references
)
ConfigureProblem.configure_stochastic_ref(ocp, nlp, n_references=nlp.model.n_references)
n_collocation_points = 1
if isinstance(problem_type, SocpType.COLLOCATION):
n_collocation_points += problem_type.polynomial_degree
ConfigureProblem.configure_stochastic_m(

Check warning on line 554 in bioptim/dynamics/configure_problem.py

View check run for this annotation

Codecov / codecov/patch

bioptim/dynamics/configure_problem.py#L550-L554

Added lines #L550 - L554 were not covered by tests
ocp, nlp, n_noised_states=n_noised_states, n_collocation_points=n_collocation_points
)

if isinstance(problem_type, SocpType.TRAPEZOIDAL_EXPLICIT):
if initial_matrix is None:
raise RuntimeError(

Check warning on line 560 in bioptim/dynamics/configure_problem.py

View check run for this annotation

Codecov / codecov/patch

bioptim/dynamics/configure_problem.py#L558-L560

Added lines #L558 - L560 were not covered by tests
"The initial value for the covariance matrix must be provided for TRAPEZOIDAL_EXPLICIT"
)
ConfigureProblem.configure_stochastic_cov_explicit(

Check warning on line 563 in bioptim/dynamics/configure_problem.py

View check run for this annotation

Codecov / codecov/patch

bioptim/dynamics/configure_problem.py#L563

Added line #L563 was not covered by tests
ocp, nlp, n_noised_states=n_noised_states, initial_matrix=initial_matrix
)
else:
if with_cholesky:
ConfigureProblem.configure_stochastic_cholesky_cov(ocp, nlp, n_noised_states=n_noised_states)

Check warning on line 568 in bioptim/dynamics/configure_problem.py

View check run for this annotation

Codecov / codecov/patch

bioptim/dynamics/configure_problem.py#L567-L568

Added lines #L567 - L568 were not covered by tests
else:
ConfigureProblem.configure_stochastic_cov_implicit(ocp, nlp, n_noised_states=n_noised_states)

Check warning on line 570 in bioptim/dynamics/configure_problem.py

View check run for this annotation

Codecov / codecov/patch

bioptim/dynamics/configure_problem.py#L570

Added line #L570 was not covered by tests

if isinstance(problem_type, SocpType.TRAPEZOIDAL_IMPLICIT):
ConfigureProblem.configure_stochastic_a(ocp, nlp, n_noised_states=n_noised_states)
ConfigureProblem.configure_stochastic_c(ocp, nlp, n_noised_states=n_noised_states, n_noise=n_noise)

Check warning on line 574 in bioptim/dynamics/configure_problem.py

View check run for this annotation

Codecov / codecov/patch

bioptim/dynamics/configure_problem.py#L572-L574

Added lines #L572 - L574 were not covered by tests

ConfigureProblem.torque_driven_free_floating_base(

Check warning on line 576 in bioptim/dynamics/configure_problem.py

View check run for this annotation

Codecov / codecov/patch

bioptim/dynamics/configure_problem.py#L576

Added line #L576 was not covered by tests
ocp=ocp,
nlp=nlp,
with_contact=with_contact,
with_friction=with_friction,
)

ConfigureProblem.configure_dynamics_function(

Check warning on line 583 in bioptim/dynamics/configure_problem.py

View check run for this annotation

Codecov / codecov/patch

bioptim/dynamics/configure_problem.py#L583

Added line #L583 was not covered by tests
ocp,
nlp,
DynamicsFunctions.stochastic_torque_driven_free_floating_base,
with_contact=with_contact,
with_friction=with_friction,
)

@staticmethod
def torque_derivative_driven(
ocp,
Expand Down Expand Up @@ -1576,7 +1789,9 @@
"""

TORQUE_DRIVEN = (ConfigureProblem.torque_driven,)
TORQUE_DRIVEN_FREE_FLOATING_BASE = (ConfigureProblem.torque_driven_free_floating_base,)
STOCHASTIC_TORQUE_DRIVEN = (ConfigureProblem.stochastic_torque_driven,)
STOCHASTIC_TORQUE_DRIVEN_FREE_FLOATING_BASE = (ConfigureProblem.stochastic_torque_driven_free_floating_base,)
TORQUE_DERIVATIVE_DRIVEN = (ConfigureProblem.torque_derivative_driven,)
TORQUE_ACTIVATIONS_DRIVEN = (ConfigureProblem.torque_activations_driven,)
JOINTS_ACCELERATION_DRIVEN = (ConfigureProblem.joints_acceleration_driven,)
Expand Down
Loading
Loading