diff --git a/README.md b/README.md
index 5ea110b..eff7747 100644
--- a/README.md
+++ b/README.md
@@ -1,89 +1,148 @@
-# rover-ros2
+# ASTRA Rover ROS2 Packages
[](https://www.gnu.org/licenses/agpl-3.0)
-Submodule which includes all ros2 packages for the rover. These are centrally located for modular rover operation.
+Includes all main ROS2 packages for the rover. These are centrally located for modular rover operation.
-You will use this package to launch any module-side ROS2 nodes.
-
+You will use these packages to launch all rover-side ROS2 nodes.
-## Software Pre-reqs
+## Table of Contents
-An acting base station computer will need several things:
+- [Software Prerequisites](#software-prerequisites)
+ - [Nix](#nix)
+ - [ROS2 Humble + rosdep](#ros2-humble--rosdep)
+- [Running](#running)
+ - [Testing Serial](#testing-serial)
+ - [Connecting the GuliKit Controller](#connecting-the-gulikit-controller)
+- [Common Problems/Toubleshooting](#common-problemstroubleshooting)
+- [Packages](#packages)
+- [Maintainers](#maintainers)
-* ROS2 Humble
- * Follow the standard ROS2 humble install process. Linux recommended.
- * https://docs.ros.org/en/humble/Installation.html
-* Colcon
- * `$ sudo apt update`
- * `$ sudo apt install python3-colcon-common-extensions`
-* Configured Static IP for Ubiquiti bullet (Process varies by OS)
- * IP Address: 192.168.1.x
- * This can be just about anything not already in use. I recommend something 30-39
- * Net Mask: 255.255.255.0
- * Gateway: 192.168.1.0
+## Software Prerequisites
-## Launching with ANCHOR
+You need either [ROS2 Humble](https://docs.ros.org/en/humble/index.html)
+with [rosdep](https://docs.ros.org/en/humble/Tutorials/Intermediate/Rosdep.html#rosdep-installation)
+or [Nix](https://nixos.org/download/#nix-install-linux) installed. We recommend
+using Nix.
-ANCHOR (Active Node Controller Hub and Operational Relay)
-Allows for launching all nodes on the rover simulataneously. Additionally, all controls will run through the core's NUC and MCU.
-
-1. SSH to core
- * Core1: `ssh clucky@192.168.1.69`
- * Core2: `ssh clucky@192.168.1.70`
- * Password: \
-2. Navigate to rover-ros2 workspace
- * `cd rover-ros2`
-3. Source the workspace
- * `source install/setup.bash`
-4. Launch ANCHOR
- * `ros2 launch rover_launch.py mode:=anchor`
+### Nix
-## Launching as Standalone
+With Nix, all you have to do is enter the development shell:
-For use when running independent modules through their respective computers (pi/NUC) without ANCHOR.
+```bash
+$ cd path/to/rover-ros2
+$ nix develop
+```
-1. SSH to the the module's computer
- * Core1: `ssh clucky@192.168.1.69`
- * Core2: `ssh clucky@192.168.1.70`
- * Arm: `ssh arm@192.168.1.70`
- * Bio: \
- * Password: \
-2. Run the main node (this sends commands to the MCU)
- * Navigate to the rover-ros2 workspace (location may vary)
- * `cd rover-ros2`
- * Source the workspace
- * `source install/setup.bash`
- * Start the node
- * ARM: `ros2 launch rover_launch.py mode:=arm`
- * CORE: `ros2 launch rover_launch.py mode:=core`
- * BIO: `ros2 launch rover_launch.py mode:=bio`
+### ROS2 Humble + rosdep
-## Running Headless
+With ROS2 Humble, start by using rosdep to install dependencies:
-Headless control nodes (for ARM and CORE) allow running of the module on-rover without the operator having ROS2 installed on their machine. You will need a laptop to connect to the pi/NUC in order to launch headless but it can be disconnected after the nodes are spun up.
-
-1. SSH to the the module's computer
- * Core1: `ssh clucky@192.168.1.69`
- * Core2: `ssh clucky@192.168.1.70`
- * Arm: `ssh arm@192.168.1.70`
- * Password: \
-2. Run the headless node
- * You must have ANCHOR or the module's Standalone node running
- * Open a new terminal (SSH'd to the module)
- * Navigate to rover-ros2 workspace
- * `cd rover-ros2`
- * Source the workspace
- * `source install/setup.bash`
- * Run the node (ensure controller is connected and on x-input mode)
- * CORE: `ros2 run core_pkg headless`
- * ARM: `ros2 run arm_pkg headless`
+```bash
+ # Setup rosdep
+$ sudo rosdep init # only run if you haven't already
+$ rosdep update
+ # Install dependencies
+$ cd path/to/rover-ros2
+$ rosdep install --from-paths src -y --ignore-src
+```
-## Connecting the GuliKit Controller
+## Running
-Connecting the GuliKit Controller (Recommended)
+```bash
+$ colcon build
+$ source install/setup.bash
+ # main launch files:
+$ ros2 launch anchor_pkg rover.launch.py # Must be run on a computer connected to a MCU on the rover.
+$ ros2 run headless_pkg headless_full # Optionally run in a separate shell on the same or different computer.
+```
-* Connect controller to pc with USB-C
+### Testing Serial
+
+You can fake the presence of a Serial device (i.e., MCU) by using the following command:
+
+```bash
+$ socat -dd -v pty,rawer,crnl,link=/tmp/ttyACM9 pty,rawer,crnl,link=/tmp/ttyOUT
+```
+
+When you go to run anchor, use the `PORT_OVERRIDE` environment variable to point it to the fake serial port, like so:
+
+```bash
+$ PORT_OVERRIDE=/tmp/ttyACM9 ros2 launch anchor_pkg rover.launch.py
+```
+
+### Connecting the GuliKit Controller
+
+These instructions apply to the black XBox-style GuliKit controller, primarily used for controlling Arm through Basestation.
+
+* Connect the controller to your PC with a USB-C cable
* Select the "X-Input" control mode (Windows logo) on the controller.
-* Hold the button next to the symbols (windows, android, switch, etc...)
-* You'll need to release the button and press down again to cycle to the next mode
+ * Hold the button next to the symbols (windows, android, switch, etc...)
+ * You'll need to release the button and press down again to cycle to the next mode
+
+## Common Problems/Troubleshooting
+
+**Q**: When I try to launch the nodes, I receive a `package '' not found` error.
+
+A: Make sure you have sourced the workspace in the current shell:
+
+```bash
+$ source install/setup.bash # or setup.zsh if using ZSH
+```
+
+**Q**: When I try to launch the nodes, I receive several `FileNotFoundError: [Errno 2]` errors.
+
+A: Sometimes the install files get messed up by running `colcon build` in different shells or updating packages. Try running the following commands to clean up your local build files:
+
+```bash
+$ rm -rf build/ install/
+$ colcon build
+```
+
+**Q**: When I run `colcon build` after the above suggestion, I receive several of the following errors:
+
+```bash
+[0.557s] WARNING:colcon.colcon_ros.prefix_path.ament:The path '' in the environment variable AMENT_PREFIX_PATH doesn't exist
+```
+
+A: Don't worry about it. If you had the workspace sourced, ROS2 will complain about the workspace install files not existing anymore after you deleted them. They will be re-created by `colcon build`, after which you can run `source install/setup.bash` to source the new install files.
+
+**Q**: When I try to launch Anchor, I receive the following errors:
+
+```bash
+[anchor-5] [INFO] [1762239452.937881841] [anchor]: Unable to find MCU...
+...
+[ERROR] [anchor-5]: process has died [pid 101820, exit code 1, cmd '.../rover-ros2/install/anchor_pkg/lib/anchor_pkg/anchor --ros-args -r __node:=anchor --params-file /tmp/launch_params_nmv6tpw4'].
+[INFO] [launch]: process[anchor-5] was required: shutting down launched system
+[INFO] [bio-4]: sending signal 'SIGINT' to process[bio-4]
+[INFO] [ptz-3]: sending signal 'SIGINT' to process[ptz-3]
+[INFO] [core-2]: sending signal 'SIGINT' to process[core-2]
+[INFO] [arm-1]: sending signal 'SIGINT' to process[arm-1]
+...
+```
+
+A: To find a microcontroller to talk to, Anchor sends a ping to every Serial port on your computer. If it does not receive a 'pong' in less than one second, then it aborts. There are a few possible fixes:
+
+- Keep trying to run it until it works
+- Run `lsusb` to see if the microcontroller is detected by your computer.
+- Run `ls /dev/tty*0` to see if there is a valid Serial port enumerated for the microcontroller.
+- Check if you are in the `dialout` group (or whatever group shows up by running `ls -l /dev/tty*`).
+
+## Packages
+
+- [anchor\_pkg](./src/anchor_pkg) - Handles Serial communication between the various other packages here and the microcontroller.
+- [arm\_pkg](./src/arm_pkg) - Relays controls and sensor data for the arm (socket and digit) between anchor and basestation/headless.
+- [astra\_descriptions](./src/astra_descriptions) - Submodule with URDF-related packages.
+- [bio\_pkg](./src/bio_pkg) - Like arm_pkg, but for CITADEL and FAERIE
+- [core\_pkg](./src/core_pkg) - Like arm_pkg, but for Core
+- [headless\_pkg](./src/headless_pkg) - Simple, non-graphical controller node to work in place of basestation when controlling the rover by itself. This is autostarted with anchor to allow for setup-less control of the rover.
+- [latency\_tester](./src/latency_tester) - A temporary node to test comms latency over ROS2, Serial, and CAN.
+- [ros2\_interfaces\_pkg](./src/ros2_interfaces_pkg) - Contains custom message types for communication between basestation and the rover over ROS2. (being renamed to `astra_msgs`).
+- [servo\_arm\_twist\_pkg](./src/servo_arm_twist_pkg) - A temporary node to translate controller state from `ros2_joy` to `Twist` messages to control the Arm via IK.
+
+## Maintainers
+
+| Name | Email | Discord |
+| ---- | ----- | ------- |
+| David Sharpe | | `@ddavdd` |
+| Riley McLain | | `@ryleu` |
diff --git a/auto_start/auto_start_anchor.sh b/auto_start/auto_start_anchor.sh
index 71cc2e1..12419bd 100755
--- a/auto_start/auto_start_anchor.sh
+++ b/auto_start/auto_start_anchor.sh
@@ -1,4 +1,7 @@
#!/usr/bin/env bash
+set -e
+
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# Wait for a network interface to be up (not necessarily online)
while ! ip link show | grep -q "state UP"; do
@@ -15,10 +18,7 @@ echo "[INFO] Starting ROS node..."
source /opt/ros/humble/setup.bash
# Source your workspace setup script
-source /home/clucky/rover-ros2/install/setup.bash
-
-# CD to directory
-cd /home/clucky/rover-ros2/
+source $SCRIPT_DIR/../install/setup.bash
# Launch the ROS 2 node with the desired mode
ros2 launch anchor_pkg rover.launch.py mode:=anchor
diff --git a/auto_start/auto_start_core_headless.sh b/auto_start/auto_start_core_headless.sh
deleted file mode 100755
index 8e787b8..0000000
--- a/auto_start/auto_start_core_headless.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env bash
-
-# Wait for a network interface to be up (not necessarily online)
-while ! ip link show | grep -q "state UP"; do
- echo "[INFO] Waiting for active network interface..."
- sleep 1
-done
-
-echo "[INFO] Network interface is up!"
-
-# Your actual ROS node start command goes here
-echo "[INFO] Starting ROS node..."
-
-# Source ROS 2 Humble setup script
-source /opt/ros/humble/setup.bash
-
-# Source your workspace setup script
-source /home/clucky/rover-ros2/install/setup.bash
-
-# CD to directory
-cd /home/clucky/rover-ros2/
-
-# Launch the ROS 2 node
-ros2 run core_pkg headless
diff --git a/auto_start/auto_start_headless_full.sh b/auto_start/auto_start_headless_full.sh
index 870a646..8a014e1 100755
--- a/auto_start/auto_start_headless_full.sh
+++ b/auto_start/auto_start_headless_full.sh
@@ -1,4 +1,7 @@
#!/usr/bin/env bash
+set -e
+
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# Wait for a network interface to be up (not necessarily online)
while ! ip link show | grep -q "state UP"; do
@@ -15,10 +18,7 @@ echo "[INFO] Starting ROS node..."
source /opt/ros/humble/setup.bash
# Source your workspace setup script
-source /home/clucky/rover-ros2/install/setup.bash
-
-# CD to directory
-cd /home/clucky/rover-ros2/
+source $SCRIPT_DIR/../install/setup.bash
# Launch the ROS 2 node
ros2 run headless_pkg headless_full
diff --git a/auto_start/start_rosbag.sh b/auto_start/start_rosbag.sh
index 786a153..dcc07d7 100755
--- a/auto_start/start_rosbag.sh
+++ b/auto_start/start_rosbag.sh
@@ -1,8 +1,12 @@
#!/usr/bin/env bash
+set -e
-ANCHOR_WS="/home/clucky/rover-ros2"
-AUTONOMY_WS="/home/clucky/rover-Autonomy"
-BAG_LOCATION="/home/clucky/bags/autostart"
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+
+[[ -z "$ANCHOR_WS" ]] && ANCHOR_WS="$SCRIPT_DIR/.."
+[[ -z "$AUTONOMY_WS" ]] && AUTONOMY_WS="$HOME/rover-Autonomy"
+BAG_LOCATION="$HOME/bags/autostart"
+[[ ! -d "$BAG_LOCATION" ]] && mkdir -p "$BAG_LOCATION"
# Wait for a network interface to be up (not necessarily online)
while ! ip link show | grep -q "state UP"; do
@@ -15,7 +19,7 @@ echo "[INFO] Network interface is up!"
source /opt/ros/humble/setup.bash
source $ANCHOR_WS/install/setup.bash
-[ -f $AUTONOMY_WS/install/setup.bash ] && source $AUTONOMY_WS/install/setup.bash
+[[ -f $AUTONOMY_WS/install/setup.bash ]] && source $AUTONOMY_WS/install/setup.bash
cd $BAG_LOCATION