17 const auto inf = std::numeric_limits<real_t>::infinity();
19 auto n_masses =
static_cast<index_t
>(p.
masses.size());
20 const index_t ny_x = p.
v_max > 0 ? 2 * n_masses : n_masses,
21 ny_x_N = p.
v_max_f > 0 ? 2 * n_masses : n_masses;
29 auto [N, nx, nu, ny, ny_N] = ocp.
dim;
32 eigen_mat A = eigen_mat::Zero(nx, nx), B = eigen_mat::Zero(nx, nu), b = eigen_mat::Zero(nx, 1);
33 for (Eigen::Index
v = 0;
v < n_masses; ++
v) {
35 A(
v, n_masses +
v) = 1;
37 A(n_masses +
v,
v) = -2 * km;
39 A(n_masses +
v,
v - 1) = km;
41 A(n_masses +
v,
v + 1) = km;
43 b(n_masses +
v, 0) = km * p.
width;
48 B(n_masses + a, a) = 1 / p.
masses[a];
51 std::mt19937 rng(p.
seed);
52 std::vector<index_t> actuator_indices(n_masses);
53 std::ranges::iota(actuator_indices, index_t{});
54 std::shuffle(actuator_indices.begin(), actuator_indices.end(), rng);
56 B(n_masses + actuator_indices[a], a) = 1 / p.
masses[actuator_indices[a]];
59 std::mt19937 rng(p.
seed);
60 std::vector<index_t> actuator_indices_l(n_masses), actuator_indices_r(n_masses);
61 std::ranges::iota(actuator_indices_l, index_t{});
62 std::ranges::iota(actuator_indices_r, index_t{});
63 std::shuffle(actuator_indices_l.begin(), actuator_indices_l.end(), rng);
64 std::shuffle(actuator_indices_r.begin(), actuator_indices_r.end(), rng);
66 B(n_masses + actuator_indices_l[a], a) = +1 / p.
masses[actuator_indices_l[a]];
67 B(n_masses + actuator_indices_r[a], a) = -1 / p.
masses[actuator_indices_r[a]];
73 auto v_l = 2 * a, v_r = 2 * a + 1;
75 B(n_masses + v_l, a) = +1 / p.
masses[v_l];
77 B(n_masses + v_r, a) = -1 / p.
masses[v_r];
78 }
else if (a % 3 == 1) {
79 auto v_l = 2 * a, v_r = 2 * a + 2;
81 B(n_masses + v_l, a) = +1 / p.
masses[v_l];
83 B(n_masses + v_r, a) = -1 / p.
masses[v_r];
85 auto v_l = 2 * a - 1, v_r = 2 * a + 1;
87 B(n_masses + v_l, a) = +1 / p.
masses[v_l];
89 B(n_masses + v_r, a) = -1 / p.
masses[v_r];
93 default:
throw std::invalid_argument(
"Invalid actuator placement");
100 ocp.
b().set_constant(0);
101 ocp.
b_min().set_constant(-inf);
102 ocp.
b_max().set_constant(+inf);
104 for (index_t
v = 0;
v < n_masses; ++
v)
105 x0(
v, 0) =
static_cast<real_t
>(
v + 1) * p.
width /
static_cast<real_t
>(n_masses + 1);
108 for (index_t i = 0; i < N; ++i) {
109 auto Ai = ocp.
A(i), Bi = ocp.
B(i), bi = ocp.
b(i + 1), Ci = ocp.
C(i), Di = ocp.
D(i);
110 auto Qi = ocp.
Q(i), Ri = ocp.
R(i);
112 for (index_t
v = 0;
v < n_masses; ++
v) {
117 lbi(
v, 0) = x0(
v, 0) + p.
p_min;
118 ubi(
v, 0) = x0(
v, 0) + p.
p_max;
120 Ci(n_masses +
v, n_masses +
v) = 1;
121 lbi(n_masses +
v, 0) = -p.
v_max;
122 ubi(n_masses +
v, 0) = +p.
v_max;
125 Qi(n_masses +
v, n_masses +
v) = p.
q_vel;
129 lbi(ny_x + a, 0) = -p.
F_max;
130 ubi(ny_x + a, 0) = +p.
F_max;
134 auto Ci = ocp.
C(N), Qi = ocp.
Q(N);
136 for (index_t
v = 0;
v < n_masses; ++
v) {
141 Ci(n_masses +
v, n_masses +
v) = 1;
146 Qi(n_masses +
v, n_masses +
v) = p.
q_vel_f;
148 std::vector<real_t> ref(nx + nu + nx);
149 for (index_t
v = 0;
v < n_masses; ++
v) {
151 ref[nx + nu +
v] = x0(
v, 0);
156 .ocp = std::move(ocp),
157 .ref = std::move(ref),