GCC Code Coverage Report


Directory: ./
File: benchmark/quadruped-non-linear.cpp
Date: 2024-12-02 00:24:10
Exec Total Coverage
Lines: 0 125 0.0%
Branches: 0 674 0.0%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (C) 2018-2019, LAAS-CNRS
5 // Copyright note valid unless otherwise stated in individual files.
6 // All rights reserved.
7 ///////////////////////////////////////////////////////////////////////////////
8
9 #include <quadruped-walkgen/quadruped_nl.hpp>
10
11 #include "crocoddyl/core/actions/unicycle.hpp"
12 #include "crocoddyl/core/solvers/ddp.hpp"
13 #include "crocoddyl/core/utils/callbacks.hpp"
14 #include "crocoddyl/core/utils/timer.hpp"
15
16 void updateModel(
17 std::vector<
18 boost::shared_ptr<quadruped_walkgen::ActionModelQuadrupedNonLinear> >
19 running_models_2,
20 boost::shared_ptr<quadruped_walkgen::ActionModelQuadrupedNonLinear>
21 terminal_model_2,
22 Eigen::Matrix<double, 6, 5> gait, Eigen::Matrix<double, 12, 17> xref,
23 Eigen::Matrix<double, 6, 13> fsteps, int N) {
24 // Iterate over all the phases of the gait matrix
25 // The first column of xref correspond to the current state = x0
26 // Tmp is needed to use .data(), transformation of a column into a vector
27 Eigen::Array<double, 1, 12> tmp = Eigen::Array<double, 1, 12>::Zero();
28 int max_index = int(gait.block(0, 0, 6, 1).array().min(1.).matrix().sum());
29 int k_cum = 0;
30
31 for (int j = 0; j < max_index; j++) {
32 for (int k = k_cum; k < k_cum + int(gait(j, 0)); ++k) {
33 if (k < int(N)) {
34 // Update model :
35 tmp = fsteps.block(j, 1, 1, 12).array();
36 running_models_2[k]->update_model(
37 Eigen::Map<Eigen::Matrix<double, 3, 4> >(tmp.data(), 3, 4),
38 Eigen::Map<Eigen::Matrix<double, 12, 1> >(
39 xref.block(0, k + 1, 12, 1).data(), 12, 1),
40 Eigen::Map<Eigen::Matrix<double, 4, 1> >(
41 gait.block(j, 1, 1, 4).data(), 4, 1));
42 }
43 }
44 k_cum += int(gait(j, 0));
45 }
46
47 tmp = fsteps.block(max_index - 1, 1, 1, 12).array();
48 Eigen::Array<double, 1, 4> gait_tmp = Eigen::Array<double, 1, 4>::Zero();
49 gait_tmp = gait.block(max_index - 1, 1, 1, 4).array();
50
51 terminal_model_2->update_model(
52 Eigen::Map<Eigen::Matrix<double, 3, 4> >(tmp.data(), 3, 4),
53 Eigen::Map<Eigen::Matrix<double, 12, 1> >(xref.block(0, 16, 12, 1).data(),
54 12, 1),
55 Eigen::Map<Eigen::Matrix<double, 4, 1> >(gait_tmp.data(), 4, 1));
56 terminal_model_2->set_force_weights(Eigen::Matrix<double, 12, 1>::Zero());
57 terminal_model_2->set_friction_weight(0);
58 }
59
60 int main(int argc, char* argv[]) {
61 // The time of the cycle contol is 0.02s, and last 0.32s --> 16nodes
62 // Control cycle during one gait period
63 unsigned int N = 16; // number of nodes
64 unsigned int T = 1000; // number of trials
65 unsigned int MAXITER = 1;
66 if (argc > 1) {
67 T = atoi(argv[1]);
68 MAXITER = atoi(argv[2]);
69 ;
70 }
71
72 // Creating the initial state vector (size x12)
73 // [x,y,z,Roll,Pitch,Yaw,Vx,Vy,Vz,Wroll,Wpitch,Wyaw] Perturbation of Vx =
74 // 0.2m.s-1
75 Eigen::Matrix<double, 12, 1> x0;
76 x0 << 0, 0, 0.25, 0.15, 0.1, 0, 0.2, 0, 0, 0, 0, 0;
77 Eigen::Matrix<double, 4, 1> S;
78 S << 1, 0, 0, 1;
79
80 // Creating the reference state vector (size 12x16) to follow during the
81 // control cycle Nullifying the Vx speed.
82 Eigen::Matrix<double, 12, 1> xref_vector;
83 xref_vector << 0, 0, 0.2, 0, 0, 0, 0, 0, 0, 0, 0, 0;
84 Eigen::Matrix<double, 12, 17> xref;
85 xref.block(0, 0, 12, 1) = x0; // first vector is the initial state
86 xref.block(0, 1, 12, 16) = xref_vector.replicate<1, 16>();
87
88 // Creating the gait matrix : The number at the beginning represents the
89 // number of node spent in that position 1 -> foot in contact with the ground
90 // : 0-> foot in the air
91 Eigen::Matrix<double, 6, 5> gait;
92 gait << 1, 1, 1, 1, 1, 7, 1, 0, 0, 1, 1, 1, 1, 1, 1, 7, 0, 1, 1, 0, 0, 0, 0,
93 0, 0, 0, 0, 0, 0, 0;
94
95 // Creating the fsteps matrix that represents the position of the feet during
96 // the whole control cycle (0.32s). [nb , x1,y1,z1, x2,y2,z2 ...] in local
97 // frame The number at the beginning represents the number of node spent in
98 // that position Here, the robot starts with 4 feet on the ground at the first
99 // node, then during 7 nodes (0.02s * 7) The leg right front leg and left back
100 // leg are in the air ...etc
101
102 Eigen::Matrix<double, 6, 13> fsteps;
103 fsteps << 1, 0.19, 0.15, 0.0, 0.19, -0.15, 0.0, -0.19, 0.15, 0.0, -0.19,
104 -0.15, 0.0, 7, 0.19, 0.15, 0.0, 0, 0, 0, 0, 0, 0, -0.19, -0.15, 0.0, 1,
105 0.19, 0.15, 0.0, 0.19, -0.15, 0.0, -0.19, 0.15, 0.0, -0.19, -0.15, 0.0, 7,
106 0, 0, 0, 0.19, -0.15, 0.0, -0.19, 0.15, 0.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
108
109 // Creating the Shoting problem that needs
110 // boost::shared_ptr<crocoddyl::ActionModelAbstract>
111
112 // Cannot use 1 model for the whole control cycle, because each model depends
113 // on the position of the feet And the inertia matrix depends on the reference
114 // state (approximation )
115 std::vector<boost::shared_ptr<crocoddyl::ActionModelAbstract> >
116 running_models;
117
118 for (int i = 0; i < int(N); ++i) { // 16 nodes
119 boost::shared_ptr<crocoddyl::ActionModelAbstract> model =
120 boost::make_shared<quadruped_walkgen::ActionModelQuadrupedNonLinear>();
121 running_models.push_back(model);
122 }
123
124 boost::shared_ptr<crocoddyl::ActionModelAbstract> terminal_model;
125 terminal_model =
126 boost::make_shared<quadruped_walkgen::ActionModelQuadrupedNonLinear>();
127
128 // Update each model and set to 0 the weight ont the command for the terminal
129 // node For that, the internal method of
130 // quadruped_walkgen::ActionModelQuadruped needs to be accessed
131 // -> Creation of a 2nd list using dynamic_cast
132
133 int k_cum = 0;
134 std::vector<
135 boost::shared_ptr<quadruped_walkgen::ActionModelQuadrupedNonLinear> >
136 running_models_2;
137
138 // Iterate over all the phases of the gait matrix
139 // The first column of xref correspond to the current state = x0
140 // Tmp is needed to use .data(), transformation of a column into a vector
141 Eigen::Array<double, 1, 12> tmp = Eigen::Array<double, 1, 12>::Zero();
142 int max_index = int(gait.block(0, 0, 6, 1).array().min(1.).matrix().sum());
143
144 for (int j = 0; j < max_index; j++) {
145 for (int k = k_cum; k < k_cum + int(gait(j, 0)); ++k) {
146 if (k < int(N)) {
147 boost::shared_ptr<quadruped_walkgen::ActionModelQuadrupedNonLinear>
148 model2 = boost::dynamic_pointer_cast<
149 quadruped_walkgen::ActionModelQuadrupedNonLinear>(
150 running_models[k]);
151 running_models_2.push_back(model2);
152
153 // Update model :
154 tmp = fsteps.block(j, 1, 1, 12).array();
155 model2->update_model(
156 Eigen::Map<Eigen::Matrix<double, 3, 4> >(tmp.data(), 3, 4),
157 Eigen::Map<Eigen::Matrix<double, 12, 1> >(
158 xref.block(0, k + 1, 12, 1).data(), 12, 1),
159 Eigen::Map<Eigen::Matrix<double, 4, 1> >(
160 gait.block(j, 1, 1, 4).data(), 4, 1));
161 }
162 }
163 k_cum += int(gait(j, 0));
164 }
165
166 boost::shared_ptr<quadruped_walkgen::ActionModelQuadrupedNonLinear>
167 terminal_model_2 = boost::dynamic_pointer_cast<
168 quadruped_walkgen::ActionModelQuadrupedNonLinear>(terminal_model);
169
170 tmp = fsteps.block(max_index - 1, 1, 1, 12).array();
171 Eigen::Array<double, 1, 4> gait_tmp = Eigen::Array<double, 1, 4>::Zero();
172 gait_tmp = gait.block(max_index - 1, 1, 1, 4).array();
173
174 terminal_model_2->update_model(
175 Eigen::Map<Eigen::Matrix<double, 3, 4> >(tmp.data(), 3, 4),
176 Eigen::Map<Eigen::Matrix<double, 12, 1> >(xref.block(0, 16, 12, 1).data(),
177 12, 1),
178 Eigen::Map<Eigen::Matrix<double, 4, 1> >(gait_tmp.data(), 4, 1));
179 terminal_model_2->set_force_weights(Eigen::Matrix<double, 12, 1>::Zero());
180 terminal_model_2->set_friction_weight(0);
181
182 boost::shared_ptr<crocoddyl::ShootingProblem> problem =
183 boost::make_shared<crocoddyl::ShootingProblem>(x0, running_models,
184 terminal_model);
185 crocoddyl::SolverDDP ddp(problem);
186
187 std::vector<Eigen::VectorXd> xs(int(N) + 1, x0);
188 Eigen::Matrix<double, 12, 1> u0;
189 u0 << 1, 0.2, 0.5, 1, 1, -0.2, -1, 1, 0.5, -1, -1, -0.5;
190 std::vector<Eigen::VectorXd> us(int(N), u0);
191
192 Eigen::ArrayXd duration(T);
193
194 // Updating the problem
195 for (unsigned int i = 0; i < T; ++i) {
196 crocoddyl::Timer timer;
197 updateModel(running_models_2, terminal_model_2, gait, xref, fsteps, N);
198 duration[i] = timer.get_duration();
199 }
200 double avrg_duration = duration.sum() / T;
201 double min_duration = duration.minCoeff();
202 double max_duration = duration.maxCoeff();
203 std::cout << " UpdateModel [ms]: " << avrg_duration << " (" << min_duration
204 << "-" << max_duration << ")" << std::endl;
205
206 // Solving the optimal control problem
207 for (unsigned int i = 0; i < T; ++i) {
208 crocoddyl::Timer timer;
209 ddp.solve(xs, us, MAXITER);
210 duration[i] = timer.get_duration();
211 }
212
213 avrg_duration = duration.sum() / T;
214 min_duration = duration.minCoeff();
215 max_duration = duration.maxCoeff();
216 std::cout << " DDP.solve [ms]: " << avrg_duration << " (" << min_duration
217 << "-" << max_duration << ")" << std::endl;
218
219 // Running calc
220 for (unsigned int i = 0; i < T; ++i) {
221 crocoddyl::Timer timer;
222 problem->calc(xs, us);
223 duration[i] = timer.get_duration();
224 }
225
226 avrg_duration = duration.sum() / T;
227 min_duration = duration.minCoeff();
228 max_duration = duration.maxCoeff();
229 std::cout << " ShootingProblem.calc [ms]: " << avrg_duration << " ("
230 << min_duration << "-" << max_duration << ")" << std::endl;
231
232 // Running calcDiff
233 for (unsigned int i = 0; i < T; ++i) {
234 crocoddyl::Timer timer;
235 problem->calcDiff(xs, us);
236 duration[i] = timer.get_duration();
237 }
238
239 avrg_duration = duration.sum() / T;
240 min_duration = duration.minCoeff();
241 max_duration = duration.maxCoeff();
242 std::cout << " ShootingProblem.calcDiff [ms]: " << avrg_duration << " ("
243 << min_duration << "-" << max_duration << ")" << std::endl;
244 }
245