Contenu principal

Generate Trajectory Live Editor Task for Flight Mission with No-Fly Zones

Since R2026a

This example shows how to use the Generate Trajectory live task to create a trajectory for a flight mission with no-fly zones using waypoints.

Add Waypoints Using Generate Trajectory Live Task

On the Live Editor tab, select Insert > Task, and then select Generate Trajectory.

Live Task

To see the generated code, select Show code.

Define No-Fly Zones

Define the bounding area for the no-fly zones. Use the convhull function to compute convex hull indices and then plot the area and fill in the no-fly zones.

Outline the perimeter of the no-fly zone.

xlim = [0 50];
ylim = [0 50];

Define a consistent set of boundary waypoints inside the boundary area.

x = [10 20 35 40 30 15 5 12 28 22];
y = [10 40 45 30 20 5 25 15 38 18];

Use the convhull function to compute the convex hull indices, and then plot the area and fill in the no-fly zones.

hullIdx = convhull(x, y);

% Plot the square area
figure;

hold on;
rectangle('Position',[xlim(1), ylim(1), xlim(2)-xlim(1), ylim(2)-ylim(1)], ...
    'EdgeColor','k','LineStyle','--');

% Plot the points
plot(x, y, 'bo', 'MarkerFaceColor', 'b');

% Plot the convex hull boundary
plot(x(hullIdx), y(hullIdx), 'r-', 'LineWidth', 2);

Fill the no-fly zone, and then define the axis settings.

% Fill the no-fly zone
fill(x(hullIdx), y(hullIdx), 'r', 'FaceAlpha', 0.2, 'EdgeColor', 'none');

% Axis settings
axis([xlim ylim]);
axis equal;
title('No-Fly Zone Boundary Using convhull');
xlabel('North');
ylabel('East');
legend('Points','No-Fly Zone Boundary','No-Fly Zone', 'Location', 'bestoutside');
hold off;

Figure contains an axes object. The axes object with title No-Fly Zone Boundary Using convhull, xlabel North, ylabel East contains 4 objects of type rectangle, line, patch. One or more of the lines displays its values using only markers These objects represent Points, No-Fly Zone Boundary, No-Fly Zone.

Get Suitable Path Avoiding No-Fly Zones

Extract the trajectory data from the timeseries.

xTraj = Vehicle1Traj.xNorth.Data;
yTraj = Vehicle1Traj.yEast.Data;

Prepare the convex hull polygon and then close the polygon.

xHull = x(hullIdx);
yHull = y(hullIdx); % closed polygon with repeated last point

Find the intersection points between the trajectory and the hull.

xIntersections = [];
yIntersections = [];
trajectorySegmentIndicesAtIntersection = [];
hullSegmentIndicesAtIntersection = [];

numTrajectorySegments = numel(xTraj) - 1;
numHullSegments = numel(xHull) - 1; % assumes last point repeats first

for trajectorySegmentIndex = 1:numTrajectorySegments
    for hullSegmentIndex = 1:numHullSegments
        % Trajectory segment endpoints
        xTrajectoryStart = xTraj(trajectorySegmentIndex);
        yTrajectoryStart = yTraj(trajectorySegmentIndex);
        xTrajectoryEnd   = xTraj(trajectorySegmentIndex + 1);
        yTrajectoryEnd   = yTraj(trajectorySegmentIndex + 1);

        % Hull segment endpoints
        xHullStart = xHull(hullSegmentIndex);
        yHullStart = yHull(hullSegmentIndex);
        xHullEnd   = xHull(hullSegmentIndex + 1);
        yHullEnd   = yHull(hullSegmentIndex + 1);

        % Segment intersection (parametric form)
        denominator = (xTrajectoryEnd - xTrajectoryStart) * (yHullEnd - yHullStart) ...
                   - (yTrajectoryEnd - yTrajectoryStart) * (xHullEnd - xHullStart);

        if denominator == 0
            continue; % Parallel segments, no intersection
        end

        % Parameters along trajectory (uTraj) and hull (uHull) segments
        uTraj = ((xHullEnd - xHullStart) * (yTrajectoryStart - yHullStart) ...
              - (yHullEnd - yHullStart) * (xTrajectoryStart - xHullStart)) / denominator;

        uHull = ((xTrajectoryEnd - xTrajectoryStart) * (yTrajectoryStart - yHullStart) ...
              - (yTrajectoryEnd - yTrajectoryStart) * (xTrajectoryStart - xHullStart)) / denominator;

        % Check if intersection lies within both segments
        if uTraj >= 0 && uTraj <= 1 && uHull >= 0 && uHull <= 1
            xIntersections(end+1,1) = xTrajectoryStart + uTraj * (xTrajectoryEnd - xTrajectoryStart);
            yIntersections(end+1,1) = yTrajectoryStart + uTraj * (yTrajectoryEnd - yTrajectoryStart);
            trajectorySegmentIndicesAtIntersection(end+1,1) = trajectorySegmentIndex;
            hullSegmentIndicesAtIntersection(end+1,1) = hullSegmentIndex;
        end
    end
end

Remove duplicate intersection points (with tolerance).

if ~isempty(xIntersections)
    tolerance = 1e-8;
    intersectionCoordinates = [xIntersections yIntersections];
    intersectionRounded = round(intersectionCoordinates / tolerance) * tolerance;

    [~, uniqueIndices] = unique(intersectionRounded, 'rows', 'stable');

    xIntersections = xIntersections(uniqueIndices);
    yIntersections = yIntersections(uniqueIndices);
    trajectorySegmentIndicesAtIntersection = trajectorySegmentIndicesAtIntersection(uniqueIndices);
    hullSegmentIndicesAtIntersection = hullSegmentIndicesAtIntersection(uniqueIndices);
else
    legend('Area Boundary', 'Points', 'No-Fly Zone Boundary', 'No-Fly Zone', 'Vehicle 1 Trajectory');
    disp('No intersection between trajectory and NFZ.');
    return
end

Find the closest vertex indices on trajectory and hull for each intersection.

closestTrajectoryPointIndices = zeros(size(xIntersections));
closestHullPointIndices = zeros(size(xIntersections));

for intersectionIndex = 1:length(xIntersections)
    [~, closestTrajectoryPointIndices(intersectionIndex)] = min(hypot(xTraj - xIntersections(intersectionIndex), yTraj - yIntersections(intersectionIndex)));
    [~, closestHullPointIndices(intersectionIndex)] = min(hypot(xHull - xIntersections(intersectionIndex), yHull - yIntersections(intersectionIndex)));
end

Sort the intersections in order along trajectory.

[~, sortOrder] = sort(closestTrajectoryPointIndices);
xIntersections = xIntersections(sortOrder);
yIntersections = yIntersections(sortOrder);
closestTrajectoryPointIndices = closestTrajectoryPointIndices(sortOrder);
closestHullPointIndices = closestHullPointIndices(sortOrder);

Handle the first entry and first exit.

if length(xIntersections) < 2
    legend('Area Boundary', 'Points', 'No-Fly Zone Boundary', 'No-Fly Zone', 'Vehicle 1 Trajectory');
    disp('Trajectory crosses NFZ less than twice. No rerouting performed.');
    return
end

entryTrajectoryIndex = closestTrajectoryPointIndices(1);
exitTrajectoryIndex  = closestTrajectoryPointIndices(2);
entryHullIndex = closestHullPointIndices(1);
exitHullIndex  = closestHullPointIndices(2);

Find the shortest path along the hull between entry and exit in both directions.

numHullVertices = length(xHull);
if exitHullIndex > entryHullIndex
    hullPathForward = entryHullIndex:exitHullIndex;
    hullPathBackward = [exitHullIndex:numHullVertices, 1:entryHullIndex];
else
    hullPathForward = [entryHullIndex:numHullVertices, 1:exitHullIndex];
    hullPathBackward = exitHullIndex:entryHullIndex;
end

if length(hullPathForward) < length(hullPathBackward)
    hullPathIndices = hullPathForward;
else
    hullPathIndices = hullPathBackward;
end

Build a new rerouted polyline from the entry to the exit via the hull perimeter.

xRerouted = [xTraj(1:entryTrajectoryIndex);  xHull(hullPathIndices)'; xIntersections(2); xTraj(exitTrajectoryIndex+1:end)];
yRerouted = [yTraj(1:entryTrajectoryIndex);  yHull(hullPathIndices)'; yIntersections(2); yTraj(exitTrajectoryIndex+1:end)];

Convert the rerouted polyline to segments, distances, bearings, and altitudes.

deltaX = diff(xRerouted);
deltaY = diff(yRerouted);
segmentDistances = hypot(deltaX, deltaY);
segmentAbsoluteBearings = mod(atan2(deltaY, deltaX), 2*pi);
segmentAltitudes = zeros(1, numel(segmentDistances));

Create an aerospace polyline trajectory with timeseries output.

reroutedTrajectory = Aero.trajectory.polylineTrajectory( ...
    CoordinatePlane = "Flat", ...
    InitialPosition = [xRerouted(1), yRerouted(1)], ...
    Speed = 10, ...
    InitialHeading = segmentAbsoluteBearings(1), ...
    InitialAltitude = 0, ...
    OutputFormat = "timeseries", ...
    Units = "Metric (MKS)", ...
    StartTime = "2025-10-12 11:20:02", ...
    SegmentDistance = segmentDistances(1), ...
    AbsoluteBearing = segmentAbsoluteBearings(1), ...
    Altitude = segmentAltitudes(1));

for segmentIndex = 2:numel(segmentDistances)
    reroutedTrajectory = Aero.trajectory.polylineTrajectory( ...
        PriorTrajectory = reroutedTrajectory, ...
        SegmentDistance = segmentDistances(segmentIndex), ...
        AbsoluteBearing = segmentAbsoluteBearings(segmentIndex), ...
        Altitude = segmentAltitudes(segmentIndex));
end

xReroutedTrajectory = reroutedTrajectory.xNorth.Data;
yReroutedTrajectory = reroutedTrajectory.yEast.Data;

Plot Trajectory

Plot the original trajectory as a dotted black line.

figure;
hold on;

plot(xTraj, yTraj, 'k:', 'LineWidth', 2); % Dotted black line

% Draw the plotting window rectangle (based on current axis limits)
rectangle('Position', [xlim(1), ylim(1), xlim(2)-xlim(1), ylim(2)-ylim(1)], ...
    'EdgeColor', 'k', 'LineStyle', '--');

% Plot the input points
plot(x, y, 'bo', 'MarkerFaceColor', 'b');

% Plot the convex hull boundary
plot(x(hullIdx), y(hullIdx), 'r-', 'LineWidth', 2);

% Fill the no-fly zone
fill(x(hullIdx), y(hullIdx), 'r', 'FaceAlpha', 0.2, 'EdgeColor', 'none');

% Axis settings
axis([xlim ylim]);
axis equal;
title('No-Fly Zone Boundary Using convhull');
xlabel('North');
ylabel('East');

% Plot rerouted trajectory and intersection points
plot(xReroutedTrajectory, yReroutedTrajectory, 'm-', 'LineWidth', 2);
plot(xIntersections(1), yIntersections(1), 'ks', 'MarkerFaceColor', 'y', 'MarkerSize', 10); % Entry
plot(xIntersections(2), yIntersections(2), 'ks', 'MarkerFaceColor', 'c', 'MarkerSize', 10); % Exit

legend('Original Trajectory', 'Points', 'No-Fly Zone Boundary', 'No-Fly Zone', ...
       'Obstacle-free Trajectory', 'Entry', 'Exit', 'Location', 'bestoutside');
hold off;

Figure contains an axes object. The axes object with title No-Fly Zone Boundary Using convhull, xlabel North, ylabel East contains 8 objects of type line, rectangle, patch. One or more of the lines displays its values using only markers These objects represent Original Trajectory, Points, No-Fly Zone Boundary, No-Fly Zone, Obstacle-free Trajectory, Entry, Exit.

clearvars -except Vehicle1Traj reroutedTrajectory

See Also

Topics