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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: ROS CI
name: Boat CI

on:
push:
Expand Down Expand Up @@ -49,3 +49,28 @@ jobs:
colcon test-result --verbose
exit "$test_status"
'

teensy:
runs-on: ubuntu-24.04
timeout-minutes: 15
defaults:
run:
working-directory: teensy
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Cache PlatformIO
uses: actions/cache@v4
with:
path: ~/.platformio
key: pio-${{ runner.os }}-${{ hashFiles('teensy/platformio.ini') }}
- name: Install PlatformIO
run: pip install --upgrade platformio
- name: Build firmware
run: pio run -e teensy40
- name: Run unit tests
run: ./test/run_tests.sh
77 changes: 16 additions & 61 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,75 +1,30 @@
devel/
logs/
# ROS2/colcon build artifacts.
build/
bin/
lib/
msg_gen/
srv_gen/
msg/*Action.msg
msg/*ActionFeedback.msg
msg/*ActionGoal.msg
msg/*ActionResult.msg
msg/*Feedback.msg
msg/*Goal.msg
msg/*Result.msg
msg/_*.py
build_isolated/
devel_isolated/

# Generated by dynamic reconfigure
*.cfgc
/cfg/cpp/
/cfg/*.py

# Ignore generated docs
*.dox
*.wikidoc

# eclipse stuff
.project
.cproject

# qcreator stuff
CMakeLists.txt.user

srv/_*.py
*.pcd
*.pyc
qtcreator-*
*.user

/planning/cfg
/planning/docs
/planning/src

*~

# Emacs
.#*

# Catkin custom files
CATKIN_IGNORE

# ROS 2 generated artifacts
install/
log/
__pycache__/

# ROS workspace metadata
.rosinstall
logs/
.ament_version
colcon.meta

# System logs
sys/sys.log
sys/ros.out
# Python.
__pycache__/
*.pyc

# IDE.
.vscode/
.idea/

# CV models
# Project specific.
/lib/
*.pt
sys/sys.log
sys/ros.out

# Miscellaneous
# Miscellaneous.
*.DS_Store
*.swp
*.swo
*.bak
*.tmp
*~
.#*
3 changes: 3 additions & 0 deletions teensy/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.pio/
.vscode/
.idea/
88 changes: 88 additions & 0 deletions teensy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Overview

The `teensy` directory includes the code for our Teensy 4.0 microcontroller, which serves as the low-level controller
of our sailboat. The code manages the sensors, actuators (such as the servos for the sail and rudder), and communicates
with the Jetson via a serial connection.

---


## Source Code (`src/`)
This code is structured based on [Lodestar](https://github.com/shihaocao/lodestar), a small scale electric demonstrator for the belly-flop and
tail-sitting control algorithms necessary for SpaceX's Starship.

### main.cpp
This file is comparable to a `.ino` file you would see in the Arduino IDE (notice setup and loop are exactly the same as
they would be in an Arduino file).

### MainControlLoop
The MainControlLoop initializes and executes all monitors and control tasks.

### SFR
SFR stands for State Field Registry. It contains values that should be available to the entire boat (sensor values,
serial buffer data, etc).

### Monitors
Monitors read input from some source and update corresponding values in the SFR.

### Control Tasks
Control tasks perform actions based on the current state of the boat or SFR values.

### constants.hpp
This file contains values that will never be dynamically changed (mainly physical parameters for a specific boat). This
prevents "magic numbers" in the codebase.


## Testing (`test/`)
A directory intended for PlatformIO Test Runner and project tests. The tests currently included here run locally, with
no need to have a Teensy plugged in. Run them from the `test/` directory with the command `./run_tests.sh`.

See [test/README.md](test/README.md) for how more on how this test suite works and what is covered.

---


## Getting Started
Below are the steps to set up your development environment to upload code and observe serial outputs from the Teensy.

### Prerequisites:
- [VSCode](https://code.visualstudio.com/download) or [CLion](https://www.jetbrains.com/clion/) is installed.
- The [boat](https://github.com/CUSail-Navigation/boat) repository is cloned.

### Steps:
1. In VSCode, click "Extensions" on the left-hand side toolbar and search for PlatformIO IDE.
In CLion, click "File → Plugins" and search for PlatformIO for CLion.
2. Open the `teensy/` folder within the boat repository. Make sure the `teensy/` folder is the project root.
3. (VSCode) At the bottom of your screen in the blue toolbar, you should see a check, arrow, and serial monitor icon.
- If you would just like to compile code but not upload to the Teensy, press the check.
- If you would like to upload to the Teensy, press the arrow.
- To view the serial monitor, press the electrical cord icon.


## Developing with a Teensy with Docker & WSL on Windows:
The following steps expose a Windows COM port to WSL and then expose the WSL port to the Docker image running in WSL.
This was necessary to set up a test environment with the ROS2 codebase on a Windows 11 computer.

### Changing Docker Desktop Backend to support WSL
Make sure you have:
- [Docker Desktop](https://docs.docker.com/desktop/setup/install/windows-install/) installed.
- [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) installed.

1. Open Docker Desktop.
2. Navigate to Settings → General.
3. Check the box "Use the WSL 2 based engine".

### Expose Windows COM port to WSL
1. Download and install [USBIPD-WIN](https://github.com/dorssel/usbipd-win/) (follow their README.md instructions).
2. Open PowerShell as an administrator.
3. Obtain a list of USB devices using `usbipd list`.
4. Find the bus ID of the device (e.g. 4-4) and use `usbipd bind --busid <id>` to share it with WSL.
5. Use `usbipd attach --wsl --busid <id>` to attach the USB port to WSL.
6. In WSL, you can use the command `lsusb` to see the device.

### Expose WSL port to Docker image
1. Run `ls /dev` or `lsusb` to view ports accessible by WSL. The Teensy will most likely appear as `/dev/ttyACM0`.
2. Run the following command in WSL to expose the shared port with the docker image:
```
docker run -it --rm --name boat-dev -v "$(pwd)/src:/home/ros2_user/ros2_ws/src" --device=<port> boat-local
```
44 changes: 44 additions & 0 deletions teensy/lib/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.

The source code of each library should be placed in an own separate directory
("lib/your_library_name/[here are source files]").

For example, see a structure of the following two libraries `Foo` and `Bar`:

|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c

and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>

int main (void) {
...
}

```

PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.

More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html
47 changes: 47 additions & 0 deletions teensy/platformio.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html


; ---- DEFAULT: only firmware environment built (`pio run` compiles firmware for Teensy; never touches test env). ----
[platformio]
default_envs = teensy40


; ---- FIRMWARE: what actually gets flashed onto the Teensy. ----
[env:teensy40]
platform = teensy@4.18
board = teensy40
framework = arduino
build_unflags = -std=gnu++14
build_flags =
-std=gnu++17
-I .pio/libdeps/native/Unity/src


; ---- TESTS: run locally (no board needs to be plugged in). ----
; Note: `-I test/mocks` puts the `test/mocks/` directory first on the include path, to use for our testing.
[env:native]
platform = native
test_framework = unity
build_flags =
-std=gnu++17
-Wall
-Wextra
-Wno-unused-parameter
-I src
-I test/mocks
-I .pio/libdeps/native/Unity/src

; 1) Compile src/ into test binary (off by default) so tests exercise the real firmware code rather than a copy.
; 2) Exclude main.cpp only (has Arduino setup()/loop() entry points + MCL; each test suite supplies its own main()).
; 3) Folders named test_* treated as test suites (test/mocks/ should be ignored and used just as an include directory).
test_build_src = yes
build_src_filter = +<*> -<main.cpp>
test_filter = test_*
32 changes: 32 additions & 0 deletions teensy/src/ControlTasks/LedControlTask.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "LedControlTask.hpp"

LedControlTask::LedControlTask() : LED_PIN(constants::led::LED_PIN) {
pinMode(LED_PIN, OUTPUT);
}

/**
* Blinks the status LED to indicate the current connectivity/data state of the boat.
*/
void LedControlTask::execute() const {
const bool update_servos = sfr::serial::update_servos_radio || sfr::serial::update_servos_usb;
if (Serial.available() && !update_servos) {
digitalWrite(LED_PIN, LOW);
delay(2000);
digitalWrite(LED_PIN, HIGH);
delay(2000);
}
else if (update_servos) {
digitalWrite(LED_PIN, HIGH);
delay(1000);
}
else if (!Serial.available()) {
digitalWrite(LED_PIN, LOW);
delay(1000);
}
else {
digitalWrite(LED_PIN, LOW);
delay(500);
digitalWrite(LED_PIN, HIGH);
delay(500);
}
}
11 changes: 11 additions & 0 deletions teensy/src/ControlTasks/LedControlTask.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once
#include "sfr.hpp"

class LedControlTask {
public:
LedControlTask();
void execute() const;

private:
const uint8_t LED_PIN;
};
Loading
Loading