diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index ae0eec32e..cae6c5f1e 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -33,6 +33,32 @@ jobs:
- id: check_skip
uses: fkirc/skip-duplicate-actions@v5
+ ubuntu-22-test:
+ name: Ensure Ubuntu 22 is prohibited
+ runs-on: ubuntu-22.04
+ needs: avoid-duplicate-ci
+ if: needs.avoid-duplicate-ci.outputs.should_skip != 'true'
+ steps:
+ - name: Check out code from GitHub
+ uses: actions/checkout@v4
+ - name: Ensure install script fails
+ run: |
+ cd $GITHUB_WORKSPACE
+ ./scripts/install.sh && exit 1 || exit 0
+
+ ubuntu-24-test:
+ name: Ensure Ubuntu 24 is prohibited
+ runs-on: ubuntu-24.04
+ needs: avoid-duplicate-ci
+ if: needs.avoid-duplicate-ci.outputs.should_skip != 'true'
+ steps:
+ - name: Check out code from GitHub
+ uses: actions/checkout@v4
+ - name: Ensure install script fails
+ run: |
+ cd $GITHUB_WORKSPACE
+ ./scripts/install.sh && exit 1 || exit 0
+
super-ci:
name: Run tests and build docs
needs: avoid-duplicate-ci
diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml
index 3c61c272e..37b4ce2d1 100644
--- a/.github/workflows/docs.yaml
+++ b/.github/workflows/docs.yaml
@@ -38,7 +38,7 @@ jobs:
mkdir -p ${{ github.workspace }}/pr-docs/
- name: Download artifact
- uses: dawidd6/action-download-artifact@v2
+ uses: dawidd6/action-download-artifact@v6
if: github.event.action != 'closed'
with:
github_token: ${{ secrets.INVESTIGATOR_BOT_TOKEN }}
diff --git a/NaviGator/mission_control/navigator_launch/config/pcodar_vrx.yaml b/NaviGator/mission_control/navigator_launch/config/pcodar_vrx.yaml
index 582682cc9..85bfcaf07 100644
--- a/NaviGator/mission_control/navigator_launch/config/pcodar_vrx.yaml
+++ b/NaviGator/mission_control/navigator_launch/config/pcodar_vrx.yaml
@@ -28,4 +28,4 @@ intensity_filter_max_intensity: 1
# yamllint disable-line rule:line-length
# classifications: ["buoy", "dock", "stc_platform", "red_totem", "green_totem", "blue_totem", "yellow_totem", "black_totem", "surmark46104", "surmark950400", "surmark950410", "UNKNOWN"]
# yamllint disable-line rule:line-length
-classifications: ["mb_marker_buoy_red", "mb_marker_buoy_green", "mb_marker_buoy_black", "mb_marker_buoy_white", "mb_round_buoy_black", "mb_round_buoy_orange", "stc_platform", "red_python_buoy", "blue_manatee_buoy", "green_iguana_buoy", "UNKNOWN"]
+classifications: ["mb_marker_buoy_red", "mb_marker_buoy_green", "mb_marker_buoy_black", "mb_marker_buoy_white", "mb_round_buoy_black", "mb_round_buoy_orange", "stc_platform", "red_python_buoy", "blue_manatee_buoy", "green_iguana_buoy", "black_cylinder", "white_cylinder", "red_cylinder", "green_cylinder", "UNKNOWN"]
diff --git a/NaviGator/mission_control/navigator_launch/config/poi_sim.yaml b/NaviGator/mission_control/navigator_launch/config/poi_sim.yaml
index 2a27948a7..b50413ccc 100644
--- a/NaviGator/mission_control/navigator_launch/config/poi_sim.yaml
+++ b/NaviGator/mission_control/navigator_launch/config/poi_sim.yaml
@@ -1,10 +1,8 @@
---
global_frame: enu
initial_pois:
- wildlife: [26.09821319580078, 59.91523361206055, 0.0]
- dock: [108.05, -1.07, 0.0]
- entrance_gate: [51.28, -48.69, 0.0]
- obstacle_course: [-32.803, -83.41, 0.0]
- ring_challenge: [61.271873474121094, 15.894840240478516, 0.0]
- start_gate: [12.75, 0.433, 0.0]
- stc: [49.49, -82.65, 0.0]
+ wildlife: [-1.7053, 44.9246, 0.0]
+ docking: [-3.24, 58.64265, 0.0]
+ entrance_gate: [22.87, 8.66, 0.0]
+ navigation: [46.6878, 23.3085, 0.0]
+ scan_the_code: [29.868, 44.1452, 0.0]
diff --git a/NaviGator/mission_control/navigator_launch/launch/robotx_comms.launch b/NaviGator/mission_control/navigator_launch/launch/robotx_comms.launch
index 6495fd37c..a901a68fa 100644
--- a/NaviGator/mission_control/navigator_launch/launch/robotx_comms.launch
+++ b/NaviGator/mission_control/navigator_launch/launch/robotx_comms.launch
@@ -2,9 +2,9 @@
-
+
-
+
diff --git a/NaviGator/mission_control/navigator_missions/navigator_missions/autonomous_2024.py b/NaviGator/mission_control/navigator_missions/navigator_missions/autonomous_2024.py
index d1ff9007d..70afa21b5 100644
--- a/NaviGator/mission_control/navigator_missions/navigator_missions/autonomous_2024.py
+++ b/NaviGator/mission_control/navigator_missions/navigator_missions/autonomous_2024.py
@@ -1,14 +1,11 @@
from __future__ import annotations
import asyncio
+import datetime
-import rospy
-
-from .docking import Docking
from .entrance_gate2 import EntranceGate2
-from .navigation import Navigation
+from .go_to_poi import GoToPOI
from .navigator import NaviGatorMission
-from .scan_the_code import ScanTheCodeMission
from .wildlife import Wildlife
@@ -17,28 +14,69 @@ class Autonomous2024(NaviGatorMission):
# timeout (in secs)
TIMEOUT = 180
- async def run_mission(self, mission_cls: type[NaviGatorMission], name: str):
- rospy.loginfo(f"[autonomous] beginning {name}...")
+ async def run_mission(
+ self,
+ mission_cls: type[NaviGatorMission],
+ name: str,
+ *args,
+ str_arg: str = "",
+ **kwargs,
+ ):
+ # self.send_feedback(f"beginning {name}...")
try:
- await asyncio.wait_for(mission_cls().run(""), self.TIMEOUT)
+ await asyncio.wait_for(
+ mission_cls().run(str_arg, *args, **kwargs),
+ self.TIMEOUT,
+ )
except asyncio.TimeoutError:
- rospy.logwarn(f"[autonomous] ran out of time on {name}!")
+ self.send_feedback(f"!!! ran out of time on {name}!")
+
+ async def go_to_poi(self, name: str):
+ await self.run_mission(GoToPOI, f"go to {name} poi", str_arg=name)
+
+ def time_elapsed(self) -> str:
+ last_min, last_sec = divmod(
+ (datetime.datetime.now() - self._last_checkpoint).total_seconds(),
+ 60,
+ )
+ min, sec = divmod(
+ (datetime.datetime.now() - self.start_time).total_seconds(),
+ 60,
+ )
+ self._last_checkpoint = datetime.datetime.now()
+ return f"{int(min)}m {int(sec)}s (+{int(last_min)}m {int(last_sec)}s)"
+
+ def send_feedback(self, msg: str):
+ super().send_feedback(f"[autonomous, {self.time_elapsed()}] {msg}")
async def run(self, args: str):
- # Step 1: Entrance and exit gates
- await self.run_mission(EntranceGate2, "entrance gate")
+ # Step 1: Entrance gate
+ self.start_time = datetime.datetime.now()
+ self._last_checkpoint = self.start_time
+ self.send_feedback("proceeding to entrance gate...")
+ await self.go_to_poi("entrance_gate")
+ self.send_feedback("starting entrance gate task...")
+ await self.run_mission(
+ EntranceGate2,
+ "entrance gate",
+ scan_code=True,
+ return_to_start=False,
+ circle=False,
+ )
# Step 2: Scan the Code
- await self.run_mission(ScanTheCodeMission, "scan the code")
+ # await self.run_mission(ScanTheCodeMission, "scan the code")
# Step 3: Wildlife Mission
+ self.send_feedback("going to wildlife poi...")
+ await self.go_to_poi("wildlife")
+ self.send_feedback("running wildlife mission...")
await self.run_mission(Wildlife, "wildlife")
# Step 4: Navigation Mission
- await self.run_mission(Navigation, "navigation")
+ # await self.run_mission(Navigation, "navigation")
# Step 5: Dock Mission
- await self.run_mission(Docking, "docking")
+ # await self.run_mission(Docking, "docking")
- # Step 6: UAV Mission
- pass
+ # Step 6: Exit through the same gate
diff --git a/NaviGator/mission_control/navigator_missions/navigator_missions/entrance_gate2.py b/NaviGator/mission_control/navigator_missions/navigator_missions/entrance_gate2.py
index a025b9b69..33acb2391 100644
--- a/NaviGator/mission_control/navigator_missions/navigator_missions/entrance_gate2.py
+++ b/NaviGator/mission_control/navigator_missions/navigator_missions/entrance_gate2.py
@@ -9,10 +9,14 @@
class EntranceGate2(NaviGatorMission):
- async def run(self, args):
- # Parameters:
- scan_code = False
- return_to_start = True
+ async def run(
+ self,
+ args,
+ *,
+ scan_code: bool = False,
+ return_to_start: bool = True,
+ circle: bool = True,
+ ):
circle_radius = 5
circle_direction = "cw"
yaw_offset = 1.57
@@ -52,7 +56,7 @@ async def run(self, args):
if scan_code:
pass
- elif return_to_start:
+ elif return_to_start and circle:
# Approach buoy we will rotate around
buoy = await self.get_sorted_objects("black_cylinder", n=1)
buoy = buoy[1][0]
@@ -78,8 +82,9 @@ async def run(self, args):
yaw_offset,
)
+ if return_to_start:
# Go back through start gate
- self.send_feedback("Navigating through gate")
+ self.send_feedback("Navigating through original gate")
await self.move.set_position(traversal_points[1]).look_at(
traversal_points[0],
).go()
diff --git a/mil_common/utils/mil_poi/mil_poi/server.py b/mil_common/utils/mil_poi/mil_poi/server.py
index 763fd2131..728762d56 100644
--- a/mil_common/utils/mil_poi/mil_poi/server.py
+++ b/mil_common/utils/mil_poi/mil_poi/server.py
@@ -7,12 +7,13 @@
import rospy
import tf2_ros
-from geometry_msgs.msg import Point, PointStamped, Pose, Quaternion
+from geometry_msgs.msg import Point, Pose, Quaternion
from interactive_markers.interactive_marker_server import InteractiveMarkerServer
from mil_ros_tools.msg_helpers import numpy_to_point
from mil_tools import thread_lock
from std_srvs.srv import Trigger, TriggerRequest, TriggerResponse
from tf.transformations import euler_from_quaternion
+from tf2_geometry_msgs import PointStamped
from visualization_msgs.msg import (
InteractiveMarker,
InteractiveMarkerControl,
diff --git a/scripts/install.sh b/scripts/install.sh
index fbef4dbbe..ca93a70bd 100755
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -20,6 +20,22 @@ if [[ -z ${TERM} ]]; then
clear
fi
+# Before even starting, check if using Ubuntu 20.04
+NAME=$(awk -F= '/^NAME/{print $2}' /etc/os-release)
+VERSION=$(awk -F'=' '/^VERSION=/{print $2}' /etc/os-release)
+if [[ $NAME != *"Ubuntu"* ]]; then
+ printf "${Red}This script is only supported on Ubuntu (you're using: ${NAME}). Please install Ubuntu 20.04.${Res}\n"
+ exit 1
+fi
+if [[ $VERSION != *"20.04"* ]]; then
+ printf "${Red}This script is only supported on Ubuntu 20.04 (you're using: ${VERSION}). Please install Ubuntu 20.04.${Res}\n"
+ exit 1
+fi
+if [[ $(grep -i Microsoft /proc/version) ]]; then
+ printf "${Red}Using WSL is not supported, due to graphical issues with our simulation environment. Please dual-boot your computer, or use a virtual machine.${Res}\n"
+ exit 1
+fi
+
# Display header
cat <