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

#include <cp_forward_obstacle_guard.hpp>

Inheritance diagram for cl_px4_mr::CpForwardObstacleGuard:
Inheritance graph
Collaboration diagram for cl_px4_mr::CpForwardObstacleGuard:
Collaboration graph

Public Member Functions

 CpForwardObstacleGuard (ForwardObstacleGuardParams params={})
 
virtual ~CpForwardObstacleGuard ()
 
void onInitialize () override
 
template<typename T >
smacc2::SmaccSignalConnection onObstacleTooClose (void(T::*callback)(), T *object)
 
template<typename T >
smacc2::SmaccSignalConnection onObstacleCleared (void(T::*callback)(), T *object)
 
void reset ()
 
bool isTooClose () const
 
float lastYawRate () const
 
float lastMinRange () const
 
int lastHits () const
 
const ForwardObstacleGuardParams & params () const
 
- Public Member Functions inherited from smacc2::ISmaccComponent
 ISmaccComponent ()
 
virtual ~ISmaccComponent ()
 
virtual std::string getName () const
 

Public Attributes

smacc2::SmaccSignal< void()> onObstacleTooClose_
 
smacc2::SmaccSignal< void()> onObstacleCleared_
 

Private Member Functions

void onCloud (const sensor_msgs::msg::PointCloud2 &msg)
 
void onAttitude (const px4_msgs::msg::VehicleAttitude::SharedPtr msg)
 
bool levelRotation (std::array< float, 9 > &r) const
 

Private Attributes

ForwardObstacleGuardParams params_
 
smacc2::client_core_components::CpTopicSubscriber< sensor_msgs::msg::PointCloud2 > * subscriber_
 
rclcpp::Subscription< px4_msgs::msg::VehicleAttitude >::SharedPtr attitudeSub_
 
double lastYaw_ = 0.0
 
uint64_t lastYawStampUs_ = 0
 
std::mutex attitudeMutex_
 
std::array< float, 4 > attitudeQ_ {{1.0f, 0.0f, 0.0f, 0.0f}}
 
bool haveAttitude_ = false
 
std::atomic< float > yawRate_ {0.0f}
 
int gatedClouds_ = 0
 
float cosHalfAngle_ = 1.0f
 
int triggerStreak_ = 0
 
int clearStreak_ = 0
 
std::atomic< bool > tooClose_ {false}
 
std::atomic< float > lastMinRange_ {std::numeric_limits<float>::infinity()}
 
std::atomic< int > lastHits_ {0}
 

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 89 of file cp_forward_obstacle_guard.hpp.

Constructor & Destructor Documentation

◆ CpForwardObstacleGuard()

cl_px4_mr::CpForwardObstacleGuard::CpForwardObstacleGuard ( ForwardObstacleGuardParams params = {})
explicit

◆ ~CpForwardObstacleGuard()

cl_px4_mr::CpForwardObstacleGuard::~CpForwardObstacleGuard ( )
virtual

Definition at line 37 of file cp_forward_obstacle_guard.cpp.

37{}

Member Function Documentation

◆ isTooClose()

bool cl_px4_mr::CpForwardObstacleGuard::isTooClose ( ) const
inline

Definition at line 115 of file cp_forward_obstacle_guard.hpp.

115{ return tooClose_.load(); }

References tooClose_.

◆ lastHits()

int cl_px4_mr::CpForwardObstacleGuard::lastHits ( ) const
inline

Definition at line 118 of file cp_forward_obstacle_guard.hpp.

118{ return lastHits_.load(); }

References lastHits_.

◆ lastMinRange()

float cl_px4_mr::CpForwardObstacleGuard::lastMinRange ( ) const
inline

Definition at line 117 of file cp_forward_obstacle_guard.hpp.

117{ return lastMinRange_.load(); }

References lastMinRange_.

◆ lastYawRate()

float cl_px4_mr::CpForwardObstacleGuard::lastYawRate ( ) const
inline

Definition at line 116 of file cp_forward_obstacle_guard.hpp.

116{ return yawRate_.load(); }

References yawRate_.

◆ levelRotation()

bool cl_px4_mr::CpForwardObstacleGuard::levelRotation ( std::array< float, 9 > & r) const
private

Definition at line 103 of file cp_forward_obstacle_guard.cpp.

104{
105 std::array<float, 4> q;
106 {
107 std::lock_guard<std::mutex> lock(attitudeMutex_);
108 if (!haveAttitude_)
109 {
110 return false;
111 }
112 q = attitudeQ_;
113 }
114 // body FLU -> ENU (px4_ros_com constants), then strip the yaw so the result
115 // is the roll/pitch-only rotation into a level, heading-aligned frame
116 const tf2::Quaternion kNedEnuQ(0.70710678118654752, 0.70710678118654752, 0.0, 0.0);
117 const tf2::Quaternion kFrdFluQ(1.0, 0.0, 0.0, 0.0);
118 const tf2::Quaternion qNedFrd(q[1], q[2], q[3], q[0]);
119 tf2::Quaternion qEnuFlu = kNedEnuQ * qNedFrd * kFrdFluQ;
120 qEnuFlu.normalize();
121 const tf2::Matrix3x3 m(qEnuFlu);
122 const double yaw = std::atan2(m[1][0], m[0][0]);
123 tf2::Matrix3x3 unyaw;
124 unyaw.setRPY(0.0, 0.0, -yaw);
125 const tf2::Matrix3x3 level = unyaw * m;
126 for (int i = 0; i < 3; ++i)
127 {
128 for (int j = 0; j < 3; ++j)
129 {
130 r[i * 3 + j] = static_cast<float>(level[i][j]);
131 }
132 }
133 return true;
134}
const tf2::Quaternion kFrdFluQ(1.0, 0.0, 0.0, 0.0)
const tf2::Quaternion kNedEnuQ(0.70710678118654752, 0.70710678118654752, 0.0, 0.0)

References attitudeMutex_, attitudeQ_, and haveAttitude_.

Referenced by onCloud().

Here is the caller graph for this function:

◆ onAttitude()

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

Definition at line 78 of file cp_forward_obstacle_guard.cpp.

79{
80 // yaw rate by finite difference of the NED heading (PX4 does not bridge
81 // vehicle_angular_velocity by default); light EMA against quantisation
82 const double w = msg->q[0], x = msg->q[1], y = msg->q[2], z = msg->q[3];
83 const double yaw = std::atan2(2.0 * (w * z + x * y), 1.0 - 2.0 * (y * y + z * z));
84 if (lastYawStampUs_ != 0 && msg->timestamp > lastYawStampUs_)
85 {
86 const double dt = static_cast<double>(msg->timestamp - lastYawStampUs_) * 1e-6;
87 double d = yaw - lastYaw_;
88 d = std::atan2(std::sin(d), std::cos(d));
89 if (dt > 1e-4 && dt < 0.5)
90 {
91 const float rate = static_cast<float>(d / dt);
92 yawRate_ = 0.5f * yawRate_.load() + 0.5f * rate;
93 }
94 }
95 lastYaw_ = yaw;
96 lastYawStampUs_ = msg->timestamp;
97
98 std::lock_guard<std::mutex> lock(attitudeMutex_);
99 attitudeQ_ = {msg->q[0], msg->q[1], msg->q[2], msg->q[3]};
100 haveAttitude_ = true;
101}

References attitudeMutex_, attitudeQ_, haveAttitude_, lastYaw_, lastYawStampUs_, and yawRate_.

Referenced by onInitialize().

Here is the caller graph for this function:

◆ onCloud()

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

Definition at line 136 of file cp_forward_obstacle_guard.cpp.

137{
138 if (params_.maxYawRateRadS > 0.0f && std::fabs(yawRate_.load()) > params_.maxYawRateRadS)
139 {
140 // turning: the cone is sweeping sideways; keep the current flag, count nothing
141 if (++gatedClouds_ == 1)
142 {
143 RCLCPP_INFO(
144 getLogger(), "CpForwardObstacleGuard: yawing at %.2f rad/s - cone gated", yawRate_.load());
145 }
146 return;
147 }
148 if (gatedClouds_ > 0)
149 {
150 RCLCPP_INFO(
151 getLogger(), "CpForwardObstacleGuard: cone active again after %d gated clouds", gatedClouds_);
152 gatedClouds_ = 0;
153 triggerStreak_ = 0;
154 }
155
156 int hits = 0;
157 float minRange = std::numeric_limits<float>::infinity();
158
159 std::array<float, 9> r{};
160 const bool level = params_.levelFrame && levelRotation(r);
161
162 sensor_msgs::PointCloud2ConstIterator<float> ix(msg, "x");
163 sensor_msgs::PointCloud2ConstIterator<float> iy(msg, "y");
164 sensor_msgs::PointCloud2ConstIterator<float> iz(msg, "z");
165 for (; ix != ix.end(); ++ix, ++iy, ++iz)
166 {
167 float x = *ix;
168 float y = *iy;
169 float z = *iz;
170 if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(z))
171 {
172 continue; // gz reports no-return as inf (is_dense = false)
173 }
175 {
176 // optical (z forward, x right, y down) -> sensor (x forward, y left, z up)
177 const float ox = x, oy = y, oz = z;
178 x = oz;
179 y = -ox;
180 z = -oy;
181 }
182 if (level)
183 {
184 const float lx = r[0] * x + r[1] * y + r[2] * z;
185 const float ly = r[3] * x + r[4] * y + r[5] * z;
186 const float lz = r[6] * x + r[7] * y + r[8] * z;
187 x = lx;
188 y = ly;
189 z = lz;
190 }
191 if (params_.floorCutoffM > 0.0f && z < -params_.floorCutoffM)
192 {
193 continue; // the floor, not something in the way
194 }
195 const float r = std::sqrt(x * x + y * y + z * z);
196 if (r < params_.minRangeM || r > params_.clearRangeM)
197 {
198 continue;
199 }
200 if (x / r < cosHalfAngle_)
201 {
202 continue; // outside the forward cone
203 }
204 if (r < minRange)
205 {
206 minRange = r;
207 }
208 if (r < params_.triggerRangeM)
209 {
210 ++hits;
211 }
212 }
213
214 lastMinRange_ = minRange;
215 lastHits_ = hits;
216
217 const bool triggering = hits >= params_.minHits;
218 // cleared only when nothing in the cone is below the clear range at all
219 const bool clear = !(minRange < params_.clearRangeM);
220
221 if (!tooClose_)
222 {
223 triggerStreak_ = triggering ? triggerStreak_ + 1 : 0;
225 {
226 tooClose_ = true;
227 clearStreak_ = 0;
228 RCLCPP_WARN(
229 getLogger(), "CpForwardObstacleGuard: OBSTACLE min range %.2f m (%d hits in cone)",
230 minRange, hits);
232 }
233 }
234 else
235 {
236 clearStreak_ = clear ? clearStreak_ + 1 : 0;
238 {
239 tooClose_ = false;
240 triggerStreak_ = 0;
241 RCLCPP_INFO(getLogger(), "CpForwardObstacleGuard: cleared (min range %.2f m)", minRange);
243 }
244 }
245}
bool levelRotation(std::array< float, 9 > &r) const
smacc2::SmaccSignal< void()> onObstacleCleared_
smacc2::SmaccSignal< void()> onObstacleTooClose_
rclcpp::Logger getLogger() const

References cl_px4_mr::ForwardObstacleGuardParams::clearClouds, cl_px4_mr::ForwardObstacleGuardParams::clearRangeM, clearStreak_, cosHalfAngle_, cl_px4_mr::ForwardObstacleGuardParams::floorCutoffM, gatedClouds_, smacc2::ISmaccComponent::getLogger(), lastHits_, lastMinRange_, cl_px4_mr::ForwardObstacleGuardParams::levelFrame, levelRotation(), cl_px4_mr::ForwardObstacleGuardParams::maxYawRateRadS, cl_px4_mr::ForwardObstacleGuardParams::minHits, onObstacleCleared_, onObstacleTooClose_, cl_px4_mr::ForwardObstacleGuardParams::opticalFrameInput, params_, tooClose_, cl_px4_mr::ForwardObstacleGuardParams::triggerClouds, cl_px4_mr::ForwardObstacleGuardParams::triggerRangeM, triggerStreak_, and yawRate_.

Referenced by onInitialize().

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

◆ onInitialize()

void cl_px4_mr::CpForwardObstacleGuard::onInitialize ( )
overridevirtual

Reimplemented from smacc2::ISmaccComponent.

Definition at line 39 of file cp_forward_obstacle_guard.cpp.

40{
42 if (subscriber_ == nullptr)
43 {
44 RCLCPP_ERROR(
45 getLogger(),
46 "CpForwardObstacleGuard: no CpTopicSubscriber<PointCloud2> on this client - guard inactive");
47 return;
48 }
51 {
52 attitudeSub_ = this->getNode()->create_subscription<px4_msgs::msg::VehicleAttitude>(
53 "/fmu/out/vehicle_attitude", rclcpp::SensorDataQoS(),
54 std::bind(&CpForwardObstacleGuard::onAttitude, this, std::placeholders::_1));
55 }
56 RCLCPP_INFO(
57 getLogger(),
58 "CpForwardObstacleGuard: subscribed - cone %.0f deg, trigger < %.1f m, clear > %.1f m, "
59 "%d hits, %d/%d clouds, yaw-rate gate %.2f rad/s, floor cutoff %.1f m, level frame %s",
62 params_.floorCutoffM, params_.levelFrame ? "on" : "off");
63}
smacc2::client_core_components::CpTopicSubscriber< sensor_msgs::msg::PointCloud2 > * subscriber_
void onAttitude(const px4_msgs::msg::VehicleAttitude::SharedPtr msg)
void onCloud(const sensor_msgs::msg::PointCloud2 &msg)
rclcpp::Subscription< px4_msgs::msg::VehicleAttitude >::SharedPtr attitudeSub_
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::ForwardObstacleGuardParams::clearClouds, cl_px4_mr::ForwardObstacleGuardParams::clearRangeM, cl_px4_mr::ForwardObstacleGuardParams::floorCutoffM, smacc2::ISmaccComponent::getLogger(), smacc2::ISmaccComponent::getNode(), cl_px4_mr::ForwardObstacleGuardParams::halfAngleRad, cl_px4_mr::ForwardObstacleGuardParams::levelFrame, cl_px4_mr::ForwardObstacleGuardParams::maxYawRateRadS, cl_px4_mr::ForwardObstacleGuardParams::minHits, onAttitude(), onCloud(), smacc2::client_core_components::CpTopicSubscriber< MessageType >::onMessageReceived(), params_, smacc2::ISmaccComponent::requiresComponent(), subscriber_, cl_px4_mr::ForwardObstacleGuardParams::triggerClouds, and cl_px4_mr::ForwardObstacleGuardParams::triggerRangeM.

Here is the call graph for this function:

◆ onObstacleCleared()

template<typename T >
smacc2::SmaccSignalConnection cl_px4_mr::CpForwardObstacleGuard::onObstacleCleared ( void(T::* callback )(),
T * object )
inline

Definition at line 104 of file cp_forward_obstacle_guard.hpp.

105 {
106 return this->getStateMachine()->createSignalConnection(onObstacleCleared_, callback, object);
107 }
ISmaccStateMachine * getStateMachine()
smacc2::SmaccSignalConnection createSignalConnection(TSmaccSignal &signal, TMemberFunctionPrototype callback, TSmaccObjectType *object)

References smacc2::ISmaccStateMachine::createSignalConnection(), smacc2::ISmaccComponent::getStateMachine(), and onObstacleCleared_.

Referenced by cl_px4_mr::CbObstacleGuard::onEntry().

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

◆ onObstacleTooClose()

template<typename T >
smacc2::SmaccSignalConnection cl_px4_mr::CpForwardObstacleGuard::onObstacleTooClose ( void(T::* callback )(),
T * object )
inline

Definition at line 98 of file cp_forward_obstacle_guard.hpp.

99 {
100 return this->getStateMachine()->createSignalConnection(onObstacleTooClose_, callback, object);
101 }

References smacc2::ISmaccStateMachine::createSignalConnection(), smacc2::ISmaccComponent::getStateMachine(), and onObstacleTooClose_.

Referenced by cl_px4_mr::CbObstacleGuard::onEntry().

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

◆ params()

const ForwardObstacleGuardParams & cl_px4_mr::CpForwardObstacleGuard::params ( ) const
inline

Definition at line 119 of file cp_forward_obstacle_guard.hpp.

119{ return params_; }

References params_.

◆ reset()

void cl_px4_mr::CpForwardObstacleGuard::reset ( )

Definition at line 65 of file cp_forward_obstacle_guard.cpp.

66{
67 const bool was = tooClose_.exchange(false);
69 clearStreak_ = 0;
70 if (was)
71 {
72 RCLCPP_INFO(
73 getLogger(), "CpForwardObstacleGuard: reset (stale flag dropped, last min range %.2f m)",
74 lastMinRange_.load());
75 }
76}

References clearStreak_, smacc2::ISmaccComponent::getLogger(), lastMinRange_, tooClose_, and triggerStreak_.

Referenced by cl_px4_mr::CbObstacleGuard::onEntry().

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

Member Data Documentation

◆ attitudeMutex_

std::mutex cl_px4_mr::CpForwardObstacleGuard::attitudeMutex_
mutableprivate

Definition at line 136 of file cp_forward_obstacle_guard.hpp.

Referenced by levelRotation(), and onAttitude().

◆ attitudeQ_

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

Definition at line 137 of file cp_forward_obstacle_guard.hpp.

137{{1.0f, 0.0f, 0.0f, 0.0f}}; // PX4 order w, x, y, z

Referenced by levelRotation(), and onAttitude().

◆ attitudeSub_

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

Definition at line 133 of file cp_forward_obstacle_guard.hpp.

Referenced by onInitialize().

◆ clearStreak_

int cl_px4_mr::CpForwardObstacleGuard::clearStreak_ = 0
private

Definition at line 143 of file cp_forward_obstacle_guard.hpp.

Referenced by onCloud(), and reset().

◆ cosHalfAngle_

float cl_px4_mr::CpForwardObstacleGuard::cosHalfAngle_ = 1.0f
private

Definition at line 141 of file cp_forward_obstacle_guard.hpp.

Referenced by onCloud().

◆ gatedClouds_

int cl_px4_mr::CpForwardObstacleGuard::gatedClouds_ = 0
private

Definition at line 140 of file cp_forward_obstacle_guard.hpp.

Referenced by onCloud().

◆ haveAttitude_

bool cl_px4_mr::CpForwardObstacleGuard::haveAttitude_ = false
private

Definition at line 138 of file cp_forward_obstacle_guard.hpp.

Referenced by levelRotation(), and onAttitude().

◆ lastHits_

std::atomic<int> cl_px4_mr::CpForwardObstacleGuard::lastHits_ {0}
private

Definition at line 146 of file cp_forward_obstacle_guard.hpp.

146{0};

Referenced by lastHits(), and onCloud().

◆ lastMinRange_

std::atomic<float> cl_px4_mr::CpForwardObstacleGuard::lastMinRange_ {std::numeric_limits<float>::infinity()}
private

Definition at line 145 of file cp_forward_obstacle_guard.hpp.

145{std::numeric_limits<float>::infinity()};

Referenced by lastMinRange(), onCloud(), and reset().

◆ lastYaw_

double cl_px4_mr::CpForwardObstacleGuard::lastYaw_ = 0.0
private

Definition at line 134 of file cp_forward_obstacle_guard.hpp.

Referenced by onAttitude().

◆ lastYawStampUs_

uint64_t cl_px4_mr::CpForwardObstacleGuard::lastYawStampUs_ = 0
private

Definition at line 135 of file cp_forward_obstacle_guard.hpp.

Referenced by onAttitude().

◆ onObstacleCleared_

smacc2::SmaccSignal<void()> cl_px4_mr::CpForwardObstacleGuard::onObstacleCleared_

Definition at line 122 of file cp_forward_obstacle_guard.hpp.

Referenced by onCloud(), and onObstacleCleared().

◆ onObstacleTooClose_

smacc2::SmaccSignal<void()> cl_px4_mr::CpForwardObstacleGuard::onObstacleTooClose_

Definition at line 121 of file cp_forward_obstacle_guard.hpp.

Referenced by onCloud(), and onObstacleTooClose().

◆ params_

ForwardObstacleGuardParams cl_px4_mr::CpForwardObstacleGuard::params_
private

Definition at line 130 of file cp_forward_obstacle_guard.hpp.

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

◆ subscriber_

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

Definition at line 131 of file cp_forward_obstacle_guard.hpp.

Referenced by onInitialize().

◆ tooClose_

std::atomic<bool> cl_px4_mr::CpForwardObstacleGuard::tooClose_ {false}
private

Definition at line 144 of file cp_forward_obstacle_guard.hpp.

144{false};

Referenced by isTooClose(), onCloud(), and reset().

◆ triggerStreak_

int cl_px4_mr::CpForwardObstacleGuard::triggerStreak_ = 0
private

Definition at line 142 of file cp_forward_obstacle_guard.hpp.

Referenced by onCloud(), and reset().

◆ yawRate_

std::atomic<float> cl_px4_mr::CpForwardObstacleGuard::yawRate_ {0.0f}
private

Definition at line 139 of file cp_forward_obstacle_guard.hpp.

139{0.0f};

Referenced by lastYawRate(), onAttitude(), and onCloud().


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