SMACC2
Loading...
Searching...
No Matches
cb_sine_altitude_cruise.cpp
Go to the documentation of this file.
1// Copyright 2026 RobosoftAI 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
19
20#include <algorithm>
21
22namespace cl_px4_mr
23{
24
26 float groundSpeed, float amplitude, float wavelength, float heading)
27: groundSpeed_(groundSpeed),
28 amplitude_(amplitude),
29 wavelength_(std::max(wavelength, 0.1f)),
30 heading_(heading)
31{
32}
33
35{
36 if (localPosition_ == nullptr || !localPosition_->isValid())
37 {
38 RCLCPP_ERROR(
39 getLogger(), "CbSineAltitudeCruise: no valid local position at entry - posting failure");
40 this->postPx4Failure();
41 return;
42 }
43
47
48 if (std::isnan(heading_))
49 {
51 }
53
54 // Peak vertical speed of the commanded path; PX4 defaults limit climb/descent
55 // to ~2-3 m/s and the flown sine flattens beyond that.
56 float peakVerticalSpeed =
57 amplitude_ * 2.0f * static_cast<float>(M_PI) * groundSpeed_ / wavelength_;
58 if (peakVerticalSpeed > 2.0f)
59 {
60 RCLCPP_WARN(
61 getLogger(),
62 "CbSineAltitudeCruise: commanded peak vertical speed %.2f m/s exceeds typical PX4 limits - "
63 "the flown path will flatten",
64 peakVerticalSpeed);
65 }
66
67 arcLength_ = 0.0f;
70 lastUpdateTime_ = std::chrono::steady_clock::now();
71
72 RCLCPP_INFO(
73 getLogger(),
74 "CbSineAltitudeCruise: cruising heading=%.2f rad v=%.2f m/s A=%.2f m lambda=%.2f m "
75 "(continuous - exits only on state change)",
77
79 active_ = true;
80}
81
83{
84 if (active_.exchange(false))
85 {
86 // Settle at the entry altitude at the last commanded ground position; the
87 // offboard keep-alive republishes this until the next state commands otherwise.
89 RCLCPP_INFO(
90 getLogger(), "CbSineAltitudeCruise: exiting - settling at base altitude (NED z=%.2f)",
91 baseZ_);
92 }
93}
94
96{
98
99 if (!active_)
100 {
101 return;
102 }
103
104 auto now = std::chrono::steady_clock::now();
105 double dt = std::chrono::duration<double>(now - lastUpdateTime_).count();
106 lastUpdateTime_ = now;
107
108 arcLength_ += groundSpeed_ * static_cast<float>(dt);
109
110 float x = startX_ + arcLength_ * std::cos(heading_);
111 float y = startY_ + arcLength_ * std::sin(heading_);
112 float phase = 2.0f * static_cast<float>(M_PI) * arcLength_ / wavelength_;
113 float z = baseZ_ - amplitude_ * std::sin(phase); // NED: up is negative
114
115 lastCmdX_ = x;
116 lastCmdY_ = y;
118}
119
120} // namespace cl_px4_mr
CbSineAltitudeCruise(float groundSpeed=2.0f, float amplitude=1.5f, float wavelength=20.0f, float heading=std::numeric_limits< float >::quiet_NaN())
std::chrono::steady_clock::time_point lastUpdateTime_
void setPositionNED(float x, float y, float z, float yaw=std::numeric_limits< float >::quiet_NaN())
virtual rclcpp::Logger getLogger() const
float wrapPi(float angle)