Need help with waypoint navigation code
댓글 수: 4
답변 (1개)
1 개 추천
Hi @SM,
To address your query about the waypoint navigation code and its issues, I have broken down the problem, analyzed the code, and providing a comprehensive solution. So, you are trying to simulate the movement of an RC boat that navigates between waypoints based on its current location. The challenge arises from an error during execution due to incorrect indexing, as well as a misunderstanding of how to effectively manage the waypoint navigation logic.
Key Issues Identified
Indexing Errors: The original line lat2(i, 1) and lon2(i, 1) leads to an index out-of-bounds error because lat2 and lon2 are scalar values (not arrays).
Logic for Waypoint Navigation: The use of a for-loop with manual index increment can lead to unpredictable behavior. Instead, a while-loop is more appropriate for continuously checking conditions.
Distance Threshold Logic: The condition if s < 5 was incorrectly implemented; it should check the specific distance to the current waypoint rather than comparing the entire vector. The revised version of your code improves upon these points by:
- Correctly indexing latitude and longitude when calling your custom function.
- Implementing a while-loop that allows continuous navigation until all waypoints are reached.
- Ensuring that distance checks are performed correctly on individual waypoint distances.
Here is the modified version of your waypoint navigation function:
function [s, bearing] = waypoint_navigation(lat1, lon1, waypoints)
% Check for sufficient input arguments
if nargin < 3
error('Not enough input arguments. Provide latitude, longitude, and
waypoints.');
end % Initialize output arrays
s = zeros(1, length(waypoints)); % Preallocate distance array
bearing = zeros(1, length(waypoints)); % Preallocate bearing array
R = 6371e3; % Earth's radius in meters
lat1 = deg2rad(lat1);
lon1 = deg2rad(lon1); % Initialize waypoint index
i = 1;
while true % Infinite loop to continuously navigate waypoints
% Get the current waypoint coordinates
lat2 = deg2rad(waypoints(i, 1));
lon2 = deg2rad(waypoints(i, 2)); % Calculate distance and bearing using the custom function
[s(i), bearing(i)] = haversine_distance_and_bearing(lat1, lon1, lat2,
lon2); % Check if the distance to the current waypoint is less than 5 meters
if s(i) < 5
% Move to the next waypoint
i = i + 1;
% Loop back to the first waypoint if at the last waypoint
if i > length(waypoints)
i = 1; % Reset to the first waypoint
end
end % Optional: Add a break condition to avoid infinite loop during testing
if i == 1 && all(s < 5) % Break if all waypoints are reached
break;
end % Update the current position to the last waypoint reached
lat1 = lat2;
lon1 = lon2;
end % Plotting waypoints after navigation loop (optional)
figure;
hold on;
plot(waypoints(:, 2), waypoints(:, 1), 'ro', 'MarkerSize', 10, 'DisplayName',
'Waypoints');
plot(rad2deg(lon1), rad2deg(lat1), 'bo', 'MarkerSize', 10, 'DisplayName',
'Current Position');
xlabel('Longitude');
ylabel('Latitude');
title('Waypoint Navigation Path');
legend;
grid on;
hold off;
endfunction [distance, bearing] = haversine_distance_and_bearing(lat1, lon1, lat2, lon2) dlat = lat2 - lat1; dlon = lon2 - lon1;
a = sin(dlat/2)^2 + cos(lat1) * cos(lat2) * sin(dlon/2)^2;
c = 2 * atan2(sqrt(a), sqrt(1-a)); R = 6371e3; % Radius of Earth in meters
distance = R * c; % Distance in meters bearing = atan2(sin(dlon) * cos(lat2), cos(lat1) * sin(lat2) - sin(lat1) *
cos(lat2) * cos(dlon));
bearing = rad2deg(bearing);
bearing = mod(bearing + 360, 360);
endfunction test_waypoint_navigation() start_lat = 37.7749; start_lon = -122.4194;
waypoints = [
37.7750, -122.4183;
37.7760, -122.4170;
37.7770, -122.4160
];[distances, bearings] = waypoint_navigation(start_lat, start_lon, waypoints);
disp('Distances to waypoints (meters):');
disp(distances); disp('Bearings to waypoints (degrees):');
disp(bearings);
endtest_waypoint_navigation();
Please see attached.


In summary, the waypoint_navigation function takes the initial latitude and longitude, along with a matrix of waypoints, to compute the distance and bearing to each waypoint. It first checks for sufficient input arguments and initializes output arrays for distances (s) and bearings. The Earth's radius is defined, and the input coordinates are converted from degrees to radians. An infinite loop is employed to navigate through the waypoints. For each waypoint, the function haversine_distance_and_bearing is called to calculate the distance and bearing from the current position to the waypoint. If the distance to a waypoint is less than 5 meters, the function moves to the next waypoint. The loop continues until all waypoints are reached, at which point a plot visualizes the waypoints and the current position.
The haversine_distance_and_bearing function computes the great-circle distance and bearing using the Haversine formula, ensuring accurate navigation over the Earth's surface.
Finally, the test_waypoint_navigation function demonstrates the usage of the main function with sample coordinates.
If you have any further questions, please let us know.
댓글 수: 6
Hi @SM,
I was not able to open your “Test_PlantID.slx “ since I am using Matlab Mobile version. However, going through documentation provided at the link below,
https://www.mathworks.com/help/simulink/slref/matlabfunction.html
I was able to understand your concerns regarding to implementing your waypoint navigation functionality in Simulink while addressing the issues you've faced, so, based on that I will focus on two primary objectives:
Visualizing the Navigation Path: need to ensure that the waypoints and current position are plotted correctly within your Simulink model.
Implementing Break Conditions: adapt your MATLAB logic to check if all waypoints have been reached using Simulink blocks.
MATLAB Function Block Implementation
Create a MATLAB Function block in your Simulink model. Here is how you can redefine your waypoint_navigation function:
function [distances, bearings, waypoint_index] =
waypoint_navigation(lat1,
lon1, waypoints)
persistent index; % Persistent variable to track the
waypoint index if isempty(index)
index = 1; % Initialize the index on first call
end R = 6371e3; % Earth's radius in meters
lat1 = deg2rad(lat1);
lon1 = deg2rad(lon1); lat2 = deg2rad(waypoints(index, 1));
lon2 = deg2rad(waypoints(index, 2)); % Calculate distance and bearing
[distances, bearings] = haversine_distance_and_bearing(lat1,
lon1, lat2, lon2); % Check if we have reached the waypoint
if distances < 5
index = index + 1; % Move to next waypoint
if index > size(waypoints, 1)
index = 1; % Reset to first waypoint
end
endwaypoint_index = index; % Output current waypoint index end
function [distance, bearing] =
haversine_distance_and_bearing(lat1, lon1,
lat2, lon2)
dlat = lat2 - lat1;
dlon = lon2 - lon1;
a = sin(dlat/2)^2 + cos(lat1) * cos(lat2) * sin(dlon/2)^2;
c = 2 * atan2(sqrt(a), sqrt(1-a));
R = 6371e3; % Radius of Earth in meters
distance = R * c; % Distance in meters
bearing = atan2(sin(dlon) * cos(lat2), cos(lat1) * sin(lat2)
- sin(lat1) *
cos(lat2) * cos(dlon));
bearing = rad2deg(bearing);
bearing = mod(bearing + 360, 360);
endThis code utilizes a persistent variable index to keep track of which waypoint is currently being approached. The output variables include distances, bearings, and the current waypoint_index.
Simulink Blocks Setup
Input Ports: Create input ports for initial latitude and longitude.
Output Ports: Set up output ports for distances, bearings, and waypoint indices. Use a Scope block or a MATLAB Function block for plotting the waypoints against the current position.
Implementing Break Conditions
To implement the break condition (checking if all distances are less than 5 meters), you can use logical blocks:
- Add a logical block that checks if all outputs from the distance calculation are less than 5 meters.
- Use an "AND" block to combine these conditions into a single output signal that can trigger stopping or resetting behaviors in your model.
Testing Your Model
After setting up your model
- Connect the output of your MATLAB Function block to either a Display or Scope block for visual confirmation.
- Ensure that you run multiple simulations with varying waypoints to validate both the navigation logic and visualization accuracy.
Utilize breakpoints within the MATLAB Function block editor to step through your code and monitor variable values during simulation. If you notice performance issues with large datasets or complex navigation paths, consider optimizing by pre-calculating static values (like converted radians) outside of frequently called loops.
Hope this helps.
If further issues arise or specific scenarios need addressing, please feel free to reach out!
Hi @SM,
Let me break down your code and identify potential issues that could be causing this behavior:
Waypoint Index Update Logic: Your code attempts to update the index variable based on whether the distance to the current waypoint is less than or equal to 5 meters. However, there may be a logical flaw in how you're checking and updating this index.
Distance Calculation: The line where you check if s <= 5 is not correctly indexed because s is initialized as a zeros array. You should be checking the distance to the current waypoint, which is s(index) instead.
Looping Back to Start: Ensure that your indexing logic correctly wraps around when reaching the end of the waypoints array. The current check if index+1 > length(waypoints) might lead to an off-by-one error.
Here is a revised version of your function with corrections:
function [s_initial, bearing_initial, s, bearing, waypoint_index] =
waypoint_navigation(lat1, lon1, waypoints)
persistent index; % Persistent variable to track the waypoint
index
if isempty(index)
index = 1; % Initialize index
end
lat2 = waypoints(:,1);
lon2 = waypoints(:,2); % Initial distance and bearing from current location to 1st
waypoint
[s_initial, bearing_initial] =
haversine_distance_and_bearing(lat1, lon1,
waypoints(1,1), waypoints(1,2)); % Calculate distance and bearing to next waypoint
s = zeros(1);
bearing = zeros(1); if index < length(waypoints) % Ensure we do not exceed bounds
[s(index), bearing(index)] =
haversine_distance_and_bearing(waypoints(index,1),
waypoints(index,2),
waypoints(index+1,1), waypoints(index+1,2));
else
[s(index), bearing(index)] =
haversine_distance_and_bearing(waypoints(index,1),
waypoints(index,2),
waypoints(1,1), waypoints(1,2)); % Loop back to start if at
last waypoint
end % Check if we have reached the current waypoint
if s(index) <= 5 % Check distance to current waypoint
index = index + 1; % Move to next waypoint if index > length(waypoints) % Loop back if at last
waypoint
index = 1;
end
end waypoint_index = index; % Output current waypoint index end
function [s, bearing] = haversine_distance_and_bearing(lat1, lon1, lat2, lon2) R = 6371000; % Radius of Earth in meters lat1 = deg2rad(lat1); lon1 = deg2rad(lon1); lat2 = deg2rad(lat2); lon2 = deg2rad(lon2);
dlat = lat2 - lat1;
dlon = lon2 - lon1; a = sin(dlat / 2)^2 + cos(lat1) * cos(lat2) * sin(dlon / 2)^2;
c = 2 * atan2(sqrt(a), sqrt(1 - a));s = R * c; % Distance in meters
y = sin(dlon) * cos(lat2);
x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlon); bearing_rad = atan2(y, x);
bearing = rad2deg(bearing_rad); % Convert from radians to
degrees
endMake sure you test your updated function with various sets of waypoints. This will help confirm that it behaves as expected across different scenarios. Consider adding debug statements (e.g., disp() or logging) within your function to track values of key variables like s, index, and bearings during execution. Also, when integrating with Simulink blocks, ensure that you properly set up input and output ports for your function block.
This adjusted approach should help you move seamlessly from one waypoint to another after reaching your initial target. Keep iterating on your design based on real-world testing!
카테고리
도움말 센터 및 File Exchange에서 Axes Transformations에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!