28 armarx::Vector3IBase
operator +(
const armarx::Vector3IBase& lhs,
const armarx::Vector3IBase& rhs)
30 return armarx::Vector3IBase {lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z};
67 s <<
"Invalid translation step size: " << step <<
" < 0.0";
69 throw armarx::InvalidArgumentException {
s.str()};
80 stepSizeDeg =
static_cast<int>(step /
M_PI * 180);
86 if (range.max < range.min)
89 s <<
"Invalid bounding range for x dimension: min = " << range.min <<
", max = " << range.max;
91 throw armarx::InvalidArgumentException {
s.str()};
94 xBoundingRange = range;
99 if (range.max < range.min)
102 s <<
"Invalid bounding range for y dimension: min = " << range.min <<
", max = " << range.max;
104 throw armarx::InvalidArgumentException {
s.str()};
107 yBoundingRange = range;
112 neighbourDeltas = neighbours;
117 rotationFactorForHeuristic = factor;
122 distanceFactorForHeuristic = factor;
128 return distanceFactorForHeuristic * std::hypot(delta(0), delta(1)) + rotationFactorForHeuristic *
std::abs(delta(2));
133 return distanceFactorForHeuristic * std::hypot(to.x - from.x, to.y - from.y) + rotationFactorForHeuristic *
std::abs(to.z - from.z);
147 if (!(isPositionValid(
Vector3 {from->x, from->y, from->z}) && isPositionValid(
Vector3 {to->x, to->y, to->z})))
149 return Vector3BaseList {};
156 ARMARX_VERBOSE <<
"Planning path from (" << from->x <<
", " << from->y <<
", " << from->z <<
") to (" << to->x <<
", " << to->y <<
", " << to->z <<
")";
158 auto toGlobal = [&](
const armarx::Vector3IBase & node)
162 from->x + node.x * tStepSize,
163 from->y + node.y * tStepSize,
164 from->z +
static_cast<float>(node.z*
M_PI / 180)
168 auto getNeighbours = [&](
const armarx::Vector3IBase & node)
170 armarx::Vector3IBaseList neighbours;
172 for (
const auto& delta : neighbourDeltas)
174 armarx::Vector3IBase neighbour {node.x + delta.x, node.y + delta.y,
175 (((node.z + delta.z * stepSizeDeg) % 360) + 360) % 360
179 if (globalNeighbour.x <= xBoundingRange.max &&
180 globalNeighbour.x >= xBoundingRange.min &&
181 globalNeighbour.y <= yBoundingRange.max &&
182 globalNeighbour.y >= yBoundingRange.min &&
183 isPositionValid(globalNeighbour))
185 neighbours.push_back(neighbour);
202 const armarx::Vector3IBase start
207 armarx::Vector3 fromToDelta {to->x - from->x, to->y - from->y, to->z - from->z};
209 armarx::Vector3IBase goal {
static_cast<int>(std::lround(fromToDelta.x / tStepSize)),
210 static_cast<int>(std::lround(fromToDelta.y / tStepSize)),
211 ((
static_cast<int>(fromToDelta.z /
M_PI * 180) % 360) + 360) % 360
215 int goalZMod = goal.z % stepSizeDeg;
216 goal.z = goal.z - goalZMod;
217 goal.z += ((goalZMod >= stepSizeDeg / 2) ? stepSizeDeg : 0);
220 assert(globalGoalPtr);
222 ::armarx::Vector3BaseList path {};
223 std::vector<armarx::Vector3IBase> openSet {};
224 std::vector<armarx::Vector3IBase> closedSet {};
226 openSet.push_back(start);
228 std::map<armarx::Vector3IBase, float> fScore;
229 std::map<armarx::Vector3IBase, float> gScore;
231 fScore[start] = gScore.at(start) + heuristic(
toGlobal(start), *globalGoalPtr);
233 std::map<armarx::Vector3IBase, armarx::Vector3IBase> cameFrom;
234 cameFrom[goal] = start;
241 while (!openSet.empty())
245 std::min_element(openSet.begin(), openSet.end(),
246 [&](
const armarx::Vector3IBase &
a,
const armarx::Vector3IBase & b)
248 return fScore.at(a) < fScore.at(b);
251 assert(currentIT != openSet.end());
252 const armarx::Vector3IBase current = *currentIT;
255 if ((current.x == goal.x) && (current.y == goal.y) && (current.z == goal.z))
259 armarx::Vector3IBase cameFromNode = goal;
261 while (cameFromNode != start)
263 armarx::Vector3BasePtr globalCameFromNodePtr = armarx::Vector3BasePtr {
new armarx::Vector3{
toGlobal(cameFromNode)}};
264 path.insert(path.begin(), globalCameFromNodePtr);
265 cameFromNode = cameFrom.at(cameFromNode);
268 path.insert(path.begin(), from);
272 openSet.erase(currentIT);
273 closedSet.push_back(current);
278 for (
const armarx::Vector3IBase& neighbour : getNeighbours(current))
280 if (std::find(closedSet.begin(), closedSet.end(), neighbour) != closedSet.end())
289 float tentativeGScore = gScore.at(current) + heuristic(current, neighbour);
290 bool notInOS = std::find(openSet.begin(), openSet.end(), neighbour) == openSet.end();
292 if (notInOS || tentativeGScore < gScore.at(neighbour))
294 cameFrom[neighbour] = current;
295 gScore[neighbour] = tentativeGScore;
297 fScore[neighbour] = tentativeGScore + heuristic(neighbour, goal);
303 openSet.push_back(neighbour);