41 const bool atXy = std::hypot(target.
x - current.
x, target.
y - current.
y) <= p.
tolerance;
42 if (atXy && std::fabs(current.
z - target.
z) <= p.
tolerance)
48 return {start, target};
54 const float cx = pick(p.
centerX, current.
x);
55 const float cy = pick(p.
centerY, current.
y);
57 const float r = std::max(p.
radius, 0.5f);
69 const int count = p.
count;
73 const float dx = current.
x - cx;
74 const float dy = current.
y - cy;
76 std::hypot(dx, dy) > 0.1f ? std::atan2(dy, dx) : (std::isnan(current.
yaw) ? 0.0f : current.
yaw);
78 std::vector<NedPoint> path;
79 path.reserve(
static_cast<size_t>(count * n + 1));
80 for (
int k = 0; k <= count * n; ++k)
82 const float theta = theta0 + sign * 2.0f *
static_cast<float>(M_PI) * k / n;
84 v.
x = cx + r * std::cos(theta);
85 v.y = cy + r * std::sin(theta);
87 v.yaw = p.
faceCenter ? std::atan2(cy - v.y, cx - v.x) : kNaN;
98 float ux = 0.0f, uy = 0.0f;
105 const float dx = endX - start.
x;
106 const float dy = endY - start.
y;
107 leg.
length = std::hypot(dx, dy);
121 const float cx = pick(p.
centerX, current.
x);
122 const float cy = pick(p.
centerY, current.
y);
124 const float a = std::max(p.
size, 0.5f);
137 const float heading =
139 const float ch = std::cos(heading);
140 const float sh = std::sin(heading);
143 std::vector<NedPoint> loop;
144 loop.reserve(
static_cast<size_t>(n));
145 for (
int k = 0; k < n; ++k)
147 const float t = sign * 2.0f *
static_cast<float>(M_PI) * k / n;
148 const float st = std::sin(t);
149 const float ct = std::cos(t);
150 const float denom = 1.0f + st * st;
151 const float lx = a * ct / denom;
152 const float ly = a * st * ct / denom;
154 v.
x = cx + lx * ch - ly * sh;
155 v.
y = cy + lx * sh + ly * ch;
163 float best = std::numeric_limits<float>::infinity();
164 for (
int k = 0; k < n; ++k)
166 const float d = std::hypot(loop[k].x - current.
x, loop[k].y - current.
y);
174 std::vector<NedPoint> path;
175 path.reserve(
static_cast<size_t>(p.
count * n + 1));
176 for (
int k = 0; k <= p.
count * n; ++k)
178 path.push_back(loop[
static_cast<size_t>((start + k) % n)]);
186 return 5.2441f * std::max(p.
size, 0.5f) * std::max(p.
count, 0);
192 const float endX = pick(p.
endX, current.
x);
193 const float endY = pick(p.
endY, current.
y);
195 const float lambda = std::max(p.
wavelength, 0.1f);
197 const Leg leg = legFrom(current, endX, endY);
199 std::vector<NedPoint> path;
200 if (leg.length <= 1e-3f)
202 path.push_back(
NedPoint{endX, endY, zBase, kNaN});
206 const int n =
static_cast<int>(std::floor(leg.length / spacing));
207 path.reserve(
static_cast<size_t>(n + 2));
208 for (
int k = 0; k < n; ++k)
210 const float s = k * spacing;
212 v.
x = current.
x + s * leg.ux;
213 v.
y = current.
y + s * leg.uy;
214 v.
z = zBase - p.
amplitude * std::sin(2.0f *
static_cast<float>(M_PI) * s / lambda);
217 path.push_back(
NedPoint{endX, endY, zBase, kNaN});
224 const float endX = pick(p.
endX, current.
x);
225 const float endY = pick(p.
endY, current.
y);
227 const float lambda = std::max(p.
wavelength, 0.1f);
229 const Leg leg = legFrom(current, endX, endY);
231 std::vector<NedPoint> path;
232 if (leg.length <= 1e-3f)
234 path.push_back(
NedPoint{endX, endY, z, kNaN});
239 const float nx = leg.uy;
240 const float ny = -leg.ux;
242 const int n =
static_cast<int>(std::floor(leg.length / spacing));
243 path.reserve(
static_cast<size_t>(n + 2));
244 for (
int k = 0; k < n; ++k)
246 const float s = k * spacing;
247 const float offset = p.
amplitude * std::sin(2.0f *
static_cast<float>(M_PI) * s / lambda);
249 v.
x = current.
x + s * leg.ux + offset * nx;
250 v.
y = current.
y + s * leg.uy + offset * ny;
254 path.push_back(
NedPoint{endX, endY, z, kNaN});
261 const float ox = pick(p.
originX, current.
x);
262 const float oy = pick(p.
originY, current.
y);
264 const float spacing = std::max(p.
spacing, 0.5f);
268 std::vector<NedPoint> path;
269 path.reserve(
static_cast<size_t>(std::max(p.
numLegs, 0) + 1));
276 for (
int i = 0; i < p.
numLegs; ++i)
278 const float len = spacing *
static_cast<float>(i / 2 + 1);
283 v.
x += len * std::cos(heading);
284 v.
y += len * std::sin(heading);
286 heading += sign *
static_cast<float>(M_PI) / 2.0f;
293 const float spacing = std::max(p.
spacing, 0.5f);
295 for (
int i = 0; i < p.
numLegs; ++i)
297 const float len = spacing *
static_cast<float>(i / 2 + 1);
310 const float cx = pick(p.
centerX, current.
x);
311 const float cy = pick(p.
centerY, current.
y);
313 const float spacing = std::max(p.
spacing, 0.5f);
314 const float a = spacing / (2.0f *
static_cast<float>(M_PI));
315 const float rStart = std::max(p.
startRadius, 0.0f);
316 const float rEnd = std::max(p.
endRadius, rStart);
321 const float dx = current.
x - cx;
322 const float dy = current.
y - cy;
324 std::hypot(dx, dy) > 0.1f ? std::atan2(dy, dx) : (std::isnan(current.
yaw) ? 0.0f : current.
yaw);
326 const float thetaStart = rStart / a;
327 const float thetaEnd = rEnd / a;
329 std::vector<NedPoint> path;
330 float theta = thetaStart;
331 while (theta < thetaEnd)
333 const float r = a * theta;
335 v.
x = cx + r * std::cos(theta0 + sign * theta);
336 v.
y = cy + r * std::sin(theta0 + sign * theta);
339 theta += ds / std::max(r, a);
342 last.
x = cx + rEnd * std::cos(theta0 + sign * thetaEnd);
343 last.
y = cy + rEnd * std::sin(theta0 + sign * thetaEnd);
345 path.push_back(last);
349 std::reverse(path.begin(), path.end());
357 const float rStart = std::max(p.
startRadius, 0.0f);
358 const float rEnd = std::max(p.
endRadius, rStart);
359 const float spacing = std::max(p.
spacing, 0.5f);
360 return static_cast<float>(M_PI) * (rEnd * rEnd - rStart * rStart) / spacing;
365 const float spacing = std::max(p.
laneSpacing, 0.5f);
366 return std::max(1,
static_cast<int>(std::floor(std::max(p.
width, 0.0f) / spacing + 1e-3f)) + 1);
379 const float heading = pick(p.
laneHeading, std::isnan(current.
yaw) ? 0.0f : current.
yaw);
380 const float ux = std::cos(heading);
381 const float uy = std::sin(heading);
384 const float nx = -uy * side;
385 const float ny = ux * side;
388 const float spacing = std::max(p.
laneSpacing, 0.5f);
389 const float length = std::max(p.
laneLength, 0.0f);
390 const float coveredWidth = (lanes - 1) * spacing;
392 float ox = pick(p.
originX, current.
x);
393 float oy = pick(p.
originY, current.
y);
396 ox -= 0.5f * length * ux + 0.5f * coveredWidth * nx;
397 oy -= 0.5f * length * uy + 0.5f * coveredWidth * ny;
400 std::vector<NedPoint> path;
401 path.reserve(
static_cast<size_t>(2 * lanes));
402 for (
int i = 0; i < lanes; ++i)
405 a.
x = ox + i * spacing * nx;
406 a.
y = oy + i * spacing * ny;
409 b.
x = a.
x + length * ux;
410 b.
y = a.
y + length * uy;
453 const NedPoint & joint = path.back();
454 std::vector<NedPoint> best;
455 float bestDist = std::numeric_limits<float>::max();
456 for (
int variant = 0; variant < 4; ++variant)
462 first.
laneHeading + ((variant & 1) ? -1.0f : 1.0f) *
static_cast<float>(M_PI) / 2.0f;
465 if (candidate.empty())
469 const float d =
nedDistance(joint, candidate.front());
473 best = std::move(candidate);
476 path.insert(path.end(), best.begin(), best.end());
482 return 9.0f * std::max(p.
radius, 1.0f) *
static_cast<float>(std::max(p.
cycles, 1));
488 const float dx = pick(p.
datumX, current.
x);
489 const float dy = pick(p.
datumY, current.
y);
491 const float r = std::max(p.
radius, 1.0f);
494 const int cycles = std::max(p.
cycles, 1);
498 static const int kSteps[9] = {0, 1, 2, 2, 0, 1, 1, 2, 0};
499 const float third = 2.0f *
static_cast<float>(M_PI) / 3.0f;
501 std::vector<NedPoint> path;
502 path.reserve(
static_cast<size_t>(9 * cycles + 1));
509 for (
int c = 0; c < cycles; ++c)
511 const float base = h0 + sign * p.
reorientation *
static_cast<float>(c);
512 for (
int leg = 0; leg < 9; ++leg)
514 const float heading = base + sign * third *
static_cast<float>(kSteps[leg]);
515 v.
x += r * std::cos(heading);
516 v.
y += r * std::sin(heading);
Leg legFrom(const NedPoint &start, float endX, float endY)
float altitudeToZ(float altitudeAgl, float currentZ)
float pick(float param, float fallback)
std::vector< NedPoint > generateFlightPatternSpiral(const FlightPatternSpiralParams &p, const NedPoint ¤t)
std::vector< NedPoint > generateFlightPatternFigureEight(const FlightPatternFigureEightParams &p, const NedPoint ¤t)
std::vector< NedPoint > generateFlightPatternSineWaveVertical(const FlightPatternSineWaveVerticalParams &p, const NedPoint ¤t)
std::vector< NedPoint > generateFlightPatternVSSearch(const FlightPatternVSSearchParams &p, const NedPoint ¤t)
std::vector< NedPoint > generateFlightPatternSquareSpiral(const FlightPatternSquareSpiralParams &p, const NedPoint ¤t)
std::vector< NedPoint > generateFlightPatternLoiter(const FlightPatternLoiterParams &p, const NedPoint ¤t)
float flightPatternSquareSpiralLength(const FlightPatternSquareSpiralParams &p)
float nedDistance(const NedPoint &a, const NedPoint &b)
std::vector< NedPoint > generateFlightPatternSineWaveHorizontal(const FlightPatternSineWaveHorizontalParams &p, const NedPoint ¤t)
float flightPatternGridPatternLength(const FlightPatternGridPatternParams &p)
float flightPatternFigureEightLength(const FlightPatternFigureEightParams &p)
std::vector< NedPoint > generateFlightPatternLawnmower(const FlightPatternLawnmowerParams &p, const NedPoint ¤t)
int flightPatternLawnmowerLaneCount(const FlightPatternLawnmowerParams &p)
float flightPatternVSSearchLength(const FlightPatternVSSearchParams &p)
std::vector< NedPoint > generateFlightPatternGridPattern(const FlightPatternGridPatternParams &p, const NedPoint ¤t)
float flightPatternSpiralLength(const FlightPatternSpiralParams &p)
float flightPatternLawnmowerLength(const FlightPatternLawnmowerParams &p)
std::vector< NedPoint > generateFlightPatternAscend(const FlightPatternAscendParams &p, const NedPoint ¤t)
FlightPatternLawnmowerParams base