SMACC2
Loading...
Searching...
No Matches
cl_px4_mr::CpTunnelCentering Class Reference

#include <cp_tunnel_centering.hpp>

Inheritance diagram for cl_px4_mr::CpTunnelCentering:
Inheritance graph
Collaboration diagram for cl_px4_mr::CpTunnelCentering:
Collaboration graph

Public Member Functions

 CpTunnelCentering (TunnelCenteringParams params={})
 
virtual ~CpTunnelCentering ()
 
void onInitialize () override
 
float lateralOffsetM () const
 
float verticalOffsetM () const
 
bool valid () const
 
float leftWallM () const
 
float rightWallM () const
 
float floorM () const
 
float ceilingM () const
 
const TunnelCenteringParams & params () const
 
- Public Member Functions inherited from smacc2::ISmaccComponent
 ISmaccComponent ()
 
virtual ~ISmaccComponent ()
 
virtual std::string getName () const
 

Private Member Functions

void onCloud (const sensor_msgs::msg::PointCloud2 &msg)
 
void onAttitude (const px4_msgs::msg::VehicleAttitude::SharedPtr msg)
 

Private Attributes

TunnelCenteringParams params_
 
smacc2::client_core_components::CpTopicSubscriber< sensor_msgs::msg::PointCloud2 > * subscriber_
 
rclcpp::Subscription< px4_msgs::msg::VehicleAttitude >::SharedPtr attitudeSub_
 
std::mutex attitudeMutex_
 
std::array< float, 4 > attitudeQ_ {{1.0f, 0.0f, 0.0f, 0.0f}}
 
bool haveAttitude_ = false
 
std::atomic< float > lateral_ {0.0f}
 
std::atomic< float > vertical_ {0.0f}
 
std::atomic< float > left_ {0.0f}
 
std::atomic< float > right_ {0.0f}
 
std::atomic< float > floor_ {0.0f}
 
std::atomic< float > ceiling_ {0.0f}
 
std::atomic< int64_t > lastCloudNs_ {0}
 
std::chrono::steady_clock::time_point lastLog_
 

Additional Inherited Members

- Protected Member Functions inherited from smacc2::ISmaccComponent
template<typename TOrthogonal , typename TClient >
void onComponentInitialization ()
 
template<typename EventType >
void postEvent (const EventType &ev)
 
template<typename EventType >
void postEvent ()
 
template<typename TOrthogonal , typename TSourceObject >
void onStateOrthogonalAllocation ()
 
template<typename TComponent >
void requiresComponent (TComponent *&requiredComponentStorage, ComponentRequirement requirementType=ComponentRequirement::SOFT)
 
template<typename TComponent >
void requiresComponent (std::string name, TComponent *&requiredComponentStorage, ComponentRequirement requirementType=ComponentRequirement::SOFT)
 
template<typename TClient >
void requiresClient (TClient *&requiredClientStorage)
 
template<typename SmaccComponentType , typename TOrthogonal , typename TClient , typename... TArgs>
SmaccComponentType * createSiblingComponent (TArgs... targs)
 
template<typename SmaccComponentType , typename TOrthogonal , typename TClient , typename... TArgs>
SmaccComponentType * createSiblingNamedComponent (std::string name, TArgs... targs)
 
rclcpp::Node::SharedPtr getNode ()
 
rclcpp::Logger getLogger () const
 
ISmaccStateMachine * getStateMachine ()
 
- Protected Attributes inherited from smacc2::ISmaccComponent
ISmaccStateMachine * stateMachine_
 
ISmaccClient * owner_
 

Detailed Description

Definition at line 90 of file cp_tunnel_centering.hpp.

Constructor & Destructor Documentation

◆ CpTunnelCentering()

cl_px4_mr::CpTunnelCentering::CpTunnelCentering ( TunnelCenteringParams params = {})
explicit

Definition at line 57 of file cp_tunnel_centering.cpp.

57: params_(params) {}
const TunnelCenteringParams & params() const

◆ ~CpTunnelCentering()

cl_px4_mr::CpTunnelCentering::~CpTunnelCentering ( )
virtual

Definition at line 59 of file cp_tunnel_centering.cpp.

59{}

Member Function Documentation

◆ ceilingM()

float cl_px4_mr::CpTunnelCentering::ceilingM ( ) const
inline

Definition at line 108 of file cp_tunnel_centering.hpp.

108{ return ceiling_.load(); }

References ceiling_.

◆ floorM()

float cl_px4_mr::CpTunnelCentering::floorM ( ) const
inline

Definition at line 107 of file cp_tunnel_centering.hpp.

107{ return floor_.load(); }

References floor_.

◆ lateralOffsetM()

float cl_px4_mr::CpTunnelCentering::lateralOffsetM ( ) const
inline

Definition at line 99 of file cp_tunnel_centering.hpp.

99{ return lateral_.load(); }

References lateral_.

Referenced by cl_px4_mr::CbPx4PathFollowerBase::applyCentering().

Here is the caller graph for this function:

◆ leftWallM()

float cl_px4_mr::CpTunnelCentering::leftWallM ( ) const
inline

Definition at line 105 of file cp_tunnel_centering.hpp.

105{ return left_.load(); }

References left_.

◆ onAttitude()

void cl_px4_mr::CpTunnelCentering::onAttitude ( const px4_msgs::msg::VehicleAttitude::SharedPtr msg)
private

Definition at line 94 of file cp_tunnel_centering.cpp.

95{
96 std::lock_guard<std::mutex> lock(attitudeMutex_);
97 attitudeQ_ = {msg->q[0], msg->q[1], msg->q[2], msg->q[3]};
98 haveAttitude_ = true;
99}

References attitudeMutex_, attitudeQ_, and haveAttitude_.

Referenced by onInitialize().

Here is the caller graph for this function:

◆ onCloud()

void cl_px4_mr::CpTunnelCentering::onCloud ( const sensor_msgs::msg::PointCloud2 & msg)
private

Definition at line 101 of file cp_tunnel_centering.cpp.

102{
103 std::array<float, 9> r{};
104 bool level = false;
106 {
107 std::array<float, 4> q;
108 {
109 std::lock_guard<std::mutex> lock(attitudeMutex_);
110 level = haveAttitude_;
111 q = attitudeQ_;
112 }
113 if (level)
114 {
116 }
117 }
118
119 std::vector<float> leftY, rightY, floorZ, ceilZ;
120 leftY.reserve(512);
121 rightY.reserve(512);
122 floorZ.reserve(512);
123 ceilZ.reserve(512);
124
125 const float minRangeSq = params_.minRangeM * params_.minRangeM;
126 sensor_msgs::PointCloud2ConstIterator<float> ix(msg, "x");
127 sensor_msgs::PointCloud2ConstIterator<float> iy(msg, "y");
128 sensor_msgs::PointCloud2ConstIterator<float> iz(msg, "z");
129 for (; ix != ix.end(); ++ix, ++iy, ++iz)
130 {
131 float x = *ix;
132 float y = *iy;
133 float z = *iz;
134 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(z))
135 {
136 continue;
137 }
138 if (x * x + y * y + z * z < minRangeSq)
139 {
140 continue; // own airframe
141 }
142 if (level)
143 {
144 const float lx = r[0] * x + r[1] * y + r[2] * z;
145 const float ly = r[3] * x + r[4] * y + r[5] * z;
146 const float lz = r[6] * x + r[7] * y + r[8] * z;
147 x = lx;
148 y = ly;
149 z = lz;
150 }
151 if (x < -params_.floorLookBackM || x > params_.lookAheadMaxM)
152 {
153 continue;
154 }
155 const bool ahead = x >= params_.lookAheadMinM;
156 // walls: the band at flight height, in the slab ahead
157 if (
158 ahead && std::fabs(z) <= params_.wallBandHalfHeightM &&
159 std::fabs(y) <= params_.lateralSearchM)
160 {
161 if (y > 0.0f)
162 {
163 leftY.push_back(y);
164 }
165 else if (y < 0.0f)
166 {
167 rightY.push_back(-y);
168 }
169 }
170 // floor / ceiling: the column along the heading, EXCLUDING the wall band -
171 // rock beside the vehicle at sensor height is a wall (lateral channel), not
172 // a floor 0.1 m below it (run 22: an arch wall read as "floor 0.1" forced a
173 // 1 m climb into the ceiling)
174 if (
175 std::fabs(y) <= params_.columnHalfWidthM && std::fabs(z) > params_.wallBandHalfHeightM &&
176 std::fabs(z) <= params_.verticalSearchM)
177 {
178 if (z < 0.0f)
179 {
180 floorZ.push_back(-z);
181 }
182 else
183 {
184 ceilZ.push_back(z);
185 }
186 }
187 }
188
189 // nearest surfaces, robust to a few stray returns
190 const size_t kw = static_cast<size_t>(std::max(params_.minWallPoints, 1));
191 const size_t kf = static_cast<size_t>(std::max(params_.minFloorPoints, 1));
192 const float left = kthSmallest(leftY, kw);
193 const float right = kthSmallest(rightY, kw);
194 const float floorD = kthSmallest(floorZ, kf);
195 const float ceilD = kthSmallest(ceilZ, kf);
196
197 // lateral: toward the midpoint between the walls; needs both, fades when far
198 float lateral = 0.0f;
199 if (std::isfinite(left) && std::isfinite(right))
200 {
201 lateral = 0.5f * (left - right); // > 0: more room on the left -> move left
202 const float nearer = std::min(left, right);
203 if (nearer > params_.wallFadeM)
204 {
205 lateral = 0.0f;
206 }
207 else if (nearer > 0.5f * params_.wallFadeM)
208 {
209 lateral *= (params_.wallFadeM - nearer) / (0.5f * params_.wallFadeM);
210 }
211 }
212 lateral = std::clamp(lateral, -params_.maxLateralM, params_.maxLateralM);
213
214 // vertical: hold the floor clearance, but stay below the ceiling
215 float vertical = 0.0f;
216 if (std::isfinite(floorD))
217 {
218 vertical = params_.floorClearanceM - floorD; // > 0: climb
219 }
220 if (std::isfinite(ceilD))
221 {
222 vertical = std::min(vertical, ceilD - params_.ceilingClearanceM);
223 }
224 if (std::isfinite(floorD))
225 {
226 // never below the minimum floor clearance, even when the overhead reading
227 // (possibly rising terrain ahead) asks for it
228 vertical = std::max(vertical, params_.minFloorClearanceM - floorD);
229 }
230 vertical = std::clamp(vertical, -params_.maxVerticalM, params_.maxVerticalM);
231
232 const float a = std::clamp(params_.smoothing, 0.0f, 0.95f);
233 const bool first = lastCloudNs_.load() == 0;
234 lateral_ = first ? lateral : a * lateral_.load() + (1.0f - a) * lateral;
235 vertical_ = first ? vertical : a * vertical_.load() + (1.0f - a) * vertical;
236 left_ = left;
237 right_ = right;
238 floor_ = floorD;
239 ceiling_ = ceilD;
241
242 const auto now = std::chrono::steady_clock::now();
243 if (std::chrono::duration<double>(now - lastLog_).count() >= 2.0)
244 {
245 lastLog_ = now;
246 RCLCPP_INFO(
247 getLogger(),
248 "CpTunnelCentering: walls L %.1f R %.1f, floor %.1f, ceiling %.1f m -> lateral %+.2f, "
249 "vertical %+.2f m",
250 left, right, floorD, ceilD, lateral_.load(), vertical_.load());
251 }
252}
std::chrono::steady_clock::time_point lastLog_
std::atomic< int64_t > lastCloudNs_
rclcpp::Logger getLogger() const
float kthSmallest(std::vector< float > &v, size_t k)
void levelRotationFromPx4Quaternion(const std::array< float, 4 > &q, std::array< float, 9 > &r)

References attitudeMutex_, attitudeQ_, ceiling_, cl_px4_mr::TunnelCenteringParams::ceilingClearanceM, cl_px4_mr::TunnelCenteringParams::columnHalfWidthM, floor_, cl_px4_mr::TunnelCenteringParams::floorClearanceM, smacc2::ISmaccComponent::getLogger(), haveAttitude_, lastCloudNs_, lastLog_, lateral_, cl_px4_mr::TunnelCenteringParams::lateralSearchM, left_, cl_px4_mr::TunnelCenteringParams::levelFrame, cl_px4_mr::levelRotationFromPx4Quaternion(), cl_px4_mr::TunnelCenteringParams::lookAheadMaxM, cl_px4_mr::TunnelCenteringParams::lookAheadMinM, cl_px4_mr::TunnelCenteringParams::maxLateralM, cl_px4_mr::TunnelCenteringParams::maxVerticalM, cl_px4_mr::TunnelCenteringParams::minFloorClearanceM, cl_px4_mr::TunnelCenteringParams::minFloorPoints, cl_px4_mr::TunnelCenteringParams::minRangeM, cl_px4_mr::TunnelCenteringParams::minWallPoints, params_, right_, cl_px4_mr::TunnelCenteringParams::smoothing, vertical_, cl_px4_mr::TunnelCenteringParams::verticalSearchM, cl_px4_mr::TunnelCenteringParams::wallBandHalfHeightM, and cl_px4_mr::TunnelCenteringParams::wallFadeM.

Referenced by onInitialize().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ onInitialize()

void cl_px4_mr::CpTunnelCentering::onInitialize ( )
overridevirtual

Reimplemented from smacc2::ISmaccComponent.

Definition at line 61 of file cp_tunnel_centering.cpp.

62{
64 if (subscriber_ == nullptr)
65 {
66 RCLCPP_ERROR(
67 getLogger(),
68 "CpTunnelCentering: no CpTopicSubscriber<PointCloud2> on this client - centering inactive");
69 return;
70 }
73 {
74 attitudeSub_ = this->getNode()->create_subscription<px4_msgs::msg::VehicleAttitude>(
75 "/fmu/out/vehicle_attitude", rclcpp::SensorDataQoS(),
76 std::bind(&CpTunnelCentering::onAttitude, this, std::placeholders::_1));
77 }
78 lastLog_ = std::chrono::steady_clock::now();
79 RCLCPP_INFO(
80 getLogger(),
81 "CpTunnelCentering: subscribed - slab %.1f..%.1f m ahead, floor clearance %.2f m (min %.1f), "
82 "ceiling clearance %.1f m, max lateral %.1f m, max vertical %.1f m, wall fade %.1f m",
86}
rclcpp::Subscription< px4_msgs::msg::VehicleAttitude >::SharedPtr attitudeSub_
void onCloud(const sensor_msgs::msg::PointCloud2 &msg)
void onAttitude(const px4_msgs::msg::VehicleAttitude::SharedPtr msg)
smacc2::client_core_components::CpTopicSubscriber< sensor_msgs::msg::PointCloud2 > * subscriber_
void requiresComponent(TComponent *&requiredComponentStorage, ComponentRequirement requirementType=ComponentRequirement::SOFT)
rclcpp::Node::SharedPtr getNode()
smacc2::SmaccSignalConnection onMessageReceived(void(T::*callback)(const MessageType &), T *object)

References attitudeSub_, cl_px4_mr::TunnelCenteringParams::ceilingClearanceM, cl_px4_mr::TunnelCenteringParams::floorClearanceM, smacc2::ISmaccComponent::getLogger(), smacc2::ISmaccComponent::getNode(), lastLog_, cl_px4_mr::TunnelCenteringParams::levelFrame, cl_px4_mr::TunnelCenteringParams::lookAheadMaxM, cl_px4_mr::TunnelCenteringParams::lookAheadMinM, cl_px4_mr::TunnelCenteringParams::maxLateralM, cl_px4_mr::TunnelCenteringParams::maxVerticalM, cl_px4_mr::TunnelCenteringParams::minFloorClearanceM, onAttitude(), onCloud(), smacc2::client_core_components::CpTopicSubscriber< MessageType >::onMessageReceived(), params_, smacc2::ISmaccComponent::requiresComponent(), subscriber_, and cl_px4_mr::TunnelCenteringParams::wallFadeM.

Here is the call graph for this function:

◆ params()

const TunnelCenteringParams & cl_px4_mr::CpTunnelCentering::params ( ) const
inline

Definition at line 110 of file cp_tunnel_centering.hpp.

110{ return params_; }

References params_.

◆ rightWallM()

float cl_px4_mr::CpTunnelCentering::rightWallM ( ) const
inline

Definition at line 106 of file cp_tunnel_centering.hpp.

106{ return right_.load(); }

References right_.

◆ valid()

bool cl_px4_mr::CpTunnelCentering::valid ( ) const

Definition at line 88 of file cp_tunnel_centering.cpp.

89{
90 const int64_t last = lastCloudNs_.load();
91 return last > 0 && (nowNs() - last) < 1000000000LL;
92}

References lastCloudNs_.

Referenced by cl_px4_mr::CbPx4PathFollowerBase::applyCentering().

Here is the caller graph for this function:

◆ verticalOffsetM()

float cl_px4_mr::CpTunnelCentering::verticalOffsetM ( ) const
inline

Definition at line 100 of file cp_tunnel_centering.hpp.

100{ return vertical_.load(); }

References vertical_.

Referenced by cl_px4_mr::CbPx4PathFollowerBase::applyCentering().

Here is the caller graph for this function:

Member Data Documentation

◆ attitudeMutex_

std::mutex cl_px4_mr::CpTunnelCentering::attitudeMutex_
mutableprivate

Definition at line 120 of file cp_tunnel_centering.hpp.

Referenced by onAttitude(), and onCloud().

◆ attitudeQ_

std::array<float, 4> cl_px4_mr::CpTunnelCentering::attitudeQ_ {{1.0f, 0.0f, 0.0f, 0.0f}}
private

Definition at line 121 of file cp_tunnel_centering.hpp.

121{{1.0f, 0.0f, 0.0f, 0.0f}};

Referenced by onAttitude(), and onCloud().

◆ attitudeSub_

rclcpp::Subscription<px4_msgs::msg::VehicleAttitude>::SharedPtr cl_px4_mr::CpTunnelCentering::attitudeSub_
private

Definition at line 119 of file cp_tunnel_centering.hpp.

Referenced by onInitialize().

◆ ceiling_

std::atomic<float> cl_px4_mr::CpTunnelCentering::ceiling_ {0.0f}
private

Definition at line 129 of file cp_tunnel_centering.hpp.

129{0.0f};

Referenced by ceilingM(), and onCloud().

◆ floor_

std::atomic<float> cl_px4_mr::CpTunnelCentering::floor_ {0.0f}
private

Definition at line 128 of file cp_tunnel_centering.hpp.

128{0.0f};

Referenced by floorM(), and onCloud().

◆ haveAttitude_

bool cl_px4_mr::CpTunnelCentering::haveAttitude_ = false
private

Definition at line 122 of file cp_tunnel_centering.hpp.

Referenced by onAttitude(), and onCloud().

◆ lastCloudNs_

std::atomic<int64_t> cl_px4_mr::CpTunnelCentering::lastCloudNs_ {0}
private

Definition at line 130 of file cp_tunnel_centering.hpp.

130{0};

Referenced by onCloud(), and valid().

◆ lastLog_

std::chrono::steady_clock::time_point cl_px4_mr::CpTunnelCentering::lastLog_
private

Definition at line 131 of file cp_tunnel_centering.hpp.

Referenced by onCloud(), and onInitialize().

◆ lateral_

std::atomic<float> cl_px4_mr::CpTunnelCentering::lateral_ {0.0f}
private

Definition at line 124 of file cp_tunnel_centering.hpp.

124{0.0f};

Referenced by lateralOffsetM(), and onCloud().

◆ left_

std::atomic<float> cl_px4_mr::CpTunnelCentering::left_ {0.0f}
private

Definition at line 126 of file cp_tunnel_centering.hpp.

126{0.0f};

Referenced by leftWallM(), and onCloud().

◆ params_

TunnelCenteringParams cl_px4_mr::CpTunnelCentering::params_
private

Definition at line 116 of file cp_tunnel_centering.hpp.

Referenced by onCloud(), onInitialize(), and params().

◆ right_

std::atomic<float> cl_px4_mr::CpTunnelCentering::right_ {0.0f}
private

Definition at line 127 of file cp_tunnel_centering.hpp.

127{0.0f};

Referenced by onCloud(), and rightWallM().

◆ subscriber_

smacc2::client_core_components::CpTopicSubscriber<sensor_msgs::msg::PointCloud2>* cl_px4_mr::CpTunnelCentering::subscriber_
private
Initial value:
=
nullptr

Definition at line 117 of file cp_tunnel_centering.hpp.

Referenced by onInitialize().

◆ vertical_

std::atomic<float> cl_px4_mr::CpTunnelCentering::vertical_ {0.0f}
private

Definition at line 125 of file cp_tunnel_centering.hpp.

125{0.0f};

Referenced by onCloud(), and verticalOffsetM().


The documentation for this class was generated from the following files: