SMACC2
Loading...
Searching...
No Matches
cl_px4_mr::CbPx4PathFollowerBase Class Referenceabstract

#include <cb_px4_path_follower_base.hpp>

Inheritance diagram for cl_px4_mr::CbPx4PathFollowerBase:
Inheritance graph
Collaboration diagram for cl_px4_mr::CbPx4PathFollowerBase:
Collaboration graph

Public Member Functions

 CbPx4PathFollowerBase (PathFollowerParams params={})
 
virtual ~CbPx4PathFollowerBase ()
 
void setFollowerParams (const PathFollowerParams &params)
 
const PathFollowerParams & followerParams () const
 
void onEntry () override
 
void onExit () override
 
void update () override
 
- Public Member Functions inherited from cl_px4_mr::CbPx4ClientBehaviorBase
template<typename TOrthogonal , typename TSourceObject >
void onStateOrthogonalAllocation ()
 
virtual ~CbPx4ClientBehaviorBase ()
 
void setTimeout (std::chrono::milliseconds timeout)
 
bool hasTimeout () const
 
- Public Member Functions inherited from smacc2::SmaccAsyncClientBehavior
template<typename TOrthogonal , typename TSourceObject >
void onStateOrthogonalAllocation ()
 
virtual ~SmaccAsyncClientBehavior ()
 
template<typename TCallback , typename T >
smacc2::SmaccSignalConnection onSuccess (TCallback callback, T *object)
 
template<typename TCallback , typename T >
smacc2::SmaccSignalConnection onFinished (TCallback callback, T *object)
 
template<typename TCallback , typename T >
smacc2::SmaccSignalConnection onFailure (TCallback callback, T *object)
 
void requestForceFinish ()
 
void executeOnEntry () override
 
void executeOnExit () override
 
void waitOnEntryThread (bool requestFinish)
 
template<typename TCallbackMethod , typename T >
smacc2::SmaccSignalConnection onSuccess (TCallbackMethod callback, T *object)
 
template<typename TCallbackMethod , typename T >
smacc2::SmaccSignalConnection onFinished (TCallbackMethod callback, T *object)
 
template<typename TCallbackMethod , typename T >
smacc2::SmaccSignalConnection onFailure (TCallbackMethod callback, T *object)
 
- Public Member Functions inherited from smacc2::ISmaccClientBehavior
 ISmaccClientBehavior ()
 
virtual ~ISmaccClientBehavior ()
 
ISmaccStateMachine * getStateMachine ()
 
std::string getName () const
 
template<typename SmaccClientType >
void requiresClient (SmaccClientType *&storage)
 
template<typename SmaccComponentType >
void requiresComponent (SmaccComponentType *&storage, ComponentRequirement requirementType=ComponentRequirement::SOFT)
 
template<typename SmaccComponentType >
void requiresComponent (std::string name, SmaccComponentType *&storage, ComponentRequirement requirementType=ComponentRequirement::SOFT)
 
- Public Member Functions inherited from smacc2::ISmaccUpdatable
 ISmaccUpdatable ()
 
 ISmaccUpdatable (rclcpp::Duration duration)
 
void executeUpdate (rclcpp::Node::SharedPtr node)
 
void setUpdatePeriod (rclcpp::Duration duration)
 

Protected Member Functions

virtual std::vector< NedPoint > buildPath (const NedPoint &current)=0
 
virtual const char * behaviorName () const
 
virtual void onPathStarted (const std::vector< NedPoint > &)
 
virtual void onPathCompleted ()
 
float totalLength () const
 
float progressFraction () const
 
- Protected Member Functions inherited from cl_px4_mr::CbPx4ClientBehaviorBase
virtual void wireCompletionSignals ()
 
void postPx4Success ()
 
void postPx4Failure ()
 
- Protected Member Functions inherited from smacc2::SmaccAsyncClientBehavior
void postSuccessEvent ()
 
void postFailureEvent ()
 
virtual void dispose () override
 
bool isShutdownRequested ()
 onEntry is executed in a new thread. However the current state cannot be left until the onEntry thread finishes. This flag can be checked from the onEntry thread to force finishing the thread.
 
- Protected Member Functions inherited from smacc2::ISmaccClientBehavior
virtual void runtimeConfigure ()
 
template<typename EventType >
void postEvent (const EventType &ev)
 
template<typename EventType >
void postEvent ()
 
ISmaccState * getCurrentState ()
 
virtual rclcpp::Node::SharedPtr getNode () const
 
virtual rclcpp::Logger getLogger () const
 
- Protected Member Functions inherited from smacc2::ISmaccUpdatable

Protected Attributes

PathFollowerParams followerParams_
 
- Protected Attributes inherited from cl_px4_mr::CbPx4ClientBehaviorBase
CpVehicleCommand * vehicleCommand_ = nullptr
 
CpVehicleStatus * vehicleStatus_ = nullptr
 
CpTrajectorySetpoint * trajectorySetpoint_ = nullptr
 
CpGoalChecker * goalChecker_ = nullptr
 
CpVehicleLocalPosition * localPosition_ = nullptr
 
CpOffboardKeepAlive * offboardKeepAlive_ = nullptr
 

Private Member Functions

NedPoint commandFor (float s)
 
float tangentYawAt (size_t segmentIndex) const
 

Private Attributes

std::vector< NedPoint > path_
 
std::vector< float > cumLen_
 
float totalLen_ = 0.0f
 
float sCarrot_ = 0.0f
 
float entryHeading_ = 0.0f
 
NedPoint lastCmd_
 
int lastProgressDecile_ = -1
 
std::atomic< bool > active_ {false}
 
std::chrono::steady_clock::time_point lastUpdateTime_
 

Detailed Description

Definition at line 76 of file cb_px4_path_follower_base.hpp.

Constructor & Destructor Documentation

◆ CbPx4PathFollowerBase()

cl_px4_mr::CbPx4PathFollowerBase::CbPx4PathFollowerBase ( PathFollowerParams params = {})
explicit

Definition at line 32 of file cb_px4_path_follower_base.cpp.

◆ ~CbPx4PathFollowerBase()

virtual cl_px4_mr::CbPx4PathFollowerBase::~CbPx4PathFollowerBase ( )
inlinevirtual

Definition at line 80 of file cb_px4_path_follower_base.hpp.

80{}

Member Function Documentation

◆ behaviorName()

virtual const char * cl_px4_mr::CbPx4PathFollowerBase::behaviorName ( ) const
inlineprotectedvirtual

◆ buildPath()

virtual std::vector< NedPoint > cl_px4_mr::CbPx4PathFollowerBase::buildPath ( const NedPoint & current)
protectedpure virtual

◆ commandFor()

NedPoint cl_px4_mr::CbPx4PathFollowerBase::commandFor ( float s)
private

Definition at line 216 of file cb_px4_path_follower_base.cpp.

217{
218 size_t segment = 0;
219 NedPoint cmd = sampleAtArcLength(path_, cumLen_, s, &segment);
220
221 switch (followerParams_.yawMode)
222 {
223 case YawMode::FIXED:
225 break;
227 cmd.yaw = entryHeading_;
228 break;
230 if (std::isnan(cmd.yaw))
231 {
232 cmd.yaw = tangentYawAt(segment);
233 }
234 break;
235 case YawMode::TANGENT:
236 default:
237 cmd.yaw = tangentYawAt(segment);
238 break;
239 }
240 cmd.yaw = wrapPi(cmd.yaw);
241 return cmd;
242}
float tangentYawAt(size_t segmentIndex) const
NedPoint sampleAtArcLength(const std::vector< NedPoint > &path, const std::vector< float > &cum, float s, size_t *segmentIndex=nullptr)
float wrapPi(float angle)

References cumLen_, entryHeading_, cl_px4_mr::FIXED, cl_px4_mr::PathFollowerParams::fixedYaw, followerParams_, cl_px4_mr::HOLD_ENTRY, path_, cl_px4_mr::PER_VERTEX, cl_px4_mr::sampleAtArcLength(), cl_px4_mr::TANGENT, tangentYawAt(), cl_px4_mr::wrapPi(), cl_px4_mr::NedPoint::yaw, and cl_px4_mr::PathFollowerParams::yawMode.

Referenced by onEntry(), and update().

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

◆ followerParams()

const PathFollowerParams & cl_px4_mr::CbPx4PathFollowerBase::followerParams ( ) const
inline

Definition at line 83 of file cb_px4_path_follower_base.hpp.

83{ return followerParams_; }

References followerParams_.

◆ onEntry()

void cl_px4_mr::CbPx4PathFollowerBase::onEntry ( )
overridevirtual

Reimplemented from smacc2::ISmaccClientBehavior.

Definition at line 34 of file cb_px4_path_follower_base.cpp.

35{
36 if (localPosition_ == nullptr || trajectorySetpoint_ == nullptr)
37 {
38 RCLCPP_ERROR(
39 getLogger(), "%s: local position / trajectory setpoint component missing - posting failure",
40 behaviorName());
41 this->postPx4Failure();
42 return;
43 }
44 if (!localPosition_->isValid())
45 {
46 RCLCPP_ERROR(
47 getLogger(), "%s: no valid local position at entry - posting failure", behaviorName());
48 this->postPx4Failure();
49 return;
50 }
51
52 NedPoint current;
53 current.x = localPosition_->getX();
54 current.y = localPosition_->getY();
55 current.z = localPosition_->getZ();
56 current.yaw = localPosition_->getHeading();
57 entryHeading_ = current.yaw;
58
59 std::vector<NedPoint> raw = buildPath(current);
60 if (raw.empty())
61 {
62 RCLCPP_ERROR(
63 getLogger(), "%s: buildPath() returned no vertices - posting failure", behaviorName());
64 this->postPx4Failure();
65 return;
66 }
67
68 path_.clear();
70 {
71 NedPoint start = current;
72 start.yaw = std::numeric_limits<float>::quiet_NaN();
73 path_.push_back(start);
74 }
75 for (const NedPoint & v : raw)
76 {
77 if (!path_.empty() && nedDistance(path_.back(), v) < followerParams_.minSegmentLength)
78 {
79 // keep the later vertex's yaw, drop the degenerate segment
80 path_.back().yaw = std::isnan(v.yaw) ? path_.back().yaw : v.yaw;
81 continue;
82 }
83 path_.push_back(v);
84 }
85
87 totalLen_ = cumLen_.empty() ? 0.0f : cumLen_.back();
88 sCarrot_ = 0.0f;
90
91 const float speed = std::max(followerParams_.groundSpeed, 0.05f);
92 const float lag = speed / 0.95f;
93 if (followerParams_.leash < 1.2f * lag)
94 {
95 RCLCPP_WARN(
96 getLogger(),
97 "%s: leash %.1f m is below 1.2x the expected tracking lag (%.1f m at %.1f m/s) - effective "
98 "speed will be throttled to ~%.1f m/s",
100 }
101
102 if (!this->hasTimeout() && followerParams_.autoTimeoutFactor > 0.0f)
103 {
104 const float seconds = std::max(30.0f, followerParams_.autoTimeoutFactor * totalLen_ / speed);
105 this->setTimeout(std::chrono::milliseconds(static_cast<int64_t>(seconds * 1000.0f)));
106 RCLCPP_INFO(getLogger(), "%s: auto-timeout armed at %.0f s", behaviorName(), seconds);
107 }
108
109 RCLCPP_INFO(
110 getLogger(),
111 "%s: following %zu vertices, %.1f m at %.1f m/s (leash %.1f m) from NED (%.1f, %.1f, %.1f) "
112 "to (%.1f, %.1f, %.1f)",
113 behaviorName(), path_.size(), totalLen_, speed, followerParams_.leash, path_.front().x,
114 path_.front().y, path_.front().z, path_.back().x, path_.back().y, path_.back().z);
116
117 lastCmd_ = commandFor(0.0f);
119 lastUpdateTime_ = std::chrono::steady_clock::now();
120 active_ = true;
121}
void setTimeout(std::chrono::milliseconds timeout)
std::chrono::steady_clock::time_point lastUpdateTime_
virtual std::vector< NedPoint > buildPath(const NedPoint &current)=0
virtual void onPathStarted(const std::vector< NedPoint > &)
virtual const char * behaviorName() const
void setPositionNED(float x, float y, float z, float yaw=std::numeric_limits< float >::quiet_NaN())
virtual rclcpp::Logger getLogger() const
float nedDistance(const NedPoint &a, const NedPoint &b)
std::vector< float > cumulativeLengths(const std::vector< NedPoint > &path)

References active_, cl_px4_mr::PathFollowerParams::autoTimeoutFactor, behaviorName(), buildPath(), commandFor(), cumLen_, cl_px4_mr::cumulativeLengths(), entryHeading_, followerParams_, cl_px4_mr::CpVehicleLocalPosition::getHeading(), smacc2::ISmaccClientBehavior::getLogger(), cl_px4_mr::CpVehicleLocalPosition::getX(), cl_px4_mr::CpVehicleLocalPosition::getY(), cl_px4_mr::CpVehicleLocalPosition::getZ(), cl_px4_mr::PathFollowerParams::groundSpeed, cl_px4_mr::CbPx4ClientBehaviorBase::hasTimeout(), cl_px4_mr::CpVehicleLocalPosition::isValid(), lastCmd_, lastProgressDecile_, lastUpdateTime_, cl_px4_mr::PathFollowerParams::leash, cl_px4_mr::CbPx4ClientBehaviorBase::localPosition_, cl_px4_mr::PathFollowerParams::minSegmentLength, cl_px4_mr::nedDistance(), onPathStarted(), path_, cl_px4_mr::CbPx4ClientBehaviorBase::postPx4Failure(), cl_px4_mr::PathFollowerParams::prependCurrentPosition, sCarrot_, cl_px4_mr::CpTrajectorySetpoint::setPositionNED(), cl_px4_mr::CbPx4ClientBehaviorBase::setTimeout(), totalLen_, cl_px4_mr::CbPx4ClientBehaviorBase::trajectorySetpoint_, cl_px4_mr::NedPoint::x, cl_px4_mr::NedPoint::y, cl_px4_mr::NedPoint::yaw, and cl_px4_mr::NedPoint::z.

Here is the call graph for this function:

◆ onExit()

void cl_px4_mr::CbPx4PathFollowerBase::onExit ( )
overridevirtual

Reimplemented from smacc2::ISmaccClientBehavior.

Definition at line 123 of file cb_px4_path_follower_base.cpp.

124{
125 if (active_.exchange(false))
126 {
127 // hold at the last carrot (not hold(): that would step the setpoint back
128 // to the lagging vehicle position)
130 RCLCPP_INFO(
131 getLogger(), "%s: exiting at %.0f%% - holding at last setpoint (%.1f, %.1f, %.1f)",
133 }
134}

References active_, behaviorName(), smacc2::ISmaccClientBehavior::getLogger(), lastCmd_, progressFraction(), cl_px4_mr::CpTrajectorySetpoint::setPositionNED(), cl_px4_mr::CbPx4ClientBehaviorBase::trajectorySetpoint_, cl_px4_mr::NedPoint::x, cl_px4_mr::NedPoint::y, cl_px4_mr::NedPoint::yaw, and cl_px4_mr::NedPoint::z.

Here is the call graph for this function:

◆ onPathCompleted()

virtual void cl_px4_mr::CbPx4PathFollowerBase::onPathCompleted ( )
inlineprotectedvirtual

Definition at line 98 of file cb_px4_path_follower_base.hpp.

98{}

Referenced by update().

Here is the caller graph for this function:

◆ onPathStarted()

virtual void cl_px4_mr::CbPx4PathFollowerBase::onPathStarted ( const std::vector< NedPoint > & )
inlineprotectedvirtual

Definition at line 97 of file cb_px4_path_follower_base.hpp.

97{}

Referenced by onEntry().

Here is the caller graph for this function:

◆ progressFraction()

float cl_px4_mr::CbPx4PathFollowerBase::progressFraction ( ) const
inlineprotected

Definition at line 101 of file cb_px4_path_follower_base.hpp.

101{ return totalLen_ > 0.0f ? sCarrot_ / totalLen_ : 1.0f; }

References sCarrot_, and totalLen_.

Referenced by onExit(), and update().

Here is the caller graph for this function:

◆ setFollowerParams()

void cl_px4_mr::CbPx4PathFollowerBase::setFollowerParams ( const PathFollowerParams & params)
inline

Definition at line 82 of file cb_px4_path_follower_base.hpp.

82{ followerParams_ = params; }

References followerParams_.

◆ tangentYawAt()

float cl_px4_mr::CbPx4PathFollowerBase::tangentYawAt ( size_t segmentIndex) const
private

Definition at line 198 of file cb_px4_path_follower_base.cpp.

199{
200 if (path_.size() < 2)
201 {
202 return entryHeading_;
203 }
204 const size_t i0 = std::min(segmentIndex, path_.size() - 2);
205 const NedPoint & a = path_[i0];
206 const NedPoint & b = path_[i0 + 1];
207 const float dx = b.x - a.x;
208 const float dy = b.y - a.y;
209 if (std::hypot(dx, dy) < 1e-3f)
210 {
211 return entryHeading_; // vertical segment: keep heading
212 }
213 return std::atan2(dy, dx);
214}

References entryHeading_, path_, cl_px4_mr::NedPoint::x, and cl_px4_mr::NedPoint::y.

Referenced by commandFor().

Here is the caller graph for this function:

◆ totalLength()

float cl_px4_mr::CbPx4PathFollowerBase::totalLength ( ) const
inlineprotected

Definition at line 100 of file cb_px4_path_follower_base.hpp.

100{ return totalLen_; }

References totalLen_.

◆ update()

void cl_px4_mr::CbPx4PathFollowerBase::update ( )
overridevirtual

Reimplemented from cl_px4_mr::CbPx4ClientBehaviorBase.

Definition at line 136 of file cb_px4_path_follower_base.cpp.

137{
139
140 if (!active_)
141 {
142 return;
143 }
144
145 const auto now = std::chrono::steady_clock::now();
146 float dt = std::chrono::duration<float>(now - lastUpdateTime_).count();
147 lastUpdateTime_ = now;
148 dt = std::clamp(dt, 0.0f, 0.5f);
149
150 if (!localPosition_->isValid())
151 {
152 // freeze the carrot; the watchdog covers a lost position
153 return;
154 }
155
156 NedPoint vehicle;
157 vehicle.x = localPosition_->getX();
158 vehicle.y = localPosition_->getY();
159 vehicle.z = localPosition_->getZ();
160
161 // advance the carrot, throttled by the leash
162 const float sNext = std::min(sCarrot_ + followerParams_.groundSpeed * dt, totalLen_);
163 const NedPoint candidate = sampleAtArcLength(path_, cumLen_, sNext);
164 if (nedDistance(candidate, vehicle) <= followerParams_.leash)
165 {
166 sCarrot_ = sNext;
167 }
168
171
172 const int decile = static_cast<int>(progressFraction() * 10.0f);
173 if (decile != lastProgressDecile_ && decile > 0 && decile < 10)
174 {
175 lastProgressDecile_ = decile;
176 RCLCPP_INFO(
177 getLogger(), "%s: %d%% (%.0f / %.0f m)", behaviorName(), decile * 10, sCarrot_, totalLen_);
178 }
179
180 // completion: carrot at the end and vehicle within tolerance of the last vertex
181 if (sCarrot_ >= totalLen_)
182 {
183 const NedPoint & end = path_.back();
184 const float dxy = nedDistanceXY(vehicle, end);
185 const float dz = std::fabs(vehicle.z - end.z);
187 {
188 active_ = false;
189 RCLCPP_INFO(
190 getLogger(), "%s: path complete (xy err %.2f m, z err %.2f m) - posting success",
191 behaviorName(), dxy, dz);
193 this->postPx4Success();
194 }
195 }
196}
float nedDistanceXY(const NedPoint &a, const NedPoint &b)

References active_, cl_px4_mr::PathFollowerParams::arrivalXyTol, cl_px4_mr::PathFollowerParams::arrivalZTol, behaviorName(), commandFor(), cumLen_, followerParams_, smacc2::ISmaccClientBehavior::getLogger(), cl_px4_mr::CpVehicleLocalPosition::getX(), cl_px4_mr::CpVehicleLocalPosition::getY(), cl_px4_mr::CpVehicleLocalPosition::getZ(), cl_px4_mr::PathFollowerParams::groundSpeed, cl_px4_mr::CpVehicleLocalPosition::isValid(), lastCmd_, lastProgressDecile_, lastUpdateTime_, cl_px4_mr::PathFollowerParams::leash, cl_px4_mr::CbPx4ClientBehaviorBase::localPosition_, cl_px4_mr::nedDistance(), cl_px4_mr::nedDistanceXY(), onPathCompleted(), path_, cl_px4_mr::CbPx4ClientBehaviorBase::postPx4Success(), progressFraction(), cl_px4_mr::sampleAtArcLength(), sCarrot_, cl_px4_mr::CpTrajectorySetpoint::setPositionNED(), totalLen_, cl_px4_mr::CbPx4ClientBehaviorBase::trajectorySetpoint_, cl_px4_mr::CbPx4ClientBehaviorBase::update(), cl_px4_mr::NedPoint::x, cl_px4_mr::NedPoint::y, cl_px4_mr::NedPoint::yaw, and cl_px4_mr::NedPoint::z.

Here is the call graph for this function:

Member Data Documentation

◆ active_

std::atomic<bool> cl_px4_mr::CbPx4PathFollowerBase::active_ {false}
private

Definition at line 116 of file cb_px4_path_follower_base.hpp.

116{false};

Referenced by onEntry(), onExit(), and update().

◆ cumLen_

std::vector<float> cl_px4_mr::CbPx4PathFollowerBase::cumLen_
private

Definition at line 110 of file cb_px4_path_follower_base.hpp.

Referenced by commandFor(), onEntry(), and update().

◆ entryHeading_

float cl_px4_mr::CbPx4PathFollowerBase::entryHeading_ = 0.0f
private

Definition at line 113 of file cb_px4_path_follower_base.hpp.

Referenced by commandFor(), onEntry(), and tangentYawAt().

◆ followerParams_

◆ lastCmd_

NedPoint cl_px4_mr::CbPx4PathFollowerBase::lastCmd_
private

Definition at line 114 of file cb_px4_path_follower_base.hpp.

Referenced by onEntry(), onExit(), and update().

◆ lastProgressDecile_

int cl_px4_mr::CbPx4PathFollowerBase::lastProgressDecile_ = -1
private

Definition at line 115 of file cb_px4_path_follower_base.hpp.

Referenced by onEntry(), and update().

◆ lastUpdateTime_

std::chrono::steady_clock::time_point cl_px4_mr::CbPx4PathFollowerBase::lastUpdateTime_
private

Definition at line 117 of file cb_px4_path_follower_base.hpp.

Referenced by onEntry(), and update().

◆ path_

std::vector<NedPoint> cl_px4_mr::CbPx4PathFollowerBase::path_
private

Definition at line 109 of file cb_px4_path_follower_base.hpp.

Referenced by commandFor(), onEntry(), tangentYawAt(), and update().

◆ sCarrot_

float cl_px4_mr::CbPx4PathFollowerBase::sCarrot_ = 0.0f
private

Definition at line 112 of file cb_px4_path_follower_base.hpp.

Referenced by onEntry(), progressFraction(), and update().

◆ totalLen_

float cl_px4_mr::CbPx4PathFollowerBase::totalLen_ = 0.0f
private

Definition at line 111 of file cb_px4_path_follower_base.hpp.

Referenced by onEntry(), progressFraction(), totalLength(), and update().


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