40 const bool atXy = std::hypot(target.
x - current.
x, target.
y - current.
y) <= p.
tolerance;
41 if (atXy && std::fabs(current.
z - target.
z) <= p.
tolerance)
47 return {start, target};
53 const float cx = pick(p.
centerX, current.
x);
54 const float cy = pick(p.
centerY, current.
y);
56 const float r = std::max(p.
radius, 0.5f);
68 const int count = p.
count;
72 const float dx = current.
x - cx;
73 const float dy = current.
y - cy;
75 std::hypot(dx, dy) > 0.1f ? std::atan2(dy, dx) : (std::isnan(current.
yaw) ? 0.0f : current.
yaw);
77 std::vector<NedPoint> path;
78 path.reserve(
static_cast<size_t>(count * n + 1));
79 for (
int k = 0; k <= count * n; ++k)
81 const float theta = theta0 + sign * 2.0f *
static_cast<float>(M_PI) * k / n;
83 v.
x = cx + r * std::cos(theta);
84 v.y = cy + r * std::sin(theta);
86 v.yaw = p.
faceCenter ? std::atan2(cy - v.y, cx - v.x) : kNaN;
97 float ux = 0.0f, uy = 0.0f;
104 const float dx = endX - start.
x;
105 const float dy = endY - start.
y;
106 leg.
length = std::hypot(dx, dy);
120 const float endX = pick(p.
endX, current.
x);
121 const float endY = pick(p.
endY, current.
y);
123 const float lambda = std::max(p.
wavelength, 0.1f);
125 const Leg leg = legFrom(current, endX, endY);
127 std::vector<NedPoint> path;
128 if (leg.length <= 1e-3f)
130 path.push_back(
NedPoint{endX, endY, zBase, kNaN});
134 const int n =
static_cast<int>(std::floor(leg.length / spacing));
135 path.reserve(
static_cast<size_t>(n + 2));
136 for (
int k = 0; k < n; ++k)
138 const float s = k * spacing;
140 v.
x = current.
x + s * leg.ux;
141 v.
y = current.
y + s * leg.uy;
142 v.
z = zBase - p.
amplitude * std::sin(2.0f *
static_cast<float>(M_PI) * s / lambda);
145 path.push_back(
NedPoint{endX, endY, zBase, kNaN});
152 const float endX = pick(p.
endX, current.
x);
153 const float endY = pick(p.
endY, current.
y);
155 const float lambda = std::max(p.
wavelength, 0.1f);
157 const Leg leg = legFrom(current, endX, endY);
159 std::vector<NedPoint> path;
160 if (leg.length <= 1e-3f)
162 path.push_back(
NedPoint{endX, endY, z, kNaN});
167 const float nx = leg.uy;
168 const float ny = -leg.ux;
170 const int n =
static_cast<int>(std::floor(leg.length / spacing));
171 path.reserve(
static_cast<size_t>(n + 2));
172 for (
int k = 0; k < n; ++k)
174 const float s = k * spacing;
175 const float offset = p.
amplitude * std::sin(2.0f *
static_cast<float>(M_PI) * s / lambda);
177 v.
x = current.
x + s * leg.ux + offset * nx;
178 v.
y = current.
y + s * leg.uy + offset * ny;
182 path.push_back(
NedPoint{endX, endY, z, kNaN});
189 const float ox = pick(p.
originX, current.
x);
190 const float oy = pick(p.
originY, current.
y);
192 const float spacing = std::max(p.
spacing, 0.5f);
196 std::vector<NedPoint> path;
197 path.reserve(
static_cast<size_t>(std::max(p.
numLegs, 0) + 1));
204 for (
int i = 0; i < p.
numLegs; ++i)
206 const float len = spacing *
static_cast<float>(i / 2 + 1);
211 v.
x += len * std::cos(heading);
212 v.
y += len * std::sin(heading);
214 heading += sign *
static_cast<float>(M_PI) / 2.0f;
221 const float spacing = std::max(p.
spacing, 0.5f);
223 for (
int i = 0; i < p.
numLegs; ++i)
225 const float len = spacing *
static_cast<float>(i / 2 + 1);
238 const float cx = pick(p.
centerX, current.
x);
239 const float cy = pick(p.
centerY, current.
y);
241 const float spacing = std::max(p.
spacing, 0.5f);
242 const float a = spacing / (2.0f *
static_cast<float>(M_PI));
243 const float rStart = std::max(p.
startRadius, 0.0f);
244 const float rEnd = std::max(p.
endRadius, rStart);
249 const float dx = current.
x - cx;
250 const float dy = current.
y - cy;
252 std::hypot(dx, dy) > 0.1f ? std::atan2(dy, dx) : (std::isnan(current.
yaw) ? 0.0f : current.
yaw);
254 const float thetaStart = rStart / a;
255 const float thetaEnd = rEnd / a;
257 std::vector<NedPoint> path;
258 float theta = thetaStart;
259 while (theta < thetaEnd)
261 const float r = a * theta;
263 v.
x = cx + r * std::cos(theta0 + sign * theta);
264 v.
y = cy + r * std::sin(theta0 + sign * theta);
267 theta += ds / std::max(r, a);
270 last.
x = cx + rEnd * std::cos(theta0 + sign * thetaEnd);
271 last.
y = cy + rEnd * std::sin(theta0 + sign * thetaEnd);
273 path.push_back(last);
277 std::reverse(path.begin(), path.end());
285 const float rStart = std::max(p.
startRadius, 0.0f);
286 const float rEnd = std::max(p.
endRadius, rStart);
287 const float spacing = std::max(p.
spacing, 0.5f);
288 return static_cast<float>(M_PI) * (rEnd * rEnd - rStart * rStart) / spacing;
293 const float spacing = std::max(p.
laneSpacing, 0.5f);
294 return std::max(1,
static_cast<int>(std::floor(std::max(p.
width, 0.0f) / spacing + 1e-3f)) + 1);
307 const float heading = pick(p.
laneHeading, std::isnan(current.
yaw) ? 0.0f : current.
yaw);
308 const float ux = std::cos(heading);
309 const float uy = std::sin(heading);
312 const float nx = -uy * side;
313 const float ny = ux * side;
316 const float spacing = std::max(p.
laneSpacing, 0.5f);
317 const float length = std::max(p.
laneLength, 0.0f);
318 const float coveredWidth = (lanes - 1) * spacing;
320 float ox = pick(p.
originX, current.
x);
321 float oy = pick(p.
originY, current.
y);
324 ox -= 0.5f * length * ux + 0.5f * coveredWidth * nx;
325 oy -= 0.5f * length * uy + 0.5f * coveredWidth * ny;
328 std::vector<NedPoint> path;
329 path.reserve(
static_cast<size_t>(2 * lanes));
330 for (
int i = 0; i < lanes; ++i)
333 a.
x = ox + i * spacing * nx;
334 a.
y = oy + i * spacing * ny;
337 b.
x = a.
x + length * ux;
338 b.
y = a.
y + length * uy;
381 const NedPoint & joint = path.back();
382 std::vector<NedPoint> best;
383 float bestDist = std::numeric_limits<float>::max();
384 for (
int variant = 0; variant < 4; ++variant)
390 first.
laneHeading + ((variant & 1) ? -1.0f : 1.0f) *
static_cast<float>(M_PI) / 2.0f;
393 if (candidate.empty())
397 const float d =
nedDistance(joint, candidate.front());
401 best = std::move(candidate);
404 path.insert(path.end(), best.begin(), best.end());
410 return 9.0f * std::max(p.
radius, 1.0f) *
static_cast<float>(std::max(p.
cycles, 1));
416 const float dx = pick(p.
datumX, current.
x);
417 const float dy = pick(p.
datumY, current.
y);
419 const float r = std::max(p.
radius, 1.0f);
422 const int cycles = std::max(p.
cycles, 1);
426 static const int kSteps[9] = {0, 1, 2, 2, 0, 1, 1, 2, 0};
427 const float third = 2.0f *
static_cast<float>(M_PI) / 3.0f;
429 std::vector<NedPoint> path;
430 path.reserve(
static_cast<size_t>(9 * cycles + 1));
437 for (
int c = 0; c < cycles; ++c)
439 const float base = h0 + sign * p.
reorientation *
static_cast<float>(c);
440 for (
int leg = 0; leg < 9; ++leg)
442 const float heading = base + sign * third *
static_cast<float>(kSteps[leg]);
443 v.
x += r * std::cos(heading);
444 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 > 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)
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