Navigation3D motion models and path following
Pathfinding only produces a geometric path. This chapter turns it into a flyable trajectory (post-processors) and into per-frame motion (FlightPathFollowComponent).
A path is not motion: the follow component publishes desired velocity and never writes Transform. To feed desired velocity into flight control, see Flight.
Post-processor overview
Post-processors convert a geometric path into a FlightTrajectory with speed hints and validate with CapsuleFree.
| Type | Motion model | Can fail |
|---|---|---|
Hover | Omnidirectional (multirotor / hover) | No (always succeeds) |
FixedWing | Fixed wing (Dubins Airplane) | Yes (failed segments tabu-replan) |
Failed segments feed pathfinding replan (bounded retries); persistent failure falls back to a straight trajectory.
Hover
Three stages: line-of-sight shortcut → centripetal Catmull-Rom smoothing (optional curvature tightening) → curvature-based speed labels with arrival slowdown ramps.
Relevant FlightAgentConfig: MaxSpeed, MaxAccel, SampleStep, ArrivalSlowdownDistance, MinSpeed, ExtraRadius.
FixedWing
Dubins Airplane: horizontal CSC/CCC shortest paths (MinTurnRadius); vertical linear height interpolation with loiter helices when too steep; G1 continuity at waypoints; per-segment CapsuleFree, failures become tabu.
Extras: MaxClimbAngle (default 0.5 rad), MinAirspeed (default 2.0). Pathfinding-stage turn penalties come from component FixedWingTurnAngleThreshold / FixedWingTurnPenalty (or query config).
Climb trajectories
Separate domain—not SVO flight post-process. FindClimbTrajectoryBetweenPositions(D) returns ClimbTrajectory:
- Surface geodesic approximation resampled by arc length;
- Each point carries
m_normal(wall-facing),m_tangent,m_speedHint.
ClimbAgentConfig defaults: MaxSpeed 3.0, MaxAccel 6.0, SampleStep 0.5, ProjectMaxDistance 3.0.
FlightPathFollowComponent
Turns a trajectory into a per-frame desired velocity for your motion / physics layer to apply.
Typical usage
Navigation3D::FlightPathFollowRequestBus::Event(
agentEntityId, &Navigation3D::FlightPathFollowRequests::StartFollowing, trajectory);
// Each frame:
AZ::Vector3 v;
Navigation3D::FlightPathFollowRequestBus::EventResult(
v, agentEntityId, &Navigation3D::FlightPathFollowRequests::GetDesiredVelocity);
// Apply v in your motion layer
Also: StartFollowingOnVolume, Stop, IsFollowing, GetPreferredVelocity (pre-avoidance intent), GetDesiredOrientation.
FlightFollowConfig
| Field | Default | Purpose |
|---|---|---|
m_lookaheadBase | 2.0 | Pure-pursuit base lookahead (m) |
m_lookaheadSpeedFactor | 0.5 | Lookahead grows with speed |
m_arrivalTolerance | 1.0 | Arrival distance (m) |
m_arrivalSpeedThreshold | 0.5 | Arrival speed threshold (m/s) |
m_deviationThreshold | 3.0 | Fires OnPathDeviated (m) |
m_maxSpeed | 10.0 | Speed cap |
m_headingMode | VelocityDirection | Heading mode |
m_lookaheadSafetyCheck | true | CapsuleFree lookahead against SVO |
m_fixedWing | false | Fixed-wing follow (no hover / reverse) |
m_minAirspeed | 2.0 | Fixed-wing min airspeed |
m_avoidance | see below | Velocity-obstacle avoidance |
FlightHeadingMode: VelocityDirection / TowardTarget / Free (external control).
Velocity obstacles (VelocityObstacleConfig)
| Field | Default | Purpose |
|---|---|---|
m_enabled | true | Enable avoidance |
m_queryRadius | 10.0 | Nearby dynamic-body query radius (m) |
m_timeHorizon | 2.0 | Time horizon (s) |
m_queryIntervalTicks | 2 | Re-query obstacles every N ticks |
m_sampleDirections | 24 | Candidate velocity directions |
m_reciprocal | false | Reciprocal avoidance (ORCA-style) |
Global switch: /O3DE/Gems/Navigation3D/Runtime/VelocityObstacleEnabled (default true).
Lifecycle notifications
FlightPathFollowNotificationBus: OnDesiredVelocityUpdated / OnPathCompleted / OnPathDeviated / OnPathBlocked / OnAvoidanceFailed (scriptable).
Hook into your motion layer
Query → FlightTrajectory
→ FlightPathFollow.StartFollowing
→ each frame GetDesiredVelocity → your motion / physics → Transform
→ deviate / blocked → your logic re-queries
- Follow only answers “where / how fast”; not “how to move”.
- Listen for
OnPathDeviated/OnPathBlockedto decide when to replan.
Next steps
- HTN integration — let a planner drive takeoff / flight
- Debugging — paths / velocity missing or wrong