SMACC2
Loading...
Searching...
No Matches
cb_yaw_scan.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
25CbYawScan::CbYawScan(float amplitude, float period, float baseHeading)
26: amplitude_(amplitude), period_(std::max(period, 0.1f)), baseHeading_(baseHeading)
27{
28}
29
31{
32 if (localPosition_ == nullptr || !localPosition_->isValid())
33 {
34 RCLCPP_ERROR(getLogger(), "CbYawScan: no valid local position at entry - posting failure");
35 this->postPx4Failure();
36 return;
37 }
38
42
43 if (std::isnan(baseHeading_))
44 {
46 }
48
49 // Peak yaw rate of the commanded sweep; PX4's autonomous yaw rate limit is
50 // ~0.8 rad/s by default and the flown sweep clips beyond it.
51 float peakYawRate = amplitude_ * 2.0f * static_cast<float>(M_PI) / period_;
52 if (peakYawRate > 0.8f)
53 {
54 RCLCPP_WARN(
55 getLogger(),
56 "CbYawScan: commanded peak yaw rate %.2f rad/s exceeds typical PX4 limits - the flown "
57 "sweep will clip",
58 peakYawRate);
59 }
60
61 elapsed_ = 0.0f;
62 lastUpdateTime_ = std::chrono::steady_clock::now();
63
64 RCLCPP_INFO(
65 getLogger(),
66 "CbYawScan: scanning around heading=%.2f rad A=%.2f rad T=%.2f s "
67 "(continuous - exits only on state change)",
69
71 active_ = true;
72}
73
75{
76 if (active_.exchange(false))
77 {
78 // Restore the base heading; the offboard keep-alive republishes this until
79 // the next state commands otherwise.
81 RCLCPP_INFO(getLogger(), "CbYawScan: exiting - restoring base heading %.2f rad", baseHeading_);
82 }
83}
84
86{
88
89 if (!active_)
90 {
91 return;
92 }
93
94 auto now = std::chrono::steady_clock::now();
95 double dt = std::chrono::duration<double>(now - lastUpdateTime_).count();
96 lastUpdateTime_ = now;
97
98 elapsed_ += static_cast<float>(dt);
99
100 float phase = 2.0f * static_cast<float>(M_PI) * elapsed_ / period_;
101 float yaw = wrapPi(baseHeading_ + amplitude_ * std::sin(phase));
102
104}
105
106} // namespace cl_px4_mr
std::chrono::steady_clock::time_point lastUpdateTime_
void onEntry() override
void update() override
void onExit() override
CbYawScan(float amplitude=0.6f, float period=6.0f, float baseHeading=std::numeric_limits< float >::quiet_NaN())
std::atomic< bool > active_
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)