time_indexed_sampling_problem.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2018, University of Edinburgh
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 
31 #include <exotica_core/setup.h>
32 
34 
36 {
37 TimeIndexedSamplingProblem::TimeIndexedSamplingProblem()
38 {
39  flags_ = KIN_FK;
40 }
41 
42 TimeIndexedSamplingProblem::~TimeIndexedSamplingProblem() = default;
43 
44 std::vector<double> TimeIndexedSamplingProblem::GetBounds()
45 {
46  std::vector<double> bounds;
47  auto joint_limits = scene_->GetKinematicTree().GetJointLimits();
48 
49  bounds.resize(2 * N);
50  for (unsigned int i = 0; i < N; ++i)
51  {
52  bounds[i] = joint_limits(i, 0);
53  bounds[i + N] = joint_limits(i, 1);
54  }
55 
56  return bounds;
57 }
58 
59 void TimeIndexedSamplingProblem::Instantiate(const TimeIndexedSamplingProblemInitializer& init)
60 {
61  parameters = init;
62 
63  if (init.Goal.size() == N)
64  {
65  goal_ = init.Goal;
66  }
67  else if (init.Goal.size() == 0)
68  {
69  goal_ = Eigen::VectorXd::Zero(N);
70  }
71  else
72  {
73  ThrowNamed("Dimension mismatch: problem N=" << N << ", but goal state has dimension " << goal_.rows());
74  }
75 
76  t_goal_ = init.GoalTime;
77  if (t_goal_ <= t_start)
78  ThrowNamed("Invalid goal time t_goal= " << t_goal_ << ", where t_start=" << t_start);
79 
80  if (init.JointVelocityLimits.size() == N)
81  {
82  vel_limits = init.JointVelocityLimits;
83  }
84  else if (init.JointVelocityLimits.size() == 1)
85  {
86  vel_limits = init.JointVelocityLimits(0) * Eigen::VectorXd::Ones(N);
87  }
88  else
89  {
90  ThrowNamed("Dimension mismatch: problem N=" << N << ", but joint velocity limits has dimension " << vel_limits.rows());
91  }
92 
93  num_tasks = tasks_.size();
94  length_Phi = 0;
95  length_jacobian = 0;
96  for (int i = 0; i < num_tasks; ++i)
97  {
98  AppendVector(Phi.map, tasks_[i]->GetLieGroupIndices());
99  length_Phi += tasks_[i]->length;
100  length_jacobian += tasks_[i]->length_jacobian;
101  }
102  Phi.SetZero(length_Phi);
103 
104  inequality.Initialize(init.Inequality, shared_from_this(), constraint_phi);
105  inequality.tolerance = init.ConstraintTolerance;
106  equality.Initialize(init.Equality, shared_from_this(), constraint_phi);
107  equality.tolerance = init.ConstraintTolerance;
108 
109  ApplyStartState(false);
110 
111  if (scene_->GetKinematicTree().GetControlledBaseType() != exotica::BaseType::FIXED && init.FloatingBaseLowerLimits.rows() > 0 && init.FloatingBaseUpperLimits.rows() > 0)
112  {
113  if (scene_->GetKinematicTree().GetControlledBaseType() == exotica::BaseType::FLOATING && init.FloatingBaseLowerLimits.rows() == 6 && init.FloatingBaseUpperLimits.rows() == 6)
114  {
115  scene_->GetKinematicTree().SetFloatingBaseLimitsPosXYZEulerZYX(
116  std::vector<double>(init.FloatingBaseLowerLimits.data(), init.FloatingBaseLowerLimits.data() + init.FloatingBaseLowerLimits.size()),
117  std::vector<double>(init.FloatingBaseUpperLimits.data(), init.FloatingBaseUpperLimits.data() + init.FloatingBaseUpperLimits.size()));
118  }
119  else if (scene_->GetKinematicTree().GetControlledBaseType() == exotica::BaseType::PLANAR && init.FloatingBaseLowerLimits.rows() == 3 && init.FloatingBaseUpperLimits.rows() == 3)
120  {
121  scene_->GetKinematicTree().SetPlanarBaseLimitsPosXYEulerZ(
122  std::vector<double>(init.FloatingBaseLowerLimits.data(), init.FloatingBaseLowerLimits.data() + init.FloatingBaseLowerLimits.size()),
123  std::vector<double>(init.FloatingBaseUpperLimits.data(), init.FloatingBaseUpperLimits.data() + init.FloatingBaseUpperLimits.size()));
124  }
125  else
126  {
127  ThrowNamed("Invalid base limits!");
128  }
129  }
130 
131  PreUpdate();
132 }
133 
134 double TimeIndexedSamplingProblem::GetGoalTime() const
135 {
136  return t_goal_;
137 }
138 
139 void TimeIndexedSamplingProblem::SetGoalTime(const double& t)
140 {
141  t_goal_ = t;
142 }
143 
144 Eigen::VectorXd TimeIndexedSamplingProblem::GetGoalState() const
145 {
146  return goal_;
147 }
148 
149 void TimeIndexedSamplingProblem::SetGoalState(Eigen::VectorXdRefConst qT)
150 {
151  if (qT.rows() != N)
152  ThrowPretty("Dimensionality of goal state wrong: Got " << qT.rows() << ", expected " << N);
153  goal_ = qT;
154 }
155 
156 void TimeIndexedSamplingProblem::SetGoalEQ(const std::string& task_name, Eigen::VectorXdRefConst goal)
157 {
158  for (int i = 0; i < equality.indexing.size(); ++i)
159  {
160  if (equality.tasks[i]->GetObjectName() == task_name)
161  {
162  if (goal.rows() != equality.indexing[i].length) ThrowPretty("Expected length of " << equality.indexing[i].length << " and got " << goal.rows());
163  equality.y.data.segment(equality.indexing[i].start, equality.indexing[i].length) = goal;
164  return;
165  }
166  }
167  ThrowPretty("Cannot set Goal. Task map '" << task_name << "' does not exist.");
168 }
169 
170 void TimeIndexedSamplingProblem::SetRhoEQ(const std::string& task_name, const double& rho)
171 {
172  for (int i = 0; i < equality.indexing.size(); ++i)
173  {
174  if (equality.tasks[i]->GetObjectName() == task_name)
175  {
176  equality.rho(equality.indexing[i].id) = rho;
177  PreUpdate();
178  return;
179  }
180  }
181  ThrowPretty("Cannot set rho. Task map '" << task_name << "' does not exist.");
182 }
183 
184 Eigen::VectorXd TimeIndexedSamplingProblem::GetGoalEQ(const std::string& task_name)
185 {
186  for (int i = 0; i < equality.indexing.size(); ++i)
187  {
188  if (equality.tasks[i]->GetObjectName() == task_name)
189  {
190  return equality.y.data.segment(equality.indexing[i].start, equality.indexing[i].length);
191  }
192  }
193  ThrowPretty("Cannot get Goal. Task map '" << task_name << "' does not exist.");
194 }
195 
196 double TimeIndexedSamplingProblem::GetRhoEQ(const std::string& task_name)
197 {
198  for (int i = 0; i < equality.indexing.size(); ++i)
199  {
200  if (equality.tasks[i]->GetObjectName() == task_name)
201  {
202  return equality.rho(equality.indexing[i].id);
203  }
204  }
205  ThrowPretty("Cannot get rho. Task map '" << task_name << "' does not exist.");
206 }
207 
208 void TimeIndexedSamplingProblem::SetGoalNEQ(const std::string& task_name, Eigen::VectorXdRefConst goal)
209 {
210  for (int i = 0; i < inequality.indexing.size(); ++i)
211  {
212  if (inequality.tasks[i]->GetObjectName() == task_name)
213  {
214  if (goal.rows() != inequality.indexing[i].length) ThrowPretty("Expected length of " << inequality.indexing[i].length << " and got " << goal.rows());
215  inequality.y.data.segment(inequality.indexing[i].start, inequality.indexing[i].length) = goal;
216  return;
217  }
218  }
219  ThrowPretty("Cannot set Goal. Task map '" << task_name << "' does not exist.");
220 }
221 
222 void TimeIndexedSamplingProblem::SetRhoNEQ(const std::string& task_name, const double& rho)
223 {
224  for (int i = 0; i < inequality.indexing.size(); ++i)
225  {
226  if (inequality.tasks[i]->GetObjectName() == task_name)
227  {
228  inequality.rho(inequality.indexing[i].id) = rho;
229  PreUpdate();
230  return;
231  }
232  }
233  ThrowPretty("Cannot set rho. Task map '" << task_name << "' does not exist.");
234 }
235 
236 Eigen::VectorXd TimeIndexedSamplingProblem::GetGoalNEQ(const std::string& task_name)
237 {
238  for (int i = 0; i < inequality.indexing.size(); ++i)
239  {
240  if (inequality.tasks[i]->GetObjectName() == task_name)
241  {
242  return inequality.y.data.segment(inequality.indexing[i].start, inequality.indexing[i].length);
243  }
244  }
245  ThrowPretty("Cannot get Goal. Task map '" << task_name << "' does not exist.");
246 }
247 
248 double TimeIndexedSamplingProblem::GetRhoNEQ(const std::string& task_name)
249 {
250  for (int i = 0; i < inequality.indexing.size(); ++i)
251  {
252  if (inequality.tasks[i]->GetObjectName() == task_name)
253  {
254  return inequality.rho(inequality.indexing[i].id);
255  }
256  }
257  ThrowPretty("Cannot get rho. Task map '" << task_name << "' does not exist.");
258 }
259 
260 bool TimeIndexedSamplingProblem::IsValid(Eigen::VectorXdRefConst x, const double& t)
261 {
262  scene_->Update(x, t);
263  for (int i = 0; i < num_tasks; ++i)
264  {
265  if (tasks_[i]->is_used)
266  tasks_[i]->Update(x, Phi.data.segment(tasks_[i]->start, tasks_[i]->length));
267  }
268  inequality.Update(Phi);
269  equality.Update(Phi);
270  ++number_of_problem_updates_;
271 
272  bool inequality_is_valid = ((inequality.S * inequality.ydiff).array() <= 0.0).all();
273  bool equality_is_valid = ((equality.S * equality.ydiff).array().abs() == 0.0).all();
274 
275  if (debug_)
276  {
277  HIGHLIGHT_NAMED("TimeIndexedSamplingProblem::IsValid", "Equality valid? = " << equality_is_valid << "\tInequality valid? = " << inequality_is_valid);
278  }
279 
280  return (inequality_is_valid && equality_is_valid);
281 }
282 
283 void TimeIndexedSamplingProblem::PreUpdate()
284 {
285  PlanningProblem::PreUpdate();
286  for (int i = 0; i < tasks_.size(); ++i) tasks_[i]->is_used = false;
287  inequality.UpdateS();
288  equality.UpdateS();
289 }
290 
291 void TimeIndexedSamplingProblem::Update(Eigen::VectorXdRefConst x, const double& t)
292 {
293  IsValid(x, t);
294  ++number_of_problem_updates_;
295 }
296 
297 int TimeIndexedSamplingProblem::GetSpaceDim()
298 {
299  return N;
300 }
301 } // namespace exotica
#define ThrowPretty(m)
Definition: exception.h:36
#define ThrowNamed(m)
Definition: exception.h:42
const Eigen::Ref< const Eigen::VectorXd > & VectorXdRefConst
Convenience wrapper for storing references to sub-matrices/vectors.
Definition: conversions.h:52
#define HIGHLIGHT_NAMED(name, x)
Definition: printable.h:62
void AppendVector(std::vector< Val > &orig, const std::vector< Val > &extra)
Definition: conversions.h:223
#define REGISTER_PROBLEM_TYPE(TYPE, DERIV)


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