+ );
+ }
+ return (
+
+ {label}
+
+
+ );
+ })}
+ >
+ )
+}
+
+
diff --git a/src/content/docs/archive/projects/2024-projects.md b/src/content/docs/archive/projects/2024-projects.md
new file mode 100644
index 0000000..5a46f7b
--- /dev/null
+++ b/src/content/docs/archive/projects/2024-projects.md
@@ -0,0 +1,39 @@
+---
+title: "2024 Projects"
+---
+## Perception
+
+* [Long range ArUco tag detection](/autonomy/perception/long-range-tag-detection)
+* [Object detection](/autonomy/perception/object-detection)
+* [Surface normals costmap](/autonomy/navigation/surface-normals-costmap)
+* Spatial mapping for teleop
+* [Lander auto-align](/autonomy/navigation/lander-auto-align)
+
+## Navigation
+
+* [Approach Target Base State](/autonomy/navigation/approach-target-base-state)
+ * [Second Camera Navigation Integration (LongRangeState)](/autonomy/navigation/second-camera-integration)
+ * [ApproachObjectState](/autonomy/navigation/approach-object-state)
+* [Obstacle Avoidance](/autonomy/navigation/obstacle-avoidance)
+* [Adaptive pure pursuit](/autonomy/navigation/adaptive-pure-pursuit)
+* [URC vs. CIRC switch](/general-resources/devops/urc-vs-circ-switch)
+
+## Localization
+
+* Real-time kinematic positioning
+* Dual GNSS Heading
+* IMU Setup
+* Tip Detection
+
+## ESW
+
+* Hardware accelerated and robust camera streaming
+* Brushed motor controller STM
+* Brushed motor controller ROS
+* Brushless ROS
+* Science controller STM
+* PDB STM
+
+## Teleop
+* Convert to Django
+* [5dof IK](/autonomy/navigation/5dof-ik)
diff --git a/src/content/docs/archive/projects/2025-2026-projects.md b/src/content/docs/archive/projects/2025-2026-projects.md
new file mode 100644
index 0000000..92a42a7
--- /dev/null
+++ b/src/content/docs/archive/projects/2025-2026-projects.md
@@ -0,0 +1,30 @@
+---
+title: "2025-2026 Projects"
+---
+## Perception
+* [Key-Detection](/autonomy/perception/key-detection)
+* [Object Detector Model](/autonomy/perception/object-detector-model)
+* [Light Detector](/autonomy/perception/light-detector)
+
+## Navigation
+
+* [Arm IK](/autonomy/navigation/arm-ik)
+* [Click IK](/autonomy/navigation/click-ik)
+* [Path Execution](/autonomy/navigation/path-execution)
+
+## Localization
+
+* [Localisation Caching State Machine](/autonomy/localization/data-caching-state-machine)
+* [Invariant EKF](/autonomy/localization/invariant-ekf)
+* [Dual Antenna RTK](/autonomy/localization/dual-antenna-rtk)
+* Directional Antenna (RAT)
+
+## ESW
+
+* Hardware accelerated and robust camera streaming
+* Science Board STM
+* CANalyzer
+
+## Teleop
+* Convert to Django
+* [5dof IK](/autonomy/navigation/5dof-ik)
diff --git a/src/content/docs/autonomy/drone.md b/src/content/docs/autonomy/drone.md
deleted file mode 100644
index 757755b..0000000
--- a/src/content/docs/autonomy/drone.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: "Drone"
----
-Go to umrover/mrover-drone
\ No newline at end of file
diff --git a/src/content/docs/localization/data-caching-state-machine.md b/src/content/docs/autonomy/localization/data-caching-state-machine.md
similarity index 100%
rename from src/content/docs/localization/data-caching-state-machine.md
rename to src/content/docs/autonomy/localization/data-caching-state-machine.md
diff --git a/src/content/docs/localization/dual-antenna-rtk.md b/src/content/docs/autonomy/localization/dual-antenna-rtk.md
similarity index 99%
rename from src/content/docs/localization/dual-antenna-rtk.md
rename to src/content/docs/autonomy/localization/dual-antenna-rtk.md
index f0152f7..26f57c0 100644
--- a/src/content/docs/localization/dual-antenna-rtk.md
+++ b/src/content/docs/autonomy/localization/dual-antenna-rtk.md
@@ -57,7 +57,7 @@ Key properties:
### IEKF: using RTK heading as a measurement
The IEKF fuses dual‑antenna RTK heading as a yaw measurement. It gates out invalid data, converts the heading into a body‑frame reference vector, builds a measurement model, and runs the EKF correction step weighted by `rtk_heading_noise`.
-```302:330:localization/iekf_se3/iekf_se3.cpp
+```cpp
void IEKF_SE3::rtk_heading_callback(const mrover::msg::Heading::ConstSharedPtr &rtk_heading, const mrover::msg::FixStatus::ConstSharedPtr &rtk_heading_status) {
if (rtk_heading_status->fix_type.fix == mrover::msg::FixType::NO_SOL) {
@@ -104,7 +104,7 @@ Tip: Tune `iekf_se3.rtk_heading_noise` in `config/localization.yaml` to balance
### Heading filter: correcting IMU yaw when RTK heading is FIXED
This node applies a 1D Kalman filter to correct yaw using dual‑antenna heading only when the heading solution is `FIXED` (highest quality). It computes the uncorrected yaw from the IMU quaternion, forms an angle error to the measured RTK heading, then predict–corrects the scalar filter.
-```71:99:localization/heading_filter/heading_filter.cpp
+```cpp
void HeadingFilter::sync_rtk_heading_callback(const mrover::msg::Heading::ConstSharedPtr &heading, const mrover::msg::FixStatus::ConstSharedPtr &heading_status) {
diff --git a/src/content/docs/localization/globally-accurate-orientation.md b/src/content/docs/autonomy/localization/globally-accurate-orientation.md
similarity index 100%
rename from src/content/docs/localization/globally-accurate-orientation.md
rename to src/content/docs/autonomy/localization/globally-accurate-orientation.md
diff --git a/src/content/docs/localization/imu-calibration.md b/src/content/docs/autonomy/localization/imu-calibration.md
similarity index 100%
rename from src/content/docs/localization/imu-calibration.md
rename to src/content/docs/autonomy/localization/imu-calibration.md
diff --git a/src/content/docs/localization/invariant-ekf.md b/src/content/docs/autonomy/localization/invariant-ekf.md
similarity index 77%
rename from src/content/docs/localization/invariant-ekf.md
rename to src/content/docs/autonomy/localization/invariant-ekf.md
index 009eb5c..99d2934 100644
--- a/src/content/docs/localization/invariant-ekf.md
+++ b/src/content/docs/autonomy/localization/invariant-ekf.md
@@ -5,7 +5,7 @@ title: "Invariant EKF"

-Please read over the Kalman Filter and Sensor Fusion section of the [Localization](/localization/overview) page and view the additional resources before starting here. The Extended Kalman Filter (EKF) is a version of the Kalman filter adapted for nonlinear systems, and is the standard used in navigation systems today. Instead of representing process dynamics through a constant matrix, which is only suitable for linear processes, the EKF uses the Jacobian of the process dynamics model. Evaluated at the current state, it provides a local linear approximation for an otherwise nonlinear process. This approximation is then used in the regular Kalman filter as matrix $A$. You can think of this as similar to a tangent line approximation you may have done in calculus.
+Please read over the Kalman Filter and Sensor Fusion section of the [Localization](/autonomy/localization/overview) page and view the additional resources before starting here. The Extended Kalman Filter (EKF) is a version of the Kalman filter adapted for nonlinear systems, and is the standard used in navigation systems today. Instead of representing process dynamics through a constant matrix, which is only suitable for linear processes, the EKF uses the Jacobian of the process dynamics model. Evaluated at the current state, it provides a local linear approximation for an otherwise nonlinear process. This approximation is then used in the regular Kalman filter as matrix $A$. You can think of this as similar to a tangent line approximation you may have done in calculus.
Highly recommend checking out these resources for a more detailed explanation and algorithm equations:
* https://en.wikipedia.org/wiki/Extended_Kalman_filter
diff --git a/src/content/docs/localization/overview.md b/src/content/docs/autonomy/localization/overview.md
similarity index 98%
rename from src/content/docs/localization/overview.md
rename to src/content/docs/autonomy/localization/overview.md
index 61c2720..1bdbf34 100644
--- a/src/content/docs/localization/overview.md
+++ b/src/content/docs/autonomy/localization/overview.md
@@ -2,7 +2,7 @@
title: "Localization"
---
# What is Localization?
-In simple terms, localization is just figuring out where the robot is. In the case of our rover, we need to know what point it is located at in 3D space, as well as what angle it is rotated to in each axis. This information is also known as a pose (see [this](/autonomy/3d-poses-transforms-rotations) page). We need to have this data at all times, and it needs to be updated frequently enough to keep up with the rover's motion. We typically estimate this data by measuring it with a variety of sensors and then processing that sensor data with a variety of fusion and filtering algorithms to make it more accurate.
+In simple terms, localization is just figuring out where the robot is. In the case of our rover, we need to know what point it is located at in 3D space, as well as what angle it is rotated to in each axis. This information is also known as a pose (see [this](/autonomy/resources/3d-poses-transforms-rotations) page). We need to have this data at all times, and it needs to be updated frequently enough to keep up with the rover's motion. We typically estimate this data by measuring it with a variety of sensors and then processing that sensor data with a variety of fusion and filtering algorithms to make it more accurate.
# Sensors
## GPS
diff --git a/src/content/docs/navigation/5dof-ik.md b/src/content/docs/autonomy/navigation/5dof-ik.md
similarity index 100%
rename from src/content/docs/navigation/5dof-ik.md
rename to src/content/docs/autonomy/navigation/5dof-ik.md
diff --git a/src/content/docs/navigation/adaptive-pure-pursuit.md b/src/content/docs/autonomy/navigation/adaptive-pure-pursuit.md
similarity index 100%
rename from src/content/docs/navigation/adaptive-pure-pursuit.md
rename to src/content/docs/autonomy/navigation/adaptive-pure-pursuit.md
diff --git a/src/content/docs/navigation/approach-object-state.md b/src/content/docs/autonomy/navigation/approach-object-state.md
similarity index 100%
rename from src/content/docs/navigation/approach-object-state.md
rename to src/content/docs/autonomy/navigation/approach-object-state.md
diff --git a/src/content/docs/navigation/approach-target-base-state.md b/src/content/docs/autonomy/navigation/approach-target-base-state.md
similarity index 94%
rename from src/content/docs/navigation/approach-target-base-state.md
rename to src/content/docs/autonomy/navigation/approach-target-base-state.md
index 768440b..61f07dd 100644
--- a/src/content/docs/navigation/approach-target-base-state.md
+++ b/src/content/docs/autonomy/navigation/approach-target-base-state.md
@@ -22,4 +22,4 @@ Also the rules specify two new waypoints during the Autonomy mission that requir
**Rough Steps**:
1. Learn how the new state machine library works. The code new code is merged into [master](https://github.com/umrover/mrover-ros). The files for the library are in src/util/state_lib and the updated states are in src/navigation. Some other examples of how to use the library are in test/util/state_lib.
2. Review the outlines of the new states in the ENGIN|MRover/Software/Auton/New States folder in the shared drive. These outlines don't contain all the code you need, make sure to reference the already implemented ApproachPostState for what other things you may need to add.
-3. Start coding up the outline of the ApproachTargetBaseState. After everyone understands this state, split into smaller groups to work on the ApproachPostState, [LongRangeState](/navigation/second-camera-integration), and [ApproachObjectState](/navigation/approach-object-state) states.
\ No newline at end of file
+3. Start coding up the outline of the ApproachTargetBaseState. After everyone understands this state, split into smaller groups to work on the ApproachPostState, [LongRangeState](/autonomy/navigation/second-camera-integration), and [ApproachObjectState](/autonomy/navigation/approach-object-state) states.
\ No newline at end of file
diff --git a/src/content/docs/navigation/arm-ik-testing.md b/src/content/docs/autonomy/navigation/arm-ik-testing.md
similarity index 100%
rename from src/content/docs/navigation/arm-ik-testing.md
rename to src/content/docs/autonomy/navigation/arm-ik-testing.md
diff --git a/src/content/docs/navigation/arm-ik.md b/src/content/docs/autonomy/navigation/arm-ik.md
similarity index 95%
rename from src/content/docs/navigation/arm-ik.md
rename to src/content/docs/autonomy/navigation/arm-ik.md
index 41fc964..aa26204 100644
--- a/src/content/docs/navigation/arm-ik.md
+++ b/src/content/docs/autonomy/navigation/arm-ik.md
@@ -11,4 +11,4 @@ The current IK implementation has not been fully tested on the rover, so it is n
# Solution
-The end effector has a limited range of motion, particularly in terms of pitch. This means that it is not always possible to make the end effector parallel to the ground (as we would like to, especially for typing) for all arm positions. Thus it is necessary to determine the bubble of positions that are reachable with the end effector level, so that we can optimally position the rover for typing. More details on finding this "bubble" can be found [here](/navigation/arm-ik-testing).
\ No newline at end of file
+The end effector has a limited range of motion, particularly in terms of pitch. This means that it is not always possible to make the end effector parallel to the ground (as we would like to, especially for typing) for all arm positions. Thus it is necessary to determine the bubble of positions that are reachable with the end effector level, so that we can optimally position the rover for typing. More details on finding this "bubble" can be found [here](/autonomy/navigation/arm-ik-testing).
\ No newline at end of file
diff --git a/src/content/docs/navigation/arm-velocity-control.md b/src/content/docs/autonomy/navigation/arm-velocity-control.md
similarity index 100%
rename from src/content/docs/navigation/arm-velocity-control.md
rename to src/content/docs/autonomy/navigation/arm-velocity-control.md
diff --git a/src/content/docs/navigation/click-ik.md b/src/content/docs/autonomy/navigation/click-ik.md
similarity index 100%
rename from src/content/docs/navigation/click-ik.md
rename to src/content/docs/autonomy/navigation/click-ik.md
diff --git a/src/content/docs/navigation/cost-map.md b/src/content/docs/autonomy/navigation/cost-map.md
similarity index 100%
rename from src/content/docs/navigation/cost-map.md
rename to src/content/docs/autonomy/navigation/cost-map.md
diff --git a/src/content/docs/navigation/costmap-path-planning.md b/src/content/docs/autonomy/navigation/costmap-path-planning.md
similarity index 90%
rename from src/content/docs/navigation/costmap-path-planning.md
rename to src/content/docs/autonomy/navigation/costmap-path-planning.md
index ee1cdac..bc229d7 100644
--- a/src/content/docs/navigation/costmap-path-planning.md
+++ b/src/content/docs/autonomy/navigation/costmap-path-planning.md
@@ -7,4 +7,4 @@ title: "Costmap Path Planning"
Here's a (simplified) overview of the navigation state machine as it is now:

-For more details on the specifics of how the current costmap implementation works, be sure to check out [this](/navigation/obstacle-avoidance) page.
\ No newline at end of file
+For more details on the specifics of how the current costmap implementation works, be sure to check out [this](/autonomy/navigation/obstacle-avoidance) page.
\ No newline at end of file
diff --git a/src/content/docs/navigation/inward-spiraling.md b/src/content/docs/autonomy/navigation/inward-spiraling.md
similarity index 100%
rename from src/content/docs/navigation/inward-spiraling.md
rename to src/content/docs/autonomy/navigation/inward-spiraling.md
diff --git a/src/content/docs/navigation/lander-auto-align.md b/src/content/docs/autonomy/navigation/lander-auto-align.md
similarity index 100%
rename from src/content/docs/navigation/lander-auto-align.md
rename to src/content/docs/autonomy/navigation/lander-auto-align.md
diff --git a/src/content/docs/navigation/obstacle-avoidance.md b/src/content/docs/autonomy/navigation/obstacle-avoidance.md
similarity index 100%
rename from src/content/docs/navigation/obstacle-avoidance.md
rename to src/content/docs/autonomy/navigation/obstacle-avoidance.md
diff --git a/src/content/docs/navigation/overview.md b/src/content/docs/autonomy/navigation/overview.md
similarity index 96%
rename from src/content/docs/navigation/overview.md
rename to src/content/docs/autonomy/navigation/overview.md
index 2e4d603..424f668 100644
--- a/src/content/docs/navigation/overview.md
+++ b/src/content/docs/autonomy/navigation/overview.md
@@ -5,44 +5,44 @@ title: "Navigation"
## Contents
-1. [State Machine Diagram](#State-machine-diagram)
-2. [What is a State Machine and why do we use a custom implementation?](#What-is-a-State-Machine-and-why-do-we-use-a-custom-implementation?)
-3. [State Descriptions](#State-Descriptions)
+1. [State Machine Diagram](#state-machine-diagram)
+2. [What is a State Machine and why do we use a custom implementation?](#what-is-a-state-machine-and-why-do-we-use-a-custom-implementation)
+3. [State Descriptions](#state-descriptions)
- 3.1 [Off State](#Off-State)
+ 3.1 [Off State](#off-state)
- 3.2 [Done State](#Done-State)
+ 3.2 [Done State](#done-state)
- 3.3 [Waypoint State](#Waypoint-State)
+ 3.3 [Waypoint State](#waypoint-state)
- 3.4 [Approach Target State](#Approach-Target-State)
+ 3.4 [Approach Target State](#approach-target-state)
- 3.5 [Long Range State](#Long-Range-State)
+ 3.5 [Long Range State](#long-range-state)
- 3.6 [Costmap Search State](#Costmap-Search-State)
+ 3.6 [Costmap Search State](#costmap-search-state)
- 3.7 [Backup State](#Backup-State)
+ 3.7 [Backup State](#backup-state)
- 3.8 [Stuck Recovery State](#Stuck-Recovery-State)
+ 3.8 [Stuck Recovery State](#stuck-recovery-state)
-4. [Path Planning](#Path-Planning)
+4. [Path Planning](#path-planning)
4.1 [A* Algorithm](#a-algorithm)
- 4.2 [Costmap Integration](#costmap-integration)
+ 4.2 Costmap Integration
-5. [Context, Rover, Environment, Course](#Context,-Rover,-Environment,-Course)
+5. [Context, Rover, Environment, Course](#context-rover-environment-course)
- 5.1 [Context](#Context-Functions/Attributes)
+ 5.1 [Context](#context-functionsattributes)
- 5.2 [Rover](#Rover)
+ 5.2 [Rover](#rover)
- 5.3 [Environment](#Environment)
+ 5.3 [Environment](#environment)
- 5.4 [Course](#Course)
+ 5.4 [Course](#course)
-6. [DriveController Class](#DriveController-Class)
-7. [Trajectory](#Trajectory)
-8. [SearchTrajectory](#SearchTrajectory)
-9. [ArmController](#armcontroller)
+6. [DriveController Class](#drivecontroller-class)
+7. [Trajectory](#trajectory)
+8. [SearchTrajectory](#searchtrajectory)
+9. [ArmController](#arm-controller)
## State machine diagram
diff --git a/src/content/docs/navigation/path-execution.md b/src/content/docs/autonomy/navigation/path-execution.md
similarity index 52%
rename from src/content/docs/navigation/path-execution.md
rename to src/content/docs/autonomy/navigation/path-execution.md
index 5c02f54..f871832 100644
--- a/src/content/docs/navigation/path-execution.md
+++ b/src/content/docs/autonomy/navigation/path-execution.md
@@ -8,11 +8,11 @@ Last year A* was implemented into the rover's path planning logic providing us w
During the auton mission, we are limited on time. As such, we need to drive in a way that will save us the most time possible.
# **Solutions**
-## [Pure Pursuit](/navigation/pure-pursuit)
-Currently, our path-tracking algorithm is built around a state machine that limits the rover's driving to essentially two states -- turn in place and drive forward (read more [here](/navigation/overview) ). This is problematic since A*'s path is often quite jagged, meaning the rover is constantly stopping and turning in place to try to follow this path. To solve this, we will utilize a pure pursuit algorithm, which will eliminate the turn in place/drive forward behavior entirely. More details can be found at the page linked above.
+## [Pure Pursuit](/autonomy/navigation/pure-pursuit)
+Currently, our path-tracking algorithm is built around a state machine that limits the rover's driving to essentially two states -- turn in place and drive forward (read more [here](/autonomy/navigation/overview) ). This is problematic since A*'s path is often quite jagged, meaning the rover is constantly stopping and turning in place to try to follow this path. To solve this, we will utilize a pure pursuit algorithm, which will eliminate the turn in place/drive forward behavior entirely. More details can be found at the page linked above.
-## [Path Smoothing](/navigation/path-smoothing)
+## [Path Smoothing](/autonomy/navigation/path-smoothing)
One level above the rover's path-tracking is its path planning. As mentioned above, A*'s paths are quite jagged, and while the implementation of pure pursuit will generally smooth out the rover's traversal, we are also seeking to process and smooth out the A* trajectory before we begin to track it. This will reduce unnecessary oscillations and sharp turns, leading to a more efficient, natural, and stable trajectory for the rover to follow. As such, we will incorporate some form of path smoothing, either with relaxation, interpolation, or both, into the path planning process. More details can be found at the page linked above.
-## [Inward Spiraling](/navigation/inward-spiraling)
-As detailed in the [navigation wiki](/navigation/overview), the high-level decision-making for the rover's navigation is based off of a state machine. In the search state, we currently spiral from a center waypoint outwards within some radius. However, this is not optimal if we are driving to the center waypoint from outside of the search area's radius. Instead, rather than driving from outside of the search area to its center and spiraling back to the edge, we should start spiraling _inwards_ from the edge of the search area towards the center waypoint.
\ No newline at end of file
+## [Inward Spiraling](/autonomy/navigation/inward-spiraling)
+As detailed in the [navigation wiki](/autonomy/navigation/overview), the high-level decision-making for the rover's navigation is based off of a state machine. In the search state, we currently spiral from a center waypoint outwards within some radius. However, this is not optimal if we are driving to the center waypoint from outside of the search area's radius. Instead, rather than driving from outside of the search area to its center and spiraling back to the edge, we should start spiraling _inwards_ from the edge of the search area towards the center waypoint.
\ No newline at end of file
diff --git a/src/content/docs/navigation/path-smoothing.md b/src/content/docs/autonomy/navigation/path-smoothing.md
similarity index 100%
rename from src/content/docs/navigation/path-smoothing.md
rename to src/content/docs/autonomy/navigation/path-smoothing.md
diff --git a/src/content/docs/navigation/pure-pursuit.md b/src/content/docs/autonomy/navigation/pure-pursuit.md
similarity index 100%
rename from src/content/docs/navigation/pure-pursuit.md
rename to src/content/docs/autonomy/navigation/pure-pursuit.md
diff --git a/src/content/docs/navigation/second-camera-integration.md b/src/content/docs/autonomy/navigation/second-camera-integration.md
similarity index 100%
rename from src/content/docs/navigation/second-camera-integration.md
rename to src/content/docs/autonomy/navigation/second-camera-integration.md
diff --git a/src/content/docs/navigation/state-machine-library.md b/src/content/docs/autonomy/navigation/state-machine-library.md
similarity index 100%
rename from src/content/docs/navigation/state-machine-library.md
rename to src/content/docs/autonomy/navigation/state-machine-library.md
diff --git a/src/content/docs/navigation/stuck-detector.md b/src/content/docs/autonomy/navigation/stuck-detector.md
similarity index 100%
rename from src/content/docs/navigation/stuck-detector.md
rename to src/content/docs/autonomy/navigation/stuck-detector.md
diff --git a/src/content/docs/navigation/surface-normals-costmap.md b/src/content/docs/autonomy/navigation/surface-normals-costmap.md
similarity index 100%
rename from src/content/docs/navigation/surface-normals-costmap.md
rename to src/content/docs/autonomy/navigation/surface-normals-costmap.md
diff --git a/src/content/docs/perception/key-detection.md b/src/content/docs/autonomy/perception/key-detection.md
similarity index 100%
rename from src/content/docs/perception/key-detection.md
rename to src/content/docs/autonomy/perception/key-detection.md
diff --git a/src/content/docs/perception/light-detector.md b/src/content/docs/autonomy/perception/light-detector.md
similarity index 100%
rename from src/content/docs/perception/light-detector.md
rename to src/content/docs/autonomy/perception/light-detector.md
diff --git a/src/content/docs/perception/long-range-tag-detection.md b/src/content/docs/autonomy/perception/long-range-tag-detection.md
similarity index 97%
rename from src/content/docs/perception/long-range-tag-detection.md
rename to src/content/docs/autonomy/perception/long-range-tag-detection.md
index 736e13d..643e577 100644
--- a/src/content/docs/perception/long-range-tag-detection.md
+++ b/src/content/docs/autonomy/perception/long-range-tag-detection.md
@@ -6,7 +6,7 @@ title: "Long Range Tag Detection"
> The 3 posts will have GNSS coordinates that are within the vicinity of the posts,
increasing in range from approximately 5-20 m.
-Please also read the Wiki page on [perception](/perception/overview).
+Please also read the Wiki page on [perception](/autonomy/perception/overview).
**Problem**: The [ZED stereo camera](https://www.stereolabs.com/zed-2/) can only detect tags around 8 meters away. As such we have to run a spiral search to find the tag. This takes precious time since the autonomy period is only 30 minutes long.
diff --git a/src/content/docs/perception/object-detection.md b/src/content/docs/autonomy/perception/object-detection.md
similarity index 96%
rename from src/content/docs/perception/object-detection.md
rename to src/content/docs/autonomy/perception/object-detection.md
index 4cc4838..4912484 100644
--- a/src/content/docs/perception/object-detection.md
+++ b/src/content/docs/autonomy/perception/object-detection.md
@@ -32,7 +32,7 @@ Rough Steps:
2. Create a subscriber to the ZED point cloud topic
3. Write a function that takes the point cloud, compresses it into a 2D cv::Mat, and passes it into the model to detect the objects (see tag_detector.processing.cpp for an example of this)
4. Find the point that corresponds to the center of the object bounding box in the Point Cloud and assign that as the Object's distance from the rover
-5. Determine the relative bearing of the Object from the rover's current position. This can be done similar to the tag bearing calculation in the [long range detection project](/perception/long-range-tag-detection).
+5. Determine the relative bearing of the Object from the rover's current position. This can be done similar to the tag bearing calculation in the [long range detection project](/autonomy/perception/long-range-tag-detection).
5. Create a publisher for the Object topic
6. Write a function that publishes the detected Objects from the Point Cloud message to the Object topic as well as the tf tree
7. Determine a more robust way of detecting the Object's distance from ZED. Picking the center point of the bounding box could often be NaN or located somewhere in open space
diff --git a/src/content/docs/perception/object-detector-model.md b/src/content/docs/autonomy/perception/object-detector-model.md
similarity index 100%
rename from src/content/docs/perception/object-detector-model.md
rename to src/content/docs/autonomy/perception/object-detector-model.md
diff --git a/src/content/docs/perception/overview.md b/src/content/docs/autonomy/perception/overview.md
similarity index 100%
rename from src/content/docs/perception/overview.md
rename to src/content/docs/autonomy/perception/overview.md
diff --git a/src/content/docs/autonomy/quickstart.md b/src/content/docs/autonomy/quickstart.md
index 0e47f03..21840e7 100644
--- a/src/content/docs/autonomy/quickstart.md
+++ b/src/content/docs/autonomy/quickstart.md
@@ -1,7 +1,7 @@
---
title: "Autonomy Quickstart"
---
-This assumes that you have already installed (and verified) ROS for our system if not follow this [tutorial](/getting-started/install-ros)
+This assumes that you have already installed (and verified) ROS for our system if not follow this [tutorial](/general-resources/ros/install-ros/install-ros)
This tutorial will take you through starting up the autonomy system and running the navigation code to hopefully be able to see the rover run in simulation.
diff --git a/src/content/docs/autonomy/3d-poses-transforms-rotations.md b/src/content/docs/autonomy/resources/3d-poses-transforms-rotations.md
similarity index 100%
rename from src/content/docs/autonomy/3d-poses-transforms-rotations.md
rename to src/content/docs/autonomy/resources/3d-poses-transforms-rotations.md
diff --git a/src/content/docs/autonomy/vectorization.md b/src/content/docs/autonomy/resources/vectorization.md
similarity index 100%
rename from src/content/docs/autonomy/vectorization.md
rename to src/content/docs/autonomy/resources/vectorization.md
diff --git a/src/content/docs/autonomy/starter-project.md b/src/content/docs/autonomy/starter-project.md
deleted file mode 100644
index ac4d7b9..0000000
--- a/src/content/docs/autonomy/starter-project.md
+++ /dev/null
@@ -1,224 +0,0 @@
----
-title: "Autonomy Starter Project"
----
-# Overview
-
-
-
-Welcome to the autonomy starter project tutorial! In this tutorial, you will write code for all three subsystems encompassed by autonomy: perception, navigation, and localization. You will then put them all together in order to complete a task with a simulated rover. The goal is to familiarize yourself with what type of problems we tackle and how to do that with our codebase.
-
-When you complete the project you will have a rover that uses its localization system to navigate to a set waypoint and then uses its perception system to drive it to a tag, here is an example of a working solution (click the image below, it's a link):
-
-[](https://youtu.be/H43zXWK88_c)
-
-# Getting Started
-
-Use the `mrover` command to navigate to `~/ros2_ws/src/mrover`:
-
-Follow the setup instructions [here](/getting-started/install-ros) to setup up the codebase. Note the following folder `./starter_project`, this is where the majority of the work will be done.
-
-# Perception
-
-Make sure you read the "Overview" of the [perception page](/perception/overview) before working on this part of the project. Note that this is the overall Wiki page for our non starter project code and there is one specific to the starter project later in this subsection.
-
-For perception, you will write a ROS node that uses camera data to detect ArUco tags using [OpenCV](https://github.com/opencv/opencv), a popular computer vision library. Navigation will read this data in order to align the rover with it.
-
-### Inputs
-- Image data: `Image` messages published to the `zed/left/image` topic via the [`image_transport`](http://wiki.ros.org/image_transport) package
-
-### Outputs
-- Custom message published to `tag` topic with:
- - Tag center location in camera space
- - An approximation for rover to tag distance
-
-Now proceed to [perception-specific page](/autonomy/starter-project-perception) for the implementation! You will notice a common theme on MRover is breaking down problems into inputs and outputs then providing more details on specifics in separate locations. And remember, the [ROS2 humble wiki](https://docs.ros.org/en/humble/index.html) is one of your greatest resources!!
-
-
-# Localization
-Make sure you read the "GPS", "IMU", "GPS Linearization", and "Guide to Localization Frames" sections from the [Localization page](/localization/overview) before working on this part of the project (RTK is beyond the scope of our starter project but recommended).
-
-For localization, you will write a ROS node that uses GPS and IMU data to figure out where the rover is, and then publish this information as a transform in the TF tree. Here is the interface your node should follow:
-
-### Inputs
-- GPS data: [NavSatFix messages](http://docs.ros.org/en/melodic/api/sensor_msgs/html/msg/NavSatFix.html) published to the `/gps/fix` topic
-- IMU data: [Imu messages](http://docs.ros.org/en/melodic/api/sensor_msgs/html/msg/Imu.html) published to the `/imu/data_raw` topic
-
-### Outputs
-- Rover pose: transform in meters published to TF tree
-
-### Subscribing to Sensor Data
-
-You should start by subscribing to the GPS and IMU sensor data provided as inputs. To do this, you will have to create two `rclpy.Subscriber` objects. The python syntax for creating a subscriber looks like this:
-```py
-self.create_subscription(msg_type, topic_name, callback_function, buffer_size)
-```
-What this effectively does is tell ROS that your node should listen to, or "subscribe" to a ros topic `topic_name` that carries `msg_type` messages, and whenever you receive one, `callback_function` should be called. The callback function headers for `gps_callback` and `imu_callback` have already been provided for you, so make sure to use them when creating the subscribers.
-
-In your callback functions, all you should do for now is print out the data you're receiving (which comes in the form of the `msg` argument to the function), that way you can make sure you're successfully getting the data. For more help on writing a subscriber, read [this ROS tutorial](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html) on writing a Publisher/Subscriber Node.
-
-### Adding your node to the launch file
-In order to run your node along with the rest of the starter project, you will need to add it to the starter project launch file. Open `starter_project.launch.py` in the launch folder and uncomment the line declaring a node in the localization section. Notice the syntax for launching a node:
-```py
-...
-localization_node = Node(package="mrover", executable="localization.py", name="localization")
-...
-return LaunchDescription(
- [
- ...
- localization_node
- ]
-)
-```
-As you can see, we are launching a node that we have named "localization", is from the mrover package, and has an executable `localization.py` which is what will actually get run.
-
-Once this line is uncommented, you should be able to launch the file with
-```bash
-ros2 launch mrover starter_project.launch.py
-```
-
-
-### Linearize GPS coordinates into euclidean coordinates
-Now that you have your data, you need to use it to figure out where the rover is; Let's start with GPS. The GPS latitude and longitude coordinates tell us where we are in spherical earth coordinates, but what we really want are cartesian (x, y, z) coordinates in meters. Because our rover is driving in an area that is tiny relative to the size of the earth, we can approximate the area the rover drives in as a flat plane tangent to the surface of the earth:
-
-
-
-For this to work, we will need to define a point on the earth in (latitude, longitude) coordinates where the center of our tangent plane will be; this point will be called the reference point. As long as this reference point is
-close (within a few hundred miles probably) to where the rover is going to be, this tangent plane will be a pretty good approximation. For this project we will simulate the rover as driving near the Mars Desert Research Centre in Utah. Use the reference latitude and longitude found in `config/reference_coords.yaml` under the Sim section.
-
-
-
-To convert our spherical coordinates to cartesian coordinates, you can imagine zooming in on the tangent plane. We can find our latitude and longitude "distances" by subtracting our reference coordinates from our spherical coordinates, and then we just need to convert the units of those distances from degrees to meters. We are going to pretend the earth is a perfect sphere to make things simple.
-
-For north/south latitude distance, which will become our x coordinate, this is pretty simple. If the earth is a perfect sphere, then each meridian (vertical band) around the earth has the same circumference as the equator. Since we know the circumference of the earth at the equator (6371000 meters), we know that 1 degree of latitude is equal to the circumference divided by 360.
-
-For east/west longitude distance, which will become our y coordinate, things get a little trickier because each horizontal band around the earth does not have the same circumference. To account for this, we have to scale the circumference with the cosine of latitude (think about why this makes sense). Then we can use the same equation as we used for latitude. Here are the equations you need to implement in code:
-
-
-
-This equation assumes that our reference heading is 0 degrees (North), but in the simulator, it is actually 90 degrees so you will need to rotate the point by 90 degrees. You should implement this conversion in the `spherical_to_cartesian` function. This is a static method, so it should be called with the class name instead of an object name: `Localization.spherical_to_cartesian()`. Read the function docstring for more details. Make sure to use numpy for the trig functions (`np.sin()`, `np.cos()`, etc) and make sure to convert between radians and degrees when necessary (check the ROS message definitions and function docstrings when in doubt - GPS coordinates are given to you in degrees, what do the trig functions from numpy (and python math) operate on?. For this simple starter project, we don't care about the Z coordinate, so just set it to zero. Once you are done, make sure to test your code by printing out your cartesian coordinates. You can do this by using the rospy.loginfo(msg) function.
-
-You don't have to do any conversions for the IMU data, since it will give you an orientation quaternion, which is exactly what you need in order to make an [SE3](/autonomy/3d-poses-transforms-rotations).
-
-### Update and publish pose to TF tree
-At the end of each callback function, you will now have either [x,y,z] coordinates or an orientation quaternion. How do we give this data to the rest of the autonomy system? It's pretty simple, there are just a couple steps.
-
-First, we have to update our classes global state. Inside of our Localization class, we can keep track of our rover's pose using the SE3 `self.pose`. For this beginner project, we will go with a simple update policy, where we want to update our global state every time we get any new sensor data. This means we want to update `self.pose` in both callback functions, and in each one we only want to change the data that we know. So in the GPS callback, you will need to set `self.pose` equal to a new SE3 using your new [x, y, z] position and the existing orientation data in `self.pose`. The GPS callback function is called whenever the localization node receives a message on the /gps topic that we subscribed to in the init function. Conversely, in the IMU callback, you need to set `self.pose` equal to a new SE3 with the same position data and your new orientation data.
-
-Once you've done that, you can simply call the `publish_to_tf_tree()` method on your SE3. As the name implies, this will publish your pose to the TF tree. Since this is the pose of the base of the rover relative to the map, you should specify your parent frame as "map" and your child frame as "rover_base_link" (this is the name used for the base of the rover).
-
-
-# Navigation
-For navigation, you will write a ROS node that uses the outputs of the localization and perception nodes in order to command the rover towards the point and then the AR tag. In the end, the rover will turn towards a given point (8 meters, 2 meters) and then drive towards it until it is in a set threshold. Once there, the rover should be able to see an AR tag. The rover will turn towards the AR tag so it is directly aligned, then drive forward until it is in a set threshold.
-
-It is often easiest to think in terms of inputs and outputs so here are the inputs and outputs for this node:
-
-### Inputs
-- Rover pose (the rover’s position and orientation in space): transform from TF tree
-- Tag message published from the perception node (from channel `tag`)
-
-### Outputs
-- Velocity data: [Twist message](http://docs.ros.org/en/lunar/api/geometry_msgs/html/msg/Twist.html)
-
-### General Project Structure
-
-We've created the base structure of the project for you in order to mimic the structure of our current code. We recognize that there are other ways to do this, and probably ways to do the same thing in less code, however we want you to gain an understanding of our state machine and the general way we structure code in the navigation subsystem. With that said, here is an outline of each subcomponent of the navigation system and what it is responsible for as well as what you will need to do in each one in order to complete the project. Start by implementing the underlying infrastructure required for the navigation node to be able to properly read its inputs and send its outputs. Then write the logic for each of the two states that you will need for the project.
-
-The files you need to edit are under `mrover/starter_project/autonomy/src/navigation`.
-
-#### Context class (no TODOs, fully provided)
-
-In `context.py`
-
-The goal of this class is to provide access to an interface for reading and writing information regarding the rover's environment and the rover itself. It contains objects of `Rover` and `Environment` both of which you will need to implement various functions in. It also contains the ROS publisher and subscriber objects that you will need to use to listen to and send the messages for this node.
-
-
-#### Rover class
-
-In `context.py`
-
-Lets start by implementing the Rover class. The rover object (accessed through the context object) is responsible for the interface for all things related to the rover. In our case, this will mean we need to implement three functions:
-
-1. `get_pose(self) -> Optional[SE3]`
-
-Here we will need to fill in the code so that the function returns an SE3 object that represents where the rover is in the world. For more information about SE3s and what they are checkout [this wikipage](/autonomy/3d-poses-transforms-rotations). Additionally, read over the docstrings within `mrover/starter_project/autonomy/src/util/SE3.py` to see the full SE3 interface and understand what the interface is.
-
-Once you do that, you're going to want to use the `SE3.from_tf_tree` function in order to get the SE3 that represents the rover's pose. This function is found in the `SE3.py` file. We have imported this class into the context file. The function’s parameters include:
-
-`tf_buffer`: the tf buffer used to query the TF tree
-`parent_frame`: the parent frame of the desired transform
-`child_frame`: the child frame of the desired transform
-
-Note that the `tf_buffer` has already been created for you and is owned by the Context object which is called `ctx` in the rover class. Once again, since this is the pose of the base of the rover relative to the map, you should specify your parent frame as "map" and your child frame as "rover_base_link" (this is the name used for the base of the rover).
-
-2. `send_drive_command(self, twist: Twist)`
-
-Here we will need to fill in the code so that the function publishes a twist message using the velocity command publisher object that is also already a member of the context (`vel_cmd_publisher`). This is of type Publisher so you will need to use the function `publish()` on this publisher. If you wish, you can learn more about publishers and subscribers [here](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html)
-
-3. `send_drive_stop(self)`
-
-Here we will need to fill in the function so that it stops the rover when run (hint #1: use `send_drive_command()`) (hint #2: `Twist()` initializes velocities to be 0 in its message).
-
-#### Environment class
-
-In `context.py`
-
-The environment class is similar to the rover class except instead of providing an interface to things going on on the rover, it provides an interface to things going on in the environment around the rover. For us this means implementing two functions:
-
-1. `receive_fid_data(self, message : StarterProjectTag)`
-
-This function is the callback function that we have set up for you such that it will be invoked every time we receive an AR tag position message. You will need to update a member variable in the Environment class to hold the StarterProjectTag message passed to this function (hint: fid stands for fiducial, which is the AR tag in this case).
-
-2. `get_fid_data(self) -> Optional[StarterProjectTag]`
-
-This function should return either `None` or your AR tag position message. It should return `None` if you don't know where the tag is, or it should return the most recent ROS message regarding the AR tag's position if you do know where the tag is.
-HINT: Use the same member variable you just set in your `receive_fid_data` function.
-
-Now we have finished creating the base-level interfaces that we will use to actually write the logic on top! Basically, all of the interaction with the outside world is complete, we now will use the abstractions we've created to code the logic of our state machine. Let's take a look at how we structure single states and build the states that we will need. After that, we will hook our states into the greater state machine and we will have completed the project!
-
-First of all, what is a state? Please read [this page](/navigation/overview) to learn what a state is.
-
-#### Done state (no TODOs, fully provided)
-
-See `state.py`
-
-We have provided a Done State that represents the rover in its "Done State" because we don't want our program to just end when the rover completes, we have a state that essentially just loops and does nothing. We have also provided a Fail State that represents failure to finish the task.
-
-#### Drive State
-
-In `drive_state.py`
-
-The goal of this state is to drive towards the set point (8, 2). We've created the class for you but you will need to implement the `on_loop()` function. We've provided a general outline in the comments of how this function might be structured and have also providing a function `get_drive_command()` imported from `drive.py` that you can use to do some of the math in this step for you. The function should return the state it needs to transition to next.
-
-Hint: Use the functions from context.rover we've already written
-
-#### Tag Seek State
-
-In `tag_seek.py`
-
-The goal of this state is to drive towards the AR tag after arriving at the set point (8, 2). We've created the class for you but just like the Drive State you will need to implement the `on_loop()` function. This will be a bit trickier as you don't actually have a pose to drive to you just have the same general measurements regarding angular and distance offsets that you calculated earlier.
-
-You can get information about how close the rover is to the tag by using the function `get_fid_data` in context.env. You want the rover to be within a certain distance (`DISTANCE_TOLERANCE`) from the tag, and face the tag within a certain angular distance (`ANGULAR_TOLERANCE`), to be able to transition to the Done state. We have set these tolerances to be `DISTANCE_TOLERANCE = 0.99`, `ANGULAR_TOLERANCE = 0.3`. Hint: `get_fid_data()` returns `StarterProjectTag`, this includes information about how close the rover is to the tag and the measurements of where the center of the tag is in our view (x and y).
-
-If the rover is not within the angular and distance tolerances, create a twist command and change the linear.x value and/or the angular.z value so that the rover becomes within the tolerances. Then send this twist command to the rover and stay in the TagSeekState.
-
-#### Navigation class
-
-In `navigation_starter_project.py`
-
-The navigation class is where the whole state machine comes together. We've already done the hard work of creating the whole state machine now we just need to put it all together. We've already added the DoneState to the state machine, and use a similar pattern for adding the TagSeek and DriveState states to the state machine.
-
-## Testing your Work
-Now open `starter_project.launch.py` which is in the `mrover/starter_project/autonomy/launch` folder. Make sure the lines declaring a node in the localization, perception, and navigation sections are uncommented.
-
-To run the rover in the simulator:
-1. In your terminal run `ros2 launch mrover starter_project.launch.py` to open the simulator, you should see the rover not moving in the simulator.
-2. In a new terminal run `ros2 run mrover visualizer.py` so you can monitor which state the rover once you start it.
-3. In the simulator press `p` to enable physics. Watch the rover move to (8, 2) while being in the DriveState, transition to TagSeekState, see the tag, and finally reach the tag and move to the DoneState.
-
-
-
-## Completion
-
-Congrats! You've finished the autonomy starter project!
-
-
diff --git a/src/content/docs/autonomy/starter-project/localization.md b/src/content/docs/autonomy/starter-project/localization.md
new file mode 100644
index 0000000..f804ef0
--- /dev/null
+++ b/src/content/docs/autonomy/starter-project/localization.md
@@ -0,0 +1,77 @@
+---
+title: "Localization"
+sidebar:
+ order: 2
+---
+# Localization
+
+Make sure you read the "GPS", "IMU", "GPS Linearization", and "Guide to Localization Frames" sections from the [Localization page](/autonomy/localization/overview) before working on this part of the project (RTK is beyond the scope of our starter project but recommended).
+
+For localization, you will write a ROS node that uses GPS and IMU data to figure out where the rover is, and then publish this information as a transform in the TF tree. Here is the interface your node should follow:
+
+### Inputs
+- GPS data: [NavSatFix messages](http://docs.ros.org/en/melodic/api/sensor_msgs/html/msg/NavSatFix.html) published to the `/gps/fix` topic
+- IMU data: [Imu messages](http://docs.ros.org/en/melodic/api/sensor_msgs/html/msg/Imu.html) published to the `/imu/data_raw` topic
+
+### Outputs
+- Rover pose: transform in meters published to TF tree
+
+### Subscribing to Sensor Data
+
+You should start by subscribing to the GPS and IMU sensor data provided as inputs. To do this, you will have to create two `rclpy.Subscriber` objects. The python syntax for creating a subscriber looks like this:
+```py
+self.create_subscription(msg_type, topic_name, callback_function, buffer_size)
+```
+What this effectively does is tell ROS that your node should listen to, or "subscribe" to a ros topic `topic_name` that carries `msg_type` messages, and whenever you receive one, `callback_function` should be called. The callback function headers for `gps_callback` and `imu_callback` have already been provided for you, so make sure to use them when creating the subscribers.
+
+In your callback functions, all you should do for now is print out the data you're receiving (which comes in the form of the `msg` argument to the function), that way you can make sure you're successfully getting the data. For more help on writing a subscriber, read [this ROS tutorial](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html) on writing a Publisher/Subscriber Node.
+
+### Adding your node to the launch file
+In order to run your node along with the rest of the starter project, you will need to add it to the starter project launch file. Open `starter_project.launch.py` in the launch folder and uncomment the line declaring a node in the localization section. Notice the syntax for launching a node:
+```py
+...
+localization_node = Node(package="mrover", executable="localization.py", name="localization")
+...
+return LaunchDescription(
+ [
+ ...
+ localization_node
+ ]
+)
+```
+As you can see, we are launching a node that we have named "localization", is from the mrover package, and has an executable `localization.py` which is what will actually get run.
+
+Once this line is uncommented, you should be able to launch the file with
+```bash
+ros2 launch mrover starter_project.launch.py
+```
+
+
+### Linearize GPS coordinates into euclidean coordinates
+Now that you have your data, you need to use it to figure out where the rover is; Let's start with GPS. The GPS latitude and longitude coordinates tell us where we are in spherical earth coordinates, but what we really want are cartesian (x, y, z) coordinates in meters. Because our rover is driving in an area that is tiny relative to the size of the earth, we can approximate the area the rover drives in as a flat plane tangent to the surface of the earth:
+
+
+
+For this to work, we will need to define a point on the earth in (latitude, longitude) coordinates where the center of our tangent plane will be; this point will be called the reference point. As long as this reference point is
+close (within a few hundred miles probably) to where the rover is going to be, this tangent plane will be a pretty good approximation. For this project we will simulate the rover as driving near the Mars Desert Research Centre in Utah. Use the reference latitude and longitude found in `config/reference_coords.yaml` under the Sim section.
+
+
+
+To convert our spherical coordinates to cartesian coordinates, you can imagine zooming in on the tangent plane. We can find our latitude and longitude "distances" by subtracting our reference coordinates from our spherical coordinates, and then we just need to convert the units of those distances from degrees to meters. We are going to pretend the earth is a perfect sphere to make things simple.
+
+For north/south latitude distance, which will become our x coordinate, this is pretty simple. If the earth is a perfect sphere, then each meridian (vertical band) around the earth has the same circumference as the equator. Since we know the circumference of the earth at the equator (6371000 meters), we know that 1 degree of latitude is equal to the circumference divided by 360.
+
+For east/west longitude distance, which will become our y coordinate, things get a little trickier because each horizontal band around the earth does not have the same circumference. To account for this, we have to scale the circumference with the cosine of latitude (think about why this makes sense). Then we can use the same equation as we used for latitude. Here are the equations you need to implement in code:
+
+
+
+This equation assumes that our reference heading is 0 degrees (North), but in the simulator, it is actually 90 degrees so you will need to rotate the point by 90 degrees. You should implement this conversion in the `spherical_to_cartesian` function. This is a static method, so it should be called with the class name instead of an object name: `Localization.spherical_to_cartesian()`. Read the function docstring for more details. Make sure to use numpy for the trig functions (`np.sin()`, `np.cos()`, etc) and make sure to convert between radians and degrees when necessary (check the ROS message definitions and function docstrings when in doubt - GPS coordinates are given to you in degrees, what do the trig functions from numpy (and python math) operate on?. For this simple starter project, we don't care about the Z coordinate, so just set it to zero. Once you are done, make sure to test your code by printing out your cartesian coordinates. You can do this by using the rospy.loginfo(msg) function.
+
+You don't have to do any conversions for the IMU data, since it will give you an orientation quaternion, which is exactly what you need in order to make an [SE3](/autonomy/resources/3d-poses-transforms-rotations).
+
+### Update and publish pose to TF tree
+At the end of each callback function, you will now have either [x,y,z] coordinates or an orientation quaternion. How do we give this data to the rest of the autonomy system? It's pretty simple, there are just a couple steps.
+
+First, we have to update our classes global state. Inside of our Localization class, we can keep track of our rover's pose using the SE3 `self.pose`. For this beginner project, we will go with a simple update policy, where we want to update our global state every time we get any new sensor data. This means we want to update `self.pose` in both callback functions, and in each one we only want to change the data that we know. So in the GPS callback, you will need to set `self.pose` equal to a new SE3 using your new [x, y, z] position and the existing orientation data in `self.pose`. The GPS callback function is called whenever the localization node receives a message on the /gps topic that we subscribed to in the init function. Conversely, in the IMU callback, you need to set `self.pose` equal to a new SE3 with the same position data and your new orientation data.
+
+Once you've done that, you can simply call the `publish_to_tf_tree()` method on your SE3. As the name implies, this will publish your pose to the TF tree. Since this is the pose of the base of the rover relative to the map, you should specify your parent frame as "map" and your child frame as "rover_base_link" (this is the name used for the base of the rover).
diff --git a/src/content/docs/autonomy/starter-project/navigation.md b/src/content/docs/autonomy/starter-project/navigation.md
new file mode 100644
index 0000000..b76501f
--- /dev/null
+++ b/src/content/docs/autonomy/starter-project/navigation.md
@@ -0,0 +1,105 @@
+---
+title: "Navigation"
+sidebar:
+ order: 4
+---
+# Navigation
+
+For navigation, you will write a ROS node that uses the outputs of the localization and perception nodes in order to command the rover towards the point and then the AR tag. In the end, the rover will turn towards a given point (8 meters, 2 meters) and then drive towards it until it is in a set threshold. Once there, the rover should be able to see an AR tag. The rover will turn towards the AR tag so it is directly aligned, then drive forward until it is in a set threshold.
+
+It is often easiest to think in terms of inputs and outputs so here are the inputs and outputs for this node:
+
+### Inputs
+- Rover pose (the rover’s position and orientation in space): transform from TF tree
+- Tag message published from the perception node (from channel `tag`)
+
+### Outputs
+- Velocity data: [Twist message](http://docs.ros.org/en/lunar/api/geometry_msgs/html/msg/Twist.html)
+
+### General Project Structure
+
+We've created the base structure of the project for you in order to mimic the structure of our current code. We recognize that there are other ways to do this, and probably ways to do the same thing in less code, however we want you to gain an understanding of our state machine and the general way we structure code in the navigation subsystem. With that said, here is an outline of each subcomponent of the navigation system and what it is responsible for as well as what you will need to do in each one in order to complete the project. Start by implementing the underlying infrastructure required for the navigation node to be able to properly read its inputs and send its outputs. Then write the logic for each of the two states that you will need for the project.
+
+The files you need to edit are under `mrover/starter_project/autonomy/src/navigation`.
+
+#### Context class (no TODOs, fully provided)
+
+In `context.py`
+
+The goal of this class is to provide access to an interface for reading and writing information regarding the rover's environment and the rover itself. It contains objects of `Rover` and `Environment` both of which you will need to implement various functions in. It also contains the ROS publisher and subscriber objects that you will need to use to listen to and send the messages for this node.
+
+
+#### Rover class
+
+In `context.py`
+
+Lets start by implementing the Rover class. The rover object (accessed through the context object) is responsible for the interface for all things related to the rover. In our case, this will mean we need to implement three functions:
+
+1. `get_pose(self) -> Optional[SE3]`
+
+Here we will need to fill in the code so that the function returns an SE3 object that represents where the rover is in the world. For more information about SE3s and what they are checkout [this wikipage](/autonomy/resources/3d-poses-transforms-rotations). Additionally, read over the docstrings within `mrover/starter_project/autonomy/src/util/SE3.py` to see the full SE3 interface and understand what the interface is.
+
+Once you do that, you're going to want to use the `SE3.from_tf_tree` function in order to get the SE3 that represents the rover's pose. This function is found in the `SE3.py` file. We have imported this class into the context file. The function’s parameters include:
+
+`tf_buffer`: the tf buffer used to query the TF tree
+`parent_frame`: the parent frame of the desired transform
+`child_frame`: the child frame of the desired transform
+
+Note that the `tf_buffer` has already been created for you and is owned by the Context object which is called `ctx` in the rover class. Once again, since this is the pose of the base of the rover relative to the map, you should specify your parent frame as "map" and your child frame as "rover_base_link" (this is the name used for the base of the rover).
+
+2. `send_drive_command(self, twist: Twist)`
+
+Here we will need to fill in the code so that the function publishes a twist message using the velocity command publisher object that is also already a member of the context (`vel_cmd_publisher`). This is of type Publisher so you will need to use the function `publish()` on this publisher. If you wish, you can learn more about publishers and subscribers [here](https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html)
+
+3. `send_drive_stop(self)`
+
+Here we will need to fill in the function so that it stops the rover when run (hint #1: use `send_drive_command()`) (hint #2: `Twist()` initializes velocities to be 0 in its message).
+
+#### Environment class
+
+In `context.py`
+
+The environment class is similar to the rover class except instead of providing an interface to things going on on the rover, it provides an interface to things going on in the environment around the rover. For us this means implementing two functions:
+
+1. `receive_fid_data(self, message : StarterProjectTag)`
+
+This function is the callback function that we have set up for you such that it will be invoked every time we receive an AR tag position message. You will need to update a member variable in the Environment class to hold the StarterProjectTag message passed to this function (hint: fid stands for fiducial, which is the AR tag in this case).
+
+2. `get_fid_data(self) -> Optional[StarterProjectTag]`
+
+This function should return either `None` or your AR tag position message. It should return `None` if you don't know where the tag is, or it should return the most recent ROS message regarding the AR tag's position if you do know where the tag is.
+HINT: Use the same member variable you just set in your `receive_fid_data` function.
+
+Now we have finished creating the base-level interfaces that we will use to actually write the logic on top! Basically, all of the interaction with the outside world is complete, we now will use the abstractions we've created to code the logic of our state machine. Let's take a look at how we structure single states and build the states that we will need. After that, we will hook our states into the greater state machine and we will have completed the project!
+
+First of all, what is a state? Please read [this page](/autonomy/navigation/overview) to learn what a state is.
+
+#### Done state (no TODOs, fully provided)
+
+See `state.py`
+
+We have provided a Done State that represents the rover in its "Done State" because we don't want our program to just end when the rover completes, we have a state that essentially just loops and does nothing. We have also provided a Fail State that represents failure to finish the task.
+
+#### Drive State
+
+In `drive_state.py`
+
+The goal of this state is to drive towards the set point (8, 2). We've created the class for you but you will need to implement the `on_loop()` function. We've provided a general outline in the comments of how this function might be structured and have also providing a function `get_drive_command()` imported from `drive.py` that you can use to do some of the math in this step for you. The function should return the state it needs to transition to next.
+
+Hint: Use the functions from context.rover we've already written
+
+#### Tag Seek State
+
+In `tag_seek.py`
+
+The goal of this state is to drive towards the AR tag after arriving at the set point (8, 2). We've created the class for you but just like the Drive State you will need to implement the `on_loop()` function. This will be a bit trickier as you don't actually have a pose to drive to you just have the same general measurements regarding angular and distance offsets that you calculated earlier.
+
+You can get information about how close the rover is to the tag by using the function `get_fid_data` in context.env. You want the rover to be within a certain distance (`DISTANCE_TOLERANCE`) from the tag, and face the tag within a certain angular distance (`ANGULAR_TOLERANCE`), to be able to transition to the Done state. We have set these tolerances to be `DISTANCE_TOLERANCE = 0.99`, `ANGULAR_TOLERANCE = 0.3`. Hint: `get_fid_data()` returns `StarterProjectTag`, this includes information about how close the rover is to the tag and the measurements of where the center of the tag is in our view (x and y).
+
+If the rover is not within the angular and distance tolerances, create a twist command and change the linear.x value and/or the angular.z value so that the rover becomes within the tolerances. Then send this twist command to the rover and stay in the TagSeekState.
+
+#### Navigation class
+
+In `navigation_starter_project.py`
+
+The navigation class is where the whole state machine comes together. We've already done the hard work of creating the whole state machine now we just need to put it all together. We've already added the DoneState to the state machine, and use a similar pattern for adding the TagSeek and DriveState states to the state machine.
diff --git a/src/content/docs/autonomy/starter-project/overview.md b/src/content/docs/autonomy/starter-project/overview.md
new file mode 100644
index 0000000..3107f0d
--- /dev/null
+++ b/src/content/docs/autonomy/starter-project/overview.md
@@ -0,0 +1,20 @@
+---
+title: "Overview"
+sidebar:
+ order: 1
+---
+# Overview
+
+
+
+Welcome to the autonomy starter project tutorial! In this tutorial, you will write code for all three subsystems encompassed by autonomy: perception, navigation, and localization. You will then put them all together in order to complete a task with a simulated rover. The goal is to familiarize yourself with what type of problems we tackle and how to do that with our codebase.
+
+When you complete the project you will have a rover that uses its localization system to navigate to a set waypoint and then uses its perception system to drive it to a tag, here is an example of a working solution (click the image below, it's a link):
+
+[](https://youtu.be/H43zXWK88_c)
+
+# Getting Started
+
+Use the `mrover` command to navigate to `~/ros2_ws/src/mrover`:
+
+Follow the setup instructions [here](/general-resources/ros/install-ros/install-ros) to setup up the codebase. Note the following folder `./starter_project`, this is where the majority of the work will be done.
diff --git a/src/content/docs/autonomy/starter-project-perception.md b/src/content/docs/autonomy/starter-project/perception.md
similarity index 88%
rename from src/content/docs/autonomy/starter-project-perception.md
rename to src/content/docs/autonomy/starter-project/perception.md
index 1870534..f0b466f 100644
--- a/src/content/docs/autonomy/starter-project-perception.md
+++ b/src/content/docs/autonomy/starter-project/perception.md
@@ -1,6 +1,22 @@
---
-title: "Autonomy Starter Project - Perception"
+title: "Perception"
+sidebar:
+ order: 3
---
+# Perception
+
+For perception, you will write a ROS node that uses camera data to detect ArUco tags using [OpenCV](https://github.com/opencv/opencv), a popular computer vision library. Navigation will read this data in order to align the rover with it.
+
+### Inputs
+- Image data: `Image` messages published to the `zed/left/image` topic via the [`image_transport`](http://wiki.ros.org/image_transport) package
+
+### Outputs
+- Custom message published to `tag` topic with:
+ - Tag center location in camera space
+ - An approximation for rover to tag distance
+
+And remember, the [ROS2 humble wiki](https://docs.ros.org/en/humble/index.html) is one of your greatest resources!!
+
## Implementation
### Creating a Custom Tag Message
@@ -79,5 +95,3 @@ Make sure to set breakpoints in the source code files! They are almost always be
Consider the following image. Let's say it is 400x400 pixels. We can define a coordinate system that starts at the top left corner, consider that `(0,0)` with positive values of x extending right and positive values of y extending downward. The center of the tag would be about `(300,100)` in this space. Here is a diagram to aid understanding:

-
-
diff --git a/src/content/docs/autonomy/starter-project/testing.md b/src/content/docs/autonomy/starter-project/testing.md
new file mode 100644
index 0000000..e2fea70
--- /dev/null
+++ b/src/content/docs/autonomy/starter-project/testing.md
@@ -0,0 +1,21 @@
+---
+title: "Testing & Completion"
+sidebar:
+ order: 5
+---
+# Testing & Completion
+
+## Testing your Work
+
+Now open `starter_project.launch.py` which is in the `mrover/starter_project/autonomy/launch` folder. Make sure the lines declaring a node in the localization, perception, and navigation sections are uncommented.
+
+To run the rover in the simulator:
+1. In your terminal run `ros2 launch mrover starter_project.launch.py` to open the simulator, you should see the rover not moving in the simulator.
+2. In a new terminal run `ros2 run mrover visualizer.py` so you can monitor which state the rover once you start it.
+3. In the simulator press `p` to enable physics. Watch the rover move to (8, 2) while being in the DriveState, transition to TagSeekState, see the tag, and finally reach the tag and move to the DoneState.
+
+
+
+## Completion
+
+Congrats! You've finished the autonomy starter project!
diff --git a/src/content/docs/drone/drone-arch.png b/src/content/docs/drone/drone-arch.png
new file mode 100644
index 0000000..fa11a77
Binary files /dev/null and b/src/content/docs/drone/drone-arch.png differ
diff --git a/src/content/docs/drone/drone-wiring.png b/src/content/docs/drone/drone-wiring.png
new file mode 100644
index 0000000..fd7df46
Binary files /dev/null and b/src/content/docs/drone/drone-wiring.png differ
diff --git a/src/content/docs/drone/software-install.md b/src/content/docs/drone/software-install.md
index bde6bc5..7c53f10 100644
--- a/src/content/docs/drone/software-install.md
+++ b/src/content/docs/drone/software-install.md
@@ -3,7 +3,7 @@ title: "Software Install"
---
## Install ROS2
-Follow [these instructions](/getting-started/install-ros) to get the MRover ROS2 install done.
+Follow [these instructions](/general-resources/ros/install-ros/install-ros) to get the MRover ROS2 install done.
We still need more packages:
```
diff --git a/src/content/docs/drone/starter-project.md b/src/content/docs/drone/starter-project.md
index 5448369..02d7344 100644
--- a/src/content/docs/drone/starter-project.md
+++ b/src/content/docs/drone/starter-project.md
@@ -4,7 +4,7 @@ title: "Software Starter Project 2025-26"
# Drone Software Starter Project
-This year, we are looking to develop capabilities for the drone to operate autonomously during the URC missions. The aim of the drone software starter project is to familiarize you with the key frameworks and software tools we will use to operate the drone and implement capability for autonomous flight. Once you have installed [all necessary software](/getting-started/install-ros), proceed through the sections of this page to complete the starter project.
+This year, we are looking to develop capabilities for the drone to operate autonomously during the URC missions. The aim of the drone software starter project is to familiarize you with the key frameworks and software tools we will use to operate the drone and implement capability for autonomous flight. Once you have installed [all necessary software](/general-resources/ros/install-ros/install-ros), proceed through the sections of this page to complete the starter project.
## ROS2 Introduction
diff --git a/src/content/docs/drone/system-architecture.md b/src/content/docs/drone/system-architecture.md
index fffbffa..17ee461 100644
--- a/src/content/docs/drone/system-architecture.md
+++ b/src/content/docs/drone/system-architecture.md
@@ -2,5 +2,5 @@
title: "System Architecture"
---
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/src/content/docs/esw/.prettierrc.yml b/src/content/docs/esw/.prettierrc.yml
new file mode 100644
index 0000000..f1d7f90
--- /dev/null
+++ b/src/content/docs/esw/.prettierrc.yml
@@ -0,0 +1 @@
+tabWidth: 4
diff --git a/src/content/docs/esw/brushed-controller-ros.md b/src/content/docs/esw/brushed-controller-ros.md
deleted file mode 100644
index 1351889..0000000
--- a/src/content/docs/esw/brushed-controller-ros.md
+++ /dev/null
@@ -1,36 +0,0 @@
----
-title: "Brushed Controller ROS"
----
-**Context**: On our rover, we have various PCBs that are responsible for the brushed motors on our rover. We call these PCBs our brushed DC motor controllers (BDCMC) PCBs. Take a look at the below picture to see a draft of all the devices on the rover and see where the BDCMCs fit into the system.
-
-
-
-**Problem**: We need to write ROS programs that communicate with these BDCMC PCBs. Teleop will ask ESW to move the joints/motors, and ESW's ROS node needs to tell eventually communicate to the motors over CAN about how to reach that target (target velocity or target position).
-
-**Solution**:
-
-* Develop all the ROS software in C++.
-* Implement the bridge software
-* Implement the motor_library library software
-* Implement the CAN node (technically a separate project but it is very closely related)
-
-**Interface**:
-
-* There is currently not a good description of the interface since it is still in the works of being developed
-* However, we can expect the ROS node to be able to do the following: Send velocity commands in terms of rad/s. Receive and process angular data based on quadrature encoder data. More.
-* See the below picture to see how the software that you are writing fits into the bigger picture
-
-
-
-**Rough Steps To Get Started**:
-
-* This project is big. So it might be overwhelming
-* We are developing all code in the mrover-ros repository in the branch embedded
-* The code is located in the src/esw/ folder in various folders
-* DONE/NOT-TESTED: We need help developing the CAN node and making sure that we can process ROS messages and send out actual CAN messages
-* For the CAN node, once we receive CAN messages back, we need to be able to understand it as well
-* DONE: For the motors_library library, we need to be able to abstract between brushed motor controllers and brushless controllers. This project does not deal with brushless controllers but it is a consequence of working with the same software.
-* DONE: For the bridges, you will need to call on the motors_library and keep track of instances that are Motors.
-* DONE: Whenever you ask a Motor to set_velocity (or something similar to that), then you are asking for it to send a request to the CAN Node to send a message.
-* DONE: This request to the CAN Node should basically have the information of a raw CAN frame. The formatting of this raw CAN frame should be consistent with whatever is being written for the STM32 firmware. See the Brushed Controller STM32 for more information on that.
-* As for hardware, you can perhaps try testing if you are sending out CAN messages once the CAN node is implemented. If you want to test on actual motors, then we currently do not have actual hardware to test on. This will change once we have EHW's dev board and on actual motors once we have EHW's actual BDCMC. Also, in order to test this actual hardware, then you will need to wait for the firmware for that hardware to be developed. See the Brushed Controller STM32 project for more information on that.
diff --git a/src/content/docs/esw/brushed-controller-stm.md b/src/content/docs/esw/brushed-controller-stm.md
deleted file mode 100644
index 157a074..0000000
--- a/src/content/docs/esw/brushed-controller-stm.md
+++ /dev/null
@@ -1,32 +0,0 @@
----
-title: "Brushed Controller STM"
----
-**Context**: On our rover, we have various PCBs that are responsible for the brushed motors on our rover. We call these PCBs our brushed DC motor controllers (BDCMC) PCBs. Take a look at the below picture to see a draft of all the devices on the rover and see where the BDCMCs fit into the system.
-
-
-
-**Problem**: These PCBs need an MCU to process all incoming CAN requests and control the motor based on that. Thus, we use an STM32 chip as our main MCU. The issue is that we need code for that.
-
-**Solution**:
-
-* Develop STM32 software (firmware) using the CubeIDE in C++
-* The firmware should be able to receive CAN messages and process them
-* The CAN messages should be consistent with whatever the corresponding ROS program is sending (see the [Brushed Controller ROS project](/esw/brushed-controller-ros))
-* The CAN messages interface should be defined
-* The firmware should be able to control the movement of a particular motor
-
-**Interface**:
-
-* There is currently not a good description of the interface since it is still in the works of being developed
-* However, one can expect the STM32 to be able to do the following: Process velocity commands in terms of rad/s. Report angular data based on quadrature encoder data. Respect limits based on limit switches.
-* See the below picture to see how the firmware that you are writing fits into the bigger picture
-
-
-
-**Rough Steps To Get Started**:
-
-* This project is big. So it might be overwhelming
-* We are developing all code in the mrover-ros repository in the branch embedded
-* The code is located in the src/esw/fw/bdcmc folder
-* CubeIDE should be installed
-* As for hardware, we currently do not have actual hardware to test on. This will change once we have EHW's dev board and on actual motors once we have EHW's actual BDCMC.
diff --git a/src/content/docs/esw/brushed-motors-planning.md b/src/content/docs/esw/brushed-motors-planning.md
deleted file mode 100644
index 4cd501a..0000000
--- a/src/content/docs/esw/brushed-motors-planning.md
+++ /dev/null
@@ -1,32 +0,0 @@
----
-title: "Brushed Motors Planning"
----
-## Task: Write brushed motors ROS code
-Location: `mrover-ros/embedded/esw/brushed_motors`
-- [ ] Get Quintin's Code to build
-### Arm to Can Node
-Reads in arm message from rostopic ra_cmd. This message contains a motor name, target velocity, and target position. Then, the node will convert this message into a can message and publish to rostopic can_messages. A different can node will deal brushed vs. brushless
-Will probably look very similar to last year's code.
-```
-motor_message:
- motor_name
- velocity
- position
-
-can_message:
- bus_name
- can frame
-```
-#### Implementation Details:
-Written in Python
-***
-## Task: Write brushed motors open loop control
-Location: `mrover-ros/embedded/esw/fw/motor_mother`
-
-#### Implementation Details:
-
-
-***
-## Task: Test brushed firmware code w/out motor
-
-#### Implementation Details:
diff --git a/src/content/docs/esw/brushed-motors.md b/src/content/docs/esw/brushed-motors.md
deleted file mode 100644
index 7324086..0000000
--- a/src/content/docs/esw/brushed-motors.md
+++ /dev/null
@@ -1,85 +0,0 @@
----
-title: "Brushed Motors"
----
-## Project Overview
-
-On the rover exists a MCU board which essentially is a PCB powered by 12V which has
-various voltage lines and MCUs embedded on it. Two of the MCUs embedded on it is what
-we call the Motor MCUs, which are two STM32s chip whose tasks are to control the brushed motors
-of the rover.
-
-The brushed motors which the STM32s control are the arm joints (Joints A, B, F, Finger, Gripper), Mast Gimbal (Pitch and Yaw),
-ISH carousel system, the SA system (Joints 1, 2, 3, Scoop, and Microscope).
-
----
-
-## System Overview
-
-The two STM32 MCUs are connected via the same I2C line. They are both follower devices and the leader device in the I2C bus is the Raspberry Pi.
-
----
-
-## Top Level Code
-
-The code is written in C++.
-
-The I2C.cpp file is a wrapper for I2C.
-The Controller.cpp defines the Controller class which basically represents a motor.
-The ControllerMap.cpp file basically creates Controller devices based on the config (esw.yaml) file.
-The ROSHandler.cpp file defines all the functions that are called in response to services and topics.
-
----
-
-## MCU Code
-
-Code can be found in embedded-testbench in dev/motors.
-
-https://github.com/umrover/embedded-testbench/tree/dev/motors
-
----
-
-## Appendix
-
-### Motor MCU Pinouts (Blurry - sorry)
-
-There are some pins that happened to be swapped on the actual motors MCU board.
-
-
-
-
-### Motor MCU 0 Pinout
-
-Source is Motor MCU Pinout Google Sheets
-
-
-
-
-
-### Motor MCU 1 Pinout
-
-Source is Motor MCU Pinout Google Sheets
-
-
-
-
-### Arm Topics
-
-Source is Teleop ESW ICD Sheet Google Sheets
-
-
-### Arm Services
-
-Source is Teleop ESW ICD Sheet Google Sheets
-
-
-### Science Topics
-
-
-
-### Science Services
-
-
-
-
-
-
diff --git a/src/content/docs/esw/brushless-motors.md b/src/content/docs/esw/brushless-motors.md
deleted file mode 100644
index 53de8fb..0000000
--- a/src/content/docs/esw/brushless-motors.md
+++ /dev/null
@@ -1,140 +0,0 @@
----
-title: "Brushless Motors"
----
-# Brushless Motors (Moteus)
-
-## Project Overview (last updated 4/3/2024)
-
-The Moteus controllers are used to control the brushless motors on the rover. We use the Raspberry Pi and the Pi3Hat to communicate to the motei that are located by the drive and arm joints via CAN. The three arm brushless motors (Joints C, D, and E) are connected on one CAN bus, all the left drive wheels are connected on another CAN bus, and all the right drive wheels are connected on the last CAN bus (result in three total CAN buses).
-
----
-### _The following sections are in the order that they should be executed in._
-
-# Download Firmware
-Connect the moteus to CAN and power the moteus with ~36V. **Do not connect the motor yet.**
-
-If the moteus has never been used before, run tview with: `sudo python3 -m tview --target 1`
-
-Otherwise, run tview with the CAN ID of the moteus (in decimal). CAN IDs can be found in [the software commands document](https://docs.google.com/document/d/1xOSqh_SqRyvgayEssh9qdBPRjPWQhUd8Kiva0eOGTvw/edit?usp=sharing).
-
-In the Telemetry tab, check the Firmware Version. If it is not 262, you will need to update the firmware.
-
-To update firmware, go to the [releases page](https://github.com/mjbots/moteus/releases) on the MJBots Github. Download the most recent firmware version available, this is the .elf file that does **not** have the word "bootloader" in it.
-
-Once the .elf is downloaded, make sure the .elf is in the Downloads folder and run the command ``.
-
-# Configure Moteus (Hall encoder)
-1. Look at which Aux connector the Hall encoder should be wired to. Aux ports are labeled on the Moteus.
-2. Using the [tables in the MJBots Reference Document](https://github.com/mjbots/moteus/blob/main/docs/reference.md#pin-options) figure out which Aux pin numbers the 3 Hall lines are connected to.
-
-For Aux1:
-
-
-
-For Aux2:
-
-
-
-To read the tables, match the labeling on the Moteus to the Aux Pin number in the same row.
-
-3. Update the Moteus config in tview to match, check all Aux1 and Aux2 configurations by using the dropdown menus in the Config tab on tview.
-4. Change the CAN ID to the appropriate ID by finding and editing the Device ID. Make sure the set the CAN ID using decimal numbers.
-5. In the terminal in tview, run the command `conf write`.
-6. Close tview
-
-# Run Calibration
-Make sure the moteus is **powered off** then plug the phase wires and encoder wires into the moteus. Connect the moteus CAN.
-
-Make sure the motor is secured and positioned so that it can spin freely. It may vibrate slightly during calibration so be careful. The black "housing" part of the motor will also spin.
-
-In the terminal run the following command:
-
-`sudo python3 -m moteus.moteus_tool --target --calibrate --cal-hall --cal-motor-poles `
-
-The number of poles and CANIDs can be found in [the software commands document](https://docs.google.com/document/d/1xOSqh_SqRyvgayEssh9qdBPRjPWQhUd8Kiva0eOGTvw/edit?usp=sharing).
-
-# PID Tuning
-TODO
-
-# Commit a working version of the configuration
-
-
-# Set up additional hardware
-All motei need a commutation source, for Rover applications this would be the hall encoder. Any other encoders or hardware that need to be set up for the moteus firmware to handle need to be on the other Aux port. For example, if using a hall encoder on Aux1, the absolute encoder must be on Aux2.
-## Absolute Encoder
-The moteus supports a limited selection of absolute encoders. We use the [AS5048B](https://look.ams-osram.com/m/287d7ad97d1ca22e/original/AS5048-DS000298.pdf).
-
-Configure the moteus to read the absolute encoder data:
-1. Configure I2C device 0 on the Aux port that the absolute encoder is wired to to be type: AS5048
-2. If there is only one absolute encoder on the moteus, the address should be 64. If there are multiple absolute encoders, refer to the reference sheet and selection pins
-3. Change the motor_position.output or motor_position.reference_source as needed
-
-## Limit switches
-We handle limit switches in application layer code (ROS). However, we need to set the moteus up to have data on the limit switches ready.
-1. Change the Pins configuration in tview. Go to aux[1,2]->Pins. Configure the pin(s) that the limit switch(s) are connected to to be digital_in and pull_up.
-2. Check that the pin values are updating as expected with the pin value in the Telemetry tab. Connect the limit switches and press them to see the values change. The values are a decimal conversion of binary bits based on which pins are high or low.
-
-# Other helpful commands
-## Resetting all Moteus configs
-If restarting with Moteus setup, you can connect to the Moteus in tview and run the command `conf default`. Note: this will change the CAN ID back to 1 as well as configure the Moteus to use SPI.
-
-## Check Hall States with Moteus
-To check if the motor's hall encoders are working or if the Hall configurations on the Moteus is set up correctly:
-1. Connect the motor encoder wires to the Moteus
-2. Open tview and go to the telemetry tab. Under the Aux port that the encoder is connected to, click Hall and read the Bits value as you turn the motor by hand.
-3. Bits values should be 1, 2, 3, 4, 5, 6. If you see any numbers other than these (0 or 7) or not all of those numbers, either the Hall sensor in the motor is broken, the wiring between the hall encoder and the Moteus is wrong/bad, and/or the configuration in the Moteus is wrong.
-
-## Configuration and PID tuning
-
-To configure the moteus, you would first like to change some of the settings through the GUI called tview. Settings you'd like to change include the current limit, PID values, CAN ID, and others.
-
-To save a particular configuration, use `sudo moteus_tool -t X --dump-config > filename.cfg`. Run this through the the moteusConfigCalib.py script found in /scripts/moteusConfigCalib.py. It will spit out "filename_write.cfg". You can use `sudo moteus_tool -t X --write-config filename_write.cfg` to write the config to moteus X.
-
-To open tview, run ```python3 -m moteus_gui.tview```. If you would like to run various targets, run something like ```python3 -m moteus_gui.tview --target 1,2```. If you are unable to detect a CAN-FD transport (if you have the fdcanusb connected), you should run the command ```sudo chmod a+rw /dev/ttyACM0```.
-
-In case you want to configure the Moteus Manually you can follow these steps:
-* In order to set the CAN ID open config > id > change value to desired ID
-
-* Re-open tview and run `conf write`
-* Open aux 2 or the port (your hall lines are on) int the config page of tview
-* Disable spi
-* Set hall enable to true
-* Set pins 2 and 3 to work on hall mode (these are the debug pins on the Moteus), also enable pull ups
-* Find out if the 3rd pin is connected to pin 1 or pin 0 [here](https://github.com/mjbots/moteus/blob/main/docs/reference.md#aux2--abs), set that to work on hall mode also enable pull ups.
-
-* Go to motor position > sources > 0 > aux number and set it to 2, also set it to hall mode
-
-* Go to config => servo => pid_position; set the PID values
- kp = 0.5; ki = 0; kd = 0.05 for the Maxon motors.
-* Set max current to 4 A
-* Set max_position_slip to 10
-
-* config > servopos > position_min = nan
-* config > servopos > position_max = nan
-
-* Run `conf write` to save the configuration to memory
-
-Changing the I limit does not do anything if the ilimit is 0 (which is fine for basic velocity control applications).
-
-## Watchdog
-
-A watchdog timeout of 1.0 seconds is used.
-If communication between the jetson_teleop node and the brushless_motors node is lost (after 0.1s), then the brushless_motors node will tell the moteus to turn its velocity to 0. This basically means means that jetson_teleop stopped receiving updated commands from the basestation (or from navigation).
-
-If communication between the rover node and moteus is lost (if the moteus does not receive a new CAN message after 0.1s), then the moteus driver will be placed in brake mode.
-
-MOTEUS_RESPONSE_TIME_INDICATING_DISCONNECTED_S = 0.01
-ROVER_NODE_TO_MOTEUS_WATCHDOG_TIMEOUT_S = 0.1
-
-# Appendix
-
-### Pinout
-
-Source is Moteus Documentation Google Sheet
-
-
-### Topics
-
-Source is Teleop ESW ICD Sheet Google Sheets
-
-
diff --git a/src/content/docs/esw/brushless-ros.md b/src/content/docs/esw/brushless-ros.md
deleted file mode 100644
index 753519d..0000000
--- a/src/content/docs/esw/brushless-ros.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-title: "Brushless ROS"
----
-**Context**: On our rover, we have brushless motors. We control them using brushless motor controllers called Moteus.
-
-
-
-**Problem**: We need to write ROS programs that communicate with these brushless motor controllers. Teleop will ask ESW to move the joints/motors, and ESW's ROS node needs to tell eventually communicate to the motors over CAN about how to reach that target (target velocity or target position).
-
-**Solution**:
-
-* Develop all the ROS software in C++.
-* Implement the bridge software
-* Implement the motor_library library software for the brushless side only
-* Implement the CAN node (technically a separate project but it is very closely related)
-
-**Interface**:
-
-* There is currently not a good description of the interface since it is still in the works of being developed
-* However, we can expect the ROS node to be able to do the following: Send velocity commands in terms of rad/s. Receive and process angular data based on encoder/hall effector sensor data. More.
-* See the below picture to see how the software that you are writing fits into the bigger picture
-
-
-
-**Rough Steps To Get Started**:
-
-* Get the developer kit running using the GUI
-* Talk to the moteus with a C++ testing file (either move at a certain velocity, or continuously print out angles)
-* Integrate software with rest of actual brushless motor control
-* Need to see how to send the moteus commands as raw commands
diff --git a/src/content/docs/esw/camera-streaming.md b/src/content/docs/esw/camera-streaming.md
deleted file mode 100644
index 48e7c17..0000000
--- a/src/content/docs/esw/camera-streaming.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "Camera Streaming"
----
-**Context**: At URC we are not allowed to look directly at the rover. Instead we are in a "basestation" which is sealed off. Thus we need a camera stream to view what is happening near the rover.
-
-**Problem**: GStreamer is finicky and unreliable. At URC it cut out and we did not regain it. It also is such a general tool that it suffers performance issues - we could get a much faster and robust stream by writing some custom code for known hardware.
-
-**Solution**:
-
-* Use the [NVIDIA Video Encoder API](https://docs.nvidia.com/video-technologies/video-codec-sdk/11.1/nvenc-video-encoder-api-prog-guide/index.html) directly on the Jetson. Encode using H.265 (HVEC) which is better than H.264 (previously used).
-* Connect a websocket on the basestation to a POSIX socket on the Jetson. Forward bytes outputed by the encoder to this stream.
-* Use [emscripten](https://emscripten.org/) to compile a H.265 C library (such as [libde265](https://github.com/strukturag/libde265)) that parses the input stream and converts it to a video directly in the browser. Draw it to a canvas.
\ No newline at end of file
diff --git a/src/content/docs/esw/canalyzer.md b/src/content/docs/esw/canalyzer.md
deleted file mode 100644
index fb10bd2..0000000
--- a/src/content/docs/esw/canalyzer.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: "CANalyzer"
----
-# CANalyzer
-
-CANalyzer will be a custom CAN bus analyzer tool device. The end-goal is to have a fully embedded
-device that can be used to monitor and log CAN bus traffic. Use a Raspberry Pi with an FDCANUSB or PiCAN FD HAT to receive and handle any traffic on a CAN bus using SocketCAN.
-
-## Project Goals
-
-- **Real-time Monitoring:** Display CAN bus messages in a structured and easy-to-read format
-- **Custom CAN Message Handling:** Implement support for our team's custom CAN message format
-- **Filter and Search:** Implement filters to allow users to focus on specific CAN IDs or data patterns using custom configurations provided in a .yaml file.
-- **Logging:** Enable saving of CAN bus data to a file (.asc or .log) for later analysis
-- **Replaying Logs:** Ensure that log files are properly formatted in order to replay logs for testing using the [can-utils](https://manpages.debian.org/testing/can-utils/candump.1.en.html) Linux package or something similar.
-- **Other Thoughts:** Add capability for adjusting CAN message format - extended/standard ID, BRS on/off, etc.
diff --git a/src/content/docs/esw/directional-antenna.md b/src/content/docs/esw/directional-antenna.md
deleted file mode 100644
index fd94190..0000000
--- a/src/content/docs/esw/directional-antenna.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Directional Antenna"
----
-## Context
-During the previous year's competition cycle, we struggled with retaining line of sight for communications. We are hoping to improve on this by developing a directional antenna that can track the rover's position and point towards it, helping us retain line of sight as much as possible. This project is currently in the Research and Testing (RAT) stage, so if you are interested, I would recommend going to RAT subteam meetings as they are the ones primarily working on it. Once design has been finalized, this may become a future localization project!
\ No newline at end of file
diff --git a/src/content/docs/esw/electrical-system-overview.md b/src/content/docs/esw/electrical-system-overview.md
deleted file mode 100644
index 5d88bb4..0000000
--- a/src/content/docs/esw/electrical-system-overview.md
+++ /dev/null
@@ -1,44 +0,0 @@
----
-title: "Electrical System Overview"
----
-# Intro
-
-In order to understand the embedded system of the rover, it is first important to understand the electrical system of the rover.
-Below is the electrical system information for the 2023 rover Dahlia.
-
----
-
-## EBox
-
-Our rover uses one 40 V Li-ion battery to power on the entire rover. The battery voltage goes into a power distribution board (PDB) PCB. Multiple converters on the PDB drop the voltage levels into other voltage lines (3.3V, 5V, and 12V). We also have an 24V converter that is separate from the PDB.
-
-There is an MCU board. This board takes in 12V as an input. It has 3 MCUs (the STM32 MCU): 2 of them are used for controlling brushed motors (communicating with the Arduino Uno UART to I2C bridge via I2C) and 1 of them is used for controlling science operations and controlling MOSFETs (communicating via UART). There are various MOSFETs on the MCU board.
-
-There is an ethernet switch inside the rover and a POE used for handling communication between the radio and the two main devices on the rover (Jetson Xavier and Raspberry Pi).
-
-The Jetson Xavier is powered using the 12V line. It has the USB hub connected to it, and also has the GPS, IMU, Raman nucleo, cameras, and Arduino Uno used to control the Auton LEDs. It also connects to the science MCU located on the MCU board using UART (two wires).
-
-The Arduino Uno used to control the Auton LEDs takes in serial messages (over USB) from the Jetson Xavier and controls pins that connect to the auton LED PCB. There are 4 wires that are connected between the Arduino Uno and the Auton LED PCB.
-
-Our Auton LED PCB takes in 3.3V and it has 3 inputs that are used to control each of the auton LEDs (red, green, and blue). When the input goes low, then the LED turns on since there is a voltage differential between the 3.3V and the input that has been pulled low. When the input goes high (either 3.3V - 5V or disconnected), the LED turns off since there is no completed circuit or because there is no voltage differential in the correct direction of the diode.
-
-The Raspberry Pi 4 has a pi3hat on it. The pi3hat takes in 12V and it powers the Raspberry Pi 4 too. The pi3hat is connected to 3 CAN buses (2 for drive and 1 for arm). The Raspberry Pi is connected to an Arduino Uno used as an UART to I2C bridge connected to it.
-
-The Arduino Uno used as a UART to I2C bridge is used to convert serial messages (over USB) from the Jetson to I2C to the motors MCU. This was added because the current MCU board was likely killing I2C pins on the Raspberry Pi and Jetson Xavier, so it was added as a temporary solution. It has two UART wires connected to the Jetson and two I2C wires connected to the MCU board.
-
----
-
-## Drive
-
-Because there are 6 wheels, we have 6 brushless motor controllers (moteus) placed beside each wheel to control it. Each moteus takes 36V. The three moteus on the left suspension are on one CAN bus while the other three moteus on the right suspension are on one CAN bus.
-
----
-
-## Arm
-
-Only joints C, D, and E use brushless motors (everything else uses brushed motors). Each moteus takes 36V. All of the moteus are on one CAN bus, separate from the CAN buses on the drive system.
-
-
-
-
-
diff --git a/public/esw-dev/archive/3bm-architecture.webp b/src/content/docs/esw/extra/archive/3bm-architecture.webp
similarity index 100%
rename from public/esw-dev/archive/3bm-architecture.webp
rename to src/content/docs/esw/extra/archive/3bm-architecture.webp
diff --git a/src/content/docs/esw/archive.md b/src/content/docs/esw/extra/archive/index.md
similarity index 64%
rename from src/content/docs/esw/archive.md
rename to src/content/docs/esw/extra/archive/index.md
index 2ac085d..1fc37c6 100644
--- a/src/content/docs/esw/archive.md
+++ b/src/content/docs/esw/extra/archive/index.md
@@ -2,8 +2,6 @@
title: "Archive"
---
-# Archive
-
This page contains archived documentation for older projects.
## 3BM (2024-2025)
@@ -27,19 +25,19 @@ timers.
Below is a diagram of the 3BM architecture.
-
+
### Timer Overview
The 3BM uses seven hardware timers:
-- **htim1** (`PWM_TIMER_[0,1,2]`): PWM timer for the three motors (`TIM_CHANNEL_[0,1,2]` for motor [0,1,2], respectively)
-- **htim2** (`GENERIC_ELAPSED_TIMER`): Repeating count up timer where each tick is 0.001 ms (1000 ns). It used used by:
- - The absolute and quadrature encoder to measure how much time has elapsed since the last reading in order to measure velocity
- - The PIDF controller in order to measure the time elapsed since the last reading to update the "D" term
-- **htim4** (`QUADRATURE_TICK_TIMER`): Incremental encoder timer configured to read a two-phase quadrature encoder
-- **htim6** (`GLOBAL_UPDATE_TIMER`): 20 Hz timer which triggers a CAN FD transmit (sends motor state)
-- **htim15**, **htim16**, **htim17** (`RECEIVE_WATCHDOG_TIMER_[0,1,2]`): FDCAN watchdog timer that needs to be reset every time a message is received
+- **htim1** (`PWM_TIMER_[0,1,2]`): PWM timer for the three motors (`TIM_CHANNEL_[0,1,2]` for motor \[0,1,2\], respectively)
+- **htim2** (`GENERIC_ELAPSED_TIMER`): Repeating count up timer where each tick is 0.001 ms (1000 ns). It used used by:
+ - The absolute and quadrature encoder to measure how much time has elapsed since the last reading in order to measure velocity
+ - The PIDF controller in order to measure the time elapsed since the last reading to update the "D" term
+- **htim4** (`QUADRATURE_TICK_TIMER`): Incremental encoder timer configured to read a two-phase quadrature encoder
+- **htim6** (`GLOBAL_UPDATE_TIMER`): 20 Hz timer which triggers a CAN FD transmit (sends motor state)
+- **htim15**, **htim16**, **htim17** (`RECEIVE_WATCHDOG_TIMER_[0,1,2]`): FDCAN watchdog timer that needs to be reset every time a message is received
## SA Arduino (2024-2025)
diff --git a/src/content/docs/esw/extra/build-docs.md b/src/content/docs/esw/extra/build-docs.md
new file mode 100644
index 0000000..891b430
--- /dev/null
+++ b/src/content/docs/esw/extra/build-docs.md
@@ -0,0 +1,15 @@
+---
+title: "Building These Docs"
+---
+
+These docs are served using [zensical](https://zensical.org/) and are built from the source files in this repository.
+
+In order to test and build the docs locally, you must first install zensical and plugins.
+These dependencies are included in the `tools/venv` virtual environment.
+
+Then, you can run the following command in the root directory of the repo (where `zensical.toml` is located)
+to start a local server:
+
+```bash
+zensical serve
+```
diff --git a/src/content/docs/esw/cmake-cubemx.md b/src/content/docs/esw/extra/cmake-cubemx.md
similarity index 95%
rename from src/content/docs/esw/cmake-cubemx.md
rename to src/content/docs/esw/extra/cmake-cubemx.md
index 62f2326..ce0c242 100644
--- a/src/content/docs/esw/cmake-cubemx.md
+++ b/src/content/docs/esw/extra/cmake-cubemx.md
@@ -1,10 +1,8 @@
---
-title: "CMake + CubeMX Toolchain"
+title: "CMake + CubeMX/CubeCLT Toolchain"
---
-# CMake + CubeMX/CubeCLT Toolchain
-
-In [Getting Started/STM32Cube](/esw-dev/getting-started/stm32cube), we went over how to set up the
+In [Getting Started/STM32Cube](/esw/getting-started/stm32cube), we went over how to set up the
STM32Cube toolchain utilizing our own scripts and CMakeLists.txt templates to setup and build the projects.
This document covers the manual approach of invoking CubeMX and CubeCLT directly.
@@ -12,7 +10,7 @@ This document covers the manual approach of invoking CubeMX and CubeCLT directly
## Prerequisites
Please install STM32CubeMX and STM32CubeCLT by following the instructions in the
-[Getting Started/STM32Cube](/esw-dev/getting-started/stm32cube) document.
+[Getting Started/STM32Cube](/esw/getting-started/stm32cube) document.
## 1. Creating a New CubeMX Project
@@ -144,4 +142,4 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
## 3. Building and Flashing
You can now build the CMake project as you would normally or by using our build script as
-described in [Getting Started/STM32Cube](/esw-dev/getting-started/stm32cube).
+described in [Getting Started/STM32Cube](/esw/getting-started/stm32cube).
diff --git a/src/content/docs/esw/getting-started/intro.md b/src/content/docs/esw/getting-started/intro.md
index 8be3aff..49dcb88 100644
--- a/src/content/docs/esw/getting-started/intro.md
+++ b/src/content/docs/esw/getting-started/intro.md
@@ -1,10 +1,8 @@
---
-title: "ESW Introduction"
+title: "Introduction"
---
-# Introduction
-
-Welcome to MRover Embedded Software! The Getting Started section is designed to get you up and
+Welcome to ESW! The Getting Started section is designed to get you up and
running as smooth as possible. It consists of three starter projects to help you get experience with
using microcontrollers and communication protocols, as well as gain familiarity with the tools we use.
There is also useful information linked below to supplement the starter projects.
@@ -13,16 +11,16 @@ There is also useful information linked below to supplement the starter projects
All new members are asked to complete the following:
-1. [Install STM32Cube* Tools](/esw-dev/getting-started/stm32cube)
-2. [Starter Project: LED](/esw-dev/getting-started/starter-led)
-3. [Starter Project: Servo Part 1](/esw-dev/getting-started/starter-servo-pwm)
-4. [Starter Project: Servo Part 2](/esw-dev/getting-started/starter-servo-can)
-5. [Starter Project: Temperature and Humidity Sensor](starter/temp-humidity/index.md)
+1. [Install STM32Cube\* Tools](/esw/getting-started/stm32cube)
+2. [Starter Project: LED](/esw/getting-started/starter/led)
+3. [Starter Project: Servo Part 1](/esw/getting-started/starter/servo/part1-pwm)
+4. [Starter Project: Servo Part 2](/esw/getting-started/starter/servo/part2-can)
+5. [Starter Project: Temperature and Humidity Sensor](/esw/getting-started/starter/temp-humidity)
As everyone comes from varying levels of experience, extra information is provided in these docs to
assist the learning process. Please do not hesitate to ask for help!
Some helpful references include:
-1. [Intro to Nucleos](../info/nucleos.md)
-2. [Communication Protocols](/esw-dev/info/communication-protocols)
+1. [Intro to Nucleos](/esw/info/nucleos)
+2. [Communication Protocols](/esw/info/communication-protocols)
diff --git a/public/esw-dev/led/g4-button-pin.webp b/src/content/docs/esw/getting-started/starter/led/g4-button-pin.webp
similarity index 100%
rename from public/esw-dev/led/g4-button-pin.webp
rename to src/content/docs/esw/getting-started/starter/led/g4-button-pin.webp
diff --git a/public/esw-dev/led/g4-led-pin.webp b/src/content/docs/esw/getting-started/starter/led/g4-led-pin.webp
similarity index 100%
rename from public/esw-dev/led/g4-led-pin.webp
rename to src/content/docs/esw/getting-started/starter/led/g4-led-pin.webp
diff --git a/src/content/docs/esw/getting-started/starter-led.md b/src/content/docs/esw/getting-started/starter/led/index.md
similarity index 93%
rename from src/content/docs/esw/getting-started/starter-led.md
rename to src/content/docs/esw/getting-started/starter/led/index.md
index 8affaed..108fe3b 100644
--- a/src/content/docs/esw/getting-started/starter-led.md
+++ b/src/content/docs/esw/getting-started/starter/led/index.md
@@ -1,9 +1,7 @@
---
-title: "Starter Project: LED"
+title: "LED Starter Project"
---
-# LED Starter Project
-
## About
This tutorial is intended to get you more familiar with a Nucleo
@@ -29,22 +27,22 @@ As you walk through the guide, keep the following questions in mind:
## Prerequisites
-* STM32CubeMX [installed](/esw-dev/getting-started/stm32cube)
+* STM32CubeMX [installed](/esw/getting-started/stm32cube)
* STM32G431RB Nucleo (pictured below)
-
+
## Guide
-Open up CubeMX and create a new project called tutorial by following the steps in the [CubeMX New Project Guide](/esw-dev/getting-started/stm32cube#creating-a-new-project).
+Open up CubeMX and create a new project called tutorial by following the steps in the [CubeMX New Project Guide](/esw/getting-started/stm32cube#creating-a-new-project).
When creating a new project, the pins are not configured by default. This matters because on the Nucleo, the button and the LED are already connected to a particular pin so we need to change the pin's functionality if we want to use it. In order to determine which pins are connected to the button and the LED, one can visit [this](https://os.mbed.com/platforms/ST-Nucleo-G474RE/) page.
On this page, you will find some pinouts. Based on the pinouts, you should be able to tell that the button is connected to pin PC13 and that the LED is connected to PA5.
-
+
-
+
Head back to the CubeMX and open the .ioc file if it is not open already. You should be able to see a graphical interface with the chip on it.
@@ -52,13 +50,13 @@ The first thing we want to do is set PC13 pin (which is connected to the push bu
On the graphical interface (also called the .ioc file), locate PC13 and click on it. Then select GPIO_Input to change its configuration.
-
+
The next thing we want to do is set PA5 (which is connected to the LED) to be a GPIO output. This means that we will be able to make the pin either be set to 3.3V (high) or 0V (low). By default, the pin starts off as low.
On the .ioc file, locate PA5 and click on it. Select GPIO_Output to change its configuration. You may need to scroll down a bit. Note that the pin may already be set to GPIO_Output by default, so you may choose to not do anything new.
-
+
Optionally, right click on PC13 and select "Enter User Label" can give it a useful name, such as `BUTTON`. Do the same for PA5, but call it `LED`.
diff --git a/public/esw-dev/led/nucleo-g431.webp b/src/content/docs/esw/getting-started/starter/led/nucleo-g431.webp
similarity index 100%
rename from public/esw-dev/led/nucleo-g431.webp
rename to src/content/docs/esw/getting-started/starter/led/nucleo-g431.webp
diff --git a/public/esw-dev/led/pa5.webp b/src/content/docs/esw/getting-started/starter/led/pa5.webp
similarity index 100%
rename from public/esw-dev/led/pa5.webp
rename to src/content/docs/esw/getting-started/starter/led/pa5.webp
diff --git a/public/esw-dev/led/pc13.webp b/src/content/docs/esw/getting-started/starter/led/pc13.webp
similarity index 100%
rename from public/esw-dev/led/pc13.webp
rename to src/content/docs/esw/getting-started/starter/led/pc13.webp
diff --git a/public/esw-dev/servo/breadboard_diagram.webp b/src/content/docs/esw/getting-started/starter/servo/breadboard_diagram.webp
similarity index 100%
rename from public/esw-dev/servo/breadboard_diagram.webp
rename to src/content/docs/esw/getting-started/starter/servo/breadboard_diagram.webp
diff --git a/public/esw-dev/servo/copy-git-repo.webp b/src/content/docs/esw/getting-started/starter/servo/copy-git-repo.webp
similarity index 100%
rename from public/esw-dev/servo/copy-git-repo.webp
rename to src/content/docs/esw/getting-started/starter/servo/copy-git-repo.webp
diff --git a/public/esw-dev/servo/create_header.webp b/src/content/docs/esw/getting-started/starter/servo/create_header.webp
similarity index 100%
rename from public/esw-dev/servo/create_header.webp
rename to src/content/docs/esw/getting-started/starter/servo/create_header.webp
diff --git a/public/esw-dev/servo/create_source.webp b/src/content/docs/esw/getting-started/starter/servo/create_source.webp
similarity index 100%
rename from public/esw-dev/servo/create_source.webp
rename to src/content/docs/esw/getting-started/starter/servo/create_source.webp
diff --git a/public/esw-dev/servo/fdcan-config.webp b/src/content/docs/esw/getting-started/starter/servo/fdcan-config.webp
similarity index 100%
rename from public/esw-dev/servo/fdcan-config.webp
rename to src/content/docs/esw/getting-started/starter/servo/fdcan-config.webp
diff --git a/public/esw-dev/servo/main_include.webp b/src/content/docs/esw/getting-started/starter/servo/main_include.webp
similarity index 100%
rename from public/esw-dev/servo/main_include.webp
rename to src/content/docs/esw/getting-started/starter/servo/main_include.webp
diff --git a/public/esw-dev/servo/name_header.webp b/src/content/docs/esw/getting-started/starter/servo/name_header.webp
similarity index 100%
rename from public/esw-dev/servo/name_header.webp
rename to src/content/docs/esw/getting-started/starter/servo/name_header.webp
diff --git a/public/esw-dev/servo/new_thermistor.webp b/src/content/docs/esw/getting-started/starter/servo/new_thermistor.webp
similarity index 100%
rename from public/esw-dev/servo/new_thermistor.webp
rename to src/content/docs/esw/getting-started/starter/servo/new_thermistor.webp
diff --git a/src/content/docs/esw/getting-started/starter-servo-pwm.md b/src/content/docs/esw/getting-started/starter/servo/part1-pwm.md
similarity index 95%
rename from src/content/docs/esw/getting-started/starter-servo-pwm.md
rename to src/content/docs/esw/getting-started/starter/servo/part1-pwm.md
index 27a1e1f..d5cefab 100644
--- a/src/content/docs/esw/getting-started/starter-servo-pwm.md
+++ b/src/content/docs/esw/getting-started/starter/servo/part1-pwm.md
@@ -1,9 +1,7 @@
---
-title: "Starter Project: Servo - PWM"
+title: "Servo Starter Project - Part 1 - PWM"
---
-# Servo Starter Project - Part 1 - PWM
-
This starter project is made up of two parts: PWM and CAN. This is Part 1 - PWM.
By the end of this part, you should have an understanding of timers and PWM (pulse width modulation)
@@ -15,7 +13,7 @@ so please reach out if you ever get stuck!
## Prerequisites
-- STM32Cube [installed](/esw-dev/getting-started/stm32cube)
+- STM32Cube [installed](/esw/getting-started/stm32cube)
- LED Project [completed](https://github.com/umrover/embedded-testbench/wiki/Nucleo-LED-Starter-Project) and shown to an ESW lead
- Git installed and [basic knowledge of how to use it](https://github.com/umrover/mrover-ros2/wiki/Git)
- STM32G431RB Nucleo
@@ -38,7 +36,7 @@ Since you already have practice creating a project, you will only need to clone
premade STM32 project for this starter project.
Go to [this repository](https://github.com/umrover/mrover-esw), click the "Code" tab, and copy the SSH URL.
-
+
You now have the URL you need to clone the project.
@@ -70,11 +68,11 @@ Once the .ioc is open, configure the pins for PWM.
2. On the left side of the .ioc file, under Timers, select TIM1 (shown below).
3. Change Channel1 from "Disable" to "PWM Generation CH1" (shown below).
-
+
We will now have to configure two values—Prescaler and Counter Period—in order to
correctly set up this PWM timer. These values are located in the "Parameter Settings" and must be
-calculated. Refer to the timer [reference guide](/esw-dev/info/timers) for information on
+calculated. Refer to the timer [reference guide](/esw/info/timers) for information on
calculating these values.
Read the [datasheet](http://www.ee.ic.ac.uk/pcheung/teaching/DE1_EE/stores/sg90_datasheet.pdf) for
@@ -182,7 +180,7 @@ In order to properly wire the servo, first consult the [datasheet](http://www.ee
#### Using a Breadboard
A breadboard is broken into two sets of long rails on the outside edges of the board and multiple shorter rails on the inner part of the board. These rails allow for easy connections between wires on the same rail. Below is a picture depicting these rails.
-
+
In order for the signal to work, the servo and the Nucleo must have a common ground. Connect the servo's ground wire to one of the ground pins on the Nucleo, the power to the appropriate power pin on the Nucleo, and the signal wire to PC0.
diff --git a/src/content/docs/esw/getting-started/starter-servo-can.md b/src/content/docs/esw/getting-started/starter/servo/part2-can.md
similarity index 93%
rename from src/content/docs/esw/getting-started/starter-servo-can.md
rename to src/content/docs/esw/getting-started/starter/servo/part2-can.md
index 3394fd9..ad9f1c7 100644
--- a/src/content/docs/esw/getting-started/starter-servo-can.md
+++ b/src/content/docs/esw/getting-started/starter/servo/part2-can.md
@@ -1,9 +1,7 @@
---
-title: "Starter Project: Servo - CAN"
+title: "Servo Starter Project - Part 2 - CAN"
---
-# Servo Starter Project - Part 2 - CAN
-
This starter project is made up of two parts: PWM and CAN. This is Part 2 - CAN.
In this project, you will be using the CAN peripheral on the STM32G431RB Nucleo to send a CAN
@@ -14,14 +12,14 @@ the specified angle. By the end of this part, you should have an understanding o
Just as a reminder, if you have any questions, feel free to reach out to any ESW lead or member.
-***Before starting this project***, please give the [CAN info page](/esw-dev/info/communication-protocols#can)
+***Before starting this project***, please give the [CAN info page](/esw/info/communication-protocols#can)
a read. It will get you start on the basics of CAN communication. ***Do not read "Using the Kvaser Bit Timing Calculator."***
## Prerequisites
-* STM32Cube [installed](/esw-dev/getting-started/stm32cube)
-* LED Starter Project [completed](/esw-dev/getting-started/starter-led) and shown to an ESW lead
-* Servo Part 1 Starter Project [completed](/esw-dev/getting-started/starter-servo-pwm) and shown to an ESW lead
+* STM32Cube [installed](/esw/getting-started/stm32cube)
+* LED Starter Project [completed](/esw/getting-started/starter/led) and shown to an ESW lead
+* Servo Part 1 Starter Project [completed](/esw/getting-started/starter/servo/part1-pwm) and shown to an ESW lead
* STM32G431RB Nucleo
* MCP2551 CAN tranceiver
@@ -49,7 +47,7 @@ the servo will rotate to 90 degrees.
Once the .ioc is open, activate the FDCAN peripheral. We can do this by clicking on the FDCAN
peripheral in the `Connectivity` tab on the left side of the .ioc. Then, check the `Activated` box.
-
+
Next, we need to configure the timings for the CAN bus. Click on the `Parameter Settings` tab
(as shown above). We will be using CAN 2.0B *not* CAN FD, so `Frame Format` should be set to
@@ -61,11 +59,11 @@ only need to properly set the following values:
3. Nominal Time Seg 1
4. Nominal Time Seg 2
-Again, please refer to the [CAN info page](/esw-dev/info/communication-protocols#can) for
+Again, please refer to the [CAN info page](/esw/info/communication-protocols#can) for
more information on these values.
There is a very in depth guide to configuring these values for STM32 MCUs in the
-[CAN FD Bit Timing](/esw-dev/info/communication-protocols#can-bit-timing) section of the
+[CAN FD Bit Timing](/esw/info/communication-protocols#can-bit-timing) section of the
docs. However, for the purposes of this starter project, you can use [this online calculator](https://phryniszak.github.io/stm32g-fdcan/)
designed for STM32G4 boards. Our FDCAN peripheral is clocked at 72 MHz, and the CAN bus we are
trying to communicate on is running at 500 kbps. The calculator will give you the values you need
diff --git a/public/esw-dev/servo/servo-timer-config.webp b/src/content/docs/esw/getting-started/starter/servo/servo-timer-config.webp
similarity index 100%
rename from public/esw-dev/servo/servo-timer-config.webp
rename to src/content/docs/esw/getting-started/starter/servo/servo-timer-config.webp
diff --git a/public/esw-dev/temp-humidity/aht20.webp b/src/content/docs/esw/getting-started/starter/temp-humidity/aht20.webp
similarity index 100%
rename from public/esw-dev/temp-humidity/aht20.webp
rename to src/content/docs/esw/getting-started/starter/temp-humidity/aht20.webp
diff --git a/public/esw-dev/temp-humidity/g431rb.webp b/src/content/docs/esw/getting-started/starter/temp-humidity/g431rb.webp
similarity index 100%
rename from public/esw-dev/temp-humidity/g431rb.webp
rename to src/content/docs/esw/getting-started/starter/temp-humidity/g431rb.webp
diff --git a/src/content/docs/esw/getting-started/starter-temp-humidity.md b/src/content/docs/esw/getting-started/starter/temp-humidity/index.md
similarity index 98%
rename from src/content/docs/esw/getting-started/starter-temp-humidity.md
rename to src/content/docs/esw/getting-started/starter/temp-humidity/index.md
index 432e8ed..18a0b1a 100644
--- a/src/content/docs/esw/getting-started/starter-temp-humidity.md
+++ b/src/content/docs/esw/getting-started/starter/temp-humidity/index.md
@@ -1,20 +1,18 @@
---
-title: "Starter Project: Temperature & Humidity"
+title: "Temperature and Humidity Starter Project"
---
-# Temperature and Humidity Starter Project
-
## About
The purpose of this starter project is to guide you through reading data from the AHT20 Temperature and Humidity Sensor using I2C with an STM32 Nucleo
## Hardware
* Nucleo STM32G431RB
-
+
* AHT20 Temperature and Humidity Sensor
-
+
* Lots of female-to-male, male-to-male, and female-to-female wires!
* 1 USB A to mini B cable
diff --git a/public/esw-dev/stm32cube/board-config.webp b/src/content/docs/esw/getting-started/stm32cube/board-config.webp
similarity index 100%
rename from public/esw-dev/stm32cube/board-config.webp
rename to src/content/docs/esw/getting-started/stm32cube/board-config.webp
diff --git a/public/esw-dev/stm32cube/board-select.webp b/src/content/docs/esw/getting-started/stm32cube/board-select.webp
similarity index 100%
rename from public/esw-dev/stm32cube/board-select.webp
rename to src/content/docs/esw/getting-started/stm32cube/board-select.webp
diff --git a/public/esw-dev/stm32cube/get-cubeclt.webp b/src/content/docs/esw/getting-started/stm32cube/get-cubeclt.webp
similarity index 100%
rename from public/esw-dev/stm32cube/get-cubeclt.webp
rename to src/content/docs/esw/getting-started/stm32cube/get-cubeclt.webp
diff --git a/public/esw-dev/stm32cube/get-cubemx.webp b/src/content/docs/esw/getting-started/stm32cube/get-cubemx.webp
similarity index 100%
rename from public/esw-dev/stm32cube/get-cubemx.webp
rename to src/content/docs/esw/getting-started/stm32cube/get-cubemx.webp
diff --git a/src/content/docs/esw/getting-started/stm32cube.md b/src/content/docs/esw/getting-started/stm32cube/index.md
similarity index 91%
rename from src/content/docs/esw/getting-started/stm32cube.md
rename to src/content/docs/esw/getting-started/stm32cube/index.md
index b1ee77f..d08f3b4 100644
--- a/src/content/docs/esw/getting-started/stm32cube.md
+++ b/src/content/docs/esw/getting-started/stm32cube/index.md
@@ -1,9 +1,7 @@
---
-title: "STM32Cube Tools"
+title: "STM32Cube\\*"
---
-# STM32Cube\*
-
## About
STM32CubeMX and STM32CubeCLT allow the user to write, compile, and flash code to the STM32 microcontroller!
@@ -12,17 +10,18 @@ STM32CubeMX contains the interface for configuring the microcontroller and proje
a very powerful interface for automatic code generation, allowing the user to initialize an entire module with
a few clicks of a button, and have that code show up automatically in the main file.
-:::note
-If you've taken EECS 373, you have likely used STM32CubeIDE, which is an IDE that packages both of these tools
-together with Eclipse. However, STM32CubeIDE is a very heavy program, and newer versions no longer integrate with CubeMX,
-so we choose to use the lighter weight STM32CubeMX and STM32CubeCLT tools in combination with CMake and your favorite
-text editor or IDE.
-:::## Downloading and Installing CubeMX
+!!! note
+ If you've taken EECS 373, you have likely used STM32CubeIDE, which is an IDE that packages both of these tools
+ together with Eclipse. However, STM32CubeIDE is a very heavy program, and newer versions no longer integrate with CubeMX,
+ so we choose to use the lighter weight STM32CubeMX and STM32CubeCLT tools in combination with CMake and your favorite
+ text editor or IDE.
+
+## Downloading and Installing CubeMX
### 1. Download CubeMX
1. Go to the CubeMX [download page](https://www.st.com/en/development-tools/stm32cubemx.html) and scroll down to "Get Software."
- 
+ 
2. **_For this walkthrough, we will be using the Linux installer for UBUNTU USERS._**
Click on "Select Version", then select the **newest version** for the **_correct OS you are running!!!_**
@@ -116,7 +115,7 @@ which STM32CubeMX
### 1. Download CubeCLT
1. Go to the CubeCLT [download page](https://www.st.com/en/development-tools/stm32cubeclt.html) and scroll down to "Get Software."
- 
+ 
2. **_For this walkthrough, we will be using the Debian Linux installer for UBUNTU USERS._**
Click on "Select Version", then select the **newest version** for the **_correct OS you are running!!!_**
@@ -228,7 +227,7 @@ There are multiple ways to do this, but the way we will choose is to add the pat
2. Ensure that all the following paths exist in the file. If a path is missing, type it in on a new line.
Once you are done, make sure you write out (`^O`) and exit (`^X`).
- 
+ 
3. Restart your terminal. Ensure the paths you added have been added to your PATH environment variable
by running the command `echo $PATH`. You should see all the paths you added somewhere in the output.
@@ -244,7 +243,7 @@ will be developing on.
### Prerequisites
-- STM32CubeMX and STM32CubeCLT [installed](/esw-dev/getting-started/stm32cube)
+- STM32CubeMX and STM32CubeCLT [installed](/esw/getting-started/stm32cube)
### Guide
@@ -270,4 +269,4 @@ Open the `.ioc` file in STM32CubeMX to modify the project configuration
**Congratulations! You have successfully created a new project with CubeMX!**
-For information on how to do this process manually, refer to the [CMake + CubeMX/CubeCLT Toolchain](/esw-dev/extra/cmake-cubemx) document.
+For information on how to do this process manually, refer to the [CMake + CubeMX/CubeCLT Toolchain](/esw/extra/cmake-cubemx) document.
diff --git a/public/esw-dev/stm32cube/verify-paths-macos.webp b/src/content/docs/esw/getting-started/stm32cube/verify-paths-macos.webp
similarity index 100%
rename from public/esw-dev/stm32cube/verify-paths-macos.webp
rename to src/content/docs/esw/getting-started/stm32cube/verify-paths-macos.webp
diff --git a/src/content/docs/esw/img/favicon.ico b/src/content/docs/esw/img/favicon.ico
new file mode 100644
index 0000000..3759749
Binary files /dev/null and b/src/content/docs/esw/img/favicon.ico differ
diff --git a/src/content/docs/esw/img/logo.webp b/src/content/docs/esw/img/logo.webp
new file mode 100644
index 0000000..5486558
Binary files /dev/null and b/src/content/docs/esw/img/logo.webp differ
diff --git a/src/content/docs/esw/dev-intro.md b/src/content/docs/esw/index.md
similarity index 50%
rename from src/content/docs/esw/dev-intro.md
rename to src/content/docs/esw/index.md
index ddb0a8b..c29f249 100644
--- a/src/content/docs/esw/dev-intro.md
+++ b/src/content/docs/esw/index.md
@@ -1,16 +1,14 @@
---
-title: "ESW Overview"
+title: "MRover Embedded Software"
---
-# MRover Embedded Software
+Welcome to MRover Embedded Software (ESW)! The ESW team of MRover writes the driver code that allows
+the other programming subteams to utilize the electronic equipment on the rover. ESW works primarily
+with libraries in C, C++, and Python to abstract the functions needed by the other teams for easy use.
+To do this we use different communication protocols such as CAN and I2C to transmit and receive data
+from sensors, motors, and various other components.
-The embedded software team (ESW) of MRover writes the driver code that allows the other programming
-subteams to utilize the electronic equipment on the rover. ESW works primarily with libraries in C,
-C++, and Python to abstract the functions needed by the other teams for easy use. To do this we use
-different communication protocols such as CAN and I2C to transmit and receive data from sensors,
-motors, and various other components.
-
-New to ESW? Check out the [getting started page](/esw-dev/getting-started/intro) for developer setup and starter projects.
+New to ESW? Check out the [getting started page](/esw/getting-started/intro) for developer setup and starter projects.
## Overview
diff --git a/src/content/docs/esw/info/brushed.md b/src/content/docs/esw/info/brushed.md
new file mode 100644
index 0000000..a7f0ed8
--- /dev/null
+++ b/src/content/docs/esw/info/brushed.md
@@ -0,0 +1,10 @@
+---
+title: "Brushed DC Motors"
+---
+
+We used brushed DC motors for various mechanisms on our rover.
+For example, on our robotic arm, we use a 24V brushed motor for joint B
+and a 12V brushed motor for the gripper.
+
+Current information about our brushed motor controller (BMC) can be found
+on the ESW Google Drive in `projects/brushed-motor-controller-26` ([link](https://docs.google.com/document/d/1TxtbWJUpcLVBtVtj82RpuE8Irl_cduapGyJcjrrCujo/edit?usp=drive_link)).
diff --git a/src/content/docs/esw/info/brushless.md b/src/content/docs/esw/info/brushless.md
new file mode 100644
index 0000000..87787c7
--- /dev/null
+++ b/src/content/docs/esw/info/brushless.md
@@ -0,0 +1,28 @@
+---
+title: "Brushless DC Motors"
+---
+
+Brushless DC motors (BLDC) are electric motors that operate without the use of brushes for commutation.
+They provide higher efficiency and better performance compared to brushed motors, making them ideal for applications
+requiring precision and power. They are, however, more complex to control, requiring us to use specialized controllers.
+
+BLDC motors are used troughout the rover, such as:
+
+- All drive wheels
+- Joint A
+- Joint C
+- Joint DE
+
+## Moteus
+
+The BLDC motors are controlled using [moteus r4.11](https://mjbots.com/products/moteus-r4-11) and
+[moteus n1](https://mjbots.com/products/moteus-n1) controllers. The r4.11 controller is a bit simpler, but it is
+cheaper, so we use them for the drive motors. The n1 controller features more I/O, so we use them for the arm joints.
+
+These controllers are designed by mjbots (Josh Pieper) and are fully open source. Here are some useful links:
+
+- [moteus GitHub repository](https://github.com/mjbots/moteus)
+- [moteus documentation](https://mjbots.github.io/moteus)
+
+The moteus Discord server invite can be found in the documentation above, and is a **_great_** place to ask questions;
+Josh Pieper is very active and responsive there.
diff --git a/src/content/docs/esw/build.md b/src/content/docs/esw/info/build.md
similarity index 85%
rename from src/content/docs/esw/build.md
rename to src/content/docs/esw/info/build.md
index 774c85d..855d8d9 100644
--- a/src/content/docs/esw/build.md
+++ b/src/content/docs/esw/info/build.md
@@ -2,8 +2,6 @@
title: "Build Tools"
---
-# Build Tools
-
This document covers the build tooling and other utilities developed to aid the
development process.
@@ -29,12 +27,13 @@ that leverage the HAL libraries provided by STM. The script can be run as follow
In the invocation above, the script accepts either an MCU (e.g. `STMG431CBTx`)
or a development board (e.g. `NUCLEO-G431RB`).
-:::note
-Note that under the hood, this script emplaces this parameter directly into
-a headless STM32CubeMX script, which will fail if the MCU or board provided
-is invalid. Use the STM32CubeMX project creation wizard to see possible MCU
-options available, and to verify the correct part information.
-:::Under the hood, this script will run CubeMX and create an STM32 project for
+!!! note
+ Note that under the hood, this script emplaces this parameter directly into
+ a headless STM32CubeMX script, which will fail if the MCU or board provided
+ is invalid. Use the STM32CubeMX project creation wizard to see possible MCU
+ options available, and to verify the correct part information.
+
+Under the hood, this script will run CubeMX and create an STM32 project for
the specified MCU. It does this by running a script of STM32CubeMX commands
that create the project in the correct CMake/GCC configuration, and then
manually patches the IOC to ensure some settings that aren't linked to
@@ -64,11 +63,12 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
)
```
-:::note
-Future calls to the automated python tools that manage the auto-generated CMake
-files will overwrite this section, so these parameters will need to be provided
-to these scripts as well.
-:::### `build.sh`
+!!! note
+ Future calls to the automated python tools that manage the auto-generated CMake
+ files will overwrite this section, so these parameters will need to be provided
+ to these scripts as well.
+
+### `build.sh`
The build script is a wrapper around the CMake and the GCC distribution bundled with
the STM32CubeCLT, as well as the STMCubeProgrammer CLI. The build script can be run
@@ -106,9 +106,10 @@ To flash the executable file for a project to an MCU, use the `--flash` flag. Wh
set, the script will attempt a build as above, and if successful invoke the
STM32CubeProgrammer CLI to connect to an ST-LINK and flash the executable via SWD.
-:::caution
-Presently the script will only support flashing STM32 MCUs with SWD, and not JTAG.
-:::```bash
+!!! important
+ Presently the script will only support flashing STM32 MCUs with SWD, and not JTAG.
+
+```bash
./scripts/build.sh --src [--preset ] --flash
```
@@ -160,18 +161,20 @@ as follows.
sudo ./scripts/fdcanusb.sh --net
```
-:::caution
-This script must be run as `sudo` on linux systems to allow the virtual CAN
-network interface to be created and started.
-:::The `--net` flag specifies the virtual CAN network the fdcanusb should use. To work
+!!! important
+ This script must be run as `sudo` on linux systems to allow the virtual CAN
+ network interface to be created and started.
+
+The `--net` flag specifies the virtual CAN network the fdcanusb should use. To work
with the ROS2 stack, this should be something like `can[0-3]`. The script runs the
underlying `fdcanusb_daemon` in verbose mode, so the full CAN frame of all messages
on the bus will be directed to standard output.
-:::note
-MJBots no longer supports the `fdcanusb_daemon` (this script currently pulls the source
-for this from an archive). This script should be updated to not depend on this binary.
-:::## Python Tools
+!!! TODO
+ MJBots no longer supports the `fdcanusb_daemon` (this script currently pulls the source
+ for this from an archive). This script should be updated to not depend on this binary.
+
+## Python Tools
The ESW python tools (located in `tools/`) are designed to enable rapid development, testing,
and validation of the embedded hardware and software stack. Currently, the following submodules of
diff --git a/public/esw-dev/communication-protocols/can-bus.webp b/src/content/docs/esw/info/communication-protocols/can-bus.webp
similarity index 100%
rename from public/esw-dev/communication-protocols/can-bus.webp
rename to src/content/docs/esw/info/communication-protocols/can-bus.webp
diff --git a/public/esw-dev/communication-protocols/fdcan-clock-frequency.webp b/src/content/docs/esw/info/communication-protocols/fdcan-clock-frequency.webp
similarity index 100%
rename from public/esw-dev/communication-protocols/fdcan-clock-frequency.webp
rename to src/content/docs/esw/info/communication-protocols/fdcan-clock-frequency.webp
diff --git a/public/esw-dev/communication-protocols/g4-hsi16-characteristics.webp b/src/content/docs/esw/info/communication-protocols/g4-hsi16-characteristics.webp
similarity index 100%
rename from public/esw-dev/communication-protocols/g4-hsi16-characteristics.webp
rename to src/content/docs/esw/info/communication-protocols/g4-hsi16-characteristics.webp
diff --git a/public/esw-dev/communication-protocols/i2c-schema.webp b/src/content/docs/esw/info/communication-protocols/i2c-schema.webp
similarity index 100%
rename from public/esw-dev/communication-protocols/i2c-schema.webp
rename to src/content/docs/esw/info/communication-protocols/i2c-schema.webp
diff --git a/src/content/docs/esw/communication-protocols.md b/src/content/docs/esw/info/communication-protocols/index.md
similarity index 94%
rename from src/content/docs/esw/communication-protocols.md
rename to src/content/docs/esw/info/communication-protocols/index.md
index 3082fff..9c2e2d4 100644
--- a/src/content/docs/esw/communication-protocols.md
+++ b/src/content/docs/esw/info/communication-protocols/index.md
@@ -2,15 +2,13 @@
title: "Communication Protocols"
---
-# Communication Protocols
-
## I2C
I2C is a synchronous serial communication protocol that is commonly used in embedded systems. On MRover we often use I2C to interface with sensors. I2C has a single leader device and multiple follower devices (traditionally master and slave devices). An example of this is the science board being the leader and multiple sensors being the followers. The leader device controls the clock and initiates communication, while the followers respond when addressed. Each I2C device has a unique 7-bit address allowing for multiple devices to be placed on the same bus.
I2C uses two wires, a clock line (SCL) and a data line (SDA). Both lines are open-drain and require pull-up resistors, meaning devices are only able to pull the line low and not drive it high, preventing possible damage. Below is a diagram of a sample I2C bus setup.
-
+
### How Communication Works
@@ -112,7 +110,7 @@ although long, is very informative.
### CAN Bus
-
+
As mentioned previously, the CAN bus is made up of two wires: CAN High (CANH) and CAN Low (CANL).
Microcontrollers, however, do not have the capability to directly interface with the CAN bus. They
@@ -144,7 +142,7 @@ The clock frequency of the FDCAN peripheral is based on the system clock. It can
be found and modified by the user in the `Clock Configuration` tab of the .ioc in STM32CubeIDE.
The example below shows a clock configuration where the FDCAN peripheral clock frequency is 64 MHz.
-
+
The clock tolerance (measured in ppm) is a physical characteristic of the clock of the CAN FD hardware.
Based on the specific clock configuration shown above, we can see that the FDCAN peripheral is using
@@ -171,7 +169,7 @@ The clock frequency of the FDCAN peripheral is based on the system clock. It can
be found and modified by the user in the `Clock Configuration` tab of the .ioc in STM32CubeIDE.
The example below shows a clock configuration where the FDCAN peripheral clock frequency is 64 MHz.
-
+
The clock tolerance (measured in ppm) is a physical characteristic of the clock of the CAN FD hardware.
Based on the specific clock configuration shown above, we can see that the FDCAN peripheral is using
@@ -185,14 +183,14 @@ We then perform the following calculation:
0.005 * 1,000,000 = **5,000 ppm**
-
+
The node delay is the max input/output propagation delay of our CAN transceiver. This value is
dependent on the CAN transceiver that we are using. For the TCAN1042, the max propagation delay is
**175 ns** as shown below. Refer to the datasheet of the transceiver you are using to find this
value.
-
+
With these values, we can now use the [Kvaser tool](https://www.kvaser.com/support/calculators/can-fd-bit-timing-calculator/)
to calculate the bit timing values for our CAN bus.
diff --git a/public/esw-dev/communication-protocols/tcan1042-node-delay.webp b/src/content/docs/esw/info/communication-protocols/tcan1042-node-delay.webp
similarity index 100%
rename from public/esw-dev/communication-protocols/tcan1042-node-delay.webp
rename to src/content/docs/esw/info/communication-protocols/tcan1042-node-delay.webp
diff --git a/public/esw-dev/img/CubeIDE.png b/src/content/docs/esw/info/img/CubeIDE.png
similarity index 100%
rename from public/esw-dev/img/CubeIDE.png
rename to src/content/docs/esw/info/img/CubeIDE.png
diff --git a/public/esw-dev/img/I2CHardware.png b/src/content/docs/esw/info/img/I2CHardware.png
similarity index 100%
rename from public/esw-dev/img/I2CHardware.png
rename to src/content/docs/esw/info/img/I2CHardware.png
diff --git a/public/esw-dev/img/MCU.png b/src/content/docs/esw/info/img/MCU.png
similarity index 100%
rename from public/esw-dev/img/MCU.png
rename to src/content/docs/esw/info/img/MCU.png
diff --git a/public/esw-dev/img/Nucleo.jpg b/src/content/docs/esw/info/img/Nucleo.jpg
similarity index 100%
rename from public/esw-dev/img/Nucleo.jpg
rename to src/content/docs/esw/info/img/Nucleo.jpg
diff --git a/src/content/docs/esw/nucleos.md b/src/content/docs/esw/info/nucleos.md
similarity index 98%
rename from src/content/docs/esw/nucleos.md
rename to src/content/docs/esw/info/nucleos.md
index a8468a3..511cd28 100644
--- a/src/content/docs/esw/nucleos.md
+++ b/src/content/docs/esw/info/nucleos.md
@@ -1,22 +1,20 @@
---
title: "Nucleos Introduction"
---
-
-# Nucleos Introduction
A “Nucleo” is a microcontroller evaluation board manufactured by STM32 to prototype with STM32’s MCUs. Nucleos come with a removable ST-Link debugger/programmer integrated on the board, allowing firmware flashing and extensive debugging options through a simple USB connection. STM32 MCU have a wide range of hardware capabilities, with dedicated internal circuitry for I2C, SPI, UART, timers, and more. Firmware is typically written in C/C++ using STM32’s extremely capable Hardware Abstraction Layer (HAL) libraries, and compiled in STM32’s Cube IDE.
# MCU
STM32 microcontrollers are organized into various categories, as shown.
-
+
Each family of MCUs has dozens of models, each with a different feature set. The MCU’s are a realization of ARM’s Cortex M family of processors. Use the product selector on ST’s website to find MCU’s appropriate to your application.
# Nucleo
STM32 Nucleos are evaluation boards available to prototype designs that employ STM32 MCUs. There are many models of Nucleos, named after the MCU installed, the physical form factor, and the flash memory size. All available Nucleo boards are shown below.
-
+
Nucleos are often cheap (~$10 for a Nucleo-F303RE). The board breaks out all the MCU’s available interfaces into header pins, while implementing most of the standard extraneous circuity (voltage regulators, oscillators, etc.) required by the MCU. Designed for prototyping/testing, Nucleos come with an ST-Link debugger/programmer module, which will automatically flash the MCU’s firmware and allows the Cube IDE to debug code mid-execution.
_It is important to note that the essential component is the MCU itself - a Nucleo is just a helpful breakout board that ST has provided for select MCUs. Many topics discussed below, such as HAL/LL Libraries, interrupts, and interface peripherals, are elements of the MCU, not the Nucleo. A notable exception is the ST-Link programmer/debugger. This guide is very intentional with its use of the term "MCU" vs "Nucleo"_
# Cube IDE
ST’s Cube IDE is built off of the Eclipse IDE. Upon creating a new “STM32 Project”, the IDE will prompt the user to select a STM32 MCU. The IDE should automatically preload all relevant HAL libraries (discussed later) into the project workspace and generate the proper initialization code. A .ioc file is also generated, which when viewed in ST’s custom “Device Configuation Tool” perspective, allows the user to interactively control various features of the MCU. An example of this perspective is shown below. CubeIDE will use the settings specified in the .ioc file to automatically generate code for the STM32’s firmware.
-
+
STM32 processors typically use no operating system, and such behave much like an Arduino. At a basic level, their functionality is to run the main.c code that is flashed to their memory. Cube IDE will populate the main.c with the standard set of code necessary to get the MCU started. (RTOS is an option, but MRover firmware shouldn’t be complex enough to necessitate RTOS)
_In reality, the STM32 MCU is flashed with a binary file containing machine code. CubeIDE uses g++ to compile C/C++ code, automatically passing g++ the appropriate instruction set (in this case, ARM Cortex instruction sets). ArduinoIDE does the same, using a C compiler to flash Arduinos with machine code. Developers typically never see the machine code, as the programming languages make a point of abstracting ISAs (instruction set architectures) away from the higher-level logic/structures programmers wish to deal with._
@@ -70,7 +68,7 @@ The HAL documentation lists all the callback functions that can be overwritten.
# Interface Peripherals
Interface peripherals refer broadly to the interfaces onboard the STM32 MCU. These are often implemented in hardware, not software. For example, below is a block diagram for the I2C interface on almost all STM32 F3 series MCU’s.
-
+
Hardware implemented interfaces have a number of advantages
* They don't require processor cycles to operate
* They use system clocks and their own state registers, isolating their performance from the rest of the MCU
diff --git a/src/content/docs/esw/info/science.md b/src/content/docs/esw/info/science.md
new file mode 100644
index 0000000..b0273a9
--- /dev/null
+++ b/src/content/docs/esw/info/science.md
@@ -0,0 +1,3 @@
+---
+title: "Science"
+---
diff --git a/src/content/docs/esw/stm32-startup-boot-options.md b/src/content/docs/esw/info/stm32-boot.md
similarity index 92%
rename from src/content/docs/esw/stm32-startup-boot-options.md
rename to src/content/docs/esw/info/stm32-boot.md
index e834a6b..7f70bd9 100644
--- a/src/content/docs/esw/stm32-startup-boot-options.md
+++ b/src/content/docs/esw/info/stm32-boot.md
@@ -1,7 +1,8 @@
---
-title: "STM32 Startup Boot Options"
+title: "STM32 Boot Information"
---
-### Ever wondered what that BOOT0 pin does in the STM32Cube IDE .ioc file or stm32 chip? Want to set the BOOT0 pin to an alternate function such as an I2C CLK? Here is what you need to know before doing so.
+
+Ever wondered what that BOOT0 pin does in the STM32Cube IDE .ioc file or stm32 chip? Want to set the BOOT0 pin to an alternate function such as an I2C CLK? Here is what you need to know before doing so.
## The BOOT0 pin
The BOOT0 pin only really matters for the first 4 clock cycles of the boot sequence after reset has been released. However, it decides where the chip will boot from: Main Flash, System Memory, or Embedded SRAM. (Maybe more or less options depending on the chip). By default, holding BOOT0 LOW will make the chip boot from the main flash - this is most likely where your code is. (When using CubeIDE, this is where it is typically flashed)
@@ -53,4 +54,4 @@ Here I explain it with some more detail.\
## Other Resources
STM has other methods of programming these option bits, including using HAL functions. See the following resources for more info. Also make sure to look at the STM reference manual for your particular chip regarding boot options.\
[How to program STM32 Option Bytes with the HAL API](https://community.st.com/t5/stm32-mcus/how-to-program-stm32-option-bytes-with-the-hal-api/ta-p/49660)\
-[What are option bytes in STM32 and how do I use them?](https://community.st.com/t5/stm32-mcus/what-are-option-bytes-in-stm32-and-how-do-i-use-them/ta-p/49451)
\ No newline at end of file
+[What are option bytes in STM32 and how do I use them?](https://community.st.com/t5/stm32-mcus/what-are-option-bytes-in-stm32-and-how-do-i-use-them/ta-p/49451)
diff --git a/src/content/docs/esw/timers.md b/src/content/docs/esw/info/timers.md
similarity index 98%
rename from src/content/docs/esw/timers.md
rename to src/content/docs/esw/info/timers.md
index a887328..65b3ce8 100644
--- a/src/content/docs/esw/timers.md
+++ b/src/content/docs/esw/info/timers.md
@@ -1,9 +1,7 @@
---
-title: "STM32 Timers"
+title: "Timers"
---
-# Timers
-
The following information is for STM32 timers. You will find similar concepts with different
microcontrollers; however, the terminology and specifics may differ.
diff --git a/src/content/docs/esw/overview.md b/src/content/docs/esw/overview.md
deleted file mode 100644
index cfa41e7..0000000
--- a/src/content/docs/esw/overview.md
+++ /dev/null
@@ -1,42 +0,0 @@
----
-title: "ESW Overview"
----
-# Embedded Software
-
-The embedded software team of MRover (ESW) writes the driver code that allows the other programming subteams to utilize the electronic equipment on the rover. ESW works primarily with libraries in C, Python, and C++ to abstract the functions needed by the other teams for easy use. To do this we use different communication protocols such as I2C and CAN to transmit and receive relative data from sensors.
-
-This page will list all the systems that the ESW sub-team must write code for. If you are interested in helping out or in any of these systems or offering suggestions for improvement, please reach out! You can do this via by sending a message on Slack or by submitting a GitHub issue ticket.
-
-The steps for onboarding are listed below in the separate section.
-
-Wiki has been updated as of 01 September 2025.
-
-## Quick Summary of Systems
-
-Brushless motors (for the drive system and parts of the arm) are driven by moteus brushless motor controllers.
-
-Brushed motors (for parts of the Robotic Arm system, the Science Payload system, and the mast gimbal) are driven by STM32 chips. We are currently developing custom brushed motor controller PCBs.
-
-The science system is primarily controlled by a different STM32 chip. We are currently developing a custom science board PCB.
-
-The camera system is run on the Jetson to stream camera feed.
-
-
-
-## Onboarding
-
-Below are the all the things you need to do for onboarding (Steps 1-2 are independent of 3-7)
-
-1. [Install Ubuntu OS](/getting-started/install-ros)
-2. [Install ROS on Ubuntu](/getting-started/install-ros)
-3. Follow the steps on the [ESW Starter Project](https://umrover.github.io/mrover-esw/getting-started/intro/) page. This has a few more steps.
-4. Finished! Now go ask a lead to get involved on our [projects](https://umrover.github.io/mrover-esw/projects/overview26/)!
-
diff --git a/src/content/docs/esw/pdb-stm.md b/src/content/docs/esw/pdb-stm.md
deleted file mode 100644
index f227622..0000000
--- a/src/content/docs/esw/pdb-stm.md
+++ /dev/null
@@ -1,83 +0,0 @@
----
-title: "PDB STM"
----
-## Thermistor Calculations
-
-**Context**
-
-Here is a representation of the thermistor setup
-
-
-**Problem**
-
-The ADC for the temperature sensor takes in voltage drop from a thermistor. We need to convert this to the temperature. However, datasheets for different thermistors differ in how they report how a change in temperature affects the thermistor. For example, during 2022-23's development cycle, the thermistor's temperature coefficient was given in terms of millivolts/degree Celsius. Meanwhile, the 2023-24 thermistor had its temperature coefficient given in ohms/degree Celsius.
-
-
-**Solution**
-
-### Volt(s) per degree Celcius
-Example: [2022-2023 thermistor: MCP9701A](https://www.digikey.com/en/products/detail/microchip-technology/MCP9701T-E-TT/1987445)
-
-Since we know the relationship between volts and Celcius, we can just get the temperature directly from the ADC.
-The general equation for converting ADC value ($val_{ADC}$) to voltage ($V_{ADC}$), given a certain source voltage ($V_{source}$) and ADC bits ($bits_{ADC}$) is:
-$$V_{ADC} = val_{ADC} * V_{source} * \frac{1}{2^{bits_{ADC}}}$$
-
-So, we need to get the parameters of the ADC. The STM boards should have a 12 bit ADC. The thermistor is also powered by a 3.3V source. This means the math to convert the ADC value to voltage will be:
-$$V_{ADC} = val_{ADC} * 3.3 * \frac{1}{4096}$$
-
-Once we have this, we can just calculate the difference between the ADC voltage and the voltage at a base temperature ($V_{base}$, given in datasheet). Then, we can use the temperature coefficient ($Co_{temp}$) to find out the temperature change that caused the change in voltage. In math terms:
-$$Temp = \frac{V_{ADC} - V_{base}}{Co_{temp}} + temp_{base}$$
-
-For the 2022-2023 development cycle, the base temperature was 0 degrees celcius, the voltage at that temperature was 0.4V, and the temperature coefficient was 0.0195V/degree Celcius. So, the equation becomes:
-$$Temp = \frac{V_{ADC} - 0.4}{0.0195} + 0$$
-
-### Ohm(s) per degree Celcius
-Example: [2023-2024 themistor: TMP6431DECR](https://www.digikey.com/en/products/detail/texas-instruments/TMP6431DECR/11635694)
-
-The calculations for this one are a bit more complicated than the Volts/Celcius section. But don't worry, it's fun! 😄
-
-The basic premise is the same. We have to convert the ADC value to Celcius. The ADC value is linked to the voltage of the thermistor. We then need to use that to find the resistance of the thermistor, and then find the temperature.
-
-Finding the voltage from the ADC value is the same as the first section, or:
-$$V_{ADC} = val_{ADC} * V_{source} * \frac{1}{2^{bits_{ADC}}}$$
-
-And after we plug in the same values, we get:
-$$V_{ADC} = val_{ADC} * 3.3 * \frac{1}{4096}$$
-
-To get the resistance from the voltage, it might be easier to get the voltage from the resistance first, and then rearrange the equation. Since the output to the ADC is in parallel to the thermistor, the voltage drop over the themistor is the same as the voltage read by the ADC. From the diagram at the top of the page, we can see that the circuit forms a voltage divider. This means the voltage drop over the thermistor will be the voltage source times the thermistor resistance divided by the total resistance, or:
-$$V_{therm} = V_{source}\frac{R_{therm}}{R_{therm}+10000}$$
-
-After some rearranging to solve for the resistance of the thermistor, we have:
-$$R_{therm} = \frac{\frac{10000*V_{therm}}{V_{source}}}{1-\frac{V_{therm}}{V_{source}}}$$
-
-Which can also be written as
-$$R_{therm} = \frac{10000*V_{therm}}{V_{source}-V_{therm}}$$
-
-The source voltage is the same 3.3V, so we have:
-$$R_{therm} = \frac{10000*V_{therm}}{3.3-V_{therm}}$$
-
-Now, since we have to resistance of the thermistor, we can relate that to the temperature. The 2023-2024 thermistor had a temperature coefficient($Co_{temp}$) of 6400 ppm per degree Celcius, or 6400 microOhms per degree Celcius or $6.400*10^{-3}$ Ohms per degree Celcius.
-
-We also know the resistance at a base temperature($R_{base}$). In this case, the resistance at 25 degrees Celcius is 47000 Ohms. That means we can make the following equation:
-$$Temp = \frac{R_{therm}-R_{base}}{Co_{temp}}+temp_{base}$$
-
-And after plugging in the values we have:
-$$Temp = \frac{R_{therm}-47000}{6.400*10^{-3}}+25$$
-
-Now, we can plug the resistance of the thermistor into the equation and get the temperature in terms of the ADC value (as stated above, the voltage read by the ADC is the same as the voltage drop over the thermistor, so we can substitute $V_{ADC} = V_{therm}$):
-$$Temp = \frac{10000*\frac{val_{ADC} * 3.3 * \frac{1}{4096}}{3.3-(val_{ADC} * 3.3 * \frac{1}{4096})}-47000}{6.400*10^{-3}}+25$$
-
-In the code, this equation is broken down into the ADC Voltage, Thermistor Resistance, and Final Temperature for readability.
-
-
-## ADC Current Calculations
-
-**Context**
-We have a PDB on the rover.
-
-
-
-**Problem**
-
-
-**Solution**
\ No newline at end of file
diff --git a/src/content/docs/esw/embedded-projects.md b/src/content/docs/esw/projects/overview26.md
similarity index 90%
rename from src/content/docs/esw/embedded-projects.md
rename to src/content/docs/esw/projects/overview26.md
index d6118e5..76d6333 100644
--- a/src/content/docs/esw/embedded-projects.md
+++ b/src/content/docs/esw/projects/overview26.md
@@ -1,9 +1,7 @@
---
-title: "2025-2026 Projects"
+title: "ESW 2025-2026 Projects"
---
-# ESW 2025-2026 Projects
-
Information about the projects for the ESW 2025-2026 academic year can be found in
[this Google Doc](https://docs.google.com/document/d/1Cw7M3cpmoSit890-Cm11XMuY_vEbCZrrylU3aPUu5oU/edit?usp=sharing).
diff --git a/src/content/docs/esw/raman.md b/src/content/docs/esw/raman.md
deleted file mode 100644
index 013c06a..0000000
--- a/src/content/docs/esw/raman.md
+++ /dev/null
@@ -1,84 +0,0 @@
----
-title: "Raman"
----
-## Overview
-
-We are using Raman spectroscopy to detect substances in samples for science detection tasks. This document has been made to help anyone working with Raman.
-
-## Software
-
-The software and lots of the instructions and information provided in this document are in reference to the content found on [TCD1304.wordpress](https://tcd1304.wordpress.com/). There will be links to specific locations on this website throughout, to help show where information is found in case extra clarity is needed.
-
-## How Does It Currently Work?
-
-The CCD of the Raman setup is connected to a STMF401RE Nucleo using software from [TCD1304.wordpress](https://tcd1304.wordpress.com/). This Nucleo can be connected to a PC, jetson, or raspberry pi and with a python application, a GUI can be displayed showing the wavelengths it is reading.
-
-## What is Raman?
-
-Raman is a spectrometer setup we use on the rover. A spectrometer can conduct spectroscopy, the study of the absorption and emission of light and other radiation through matter. Essentially, this means we can shine a laser at a sample and based on the light that is not absorbed, we can detect if certain elements are present. The CCD is a sensor and is the portion of the Raman setup that collects light. This is what is connected to the STMF401RE Nucleo. The goal of the Raman is to detect kerogen and carotenoids’ spectral lines which are detected by the CCD. Kerogen is fossilized organic matter and carotenoids are cyanobacteria. Light is shone onto a sample and the light reflected is captured by the CCD. The reflected wavelengths are compared to known values so that we can characterize compounds, for example Kerogen has wavelengths of 713 nm and 726 nm while carotenoids are 695 nm, 703 nm, and 721nm.
-
-## The CCD
-
-As mentioned above, the CCD is the sensor that collects the light and relays information to the STMF401RE. We are using the TCD1304, a high pixel CCD sensor used in spectrometers. The nucleo must be set up in order to receive information from the CCD that can then be read by a computer (PC or Jetson or Raspberry PI) through a command line interface or a graphical user interface.
-
-## Connecting the CCD to the STM32F401 Nucleo
-
-Wire the two as follows:
-* fM connects to PB0
-* SH connects to PA1
-* ICG connects to PA0
-* Output connects to PC0
-* GND to GND
-* Power
- * Connect +5V to +5V if you have a TCD1304-PCB with a LDO in place
- * If voltage is not regulated by the CCD, use 3.3V or 5V (do this)
-
-## General Setup (Needed for both data collection methods)
-
-* Download TCD1304 driver firmware (UART) from [Downloads | TCD1304.wordpress](https://tcd1304.wordpress.com/downloads/)
-* Unzip the downloaded .zip file
-* Connect STMF401RE to computer and wait for file explorer browser to open (this will show the storage of the nucleo)
-* Open the TCD1304 folder that was unzipped and look for the .bin file
-* Drag the .bin into the main folder of the nucleo (basically, do not be in any of the folders
-* The .bin should disappear
-
-## Setup for Python GUI
-
-Complete General Setup and en* sure the Nucleo is still plugged in
-* Download pyCCDGUI (python) from [Downloads | TCD1304.wordpress](https://tcd1304.wordpress.com/downloads/)
-* On a windows computer
-* Run “python3 pyCCDGUI.py” from your computer (you need to be in the same directory) and it should open up a GUI
-* For COM-device, use COMX where X is a random number (4 worked for me)
-* You will know when the device is found
-* Press Collect and data will be collected and displayed on display
-* On a Linux computer (Jetson, etc.)
-* User must have read/write permissions to /dev/ttyACM0
-* To do this, you type $ sudo chmod 666 /dev/ttyACM0
-* To find current permissions of a file, do $ stat -c %a /dev/ttyACM0
-* For Mac, I found I needed to find my own port name by doing ls /dev/tty.usb* and then using what it printed rather than /dev/ttyACM0
-* Run “python3 pyCCDGUI.py” from the computer (you need to be in the same directory) and it should open up a GUI
-* For COM-device, use /dev/ttyACM0
-* You will know when the device is found
-* Press Collect and data will be collected and displayed on your display (Might need to connect Jetson to a TV with HDMI)
-* For accessible data, check out Setup for Command Line Interface, since it outputs data to files
-
-## Socat Transmission
-
-On the Jetson:
-
-Need to add the following to the 99-usb-serial.rules:
-```SUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", SYMLINK+="raman"```
-This makes it so that /dev/raman corresponds to the STM32F401
-
-Make sure to run ```sudo apt install socat```
-
-On linux device with the STM32F401 Nucleo plugged in to USB, the following needs to be ran:
-```/usr/bin/socat tcp-listen:8888,reuseaddr,fork file:/dev/raman,nonblock,waitlock=/var/run/tty0.lock,b115200,raw,echo=0```
-
-You might need to run the following on the basestation:
-
-```
-socat tcp:10.0.0.2:8888 file:/dev/raman,nonblock,waitlock=/var/run/tty0.lock,b115200,raw,echo=0
-```
-
-
diff --git a/src/content/docs/esw/science-board-stm.md b/src/content/docs/esw/science-board-stm.md
deleted file mode 100644
index 39870ac..0000000
--- a/src/content/docs/esw/science-board-stm.md
+++ /dev/null
@@ -1,28 +0,0 @@
----
-title: "Science Board STM"
----
-## Context
-The science system, which is designed for the science mission at URC, uses sensors, heaters, LEDs (think what is inside of ISH system). We want to control all of these with one STM chip on a science PCB.
-
-Look at the following diagram to get an idea of how this PCB fits in with the rest of hardware and software:
-
-
-
-## Problem
-ISH is iterating their system, and want to use different components, which we have to write code for.
-
-## Solution
-* Develop STM32 software (firmware) using the CubeIDE in C and C++
-* The firmware should be able to receive CAN messages and process them
-* The CAN messages interface should be defined
-* The firmware should be able to communicate with sensors, LEDs, and heaters (hardware specifics are defined by ISH)
-
-## Interfaces
-* For sensors: STM32 chip should read in and update values constantly, and send them to the Jetson when requested via CAN
-* For other actions, the STM32 chip should be able to process commands for LEDs, and states for heaters
-
-## Getting started
-* Start with the interface between the STM32 and the sensors, LEDs, heaters
-* Add in the CAN communication
-* Add ROS science_hw_bridge
-
diff --git a/src/content/docs/esw/science.md b/src/content/docs/esw/science.md
deleted file mode 100644
index c83d3bc..0000000
--- a/src/content/docs/esw/science.md
+++ /dev/null
@@ -1,40 +0,0 @@
----
-title: "Science"
----
-## Project Overview
-
-The science board on our team's rover is a PCB with an STM32 MCU and various components that allow the science board to control our team's ISH system. The board is responsible for interfacing with various sensors, controlling heaters via MOSFETs and thermistors, controlling LEDs via MOSFETS, and sending data to the team's Jetson over CAN.
-
----
-
-## System Overview
-
-The 2024-2025 rover used two science boards in its ISH system. Each board is responsible for two heaters, two thermistors, and one LED. Additionally, one board manages the sensor suite (a protoboard with two I2C sensors and two analog sensors). Each heater and LED has its own MOSFET connected to a GPIO pin on the MCU, allowing us to enable and disable the devices. All analog devices including the thermistors were connected to one of the two ADCs on the MCU. Finally, each I2C sensor had its own I2C bus. Sensor data, heater states, heater temperatures, and LED states were sent to the Jetson over CAN using the CAN transceiver on the science board.
-
-can_bridge.cpp uses SocketCAN to publish CAN traffic from the science boards to ROS 2 topics. science_hw_bridge.cpp then subscribes to these topics and handles decoding messages and publishing data to multiple topics. science_hw_bridge.cpp also handles the control logic for enabling and disabling the heaters and LEDs controlled by the science board, sending CAN messages to the board when the user makes requests through the team's teleop GUI.
-
----
-
-## MCU Code and IOC
-
-MCU code and IOC can be found [here](https://github.com/umrover/mrover-ros2/tree/science_board/esw/fw/science)
-
----
-
-## ROS Bridge
-
-ROS bridge can be found [here](https://github.com/umrover/mrover-ros2/blob/urc-25/esw/science_hw_bridge.cpp)
-
----
-
-## Services and Topics
-
-The science board services and topics can be found in the telop ESW ICD sheet in the google drive.
-
----
-
-## Configuration
-
-The various science board parameters should be configurable using a YAML config file.
-
-
diff --git a/src/content/docs/esw/starter-project.md b/src/content/docs/esw/starter-project.md
deleted file mode 100644
index fec8002..0000000
--- a/src/content/docs/esw/starter-project.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "ESW Starter Project"
----
-# Overview
-
-Welcome to the ESW starter projects. Here, you will learn how to get some experience with using microcontrollers and communication protocols.
-
-# Getting Started
-
-The starter projects have moved to the [mrover-esw](https://github.com/umrover/mrover-esw) repository. Please refer to the [ESW wiki pages](https://umrover.github.io/mrover-esw/getting-started/intro/) for the project walk-throughs.
diff --git a/src/content/docs/general/best-practices.md b/src/content/docs/general-resources/best-practices.md
similarity index 100%
rename from src/content/docs/general/best-practices.md
rename to src/content/docs/general-resources/best-practices.md
diff --git a/src/content/docs/general/contributing-to-the-wiki.md b/src/content/docs/general-resources/contributing-to-the-wiki.md
similarity index 100%
rename from src/content/docs/general/contributing-to-the-wiki.md
rename to src/content/docs/general-resources/contributing-to-the-wiki.md
diff --git a/src/content/docs/devops/updating-ci.md b/src/content/docs/general-resources/devops/updating-ci.md
similarity index 100%
rename from src/content/docs/devops/updating-ci.md
rename to src/content/docs/general-resources/devops/updating-ci.md
diff --git a/src/content/docs/devops/urc-vs-circ-switch.md b/src/content/docs/general-resources/devops/urc-vs-circ-switch.md
similarity index 100%
rename from src/content/docs/devops/urc-vs-circ-switch.md
rename to src/content/docs/general-resources/devops/urc-vs-circ-switch.md
diff --git a/src/content/docs/general/git.md b/src/content/docs/general-resources/git.md
similarity index 100%
rename from src/content/docs/general/git.md
rename to src/content/docs/general-resources/git.md
diff --git a/src/content/docs/getting-started/ide-configuration.md b/src/content/docs/general-resources/ide-configuration.md
similarity index 96%
rename from src/content/docs/getting-started/ide-configuration.md
rename to src/content/docs/general-resources/ide-configuration.md
index 9fbee02..30cec66 100644
--- a/src/content/docs/getting-started/ide-configuration.md
+++ b/src/content/docs/general-resources/ide-configuration.md
@@ -1,5 +1,8 @@
---
title: "IDE Configuration"
+sidebar:
+ label: "3. IDE Configuration"
+ order: 3
---
# Option 1 - VSCode
diff --git a/src/content/docs/getting-started/fundamentals-of-ros.md b/src/content/docs/general-resources/ros/fundamentals-of-ros.md
similarity index 99%
rename from src/content/docs/getting-started/fundamentals-of-ros.md
rename to src/content/docs/general-resources/ros/fundamentals-of-ros.md
index cd4ad34..a4343ef 100644
--- a/src/content/docs/getting-started/fundamentals-of-ros.md
+++ b/src/content/docs/general-resources/ros/fundamentals-of-ros.md
@@ -1,5 +1,8 @@
---
title: "Fundamentals of ROS"
+sidebar:
+ label: "4. Fundamentals of ROS"
+ order: 4
---
Here are some things to know about ROS
diff --git a/src/content/docs/getting-started/install-ros-macos.md b/src/content/docs/general-resources/ros/install-ros/install-ros-macos.md
similarity index 96%
rename from src/content/docs/getting-started/install-ros-macos.md
rename to src/content/docs/general-resources/ros/install-ros/install-ros-macos.md
index a73f9f4..90c22c9 100644
--- a/src/content/docs/getting-started/install-ros-macos.md
+++ b/src/content/docs/general-resources/ros/install-ros/install-ros-macos.md
@@ -27,4 +27,4 @@ If you encounter an error with your qt version run `brew uninstall --ignore-depe
7. Run `ros2 launch mrover simulator.launch.py`
# Alternative VM Installation
-If you're having trouble with the regular installation above(installation failing, simulator crashing, etc), ask a lead if you should use a VM instead. If so follow the installation method [here](/getting-started/macos-vm-setup).
+If you're having trouble with the regular installation above(installation failing, simulator crashing, etc), ask a lead if you should use a VM instead. If so follow the installation method [here](/general-resources/vm/macos-vm-setup).
diff --git a/src/content/docs/getting-started/install-ros.md b/src/content/docs/general-resources/ros/install-ros/install-ros.md
similarity index 98%
rename from src/content/docs/getting-started/install-ros.md
rename to src/content/docs/general-resources/ros/install-ros/install-ros.md
index eeb9fc8..4e710ba 100644
--- a/src/content/docs/getting-started/install-ros.md
+++ b/src/content/docs/general-resources/ros/install-ros/install-ros.md
@@ -1,12 +1,15 @@
---
title: "Install ROS"
+sidebar:
+ label: "2. Install ROS"
+ order: 2
---
## Operating Systems and Requirements
We highly recommend running Ubuntu 22.04 LTS natively. This will be by far the smoothest experience. There are many tutorials on dual booting out there if you are not comfortable with daily driving Linux. You will likely need 50 GB of space for your Linux partition. Perception members should aim for 100 GB due to the large nature of NVIDIA packages.
_**Please note that we will only officially support Ubuntu 22.04 LTS running natively**_. All other options are not as thoroughly tested and we cannot provide the same level of support if you run into any issue. However, here are some other options you can try to explore:
-1. macOS see [here](/getting-started/install-ros-macos)
+1. macOS see [here](/general-resources/ros/install-ros/install-ros-macos)
2. Ubuntu 22.04 LTS in a VM (Makes things like USB and GPU access difficult).
3. Other distro of choice by compiling from source (i.e. Arch and AUR) or using RoboStack for premade packages
diff --git a/src/content/docs/getting-started/intro-to-ros.md b/src/content/docs/general-resources/ros/intro-to-ros.md
similarity index 98%
rename from src/content/docs/getting-started/intro-to-ros.md
rename to src/content/docs/general-resources/ros/intro-to-ros.md
index 966f151..6808b17 100644
--- a/src/content/docs/getting-started/intro-to-ros.md
+++ b/src/content/docs/general-resources/ros/intro-to-ros.md
@@ -1,5 +1,8 @@
---
title: "Introduction to ROS"
+sidebar:
+ label: "1. Introduction to ROS"
+ order: 1
---
## What is ROS?
ROS is an open source framework for developing robotics software. It is short for robot operating system, but it is not truly an operating system like Ubuntu or Windows. Instead it is "middle-ware" that provides some common things needed for a robotic system. ROS runs on top of Ubuntu Linux. Robots typically run many pieces of software ranging from high level autonomy like computer vision to lower level software like device drivers and control loops. In many cases, this software is even distributed across computing devices such as on peripheral microcontrollers driving sensors or on high powered servers communicating with onboard computers via radio. ROS provides the following capabilities:
diff --git a/src/content/docs/general/ros-tools-rqt-bag.md b/src/content/docs/general-resources/ros/ros-tools-rqt-bag.md
similarity index 100%
rename from src/content/docs/general/ros-tools-rqt-bag.md
rename to src/content/docs/general-resources/ros/ros-tools-rqt-bag.md
diff --git a/src/content/docs/getting-started/setting-up-the-jetson.md b/src/content/docs/general-resources/setting-up-the-jetson.md
similarity index 100%
rename from src/content/docs/getting-started/setting-up-the-jetson.md
rename to src/content/docs/general-resources/setting-up-the-jetson.md
diff --git a/src/content/docs/getting-started/macos-vm-setup.md b/src/content/docs/general-resources/vm/macos-vm-setup.md
similarity index 96%
rename from src/content/docs/getting-started/macos-vm-setup.md
rename to src/content/docs/general-resources/vm/macos-vm-setup.md
index aea2a38..8fdab9a 100644
--- a/src/content/docs/getting-started/macos-vm-setup.md
+++ b/src/content/docs/general-resources/vm/macos-vm-setup.md
@@ -34,4 +34,4 @@ sudo apt install ubuntu-desktop
15. Run `sudo reboot` and sign into your VM.
-16. Now follow the Ubuntu ROS installation steps [here](/getting-started/install-ros)
\ No newline at end of file
+16. Now follow the Ubuntu ROS installation steps [here](/general-resources/ros/install-ros/install-ros)
\ No newline at end of file
diff --git a/src/content/docs/getting-started/usb-passthrough-utm.md b/src/content/docs/general-resources/vm/usb-passthrough-utm.md
similarity index 100%
rename from src/content/docs/getting-started/usb-passthrough-utm.md
rename to src/content/docs/general-resources/vm/usb-passthrough-utm.md
diff --git a/src/content/docs/general/code-style.md b/src/content/docs/general/code-style.md
deleted file mode 100644
index a9723e4..0000000
--- a/src/content/docs/general/code-style.md
+++ /dev/null
@@ -1,41 +0,0 @@
----
-title: "Code Style"
----
-### Formatting
-Run `./style.sh` in the top-level directory. `./style.sh --fix` will attempt to auto-format.
-
-### General
-- Prefer longer variable names. Avoid abbreviations. We have autocomplete for a reason!
-
-### C++
-- Adhere to all clang tidy checks defined in `.clang-tidy`. **This is tested by the CI.**
-- Style syntax with the clang format defined by `.clang-format`. **This is tested by the CI.**
-- *Never use raw pointers*, prefer [smart pointers](https://en.cppreference.com/book/intro/smart_pointers) (usually `std::shared_ptr`).
-- Check if something exists in the standard library before you reinvent the wheel!
-- Prefer [`static_cast`](https://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used) etc. instead of C style cast
-- Use `auto` on iterator types (ranged for) and *when the type is obvious*, for example casting or `std::make_shared`
-- Pass primitives by value (`int`, `float`, etc.) and complex types by reference or smart pointers
-- Do not use references (&) types for out parameters in functions, prefer returning a struct
-- Prefer using an explicit struct instead of `std::pair` or `std::tuple`
-- Use [structured binding](https://en.cppreference.com/w/cpp/language/structured_binding) when possible (e.g. iterating named map, unpacking a `std::pair`, ...)
-- Avoid `std::bind`, use an explicit lambda
-- Prefer PascalCase for things like classes and camelCase for things like member variables. **This is tested by the CI.**
-
-### Python
-- Currently `black` and `mypy` are used. **This is tested by the CI.**
-- If you are writing a function, *please use [type hinting](https://docs.python.org/3/library/typing.html) for the signature*. For other places, only use if necessary, for example a situation where the types are confusing.
-- Black is an autoformating tool that will control the format of your code
-- MyPy is a static type analysis tool that will make sure you don't violate type hinted functions
-- Document your code! Use the reST standard specifically
-- Prefer snake_case for regular python classes, functions, and variables and UPPER_CASE for constants
-
-Here is a good concrete example:
-```python
-def pos_distance_to(self, p: SE3) -> float:
- """
- Get the euclidean distance from the position of this SE3 pose to the position of another SE3 pose.
- :param p: another SE3 pose object
- :returns: euclidean distance between the two SE3 poses
- """
- return np.linalg.norm(p.position_vector() - self.position_vector())
-```
diff --git a/src/content/docs/index.mdx b/src/content/docs/index.mdx
index f0f337d..3de398f 100644
--- a/src/content/docs/index.mdx
+++ b/src/content/docs/index.mdx
@@ -11,7 +11,7 @@ import { LinkCard, CardGrid } from '@astrojs/starlight/components';
## Get Started
-
+
@@ -19,10 +19,7 @@ import { LinkCard, CardGrid } from '@astrojs/starlight/components';
-
-
-
-
+
diff --git a/src/content/docs/projects/2024-projects.md b/src/content/docs/projects/2024-projects.md
deleted file mode 100644
index bbe9ef7..0000000
--- a/src/content/docs/projects/2024-projects.md
+++ /dev/null
@@ -1,39 +0,0 @@
----
-title: "2024 Projects"
----
-## Perception
-
-* [Long range ArUco tag detection](/perception/long-range-tag-detection)
-* [Object detection](/perception/object-detection)
-* [Surface normals costmap](/navigation/surface-normals-costmap)
-* [Spatial mapping for teleop](Spatial-Mapping)
-* [Lander auto-align](/navigation/lander-auto-align)
-
-## Navigation
-
-* [Approach Target Base State](/navigation/approach-target-base-state)
- * [Second Camera Navigation Integration (LongRangeState)](/navigation/second-camera-integration)
- * [ApproachObjectState](/navigation/approach-object-state)
-* [Obstacle Avoidance](/navigation/obstacle-avoidance)
-* [Adaptive pure pursuit](/navigation/adaptive-pure-pursuit)
-* [URC vs. CIRC switch](/devops/urc-vs-circ-switch)
-
-## Localization
-
-* [Real-time kinematic positioning](RTK)
-* [Dual GNSS Heading](Dual-GNSS-Heading)
-* [IMU Setup](IMU-setup)
-* [Tip Detection](Tip-Detection)
-
-## ESW
-
-* [Hardware accelerated and robust camera streaming](/esw/camera-streaming)
-* [Brushed motor controller STM](/esw/brushed-controller-stm)
-* [Brushed motor controller ROS](/esw/brushed-controller-ros)
-* [Brushless ROS](/esw/brushless-ros)
-* [Science controller STM](Science-Controller-STM)
-* [PDB STM](/esw/pdb-stm)
-
-## Teleop
-* [Convert to Django](/teleop/convert-to-django)
-* [5dof IK](/navigation/5dof-ik)
diff --git a/src/content/docs/projects/2025-2026-projects.md b/src/content/docs/projects/2025-2026-projects.md
deleted file mode 100644
index e7a1e25..0000000
--- a/src/content/docs/projects/2025-2026-projects.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-title: "2025-2026 Projects"
----
-## Perception
-* [Key-Detection](/perception/key-detection)
-* [Object Detector Model](/perception/object-detector-model)
-* [Light Detector](/perception/light-detector)
-
-## Navigation
-
-* [Arm IK](/navigation/arm-ik)
-* [Click IK](/navigation/click-ik)
-* [Path Execution](/navigation/path-execution)
-
-## Localization
-
-* [Localisation Caching State Machine](/localization/data-caching-state-machine)
-* [Invariant EKF](/localization/invariant-ekf)
-* [Dual Antenna RTK](/localization/dual-antenna-rtk)
-* [Directional Antenna (RAT)](/esw/directional-antenna)
-
-## ESW
-
-* [Hardware accelerated and robust camera streaming](/esw/camera-streaming)
-* [Science Board STM](/esw/science-board-stm)
-* [CANalyzer](/esw/canalyzer)
-
-## Teleop
-* [Convert to Django](/teleop/convert-to-django)
-* [5dof IK](/navigation/5dof-ik)
diff --git a/src/content/docs/teleop/quickstart.md b/src/content/docs/teleop/quickstart.md
index 5814f33..28df5f5 100644
--- a/src/content/docs/teleop/quickstart.md
+++ b/src/content/docs/teleop/quickstart.md
@@ -3,7 +3,7 @@ title: "Teleop Quickstart"
---
## Additional resources: [Vue](/teleop/vue-introduction), [Tailwind](/teleop/tailwind-introduction)
-Once you have completed the installation from the [Install ROS](/getting-started/install-ros) page, make sure you are on the `main` branch:
+Once you have completed the installation from the [Install ROS](/general-resources/ros/install-ros/install-ros) page, make sure you are on the `main` branch:
```bash
git checkout main
@@ -34,7 +34,7 @@ Now, you should head to and complete the [teleop starter project](/teleop/starte
ros2 launch mrover basestation.launch.py
```
-This command starts both our **frontend and backend** services. You should be able to see the application running on [localhost:8080](http://localhost:8080). Hit `ctrl-c` on your terminal to kill the application.
+This command starts both our **frontend and backend** services. You should be able to see the application running on `localhost:8080`. Hit `ctrl-c` on your terminal to kill the application.
---