ilqgames
A new real-time solver for large-scale differential games.
dubins_origin_example.cpp
1 /*
2  * Copyright (c) 2020, The Regents of the University of California (Regents).
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following
14  * disclaimer in the documentation and/or other materials provided
15  * with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Please contact the author(s) of this library if you have any questions.
34  * Authors: David Fridovich-Keil ( dfk@eecs.berkeley.edu )
35  */
36 
37 ///////////////////////////////////////////////////////////////////////////////
38 //
39 // Two Dubins cars. One tries to follow other one, which is trying to get to the
40 // origin. Both also have penalties on control input, and we are interested in
41 // the difference between open-loop and feedback Nash strategies for this
42 // situation. Example conceived by Forrest Laine ( forrest.laine@berkeley.edu ).
43 //
44 ///////////////////////////////////////////////////////////////////////////////
45 
46 #include <ilqgames/cost/quadratic_cost.h>
47 #include <ilqgames/cost/quadratic_difference_cost.h>
48 #include <ilqgames/dynamics/concatenated_dynamical_system.h>
49 #include <ilqgames/dynamics/single_player_dubins_car.h>
50 #include <ilqgames/examples/dubins_origin_example.h>
51 #include <ilqgames/solver/ilq_solver.h>
52 #include <ilqgames/solver/problem.h>
53 #include <ilqgames/solver/solver_params.h>
54 #include <ilqgames/utils/types.h>
55 
56 #include <math.h>
57 #include <memory>
58 #include <vector>
59 
60 namespace ilqgames {
61 
62 namespace {
63 
64 // Cost weights.
65 static constexpr float kOmegaCostWeight = 100.0;
66 static constexpr float kAttractionCostWeight = 10.0;
67 static constexpr float kGoalCostWeight = 10.0;
68 
69 // Initial state.
70 static constexpr float kP1InitialX = 0.0; // m
71 static constexpr float kP1InitialY = -10.0; // m
72 static constexpr float kP1InitialHeading = M_PI - 0.01; // rad
73 
74 static constexpr float kP2InitialX = 0.0; // m
75 static constexpr float kP2InitialY = 10.0; // m
76 static constexpr float kP2InitialHeading = 1.5 * M_PI; // rad
77 
78 static constexpr float kSpeed = 1.0; // m/s
79 
80 // Goal position.
81 static constexpr float kP2GoalX = 0.0;
82 static constexpr float kP2GoalY = 0.0;
83 
84 // State dimensions.
85 using P1 = SinglePlayerDubinsCar;
86 using P2 = SinglePlayerDubinsCar;
87 
88 static const Dimension kP1XIdx = P1::kPxIdx;
89 static const Dimension kP1YIdx = P1::kPyIdx;
90 static const Dimension kP1HeadingIdx = P1::kThetaIdx;
91 
92 static const Dimension kP2XIdx = P1::kNumXDims + P2::kPxIdx;
93 static const Dimension kP2YIdx = P1::kNumXDims + P2::kPyIdx;
94 static const Dimension kP2HeadingIdx = P1::kNumXDims + P2::kThetaIdx;
95 
96 // Control dimensions.
97 static const Dimension kP1OmegaIdx = 0;
98 static const Dimension kP2OmegaIdx = 0;
99 } // anonymous namespace
100 
101 void DubinsOriginExample::ConstructDynamics() {
102  dynamics_.reset(new ConcatenatedDynamicalSystem(
103  {std::make_shared<P1>(kSpeed), std::make_shared<P2>(kSpeed)}));
104 }
105 
106 void DubinsOriginExample::ConstructInitialState() {
107  // Set up initial state.
108  x0_ = VectorXf::Zero(dynamics_->XDim());
109  x0_(kP1XIdx) = kP1InitialX;
110  x0_(kP1YIdx) = kP1InitialY;
111  x0_(kP1HeadingIdx) = kP1InitialHeading;
112  x0_(kP2XIdx) = kP2InitialX;
113  x0_(kP2YIdx) = kP2InitialY;
114  x0_(kP2HeadingIdx) = kP2InitialHeading;
115 }
116 
117 void DubinsOriginExample::ConstructPlayerCosts() {
118  // Set up costs for all players.
119  player_costs_.emplace_back("P1");
120  player_costs_.emplace_back("P2");
121  auto& p1_cost = player_costs_[0];
122  auto& p2_cost = player_costs_[1];
123 
124  // Attract P2 to P1.
125  const std::shared_ptr<QuadraticDifferenceCost> p2_attraction_cost =
126  std::shared_ptr<QuadraticDifferenceCost>(
127  new QuadraticDifferenceCost(kAttractionCostWeight, {kP1XIdx, kP1YIdx},
128  {kP2XIdx, kP2YIdx}, "AttractionCost"));
129  p2_cost.AddStateCost(p2_attraction_cost);
130 
131  // Penalize control effort.
132  const auto p1_omega_cost = std::make_shared<QuadraticCost>(
133  kOmegaCostWeight, kP1OmegaIdx, 0.0, "Steering");
134  p1_cost.AddControlCost(0, p1_omega_cost);
135 
136  const auto p2_omega_cost = std::make_shared<QuadraticCost>(
137  kOmegaCostWeight, kP2OmegaIdx, 0.0, "Steering");
138  p2_cost.AddControlCost(1, p2_omega_cost);
139 
140  // Goal cost.
141  const auto p1_goalx_cost = std::make_shared<QuadraticCost>(
142  kGoalCostWeight, kP2XIdx, kP2GoalX, "GoalX");
143  const auto p1_goaly_cost = std::make_shared<QuadraticCost>(
144  kGoalCostWeight, kP2YIdx, kP2GoalY, "GoalY");
145  p1_cost.AddStateCost(p1_goalx_cost);
146  p1_cost.AddStateCost(p1_goaly_cost);
147 }
148 
149 inline std::vector<float> DubinsOriginExample::Xs(const VectorXf& x) const {
150  return {x(kP1XIdx), x(kP2XIdx)};
151 }
152 
153 inline std::vector<float> DubinsOriginExample::Ys(const VectorXf& x) const {
154  return {x(kP1YIdx), x(kP2YIdx)};
155 }
156 
157 inline std::vector<float> DubinsOriginExample::Thetas(const VectorXf& x) const {
158  return {x(kP1HeadingIdx), x(kP2HeadingIdx)};
159 }
160 
161 } // namespace ilqgames