Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 12 additions & 3 deletions bioptim/limits/penalty.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def minimize_states(penalty: PenaltyOption, controller: PenaltyController, key:
penalty.add_target_to_plot(controller=controller, combine_to=f"{key}_states")
penalty.multi_thread = True if penalty.multi_thread is None else penalty.multi_thread

# TODO: We should scale the target here!
# States exposed by the controller are already unscaled, so targets are expressed in physical units.
return controller.states[key].cx_start

@staticmethod
Expand All @@ -109,7 +109,7 @@ def minimize_controls(penalty: PenaltyOption, controller: PenaltyController, key
penalty.add_target_to_plot(controller=controller, combine_to=f"{key}_controls")
penalty.multi_thread = True if penalty.multi_thread is None else penalty.multi_thread

# TODO: We should scale the target here!
# Controls exposed by the controller are already unscaled, so targets are expressed in physical units.
return controller.controls[key].cx_start

@staticmethod
Expand Down Expand Up @@ -1355,7 +1355,16 @@ def minimize_parameter(penalty: PenaltyOption, controller: PenaltyController, ke
penalty.quadratic = True if penalty.quadratic is None else penalty.quadratic
penalty.multi_thread = True if penalty.multi_thread is None else penalty.multi_thread

return controller.parameters.cx if key is None or key == "all" else controller.parameters[key].cx
if key is None or key == "all":
return vertcat(
*(
controller.parameters[parameter_key].cx
* controller.parameters[parameter_key].scaling.scaling
for parameter_key in controller.parameters.keys()
)
)

return controller.parameters[key].cx * controller.parameters[key].scaling.scaling

@staticmethod
def add(ocp, nlp):
Expand Down
18 changes: 18 additions & 0 deletions tests/shard6/test_penalty.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
TorqueActivationBiorbdModel,
DynamicsOptions,
ObjectiveWeight,
ParameterList,
VariableScaling,
)
from bioptim.limits.penalty import PenaltyOption
from bioptim.limits.penalty_controller import PenaltyController
Expand Down Expand Up @@ -249,6 +251,22 @@ def test_penalty_minimize_state(penalty_origin, value, phase_dynamics):
npt.assert_almost_equal(res, np.array([[value]] * 4))


@pytest.mark.parametrize("key", ["gravity", "all", None])
def test_penalty_minimize_parameter_returns_physical_values(key):
parameters = ParameterList(use_sx=False)
parameters.add("gravity", lambda *_: None, size=2, scaling=VariableScaling("gravity", [10, 100]))
parameters.add("mass", lambda *_: None, size=1, scaling=VariableScaling("mass", [5]))

controller = type("Controller", (), {"parameters": parameters})()
penalty = type("Penalty", (), {"quadratic": None, "multi_thread": None})()
value = ObjectiveFcn.Parameter.MINIMIZE_PARAMETER(penalty, controller, key=key)
function = Function("physical_parameter", [parameters.cx], [value])

result = np.array(function([2, 3, 4])).squeeze()
expected = np.array([20, 300]) if key == "gravity" else np.array([20, 300, 20])
npt.assert_equal(result, expected)


@pytest.mark.parametrize("phase_dynamics", [PhaseDynamics.SHARED_DURING_THE_PHASE, PhaseDynamics.ONE_PER_NODE])
@pytest.mark.parametrize("penalty_origin", [ObjectiveFcn.Lagrange, ObjectiveFcn.Mayer])
@pytest.mark.parametrize("value", [0.1, -10])
Expand Down
Loading