From cdcc2e788c8cc6cdab1e2701279b9e76c375197e Mon Sep 17 00:00:00 2001 From: AskewParity Date: Tue, 2 Dec 2025 17:42:02 -0800 Subject: [PATCH 1/8] chore: fix compiler warnings --- src/camera/interface.cpp | 2 +- src/network/gcs_routes.cpp | 6 +++--- src/network/mavlink.cpp | 9 ++++----- src/ticks/fly_search.cpp | 4 ++-- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/camera/interface.cpp b/src/camera/interface.cpp index 21b91d9a..71bd255c 100644 --- a/src/camera/interface.cpp +++ b/src/camera/interface.cpp @@ -83,7 +83,7 @@ bool ImageData::saveToFile(std::string directory) const { std::filesystem::path json_filepath = save_dir / (std::to_string(this->TIMESTAMP) + std::string(".json")); - LOG_F(INFO, "Saving %s to %s", img_filepath, json_filepath); + LOG_F(INFO, "Saving %s to %s", img_filepath.string().c_str(), json_filepath.string().c_str()); saveImageToFile(this->DATA, img_filepath); if (this->TELEMETRY.has_value()) { saveImageTelemetryToFile(this->TELEMETRY.value(), json_filepath); diff --git a/src/network/gcs_routes.cpp b/src/network/gcs_routes.cpp index f554e112..ec8c7bf5 100644 --- a/src/network/gcs_routes.cpp +++ b/src/network/gcs_routes.cpp @@ -265,8 +265,8 @@ DEF_GCS_HANDLE(Get, camera, capture) { compressed_image = cv::imdecode(compressed_data, cv::IMREAD_COLOR); if (!compressed_image.empty()) { - LOG_F(INFO, - "Compressed manual capture image from %d bytes to %d bytes (%.1f%% compression)", + LOG_F(INFO, + "Compressed manual capture image from %zu bytes to %zu bytes (%.1f%% compression)", image->DATA.total() * image->DATA.elemSize(), compressed_data.size(), (1.0 - static_cast(compressed_data.size()) / (image->DATA.total() * image->DATA.elemSize())) * @@ -393,7 +393,7 @@ DEF_GCS_HANDLE(Get, targets, all) { compressed_image = cv::imdecode(compressed_data, cv::IMREAD_COLOR); if (!compressed_image.empty()) { - LOG_F(INFO, "Compressed image from %d bytes to %d bytes (%.1f%% compression)", + LOG_F(INFO, "Compressed image from %zu bytes to %zu bytes (%.1f%% compression)", run.annotatedImage.total() * run.annotatedImage.elemSize(), compressed_data.size(), (1.0 - static_cast(compressed_data.size()) / diff --git a/src/network/mavlink.cpp b/src/network/mavlink.cpp index 28aa8f3e..0989d7c9 100644 --- a/src/network/mavlink.cpp +++ b/src/network/mavlink.cpp @@ -174,16 +174,15 @@ MavlinkClient::MavlinkClient(OBCConfig config) }); this->passthrough->subscribe_message(WIND_COV, [this](const mavlink_message_t& message) { - auto payload = message.payload64; - // LOG_F(INFO, "UNIX TIME: %lu", payload[0]); + // LOG_F(INFO, "UNIX TIME: %lu", message.payload64[0]); /* NOT TESTED - don't actually know where the data is in thie uint64_t[] TODO - test on actual pixhawk to make sure that the data makes sense */ - this->data.wind.x = (payload[1] >> 56) & 0xFF; - this->data.wind.y = (payload[1] >> 48) & 0xFF; - this->data.wind.z = (payload[1] >> 40) & 0xFF; + this->data.wind.x = (message.payload64[1] >> 56) & 0xFF; + this->data.wind.y = (message.payload64[1] >> 48) & 0xFF; + this->data.wind.z = (message.payload64[1] >> 40) & 0xFF; }); // this->telemetry->subscribe_attitude_euler( // [this](mavsdk::Telemetry::EulerAngle attitude) { diff --git a/src/ticks/fly_search.cpp b/src/ticks/fly_search.cpp index 900dbe87..685f0bff 100644 --- a/src/ticks/fly_search.cpp +++ b/src/ticks/fly_search.cpp @@ -40,7 +40,7 @@ void FlySearchTick::init() { LOG_F(ERROR, "Failed to reset Mission"); } - LOG_F(INFO, "Total Waypoint #: %d", this->state->getMav()->totalWaypoints()); + LOG_F(INFO, "Total Waypoint #: %zu", this->state->getMav()->totalWaypoints()); } Tick* FlySearchTick::tick() { @@ -64,7 +64,7 @@ Tick* FlySearchTick::tick() { auto curr_waypoint = this->state->getMav()->curr_waypoint(); if (this->curr_mission_item != curr_waypoint) { - LOG_F(INFO, "FlySearch Area reached (%d, %d)", this->curr_mission_item, curr_waypoint); + LOG_F(INFO, "FlySearch Area reached (%zu, %d)", this->curr_mission_item, curr_waypoint); for (int i = 0; i < this->state->config.pathing.coverage.hover.pictures_per_stop; i++) { auto photo = this->state->getCamera()->takePicture(500ms, this->state->getMav()); if (state->config.camera.save_images_to_file) { From 37933ba7b551e3b3022579daa27982033d0d6562 Mon Sep 17 00:00:00 2001 From: AskewParity Date: Wed, 3 Dec 2025 12:39:46 -0800 Subject: [PATCH 2/8] feat: add format style that satisfies lint to dev-container --- .clang-format | 17 +++++++++++++++++ .devcontainer/devcontainer.json | 5 +++-- 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..650581b9 --- /dev/null +++ b/.clang-format @@ -0,0 +1,17 @@ +BasedOnStyle: Google +UseTab: Never +IndentWidth: 4 +TabWidth: 4 +ColumnLimit: 100 +AccessModifierOffset: -3 +IncludeBlocks: Regroup +SortIncludes: true +IncludeCategories: + - Regex: "^[^\"]*interface\\.(h|hpp)$" + Priority: 1 + - Regex: "^<[^/]+\\.h>$" + Priority: 2 + - Regex: "^<[a-zA-Z0-9_]+>$" + Priority: 3 + - Regex: ".*" + Priority: 4 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f762bcef..f0a52f48 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -19,14 +19,15 @@ "customizations": { "vscode": { "settings": { - // Use bash instead ofk sh + // Use bash instead of sh "terminal.integrated.defaultProfile.linux": "bash" }, "extensions": [ "ms-vscode.cpptools", "twxs.cmake", "me-dutour-mathieu.vscode-github-actions" - ] + ], + "C_Cpp.clang_format_style": "file" } } From 50f3fb9be5103a4ee4e44858fce8769e478aeded Mon Sep 17 00:00:00 2001 From: Christopher Lee Date: Fri, 5 Dec 2025 14:00:32 -0800 Subject: [PATCH 3/8] chore: proofread READMEE --- README.md | 285 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 194 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index 2290dc8e..0171a043 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,16 @@ # obcpp -The `obcpp` is the repository for our `Onboard Computer`, which is currently a Jetson Orin Nano. This is the device that will actually be running software inside of the plane during flight, so it is essential that it works efficiently and without error. +The `obcpp` is the repository for our `Onboard Computer`, which is currently a +Jetson Orin Nano. This is the device that will actually be running software +inside of the plane during flight, so it is essential that it works efficiently +and without error. -Everyone that works on this project is strongly recommended to work inside of a Docker container. This will allow us to all work on the same underlying hardware, and even let people develop straight from Windows. +Everyone that works on this project is strongly recommended to work inside of a +Docker container. This will allow us to all work on the same underlying +hardware, and even let people develop straight from Windows. -To start, you will need to install Docker. You can follow the instructions [here](https://docs.docker.com/get-docker/) +To start, you will need to install Docker. You can follow the instructions +[here](https://docs.docker.com/get-docker/). ## Quick Setup @@ -24,10 +30,14 @@ Now you can use our build targets. - `ninja obcpp`: Makes the binary which you can run using `./bin/obcpp` - `ninja test`: Run the tests in `tests/unit` -- `ninja playground`: Runs the `tests/integration/playground.cpp` test which makes sure all dependencies work correctly +- `ninja playground`: Runs the `tests/integration/playground.cpp` test which + makes sure all dependencies work correctly - `ninja lint`: Check code for problems using `cpplint` -It is important to run `cmake` from within the `build` directory as shown so that all of the random build files CMake generates get placed in the `build` directory. Don't worry about messing this up, however, because the `cmake` will error and tell you that you should run it from within the `build` directory. +It is important to run `cmake` from within the `build` directory as shown so +that all of the random build files CMake generates get placed in the `build` +directory. Don't worry about messing this up, however, because the `cmake` will +error and tell you that you should run it from within the `build` directory. ## Command Line Usage @@ -35,14 +45,20 @@ It is important to run `cmake` from within the `build` directory as shown so tha obcpp [config_directory] [config_type] [plane] [flight_type] ``` -- `config_directory`: path to the configs directory, relative to the current working directory - - This should almost always refer to the `configs` directory at the root of the repository -- `config_file`: name of the config file (without the `.json` file extension) to use - - Currently this should either be `dev` for local development from inside the dev container, or `jetson` if you are running it on the Jetson +- `config_directory`: path to the configs directory, relative to the current + working directory + - Usually this refer to the `configs` directory in the root of the repo +- `config_file`: name of the config file (without the `.json` file extension) to + use + - Currently this should either be `dev` for local development from inside + the dev container, or `jetson` if you are running it on the Jetson - `plane`: name of the plane the obcpp is running on. - - This is used to determine what mavlink parameters should be uploaded to the plane. The only currently valid input is `stickbug` + - This is used to determine what mavlink parameters should be uploaded to + the plane. The only currently valid input is `stickbug` - `flight_type`: what kind of flight is being performed - - This is used to further specify what mavlink parameters should be uploaded to the plane. Current valid values are `sitl`, `test-flight`, or `competition`. + - This is used to further specify what mavlink parameters should be uploaded + to the plane. Current valid values are `sitl`, `test-flight`, or + `competition`. An example, running the program from the `build` directory on the sitl. @@ -52,8 +68,10 @@ An example, running the program from the `build` directory on the sitl. ## Config Files -The repo currently has the following file structure for configuration files. There are two kinds of configuration files: the high level config files (currently `dev.json` and `jetson.json`) and lower level mavlink parameter config files, which are kept -under the `params` directory as shown below. +The repo currently has the following file structure for configuration files. +There are two kinds of configuration files: the high level config files +(currently `dev.json` and `jetson.json`) and lower level mavlink parameter +config files, which are kept under the `params` directory as shown below. ``` configs |> @@ -70,19 +88,29 @@ configs |> - ... ``` -To add support for a new plane, which may require a unique set of mavlink parameters to upload, you should create a new directory adjacent to the `stickbug` directory. Inside of this directory you must have a file titled `common.json` for mavlink parameters that should always be uploaded when this plane is being used. Adjacent to `common.json`, however, you can create as many different json files for more specific parameters that should be uploaded to the plane in specific circumstances. +To add support for a new plane, which may require a unique set of mavlink +parameters to upload, you should create a new directory adjacent to the +`stickbug` directory. Inside of this directory you must have a file titled +`common.json` for mavlink parameters that should always be uploaded when this +plane is being used. Adjacent to `common.json`, however, you can create as many +different json files for more specific parameters that should be uploaded to the +plane in specific circumstances. -For example, `competition.json` sets the correct magic number for the Advanced Failsafe System to ensure that the plane will crash itself after 3 minutes of lost communications, in order to comply with SUAS competition rules. However, we really don't want this at a test flight so `test-flight.json` does not set the required magic number for the flight termination to be carried out. +For example, `competition.json` sets the correct settings to satisfy competition +rules (self-crash after 3 minutes). However, we don't want to have those limits +at a test flight, so we don't have those settings active in `test-flight.json`. -## Jetson Setup +## Jetson Setup (airdrops) -To run everything correctly on the Jetson (and possibly your local computer if you are communicating with the airdrop payloads), you will need to make sure that the `jetspot` wifi hotspot network is online, and that `obcpp` is set to use the correct network interface. +To run everything correctly on the Jetson (and possibly your local computer), +you will need to make sure that the `jetspot` wifi hotspot network is online, +and that `obcpp` is set to use the correct network interface. -The following commands must be run every time the Jetson is booted to ensure that the networking with the airdrop payloads works -correctly: +The following commands must be run every time the Jetson is booted to ensure +that the networking with the airdrop payloads works correctly: ```sh -sudo nmcli connection up Hotspot # turn on the jetspot WIFI network for the payloads to connect to +sudo nmcli connection up Hotspot # turn on the jetspot WIFI network for the payloads to connect to sudo route add default gw 10.42.0.1 # make the default interface the jetspot WIFI hotspot ``` @@ -91,11 +119,17 @@ The `jetspot` WIFI network is currently set up like so SSID: `jetspot` password: `fortnite` -The airdrop payloads are currently programmed to connect to a WIFI network with this information on boot. To make sure that it is broadcasting correctly, you can try and connect to it via your phone or other device. +The airdrop payloads are currently programmed to connect to a WIFI network with +this information on boot. To make sure that it is broadcasting correctly, you +can try and connect to it via your phone or other device. ## Setup -Now that everything is installed, here is the process to build and run the application. These instructions are for VSCode because it provides very nice integration with Docker containers. If you absolultely do not want to use VSCode, then you will have to find an equivalent way to do this with the IDE you want to use. +Now that everything is installed, here is the process to build and run the +application. These instructions are for VSCode because it provides very nice +integration with Docker containers; however, it is not strictly necessary to use +VSCode or dev-containers or Docker conainers. We will assume your docker +installation works correctly. 1. Clone the repo. If you are using git from the command line, this is the command you will use. ```sh @@ -107,22 +141,13 @@ Now that everything is installed, here is the process to build and run the appli cd obcpp ``` -3. Verify Docker is installed correctly by entering the following command into your terminal: - ```sh - docker run hello-world - ``` - If everything works correctly, you should receive a message saying that everything worked correctly. If instead you get - a message saying that Docker was not recognized, then something went wrong in your installation. If restarting your - computer does not fix it, then you should try and refollow the installation instructions again, verifying that you - didn't make any mistakes. - -4. Open the project's directory in VSCode (Make sure you are still in the `obcpp` directory, otherwise you will open - your current directory in vscode, whatever that may be.) +3. Open the project's directory in VSCode (Make sure you are in the `obcpp` + directory, otherwise VSCode will open in your current directory). ```sh code . ``` -5. Download the following extensions: +4. Download the following extensions: 1. [Remote-SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh) 2. [Remote Explorer](https://marketplace.visualstudio.com/items?itemName=ms-vscode.remote-explorer) 3. [Docker](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker) @@ -130,13 +155,14 @@ Now that everything is installed, here is the process to build and run the appli 5. [C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)
- 6. Optional steps. Only needed if you get auth issues pulling devcontainer. + 5. Optional steps. Only needed if you get auth issues pulling devcontainer. -6. Authenticate Docker +5. Authenticate Docker 1. Go to Github 2. Click on your profile icon in the top right 3. Select "Settings" - 4. Select "Developer Settings" (At the moment of writing this, it is the bottom-most option on the left sidebar). + 4. Select "Developer Settings" (At the moment of writing this, it is the + bottom-most option on the left sidebar). 5. Select "Personal access tokens" 6. Select "Tokens (classic)" 7. Select "Generate new token", then select classic again. @@ -154,102 +180,121 @@ Now that everything is installed, here is the process to build and run the appli ``` replacing USERNAME with your Github username. - 12. If you get an error along the lines of "Error Saving Credentials", you may need to run these commands: + 12. If you get an error along the lines of "Error Saving Credentials", you + may need to run these commands: ```sh service docker stop rm ~/.docker/config.json ``` - And then you can rerun the command from step 11. On a Windows system the filepath may be different. - - 13. This should authenticate your Docker so that you can now pull containers from the github container registry. You may receive a warning saying that your token is being stored unencrypted in the `~/.docker/config.json` file. If this concerns you, you can follow the link provided and fix this. + And then you can rerun the command from step 11. On a Windows system the + filepath may be different. + + 13. This should authenticate your Docker so that you can now pull containers + from the github container registry. You may receive a warning saying + that your token is being stored unencrypted in the + `~/.docker/config.json` file. If this concerns you, you can follow the + link provided and fix this.
-7. Pull the Docker Container: - 1. In the bottom left of the screen, click on the remote window icon. It should look like two angle brackets next to each other. Also, you can instead press "Ctrl+Shift+P" - 2. Select (or type) reopen in container. +6. Pull the Docker Container: + 1. In the bottom left of the screen, click on the remote window icon. It + should look like two angle brackets next to each other. Also, you can + instead press "Ctrl+Shift+P" + 2. Select (or type) `reopen in container`. -8. If the container was successfully loaded, then in the terminal you should see something along the lines of +7. If the container was successfully loaded, then in the terminal you should + see something along the lines of ```sh tuas@6178f65ec6e2:/workspaces/obcpp$ ``` -9. Create a build directory and enter it (All the following commands should be run from inside the build directory) +8. Create a build directory and enter it (All the following commands should be + run from inside the build directory) ```sh mkdir build cd build ``` -10. Build CMake files with the following command: +9. Build CMake files with the following command: ```sh cmake .. ``` -11. Build executable with the following command. (You will need to do this anytime you edit code.) +10. Build executable with the following command. (You will need to do this + anytime you edit code.) ```sh ninja obcpp ``` -12. Run the generated executable to verify it was created correctly. +11. Run the generated executable to verify it was created correctly (this will + crash early, that's ok). ```sh ./bin/obcpp ../configs dev stickbug sitl ``` -13. Verify that the testing framework is set up correctly +12. Verify that the testing framework is set up correctly ```sh ninja test ``` - If you receive output about certain tests passing/failing, then you are good. Ideally the main branch (which should be what - you cloned) won't have any failing tests, but if there are failing tests then it isn't your fault, nor does it mean your - installation is messed up. + If you receive output about certain tests passing/failing, then you are + good. Ideally the main branch won't have any failing tests, but if there are + failing tests then it isn't your fault, go ask someone about it. With that, everything should be set up correctly, and you should be good to go. ## Limiting Cores in Ninja -Ninja, the build tool we are using, tries to use a number of cores on your system based on how more cores your CPU has. For our repo, it seems like this default almost always crashes/freezes your computer because it quickly runs out of memory. +Ninja, the build tool we are using, tries to use a number of cores on your +system based on how more cores your CPU has. If you get some error along the +lines of `g++ terminated`, it likely means your computer ran out of memory. -To solve this, in our CMake config we limit the number of core ninja can use to 4. This hasn't crashed anyone's computer so far, but it is possible that you may need to reduce this number, or perhaps you want to increase it if your system can handle it so that you can get faster build times. +To solve this, in our CMake config we limit the number of core ninja can use to +4. This hasn't crashed anyone's computer so far, but it is possible that you +may need to reduce this number, or perhaps you want to increase it if your +system can handle it so that you can get faster build times. -To change the number of cores, you have to pass a special flag when you run `cmake`, like so: +To change the number of cores, you have to pass a special flag when you run +`cmake`, like so: ``` cmake -D CMAKE_JOB_POOLS="j=[# jobs]" .. ``` where you replace `[# jobs]` with a number specifying the number of jobs. -If you do this once, CMake should remember how you specified it, so as long as you don't clear the CMake cache you won't need to enter this again. (I.e. you can just run `cmake ..` and you should still see the message at the top saying that it is using a user-defined number of jobs). - -Anecdotally, on a machine with 16 virtual cores and 16GB of RAM, `-D CMAKE_JOB_POOLS="j=8"` appears to be a good balance between speed and resources usage. +Anecdotally, on a machine with 16 virtual cores and 16GB of RAM, +`-D CMAKE_JOB_POOLS="j=8"` appears to be a good balance between speed and +resources usage. ## Advanced Testing ### CV Pipeline -To fully test the CV pipeline, you will need to make sure that [not-stolen-israeli-code](https://github.com/tritonuas/not-stolen-israeli-code) is running. The easiest way to do this currently is to run the following commands from the root of the repository: +To fully test the CV pipeline, you will need to make sure that +[not-stolen-israeli-code](https://github.com/tritonuas/not-stolen-israeli-code) +is running. The easiest way to do this currently is to run the following +commands from the root of the repository: ```sh cd docker make run-sitl-compose ``` -When testing the pipeline, you will likely want to also use the `mock` camera. The Mock camera works by randomly selecting images from a specified directory in order to simulate "taking" real pictures. The relevant config options are +When testing the pipeline, you will likely want to also use the `mock` camera. ```json "camera": { ... "type": "mock", ... - "mock": { - "images_dir": "/workspaces/obcpp/tests/integration/images/saliency/" - }, ``` - -When `type` is set to `"mock"`, when `obcpp` tries to take a picture, it will instead select a random image from the given directory. +which will use `not-stolen-israeli-code` as the mock camera. ### SITL -In order to fully test `obcpp` with the SITL, you must be on a Linux machine (so that you can use Docker host networking). If this is the case, then you can do the following steps to test the obcpp with the simulated plane. +In order to fully test `obcpp` with the SITL, you must be on a Linux machine +(so that you can use Docker host networking). If this is the case, then you can +do the following steps to test the obcpp with the simulated plane. 1. Set up the [gcs](www.github.com/tritonuas/gcs) repo. 2. Run `make run-compose` inside of the `gcs` repo. @@ -292,11 +337,21 @@ If everything works correctly, you should get output similar to this 2024-06-30 05:52:20.042 ( 1.151s) [ 6C92D640] mavlink.cpp:151 INFO| Mav Flight Mode: Unknown ``` -You can technically also do this kind of testing on the Jetson itself (where you are running `obcpp` on the Jetson and the SITL either on your local computer or the Jetson itself). If that is the case, you will need to modify some of the IP addresses and ports throughout the `obcpp` and `gcs` configs / docker compose files. This is fairly complicated, so I would recommend asking for help with this. +You can technically also do this kind of testing on the Jetson itself (where +you are running `obcpp` on the Jetson and the SITL either on your local +computer or the Jetson itself). If that is the case, you will need to modify +some of the IP addresses and ports throughout the `obcpp` and `gcs` +configs/docker compose files. This is fairly complicated, so I would recommend +asking for help with this. ### Airdrop -If you specifically want to test `obcpp` with real airdrop payloads, then you will need to run some extra commands to make sure the networking is set up correctly. Note that this also requires a Linux machine to take advantage of Docker host networking. +If you specifically want to test `obcpp` with real airdrop payloads, then you +will need to run some extra commands to make sure the networking is set up +correctly. + +> NOTE: that this also requires a Linux machine to take advantage of Docker +> host networking. #### Jetson @@ -305,13 +360,31 @@ If you specifically want to test `obcpp` with real airdrop payloads, then you wi 3. `make jetson-develop` 4. Run the program like normal -NOTE: These steps may change eventually when we actually get the Jetson Docker container up and running, so you don't have to use the development container. +> NOTE: These steps may change eventually when we actually get the Jetson Docker +> container up and running, so you don't have to use the development container. #### Dev Container -1. First you will need to have a WIFI network that the payloads can connect to. If you cannot easily modify the code flashed to the airdrop payloads, then the easiest thing to do would be to rename your phone hotspot to `jetspot` with a password of `fortnite` so that the payloads automatically connect to it. -2. Figure out what the IPs on your WIFI network look like. For example, on the INNOUT WIFI network they are of the form `192.168.1.1`, whereas on the `jetspot` WIFI network they are of the form `10.42.0.1`. To figure this out, first connect to the network on the device that you are going to run the `obcpp` and enter the command `ip a` into your terminal. (On Windows, something like `ipconfig` will work). You will want to search through the output of the command and figure out what IP your device is assigned. If the network is a Hotspot hosted by the same device, it will likely be an IP Address ending in `.1` because your device is acting as the router for that particular subnet. -3. Once you know what the IP addresses on the WIFI network look like, you will want to set the default gateway router in your kernel IP routing table to the IP of the router on the network. For example, if I were to test this while connected to my home Spectrum WIFI, after running `ip a` I would get the following output: +1. First you will need to have a WIFI network that the payloads can connect to. + If you cannot easily modify the code flashed to the airdrop payloads, then + the easiest thing to do would be to rename your phone hotspot to `jetspot` + with a password of `fortnite` so that the payloads automatically connect to + it. +2. Figure out what the IPs on your WIFI network look like. For example, on the + INNOUT WIFI network they are of the form `192.168.1.1`, whereas on the + `jetspot` WIFI network they are of the form `10.42.0.1`. To figure this out, + first connect to the network on the device that you are going to run the + `obcpp` and enter the command `ip a` into your terminal. (On Windows, + something like `ipconfig` will work). You will want to search through the + output of the command and figure out what IP your device is assigned. If the + network is a Hotspot hosted by the same device, it will likely be an IP + Address ending in `.1` because your device is acting as the router for that + particular subnet. +3. Once you know what the IP addresses on the WIFI network look like, you will + want to set the default gateway router in your kernel IP routing table to + the IP of the router on the network. For example, if I were to test this + while connected to my home Spectrum WIFI, after running `ip a` I would get + the following output: ``` 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 @@ -351,39 +424,56 @@ NOTE: These steps may change eventually when we actually get the Jetson Docker c valid_lft forever preferred_lft forever ``` - After parsing this, I would figure out that the IP Addresses on my home WIFI are of the form `192.168.1.X`. This means that the router on my Home WIFI is `192.168.1.1`, which is the IP I care about right now. If the WIFI network is a Hotspot being hosted by the current device, then your device's IP on the network should already be of the form `X.X.X.1`, so you can just use its IP Address directly. + After parsing this, I would figure out that the IP Addresses on my home WIFI + are of the form `192.168.1.X`. This means that the router on my Home WIFI is + `192.168.1.1`, which is the IP I care about right now. If the WIFI network + is a Hotspot being hosted by the current device, then your device's IP on + the network should already be of the form `X.X.X.1`, so you can just use its + IP Address directly. With this information, run the following command: ```sh sudo route add default gw 192.168.1.1 # or whatever IP you found above ``` - This will make the airdrop packets `obcpp` sends out default to the correct network interface (that the airdrop payloads are on.) -4. Last but not least, go into the `.devcontainer/devcontainer.json` file and ensure that the line of the form + This will make the airdrop packets `obcpp` sends out default to the correct + network interface (that the airdrop payloads are on.) +4. Last but not least, go into the `.devcontainer/devcontainer.json` file and + ensure that the line of the form ```json "runArgs": ["--network=host"], ``` - Is not commented out. This ensures that the Docker container is running in host networking mode, and that all of the packets send from within the Docker container are treated as if you sent them directly from your host machine. + Is not commented out. This ensures that the Docker container is running in + host networking mode, and that all of the packets send from within the + Docker container are treated as if you sent them directly from your host + machine. - If the line is commented out, then uncomment it and reopen the dev container (I don't think you need to rebuild the container, but I'm not entirely sure). + If the line is commented out, then uncomment it and reopen the dev container + (I don't think you need to rebuild the container, but I'm not entirely + sure). ## Modules ### Camera -This module provides the functionality to interface with all of our physical cameras. This module is designed around one general camera "Interface" for which we provide various implementations for the different specific hardwares. +This module provides the functionality to interface with all of our physical +cameras. This module is designed around one general camera "Interface" for which +we provide various implementations for the different specific hardwares. ### Core -This module implements the backbone of the OBC, providing the structure that all other modules rely upon. +This module implements the backbone of the OBC, providing the structure that all +other modules rely upon. ### CV -This module encapsulates the entire computer vision pipeline, providing an interface which allows images to be input and identified targets to be output. +This module encapsulates the entire computer vision pipeline, providing an +interface which allows images to be input and identified targets to be output. ### Network -This module handles the various communications with other parts of the larger system. These links include +This module handles the various communications with other parts of the larger +system. These links include - an HTTP server that the GCS makes requests to - an Airdrop Client which communicates via WIFI to the airdrop payloads @@ -391,24 +481,32 @@ This module handles the various communications with other parts of the larger sy ### Pathing -This module implements the RRT* algorithm to plan out smart paths in order to navigate through competition waypoints, plan an airdrop approach path, and (possibly someday) avoid other planes flying in the sky. +This module implements the RRT* algorithm to plan out smart paths in order to +navigate through competition waypoints, plan an airdrop approach path, and +(possibly someday) avoid other planes flying in the sky. ### Ticks -This module implements all of the various ticks that the program progresses through throughout the mission. +This module implements all of the various ticks that the program progresses +through throughout the mission. ### [udp_squared](https://github.com/tritonuas/udp_squared) -A git submodule (implemented in the linked repo) which provides helper functions, enumerations, and structs for the communication protocol with the airdrop payloads. +A git submodule (implemented in the linked repo) which provides helper +functions, enumerations, and structs for the communication protocol with the +airdrop payloads. ### Utilities -This module provides various helper types and classes used throughout the OBC, as well as some mission-related constants. - +This module provides various helper types and classes used throughout the OBC, +as well as some mission-related constants. ## Modifying `CMakeLists.txt` -There is a `CMakeLists.txt` folder inside of each of the obcpp's module directories. If you add a new file to, say, the `network` module inside of `src/network/`, then you will need to add that filename to `src/network/CMakeLists.txt`. +There is a `CMakeLists.txt` folder inside of each of the obcpp's module +directories. If you add a new file to, say, the `network` module inside of +`src/network/`, then you will need to add that filename to +`src/network/CMakeLists.txt`. Note: you may need to clear you CMake cache if things get messed up. `find -name "*Cache.txt" -delete` @@ -417,7 +515,9 @@ Note: you may need to clear you CMake cache if things get messed up. ### Linting -[`cpplint`](https://github.com/cpplint/cpplint) is the linter that statically analyzes the code for style issues and other errors. It follows [Google's C++ style guide](http://google.github.io/styleguide/cppguide.html). +[`cpplint`](https://github.com/cpplint/cpplint) is the linter that statically +analyzes the code for style issues and other errors. It follows +[Google's C++ style guide](http://google.github.io/styleguide/cppguide.html). #### Setup If you're using the Devcontainer, `cpplint` will already be installed. @@ -430,7 +530,8 @@ sudo apt-get install python3-pip pip install cpplint ``` -For macOS, ensure you have `pip` installed or download it using one of the methods [here](https://pip.pypa.io/en/stable/installation/). +For macOS, ensure you have `pip` installed or download it using one of the +methods [here](https://pip.pypa.io/en/stable/installation/). Then, run: ```sh @@ -451,7 +552,9 @@ make lint #### Best Practices -Normally we want to fix every lint error that comes up, but in some cases it doesn't make sense to fix them all. To ignore linting for a specific line, add the following nolint comment as shown: +Normally we want to fix every lint error that comes up, but in some cases it +doesn't make sense to fix them all. To ignore linting for a specific line, add +the following nolint comment as shown: ```cpp int x = 0; // NOLINT From d7defec47d56536e51b440483617736a2b48b575 Mon Sep 17 00:00:00 2001 From: AskewParity Date: Fri, 5 Dec 2025 14:40:49 -0800 Subject: [PATCH 4/8] chore: remove ninja core limiter --- CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da38ed91..28bb6d42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,13 +44,13 @@ SET(CMAKE_C_FLAGS "-D_GNU_SOURCE") # eight_jobs requires more than 12GB RAM # sixteen_jobs requires more than 16GB RAM (I don't know how much, since I only have 16GB) # Therefore we default to 4 jobs, so it doesn't crash anyone's laptop with 12GB ram. -if (NOT DEFINED CMAKE_JOB_POOLS) - set_property(GLOBAL PROPERTY JOB_POOLS j=4) -else() - message("Using user defined number of pools: ${CMAKE_JOB_POOLS}") -endif() -set(CMAKE_JOB_POOL_COMPILE j) -set(CMAKE_JOB_POOL_LINK j) +# if (NOT DEFINED CMAKE_JOB_POOLS) +# set_property(GLOBAL PROPERTY JOB_POOLS j=4) +# else() +# message("Using user defined number of pools: ${CMAKE_JOB_POOLS}") +# endif() +# set(CMAKE_JOB_POOL_COMPILE j) +# set(CMAKE_JOB_POOL_LINK j) project(obcpp VERSION 1.0) From 563c26b7f54f926f2819fd0788bd39f770fbba62 Mon Sep 17 00:00:00 2001 From: AskewParity Date: Fri, 5 Dec 2025 14:41:15 -0800 Subject: [PATCH 5/8] chore: supress opencv2 compilation warnings --- deps/opencv/opencv.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deps/opencv/opencv.cmake b/deps/opencv/opencv.cmake index 43f61c0e..98b02145 100644 --- a/deps/opencv/opencv.cmake +++ b/deps/opencv/opencv.cmake @@ -2,6 +2,7 @@ function(target_add_opencv target_name) # Use system OpenCV installation from PATH find_package(OpenCV REQUIRED) - include_directories(${OpenCV_INCLUDE_DIRS}) + # Mark OpenCV headers as SYSTEM to suppress warnings from external library + include_directories(SYSTEM ${OpenCV_INCLUDE_DIRS}) target_link_libraries(${target_name} PRIVATE ${OpenCV_LIBS}) endfunction() \ No newline at end of file From f284b6b651505534213f1615523f1ad25c7530eb Mon Sep 17 00:00:00 2001 From: AskewParity Date: Fri, 5 Dec 2025 14:41:33 -0800 Subject: [PATCH 6/8] chore: fix string format warningins in log --- tests/integration/airdrop_approach.cpp | 2 +- tests/integration/coverage_pathing.cpp | 2 +- tests/integration/deviation_ranking.cpp | 2 +- tests/integration/path_planning.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/integration/airdrop_approach.cpp b/tests/integration/airdrop_approach.cpp index eb2e716c..e28264c2 100644 --- a/tests/integration/airdrop_approach.cpp +++ b/tests/integration/airdrop_approach.cpp @@ -73,7 +73,7 @@ int main() { LOG_F(WARNING, "Running Approach"); std::vector path = approach.run(); - LOG_F(INFO, "Path size: %d", path.size()); + LOG_F(INFO, "Path size: %zu", path.size()); // files to put path_coordinates to file.open("pathing_output/approach_coords.txt"); diff --git a/tests/integration/coverage_pathing.cpp b/tests/integration/coverage_pathing.cpp index bb0a3b8a..349465d9 100644 --- a/tests/integration/coverage_pathing.cpp +++ b/tests/integration/coverage_pathing.cpp @@ -73,7 +73,7 @@ int main() { LOG_F(WARNING, "Running Search"); std::vector path = search.run(); LOG_F(INFO, "Search Complete"); - LOG_F(INFO, "Path size: %d", path.size()); + LOG_F(INFO, "Path size: %zu", path.size()); // files to put path_coordinates to file.open("pathing_output/coverage_coords.txt"); diff --git a/tests/integration/deviation_ranking.cpp b/tests/integration/deviation_ranking.cpp index bc00b880..ef3f60bd 100644 --- a/tests/integration/deviation_ranking.cpp +++ b/tests/integration/deviation_ranking.cpp @@ -81,7 +81,7 @@ int main() { // get the path, put it into the file std::vector path = rrt.getPointsToGoal(); - LOG_F(INFO, "Path size: %d", path.size()); + LOG_F(INFO, "Path size: %zu", path.size()); LOG_F(INFO, "Path length: %f", path.size() * state->config.pathing.dubins.point_separation); // files to put path_coordinates to diff --git a/tests/integration/path_planning.cpp b/tests/integration/path_planning.cpp index f0b614a1..b903d1d7 100644 --- a/tests/integration/path_planning.cpp +++ b/tests/integration/path_planning.cpp @@ -103,7 +103,7 @@ int main() { // get the path, put it into the file std::vector path = rrt.getPointsToGoal(); - LOG_F(INFO, "Path size: %d", path.size()); + LOG_F(INFO, "Path size: %zu", path.size()); LOG_F(INFO, "Path length: %f", path.size() * state->config.pathing.dubins.point_separation); // files to put path_coordinates to From ce23132e8f809ee5883a3116bf77f11e42f068d2 Mon Sep 17 00:00:00 2001 From: AskewParity Date: Fri, 5 Dec 2025 14:45:11 -0800 Subject: [PATCH 7/8] fix: lint --- src/camera/interface.cpp | 4 +++- src/network/gcs_routes.cpp | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/camera/interface.cpp b/src/camera/interface.cpp index 71bd255c..279f1de7 100644 --- a/src/camera/interface.cpp +++ b/src/camera/interface.cpp @@ -83,7 +83,9 @@ bool ImageData::saveToFile(std::string directory) const { std::filesystem::path json_filepath = save_dir / (std::to_string(this->TIMESTAMP) + std::string(".json")); - LOG_F(INFO, "Saving %s to %s", img_filepath.string().c_str(), json_filepath.string().c_str()); + LOG_F(INFO, "Saving %s to %s", + img_filepath.string().c_str(), + json_filepath.string().c_str()); saveImageToFile(this->DATA, img_filepath); if (this->TELEMETRY.has_value()) { saveImageTelemetryToFile(this->TELEMETRY.value(), json_filepath); diff --git a/src/network/gcs_routes.cpp b/src/network/gcs_routes.cpp index ec8c7bf5..e77ab545 100644 --- a/src/network/gcs_routes.cpp +++ b/src/network/gcs_routes.cpp @@ -266,7 +266,8 @@ DEF_GCS_HANDLE(Get, camera, capture) { if (!compressed_image.empty()) { LOG_F(INFO, - "Compressed manual capture image from %zu bytes to %zu bytes (%.1f%% compression)", + "Compressed manual capture image from %zu bytes to %zu bytes" + + "(%.1f%% compression)", image->DATA.total() * image->DATA.elemSize(), compressed_data.size(), (1.0 - static_cast(compressed_data.size()) / (image->DATA.total() * image->DATA.elemSize())) * From baf0e04a38680b71de354ade6e7e2be08fa8a1a2 Mon Sep 17 00:00:00 2001 From: AskewParity Date: Fri, 5 Dec 2025 14:48:45 -0800 Subject: [PATCH 8/8] fix: string concatination in log statement --- src/network/gcs_routes.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/gcs_routes.cpp b/src/network/gcs_routes.cpp index e77ab545..fdd9a990 100644 --- a/src/network/gcs_routes.cpp +++ b/src/network/gcs_routes.cpp @@ -266,8 +266,8 @@ DEF_GCS_HANDLE(Get, camera, capture) { if (!compressed_image.empty()) { LOG_F(INFO, - "Compressed manual capture image from %zu bytes to %zu bytes" - + "(%.1f%% compression)", + "Compressed manual capture image from %zu bytes to %zu bytes " + "(%.1f%% compression)", image->DATA.total() * image->DATA.elemSize(), compressed_data.size(), (1.0 - static_cast(compressed_data.size()) / (image->DATA.total() * image->DATA.elemSize())) *