From 0dfbd39c6c537bd41ad3e644e44e0c5c98176f43 Mon Sep 17 00:00:00 2001 From: raghumanimehta Date: Sat, 21 Jun 2025 11:18:19 -0700 Subject: [PATCH 1/5] improved gps reference --- .../local_pathfinding/visualizer.py | 21 ++++++++++++++----- src/website/package-lock.json | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/local_pathfinding/local_pathfinding/visualizer.py b/src/local_pathfinding/local_pathfinding/visualizer.py index f482749b0..9577e930d 100644 --- a/src/local_pathfinding/local_pathfinding/visualizer.py +++ b/src/local_pathfinding/local_pathfinding/visualizer.py @@ -23,7 +23,7 @@ import plotly.graph_objects as go from dash import dcc, html from dash.dependencies import Input, Output - +import math import local_pathfinding.coord_systems as cs app = dash.Dash(__name__) @@ -190,13 +190,24 @@ def live_update_plot(state: VisualizerState) -> go.Figure: name="Intermediate", ) + goal_x = [state.final_local_wp_x[-1]] + goal_y = [state.final_local_wp_y[-1]] + boat_x = [state.sailbot_pos_x[-1]] + boat_y = [state.sailbot_pos_y[-1]] + angle_from_boat = math.atan2(goal_x[0] - boat_x[0], goal_y[0] - boat_y[0]) + angle_degrees = math.degrees(angle_from_boat) + # goal local waypoint goal_trace = go.Scatter( - x=[state.final_local_wp_x[-1]], - y=[state.final_local_wp_y[-1]], + x=goal_x, + y=goal_y, mode="markers", marker=dict(color="red", size=10), name="Goal", + hovertemplate="X: %{x:.2f}
" + + "Y: %{y:.2f}
" + + "Angle from the boat: " + f"{angle_degrees:.1f}°" + + "" ) # boat marker (current position) @@ -211,8 +222,8 @@ def live_update_plot(state: VisualizerState) -> go.Figure: marker_size=15, name="Boat", hovertemplate="🚢 Sailbot Current Position
" + - "X: %{x:.2f} meters
" + - "Y: %{y:.2f} meters
" + + "X: %{x:.2f}
" + + "Y: %{y:.2f}
" + "Heading: " + f"{state.sailbot_gps[-1].heading.heading:.1f}°
" + "Speed: " + f"{state.sailbot_gps[-1].speed.speed:.1f}
" + "" diff --git a/src/website/package-lock.json b/src/website/package-lock.json index c5e274418..1fa06270c 100644 --- a/src/website/package-lock.json +++ b/src/website/package-lock.json @@ -23,7 +23,7 @@ "leaflet": "^1.9.4", "leaflet-defaulticon-compatibility": "^0.1.2", "leaflet-geometryutil": "^0.10.2", - "mongodb": "^4.8.1", + "mongodb": "^4.17.2", "mongoose": "^7.5.0", "next": "^14.1.3", "react": "^18.2.0", From 9c86702e9628e6b01f97be2596fe9bd37646c5df Mon Sep 17 00:00:00 2001 From: raghumanimehta Date: Sat, 21 Jun 2025 13:13:32 -0700 Subject: [PATCH 2/5] added moving boat marker --- .../local_pathfinding/coord_systems.py | 17 ++++++++++ .../local_pathfinding/visualizer.py | 33 ++++++++++++------- .../test/test_coord_systems.py | 23 +++++++++++++ 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/local_pathfinding/local_pathfinding/coord_systems.py b/src/local_pathfinding/local_pathfinding/coord_systems.py index 75af9ee3a..36b5779a4 100644 --- a/src/local_pathfinding/local_pathfinding/coord_systems.py +++ b/src/local_pathfinding/local_pathfinding/coord_systems.py @@ -34,6 +34,23 @@ def cartesian_to_true_bearing(cartesian: float) -> float: return (90 - cartesian + 360) % 360 +def true_bearing_to_plotly_cartesian(true_bearing: float) -> float: + """Convert a true bearing angle to the equivalent cartesian angle . + + Args: + true_bearing (float): Angle where 0 is true north. Range: -180 < heading <= 180. + Increases in the clockwise direction till 180 degrees. + Decreases in the counter-clockwise direction till -180 (exclusive) + Returns: + float: Angle where 0 is north and values increase counter-clockwise. + """ + assert -180 < true_bearing <= 180 + + if -180 < true_bearing < 0: + true_bearing += 360.0 + return true_bearing + + def meters_to_km(meters: float) -> float: return meters / 1000 diff --git a/src/local_pathfinding/local_pathfinding/visualizer.py b/src/local_pathfinding/local_pathfinding/visualizer.py index 9577e930d..eb658a404 100644 --- a/src/local_pathfinding/local_pathfinding/visualizer.py +++ b/src/local_pathfinding/local_pathfinding/visualizer.py @@ -210,25 +210,34 @@ def live_update_plot(state: VisualizerState) -> go.Figure: "" ) - # boat marker (current position) boat_trace = go.Scatter( x=[state.sailbot_pos_x[-1]], y=[state.sailbot_pos_y[-1]], mode="markers", - marker_symbol="arrow", - marker_line_color="darkseagreen", - marker_color="lightgreen", - marker_line_width=2, - marker_size=15, name="Boat", - hovertemplate="🚢 Sailbot Current Position
" + - "X: %{x:.2f}
" + - "Y: %{y:.2f}
" + - "Heading: " + f"{state.sailbot_gps[-1].heading.heading:.1f}°
" + - "Speed: " + f"{state.sailbot_gps[-1].speed.speed:.1f}
" + - "" + hovertemplate=( + "🚢 Sailbot Current Position
" + "X: %{x:.2f}
" + "Y: %{y:.2f}
" + "Heading: " + + f"{state.sailbot_gps[-1].heading.heading:.1f}°
" + f"Speed: {state.sailbot_gps[-1].speed.speed:.1f}
" + "" + ), + marker=dict( + symbol="arrow-wide", + line_color="darkseagreen", + color="lightgreen", + line_width=2, + size=15, + angleref="up", + angle=cs.true_bearing_to_plotly_cartesian( + state.sailbot_gps[-1].heading.heading + ) + ) ) + # Add all traces to the figure fig.add_trace(intermediate_trace) fig.add_trace(goal_trace) diff --git a/src/local_pathfinding/test/test_coord_systems.py b/src/local_pathfinding/test/test_coord_systems.py index fae36e0b1..0d00aaf36 100644 --- a/src/local_pathfinding/test/test_coord_systems.py +++ b/src/local_pathfinding/test/test_coord_systems.py @@ -23,6 +23,29 @@ def test_cartesian_to_true_bearing(cartesian: float, true_bearing: float): ), "incorrect angle conversion" +@pytest.mark.parametrize( + "true_bearing, plotly_cartesian", + [ + (0.0, 0.0), + (-90.0, 270.0), + (180.0, 180.0), + (90.0, 90.0), + (45.0, 45.0), + (-45.0, 315.0), + (135.0, 135.0), + (-135.0, 225.0), + (1.0, 1.0), + (-1.0, 359.0), + (-179.0, 181.0), + (179.0, 179.0), + ], +) +def test_true_bearing_to_plotly_cartesian(true_bearing: float, plotly_cartesian: float): + assert cs.true_bearing_to_plotly_cartesian(true_bearing) == pytest.approx( + plotly_cartesian + ), "incorrect angle conversion" + + @pytest.mark.parametrize( "meters,km", [(0.0, 0.0), (30, 0.03), (500, 0.5), (-30.5, -0.0305), (-0.0, 0.0)], From 84c9b92dc33e893a57f93900c067f3b52e7f9fb2 Mon Sep 17 00:00:00 2001 From: raghumanimehta Date: Sat, 21 Jun 2025 13:21:04 -0700 Subject: [PATCH 3/5] added moving boat marker --- src/local_pathfinding/local_pathfinding/coord_systems.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/local_pathfinding/local_pathfinding/coord_systems.py b/src/local_pathfinding/local_pathfinding/coord_systems.py index 36b5779a4..ff61786cd 100644 --- a/src/local_pathfinding/local_pathfinding/coord_systems.py +++ b/src/local_pathfinding/local_pathfinding/coord_systems.py @@ -46,9 +46,10 @@ def true_bearing_to_plotly_cartesian(true_bearing: float) -> float: """ assert -180 < true_bearing <= 180 + plotly_cartesian = true_bearing if -180 < true_bearing < 0: - true_bearing += 360.0 - return true_bearing + plotly_cartesian += 360.0 + return plotly_cartesian def meters_to_km(meters: float) -> float: From 28a7694de4067faf95a2e7f3742b4e71ed970ace Mon Sep 17 00:00:00 2001 From: Akshanjay Kompelli <63443017+FireBoyAJ24@users.noreply.github.com> Date: Sat, 21 Jun 2025 16:51:18 -0700 Subject: [PATCH 4/5] Flake8 Linting --- .../local_pathfinding/visualizer.py | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/local_pathfinding/local_pathfinding/visualizer.py b/src/local_pathfinding/local_pathfinding/visualizer.py index eb658a404..3c1052774 100644 --- a/src/local_pathfinding/local_pathfinding/visualizer.py +++ b/src/local_pathfinding/local_pathfinding/visualizer.py @@ -15,6 +15,7 @@ Call the `dash_app` function with a multiprocessing shared Manager.queue to start the Dash app. """ +import math from multiprocessing import Queue from typing import List, Optional, Tuple @@ -23,7 +24,7 @@ import plotly.graph_objects as go from dash import dcc, html from dash.dependencies import Input, Output -import math + import local_pathfinding.coord_systems as cs app = dash.Dash(__name__) @@ -204,10 +205,11 @@ def live_update_plot(state: VisualizerState) -> go.Figure: mode="markers", marker=dict(color="red", size=10), name="Goal", - hovertemplate="X: %{x:.2f}
" + - "Y: %{y:.2f}
" + - "Angle from the boat: " + f"{angle_degrees:.1f}°" + - "" + hovertemplate="X: %{x:.2f}
" + + "Y: %{y:.2f}
" + + "Angle from the boat: " + + f"{angle_degrees:.1f}°" + + "", ) boat_trace = go.Scatter( @@ -219,8 +221,7 @@ def live_update_plot(state: VisualizerState) -> go.Figure: "🚢 Sailbot Current Position
" "X: %{x:.2f}
" "Y: %{y:.2f}
" - "Heading: " + - f"{state.sailbot_gps[-1].heading.heading:.1f}°
" + "Heading: " + f"{state.sailbot_gps[-1].heading.heading:.1f}°
" f"Speed: {state.sailbot_gps[-1].speed.speed:.1f}
" "" ), @@ -231,13 +232,10 @@ def live_update_plot(state: VisualizerState) -> go.Figure: line_width=2, size=15, angleref="up", - angle=cs.true_bearing_to_plotly_cartesian( - state.sailbot_gps[-1].heading.heading - ) - ) + angle=cs.true_bearing_to_plotly_cartesian(state.sailbot_gps[-1].heading.heading), + ), ) - # Add all traces to the figure fig.add_trace(intermediate_trace) fig.add_trace(goal_trace) @@ -285,12 +283,14 @@ def animated_update_plot(state: VisualizerState) -> go.Figure: marker_size=15, text=["Boat"], name="Boat", - hovertemplate="🚢 Sailbot Current Position
" + - "X: %{x:.2f} meters
" + - "Y: %{y:.2f} meters
" + - "Heading: " + f"{state.sailbot_gps[0].heading.heading:.1f}°
" + - "Speed: " + f"{state.sailbot_gps[0].speed.speed:.1f}
" + - "" + hovertemplate="🚢 Sailbot Current Position
" + + "X: %{x:.2f} meters
" + + "Y: %{y:.2f} meters
" + + "Heading: " + + f"{state.sailbot_gps[0].heading.heading:.1f}°
" + + "Speed: " + + f"{state.sailbot_gps[0].speed.speed:.1f}
" + + "", ) initial_state = [ go.Scatter( @@ -358,12 +358,14 @@ def animated_update_plot(state: VisualizerState) -> go.Figure: marker_size=15, text=["Boat"], name="Boat", - hovertemplate="🚢 Sailbot Current Position
" + - "X: %{x:.2f} meters
" + - "Y: %{y:.2f} meters
" + - "Heading: " + f"{state.sailbot_gps[i].heading.heading:.1f}°
" + - "Speed: " + f"{state.sailbot_gps[i].speed.speed:.1f}
" + - "" + hovertemplate="🚢 Sailbot Current Position
" + + "X: %{x:.2f} meters
" + + "Y: %{y:.2f} meters
" + + "Heading: " + + f"{state.sailbot_gps[i].heading.heading:.1f}°
" + + "Speed: " + + f"{state.sailbot_gps[i].speed.speed:.1f}
" + + "", ) ], name=f"Boat {i}", From 3a2316e481f58c741b84df1e0d9d9cb19a054af8 Mon Sep 17 00:00:00 2001 From: Raghumani Mehta <115026448+raghumanimehta@users.noreply.github.com> Date: Sat, 21 Jun 2025 23:33:27 -0700 Subject: [PATCH 5/5] Fixed documentation for true_bearing_to_plotly_cartesian --- src/local_pathfinding/local_pathfinding/coord_systems.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/local_pathfinding/local_pathfinding/coord_systems.py b/src/local_pathfinding/local_pathfinding/coord_systems.py index ff61786cd..69681de2f 100644 --- a/src/local_pathfinding/local_pathfinding/coord_systems.py +++ b/src/local_pathfinding/local_pathfinding/coord_systems.py @@ -42,7 +42,7 @@ def true_bearing_to_plotly_cartesian(true_bearing: float) -> float: Increases in the clockwise direction till 180 degrees. Decreases in the counter-clockwise direction till -180 (exclusive) Returns: - float: Angle where 0 is north and values increase counter-clockwise. + float: Angle where 0 is north and values increases clockwise. """ assert -180 < true_bearing <= 180