choreo_ladder_graph_builder.cpp
Go to the documentation of this file.
2 
3 #include "../include/choreo_descartes_planner/pose_sampling_helpers.h"
4 #include "../include/choreo_descartes_planner/pose_verification_helpers.h"
5 
6 // declare for descartes edge policy
7 namespace descartes_planner
8 {
9 typedef boost::function<double(const double*, const double*)> CostFunction;
10 }
11 
12 #include "descartes_planner/planning_graph_edge_policy.h"
13 
14 namespace // anon namespace to hide utility functions
15 {
16 
17 void concatenate(descartes_planner::LadderGraph& dest, const descartes_planner::LadderGraph& src)
18 {
19  assert(dest.size() > 0);
20  assert(src.size() > 0);
21  assert(dest.size() == src.size()); // same number of rungs
22  // TODO
23  // Combines the joints and edges from one graph, src, into another, dest
24  // The joints copy straight over, but the index of the points needs to be transformed
25  for (std::size_t i = 0; i < src.size(); ++i)
26  {
27  // Copy the joints
28  auto& dest_joints = dest.getRung(i).data;
29  const auto& src_joints = src.getRung(i).data;
30  dest_joints.insert(dest_joints.end(), src_joints.begin(), src_joints.end());
31 
32  if (i != src.size() - 1)
33  {
34  // Copy the edges and transform them
35  const auto next_rung_size = dest.rungSize(i + 1);
36  auto& dest_edges = dest.getEdges(i);
37  const auto& src_edges = src.getEdges(i);
38  for (const auto& edge : src_edges)
39  {
40  auto edge_copy = edge;
41  for (auto& e : edge_copy)
42  e.idx += next_rung_size;
43  dest_edges.push_back(edge_copy);
44  }
45  }
46  }
47 }
48 
49 } // end anon utility function ns
50 
51 namespace descartes_planner
52 {
53 
54 LadderGraph generateLadderGraphFromPoses(const descartes_core::RobotModel &model,
55  const std::vector <Eigen::Affine3d> &ps,
56  const double dt)
57 {
58  descartes_planner::LadderGraph graph(model.getDOF());
59  graph.resize(ps.size());
60 
61  const descartes_core::TimingConstraint timing(dt);
62 
63  // Solve IK for each point
64  for (std::size_t i = 0; i < ps.size(); ++i)
65  {
66  std::vector <std::vector<double>> joint_poses;
67  model.getAllIK(ps[i], joint_poses);
68 
69  graph.assignRung(i, descartes_core::TrajectoryID::make_nil(), timing, joint_poses);
70  }
71 
72  bool has_edges_t = true;
73 
74  // now we have a graph with data in the 'rungs' and we need to compute the edges
75  // for the last rung, there's no out edge
76  for (std::size_t i = 0; i < graph.size() - 1; ++i)
77  {
78  const auto start_idx = i;
79  const auto end_idx = i + 1;
80  const auto &joints1 = graph.getRung(start_idx).data;
81  const auto &joints2 = graph.getRung(end_idx).data;
82  const auto &tm = graph.getRung(end_idx).timing;
83  const auto dof = model.getDOF();
84 
85  const auto start_size = joints1.size() / dof;
86  const auto end_size = joints2.size() / dof;
87 
88  descartes_planner::DefaultEdgesWithTime builder(start_size, end_size, dof, tm.upper,
89  model.getJointVelocityLimits());
90  for (size_t k = 0; k < start_size; k++) // from rung
91  {
92  const auto start_index = k * dof;
93 
94  for (size_t j = 0; j < end_size; j++) // to rung
95  {
96  const auto end_index = j * dof;
97 
98  builder.consider(&joints1[start_index], &joints2[end_index], j);
99  }
100  builder.next(k);
101  }
102 
103  std::vector <descartes_planner::LadderGraph::EdgeList> edges = builder.result();
104  if (!builder.hasEdges())
105  {
106 // ROS_WARN("No edges");
107  }
108 
109  has_edges_t = has_edges_t && builder.hasEdges();
110  graph.assignEdges(i, std::move(edges));
111  } // end edge loop
112 
113  return graph;
114 }
115 
116 LadderGraph sampleSingleConfig(const descartes_core::RobotModel &model,
117  const std::vector <Eigen::Vector3d> &origins,
118  const double dt,
119  const Eigen::Matrix3d &orientation,
120  const double z_axis_angle)
121 {
122  std::vector <Eigen::Affine3d> poses;
123 
124  for (const auto &o : origins)
125  {
126  poses.push_back(makePose(o, orientation, z_axis_angle));
127  }
128 
129  return generateLadderGraphFromPoses(model, poses, dt);
130 }
131 
132 LadderGraph sampleSingleConfig(const descartes_core::RobotModel &model,
133  const std::vector <Eigen::Vector3d> &origins,
134  const Eigen::Matrix3d &orientation,
135  const double dt)
136 {
137  std::vector <Eigen::Affine3d> poses;
138 
139  for (const auto &o : origins)
140  {
141  poses.push_back(makePose(o, orientation));
142  }
143 
144  return generateLadderGraphFromPoses(model, poses, dt);
145 }
146 
147 LadderGraph sampleConstrainedPaths(const descartes_core::RobotModel &model,
148  ConstrainedSegment &segment)
149 {
150  // Determine the linear points
151  // TODO: should have a lower bound for discretization
152  // if sampled point num < threshold, discretize using threshold, otherwise use input linear_disc
153  auto points = discretizePositions(segment.start, segment.end, segment.linear_disc);
154 
155  // Compute the number of angle steps
156  static const auto min_angle = -M_PI;
157  static const auto max_angle = M_PI;
158  const auto n_angle_disc = std::lround((max_angle - min_angle) / segment.z_axis_disc);
159  const auto angle_step = (max_angle - min_angle) / n_angle_disc;
160 
161  // Compute the expected time step for each linear point
162  double traverse_length = (segment.end - segment.start).norm();
163  const auto dt = traverse_length / segment.linear_vel;
164 
165  LadderGraph graph(model.getDOF());
166 
167  // there will be a ladder rung for each point that we must solve
168  graph.resize(points.size());
169 
170  // We will build up our graph one configuration at a time: a configuration is a single orientation and z angle disc
171  for (const auto &orientation : segment.orientations)
172  {
173  std::vector <Eigen::Vector3d> process_pts = points;
174 
175  for (long i = 0; i < n_angle_disc; ++i)
176  {
177  const auto angle = angle_step * i;
178 
179  LadderGraph single_config_graph = sampleSingleConfig(model, process_pts, dt, orientation, angle);
180  concatenate(graph, single_config_graph);
181  }
182  }
183 
184  // TODO: should invoke fine resolution if any rung has no vertex
185 
186  return graph;
187 }
188 
189 // TODO:
190 void appendInTime(LadderGraph &current, const LadderGraph &next)
191 {
192  const auto ref_size = current.size();
193  const auto new_total_size = ref_size + next.size();
194 
195  // So step 1 is to literally add the two sets of joints and edges together to make
196  // one longer graph
197  current.resize(new_total_size);
198  for (std::size_t i = 0; i < next.size(); ++i)
199  {
200  current.getRung(ref_size + i) = next.getRung(i);
201  }
202 
203  // The second problem is that we now need to 'connect' the two graphs.
204  if (ref_size > 0 && next.size() > 0)
205  {
206  const auto dof = current.dof();
207  auto &a_rung = current.getRung(ref_size - 1);
208  auto &b_rung = current.getRung(ref_size);
209 
210  const auto n_start = a_rung.data.size() / dof;
211  const auto n_end = b_rung.data.size() / dof;
212 
213  descartes_planner::DefaultEdgesWithoutTime builder(n_start, n_end, dof);
214 
215  for (size_t k = 0; k < n_start; k++) // from rung
216  {
217  const auto start_index = k * dof;
218 
219  for (size_t j = 0; j < n_end; j++) // to rung
220  {
221  const auto end_index = j * dof;
222 
223  builder.consider(&a_rung.data[start_index], &b_rung.data[end_index], j);
224  }
225  builder.next(k);
226  }
227 
228  std::vector <descartes_planner::LadderGraph::EdgeList> edges = builder.result();
229 
230  if (!builder.hasEdges())
231  {
232  ROS_ERROR("[Descartes graph builder] No edges!!!");
233  }
234 
235  current.assignEdges(ref_size - 1, std::move(edges));
236  }
237 }
238 }
std::vector< Eigen::Vector3d > discretizePositions(const Eigen::Vector3d &start, const Eigen::Vector3d &stop, const double ds)
boost::function< double(const double *, const double *)> CostFunction
LadderGraph generateLadderGraphFromPoses(const descartes_core::RobotModel &model, const std::vector< Eigen::Affine3d > &ps, const double dt)
#define M_PI
std::vector< Eigen::Matrix3d > orientations
Eigen::Affine3d makePose(const Eigen::Vector3d &position, const Eigen::Matrix3d &orientation, const double z_axis_angle)
void appendInTime(LadderGraph &current, const LadderGraph &next)
LadderGraph sampleSingleConfig(const descartes_core::RobotModel &model, const std::vector< Eigen::Vector3d > &origins, const Eigen::Matrix3d &orientation, const double dt)
#define ROS_ERROR(...)
LadderGraph sampleConstrainedPaths(const descartes_core::RobotModel &model, ConstrainedSegment &segment)


choreo_descartes_planner
Author(s): Yijiang Huang , Jonathan Meyer
autogenerated on Thu Jul 18 2019 03:58:35