43 #include <ilqgames/cost/curvature_cost.h> 44 #include <ilqgames/cost/final_time_cost.h> 45 #include <ilqgames/cost/locally_convex_proximity_cost.h> 46 #include <ilqgames/cost/nominal_path_length_cost.h> 47 #include <ilqgames/cost/proximity_cost.h> 48 #include <ilqgames/cost/quadratic_cost.h> 49 #include <ilqgames/cost/quadratic_norm_cost.h> 50 #include <ilqgames/cost/quadratic_polyline2_cost.h> 51 #include <ilqgames/cost/route_progress_cost.h> 52 #include <ilqgames/cost/semiquadratic_cost.h> 53 #include <ilqgames/cost/semiquadratic_norm_cost.h> 54 #include <ilqgames/cost/semiquadratic_polyline2_cost.h> 55 #include <ilqgames/cost/weighted_convex_proximity_cost.h> 56 #include <ilqgames/dynamics/concatenated_flat_system.h> 57 #include <ilqgames/dynamics/single_player_flat_car_6d.h> 58 #include <ilqgames/dynamics/single_player_flat_unicycle_4d.h> 59 #include <ilqgames/examples/flat_roundabout_merging_example.h> 60 #include <ilqgames/examples/roundabout_lane_center.h> 61 #include <ilqgames/geometry/polyline2.h> 62 #include <ilqgames/solver/problem.h> 63 #include <ilqgames/utils/initialize_along_route.h> 64 #include <ilqgames/utils/solver_log.h> 65 #include <ilqgames/utils/strategy.h> 66 #include <ilqgames/utils/types.h> 76 static constexpr Time kTimeStep = 0.1;
77 static constexpr Time kTimeHorizon = 10.0;
78 static constexpr
size_t kNumTimeSteps =
79 static_cast<size_t>(kTimeHorizon / kTimeStep);
82 static constexpr
float kAuxCostWeight = 4.0;
83 static constexpr
float kGoalCostWeight = 10.0;
85 static constexpr
float kMaxVCostWeight = 1000.0;
86 static constexpr
float kNominalVCostWeight = 10.0;
88 static constexpr
float kLaneCostWeight = 25.0;
89 static constexpr
float kLaneBoundaryCostWeight = 100.0;
91 static constexpr
float kMinProximity = 6.0;
92 static constexpr
float kP1ProximityCostWeight = 100.0;
93 static constexpr
float kP2ProximityCostWeight = 100.0;
94 static constexpr
float kP3ProximityCostWeight = 100.0;
95 static constexpr
float kP4ProximityCostWeight = 100.0;
96 using ProxCost = ProximityCost;
98 static constexpr
bool kOrientedRight =
true;
101 static constexpr
float kLaneHalfWidth = 2.5;
104 static constexpr
float kP1MaxV = 12.0;
105 static constexpr
float kP2MaxV = 12.0;
106 static constexpr
float kP3MaxV = 12.0;
107 static constexpr
float kP4MaxV = 12.0;
108 static constexpr
float kMinV = 1.0;
110 static constexpr
float kP1NominalV = 10.0;
111 static constexpr
float kP2NominalV = 10.0;
112 static constexpr
float kP3NominalV = 10.0;
113 static constexpr
float kP4NominalV = 10.0;
116 static constexpr
float kP1InitialDistanceToRoundabout = 25.0;
117 static constexpr
float kP2InitialDistanceToRoundabout = 10.0;
118 static constexpr
float kP3InitialDistanceToRoundabout = 25.0;
119 static constexpr
float kP4InitialDistanceToRoundabout = 10.0;
121 static constexpr
float kP1InitialSpeed = 3.0;
122 static constexpr
float kP2InitialSpeed = 2.0;
123 static constexpr
float kP3InitialSpeed = 3.0;
124 static constexpr
float kP4InitialSpeed = 2.0;
127 static constexpr
float kInterAxleDistance = 4.0;
128 using P1 = SinglePlayerFlatCar6D;
129 using P2 = SinglePlayerFlatCar6D;
130 using P3 = SinglePlayerFlatCar6D;
131 using P4 = SinglePlayerFlatCar6D;
133 static const Dimension kP1XIdx = P1::kPxIdx;
134 static const Dimension kP1YIdx = P1::kPyIdx;
135 static const Dimension kP1HeadingIdx = P1::kThetaIdx;
136 static const Dimension kP1VIdx = P1::kVIdx;
137 static const Dimension kP1VxIdx = P1::kVxIdx;
138 static const Dimension kP1VyIdx = P1::kVyIdx;
140 static const Dimension kP2XIdx = P1::kNumXDims + P2::kPxIdx;
141 static const Dimension kP2YIdx = P1::kNumXDims + P2::kPyIdx;
142 static const Dimension kP2HeadingIdx = P1::kNumXDims + P2::kThetaIdx;
143 static const Dimension kP2VIdx = P1::kNumXDims + P2::kVIdx;
144 static const Dimension kP2VxIdx = P1::kNumXDims + P2::kVxIdx;
145 static const Dimension kP2VyIdx = P1::kNumXDims + P2::kVyIdx;
147 static const Dimension kP3XIdx = P1::kNumXDims + P2::kNumXDims + P3::kPxIdx;
148 static const Dimension kP3YIdx = P1::kNumXDims + P2::kNumXDims + P3::kPyIdx;
149 static const Dimension kP3HeadingIdx =
150 P1::kNumXDims + P2::kNumXDims + P3::kThetaIdx;
151 static const Dimension kP3VIdx = P1::kNumXDims + P2::kNumXDims + P3::kVIdx;
152 static const Dimension kP3VxIdx = P1::kNumXDims + P2::kNumXDims + P3::kVxIdx;
153 static const Dimension kP3VyIdx = P1::kNumXDims + P2::kNumXDims + P3::kVyIdx;
155 static const Dimension kP4XIdx =
156 P1::kNumXDims + P2::kNumXDims + P3::kNumXDims + P4::kPxIdx;
157 static const Dimension kP4YIdx =
158 P1::kNumXDims + P2::kNumXDims + P3::kNumXDims + P4::kPyIdx;
159 static const Dimension kP4HeadingIdx =
160 P1::kNumXDims + P2::kNumXDims + P3::kNumXDims + P4::kThetaIdx;
161 static const Dimension kP4VIdx =
162 P1::kNumXDims + P2::kNumXDims + P3::kNumXDims + P4::kVIdx;
163 static const Dimension kP4VxIdx =
164 P1::kNumXDims + P2::kNumXDims + P3::kNumXDims + P4::kVxIdx;
165 static const Dimension kP4VyIdx =
166 P1::kNumXDims + P2::kNumXDims + P3::kNumXDims + P4::kVyIdx;
169 static constexpr
float kAngleOffset = M_PI_2 * 0.5;
170 static constexpr
float kWedgeSize = M_PI;
171 const std::vector<float> angles = {kAngleOffset,
172 kAngleOffset + 2.0 * M_PI / 4.0,
173 kAngleOffset + 2.0 * 2.0 * M_PI / 4.0,
174 kAngleOffset + 3.0 * 2.0 * M_PI / 4.0};
175 const Polyline2 lane1(RoundaboutLaneCenter(angles[0], angles[0] + kWedgeSize,
176 kP1InitialDistanceToRoundabout));
177 const Polyline2 lane2(RoundaboutLaneCenter(angles[1], angles[1] + kWedgeSize,
178 kP2InitialDistanceToRoundabout));
179 const Polyline2 lane3(RoundaboutLaneCenter(angles[2], angles[2] + kWedgeSize,
180 kP3InitialDistanceToRoundabout));
181 const Polyline2 lane4(RoundaboutLaneCenter(angles[3], angles[3] + kWedgeSize,
182 kP4InitialDistanceToRoundabout));
186 void FlatRoundaboutMergingExample::ConstructDynamics() {
188 new ConcatenatedFlatSystem({std::make_shared<P1>(kInterAxleDistance),
189 std::make_shared<P2>(kInterAxleDistance),
190 std::make_shared<P3>(kInterAxleDistance),
191 std::make_shared<P4>(kInterAxleDistance)}));
194 void FlatRoundaboutMergingExample::ConstructInitialState() {
195 VectorXf x0 = VectorXf::Zero(dynamics_->XDim());
196 x0(kP1XIdx) = lane1.Segments()[0].FirstPoint().x();
197 x0(kP1YIdx) = lane1.Segments()[0].FirstPoint().y();
198 x0(kP1HeadingIdx) = lane1.Segments()[0].Heading();
199 x0(kP1VIdx) = kP1InitialSpeed;
200 x0(kP2XIdx) = lane2.Segments()[0].FirstPoint().x();
201 x0(kP2YIdx) = lane2.Segments()[0].FirstPoint().y();
202 x0(kP2HeadingIdx) = lane2.Segments()[0].Heading();
203 x0(kP2VIdx) = kP2InitialSpeed;
204 x0(kP3XIdx) = lane3.Segments()[0].FirstPoint().x();
205 x0(kP3YIdx) = lane3.Segments()[0].FirstPoint().y();
206 x0(kP3HeadingIdx) = lane3.Segments()[0].Heading();
207 x0(kP3VIdx) = kP3InitialSpeed;
208 x0(kP4XIdx) = lane4.Segments()[0].FirstPoint().x();
209 x0(kP4YIdx) = lane4.Segments()[0].FirstPoint().y();
210 x0(kP4HeadingIdx) = lane4.Segments()[0].Heading();
211 x0(kP4VIdx) = kP4InitialSpeed;
213 x0_ = dynamics_->ToLinearSystemState(x0);
216 void FlatRoundaboutMergingExample::ConstructInitialOperatingPoint() {
218 InitializeAlongRoute(lane1, 0.0, kP1InitialSpeed, {kP1XIdx, kP1YIdx},
219 operating_point_.get());
220 InitializeAlongRoute(lane2, 0.0, kP2InitialSpeed, {kP2XIdx, kP2YIdx},
221 operating_point_.get());
222 InitializeAlongRoute(lane3, 0.0, kP3InitialSpeed, {kP3XIdx, kP3YIdx},
223 operating_point_.get());
224 InitializeAlongRoute(lane4, 0.0, kP4InitialSpeed, {kP4XIdx, kP4YIdx},
225 operating_point_.get());
228 void FlatRoundaboutMergingExample::ConstructPlayerCosts() {
230 player_costs_.emplace_back(
"P1");
231 player_costs_.emplace_back(
"P2");
232 player_costs_.emplace_back(
"P3");
233 player_costs_.emplace_back(
"P4");
234 auto& p1_cost = player_costs_[0];
235 auto& p2_cost = player_costs_[1];
236 auto& p3_cost = player_costs_[2];
237 auto& p4_cost = player_costs_[3];
240 const std::shared_ptr<QuadraticPolyline2Cost> p1_lane_cost(
241 new QuadraticPolyline2Cost(kLaneCostWeight, lane1, {kP1XIdx, kP1YIdx},
243 const std::shared_ptr<SemiquadraticPolyline2Cost> p1_lane_r_cost(
244 new SemiquadraticPolyline2Cost(kLaneBoundaryCostWeight, lane1,
245 {kP1XIdx, kP1YIdx}, kLaneHalfWidth,
246 kOrientedRight,
"LaneRightBoundary"));
247 const std::shared_ptr<SemiquadraticPolyline2Cost> p1_lane_l_cost(
248 new SemiquadraticPolyline2Cost(kLaneBoundaryCostWeight, lane1,
249 {kP1XIdx, kP1YIdx}, -kLaneHalfWidth,
250 !kOrientedRight,
"LaneLeftBoundary"));
251 p1_cost.AddStateCost(p1_lane_cost);
252 p1_cost.AddStateCost(p1_lane_r_cost);
253 p1_cost.AddStateCost(p1_lane_l_cost);
255 const std::shared_ptr<QuadraticPolyline2Cost> p2_lane_cost(
256 new QuadraticPolyline2Cost(kLaneCostWeight, lane2, {kP2XIdx, kP2YIdx},
258 const std::shared_ptr<SemiquadraticPolyline2Cost> p2_lane_r_cost(
259 new SemiquadraticPolyline2Cost(kLaneBoundaryCostWeight, lane2,
260 {kP2XIdx, kP2YIdx}, kLaneHalfWidth,
261 kOrientedRight,
"LaneRightBoundary"));
262 const std::shared_ptr<SemiquadraticPolyline2Cost> p2_lane_l_cost(
263 new SemiquadraticPolyline2Cost(kLaneBoundaryCostWeight, lane2,
264 {kP2XIdx, kP2YIdx}, -kLaneHalfWidth,
265 !kOrientedRight,
"LaneLeftBoundary"));
266 p2_cost.AddStateCost(p2_lane_cost);
267 p2_cost.AddStateCost(p2_lane_r_cost);
268 p2_cost.AddStateCost(p2_lane_l_cost);
270 const std::shared_ptr<QuadraticPolyline2Cost> p3_lane_cost(
271 new QuadraticPolyline2Cost(kLaneCostWeight, lane3, {kP3XIdx, kP3YIdx},
273 const std::shared_ptr<SemiquadraticPolyline2Cost> p3_lane_r_cost(
274 new SemiquadraticPolyline2Cost(kLaneBoundaryCostWeight, lane3,
275 {kP3XIdx, kP3YIdx}, kLaneHalfWidth,
276 kOrientedRight,
"LaneRightBoundary"));
277 const std::shared_ptr<SemiquadraticPolyline2Cost> p3_lane_l_cost(
278 new SemiquadraticPolyline2Cost(kLaneBoundaryCostWeight, lane3,
279 {kP3XIdx, kP3YIdx}, -kLaneHalfWidth,
280 !kOrientedRight,
"LaneLeftBoundary"));
281 p3_cost.AddStateCost(p3_lane_cost);
282 p3_cost.AddStateCost(p3_lane_r_cost);
283 p3_cost.AddStateCost(p3_lane_l_cost);
285 const std::shared_ptr<QuadraticPolyline2Cost> p4_lane_cost(
286 new QuadraticPolyline2Cost(kLaneCostWeight, lane4, {kP4XIdx, kP4YIdx},
288 const std::shared_ptr<SemiquadraticPolyline2Cost> p4_lane_r_cost(
289 new SemiquadraticPolyline2Cost(kLaneBoundaryCostWeight, lane4,
290 {kP4XIdx, kP4YIdx}, kLaneHalfWidth,
291 kOrientedRight,
"LaneRightBoundary"));
292 const std::shared_ptr<SemiquadraticPolyline2Cost> p4_lane_l_cost(
293 new SemiquadraticPolyline2Cost(kLaneBoundaryCostWeight, lane4,
294 {kP4XIdx, kP4YIdx}, -kLaneHalfWidth,
295 !kOrientedRight,
"LaneLeftBoundary"));
296 p4_cost.AddStateCost(p4_lane_cost);
297 p4_cost.AddStateCost(p4_lane_r_cost);
298 p4_cost.AddStateCost(p4_lane_l_cost);
301 const std::shared_ptr<RouteProgressCost> p1_progress_cost(
302 new RouteProgressCost(kNominalVCostWeight, kP1NominalV, lane1,
303 {kP1XIdx, kP1YIdx},
"RouteProgress"));
304 p1_cost.AddStateCost(p1_progress_cost);
306 const std::shared_ptr<RouteProgressCost> p2_progress_cost(
307 new RouteProgressCost(kNominalVCostWeight, kP2NominalV, lane2,
308 {kP2XIdx, kP2YIdx},
"RouteProgress"));
309 p2_cost.AddStateCost(p2_progress_cost);
311 const std::shared_ptr<RouteProgressCost> p3_progress_cost(
312 new RouteProgressCost(kNominalVCostWeight, kP3NominalV, lane3,
313 {kP3XIdx, kP3YIdx},
"RouteProgress"));
314 p3_cost.AddStateCost(p3_progress_cost);
316 const std::shared_ptr<RouteProgressCost> p4_progress_cost(
317 new RouteProgressCost(kNominalVCostWeight, kP4NominalV, lane4,
318 {kP4XIdx, kP4YIdx},
"RouteProgress"));
319 p4_cost.AddStateCost(p4_progress_cost);
322 constexpr Dimension kApplyInAllDimensions = -1;
323 const auto aux_cost = std::make_shared<QuadraticCost>(
324 kAuxCostWeight, kApplyInAllDimensions, 0.0,
"Auxiliary Input");
325 p1_cost.AddControlCost(0, aux_cost);
326 p2_cost.AddControlCost(1, aux_cost);
327 p3_cost.AddControlCost(2, aux_cost);
328 p4_cost.AddControlCost(3, aux_cost);
331 const std::shared_ptr<ProxCost> p1p2_proximity_cost(
332 new ProxCost(kP1ProximityCostWeight, {kP1XIdx, kP1YIdx},
333 {kP2XIdx, kP2YIdx}, kMinProximity,
"ProximityP2"));
334 const std::shared_ptr<ProxCost> p1p3_proximity_cost(
335 new ProxCost(kP1ProximityCostWeight, {kP1XIdx, kP1YIdx},
336 {kP3XIdx, kP3YIdx}, kMinProximity,
"ProximityP3"));
337 const std::shared_ptr<ProxCost> p1p4_proximity_cost(
338 new ProxCost(kP1ProximityCostWeight, {kP1XIdx, kP1YIdx},
339 {kP4XIdx, kP4YIdx}, kMinProximity,
"ProximityP4"));
340 p1_cost.AddStateCost(p1p2_proximity_cost);
342 p1_cost.AddStateCost(p1p4_proximity_cost);
344 const std::shared_ptr<ProxCost> p2p1_proximity_cost(
345 new ProxCost(kP2ProximityCostWeight, {kP2XIdx, kP2YIdx},
346 {kP1XIdx, kP1YIdx}, kMinProximity,
"ProximityP1"));
347 const std::shared_ptr<ProxCost> p2p3_proximity_cost(
348 new ProxCost(kP2ProximityCostWeight, {kP2XIdx, kP2YIdx},
349 {kP3XIdx, kP3YIdx}, kMinProximity,
"ProximityP3"));
350 const std::shared_ptr<ProxCost> p2p4_proximity_cost(
351 new ProxCost(kP2ProximityCostWeight, {kP2XIdx, kP2YIdx},
352 {kP4XIdx, kP4YIdx}, kMinProximity,
"ProximityP4"));
353 p2_cost.AddStateCost(p2p1_proximity_cost);
354 p2_cost.AddStateCost(p2p3_proximity_cost);
357 const std::shared_ptr<ProxCost> p3p1_proximity_cost(
358 new ProxCost(kP3ProximityCostWeight, {kP3XIdx, kP3YIdx},
359 {kP1XIdx, kP1YIdx}, kMinProximity,
"ProximityP1"));
360 const std::shared_ptr<ProxCost> p3p2_proximity_cost(
361 new ProxCost(kP3ProximityCostWeight, {kP3XIdx, kP3YIdx},
362 {kP2XIdx, kP2YIdx}, kMinProximity,
"ProximityP2"));
363 const std::shared_ptr<ProxCost> p3p4_proximity_cost(
364 new ProxCost(kP3ProximityCostWeight, {kP3XIdx, kP3YIdx},
365 {kP4XIdx, kP4YIdx}, kMinProximity,
"ProximityP4"));
367 p3_cost.AddStateCost(p3p2_proximity_cost);
368 p3_cost.AddStateCost(p3p4_proximity_cost);
370 const std::shared_ptr<ProxCost> p4p1_proximity_cost(
371 new ProxCost(kP4ProximityCostWeight, {kP4XIdx, kP4YIdx},
372 {kP1XIdx, kP1YIdx}, kMinProximity,
"ProximityP1"));
373 const std::shared_ptr<ProxCost> p4p2_proximity_cost(
374 new ProxCost(kP4ProximityCostWeight, {kP4XIdx, kP4YIdx},
375 {kP2XIdx, kP2YIdx}, kMinProximity,
"ProximityP2"));
376 const std::shared_ptr<ProxCost> p4p3_proximity_cost(
377 new ProxCost(kP4ProximityCostWeight, {kP4XIdx, kP4YIdx},
378 {kP3XIdx, kP3YIdx}, kMinProximity,
"ProximityP3"));
379 p4_cost.AddStateCost(p4p1_proximity_cost);
381 p4_cost.AddStateCost(p4p3_proximity_cost);
384 inline std::vector<float> FlatRoundaboutMergingExample::Xs(
385 const VectorXf& xi)
const {
386 return {xi(kP1XIdx), xi(kP2XIdx), xi(kP3XIdx), xi(kP4XIdx)};
389 inline std::vector<float> FlatRoundaboutMergingExample::Ys(
390 const VectorXf& xi)
const {
391 return {xi(kP1YIdx), xi(kP2YIdx), xi(kP3YIdx), xi(kP4YIdx)};
394 inline std::vector<float> FlatRoundaboutMergingExample::Thetas(
395 const VectorXf& xi)
const {
396 const VectorXf x = dynamics_->FromLinearSystemState(xi);
397 return {x(kP1HeadingIdx), x(kP2HeadingIdx), x(kP3HeadingIdx),