GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/core/costs/cost-sum.hxx
Date: 2025-01-16 08:47:40
Exec Total Coverage
Lines: 146 171 85.4%
Branches: 114 466 24.5%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (C) 2019-2023, LAAS-CNRS, University of Edinburgh,
5 // Heriot-Watt University
6 // Copyright note valid unless otherwise stated in individual files.
7 // All rights reserved.
8 ///////////////////////////////////////////////////////////////////////////////
9
10 #include <iostream>
11
12 #include "crocoddyl/core/utils/exception.hpp"
13
14 namespace crocoddyl {
15
16 template <typename Scalar>
17 1798 CostModelSumTpl<Scalar>::CostModelSumTpl(boost::shared_ptr<StateAbstract> state,
18 const std::size_t nu)
19 1798 : state_(state), nu_(nu), nr_(0), nr_total_(0) {}
20
21 template <typename Scalar>
22 65 CostModelSumTpl<Scalar>::CostModelSumTpl(boost::shared_ptr<StateAbstract> state)
23 65 : state_(state), nu_(state->get_nv()), nr_(0), nr_total_(0) {}
24
25 template <typename Scalar>
26 1865 CostModelSumTpl<Scalar>::~CostModelSumTpl() {}
27
28 template <typename Scalar>
29 6125 void CostModelSumTpl<Scalar>::addCost(const std::string& name,
30 boost::shared_ptr<CostModelAbstract> cost,
31 const Scalar weight, const bool active) {
32
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 6125 times.
6125 if (cost->get_nu() != nu_) {
33 throw_pretty(
34 name
35 << " cost item doesn't have the same control dimension (it should be " +
36 std::to_string(nu_) + ")");
37 }
38 std::pair<typename CostModelContainer::iterator, bool> ret =
39
3/6
✓ Branch 1 taken 6125 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6125 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6125 times.
✗ Branch 8 not taken.
6125 costs_.insert(std::make_pair(
40 name, boost::make_shared<CostItem>(name, cost, weight, active)));
41
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6122 times.
6125 if (ret.second == false) {
42 std::cerr << "Warning: we couldn't add the " << name
43
4/8
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
3 << " cost item, it already existed." << std::endl;
44
2/2
✓ Branch 0 taken 6119 times.
✓ Branch 1 taken 3 times.
6122 } else if (active) {
45 6119 nr_ += cost->get_activation()->get_nr();
46 6119 nr_total_ += cost->get_activation()->get_nr();
47
1/2
✓ Branch 1 taken 6119 times.
✗ Branch 2 not taken.
6119 active_set_.insert(name);
48
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 } else if (!active) {
49 3 nr_total_ += cost->get_activation()->get_nr();
50
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 inactive_set_.insert(name);
51 }
52 6125 }
53
54 template <typename Scalar>
55 151 void CostModelSumTpl<Scalar>::removeCost(const std::string& name) {
56
1/2
✓ Branch 1 taken 151 times.
✗ Branch 2 not taken.
151 typename CostModelContainer::iterator it = costs_.find(name);
57
2/2
✓ Branch 2 taken 148 times.
✓ Branch 3 taken 3 times.
151 if (it != costs_.end()) {
58 148 nr_ -= it->second->cost->get_activation()->get_nr();
59 148 nr_total_ -= it->second->cost->get_activation()->get_nr();
60
1/2
✓ Branch 1 taken 148 times.
✗ Branch 2 not taken.
148 costs_.erase(it);
61
1/2
✓ Branch 1 taken 148 times.
✗ Branch 2 not taken.
148 active_set_.erase(name);
62
1/2
✓ Branch 1 taken 148 times.
✗ Branch 2 not taken.
148 inactive_set_.erase(name);
63 } else {
64 std::cerr << "Warning: we couldn't remove the " << name
65
4/8
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
3 << " cost item, it doesn't exist." << std::endl;
66 }
67 151 }
68
69 template <typename Scalar>
70 21 void CostModelSumTpl<Scalar>::changeCostStatus(const std::string& name,
71 const bool active) {
72
1/2
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
21 typename CostModelContainer::iterator it = costs_.find(name);
73
2/2
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 3 times.
21 if (it != costs_.end()) {
74
5/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 15 times.
18 if (active && !it->second->active) {
75 3 nr_ += it->second->cost->get_activation()->get_nr();
76
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 active_set_.insert(name);
77
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 inactive_set_.erase(name);
78 3 it->second->active = active;
79
3/6
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
15 } else if (!active && it->second->active) {
80 15 nr_ -= it->second->cost->get_activation()->get_nr();
81
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 active_set_.erase(name);
82
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 inactive_set_.insert(name);
83 15 it->second->active = active;
84 }
85 } else {
86 std::cerr << "Warning: we couldn't change the status of the " << name
87
4/8
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
3 << " cost item, it doesn't exist." << std::endl;
88 }
89 21 }
90
91 template <typename Scalar>
92 78472 void CostModelSumTpl<Scalar>::calc(const boost::shared_ptr<CostDataSum>& data,
93 const Eigen::Ref<const VectorXs>& x,
94 const Eigen::Ref<const VectorXs>& u) {
95
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 78472 times.
78472 if (static_cast<std::size_t>(x.size()) != state_->get_nx()) {
96 throw_pretty(
97 "Invalid argument: " << "x has wrong dimension (it should be " +
98 std::to_string(state_->get_nx()) + ")");
99 }
100
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 78472 times.
78472 if (static_cast<std::size_t>(u.size()) != nu_) {
101 throw_pretty(
102 "Invalid argument: " << "u has wrong dimension (it should be " +
103 std::to_string(nu_) + ")");
104 }
105
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 78472 times.
78472 if (data->costs.size() != costs_.size()) {
106 throw_pretty("Invalid argument: "
107 << "it doesn't match the number of cost datas and models");
108 }
109 78472 data->cost = Scalar(0.);
110
111 78472 typename CostModelContainer::iterator it_m, end_m;
112 78472 typename CostDataContainer::iterator it_d, end_d;
113 156944 for (it_m = costs_.begin(), end_m = costs_.end(), it_d = data->costs.begin(),
114 78472 end_d = data->costs.end();
115
5/6
✓ Branch 3 taken 78472 times.
✓ Branch 4 taken 355181 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 78472 times.
✓ Branch 8 taken 355181 times.
✓ Branch 9 taken 78472 times.
433653 it_m != end_m || it_d != end_d; ++it_m, ++it_d) {
116 355181 const boost::shared_ptr<CostItem>& m_i = it_m->second;
117
2/2
✓ Branch 1 taken 355169 times.
✓ Branch 2 taken 12 times.
355181 if (m_i->active) {
118 355169 const boost::shared_ptr<CostDataAbstract>& d_i = it_d->second;
119
1/18
✗ Branch 3 not taken.
✓ Branch 4 taken 355169 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
355169 assert_pretty(it_m->first == it_d->first,
120 "it doesn't match the cost name between model and data ("
121 << it_m->first << " != " << it_d->first << ")");
122
123
1/2
✓ Branch 3 taken 355169 times.
✗ Branch 4 not taken.
355169 m_i->cost->calc(d_i, x, u);
124 355169 data->cost += m_i->weight * d_i->cost;
125 }
126 }
127 78472 }
128
129 template <typename Scalar>
130 14186 void CostModelSumTpl<Scalar>::calc(const boost::shared_ptr<CostDataSum>& data,
131 const Eigen::Ref<const VectorXs>& x) {
132
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 14186 times.
14186 if (static_cast<std::size_t>(x.size()) != state_->get_nx()) {
133 throw_pretty(
134 "Invalid argument: " << "x has wrong dimension (it should be " +
135 std::to_string(state_->get_nx()) + ")");
136 }
137
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 14186 times.
14186 if (data->costs.size() != costs_.size()) {
138 throw_pretty("Invalid argument: "
139 << "it doesn't match the number of cost datas and models");
140 }
141 14186 data->cost = Scalar(0.);
142
143 14186 typename CostModelContainer::iterator it_m, end_m;
144 14186 typename CostDataContainer::iterator it_d, end_d;
145 28372 for (it_m = costs_.begin(), end_m = costs_.end(), it_d = data->costs.begin(),
146 14186 end_d = data->costs.end();
147
5/6
✓ Branch 3 taken 14186 times.
✓ Branch 4 taken 69473 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 14186 times.
✓ Branch 8 taken 69473 times.
✓ Branch 9 taken 14186 times.
83659 it_m != end_m || it_d != end_d; ++it_m, ++it_d) {
148 69473 const boost::shared_ptr<CostItem>& m_i = it_m->second;
149
2/2
✓ Branch 1 taken 69467 times.
✓ Branch 2 taken 6 times.
69473 if (m_i->active) {
150 69467 const boost::shared_ptr<CostDataAbstract>& d_i = it_d->second;
151
1/18
✗ Branch 3 not taken.
✓ Branch 4 taken 69467 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
69467 assert_pretty(it_m->first == it_d->first,
152 "it doesn't match the cost name between model and data ("
153 << it_m->first << " != " << it_d->first << ")");
154
155
1/2
✓ Branch 3 taken 69467 times.
✗ Branch 4 not taken.
69467 m_i->cost->calc(d_i, x);
156 69467 data->cost += m_i->weight * d_i->cost;
157 }
158 }
159 14186 }
160
161 template <typename Scalar>
162 14120 void CostModelSumTpl<Scalar>::calcDiff(
163 const boost::shared_ptr<CostDataSum>& data,
164 const Eigen::Ref<const VectorXs>& x, const Eigen::Ref<const VectorXs>& u) {
165
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 14120 times.
14120 if (static_cast<std::size_t>(x.size()) != state_->get_nx()) {
166 throw_pretty(
167 "Invalid argument: " << "x has wrong dimension (it should be " +
168 std::to_string(state_->get_nx()) + ")");
169 }
170
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14120 times.
14120 if (static_cast<std::size_t>(u.size()) != nu_) {
171 throw_pretty(
172 "Invalid argument: " << "u has wrong dimension (it should be " +
173 std::to_string(nu_) + ")");
174 }
175
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 14120 times.
14120 if (data->costs.size() != costs_.size()) {
176 throw_pretty("Invalid argument: "
177 << "it doesn't match the number of cost datas and models");
178 }
179
1/2
✓ Branch 2 taken 14120 times.
✗ Branch 3 not taken.
14120 data->Lx.setZero();
180
1/2
✓ Branch 2 taken 14120 times.
✗ Branch 3 not taken.
14120 data->Lu.setZero();
181
1/2
✓ Branch 2 taken 14120 times.
✗ Branch 3 not taken.
14120 data->Lxx.setZero();
182
1/2
✓ Branch 2 taken 14120 times.
✗ Branch 3 not taken.
14120 data->Lxu.setZero();
183
1/2
✓ Branch 2 taken 14120 times.
✗ Branch 3 not taken.
14120 data->Luu.setZero();
184
185 14120 typename CostModelContainer::iterator it_m, end_m;
186 14120 typename CostDataContainer::iterator it_d, end_d;
187 28240 for (it_m = costs_.begin(), end_m = costs_.end(), it_d = data->costs.begin(),
188 14120 end_d = data->costs.end();
189
5/6
✓ Branch 3 taken 14120 times.
✓ Branch 4 taken 60672 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 14120 times.
✓ Branch 8 taken 60672 times.
✓ Branch 9 taken 14120 times.
74792 it_m != end_m || it_d != end_d; ++it_m, ++it_d) {
190 60672 const boost::shared_ptr<CostItem>& m_i = it_m->second;
191
2/2
✓ Branch 1 taken 60666 times.
✓ Branch 2 taken 6 times.
60672 if (m_i->active) {
192 60666 const boost::shared_ptr<CostDataAbstract>& d_i = it_d->second;
193
1/18
✗ Branch 3 not taken.
✓ Branch 4 taken 60666 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
60666 assert_pretty(it_m->first == it_d->first,
194 "it doesn't match the cost name between model and data ("
195 << it_m->first << " != " << it_d->first << ")");
196
197
1/2
✓ Branch 3 taken 60666 times.
✗ Branch 4 not taken.
60666 m_i->cost->calcDiff(d_i, x, u);
198
2/4
✓ Branch 3 taken 60666 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 60666 times.
✗ Branch 8 not taken.
60666 data->Lx += m_i->weight * d_i->Lx;
199
2/4
✓ Branch 3 taken 60666 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 60666 times.
✗ Branch 8 not taken.
60666 data->Lu += m_i->weight * d_i->Lu;
200
2/4
✓ Branch 3 taken 60666 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 60666 times.
✗ Branch 8 not taken.
60666 data->Lxx += m_i->weight * d_i->Lxx;
201
2/4
✓ Branch 3 taken 60666 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 60666 times.
✗ Branch 8 not taken.
60666 data->Lxu += m_i->weight * d_i->Lxu;
202
2/4
✓ Branch 3 taken 60666 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 60666 times.
✗ Branch 8 not taken.
60666 data->Luu += m_i->weight * d_i->Luu;
203 }
204 }
205 14120 }
206
207 template <typename Scalar>
208 639 void CostModelSumTpl<Scalar>::calcDiff(
209 const boost::shared_ptr<CostDataSum>& data,
210 const Eigen::Ref<const VectorXs>& x) {
211
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 639 times.
639 if (static_cast<std::size_t>(x.size()) != state_->get_nx()) {
212 throw_pretty(
213 "Invalid argument: " << "x has wrong dimension (it should be " +
214 std::to_string(state_->get_nx()) + ")");
215 }
216
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 639 times.
639 if (data->costs.size() != costs_.size()) {
217 throw_pretty("Invalid argument: "
218 << "it doesn't match the number of cost datas and models");
219 }
220
1/2
✓ Branch 2 taken 639 times.
✗ Branch 3 not taken.
639 data->Lx.setZero();
221
1/2
✓ Branch 2 taken 639 times.
✗ Branch 3 not taken.
639 data->Lxx.setZero();
222
223 639 typename CostModelContainer::iterator it_m, end_m;
224 639 typename CostDataContainer::iterator it_d, end_d;
225 1278 for (it_m = costs_.begin(), end_m = costs_.end(), it_d = data->costs.begin(),
226 639 end_d = data->costs.end();
227
5/6
✓ Branch 3 taken 639 times.
✓ Branch 4 taken 2858 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 639 times.
✓ Branch 8 taken 2858 times.
✓ Branch 9 taken 639 times.
3497 it_m != end_m || it_d != end_d; ++it_m, ++it_d) {
228 2858 const boost::shared_ptr<CostItem>& m_i = it_m->second;
229
2/2
✓ Branch 1 taken 2852 times.
✓ Branch 2 taken 6 times.
2858 if (m_i->active) {
230 2852 const boost::shared_ptr<CostDataAbstract>& d_i = it_d->second;
231
1/18
✗ Branch 3 not taken.
✓ Branch 4 taken 2852 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
2852 assert_pretty(it_m->first == it_d->first,
232 "it doesn't match the cost name between model and data ("
233 << it_m->first << " != " << it_d->first << ")");
234
235
1/2
✓ Branch 3 taken 2852 times.
✗ Branch 4 not taken.
2852 m_i->cost->calcDiff(d_i, x);
236
2/4
✓ Branch 3 taken 2852 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 2852 times.
✗ Branch 8 not taken.
2852 data->Lx += m_i->weight * d_i->Lx;
237
2/4
✓ Branch 3 taken 2852 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 2852 times.
✗ Branch 8 not taken.
2852 data->Lxx += m_i->weight * d_i->Lxx;
238 }
239 }
240 639 }
241
242 template <typename Scalar>
243 96214 boost::shared_ptr<CostDataSumTpl<Scalar> > CostModelSumTpl<Scalar>::createData(
244 DataCollectorAbstract* const data) {
245 return boost::allocate_shared<CostDataSum>(
246
1/2
✓ Branch 2 taken 96214 times.
✗ Branch 3 not taken.
192428 Eigen::aligned_allocator<CostDataSum>(), this, data);
247 }
248
249 template <typename Scalar>
250 const boost::shared_ptr<StateAbstractTpl<Scalar> >&
251 771056 CostModelSumTpl<Scalar>::get_state() const {
252 771056 return state_;
253 }
254
255 template <typename Scalar>
256 const typename CostModelSumTpl<Scalar>::CostModelContainer&
257 628122 CostModelSumTpl<Scalar>::get_costs() const {
258 628122 return costs_;
259 }
260
261 template <typename Scalar>
262 771146 std::size_t CostModelSumTpl<Scalar>::get_nu() const {
263 771146 return nu_;
264 }
265
266 template <typename Scalar>
267 1513 std::size_t CostModelSumTpl<Scalar>::get_nr() const {
268 1513 return nr_;
269 }
270
271 template <typename Scalar>
272 15 std::size_t CostModelSumTpl<Scalar>::get_nr_total() const {
273 15 return nr_total_;
274 }
275
276 template <typename Scalar>
277 3 const std::set<std::string>& CostModelSumTpl<Scalar>::get_active_set() const {
278 3 return active_set_;
279 }
280
281 template <typename Scalar>
282 3 const std::set<std::string>& CostModelSumTpl<Scalar>::get_inactive_set() const {
283 3 return inactive_set_;
284 }
285
286 template <typename Scalar>
287 bool CostModelSumTpl<Scalar>::getCostStatus(const std::string& name) const {
288 typename CostModelContainer::const_iterator it = costs_.find(name);
289 if (it != costs_.end()) {
290 return it->second->active;
291 } else {
292 std::cerr << "Warning: we couldn't get the status of the " << name
293 << " cost item, it doesn't exist." << std::endl;
294 return false;
295 }
296 }
297
298 template <typename Scalar>
299 3 std::ostream& operator<<(std::ostream& os,
300 const CostModelSumTpl<Scalar>& model) {
301 3 const std::set<std::string>& active = model.get_active_set();
302 3 const std::set<std::string>& inactive = model.get_inactive_set();
303 3 os << "CostModelSum:" << std::endl;
304 3 os << " Active:" << std::endl;
305 3 for (std::set<std::string>::const_iterator it = active.begin();
306
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 it != active.end(); ++it) {
307 const boost::shared_ptr<typename CostModelSumTpl<Scalar>::CostItem>&
308 cost_item = model.get_costs().find(*it)->second;
309 if (it != --active.end()) {
310 os << " " << *it << ": " << *cost_item << std::endl;
311 } else {
312 os << " " << *it << ": " << *cost_item << std::endl;
313 }
314 }
315 3 os << " Inactive:" << std::endl;
316 3 for (std::set<std::string>::const_iterator it = inactive.begin();
317
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 it != inactive.end(); ++it) {
318 const boost::shared_ptr<typename CostModelSumTpl<Scalar>::CostItem>&
319 cost_item = model.get_costs().find(*it)->second;
320 if (it != --inactive.end()) {
321 os << " " << *it << ": " << *cost_item << std::endl;
322 } else {
323 os << " " << *it << ": " << *cost_item;
324 }
325 }
326 3 return os;
327 }
328
329 } // namespace crocoddyl
330