SMACC2
Loading...
Searching...
No Matches
cb_spiral_pattern.cpp
Go to the documentation of this file.
1// Copyright 2025 Robosoft Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
18
19namespace cl_px4_mr
20{
21
23 float centerX, float centerY, float altitude, float maxRadius, float spacing, float speed)
24: centerX_(centerX),
25 centerY_(centerY),
26 altitude_(altitude),
27 maxRadius_(maxRadius),
28 spacing_(spacing),
29 speed_(speed)
30{
31}
32
34{
35 theta_ = 0.0f;
36 lastUpdateTime_ = std::chrono::steady_clock::now();
37
38 // Initial position is the spiral center
39 float z = -altitude_; // NED: up is negative
40
41 RCLCPP_INFO(
42 getLogger(),
43 "CbSpiralPattern: starting spiral center=[%.2f, %.2f] alt=%.2f maxR=%.2f spacing=%.2f "
44 "speed=%.2f",
46
48}
49
51
53{
55
56 auto now = std::chrono::steady_clock::now();
57 double dt = std::chrono::duration<double>(now - lastUpdateTime_).count();
58 lastUpdateTime_ = now;
59
60 // Archimedean spiral: r(theta) = a * theta
61 // where a = spacing / (2*PI) so each revolution adds 'spacing' meters of radius
62 float a = spacing_ / (2.0f * M_PI);
63
64 // Current radius
65 float r = a * theta_;
66
67 // Adaptive angular velocity to maintain constant linear speed
68 // Arc-length speed: ds/dt = sqrt(r^2 + a^2) * dtheta/dt
69 // Solving for dtheta/dt: omega = speed / sqrt(r^2 + a^2)
70 float omega = speed_ / std::sqrt(r * r + a * a);
71
72 // Advance angle
73 theta_ += omega * dt;
74
75 // Compute new position
76 float r_new = a * theta_;
77 float x = centerX_ + r_new * std::cos(theta_);
78 float y = centerY_ + r_new * std::sin(theta_);
79 float z = -altitude_; // NED
80
81 // Yaw: face direction of travel (derivatives of Archimedean spiral)
82 // dx/dtheta = a*cos(theta) - r*sin(theta)
83 // dy/dtheta = a*sin(theta) + r*cos(theta)
84 float dxdt = a * std::cos(theta_) - r_new * std::sin(theta_);
85 float dydt = a * std::sin(theta_) + r_new * std::cos(theta_);
86 float yaw = std::atan2(dydt, dxdt);
87
89
90 // Check completion
91 if (r_new >= maxRadius_)
92 {
93 RCLCPP_INFO(
94 getLogger(), "CbSpiralPattern: max radius %.2f reached (r=%.2f) - posting success",
95 maxRadius_, r_new);
96 this->postPx4Success();
97 }
98}
99
100} // namespace cl_px4_mr
std::chrono::steady_clock::time_point lastUpdateTime_
CbSpiralPattern(float centerX, float centerY, float altitude, float maxRadius=20.0f, float spacing=3.0f, float speed=2.0f)
void setPositionNED(float x, float y, float z, float yaw=std::numeric_limits< float >::quiet_NaN())
virtual rclcpp::Logger getLogger() const