planning_problem.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2018-2020, University of Edinburgh, University of Oxford
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 met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without specific
15 // prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 
30 #include <algorithm>
31 #include <limits>
32 #include <utility>
33 
35 #include <exotica_core/server.h>
36 #include <exotica_core/setup.h>
37 
38 #include <exotica_core/planning_problem_initializer.h>
39 #include <exotica_core/task_map_initializer.h>
40 
41 namespace exotica
42 {
45 
46 std::string PlanningProblem::Print(const std::string& prepend) const
47 {
48  std::string ret = Object::Print(prepend);
49  ret += "\n" + prepend + " Task definitions:";
50  for (const auto& it : task_maps_)
51  ret += "\n" + it.second->Print(prepend + " ");
52  return ret;
53 }
54 
56 {
57  return scene_->get_num_positions();
58 }
59 
61 {
62  return scene_->get_num_velocities();
63 }
64 
66 {
67  return scene_->get_num_controls();
68 }
69 
70 Eigen::VectorXd PlanningProblem::ApplyStartState(bool update_traj)
71 {
72  // If we have a scene with a dynamics solver, get position from there
73  if (scene_->GetDynamicsSolver() != nullptr)
74  {
75  const Eigen::VectorXd start_state = scene_->GetDynamicsSolver()->GetPosition(start_state_);
76  scene_->SetModelState(start_state, t_start, update_traj);
77  }
78  else
79  {
80  scene_->SetModelState(start_state_.head(scene_->get_num_positions()), t_start, update_traj);
81  }
82 
83  return scene_->GetControlledState();
84 }
85 
87 {
88  for (auto& it : task_maps_) it.second->PreUpdate();
89 }
90 
92 {
93  const auto num_states = scene_->get_num_positions() + scene_->get_num_velocities();
94  if (x.rows() == num_states)
95  {
96  start_state_ = x;
97  }
98  else if (x.rows() == scene_->GetKinematicTree().GetNumControlledJoints())
99  {
100  std::vector<std::string> jointNames = scene_->GetControlledJointNames();
101  std::vector<std::string> modelNames = scene_->GetModelJointNames();
102  for (int i = 0; i < jointNames.size(); ++i)
103  {
104  for (int j = 0; j < modelNames.size(); ++j)
105  {
106  if (jointNames[i] == modelNames[j]) start_state_[j] = x(i);
107  }
108  }
109  }
110  else if (x.rows() == scene_->get_num_positions())
111  {
112  start_state_.head(scene_->get_num_positions()) = x;
113  }
114  // TODO: Add support for num_controlled + tangent vector size initialisation
115  else
116  {
117  ThrowNamed("Wrong start state vector size, expected " << num_states << ", got " << x.rows());
118  }
119 }
120 
121 Eigen::VectorXd PlanningProblem::GetStartState() const
122 {
123  return start_state_;
124 }
125 
127 {
128  t_start = t;
129 }
130 
132 {
133  return t_start;
134 }
135 
137 {
138  Object::InstantiateObject(init_in);
139  PlanningProblemInitializer init(init_in);
140 
141  task_maps_.clear();
142  tasks_.clear();
143 
144  // Create the scene
145  scene_.reset(new Scene());
146  scene_->InstantiateInternal(SceneInitializer(init.PlanningScene));
147 
148  // Set size of positions. This is valid for kinematic problems and will be
149  // overridden in dynamic problems inside the Scene.
150  // TODO: "N" should be determined by the Scene or size of the StateVector.
151  N = scene_->GetKinematicTree().GetNumControlledJoints();
152 
153  // Set the start state
154  start_state_ = Eigen::VectorXd::Zero(scene_->get_num_positions() + scene_->get_num_velocities());
155  if (init.StartState.rows() > 0)
156  SetStartState(init.StartState);
157 
158  // Check if the start state needs to be normalised due to a quaternion
159  if (scene_->GetDynamicsSolver() != nullptr &&
160  scene_->GetKinematicTree().GetModelBaseType() == BaseType::FLOATING &&
161  scene_->GetDynamicsSolver()->get_num_state() == scene_->GetDynamicsSolver()->get_num_state_derivative() + 1)
162  {
164  }
165 
166  // Set the start time
167  if (init.StartTime < 0) ThrowNamed("Invalid start time " << init.StartTime);
168  t_start = init.StartTime;
169 
170  // Set the derivative order for Kinematics
171  switch (init.DerivativeOrder)
172  {
173  case -1:
174  // No change - the derived problems have to set it.
175  break;
176  case 0:
177  flags_ = KIN_FK;
178  break;
179  case 1:
180  flags_ = KIN_FK | KIN_J;
181  break;
182  case 2:
183  flags_ = KIN_FK | KIN_J | KIN_H;
184  break;
185  default:
186  ThrowPretty("Unsupported DerivativeOrder: " << init.DerivativeOrder);
187  }
188 
189  KinematicsRequest request;
190  request.flags = flags_;
191 
192  // Create the maps
193  int id = 0;
194  for (const Initializer& MapInitializer : init.Maps)
195  {
196  TaskMapPtr new_map = Setup::CreateMap(MapInitializer);
197  new_map->AssignScene(scene_);
198  new_map->ns_ = ns_ + "/" + new_map->GetObjectName();
199  if (task_maps_.find(new_map->GetObjectName()) != task_maps_.end())
200  {
201  ThrowNamed("Map '" + new_map->GetObjectName() + "' already exists!");
202  }
203  std::vector<KinematicFrameRequest> frames = new_map->GetFrames();
204 
205  for (size_t i = 0; i < new_map->kinematics.size(); ++i)
206  new_map->kinematics[i] = KinematicSolution(id, frames.size());
207  id += frames.size();
208 
209  request.frames.insert(request.frames.end(), frames.begin(), frames.end());
210  task_maps_[new_map->GetObjectName()] = new_map;
211  tasks_.push_back(new_map);
212  }
213  scene_->RequestKinematics(request, std::bind(&PlanningProblem::UpdateTaskKinematics, this, std::placeholders::_1));
214 
215  id = 0;
216  int idJ = 0;
217  for (int i = 0; i < tasks_.size(); ++i)
218  {
219  tasks_[i]->id = i;
220  tasks_[i]->start = id;
221  tasks_[i]->length = tasks_[i]->TaskSpaceDim();
222  tasks_[i]->start_jacobian = idJ;
223  tasks_[i]->length_jacobian = tasks_[i]->TaskSpaceJacobianDim();
224  id += tasks_[i]->length;
225  idJ += tasks_[i]->length_jacobian;
226  }
227 
228  if (debug_ && init.Maps.size() == 0)
229  {
230  HIGHLIGHT("No maps were defined!");
231  }
232 }
233 
234 void PlanningProblem::UpdateTaskKinematics(std::shared_ptr<KinematicResponse> response)
235 {
236  for (auto task : tasks_)
237  task->kinematics[0].Create(response);
238 }
239 
240 void PlanningProblem::UpdateMultipleTaskKinematics(std::vector<std::shared_ptr<KinematicResponse>> responses)
241 {
242  for (auto task : tasks_)
243  {
244  if (task->kinematics.size() > responses.size())
245  {
246  ThrowNamed(responses.size() << " responses provided but task " << task->GetObjectName() << " requires " << task->kinematics.size());
247  }
248 
249  for (size_t i = 0; i < task->kinematics.size(); ++i)
250  {
251  task->kinematics[i].Create(responses[i]);
252  }
253  }
254 }
255 
257 {
258  return task_maps_;
259 }
260 
262 {
263  return tasks_;
264 }
265 
267 {
268  return scene_;
269 }
270 
271 std::pair<std::vector<double>, std::vector<double>> PlanningProblem::GetCostEvolution() const
272 {
273  std::pair<std::vector<double>, std::vector<double>> ret;
274  for (size_t position = 0; position < cost_evolution_.size(); ++position)
275  {
276  if (std::isnan(cost_evolution_[position].second)) break;
277  double time_point = std::chrono::duration_cast<std::chrono::duration<double>>(cost_evolution_[position].first - cost_evolution_[0].first).count();
278  ret.first.push_back(time_point);
279  ret.second.push_back(cost_evolution_[position].second);
280  }
281  return ret;
282 }
283 
285 {
286  return static_cast<int>(std::get<0>(GetCostEvolution()).size());
287 }
288 
289 double PlanningProblem::GetCostEvolution(int index) const
290 {
291  if (index > -1 && index < cost_evolution_.size())
292  {
293  return cost_evolution_[index].second;
294  }
295  else if (index == -1)
296  {
297  return cost_evolution_[cost_evolution_.size() - 1].second;
298  }
299  else
300  {
301  ThrowPretty("Out of range");
302  }
303 }
304 
306 {
307  cost_evolution_.resize(size);
308  cost_evolution_.assign(size, std::make_pair<std::chrono::high_resolution_clock::time_point, double>(std::chrono::high_resolution_clock::now(), std::numeric_limits<double>::quiet_NaN()));
309 }
310 
311 void PlanningProblem::SetCostEvolution(int index, double value)
312 {
313  if (index > -1 && index < cost_evolution_.size())
314  {
315  cost_evolution_[index].first = std::chrono::high_resolution_clock::now();
316  cost_evolution_[index].second = value;
317  }
318  else if (index == -1)
319  {
320  cost_evolution_[cost_evolution_.size() - 1].first = std::chrono::high_resolution_clock::now();
321  cost_evolution_[cost_evolution_.size() - 1].second = value;
322  }
323  else
324  {
325  ThrowPretty("Out of range: " << index << " where length=" << cost_evolution_.size());
326  }
327 }
328 } // namespace exotica
#define HIGHLIGHT(x)
Definition: printable.h:61
KinematicRequestFlags flags_
std::shared_ptr< TaskMap > TaskMapPtr
Task Map smart pointer.
Definition: task_map.h:92
int get_num_positions() const
! Dimension of planning problem. TODO: Update from positions/velocities/controls and make private...
virtual Eigen::VectorXd ApplyStartState(bool update_traj=true)
std::vector< KinematicFrameRequest > frames
void NormalizeQuaternionInConfigurationVector(Eigen::Ref< Eigen::VectorXd > q)
Definition: conversions.h:141
void InstantiateBase(const Initializer &init) override
void InstantiateObject(const Initializer &init)
Definition: object.h:71
void UpdateTaskKinematics(std::shared_ptr< KinematicResponse > response)
std::vector< std::pair< std::chrono::high_resolution_clock::time_point, double > > cost_evolution_
void ResetCostEvolution(size_t size)
std::vector< TaskMapPtr > TaskMapVec
Definition: task_map.h:94
#define ThrowPretty(m)
Definition: exception.h:36
std::shared_ptr< Scene > ScenePtr
Definition: scene.h:246
std::string Print(const std::string &prepend) const override
std::string ns_
Definition: object.h:84
#define ThrowNamed(m)
Definition: exception.h:42
KinematicRequestFlags flags
std::pair< std::vector< double >, std::vector< double > > GetCostEvolution() const
The KinematicSolution is created from - and maps into - a KinematicResponse.
bool debug_
Definition: object.h:86
The class of EXOTica Scene.
Definition: scene.h:69
const Eigen::Ref< const Eigen::VectorXd > & VectorXdRefConst
Convenience wrapper for storing references to sub-matrices/vectors.
Definition: conversions.h:52
Eigen::VectorXd GetStartState() const
void UpdateMultipleTaskKinematics(std::vector< std::shared_ptr< KinematicResponse >> responses)
void SetCostEvolution(int index, double value)
void SetStartState(Eigen::VectorXdRefConst x)
std::map< std::string, TaskMapPtr > TaskMapMap
The mapping by name of TaskMaps.
Definition: task_map.h:93
static std::shared_ptr< exotica::TaskMap > CreateMap(const std::string &type, bool prepend=true)
Definition: setup.h:64
virtual std::string Print(const std::string &prepend) const
Definition: object.h:78
Eigen::VectorXd start_state_


exotica_core
Author(s): Yiming Yang, Michael Camilleri
autogenerated on Sat Apr 10 2021 02:34:49