44 #include <ilqgames/solver/game_solver.h> 45 #include <ilqgames/solver/problem.h> 46 #include <ilqgames/utils/relative_time_tracker.h> 47 #include <ilqgames/utils/solver_log.h> 48 #include <ilqgames/utils/strategy.h> 49 #include <ilqgames/utils/types.h> 51 #include <glog/logging.h> 62 Problem::Problem() : initialized_(false) {}
64 size_t Problem::SyncToExistingProblem(
const VectorXf& x0, Time t0,
68 CHECK_GE(planner_runtime, 0.0);
69 CHECK_LE(planner_runtime + t0, operating_point_->t0 + time::kTimeHorizon);
70 CHECK_GE(t0, operating_point_->t0);
76 constexpr
float kRoundingError = 0.9;
77 const Time relative_t0 = t0 - op.t0;
78 size_t current_timestep =
static_cast<size_t>(relative_t0 / time::kTimeStep);
79 Time remaining_time_this_step =
80 (current_timestep + 1) * time::kTimeStep - relative_t0;
81 if (remaining_time_this_step < kRoundingError * time::kTimeStep) {
82 current_timestep += 1;
83 remaining_time_this_step = time::kTimeStep - remaining_time_this_step;
86 CHECK_LT(remaining_time_this_step, time::kTimeStep);
89 VectorXf x = dynamics_->IntegrateToNextTimeStep(t0, x0, *operating_point_,
91 op.t0 = t0 + remaining_time_this_step;
92 if (remaining_time_this_step <= planner_runtime) {
93 const size_t num_steps_to_integrate =
static_cast<size_t>(
94 constants::kSmallNumber +
95 (planner_runtime - remaining_time_this_step) / time::kTimeStep);
96 const size_t last_integration_timestep =
97 current_timestep + num_steps_to_integrate;
99 x = dynamics_->Integrate(current_timestep + 1, last_integration_timestep, x,
100 *operating_point_, *strategies_);
101 op.t0 += time::kTimeStep * num_steps_to_integrate;
105 const auto nearest_iter =
106 std::min_element(op.xs.begin(), op.xs.end(),
107 [
this, &x](
const VectorXf& x1,
const VectorXf& x2) {
108 return dynamics_->DistanceBetween(x, x1) <
109 dynamics_->DistanceBetween(x, x2);
113 const size_t first_timestep_in_new_problem =
114 std::distance(op.xs.begin(), nearest_iter);
117 x0_ = dynamics_->Stitch(*nearest_iter, x);
120 RelativeTimeTracker::ResetInitialTime(op.t0);
123 CHECK_LE(std::abs(t0 + planner_runtime - op.t0), time::kTimeStep);
124 return first_timestep_in_new_problem;
127 void Problem::SetUpNextRecedingHorizon(
const VectorXf& x0, Time t0,
128 Time planner_runtime) {
132 const size_t first_timestep_in_new_problem =
133 SyncToExistingProblem(x0, t0, planner_runtime, *operating_point_);
136 const size_t after_final_timestep =
137 first_timestep_in_new_problem + time::kNumTimeSteps;
138 const size_t timestep_iterator_end =
139 std::min(after_final_timestep, operating_point_->xs.size());
143 for (
size_t kk = first_timestep_in_new_problem; kk < timestep_iterator_end;
145 const size_t kk_new_problem = kk - first_timestep_in_new_problem;
148 operating_point_->xs[kk_new_problem].swap(operating_point_->xs[kk]);
149 operating_point_->us[kk_new_problem].swap(operating_point_->us[kk]);
150 CHECK_EQ(operating_point_->us[kk_new_problem].size(),
151 dynamics_->NumPlayers());
154 for (
auto& strategy : *strategies_) {
155 strategy.Ps[kk_new_problem].swap(strategy.Ps[kk]);
156 strategy.alphas[kk_new_problem].swap(strategy.alphas[kk]);
161 CHECK_GE(operating_point_->xs.size(), time::kNumTimeSteps);
162 if (operating_point_->xs.size() > time::kNumTimeSteps) {
163 operating_point_->xs.resize(time::kNumTimeSteps);
164 operating_point_->us.resize(time::kNumTimeSteps);
165 for (PlayerIndex ii = 0; ii < dynamics_->NumPlayers(); ii++) {
166 (*strategies_)[ii].Ps.resize(time::kNumTimeSteps);
167 (*strategies_)[ii].alphas.resize(time::kNumTimeSteps);
173 for (
size_t kk = timestep_iterator_end - first_timestep_in_new_problem;
174 kk < time::kNumTimeSteps; kk++) {
175 operating_point_->us[kk].resize(dynamics_->NumPlayers());
176 for (
size_t ii = 0; ii < dynamics_->NumPlayers(); ii++) {
177 (*strategies_)[ii].Ps[kk].setZero(dynamics_->UDim(ii), dynamics_->XDim());
178 (*strategies_)[ii].alphas[kk].setZero(dynamics_->UDim(ii));
179 operating_point_->us[kk][ii].setZero(dynamics_->UDim(ii));
182 operating_point_->xs[kk] = dynamics_->Integrate(
183 RelativeTimeTracker::RelativeTime(kk - 1), time::kTimeStep,
184 operating_point_->xs[kk - 1], operating_point_->us[kk - 1]);
188 void Problem::OverwriteSolution(
const OperatingPoint& operating_point,
189 const std::vector<Strategy>& strategies) {
192 *operating_point_ = operating_point;
193 *strategies_ = strategies;
196 bool Problem::IsConstrained()
const {
197 for (
const auto& pc : player_costs_) {
198 if (pc.IsConstrained())
return true;