-
Notifications
You must be signed in to change notification settings - Fork 48
/
Copy pathstatic_arm_with_contact.py
123 lines (101 loc) · 3.44 KB
/
static_arm_with_contact.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
"""
This is a basic example on how to use biorbd model driven by muscle to perform an optimal reaching task with a
contact dynamics.
The arms must reach a marker placed upward in front while minimizing the muscles activity
Please note that using show_meshes=True in the animator may be long due to the creation of a huge CasADi graph of the
mesh points.
"""
import platform
from bioptim import (
BiorbdModel,
OptimalControlProgram,
ObjectiveList,
ObjectiveFcn,
DynamicsList,
DynamicsFcn,
BoundsList,
InitialGuessList,
OdeSolver,
OdeSolverBase,
Solver,
)
def prepare_ocp(
biorbd_model_path: str,
final_time: float,
n_shooting: int,
weight: float,
ode_solver: OdeSolverBase = OdeSolver.RK4(),
) -> OptimalControlProgram:
"""
Prepare the ocp
Parameters
----------
biorbd_model_path: str
The path to the bioMod
final_time: float
The time at the final node
n_shooting: int
The number of shooting points
weight: float
The weight applied to the SUPERIMPOSE_MARKERS final objective function. The bigger this number is, the greater
the model will try to reach the marker. This is in relation with the other objective functions
ode_solver: OdeSolverBase
The ode solver to use
Returns
-------
The OptimalControlProgram ready to be solved
"""
bio_model = BiorbdModel(biorbd_model_path)
# Add objective functions
objective_functions = ObjectiveList()
objective_functions.add(ObjectiveFcn.Lagrange.MINIMIZE_CONTROL, key="tau")
objective_functions.add(ObjectiveFcn.Lagrange.MINIMIZE_CONTROL, key="muscles")
objective_functions.add(
ObjectiveFcn.Mayer.SUPERIMPOSE_MARKERS, first_marker="target", second_marker="COM_hand", weight=weight
)
# Dynamics
dynamics = DynamicsList()
dynamics.add(DynamicsFcn.MUSCLE_DRIVEN, with_residual_torque=True, with_contact=True)
# raise RuntimeError("This example is broken, since contact dynamics with muscle is not implemented")
# Path constraint
x_bounds = BoundsList()
x_bounds.add(bounds=bio_model.bounds_from_ranges(["q", "qdot"]))
x_bounds[0][:, 0] = (0, 0.07, 1.4, 0, 0, 0)
# Initial guess
x_init = InitialGuessList()
x_init.add([1.57] * bio_model.nb_q + [0] * bio_model.nb_qdot)
# Define control path constraint
muscle_min, muscle_max, muscle_init = 0.0, 1.0, 0.5
tau_min, tau_max, tau_init = -1.0, 1.0, 0.0
u_bounds = BoundsList()
u_bounds.add(
[tau_min] * bio_model.nb_tau + [muscle_min] * bio_model.nb_muscles,
[tau_max] * bio_model.nb_tau + [muscle_max] * bio_model.nb_muscles,
)
u_init = InitialGuessList()
u_init.add([tau_init] * bio_model.nb_tau + [muscle_init] * bio_model.nb_muscles)
# ------------- #
return OptimalControlProgram(
bio_model,
dynamics,
n_shooting,
final_time,
x_init,
u_init,
x_bounds,
u_bounds,
objective_functions,
ode_solver=ode_solver,
)
def main():
"""
Prepare and solve and animate a reaching task ocp
"""
ocp = prepare_ocp(biorbd_model_path="models/arm26_with_contact.bioMod", final_time=1, n_shooting=30, weight=1000)
# --- Solve the program --- #
sol = ocp.solve(Solver.IPOPT(show_online_optim=platform.system() == "Linux"))
# --- Show results --- #
sol.print_cost()
sol.animate()
if __name__ == "__main__":
main()