Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 91 additions & 49 deletions bootcamp_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"""

import multiprocessing as mp
import queue
import time

from pymavlink import mavutil
Expand All @@ -22,100 +21,143 @@
from utilities.workers import worker_controller
from utilities.workers import worker_manager


# MAVLink connection
CONNECTION_STRING = "tcp:localhost:12345"

# =================================================================================================
# ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓
# =================================================================================================
# Set queue max sizes (<= 0 for infinity)

# Set worker counts
QUEUE_SIZE = 10

NUM_HEARTBEAT_SENDERS = 1
NUM_HEARTBEAT_RECEIVERS = 1
NUM_TELEMETRY_WORKERS = 1
NUM_COMMAND_WORKERS = 1

# Any other constants
TARGET_POSITION = command.Position(10, 20, 30)

# =================================================================================================
# ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑
# =================================================================================================


def main() -> int:
"""
Main function.
"""
# Configuration settings
"""Main entry point."""

result, config = read_yaml.open_config(logger.CONFIG_FILE_PATH)
if not result:
print("ERROR: Failed to load configuration file")
return -1

# Get Pylance to stop complaining
assert config is not None

# Setup main logger
result, main_logger, _ = logger_main_setup.setup_main_logger(config)
if not result:
print("ERROR: Failed to create main logger")
return -1

# Get Pylance to stop complaining
assert main_logger is not None

# Create a connection to the drone. Assume that this is safe to pass around to all processes
# In reality, this will not work, but to simplify the bootamp, preetend it is allowed
# To test, you will run each of your workers individually to see if they work
# (test "drones" are provided for you test your workers)
# NOTE: If you want to have type annotations for the connection, it is of type mavutil.mavfile
connection = mavutil.mavlink_connection(CONNECTION_STRING)
connection.wait_heartbeat(timeout=30) # Wait for the "drone" to connect

# =============================================================================================
# ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓
# =============================================================================================
# Create a worker controller

# Create a multiprocess manager for synchronized queues

# Create queues
connection.wait_heartbeat(timeout=30)

controller = worker_controller.WorkerController()
manager = mp.Manager()

status_queue = queue_proxy_wrapper.QueueProxyWrapper(manager, QUEUE_SIZE)
telemetry_queue = queue_proxy_wrapper.QueueProxyWrapper(manager, QUEUE_SIZE)
command_queue = queue_proxy_wrapper.QueueProxyWrapper(manager, QUEUE_SIZE)

workers = []

# HEARTBEAT SENDER
workers.append(
worker_manager.WorkerManager(
heartbeat_sender_worker.heartbeat_sender_worker,
NUM_HEARTBEAT_SENDERS,
(connection, controller),
main_logger,
)
)

# HEARTBEAT RECEIVER
workers.append(
worker_manager.WorkerManager(
heartbeat_receiver_worker.heartbeat_receiver_worker,
NUM_HEARTBEAT_RECEIVERS,
(connection, controller, status_queue),
main_logger,
)
)

# TELEMETRY
workers.append(
worker_manager.WorkerManager(
telemetry_worker.telemetry_worker,
NUM_TELEMETRY_WORKERS,
(connection, controller, telemetry_queue),
main_logger,
)
)

# COMMAND
workers.append(
worker_manager.WorkerManager(
command_worker.command_worker,
NUM_COMMAND_WORKERS,
(
connection,
TARGET_POSITION,
controller,
telemetry_queue,
command_queue,
),
main_logger,
)
)

for w in workers:
w.start()

# Create worker properties for each worker type (what inputs it takes, how many workers)
# Heartbeat sender

# Heartbeat receiver
main_logger.info("Started")

# Telemetry
start_time = time.time()
run_time = 100

# Command
try:
while time.time() - start_time < run_time:

# Create the workers (processes) and obtain their managers
while not status_queue.queue.empty():
status = status_queue.queue.get()
main_logger.info(f"Heartbeat status: {status}")

# Start worker processes
if status == "Disconnected":
main_logger.error("Drone disconnected — stopping system")
raise KeyboardInterrupt

main_logger.info("Started")
while not command_queue.queue.empty():
cmd = command_queue.queue.get()
main_logger.info(cmd)

# Main's work: read from all queues that output to main, and log any commands that we make
# Continue running for 100 seconds or until the drone disconnects
time.sleep(0.1)

# Stop the processes
except KeyboardInterrupt:
main_logger.info("Shutdown requested")

controller.request_exit()
main_logger.info("Requested exit")

# Fill and drain queues from END TO START
command_queue.fill_and_drain_queue()
telemetry_queue.fill_and_drain_queue()
status_queue.fill_and_drain_queue()

main_logger.info("Queues cleared")

# Clean up worker processes
for w in workers:
w.join()

main_logger.info("Stopped")

# We can reset controller in case we want to reuse it
# Alternatively, create a new WorkerController instance

# =============================================================================================
# ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑
# =============================================================================================

return 0


Expand Down
1 change: 0 additions & 1 deletion documentation/main_multiprocess_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from utilities.workers import worker_controller
from utilities.workers import worker_manager


# Play with these numbers to see queue bottlenecks
COUNTUP_TO_ADD_RANDOM_QUEUE_MAX_SIZE = 5
ADD_RANDOM_TO_CONCATENATOR_QUEUE_MAX_SIZE = 5
Expand Down
1 change: 0 additions & 1 deletion documentation/tests/unit/test_add_or_multiply.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

import add_or_multiply


# Test functions use test fixture signature names and access class privates
# No enable
# pylint: disable=protected-access,redefined-outer-name
Expand Down
1 change: 0 additions & 1 deletion documentation/tests/unit/test_pytest_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import pytest


# Test functions use test fixture signature names and access class privates
# No enable
# pylint: disable=protected-access,redefined-outer-name
Expand Down
28 changes: 28 additions & 0 deletions logs/2026-02-12_18-40-42/command_drone_25376.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
18:40:42: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 44] Logger initialized
18:40:42: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:43: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:46: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:46: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:47: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:47: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:48: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:48: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:49: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:49: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:50: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:50: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:51: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:51: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:52: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:52: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:53: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:53: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:54: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:54: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:55: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:55: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:56: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:56: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:57: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:40:57: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 75] Received a valid command
18:41:01: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\command_drone.py | main | 82] Passed!
1 change: 1 addition & 0 deletions logs/2026-02-12_18-40-42/command_worker_1108.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
18:40:42: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\command\command_worker.py | command_worker | 37] Logger initialized
3 changes: 3 additions & 0 deletions logs/2026-02-12_18-40-42/main.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
18:40:42: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\common\modules\logger\logger_main_setup.py | setup_main_logger | 62] main logger initialized
18:40:42: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\test_command.py | main | 131] Connected!
18:40:42: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\test_command.py | read_queue | 76] CHANGE_ALTITUDE: 1
13 changes: 13 additions & 0 deletions logs/2026-02-12_18-44-26/heartbeat_receiver_drone_11844.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
18:44:27: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | main | 41] Logger initialized
18:44:27: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:44:28: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:44:29: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:44:30: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:44:31: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:44:40: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:44:41: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:44:42: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:44:43: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:44:44: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:44:46: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:44:47: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | main | 78] Passesd!
12 changes: 12 additions & 0 deletions logs/2026-02-12_18-44-26/heartbeat_receiver_worker_7668.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
18:44:27: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\heartbeat\heartbeat_receiver_worker.py | heartbeat_receiver_worker | 44] Logger initialized
18:44:27: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\heartbeat\heartbeat_receiver.py | run | 64] Connected
18:44:29: [WARNING] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\heartbeat\heartbeat_receiver.py | run | 70] Missed heartbeat
18:44:30: [WARNING] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\heartbeat\heartbeat_receiver.py | run | 70] Missed heartbeat
18:44:32: [WARNING] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\heartbeat\heartbeat_receiver.py | run | 70] Missed heartbeat
18:44:36: [ERROR] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\heartbeat\heartbeat_receiver.py | run | 75] Disconnected
18:44:40: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\heartbeat\heartbeat_receiver.py | run | 64] Connected
18:44:41: [WARNING] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\heartbeat\heartbeat_receiver.py | run | 70] Missed heartbeat
18:44:43: [WARNING] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\heartbeat\heartbeat_receiver.py | run | 70] Missed heartbeat
18:44:45: [WARNING] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\heartbeat\heartbeat_receiver.py | run | 70] Missed heartbeat
18:44:47: [WARNING] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\heartbeat\heartbeat_receiver.py | run | 70] Missed heartbeat
18:44:48: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\heartbeat\heartbeat_receiver_worker.py | heartbeat_receiver_worker | 74] Heartbeat receiver exiting
2 changes: 2 additions & 0 deletions logs/2026-02-12_18-44-26/main.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
18:44:26: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\modules\common\modules\logger\logger_main_setup.py | setup_main_logger | 62] main logger initialized
18:44:27: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\test_heartbeat_receiver.py | main | 114] Connected!
13 changes: 13 additions & 0 deletions logs/2026-02-12_18-45-51/heartbeat_receiver_drone_25376.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
18:45:51: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | main | 41] Logger initialized
18:45:51: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:45:52: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:45:53: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:45:54: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:45:55: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:46:04: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:46:05: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:46:06: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:46:07: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:46:08: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:46:10: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | send_heartbeats | 58] Drone: Sent a heartbeat
18:46:11: [INFO] [C:\Users\Jeyas\Downloads\WARGBootcamp\autonomy-bootcamp-2025-p2\tests\integration\mock_drones\heartbeat_receiver_drone.py | main | 78] Passesd!
Loading
Loading