ilqgames
A new real-time solver for large-scale differential games.
two_player_reachability_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 player reachability example. Protagonist choosing control to minimize
40 // max distance (-ve) signed distance to a wall, and antagonist choosing
41 // disturbance to maximize max signed distance.
42 //
43 ///////////////////////////////////////////////////////////////////////////////
44 
45 #include <ilqgames/constraint/single_dimension_constraint.h>
46 #include <ilqgames/cost/polyline2_signed_distance_cost.h>
47 #include <ilqgames/cost/quadratic_cost.h>
48 #include <ilqgames/dynamics/two_player_unicycle_4d.h>
49 #include <ilqgames/examples/two_player_reachability_example.h>
50 #include <ilqgames/geometry/draw_shapes.h>
51 #include <ilqgames/geometry/polyline2.h>
52 #include <ilqgames/solver/ilq_solver.h>
53 #include <ilqgames/solver/problem.h>
54 #include <ilqgames/solver/solver_params.h>
55 #include <ilqgames/utils/types.h>
56 
57 #include <gflags/gflags.h>
58 #include <math.h>
59 #include <memory>
60 #include <vector>
61 
62 // Initial state command-line flags.
63 DEFINE_double(px0, 0.0, "Initial x-position (m).");
64 DEFINE_double(py0, -10.0, "Initial y-position (m).");
65 DEFINE_double(theta0, M_PI / 4.0, "Initial heading (rad).");
66 DEFINE_double(v0, 5.0, "Initial speed (m/s).");
67 
68 namespace ilqgames {
69 
70 namespace {
71 
72 static constexpr float kOmegaMax = 0.1; // rad/s
73 static constexpr float kAMax = 1.0; // m/s/s
74 static constexpr float kDMax = 0.5; // m/s
75 static constexpr float kControlCostWeight = 0.1;
76 
77 // State dimensions.
78 using Dyn = TwoPlayerUnicycle4D;
79 
80 } // anonymous namespace
81 
82 void TwoPlayerReachabilityExample::ConstructDynamics() {
83  dynamics_.reset(new TwoPlayerUnicycle4D());
84 }
85 
86 void TwoPlayerReachabilityExample::ConstructInitialState() {
87  x0_ = VectorXf::Zero(dynamics_->XDim());
88  x0_(Dyn::kPxIdx) = FLAGS_px0;
89  x0_(Dyn::kPyIdx) = FLAGS_py0;
90  x0_(Dyn::kThetaIdx) = FLAGS_theta0;
91  x0_(Dyn::kVIdx) = FLAGS_v0;
92 }
93 
94 void TwoPlayerReachabilityExample::ConstructPlayerCosts() {
95  // Set up costs for all players.
96  player_costs_.emplace_back("P1");
97  player_costs_.emplace_back("P2");
98  auto& p1_cost = player_costs_[0];
99  auto& p2_cost = player_costs_[1];
100 
101  const auto control_cost = std::make_shared<QuadraticCost>(
102  kControlCostWeight, -1, 0.0, "ControlCost");
103  p1_cost.AddControlCost(0, control_cost);
104  p2_cost.AddControlCost(1, control_cost);
105 
106  // Target cost.
107  static constexpr bool kReach = true;
108  const float kTargetRadius = 1.0;
109  const Polyline2 circle = DrawCircle(Point2::Zero(), kTargetRadius, 10);
110  const std::shared_ptr<Polyline2SignedDistanceCost> p1_target_cost(
111  new Polyline2SignedDistanceCost(circle, {Dyn::kPxIdx, Dyn::kPyIdx},
112  !kReach, "Target"));
113  const std::shared_ptr<Polyline2SignedDistanceCost> p2_target_cost(
114  new Polyline2SignedDistanceCost(circle, {Dyn::kPxIdx, Dyn::kPyIdx},
115  kReach, "Target"));
116 
117  p1_cost.AddStateCost(p1_target_cost);
118  p2_cost.AddStateCost(p2_target_cost);
119 
120  // Make sure costs are max-over-time.
121  p1_cost.SetMaxOverTime();
122  p2_cost.SetMinOverTime();
123 }
124 
125 inline std::vector<float> TwoPlayerReachabilityExample::Xs(
126  const VectorXf& x) const {
127  return {x(Dyn::kPxIdx)};
128 }
129 
130 inline std::vector<float> TwoPlayerReachabilityExample::Ys(
131  const VectorXf& x) const {
132  return {x(Dyn::kPyIdx)};
133 }
134 
135 inline std::vector<float> TwoPlayerReachabilityExample::Thetas(
136  const VectorXf& x) const {
137  return {x(Dyn::kThetaIdx)};
138 }
139 
140 } // namespace ilqgames