Skip to content

Commit aedb16d

Browse files
Merge pull request #16 from iit-DLSLab/develop
MPX v0.1
2 parents 7d0c9fb + 06a4224 commit aedb16d

40 files changed

Lines changed: 3408 additions & 1206 deletions

.gitmodules

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
[submodule "primal_dual_ilqr"]
2-
path = mpx/primal_dual_ilqr
3-
url = https://github.com/iit-DLSLab/primal_dual_ilqr.git
1+
[submodule "jax_ocp_solvers"]
2+
path = mpx/jax_ocp_solvers
3+
url = https://github.com/iit-DLSLab/jax_ocp_solvers.git
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import os
2+
3+
import jax
4+
import jax.numpy as jnp
5+
6+
task_name = "acrobot_swingup"
7+
benchmark_mode = "direct"
8+
9+
dir_path = os.path.dirname(os.path.realpath(__file__))
10+
scene_path = os.path.abspath(os.path.join(dir_path, "..")) + "/data/acrobot/scene.xml"
11+
12+
N = 200
13+
n = 4
14+
m = 1
15+
dt = 0.01
16+
17+
m1 = 1.0
18+
m2 = 1.0
19+
l1 = 0.5
20+
l2 = 0.5
21+
lc1 = 0.5 * l1
22+
lc2 = 0.5 * l2
23+
g = 9.81
24+
I1 = m1 * l1 * l1 / 12.0
25+
I2 = m2 * l2 * l2 / 12.0
26+
27+
parameter = jnp.zeros(N + 1)
28+
reference = jnp.zeros(N + 1)
29+
30+
31+
def dynamics(x, u, t, parameter):
32+
del t, parameter
33+
theta1_dot = x[0]
34+
theta2_dot = x[1]
35+
theta1 = x[2]
36+
theta2 = x[3]
37+
38+
d11 = (
39+
I1
40+
+ I2
41+
+ m1 * lc1 * lc1
42+
+ m2 * (l1 * l1 + lc2 * lc2 + 2.0 * l1 * lc2 * jnp.cos(theta2))
43+
)
44+
d12 = I2 + m2 * (lc2 * lc2 + l1 * lc2 * jnp.cos(theta2))
45+
d21 = d12
46+
d22 = I2 + m2 * lc2 * lc2
47+
48+
c11 = -2.0 * m2 * l1 * lc2 * jnp.sin(theta2) * theta2_dot
49+
c12 = -m2 * l1 * lc2 * jnp.sin(theta2) * theta2_dot
50+
c21 = m2 * l1 * lc2 * jnp.sin(theta2) * theta1_dot
51+
c22 = 0.0
52+
53+
g1 = m1 * g * lc1 * jnp.sin(theta1) + m2 * g * (l1 * jnp.sin(theta1) + lc2 * jnp.sin(theta1 + theta2))
54+
g2 = m2 * lc2 * g * jnp.sin(theta1 + theta2)
55+
56+
D = jnp.array([[d11, d12], [d21, d22]])
57+
C = jnp.array([[c11, c12], [c21, c22]])
58+
G = jnp.array([g1, g2])
59+
60+
theta_dot = jnp.array([theta1_dot, theta2_dot])
61+
theta_dot_new = theta_dot + dt * jnp.linalg.inv(D) @ (jnp.array([0.0, u[0]]) - C @ theta_dot - G)
62+
theta_new = jnp.array([theta1, theta2]) + dt * theta_dot_new
63+
return jnp.concatenate([theta_dot_new, theta_new])
64+
65+
66+
x0 = jnp.array([0.0, 0.0, 0.0, 0.0])
67+
x_ref = jnp.array([0.0, 0.0, jnp.pi, 0.0])
68+
u_ref = jnp.array([0.0])
69+
70+
Q = jnp.diag(jnp.array([1e-5 / dt, 1e-5 / dt, 1e-5 / dt, 1e-5 / dt]))
71+
R = jnp.diag(jnp.array([1e-4 / dt]))
72+
Q_f = jnp.diag(jnp.array([10.0, 10.0, 100.0, 100.0]))
73+
W = jnp.zeros((N, 1))
74+
75+
76+
def cost(W, reference, x, u, t):
77+
del W, reference
78+
stage_cost = (x - x_ref).T @ Q @ (x - x_ref) + (u - u_ref).T @ R @ (u - u_ref)
79+
term_cost = (x - x_ref).T @ Q_f @ (x - x_ref)
80+
return jnp.where(t == N, 0.5 * term_cost, 0.5 * stage_cost)
81+
82+
83+
hessian_approx = None
84+
85+
86+
initial_X0 = jnp.tile(x0, (N + 1, 1))
87+
initial_U0 = jnp.tile(u_ref, (N, 1))
88+
initial_V0 = jnp.zeros((N + 1, n))
89+
90+
solver_mode = "fddp"
91+
92+
93+
def state_to_qpos(x):
94+
return x[2:]
95+
96+
97+
def state_to_qvel(x):
98+
return x[:2]

mpx/config/config_aliengo.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,27 @@
6363

6464
use_terrain_estimation = True # Flag to use terrain estimation
6565

66-
cost = partial(mpc_objectives.quadruped_wb_obj,True)
67-
hessian_approx = partial(mpc_objectives.quadruped_wb_hessian_gn,True)
68-
dynamics = mpc_dyn_model.quadruped_wb_dynamics
66+
_state_extra = n - (13 + 2 * n_joints + 3 * n_contact)
67+
initial_state = jnp.concatenate(
68+
[p0, quat0, q0, jnp.zeros(6 + n_joints), p_legs0, jnp.zeros(_state_extra)]
69+
)
70+
71+
cost = partial(mpc_objectives.quadruped_wb_obj, True, n_joints, n_contact, N)
72+
hessian_approx = None
73+
74+
def dynamics(model, mjx_model, contact_id, body_id):
75+
return partial(
76+
mpc_dyn_model.quadruped_wb_dynamics,
77+
model,
78+
mjx_model,
79+
contact_id,
80+
body_id,
81+
n_joints,
82+
dt,
83+
)
6984
# dynamics = mpc_dyn_model.quadruped_wb_dynamics_learned_contact_model
7085
# dynamics = mpc_dyn_model.quadruped_wb_dynamics_explicit_contact
7186
max_torque = 35
7287
min_torque = -35
88+
89+
solver_mode = "primal_dual" # Solver mode for the optimization problem
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from functools import partial
2+
3+
import mpx.config.config_aliengo as base
4+
import mpx.utils.mpc_utils as mpc_utils
5+
import mpx.utils.objectives as mpc_objectives
6+
7+
task_name = "aliengo_trot_two_step"
8+
9+
model_path = base.model_path
10+
contact_frame = base.contact_frame
11+
body_name = base.body_name
12+
13+
dt = 0.02
14+
N = 60
15+
mpc_frequency = base.mpc_frequency
16+
17+
timer_t = base.timer_t
18+
duty_factor = 0.5
19+
step_freq = base.step_freq
20+
step_height = 0.08
21+
initial_height = base.initial_height
22+
robot_height = base.robot_height
23+
24+
p0 = base.p0
25+
quat0 = base.quat0
26+
q0 = base.q0
27+
p_legs0 = base.p_legs0
28+
29+
n_joints = base.n_joints
30+
n_contact = base.n_contact
31+
n = base.n
32+
m = base.m
33+
grf_as_state = base.grf_as_state
34+
u_ref = base.u_ref
35+
36+
Qp = base.Qp
37+
Qrot = base.Qrot
38+
Qq = base.Qq
39+
Qdp = base.Qdp
40+
Qomega = base.Qomega
41+
Qdq = base.Qdq
42+
Qtau = base.Qtau
43+
Q_grf = base.Q_grf
44+
Qleg = base.Qleg
45+
W = base.W
46+
47+
use_terrain_estimation = False
48+
initial_state = base.initial_state
49+
50+
cost = partial(mpc_objectives.quadruped_wb_obj, True, n_joints, n_contact, N)
51+
hessian_approx = base.hessian_approx
52+
dynamics = base.dynamics
53+
54+
reference = partial(
55+
mpc_utils.reference_quadruped_trot_two_step,
56+
base_height=robot_height,
57+
total_forward=0.45,
58+
step_length=0.16,
59+
step_height=step_height,
60+
settle_time=0.10,
61+
phase_time=0.16,
62+
)
63+
64+
solver_mode = "fddp"
65+
max_torque = base.max_torque
66+
min_torque = base.min_torque

mpx/config/config_barrel_roll.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,26 @@
8282

8383
use_terrain_estimation = True # Flag to use terrain estimation
8484

85-
cost = partial(mpc_objectives.quadruped_wb_obj,False)
86-
hessian_approx = partial(mpc_objectives.quadruped_wb_hessian_gn,False)
87-
dynamics = mpc_dyn_model.quadruped_wb_dynamics
85+
_state_extra = n - (13 + 2 * n_joints + 3 * n_contact)
86+
initial_state = jnp.concatenate(
87+
[p0, quat0, q0, jnp.zeros(6 + n_joints), p_legs0, jnp.zeros(_state_extra)]
88+
)
89+
90+
cost = partial(mpc_objectives.quadruped_wb_obj, False, n_joints, n_contact, N)
91+
hessian_approx = None
92+
93+
def dynamics(model, mjx_model, contact_id, body_id):
94+
return partial(
95+
mpc_dyn_model.quadruped_wb_dynamics,
96+
model,
97+
mjx_model,
98+
contact_id,
99+
body_id,
100+
n_joints,
101+
dt,
102+
)
88103
reference = mpc_utils.reference_barell_roll
104+
solver_mode = "fddp" # Solver mode for the optimization problem
89105
# dynamics = mpc_dyn_model.quadruped_wb_dynamics_learned_contact_model
90106
# dynamics = mpc_dyn_model.quadruped_wb_dynamics_explicit_contact
91107
max_torque = 40

mpx/config/config_go2.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,24 @@
6464

6565
use_terrain_estimation = True # Flag to use terrain estimation
6666

67-
cost = partial(mpc_objectives.quadruped_wb_obj,True)
68-
hessian_approx = partial(mpc_objectives.quadruped_wb_hessian_gn,True)
69-
dynamics = mpc_dyn_model.quadruped_wb_dynamics
67+
_state_extra = n - (13 + 2 * n_joints + 3 * n_contact)
68+
initial_state = jnp.concatenate(
69+
[p0, quat0, q0, jnp.zeros(6 + n_joints), p_legs0, jnp.zeros(_state_extra)]
70+
)
71+
72+
cost = partial(mpc_objectives.quadruped_wb_obj, True, n_joints, n_contact, N)
73+
hessian_approx = None
74+
75+
def dynamics(model, mjx_model, contact_id, body_id):
76+
return partial(
77+
mpc_dyn_model.quadruped_wb_dynamics,
78+
model,
79+
mjx_model,
80+
contact_id,
81+
body_id,
82+
n_joints,
83+
dt,
84+
)
7085
# dynamics = mpc_dyn_model.quadruped_wb_dynamics_learned_contact_model
7186
# dynamics = mpc_dyn_model.quadruped_wb_dynamics_explicit_contact
7287
max_torque = 25

mpx/config/config_h1.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import mpx.utils.objectives as mpc_objectives
55
import os
66
import sys
7+
from functools import partial
78
dir_path = os.path.dirname(os.path.realpath(__file__))
89
model_path = os.path.abspath(os.path.join(dir_path, '..')) + '/data/unitree_h1/mjx_h1_walk_real_feet.xml' # Path to the MuJoCo model XML file
910
# Joint names and related configuration
@@ -75,9 +76,26 @@
7576

7677
use_terrain_estimation = False # Flag to use terrain estimation
7778

78-
cost = mpc_objectives.h1_wb_obj
79-
hessian_approx = mpc_objectives.h1_wb_hessian_gn
80-
dynamics = mpc_dyn_model.h1_wb_dynamics
79+
_state_extra = n - (13 + 2 * n_joints + 3 * n_contact)
80+
initial_state = jnp.concatenate(
81+
[p0, quat0, q0, jnp.zeros(6 + n_joints), p_legs0, jnp.zeros(_state_extra)]
82+
)
83+
84+
cost = partial(mpc_objectives.h1_wb_obj, n_joints, n_contact, N)
85+
hessian_approx = None
86+
87+
def dynamics(model, mjx_model, contact_id, body_id):
88+
return partial(
89+
mpc_dyn_model.h1_wb_dynamics,
90+
model,
91+
mjx_model,
92+
contact_id,
93+
body_id,
94+
n_joints,
95+
dt,
96+
)
97+
98+
solver_mode = "primal_dual" # Solver mode for the optimization problem
8199

82100
max_torque = 1000
83-
min_torque = -1000
101+
min_torque = -1000
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from functools import partial
2+
3+
import mpx.config.config_h1_kinodynamic as base
4+
import mpx.utils.mpc_utils as mpc_utils
5+
import mpx.utils.objectives as mpc_objectives
6+
7+
task_name = "h1_jump_forward"
8+
9+
model_path = base.model_path
10+
contact_frame = base.contact_frame
11+
body_name = base.body_name
12+
13+
dt = 0.02
14+
N = 50
15+
mpc_frequency = base.mpc_frequency
16+
17+
timer_t = base.timer_t
18+
duty_factor = 1.0
19+
step_freq = base.step_freq
20+
step_height = base.step_height
21+
initial_height = base.initial_height
22+
robot_height = base.robot_height
23+
24+
p0 = base.p0
25+
quat0 = base.quat0
26+
q0 = base.q0
27+
p_legs0 = base.p_legs0
28+
29+
n_joints = base.n_joints
30+
n_contact = base.n_contact
31+
n = base.n
32+
m = base.m
33+
grf_as_state = base.grf_as_state
34+
u_ref = base.u_ref
35+
W = base.W
36+
use_terrain_estimation = False
37+
initial_state = base.initial_state
38+
39+
joint_kp = base.joint_kp
40+
joint_kd = base.joint_kd
41+
torque_limits = base.torque_limits
42+
43+
cost = partial(mpc_objectives.h1_kinodynamic_obj, n_joints, n_contact, N)
44+
hessian_approx = base.hessian_approx
45+
dynamics = base.dynamics
46+
MPCWrapper = base.MPCWrapper
47+
48+
reference = partial(
49+
mpc_utils.reference_humanoid_jump_forward,
50+
base_height=robot_height,
51+
crouch_height=0.82,
52+
apex_height=1.02,
53+
jump_distance=0.35,
54+
foot_shift=0.18,
55+
foot_lift=0.10,
56+
)
57+
58+
solver_mode = "fddp"
59+
max_torque = base.max_torque
60+
min_torque = base.min_torque

0 commit comments

Comments
 (0)