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

Major refactor towards 3.2.0 #814

Merged
merged 183 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
183 commits
Select commit Hold shift + click to select a range
3dfff2e
Pendulum working with the time as parameter
pariterre Nov 15, 2023
b88933e
Fixing Mayer min time
pariterre Nov 15, 2023
55874c1
Transitionning towards t_span being [t0; tf] instead of [t0; dt]
pariterre Nov 16, 2023
680949b
Fixing multi_phase time optimization
pariterre Nov 16, 2023
58723b1
Fixed plots
pariterre Nov 16, 2023
26166af
Made IRK work on pendulum
pariterre Nov 16, 2023
9a1e67a
Removed useless duplication of code
pariterre Nov 17, 2023
c8384e9
Fixed GUI for COLLOCATIONS
pariterre Nov 17, 2023
385ab2f
Fixed COLLOCATION
pariterre Nov 17, 2023
dde332a
Fixed IRK integration
pariterre Nov 17, 2023
3c75c8d
Fixed computation of objective function with threads
pariterre Nov 17, 2023
084450e
Rebuilding time vector in solution from ground up
pariterre Nov 20, 2023
a2c9b0e
Digging my own grave...
pariterre Nov 20, 2023
2eb22a3
Drastically simplified Solution to build it from ground up. Interpola…
pariterre Nov 21, 2023
93bbb0b
Simplified OdeSolver and Integrator classes
pariterre Nov 22, 2023
244d865
Started a data structure that can manipulate the decision data
pariterre Nov 22, 2023
00ea1ef
Fixed graphics for RK
pariterre Nov 22, 2023
7858e7d
Fixed interpolation and animation for RK
pariterre Nov 23, 2023
07181b1
Fixed IRK for integration, interpolation, gui
pariterre Nov 23, 2023
a6cd9cf
Started to use a dedicated helper to dispatch data for the penalty
pariterre Nov 23, 2023
7e1e6b5
Simplified get penalty cost in solution
pariterre Nov 24, 2023
7760aff
Fixed distribution of data in COLLOCATION
pariterre Nov 24, 2023
8da4193
Renamed a function that was confusing
pariterre Nov 24, 2023
0ff02fc
Fixed graphs for COLLOCATION
pariterre Nov 24, 2023
ffd7952
Cleaned a bit
pariterre Nov 24, 2023
6f2f81a
Started to fix Multinodes
pariterre Nov 24, 2023
5664f44
Fixed some index issues
pariterre Nov 27, 2023
b782348
Fixed nasty bug in dt dispatch
pariterre Nov 27, 2023
0b4fc6e
Fixed dispatching bug for final node of control in multiphase
pariterre Nov 27, 2023
8d17e77
Fixed time for multiphase plots
pariterre Nov 27, 2023
81dff2d
Fixed phase transition with collocation
pariterre Nov 27, 2023
0833d38
Fixed custom plot
pariterre Nov 27, 2023
4800f60
Fixed ONE_PER_NODE
pariterre Nov 27, 2023
5031c40
Fixed ONE_PER_NODE for COLLOCATION
pariterre Nov 28, 2023
5e7cd55
Updated time optimization examples
pariterre Nov 28, 2023
576fdb9
Fixed some indices problems
pariterre Nov 28, 2023
5863bbe
Added somes output for the solution
pariterre Nov 28, 2023
1cc2734
Fixed multiprocessing
pariterre Nov 28, 2023
a1c181c
Fixed penalty derivative
pariterre Nov 28, 2023
bd7fd8d
Fixing tests. Still multiphase_time optimization to go and parameters
pariterre Nov 28, 2023
c9cf9a3
Consolidated SolutionData
pariterre Nov 29, 2023
776721b
Fixed scaling formatting
pariterre Nov 29, 2023
a726bdc
Fixed parameter scaling (to be completed)
pariterre Nov 29, 2023
fe96941
Fixed interpolation merging phase timing
pariterre Nov 29, 2023
0f3d414
Fixed yet again some more tests
pariterre Nov 29, 2023
421deea
Fixed MHE
pariterre Nov 29, 2023
0c70af2
FIxed graphs for control linear
pariterre Nov 30, 2023
37ab85a
Fixed more bugs
pariterre Nov 30, 2023
6f2631d
Trying to fix LINEAR_CONTINUOUS integration
pariterre Nov 30, 2023
d936e72
Fixed trapezoidal for RK
pariterre Dec 1, 2023
cc820c0
Fixed TRAPEZOIDAL for COLLOCATION
pariterre Dec 1, 2023
7e361ef
Fixed trapezoidal integrator
pariterre Dec 1, 2023
a0d75a4
fixed some more tests
pariterre Dec 1, 2023
5fbe0c9
Fixed multicyclic NMPC
pariterre Dec 1, 2023
7279d73
Fixed time tests
pariterre Dec 1, 2023
c968d67
Fixed time related tests
pariterre Dec 1, 2023
706e80a
Fixed objective derivative
pariterre Dec 1, 2023
fc98614
Added phase transitions to the integration
pariterre Dec 4, 2023
4d184e6
Fixed typo in track marker example
pariterre Dec 4, 2023
262b6fd
Fixed more tests
pariterre Dec 4, 2023
373eb82
Typo?
pariterre Dec 4, 2023
2766bf0
Added shake tree for objectives and constraints
pariterre Dec 4, 2023
a732373
Adjusted some tests
pariterre Dec 4, 2023
5cc75e4
fixed graph tests
pariterre Dec 4, 2023
fbc1677
Fixed tests ligaments
pariterre Dec 4, 2023
a4d6081
Fixed paramters scaling declaration
pariterre Dec 4, 2023
76cbcae
Started to clean
pariterre Dec 4, 2023
41130fb
Fixed muscle tracking for COLLOCATION
pariterre Dec 4, 2023
8db846d
Standardized output time
pariterre Dec 4, 2023
037a813
Added capability to skip expand when shaking tree
pariterre Dec 4, 2023
f9f8ff0
Removed fake setter in transition of penalty (may be a bad idea)
pariterre Dec 4, 2023
1d108c4
Not much have to go
EveCharbie Dec 6, 2023
4cc9646
init OK, still need to fix penalty cx_intermediate (shape4)? multi-thred
EveCharbie Dec 6, 2023
a834181
My suggestion of refactor for the creation of penalty_option Functions
EveCharbie Dec 7, 2023
2107e7e
test
Dec 7, 2023
f43dc5f
trying to set back correct time phase
Dec 8, 2023
f12b9b1
transferred to states, controls, stochastic_variables
EveCharbie Dec 8, 2023
f1898c3
setting back time phase correctly
Dec 8, 2023
b660f4d
Added the capability to allow free variables in the integrator
pariterre Dec 8, 2023
56d2eb8
trying to fix test
Dec 9, 2023
c93bf34
tried to switch to lambda fcn
EveCharbie Dec 10, 2023
d2d2079
_get_weighted_function_inputs_from_controller ok?
EveCharbie Dec 10, 2023
c89c600
all pendulum tests pass
EveCharbie Dec 10, 2023
873ed53
penalty.transition is fucked up
EveCharbie Dec 10, 2023
3d2aa34
removed ode_opt["idx"] following pariterre's confirmation
EveCharbie Dec 10, 2023
0956b95
still wrong values, but ONE_PER_NODE is fixed
EveCharbie Dec 10, 2023
ddadb2c
fixed derivative
EveCharbie Dec 11, 2023
e76e038
Fixed bunch of tests in test_penalty
pariterre Dec 12, 2023
6b8d634
Reverted some changes in ode_solver
pariterre Dec 12, 2023
485c9a3
Merge remote-tracking branch 'pariterre/master' into fixing_control_t…
Dec 12, 2023
2fa5e1c
Auto stash before merge of "node_time_mx" and "pyomeca/master"
Dec 12, 2023
86a7736
trial
Dec 12, 2023
e4e9a09
Forced to revert the idx in integrator as external forces was not int…
pariterre Dec 12, 2023
6b72b5b
Simplified the logic for PenaltyHelpers
pariterre Dec 12, 2023
b8f2036
sol.state to sol.decision_state
Dec 12, 2023
c07adbc
making optimization to converge
Dec 12, 2023
ac81c37
Introduced subnodes in penalty to unify construction and usage
pariterre Dec 12, 2023
64a4412
Started to fix multinodes
pariterre Dec 12, 2023
d744917
Continued fixing multiphase and fixed MHE
pariterre Dec 13, 2023
d24cf98
Still dealing with multinodes
pariterre Dec 13, 2023
d6ccbe7
factored multinode dispatch in PenaltyHelpers
pariterre Dec 14, 2023
fb6beae
Fixed plotting dispatch issue and removed ControlType.NONE, removed t…
pariterre Dec 14, 2023
1e10804
Removed save/load features
pariterre Dec 14, 2023
c5b8567
Fixed MHE
pariterre Dec 14, 2023
10db21e
same
pariterre Nov 14, 2023
9adad7a
Final non passing tests fix
pariterre Nov 14, 2023
230bd6b
Merge remote-tracking branch 'pariterre/master' into fixing_control_t…
Dec 14, 2023
30eeddf
Added the capability to allow free variables in the integrator
pariterre Dec 14, 2023
acd6147
Fixed scaling variables
pariterre Dec 14, 2023
a2cc07a
FOR REFERENCE removed fake penalty for derivative
pariterre Dec 14, 2023
757fe1c
Finishing derivative for controls
pariterre Dec 14, 2023
32ee1bd
Merge remote-tracking branch 'pariterre/master' into fixing_control_t…
Dec 14, 2023
88ffa90
test
Dec 14, 2023
a3b8238
.
Dec 14, 2023
186f6e4
added time as states test
Dec 15, 2023
56b2e14
previous time phase from dt_mx instead of tf
Dec 15, 2023
30177ae
Fixing penalty with derivative
pariterre Dec 15, 2023
ab6d0f6
Fixing linear_continuous controls
pariterre Dec 15, 2023
352bf2b
Fixed t_span in continuity
pariterre Dec 15, 2023
a5f009a
Starting to fix trapezoidal
pariterre Dec 15, 2023
4049ec7
Just realised that phase_dynamics checking did not even make sense in…
pariterre Dec 16, 2023
e9259d1
FIxed TRAPEZOIDAL
pariterre Dec 16, 2023
91937e8
Fixed linear_continous
pariterre Dec 16, 2023
3bb11a2
Just realized that we do not care of the type of integration when dis…
pariterre Dec 16, 2023
da0e300
Just realized the same for states, and fixed collocations
pariterre Dec 16, 2023
e41c3da
Fixed check_conditionning
pariterre Dec 17, 2023
df7f678
Fixed Mayer in multi_thread and plots of fatigue
pariterre Dec 17, 2023
c48c754
Simplifying targets
pariterre Dec 17, 2023
277d405
Fixed target
pariterre Dec 17, 2023
7686217
reverted a test changed before
pariterre Dec 17, 2023
52498b6
Fixing derivate=True
pariterre Dec 17, 2023
608c41a
Fixed derivative penalties
pariterre Dec 17, 2023
6cb1bd9
Fixed cyclic and multicyclic export
pariterre Dec 17, 2023
40ba8e1
Fixed IOCP test
pariterre Dec 17, 2023
ab2005e
Fixed SQP
pariterre Dec 17, 2023
556fec6
Fixed graphs
pariterre Dec 17, 2023
b8cf34f
Allowed for not phase mergeable animation
pariterre Dec 17, 2023
aa49f49
fixing stochastic examples
pariterre Dec 17, 2023
bcc124c
BUG EMULATION SO THE RESULTS DON'T CHANGE
pariterre Dec 17, 2023
1bae8b1
Better fix for MultiCyclic
pariterre Dec 18, 2023
b82135a
Fixed control dispatching in warm start
pariterre Dec 18, 2023
b01b6e9
Fixed multinodes in IRK
pariterre Dec 18, 2023
cc0e577
Cleaned a bit
pariterre Dec 18, 2023
8f58579
Fix dispatch of bound min and ma x in torque_max_from_q_and_qdot
pariterre Dec 18, 2023
107adea
Adapated TrackMarker
pariterre Dec 18, 2023
ff1d29f
Fixed dispatch of markers in animation for collocations
pariterre Dec 18, 2023
c58fe9f
Better initial guess to converget to same solution
pariterre Dec 18, 2023
e549093
fixed receding horizon again
pariterre Dec 18, 2023
12cf55d
Fixed time related tests in shared4
pariterre Dec 18, 2023
06642e4
Brought back solve_ivp from scipy for multiple shooting
pariterre Dec 18, 2023
5f73086
And single shoot
pariterre Dec 18, 2023
9b0a976
Added LINEAR_CONTINUOUS to interpolate (still fails)
pariterre Dec 18, 2023
91a8877
Cleaning helper (may fail?)
pariterre Dec 18, 2023
a9cde99
fixing
pariterre Dec 18, 2023
e6ef35c
refactored integration
pariterre Dec 19, 2023
e330c0a
Merge remote-tracking branch 'pariterre/master' into fixing_control_t…
Dec 19, 2023
67d541b
Fixed integration with phase merging
pariterre Dec 19, 2023
a5ee9e2
one phase test working for time_as_state
Dec 19, 2023
86ae890
Fully committed to not providing states and control property accessor…
pariterre Dec 19, 2023
0c6328e
Added capability to fetch continuous time across phases
pariterre Dec 19, 2023
b28cd65
Rewrote the time tests
pariterre Dec 19, 2023
768c89e
Fixed variational ocp
pariterre Dec 20, 2023
39452a1
Remove a deprecated test
pariterre Dec 20, 2023
e0bcf41
Fixed more broken link with removal of states and controls properties
pariterre Dec 20, 2023
fd6c438
Loosen a test on time
pariterre Dec 20, 2023
6c1e5d6
Merge branch 'master' into fixing_control_type_none_test
pariterre Dec 20, 2023
ad0dc37
Changed name of stochastic_variables for algebraic_states
pariterre Dec 20, 2023
08f27ed
Added one a
pariterre Dec 20, 2023
c94d302
Fixing more stochastic variables names
pariterre Dec 20, 2023
3e7a1c4
Started to fix stochastic ocp
pariterre Dec 20, 2023
9a6a508
Continue
pariterre Dec 20, 2023
519e48d
Continuing cleaning stochastic
pariterre Dec 21, 2023
cce6f49
Stochastic is almost there
pariterre Dec 21, 2023
68cb7c9
Fixed a bug when algebraic is None
pariterre Dec 21, 2023
2080bae
Typo
pariterre Dec 21, 2023
40b6ae3
Fixed most of acados tests
pariterre Dec 21, 2023
6de04f6
Fixing last acados tests
pariterre Dec 21, 2023
eea4f73
Fixed bug in parameters
pariterre Dec 21, 2023
9b6c9e0
Removing non-passing test for final push
pariterre Dec 21, 2023
8e84388
Changed version file for 3.2.0
pariterre Dec 21, 2023
d853a5e
Black the shit out the major thing!
pariterre Dec 21, 2023
6b17fd6
Merge branch 'master' into tata3
pariterre Dec 21, 2023
5715e1e
Fix version bug if developing version does not match relaase version
pariterre Dec 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions Notes
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
currently broken:
- ACADOS
- Linear_continous control
- No control
- Collocation and objective NODE.ALL
- Time vector in collocation (and integration)
- CVODES
1 change: 1 addition & 0 deletions bioptim/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@
)
from .optimization.parameters import ParameterList
from .optimization.solution.solution import Solution
from .optimization.solution.solution_data import SolutionMerge, TimeAlignment
from .optimization.optimization_variable import OptimizationVariableList
from .optimization.variable_scaling import VariableScalingList, VariableScaling
from .optimization.variational_optimal_control_program import VariationalOptimalControlProgram
Expand Down
129 changes: 72 additions & 57 deletions bioptim/dynamics/configure_new_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@
import numpy as np

from .fatigue.fatigue_dynamics import FatigueList, MultiFatigueInterface
from .ode_solver import OdeSolver
from ..gui.plot import CustomPlot
from ..limits.path_conditions import Bounds
from ..misc.enums import PlotType, ControlType, VariableType, PhaseDynamics
from ..misc.mapping import BiMapping


def variable_type_from_booleans_to_enums(
as_states: bool, as_controls: bool, as_states_dot: bool, as_stochastic: bool
as_states: bool, as_controls: bool, as_states_dot: bool, as_algebraic_states: bool
) -> list[VariableType]:
"""
Convert the booleans to enums
Expand All @@ -23,8 +22,8 @@ def variable_type_from_booleans_to_enums(
If the new variable should be added to the state_dot variable set
as_controls: bool
If the new variable should be added to the control variable set
as_stochastic: bool
If the new variable should be added to the stochastic variable set
as_algebraic_states: bool
If the new variable should be added to the algebraic states variable set

Returns
-------
Expand All @@ -38,21 +37,21 @@ def variable_type_from_booleans_to_enums(
variable_type.append(VariableType.STATES_DOT)
if as_controls:
variable_type.append(VariableType.CONTROLS)
if as_stochastic:
variable_type.append(VariableType.STOCHASTIC)
if as_algebraic_states:
variable_type.append(VariableType.ALGEBRAIC_STATES)
return variable_type


class NewVariableConfiguration:
# todo: add a way to remove the if as_states, as_controls, as_states_dot, as_stochastic, etc...
# todo: add a way to remove the if as_states, as_controls, as_states_dot, as_algebraic_states, etc...
# if we want to remove ocp, nlp, it
# should be a method of ocp, and specify the phase_idx where the variable is added
# ocp.configure_new_variable(
# phase_idx,
# name,
# name_elements,
# variable_type=variable_types,
# # VariableType.CONTROL, VariableType.STATE_DOT, VariableType.STOCHASTIC, VariableType.ALGEBRAIC_STATE
# # VariableType.CONTROL, VariableType.STATE_DOT, VariableType.ALGEBRAIC_STATE
# )
def __init__(
self,
Expand All @@ -63,7 +62,7 @@ def __init__(
as_states: bool,
as_controls: bool,
as_states_dot: bool = False,
as_stochastic: bool = False,
as_algebraic_states: bool = False,
fatigue: FatigueList = None,
combine_name: str = None,
combine_state_control_plot: bool = False,
Expand All @@ -89,8 +88,8 @@ def __init__(
If the new variable should be added to the state_dot variable set
as_controls: bool
If the new variable should be added to the control variable set
as_stochastic: bool
If the new variable should be added to the stochastic variable set
as_algebraic_states: bool
If the new variable should be added to the algebraic states variable set
fatigue: FatigueList
The list of fatigable item
combine_name: str
Expand All @@ -110,7 +109,7 @@ def __init__(
self.as_states = as_states
self.as_controls = as_controls
self.as_states_dot = as_states_dot
self.as_stochastic = as_stochastic
self.as_algebraic_states = as_algebraic_states
self.fatigue = fatigue
self.combine_name = combine_name
self.combine_state_control_plot = combine_state_control_plot
Expand All @@ -124,7 +123,7 @@ def __init__(
self.mx_states = None
self.mx_states_dot = None
self.mx_controls = None
self.mx_stochastic = None
self.mx_algebraic_states = None

self._check_combine_state_control_plot()

Expand Down Expand Up @@ -189,6 +188,10 @@ def _declare_phase_copy_booleans(self):
nlp, phase_idx, self.nlp.use_states_dot_from_phase_idx, self.name, "states_dot"
)

self.copy_algebraic_states = self.check_variable_copy_condition(
nlp, phase_idx, self.nlp.use_states_from_phase_idx, self.name, "algebraic_states"
)

@staticmethod
def check_variable_copy_condition(
nlp, phase_idx: int, use_from_phase_idx: int, name: str, decision_variable_attribute: str
Expand Down Expand Up @@ -302,8 +305,8 @@ def _declare_initial_guess(self):
self.name, initial_guess=np.zeros(len(self.nlp.variable_mappings[self.name].to_first.map_idx))
)

if self.as_stochastic and self.name not in self.nlp.s_init:
self.nlp.s_init.add(
if self.as_algebraic_states and self.name not in self.nlp.a_init:
self.nlp.a_init.add(
self.name, initial_guess=np.zeros(len(self.nlp.variable_mappings[self.name].to_first.map_idx))
)

Expand All @@ -320,8 +323,8 @@ def _declare_variable_scaling(self):
self.nlp.u_scaling.add(
self.name, scaling=np.ones(len(self.nlp.variable_mappings[self.name].to_first.map_idx))
)
if self.as_stochastic and self.name not in self.nlp.s_scaling:
self.nlp.s_scaling.add(
if self.as_algebraic_states and self.name not in self.nlp.a_scaling:
self.nlp.a_scaling.add(
self.name, scaling=np.ones(len(self.nlp.variable_mappings[self.name].to_first.map_idx))
)

Expand All @@ -341,7 +344,11 @@ def _use_copy(self):
if not self.copy_controls
else [self.ocp.nlp[self.nlp.use_controls_from_phase_idx].controls[0][self.name].mx]
)
self.mx_stochastic = []
self.mx_algebraic_states = (
[]
if not self.copy_algebraic_states
else [self.ocp.nlp[self.nlp.use_states_from_phase_idx].algebraic_states[0][self.name].mx]
)

# todo: if mapping on variables, what do we do with mapping on the nodes
for i in self.nlp.variable_mappings[self.name].to_second.map_idx:
Expand All @@ -360,12 +367,12 @@ def _use_copy(self):
if not self.copy_controls:
self.mx_controls.append(MX.sym(var_name, 1, 1))

self.mx_stochastic.append(MX.sym(var_name, 1, 1))
self.mx_algebraic_states.append(MX.sym(var_name, 1, 1))

self.mx_states = vertcat(*self.mx_states)
self.mx_states_dot = vertcat(*self.mx_states_dot)
self.mx_controls = vertcat(*self.mx_controls)
self.mx_stochastic = vertcat(*self.mx_stochastic)
self.mx_algebraic_states = vertcat(*self.mx_algebraic_states)

def _declare_auto_axes_idx(self):
"""Declare the axes index if not already declared"""
Expand All @@ -388,9 +395,9 @@ def _declare_legend(self):
def _declare_cx_and_plot(self):
if self.as_states:
for node_index in range(
(0 if self.nlp.phase_dynamics == PhaseDynamics.SHARED_DURING_THE_PHASE else self.nlp.ns) + 1
self.nlp.n_states_nodes if self.nlp.phase_dynamics == PhaseDynamics.ONE_PER_NODE else 1
):
n_cx = self.nlp.ode_solver.n_cx if isinstance(self.nlp.ode_solver, OdeSolver.COLLOCATION) else 3
n_cx = self.nlp.ode_solver.n_required_cx + 2
cx_scaled = (
self.ocp.nlp[self.nlp.use_states_from_phase_idx].states[node_index][self.name].original_cx
if self.copy_states
Expand All @@ -411,7 +418,9 @@ def _declare_cx_and_plot(self):
)
if not self.skip_plot:
self.nlp.plot[f"{self.name}_states"] = CustomPlot(
lambda t, x, u, p, s: x[self.nlp.states[self.name].index, :],
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 All @@ -420,19 +429,7 @@ def _declare_cx_and_plot(self):

if self.as_controls:
for node_index in range(
(
1
if self.nlp.phase_dynamics == PhaseDynamics.SHARED_DURING_THE_PHASE
else (
self.nlp.ns
+ +(
1
if self.nlp.control_type
in (ControlType.LINEAR_CONTINUOUS, ControlType.CONSTANT_WITH_LAST_NODE)
else 0
)
)
)
self.nlp.n_controls_nodes if self.nlp.phase_dynamics == PhaseDynamics.ONE_PER_NODE else 1
):
cx_scaled = (
self.ocp.nlp[self.nlp.use_controls_from_phase_idx].controls[node_index][self.name].original_cx
Expand All @@ -456,7 +453,9 @@ 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 t, x, u, p, s: u[self.nlp.controls[self.name].index, :],
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,
Expand All @@ -467,15 +466,9 @@ def _declare_cx_and_plot(self):

if self.as_states_dot:
for node_index in range(
(0 if self.nlp.phase_dynamics == PhaseDynamics.SHARED_DURING_THE_PHASE else self.nlp.ns) + 1
self.nlp.n_states_nodes if self.nlp.phase_dynamics == PhaseDynamics.ONE_PER_NODE else 1
):
n_cx = (
self.nlp.ode_solver.polynomial_degree + 1
if isinstance(self.nlp.ode_solver, OdeSolver.COLLOCATION)
else 3
)
if n_cx < 3:
n_cx = 3
n_cx = self.nlp.ode_solver.n_required_cx + 2
cx_scaled = (
self.ocp.nlp[self.nlp.use_states_dot_from_phase_idx].states_dot[node_index][self.name].original_cx
if self.copy_states_dot
Expand All @@ -495,19 +488,27 @@ def _declare_cx_and_plot(self):
node_index,
)

if self.as_stochastic:
if self.as_algebraic_states:
for node_index in range(
(0 if self.nlp.phase_dynamics == PhaseDynamics.SHARED_DURING_THE_PHASE else self.nlp.ns) + 1
self.nlp.n_states_nodes if self.nlp.phase_dynamics == PhaseDynamics.ONE_PER_NODE else 1
):
n_cx = 3
cx_scaled = self.define_cx_scaled(n_col=n_cx, n_shooting=1, initial_node=node_index)
cx = self.define_cx_unscaled(cx_scaled, self.nlp.s_scaling[self.name].scaling)
n_cx = 2
cx_scaled = (
self.ocp.nlp[self.nlp.use_states_from_phase_idx].algebraic_states[node_index][self.name].original_cx
if self.copy_algebraic_states
else self.define_cx_scaled(n_col=n_cx, n_shooting=0, initial_node=node_index)
)
cx = (
self.ocp.nlp[self.nlp.use_states_from_phase_idx].algebraic_states[node_index][self.name].original_cx
if self.copy_algebraic_states
else self.define_cx_unscaled(cx_scaled, self.nlp.a_scaling[self.name].scaling)
)

self.nlp.stochastic_variables.append(
self.nlp.algebraic_states.append(
self.name,
cx[0],
cx_scaled[0],
self.mx_stochastic,
self.mx_states,
self.nlp.variable_mappings[self.name],
node_index,
)
Expand Down Expand Up @@ -570,14 +571,22 @@ def _manage_fatigue_to_new_variable(
legend = [f"{name}_{i}" for i in name_elements]
fatigue_plot_name = f"fatigue_{name}"
nlp.plot[fatigue_plot_name] = CustomPlot(
lambda t, x, u, p, s: x[:n_elements, :] * np.nan,
lambda t0, phases_dt, node_idx, x, u, p, a: (
x[:n_elements, :] if x.any() else np.ndarray((len(name_elements), 1))
)
* np.nan,
plot_type=PlotType.INTEGRATED,
legend=legend,
bounds=Bounds(None, -1, 1),
)
control_plot_name = f"{name}_controls" if not multi_interface and split_controls else f"{name}"
nlp.plot[control_plot_name] = CustomPlot(
lambda t, x, u, p, s: u[:n_elements, :] * np.nan, plot_type=PlotType.STEP, legend=legend
lambda t0, phases_dt, node_idx, x, u, p, a: (
u[:n_elements, :] if u.any() else np.ndarray((len(name_elements), 1))
)
* np.nan,
plot_type=PlotType.STEP,
legend=legend,
)

var_names_with_suffix = []
Expand All @@ -592,7 +601,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 t, x, u, p, s, key: u[nlp.controls[key].index, :],
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 @@ -601,7 +612,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 t, x, u, p, s, key: u[nlp.controls[key].index, :],
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 @@ -612,7 +625,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 t, x, u, p, s, key, mod: mod * x[nlp.states[key].index, :],
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