Merge "Add support for JAX" into main
diff --git a/BUILD b/BUILD
index 87de71b..a23de12 100644
--- a/BUILD
+++ b/BUILD
@@ -86,6 +86,8 @@
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_pit_images_response //scouting/webserver/requests/messages:request_pit_images_response_go_fbs
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_pit_images //scouting/webserver/requests/messages:request_all_pit_images_go_fbs
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_pit_images_response //scouting/webserver/requests/messages:request_all_pit_images_response_go_fbs
+# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_current_scouting //scouting/webserver/requests/messages:request_current_scouting_go_fbs
+# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_current_scouting_response //scouting/webserver/requests/messages:request_current_scouting_response_go_fbs
gazelle(
name = "gazelle",
diff --git a/README.md b/README.md
index 6b02208..0d51aa2 100644
--- a/README.md
+++ b/README.md
@@ -37,215 +37,69 @@
Git has support for adding Signed-off-by lines by using `git commit -s`, or you can setup a git commit hook to automatically sign off your commits. [Stack Overflow](https://stackoverflow.com/questions/15015894/git-add-signed-off-by-line-using-format-signoff-not-working) has instructions for how to do this if you are interested.
## Table of contents
-* [Access to the Code](#access-to-the-code)
-* [Prerequisites](#prerequisites)
-* [Building the Code](#building-the-code)
- * [Steps to set up a computer to build the code](#steps-to-set-up-a-computer-to-build-the-code)
- * [Setting up access to a workspace on the build server](#setting-up-access-to-a-workspace-on-the-build-server)
- * [Bazel commands for building, testing, and deploying the code](#bazel-commands-for-building-testing-and-deploying-the-code)
+* [Pathway for new members](#pathway-for-new-members)
+ * [Learning C++](#1-learning-c)
+ * [XRP](#11-xrp)
+ * [Gaining code access](#2-gaining-code-access)
+ * [The codelab](#3-the-codelab)
* [Code Reviews](#code-reviews)
* [Creating SSH Aliases](#creating-ssh-aliases)
+* [Codelab](#codelab)
* [Other Information](#other-information)
* [Roborio Kernel Traces](#roborio-kernel-traces)
* [Notes on troubleshooting network setup](#notes-on-troubleshooting-network-setup)
* [LSP Setup for Rust](#lsp-setup-for-rust)
* [Other resources](#other-resources)
-## Access to the code
-The main central location for our code is our [Gerrit](https://www.gerritcodereview.com/) server at https://software.frc971.org/gerrit. If you are on a platform not compatible with our codebase follow the instructions [here](#setting-up-access-to-a-workspace-on-the-build-server) to set up access to the build server. To download a copy of the 971 code on your computer, follow these steps:
- 1. Fill out the 971 system access request form to get a gerrit account.
- - The form is pinned in the `#coding` channel in slack.
- - You need to be fully signed up for the team and have turned in all the forms and pass the safety test
- - More information on signing up with the team can be found here: https://frc971.org/join
- 2. Wait for Stephan Massalt to setup the account and message you the credentials.
- 3. When you log into Gerrit the first time, please [add your Email Address](http://software.frc971.org/gerrit/settings/#EmailAddresses)
- 4. Add your SSH key to Gerrit in order to be able to check out code
- - If you don't already have an ssh key, you can create one using `ssh-keygen -t ed25519`. This will create a public/private key pair-- the default location for your public key will be `~/.ssh/id_ed25519.pub`
- - Log into Gerrit and go to `Settings->SSH Keys` and paste your public key into the `New SSH Key` text box and clicking on `ADD NEW SSH KEY`
- 5. Install `git`: `sudo apt install git`
- 6. Go to [the 971-Robot-Code project in Gerrit](https://software.frc971.org/gerrit/#/admin/projects/971-Robot-Code) and run the command to Download the 971-Robot-Code repository.
- - We recommend downloading the code via SSH using the `clone with commit-msg hook` command
- - NOTE: Running with the option to `clone with commit-msg hook` will save you trouble later.
+## Pathway for new members
-To learn more about git, open a terminal and run `man git`, or see [git(1)](https://manpages.debian.org/buster/git-man/git.1.en.html) (especially the NOTES section).
+### 1. Learning C++
+C++ is what we use to program a majority of the code which runs on the robot.
+We generally recommend [this course by codeacademy](https://www.codecademy.com/learn/learn-c-plus-plus) which goes over the basics of C++ as well as OOP.
-## Prerequisites
-The instructions below assume you have the following:
- 1. A host computer with an appropriate OS or VM to compile the 971 code using Bazel
- 1. The currently supported operating system for building the code is amd64 Debian Buster.
- 2. It is likely to work on any `x86\_64 GNU/Linux` system (e.g., Ubuntu 20.04), but that's not at all well-tested.
- 2. Your favorite text editor installed, e.g., `vim`, `emacs`
- 3. Access to the 971-Robot-Code repository and have downloaded the source code
- 4. The ability to `ssh` into target CPU's like the roborio and Raspberry Pi
+#### 1.1 XRP
+If you are unsure what to work on yet you can start on the [XRP Platform](https://docs.wpilib.org/en/stable/docs/xrp-robot/index.html).
+Which basically lets you use smaller robots to learn about robotics through WPILib.
-## Building the code
-We use [Bazel](http://bazel.io) to build the code. Bazel has [extensive docs](https://docs.bazel.build/versions/master/build-ref.html), including a nice [build encyclopedia reference](https://docs.bazel.build/versions/master/be/overview.html), and does a great job with fast, correct incremental rebuilds.
+### 2. Gaining code access
-There are a couple options for building code that are given here-- setting up either your own computer, or using the frc971 build server.
+You can follow [these steps](./documentation/tutorials/getting-started.md) to access the code.
-### Steps to set up a computer to build the code
- 1. Install any Bazel version:
- 1. Check to see if the version of Linux you're running has an apt package for Bazel: `apt-cache search bazel` or just try `sudo apt install bazel`
- 2. More likely, you'll need to install manually-- see [here](https://docs.bazel.build/versions/master/install-ubuntu.html). We recommend using `apt-key` instead of `gnupg` in setting up the key:
- 1. Step 1: Add Bazel distribution URI as a package source
- ```
- sudo apt install curl
- curl -fsSL https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
- echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
- ```
- 2. Step 2: Install Bazel
- ```
- sudo apt update && sudo apt install bazel
- ```
+There is also a document which goes over the basics of using both gerrit and git [here](./documentation/tutorials/git-and-gerrit-basics.md)
- 2. Install the required packages:
- ```sh
- sudo apt-get update
- sudo apt-get install python
- ```
- 3. Change settings to allow Bazel's sandboxing to work-- follow the directions in `doc/frc971.conf`. For example, the commands to do this would be:
- 1. `sudo cp doc/frc971.conf /etc/sysctl.d/`
- 2. `sudo sysctl --system`
+### 3. The codelab
- 4. In order to run certain tests, you need to give yourself
- permissions--follow the "Set up real-time niceties" section of
- [aos/events/README.md](aos/events/README.md).
-
-### Setting up access to a workspace on the build server
-In order to use the build server, you'll first need to get ssh access set up. (NOTE: you don't need to do any of the other setup steps done for your own computer, since things like `bazel`, `python`, etc. are already installed on the build server)
- 1. Use ssh-keygen to create a public and private key.
-```console
-# In windows:
-# Important use Powershell!
-cd ~/.ssh
-ssh-keygen -t ed25519 -f id_971_ed25519
-chmod 600 id_971_ed25519
-```
-```console
-# In Linux and MacOS:
-cd ~
-ssh-keygen -t ed25519 -f ~/.ssh/id_971_ed25519
-chmod 600 ./.ssh/id_971_ed25519
-```
- 2. Complete the 971 system access request form for a buildserver account. WAIT for feedback, as he needs to setup the account.
- - The form is pinned in the `#coding` channel in slack.
- - When asked for your public SSH key, provide the contents of `id_971_ed25519.pub`
-```console
-cat ~/.ssh/id_971_ed25519.pub
-# This output is your public SSH key for the request form.
-```
- 3. Once you hear back from Stephan, test SSH.
-```console
-ssh REPLACE_WITH_YOUR_USERNAME@build.frc971.org -p 2222 -i ~/.ssh/id_971_ed25519
-```
- 4. If that doesnt work, then send the error msg to #coding However, if it does then use the `exit` command and then SSH tunnel.
-```console
-ssh REPLACE_WITH_YOUR_USERNAME@build.frc971.org -p 2222 -i ~/.ssh/id_971_ed25519 -L 9971:127.0.0.1:3389
-```
- 5. Now that you have buildserver access setup, you can follow the [vscode instructions](documentation/tutorials/setup-ssh-vscode.md) to use the buildserver with vscode.
- 6. For a graphical interface you can use the Remote Desktop app in Windows. Once
-you get there, all you need to do is put `127.0.0.1:9971` for the
-computer name, and use your gerrit username. Once you get connected,
-accept the server certificate and then enter your password that you
-gave Stephan. (It's either something unique or your gerrit pwd) Then
-select the Default panel config. You can exit the Remote Desktop if
-you are good w/ the raw cmd line interface. And for future logins all
-you have to do is tunnel and then login using the app. Now if you
-have a graphical application that you are developing (e.g., spline
-UI), then you have to run the build command in the Remote Desktop
-application.
- 7. Very important: In order for you to be able to commit, you need
- to configure your email address in `git`. To do this, run the
- following command, replacing `<YOUR EMAIL>` with the email that you are
- using for Gerrit:
-```console
-git config --global user.email "<YOUR EMAIL>"
-```
-If there are any questions, post to the #coding Slack channel so that other people who may reach the same issue can refer back to that.
-
-
-### Bazel commands for building, testing, and deploying the code
- * Build and test everything (on the host system, for the roborio target-- note, this may take a while):
-```
-bazel test //...
-bazel build --config=roborio -c opt //...
-```
- * Build the code for a specific robot:
-```console
-# For the roborio:
-bazel build --config=roborio -c opt //y2020/...
-```
-```
-# For the raspberry pi:
-bazel build --config=armv7 -c opt //y2020/...
-```
-
- * Configuring a roborio: Freshly imaged roboRIOs need to be configured to run the 971 code
-at startup. This is done by using the setup_roborio.sh script.
-```console
-bazel run -c opt //frc971/config:setup_roborio -- roboRIO-XXX-frc.local
-```
-
- * Download code to a robot:
-```console
-# For the roborio
-bazel run --config=roborio -c opt //y2020:download_stripped -- roboRIO-971-frc.local
-```
-This assumes the roborio is reachable at `roboRIO-971-frc.local`. If that does not work, you can try with a static IP address like `10.9.71.2` (see troubleshooting below)
-```console
-# For the raspberry pi's
-bazel run --config=armv7 -c opt //y2020:pi_download_stripped -- 10.9.71.101
-```
-NOTE:
- 1. The raspberry pi's require that you have your ssh key installed on them in order to copy code over
- 2. They are configured to use the IP addresses 10.X.71.Y, where X is 9, 79, 89, or 99 depending on the robot number (971, 7971, 8971, or 9971, respectively), and Y is 101, 102, etc for pi #1, #2, etc.
-
- * Downloading specific targets to the robot
- 1. Generally if you want to update what's running on the robot, you can use the `download_stripped` (or `pi_download_stripped`) targets. These will rsync only the changed files, and so are pretty efficient.
- 2. If you have a need to compile a specific module, you can build stripped versions of the individual modules by adding "_stripped" to the module name. For example, to build the calibration code (`//y2020/vision:calibration`) for the pi (`armv7`), run:
- ```console
- bazel run --config=armv7 -c opt //y2020/vision:calibration_stripped
- ```
- You will then need to manually copy the resulting file over to the robot.
+Once you have an understanding of C++ and have gone through using all the steps needed to access the code you can start on the [codelab](#codelab)
## Code reviews
-We want all code to at least have a second person look it over before it gets merged into the `main` branch. Gerrit has [extensive documentation on starting reviews](https://software.frc971.org/gerrit/Documentation/user-upload.html). There is also a good [intro User Guide](https://software.frc971.org/gerrit/Documentation/intro-user.html) and an [intro to working with Gerrit](https://gerrit-review.googlesource.com/Documentation/intro-gerrit-walkthrough.html) and [Gerrit workflows](https://docs.google.com/presentation/d/1C73UgQdzZDw0gzpaEqIC6SPujZJhqamyqO1XOHjH-uk)
+We want all code to at least have a second person look it over before it gets merged into the `main` branch. Gerrit has [extensive documentation on starting reviews](https://gerrit-review.googlesource.com/Documentation/user-upload.html). There is also a good [intro User Guide](https://gerrit-review.googlesource.com/Documentation/intro-user.html) and an [intro to working with Gerrit](https://gerrit-review.googlesource.com/Documentation/intro-gerrit-walkthrough.html) and [Gerrit workflows](https://docs.google.com/presentation/d/1C73UgQdzZDw0gzpaEqIC6SPujZJhqamyqO1XOHjH-uk)
TL;DR: Make and commit your changes, do `git push origin HEAD:refs/for/main`, and then click on the provided link to add reviewers. If you just upload a change without adding any reviewers, it might sit around for a long time before anybody else notices it.
[git-review](http://manpages.debian.org/cgi-bin/man.cgi?query=git-review) can make the upload process simpler.
+To download a commit you can press d or click download on gerrit, then select fetch and paste the command in your terminal. Once you've done that you should switch to a new branch in order to make working on multiple commits easier.
+You can do this by doing `git switch -c branch_name`, the branch name can be anything, and will only be public for you, so organize in whatever way you find easy to model.
+When programming in C++ we follow [Google's C++ Style Guide](https://google.github.io/styleguide/cppguide.html)
-### Some other useful packages <TODO: Need to review these>
+Furthermore, you can run `bazel run //tools/lint:run-ci` to fix linter errors which appear on buildkite.
+
+### Some other useful packages
These aren't strictly necessary to build the code, but Michael found the
additional tools provided by these packages useful to install when working with
the code on May 13, 2018.
+> **Note**: These are for local install, most of these tools will be available on the build server
-```console
-# Get some useful packages including git and subversion.
- apt-get update
- apt-get install git git-gui vim-gtk3
- apt-get install vim-doc git-doc exim4-doc-html yapf
- apt-get install bazel clang-format
- apt-get install python avahi-daemon
-# Install apt-file so that packages can be searched
- apt-get install apt-file
- apt-file update
-# Install sysstat so that you can tell how many resources are being used during
-# the compile.
- apt-get install sysstat
-# iostat is used to observe how hard the disk is being worked and other
-# performance metrics.
- iostat -dx 1
-# gitg is a graphical user interface for git. I find it useful for
-# understanding the revision history of the repository and viewing
-# log messages and changes.
- apt-get install gitg
-# Also may want to install `buildifier` for formatting BUILD files
+```bash
+apt install git
+apt install yapf3
+apt install python3
+apt install bazel
+apt install clang-format
```
### Creating ssh aliases
@@ -270,6 +124,12 @@
# Download code to robot #7971's raspberry pi #2
bazel run --config=armv7 -c opt //y2020:download_stripped -- pi-7971-2
```
+
+## Codelab
+
+The codelab is a directory living in `frc971/codelab/`. Which goes over a lot of the important introductory information that you need to know to get started when programming the robot.
+You can read the [README](./frc971/codelab/README.md), which gives you introduces you to the codelab as well as the concepts you need to understand first.
+
## Other Information
### Roborio Kernel Traces
@@ -356,6 +216,5 @@
3. Example of [logging](./aos/events/README.md)
TODOs:
- 1. Add more on networking setup and troubleshooting
- 2. Move Roborio Kernel Traces out of here, maybe into documentation/
- 3. Currently requires `apt install libsigsegv2`, but this should be temporary
+1. Add more info about git
+2. Add more robot debugging and networking troubleshooting
diff --git a/documentation/tutorials/getting-started.md b/documentation/tutorials/getting-started.md
new file mode 100644
index 0000000..8e04fcb
--- /dev/null
+++ b/documentation/tutorials/getting-started.md
@@ -0,0 +1,138 @@
+# Getting Started
+
+To get started with programming in our codebase you'll need to setup access with the buildserver, gerrit, and buildkite.
+this guide walks you through both.
+
+* [Setting up Gerrit](#setting-up-gerrit)
+* [Setting up the code](#setting-up-the-code)
+ * [Buildserver](#buildserver)
+ * [Locally](#locally)
+* [Running the code](#running-the-code)
+ * [Bazel commands for building, testing, and deploying the code](#bazel-commands-for-building-testing-and-deploying-the-code)
+
+To access our code you will need to request access to both Gerrit and the Build Server.
+Gerrit is a tool we use to manage git patches similar to github.
+While the Build Server is required in order to run code on non-linux machines*.
+
+\* It is possible to run the code locally on windows through WSL
+
+## Setting up Gerrit
+To setup Gerrit you can follow these steps
+1. Fill out the 971 system access request form pinned in the `#coding` channel in slack.
+ 1. You need to have already signed up for the team and fully filled out all forms, as well as have passed the safety test.
+ 1. [More information on signing up](https://frc971.org/join)
+2. Wait for Stephan Massalt to see your request and slack you with your credentials.
+3. Add your email address when first signing into Gerrit. [Link](https://software.frc971.org/gerrit/settings/#Profile)
+
+The process for buildkite is the same as the one for gerrit, except select buildkite in the system access request form.
+
+## Setting up the code
+
+Now that gerrit is set up you'll need a way to run the code, if you're on linux you can run it [locally](#locally).
+While on Mac and Windows you'll need to use the [buildserver](#buildserver).
+
+### Buildserver
+
+To setup the buildserver you can follow these steps
+1. Generate an SSH Key to use with the buildserver
+ 1. This is needed in order to connect to the server
+ 2. **Note:** Powershell is needed for windows on this step
+ ```bash
+ ssh-keygen -t ed25519 -f ~/.ssh/id_971_ed25519
+ chmod 600 ~/.ssh/id_971_ed25519
+ ```
+2. Fill out the 971 system access form pinned in the `#coding` channel in slack
+ 1. This has the same requirements as the form for Gerrit
+ 2. You will need to run `cat ~/.ssh/id_971_ed25519` for the key used in the form.
+3. Wait for a slack message from Stephan Massalt saying you have access to the Buildserver
+4. Setting up an SSH aliases
+ 1. This makes it easier to access the buildserver with IDEs like vscode.
+ 2. **Note:** Similar to earlier, Powershell is required for this step on windows.
+ 1. You need to place these contents into `~/.ssh/aliases`
+ ```bash
+ Host frc971
+ Port 2222
+ ForwardAgent yes
+ IdentitiesOnly yes
+ User [YOUR_GERRIT_USERNAME]
+ HostName build.frc971.org
+ IdentityFile ~/.ssh/id_971_ed25519
+ ```
+ 3. Run
+ ```bash
+ ssh build "echo If you\'re seeing this, it means everything setup correctly"
+ ```
+ and if you aren't seeing any errors, it has been setup correctly.
+5. Connecting to the build server
+ 1. You can connect either through vscode ([instructions](documentation/tutorials/setup-ssh-vscode.md)) or manually via the terminal by conecting with `ssh frc971`
+
+
+### Locally
+
+These steps assume you are on the most up to date debian linux, however they can be adapted to most other distributions.
+
+1. Updating your system
+ 1. This can be done by running `sudo apt update && sudo apt upgrade`
+2. Installing packages needed for development
+ 1. `sudo apt install git python3`
+3. Installing bazel
+ 1. Follow the steps [here](https://bazel.build/install/ubuntu)
+
+## Running the Code
+
+To run the code you'll need to download the repository from [gerrit](https://software.frc971.org/gerrit/admin/repos/971-Robot-Code), make sure to select ssh and not http.
+To learn more about git, open a terminal and run `man git`, or see [git(1)](https://manpages.debian.org/buster/git-man/git.1.en.html) (especially the NOTES section).
+
+Once the repositoy is selected you'll want to make sure to configure your name, email on git. This is required to ensure you're following the [contributing guidelines above](#contributing). You can do this by running these following commands:
+```bash
+cd 971-Robot-Code
+git config user.email "<YOUR_EMAIL_HERE>"
+git config user.name "<YOUR_NAME>"
+```
+We use [Bazel](http://bazel.io) to build the code. Bazel has [extensive docs](https://docs.bazel.build/versions/master/build-ref.html), including a nice [build encyclopedia reference](https://docs.bazel.build/versions/master/be/overview.html), and does a great job with fast, correct incremental rebuilds.
+
+### Bazel commands for building, testing, and deploying the code
+ * Build and test everything (on the host system, for the roborio target-- note, this may take a while):
+```
+bazel test //...
+bazel build --config=roborio -c opt //...
+```
+ * Build the code for a specific robot:
+```console
+# For the roborio:
+bazel build --config=roborio -c opt //y2020/...
+```
+```
+# For the raspberry pi:
+bazel build --config=armv7 -c opt //y2020/...
+```
+
+ * Configuring a roborio: Freshly imaged roboRIOs need to be configured to run the 971 code
+at startup. This is done by using the setup_roborio.sh script.
+```console
+bazel run -c opt //frc971/config:setup_roborio -- roboRIO-XXX-frc.local
+```
+
+ * Download code to a robot:
+```console
+# For the roborio
+bazel run --config=roborio -c opt //y2020:download_stripped -- roboRIO-971-frc.local
+```
+This assumes the roborio is reachable at `roboRIO-971-frc.local`. If that does not work, you can try with a static IP address like `10.9.71.2` (see troubleshooting below)
+```console
+# For the raspberry pi's
+bazel run --config=armv7 -c opt //y2020:pi_download_stripped -- 10.9.71.101
+```
+NOTE:
+ 1. The raspberry pi's require that you have your ssh key installed on them in order to copy code over
+ 2. They are configured to use the IP addresses 10.X.71.Y, where X is 9, 79, 89, or 99 depending on the robot number (971, 7971, 8971, or 9971, respectively), and Y is 101, 102, etc for pi #1, #2, etc.
+
+ * Downloading specific targets to the robot
+ 1. Generally if you want to update what's running on the robot, you can use the `download_stripped` (or `pi_download_stripped`) targets. These will rsync only the changed files, and so are pretty efficient.
+ 2. If you have a need to compile a specific module, you can build stripped versions of the individual modules by adding "_stripped" to the module name. For example, to build the calibration code (`//y2020/vision:calibration`) for the pi (`armv7`), run:
+ ```console
+ bazel run --config=armv7 -c opt //y2020/vision:calibration_stripped
+ ```
+ You will then need to manually copy the resulting file over to the robot.
+
+
diff --git a/documentation/tutorials/git-and-gerrit-basics.md b/documentation/tutorials/git-and-gerrit-basics.md
new file mode 100644
index 0000000..69584d0
--- /dev/null
+++ b/documentation/tutorials/git-and-gerrit-basics.md
@@ -0,0 +1,101 @@
+# Git and Gerrit Basics
+
+Git and Gerrit are both essential tools which we use to program the robot, this document goes over the basics of both tools and some helpful information on their use.
+
+* [What is Git?](#what-is-git)
+ * [Git basics](#git-basics)
+ * [Commits](#commits)
+ * [Branches](#branches)
+ * [Helpful commands](#helpful-commands)
+* [What is Gerrit?](#what-is-gerrit)
+ * [Gerrit basics](#gerrit-basics)
+
+## What is Git?
+
+Term Definition:
+- Repository: A project or collection of projects managed using git.
+For example our code lives in a repository called `971-Robot-Code`.
+- Commit: A collection of code changes
+- Branch: A collection of commits
+
+Git is a tool we use which manages changes to our code. Git allows you to track changes, and combine them back into the version of the code that the robot runs off of.
+
+One of the ways git tracks changes to our code is **commits**, this may deviate slightly from what you're used to if you've used github before.
+A commit contains the code of one change, as well a title and description of the change.
+
+Another way to manage your changes locally are **branches**.
+Branches contain a stack of commits, and branches are used to combine commits back into the code which runs on the robot.
+This is called the **main branch**, and is the stack of commits which runs on the robot.
+
+Once your change has finished you need to **push** it.
+Pushing your commit places it online so that it can be checked, and then put into the main branch.
+
+### Git basics
+
+When you make a new file in a git repository, its considered *untracked*.
+You can see this by doing `git status`, this shows you the status of all the files in your change, before they're committed.
+To track it you have to do `git add <FILENAME>`, now if you do git status you'll see its green and tracked.
+If you're editing an already tracked file it'll show up as tracked, but won't be added until you do git add
+
+#### Commits
+
+Once you have a change finished, and all the files added, you can do `git commit -s`.
+This then brings up your text editor and lets you edit the commit message and description.
+
+The commits are formatted like this:
+
+```
+Title
+
+Description
+
+...
+```
+
+Heres a good blog post about formatting commit messages: [link](https://cbea.ms/git-commit/)
+
+Once you have committed it you can push the code to our repository using `git push origin HEAD:refs/for/main`
+
+To break this command down you are pushing to origin, which links to the online repository, `refs/for/main` tells it to make a gerrit commit review for the main branch.
+
+
+#### Branches
+
+Whenever you need to manage multiple commits you'll be doing them accross multiple branches.
+Here are the basics of branch management:
+
+```bash
+git branch <NAME> # Creates a new branch with the given name
+git branch -D <NAME> # Deletes the branch with the given name
+git switch <NAME> # Switches to the branch with the given name
+```
+
+If you need to switch to a different branch, but the change you have on your current branch hasn't been committed.
+You can do `git stash`, which will store your uncommitted changes until you do `git stash pop`.
+
+#### Helpful commands
+
+```bash
+# This updates your local code to match the latest version
+git switch main
+git pull
+
+# Rebases your current commit onto the latest main branch
+git pull origin main --rebase
+```
+
+## What is Gerrit?
+
+Gerrit is a similar tool to github, except that instead of making changes and doing reviews on branches, you do them on commmits.
+
+### Gerrit basics
+
+If you have a commit on gerrit that you want to edit you can press d when on the commit or click download. Then select checkout.
+
+Paste the command into the terminal and do `git switch -c <NAME>`. The name can be anything, as its only used to manage local development.
+
+Once you've made your changes to that commit, you can do `git commit --amend -s`, which will add your new changes to the commit.
+
+Occasionally you'll need to edit someone elses commit.
+When you are pushing you'll get an error which states that you cannot override another author's commit.
+To get around this you can do `git commit --amend --reset-author -s`
diff --git a/frc971/control_loops/swerve/casadi_velocity_mpc.py b/frc971/control_loops/swerve/casadi_velocity_mpc.py
index 8b97933..239f49a 100644
--- a/frc971/control_loops/swerve/casadi_velocity_mpc.py
+++ b/frc971/control_loops/swerve/casadi_velocity_mpc.py
@@ -233,10 +233,13 @@
# TODO(austin): Don't penalize torque steering current.
for i in range(4):
+ Is = U[2 * i + 0]
+ Id = U[2 * i + 1]
# Steer
- J += U[2 * i + 0] * U[2 * i + 0] / 100000.0
+ J += ((Is + dynamics.STEER_CURRENT_COUPLING_FACTOR * Id)**
+ 2.0) / 100000.0
# Drive
- J += U[2 * i + 1] * U[2 * i + 1] / 1000.0
+ J += Id * Id / 1000.0
return casadi.Function("Jn", [X, U, R], [J])
diff --git a/frc971/control_loops/swerve/generate_physics.cc b/frc971/control_loops/swerve/generate_physics.cc
index e223b74..3c4eaf6 100644
--- a/frc971/control_loops/swerve/generate_physics.cc
+++ b/frc971/control_loops/swerve/generate_physics.cc
@@ -617,6 +617,16 @@
sub(integer(1), div(rb1_, rp_)))),
div(rw_, rb2_))))))))));
result_py.emplace_back("");
+ result_py.emplace_back("# Is = STEER_CURRENT_COUPLING_FACTOR * Id");
+ result_py.emplace_back(absl::Substitute(
+ "STEER_CURRENT_COUPLING_FACTOR = $0",
+ ccode(*(neg(
+ mul(div(Gs_, Kts_),
+ mul(div(Ktd_, mul(Gd_, rw_)),
+ neg(mul(add(neg(wb_), mul(add(rs_, rp_),
+ sub(integer(1), div(rb1_, rp_)))),
+ div(rw_, rb2_))))))))));
+ result_py.emplace_back("");
result_py.emplace_back("# Returns the derivative of our state vector");
result_py.emplace_back("# [thetas0, thetad0, omegas0, omegad0,");
diff --git a/frc971/control_loops/swerve/physics_test.py b/frc971/control_loops/swerve/physics_test.py
index 9aa6457..0a3fdb6 100644
--- a/frc971/control_loops/swerve/physics_test.py
+++ b/frc971/control_loops/swerve/physics_test.py
@@ -582,6 +582,23 @@
self.assertLess(xdot[dynamics.STATE_OMEGAD2, 0], -100.0)
self.assertLess(xdot[dynamics.STATE_OMEGAD3, 0], -100.0)
+ def test_steer_coupling(self):
+ """Tests that the steer coupling factor cancels out steer coupling torque."""
+ steer_I = numpy.array(
+ [[dynamics.STEER_CURRENT_COUPLING_FACTOR * 10.0], [10.0]] * 4)
+
+ X = utils.state_vector(
+ velocity=numpy.array([[0.0], [0.0]]),
+ omega=0.0,
+ )
+ X_velocity = self.to_velocity_state(X)
+ Xdot = self.velocity_swerve_physics(X_velocity, steer_I)
+
+ self.assertAlmostEqual(Xdot[dynamics.VELOCITY_STATE_OMEGAS0, 0], 0.0)
+ self.assertAlmostEqual(Xdot[dynamics.VELOCITY_STATE_OMEGAS1, 0], 0.0)
+ self.assertAlmostEqual(Xdot[dynamics.VELOCITY_STATE_OMEGAS2, 0], 0.0)
+ self.assertAlmostEqual(Xdot[dynamics.VELOCITY_STATE_OMEGAS3, 0], 0.0)
+
if __name__ == "__main__":
unittest.main()
diff --git a/frc971/control_loops/swerve/spline_ui/BUILD b/frc971/control_loops/swerve/spline_ui/BUILD
new file mode 100644
index 0000000..8b98959
--- /dev/null
+++ b/frc971/control_loops/swerve/spline_ui/BUILD
@@ -0,0 +1,34 @@
+load("//frc971/downloader:downloader.bzl", "aos_downloader_dir")
+
+aos_downloader_dir(
+ name = "www_files",
+ srcs = [
+ "//frc971/control_loops/swerve/spline_ui/www:static_files",
+ ],
+ dir = "www",
+ target_compatible_with = ["@platforms//os:linux"],
+ visibility = ["//visibility:public"],
+)
+
+cc_binary(
+ name = "server",
+ srcs = [
+ "server.cc",
+ ],
+ data = [
+ "//frc971/control_loops/swerve/spline_ui/www:static_files",
+ ],
+ target_compatible_with = ["@platforms//os:linux"],
+ visibility = ["//visibility:public"],
+ deps = [
+ "//aos:init",
+ "//aos/containers:ring_buffer",
+ "//aos/events:shm_event_loop",
+ "//aos/logging",
+ "//aos/network:gen_embedded",
+ "//aos/seasocks:seasocks_logger",
+ "//aos/time",
+ "//third_party/seasocks",
+ "@com_google_protobuf//:protobuf",
+ ],
+)
diff --git a/frc971/control_loops/swerve/spline_ui/server.cc b/frc971/control_loops/swerve/spline_ui/server.cc
new file mode 100644
index 0000000..5d8224c
--- /dev/null
+++ b/frc971/control_loops/swerve/spline_ui/server.cc
@@ -0,0 +1,108 @@
+#include "seasocks/Server.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <array>
+#include <cmath>
+#include <memory>
+#include <set>
+#include <sstream>
+
+#include "absl/flags/flag.h"
+#include "google/protobuf/util/json_util.h"
+
+#include "aos/containers/ring_buffer.h"
+#include "aos/events/shm_event_loop.h"
+#include "aos/init.h"
+#include "aos/logging/logging.h"
+#include "aos/seasocks/seasocks_logger.h"
+#include "aos/time/time.h"
+#include "internal/Embedded.h"
+#include "seasocks/StringUtil.h"
+#include "seasocks/WebSocket.h"
+
+ABSL_FLAG(int, port, 1180, "Port number to serve on");
+
+namespace frc971::control_loops::swerve::spline_ui {
+
+namespace chrono = ::std::chrono;
+
+class WebsocketHandler : public seasocks::WebSocket::Handler {
+ public:
+ WebsocketHandler();
+ void onConnect(seasocks::WebSocket *connection) override;
+ void onData(seasocks::WebSocket *connection, const char *data) override;
+ void onDisconnect(seasocks::WebSocket *connection) override;
+
+ void SendData(const std::string &data);
+
+ private:
+ std::set<seasocks::WebSocket *> connections_;
+};
+
+WebsocketHandler::WebsocketHandler() {}
+
+void WebsocketHandler::onConnect(seasocks::WebSocket *connection) {
+ connections_.insert(connection);
+ AOS_LOG(INFO, "Connected: %s : %s\n", connection->getRequestUri().c_str(),
+ seasocks::formatAddress(connection->getRemoteAddress()).c_str());
+}
+
+void WebsocketHandler::onData(seasocks::WebSocket *connection,
+ const char *data) {
+ // TODO(Nathan): needs tests to check/modify file name
+ AOS_LOG(INFO, "Got data: %s\n", data);
+ connection->send("I got your data!");
+ // parse websocket.send(filePath + '\n' + splineData);
+ // write splineData to filePath
+ std::string_view data_view(data);
+ size_t newline = data_view.find('\n');
+ if (newline == std::string_view::npos) {
+ AOS_LOG(ERROR, "No newline found in data: %s\n", data);
+ return;
+ }
+ std::string_view file_path = data_view.substr(0, newline);
+ std::string_view spline_data = data_view.substr(newline + 1);
+ aos::util::WriteStringToFileOrDie(
+ absl::StrCat(getenv("BUILD_WORKSPACE_DIRECTORY"), file_path),
+ spline_data);
+
+ AOS_LOG(
+ INFO, "Wrote data to file: %s\n",
+ absl::StrCat(getenv("BUILD_WORKSPACE_DIRECTORY"), spline_data).c_str());
+}
+
+void WebsocketHandler::onDisconnect(seasocks::WebSocket *connection) {
+ connections_.erase(connection);
+ AOS_LOG(INFO, "Disconnected: %s : %s\n", connection->getRequestUri().c_str(),
+ seasocks::formatAddress(connection->getRemoteAddress()).c_str());
+}
+
+void WebsocketHandler::SendData(const std::string &data) {
+ for (seasocks::WebSocket *websocket : connections_) {
+ websocket->send(data.c_str());
+ }
+}
+
+} // namespace frc971::control_loops::swerve::spline_ui
+
+int main(int argc, char **argv) {
+ // Make sure to reference this to force the linker to include it.
+ findEmbeddedContent("");
+
+ ::aos::InitGoogle(&argc, &argv);
+
+ seasocks::Server server(::std::shared_ptr<seasocks::Logger>(
+ new ::aos::seasocks::SeasocksLogger(seasocks::Logger::Level::Info)));
+
+ auto websocket_handler = std::make_shared<
+ frc971::control_loops::swerve::spline_ui::WebsocketHandler>();
+ server.addWebSocketHandler("/ws", websocket_handler);
+
+ server.serve("frc971/control_loops/swerve/spline_ui/www/static_files",
+ absl::GetFlag(FLAGS_port));
+
+ return 0;
+}
diff --git a/frc971/control_loops/swerve/spline_ui/www/app/app.module.ts b/frc971/control_loops/swerve/spline_ui/www/app/app.module.ts
index 6948041..6e5396b 100644
--- a/frc971/control_loops/swerve/spline_ui/www/app/app.module.ts
+++ b/frc971/control_loops/swerve/spline_ui/www/app/app.module.ts
@@ -1,7 +1,7 @@
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
-
+import {FormsModule} from '@angular/forms';
import {App} from './app';
@NgModule({
@@ -9,6 +9,7 @@
imports: [
BrowserModule,
BrowserAnimationsModule,
+ FormsModule,
],
exports: [App],
bootstrap: [App],
diff --git a/frc971/control_loops/swerve/spline_ui/www/app/app.ng.html b/frc971/control_loops/swerve/spline_ui/www/app/app.ng.html
index 6e43eac..dc753d3 100644
--- a/frc971/control_loops/swerve/spline_ui/www/app/app.ng.html
+++ b/frc971/control_loops/swerve/spline_ui/www/app/app.ng.html
@@ -1 +1,11 @@
<h1>Spline UI</h1>
+<input type="text" [(ngModel)]="fileName" placeholder="File Name">
+<button (click)="save()">Save</button>
+
+<select [(ngModel)]="year">
+ <option value="2020">2020</option>
+ <option value="2021">2021</option>
+ <option value="2022">2022</option>
+ <option value="2023">2023</option>
+ <option value="2024">2024</option>
+</select>
\ No newline at end of file
diff --git a/frc971/control_loops/swerve/spline_ui/www/app/app.ts b/frc971/control_loops/swerve/spline_ui/www/app/app.ts
index dc0cb7c..fd4e82f 100644
--- a/frc971/control_loops/swerve/spline_ui/www/app/app.ts
+++ b/frc971/control_loops/swerve/spline_ui/www/app/app.ts
@@ -6,4 +6,58 @@
styleUrls: ['../app/common.css'],
})
export class App {
-}
+ fileName: string = 'spline.json';
+ year: number = 2024;
+ splineCount: number = 0;
+ splineX: number[] = [0, 0, 0, 0, 0, 0];
+ splineY: number[] = [0, 0, 0, 0, 0, 0];
+ longConstraint: number = 10;
+ latConstraint: number = 10;
+ voltageConstraint: number = 10;
+
+ save() {
+ //make a websocket call to save the spline
+ const websocket = new WebSocket('ws://localhost:1180/ws');
+ websocket.addEventListener('open', () => {
+ const splineJson = {
+ spline_count: this.splineCount,
+ spline_x: this.splineX,
+ spline_y: this.splineY,
+ constraints: [
+ {
+ constraint_type: "LONGITUDINAL_ACCELERATION",
+ value: this.longConstraint
+ },
+ {
+ constraint_type: "LATERAL_ACCELERATION",
+ value: this.latConstraint
+ },
+ {
+ constraint_type: "VOLTAGE",
+ value: this.voltageConstraint
+ }
+ ]
+ };
+ const splineData = JSON.stringify(splineJson, null, 4);
+ const filePath = this.getPath(this.year) + this.fileName;
+ websocket.send(filePath + '\n' + splineData);
+ });
+ }
+
+ // copied from //frc971/control_loops/python/constants.py
+ // returns the path to the spline jsons for the given year
+ getPath(year: number): string {
+ if(year == 2020 || year == 2021) {
+ return "/y2020/actors/splines/";
+ }
+ else if(year == 2022) {
+ return "/y2022/actors/splines/";
+ }
+ else if(year == 2023 || year == 2024) {
+ return "/y" + year + "/autonomous/splines/";
+ }
+ else {
+ return "/frc971/control_loops/python/spline_jsons/";
+ }
+ }
+}
\ No newline at end of file
diff --git a/frc971/control_loops/swerve/spline_ui/www/package.json b/frc971/control_loops/swerve/spline_ui/www/package.json
index 54a7f09..58ce814 100644
--- a/frc971/control_loops/swerve/spline_ui/www/package.json
+++ b/frc971/control_loops/swerve/spline_ui/www/package.json
@@ -1,6 +1,8 @@
{
+ "name": "@org_frc971/control_loops/swerve/spline_ui/www",
"private": true,
"dependencies": {
- "@angular/animations": "v16-lts"
+ "@angular/animations": "v16-lts",
+ "@angular/forms": "v16-lts"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c8e5425..807e87b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -175,6 +175,9 @@
'@angular/animations':
specifier: v16-lts
version: 16.2.12(@angular/core@16.2.12)
+ '@angular/forms':
+ specifier: v16-lts
+ version: 16.2.12(@angular/common@16.2.12)(@angular/core@16.2.12)(@angular/platform-browser@16.2.12)(rxjs@7.5.7)
scouting/webserver/requests/messages: {}
diff --git a/scouting/webserver/main.go b/scouting/webserver/main.go
index d655708..6eca5a9 100644
--- a/scouting/webserver/main.go
+++ b/scouting/webserver/main.go
@@ -133,8 +133,9 @@
defer database.Delete()
scoutingServer := server.NewScoutingServer()
+ var realClock requests.RealClock
static.ServePages(scoutingServer, *dirPtr, database)
- requests.HandleRequests(database, scoutingServer)
+ requests.HandleRequests(database, scoutingServer, realClock)
scoutingServer.Start(*portPtr)
fmt.Println("Serving", *dirPtr, "on port", *portPtr)
diff --git a/scouting/webserver/requests/BUILD b/scouting/webserver/requests/BUILD
index 07ebbe6..6c0460b 100644
--- a/scouting/webserver/requests/BUILD
+++ b/scouting/webserver/requests/BUILD
@@ -25,6 +25,8 @@
"//scouting/webserver/requests/messages:request_all_notes_response_go_fbs",
"//scouting/webserver/requests/messages:request_all_pit_images_go_fbs",
"//scouting/webserver/requests/messages:request_all_pit_images_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_current_scouting_go_fbs",
+ "//scouting/webserver/requests/messages:request_current_scouting_response_go_fbs",
"//scouting/webserver/requests/messages:request_notes_for_team_go_fbs",
"//scouting/webserver/requests/messages:request_notes_for_team_response_go_fbs",
"//scouting/webserver/requests/messages:request_pit_images_go_fbs",
@@ -69,6 +71,8 @@
"//scouting/webserver/requests/messages:request_all_notes_response_go_fbs",
"//scouting/webserver/requests/messages:request_all_pit_images_go_fbs",
"//scouting/webserver/requests/messages:request_all_pit_images_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_current_scouting_go_fbs",
+ "//scouting/webserver/requests/messages:request_current_scouting_response_go_fbs",
"//scouting/webserver/requests/messages:request_notes_for_team_go_fbs",
"//scouting/webserver/requests/messages:request_pit_images_go_fbs",
"//scouting/webserver/requests/messages:request_pit_images_response_go_fbs",
diff --git a/scouting/webserver/requests/debug/BUILD b/scouting/webserver/requests/debug/BUILD
index ff85206..7a78456 100644
--- a/scouting/webserver/requests/debug/BUILD
+++ b/scouting/webserver/requests/debug/BUILD
@@ -16,6 +16,7 @@
"//scouting/webserver/requests/messages:request_all_matches_response_go_fbs",
"//scouting/webserver/requests/messages:request_all_notes_response_go_fbs",
"//scouting/webserver/requests/messages:request_all_pit_images_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_current_scouting_response_go_fbs",
"//scouting/webserver/requests/messages:request_notes_for_team_response_go_fbs",
"//scouting/webserver/requests/messages:request_pit_images_response_go_fbs",
"//scouting/webserver/requests/messages:request_shift_schedule_response_go_fbs",
diff --git a/scouting/webserver/requests/debug/cli/cli_test.py b/scouting/webserver/requests/debug/cli/cli_test.py
index cfdcd03..70a94c8 100644
--- a/scouting/webserver/requests/debug/cli/cli_test.py
+++ b/scouting/webserver/requests/debug/cli/cli_test.py
@@ -96,6 +96,15 @@
time.sleep(0.25)
+ def test_request_current_scouting(self):
+ self.start_servers(year=2020, event_code="fake")
+
+ # First submit some data to be added to the database.
+ json_path = write_json_request({"team_number": "971"})
+ exit_code, _, stderr = run_debug_cli(
+ ["-requestCurrentScouting", json_path])
+ self.assertEqual(exit_code, 0, stderr)
+
def test_submit_and_request_notes(self):
self.start_servers(year=2020, event_code="fake")
diff --git a/scouting/webserver/requests/debug/cli/main.go b/scouting/webserver/requests/debug/cli/main.go
index a4346e5..f513c50 100644
--- a/scouting/webserver/requests/debug/cli/main.go
+++ b/scouting/webserver/requests/debug/cli/main.go
@@ -95,6 +95,8 @@
"If specified, parse the file as a requestAllDriverRankings JSON request.")
requestAllNotesPtr := flag.String("requestAllNotes", "",
"If specified, parse the file as a requestAllNotes JSON request.")
+ requestCurrentScoutingPtr := flag.String("requestCurrentScouting", "",
+ "If specified, parse the file as a requestCurrentScouting JSON request.")
flag.Parse()
spew.Config.Indent = *indentPtr
@@ -144,4 +146,11 @@
*requestAllNotesPtr,
*addressPtr,
debug.RequestAllNotes)
+
+ maybePerformRequest(
+ "requestCurrentScouting",
+ "scouting/webserver/requests/messages/request_current_scouting.fbs",
+ *requestCurrentScoutingPtr,
+ *addressPtr,
+ debug.RequestCurrentScouting)
}
diff --git a/scouting/webserver/requests/debug/debug.go b/scouting/webserver/requests/debug/debug.go
index ed8a1b7..88b4eac 100644
--- a/scouting/webserver/requests/debug/debug.go
+++ b/scouting/webserver/requests/debug/debug.go
@@ -18,6 +18,7 @@
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_notes_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_pit_images_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_current_scouting_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_pit_images_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule_response"
@@ -33,6 +34,9 @@
// The username to submit the various requests as.
const DefaultUsername = "debug_cli"
+// TODO: Make the username an argument of the Request* functions.
+var Username = DefaultUsername
+
// A struct that can be used as an `error`. It contains information about the
// why the server was unhappy and what the corresponding request was.
type ResponseError struct {
@@ -82,7 +86,7 @@
return nil, err
}
req.Header.Add("Authorization", "Basic "+
- base64.StdEncoding.EncodeToString([]byte(DefaultUsername+":")))
+ base64.StdEncoding.EncodeToString([]byte(Username+":")))
client := &http.Client{}
resp, err := client.Do(req)
@@ -172,6 +176,12 @@
request_shift_schedule_response.GetRootAsRequestShiftScheduleResponse)
}
+func RequestCurrentScouting(server string, requestBytes []byte) (*request_current_scouting_response.RequestCurrentScoutingResponseT, error) {
+ return sendMessage[request_current_scouting_response.RequestCurrentScoutingResponseT](
+ server+"/requests/request/current_scouting", requestBytes,
+ request_current_scouting_response.GetRootAsRequestCurrentScoutingResponse)
+}
+
func SubmitShiftSchedule(server string, requestBytes []byte) (*submit_shift_schedule_response.SubmitShiftScheduleResponseT, error) {
return sendMessage[submit_shift_schedule_response.SubmitShiftScheduleResponseT](
server+"/requests/submit/shift_schedule", requestBytes,
diff --git a/scouting/webserver/requests/messages/BUILD b/scouting/webserver/requests/messages/BUILD
index 6dee54d..3a36304 100644
--- a/scouting/webserver/requests/messages/BUILD
+++ b/scouting/webserver/requests/messages/BUILD
@@ -10,6 +10,8 @@
"request_all_matches_response",
"request_all_notes",
"request_all_notes_response",
+ "request_current_scouting",
+ "request_current_scouting_response",
"request_2023_data_scouting",
"request_2023_data_scouting_response",
"request_2024_data_scouting",
diff --git a/scouting/webserver/requests/messages/request_current_scouting.fbs b/scouting/webserver/requests/messages/request_current_scouting.fbs
new file mode 100644
index 0000000..9f3ef9c
--- /dev/null
+++ b/scouting/webserver/requests/messages/request_current_scouting.fbs
@@ -0,0 +1,7 @@
+namespace scouting.webserver.requests;
+
+table RequestCurrentScouting {
+ team_number:string (id: 0);
+}
+
+root_type RequestCurrentScouting;
diff --git a/scouting/webserver/requests/messages/request_current_scouting_response.fbs b/scouting/webserver/requests/messages/request_current_scouting_response.fbs
new file mode 100644
index 0000000..508fa46
--- /dev/null
+++ b/scouting/webserver/requests/messages/request_current_scouting_response.fbs
@@ -0,0 +1,10 @@
+namespace scouting.webserver.requests;
+
+table CollectedBy {
+ name: string (id: 0);
+}
+table RequestCurrentScoutingResponse {
+ collected_by:[CollectedBy] (id: 0);
+}
+
+root_type RequestCurrentScoutingResponse;
diff --git a/scouting/webserver/requests/requests.go b/scouting/webserver/requests/requests.go
index 0367ff2..321f224 100644
--- a/scouting/webserver/requests/requests.go
+++ b/scouting/webserver/requests/requests.go
@@ -10,6 +10,7 @@
"sort"
"strconv"
"strings"
+ "time"
"github.com/frc971/971-Robot-Code/scouting/db"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/delete_2023_data_scouting"
@@ -29,6 +30,8 @@
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_notes_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_pit_images"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_pit_images_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_current_scouting"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_current_scouting_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_pit_images"
@@ -69,6 +72,8 @@
type RequestPitImagesResponseT = request_pit_images_response.RequestPitImagesResponseT
type RequestAllPitImages = request_all_pit_images.RequestAllPitImages
type RequestAllPitImagesResponseT = request_all_pit_images_response.RequestAllPitImagesResponseT
+type RequestCurrentScouting = request_current_scouting.RequestCurrentScouting
+type RequestCurrentScoutingResponseT = request_current_scouting_response.RequestCurrentScoutingResponseT
type RequestNotesForTeam = request_notes_for_team.RequestNotesForTeam
type RequestNotesForTeamResponseT = request_notes_for_team_response.RequestNotesForTeamResponseT
type RequestShiftSchedule = request_shift_schedule.RequestShiftSchedule
@@ -116,6 +121,16 @@
DeleteFromActions(string, int32, int32, string) error
}
+type Clock interface {
+ Now() time.Time
+}
+
+type RealClock struct{}
+
+func (RealClock) Now() time.Time {
+ return time.Now()
+}
+
// Handles unknown requests. Just returns a 404.
func unknown(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusNotFound)
@@ -372,6 +387,56 @@
w.Write(builder.FinishedBytes())
}
+type requestCurrentScoutingHandler struct {
+ // Map that has a key of team number with a value is a map of names to timestamps
+ // so there aren't duplicate timestamps for one person.
+ scoutingMap map[string]map[string]time.Time
+ db Database
+ clock Clock
+}
+
+func (handler requestCurrentScoutingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ requestBytes, err := io.ReadAll(req.Body)
+ if err != nil {
+ respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
+ return
+ }
+
+ request, success := parseRequest(w, requestBytes, "RequestCurrentScouting", request_current_scouting.GetRootAsRequestCurrentScouting)
+ if !success {
+ return
+ }
+ currentTime := handler.clock.Now()
+ teamNumber := string(request.TeamNumber())
+ collectedBy := parseUsername(req)
+
+ if handler.scoutingMap[teamNumber] == nil {
+ handler.scoutingMap[teamNumber] = map[string]time.Time{}
+ }
+ handler.scoutingMap[teamNumber][collectedBy] = currentTime
+ // Delete any scout information from 10+ seconds ago.
+ for team, teamMap := range handler.scoutingMap {
+ for name, timeStamp := range teamMap {
+ if currentTime.Sub(timeStamp) >= 10*time.Second {
+ delete(handler.scoutingMap[team], name)
+ }
+ }
+ }
+
+ var response RequestCurrentScoutingResponseT
+ for name, _ := range handler.scoutingMap[teamNumber] {
+ if name != collectedBy {
+ response.CollectedBy = append(response.CollectedBy, &request_current_scouting_response.CollectedByT{
+ Name: name,
+ })
+ }
+ }
+
+ builder := flatbuffers.NewBuilder(10)
+ builder.Finish((&response).Pack(builder))
+ w.Write(builder.FinishedBytes())
+}
+
type submitNoteScoutingHandler struct {
db Database
}
@@ -1299,7 +1364,7 @@
w.Write(builder.FinishedBytes())
}
-func HandleRequests(db Database, scoutingServer server.ScoutingServer) {
+func HandleRequests(db Database, scoutingServer server.ScoutingServer, clock Clock) {
scoutingServer.HandleFunc("/requests", unknown)
scoutingServer.Handle("/requests/request/all_matches", requestAllMatchesHandler{db})
scoutingServer.Handle("/requests/request/all_notes", requestAllNotesHandler{db})
@@ -1310,6 +1375,7 @@
scoutingServer.Handle("/requests/submit/submit_pit_image", submitPitImageScoutingHandler{db})
scoutingServer.Handle("/requests/request/pit_images", requestPitImagesHandler{db})
scoutingServer.Handle("/requests/request/all_pit_images", requestAllPitImagesHandler{db})
+ scoutingServer.Handle("/requests/request/current_scouting", requestCurrentScoutingHandler{make(map[string]map[string]time.Time), db, clock})
scoutingServer.Handle("/requests/request/notes_for_team", requestNotesForTeamHandler{db})
scoutingServer.Handle("/requests/submit/shift_schedule", submitShiftScheduleHandler{db})
scoutingServer.Handle("/requests/request/shift_schedule", requestShiftScheduleHandler{db})
diff --git a/scouting/webserver/requests/requests_test.go b/scouting/webserver/requests/requests_test.go
index d0e17b8..19bcae4 100644
--- a/scouting/webserver/requests/requests_test.go
+++ b/scouting/webserver/requests/requests_test.go
@@ -4,6 +4,7 @@
"net/http"
"reflect"
"testing"
+ "time"
"github.com/frc971/971-Robot-Code/scouting/db"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/debug"
@@ -20,6 +21,8 @@
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_notes_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_pit_images"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_pit_images_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_current_scouting"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_current_scouting_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_pit_images"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_pit_images_response"
@@ -35,11 +38,20 @@
flatbuffers "github.com/google/flatbuffers/go"
)
+type MockClock struct {
+ now time.Time
+}
+
+func (mockClock MockClock) Now() time.Time {
+ return mockClock.now
+}
+
// Validates that an unhandled address results in a 404.
func Test404(t *testing.T) {
db := MockDatabase{}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&db, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&db, scoutingServer, &mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -150,7 +162,8 @@
},
}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&db, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&db, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -235,7 +248,8 @@
},
}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&db, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&db, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -316,7 +330,8 @@
},
}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&db, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&db, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -542,7 +557,8 @@
func TestSubmitNotes(t *testing.T) {
database := MockDatabase{}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&database, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&database, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -591,6 +607,81 @@
}
}
+// Validates that we can request names of peoples who are currently scouting the same team.
+func TestRequestCurrentScouting(t *testing.T) {
+ database := MockDatabase{}
+ scoutingServer := server.NewScoutingServer()
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&database, scoutingServer, mockClock)
+ scoutingServer.Start(8080)
+ defer scoutingServer.Stop()
+
+ builder := flatbuffers.NewBuilder(1024)
+ builder.Finish((&request_current_scouting.RequestCurrentScoutingT{
+ TeamNumber: "971",
+ }).Pack(builder))
+ response, err := debug.RequestCurrentScouting("http://localhost:8080", builder.FinishedBytes())
+ if err != nil {
+ t.Fatal("Failed to request current scouting: ", err)
+ }
+
+ expected := request_current_scouting_response.RequestCurrentScoutingResponseT{
+ CollectedBy: []*request_current_scouting_response.CollectedByT{},
+ }
+
+ if len(expected.CollectedBy) != len(response.CollectedBy) {
+ t.Fatal("Expected ", expected, ", but got ", *response)
+ }
+ for i, collectRecord := range expected.CollectedBy {
+ if !reflect.DeepEqual(*collectRecord, *response.CollectedBy[i]) {
+ t.Fatal("Expected for collected by ", i, ":", *collectRecord, ", but got:", *response.CollectedBy[i])
+ }
+ }
+
+ debug.Username = "george"
+ builder.Finish((&request_current_scouting.RequestCurrentScoutingT{
+ TeamNumber: "971",
+ }).Pack(builder))
+ response, err = debug.RequestCurrentScouting("http://localhost:8080", builder.FinishedBytes())
+ if err != nil {
+ t.Fatal("Failed to request current scouting: ", err)
+ }
+
+ expected = request_current_scouting_response.RequestCurrentScoutingResponseT{
+ CollectedBy: []*request_current_scouting_response.CollectedByT{
+ {"debug_cli"},
+ },
+ }
+
+ if len(expected.CollectedBy) != len(response.CollectedBy) {
+ t.Fatal("Expected ", expected, ", but got ", *response)
+ }
+
+ for i, collectRecord := range expected.CollectedBy {
+ if !reflect.DeepEqual(*collectRecord, *response.CollectedBy[i]) {
+ t.Fatal("Expected for collected by ", i, ":", *collectRecord, ", but got:", *response.CollectedBy[i])
+ }
+ }
+
+ // After skipping 10 seconds ahead, the previous request from "debug_cli" should no longer appear.
+ mockClock.now = mockClock.now.Add(time.Second * 10)
+
+ builder.Finish((&request_current_scouting.RequestCurrentScoutingT{
+ TeamNumber: "971",
+ }).Pack(builder))
+ response, err = debug.RequestCurrentScouting("http://localhost:8080", builder.FinishedBytes())
+ if err != nil {
+ t.Fatal("Failed to request current scouting: ", err)
+ }
+
+ expected = request_current_scouting_response.RequestCurrentScoutingResponseT{
+ CollectedBy: []*request_current_scouting_response.CollectedByT{},
+ }
+
+ // Reset username for other tests.
+ debug.Username = "debug_cli"
+}
+
func TestRequestNotes(t *testing.T) {
database := MockDatabase{
notes: []db.NotesData{{
@@ -610,7 +701,8 @@
}},
}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&database, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&database, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -631,7 +723,8 @@
func TestSubmitPitImage(t *testing.T) {
database := MockDatabase{}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&database, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&database, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -677,7 +770,8 @@
}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&db, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&db, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -727,7 +821,8 @@
}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&db, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&db, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -788,7 +883,8 @@
},
}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&db, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&db, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -835,7 +931,8 @@
func TestSubmitShiftSchedule(t *testing.T) {
database := MockDatabase{}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&database, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&database, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -874,7 +971,8 @@
func TestSubmitDriverRanking(t *testing.T) {
database := MockDatabase{}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&database, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&database, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -919,7 +1017,8 @@
},
}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&db, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&db, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -994,7 +1093,8 @@
},
}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&db, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&db, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -1059,7 +1159,8 @@
func TestAddingActions2024(t *testing.T) {
database := MockDatabase{}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&database, scoutingServer)
+ mockClock := MockClock{now: time.Now()}
+ HandleRequests(&database, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -1142,6 +1243,7 @@
// Validates that we can delete 2024 stats.
func TestDeleteFromStats2024(t *testing.T) {
+ mockClock := MockClock{now: time.Now()}
database := MockDatabase{
stats2024: []db.Stats2024{
{
@@ -1185,7 +1287,7 @@
},
}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&database, scoutingServer)
+ HandleRequests(&database, scoutingServer, mockClock)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
diff --git a/scouting/www/entry/entry.component.ts b/scouting/www/entry/entry.component.ts
index 230bfec..1a757a0 100644
--- a/scouting/www/entry/entry.component.ts
+++ b/scouting/www/entry/entry.component.ts
@@ -39,6 +39,8 @@
MatchListRequestor,
ActionsSubmitter,
} from '@org_frc971/scouting/www/rpc';
+import {RequestCurrentScouting} from '@org_frc971/scouting/webserver/requests/messages/request_current_scouting_generated';
+import {RequestCurrentScoutingResponse} from '@org_frc971/scouting/webserver/requests/messages/request_current_scouting_response_generated';
import {ActionHelper, ConcreteAction} from './action_helper';
import * as pako from 'pako';
@@ -136,6 +138,8 @@
penalties: number = 0;
teamSelectionIsValid = false;
+ searchForDuplicateScouting: boolean = false;
+ duplicateSearchTimer: ReturnType<typeof setTimeout> | null = null;
// When the user chooses to generate QR codes, we convert the flatbuffer into
// a long string. Since we frequently have more data than we can display in a
@@ -165,8 +169,13 @@
this.fetchMatchList();
}
+ ngOnDestroy() {
+ clearInterval(this.duplicateSearchTimer);
+ }
+
goToNextTeam() {
this.ngOnInit();
+ this.ngOnDestroy();
this.teamNumber = this.nextTeamNumber;
this.nextTeamNumber = '';
}
@@ -184,6 +193,53 @@
}
}
+ async findOthersScoutingThisRobot() {
+ const builder = new Builder();
+ const teamNumber = builder.createString(this.teamNumber);
+
+ builder.finish(
+ RequestCurrentScouting.createRequestCurrentScouting(builder, teamNumber)
+ );
+
+ const buffer = builder.asUint8Array();
+ const res = await fetch('/requests/request/current_scouting', {
+ method: 'POST',
+ body: buffer,
+ });
+
+ if (!res.ok) {
+ const resBuffer = await res.arrayBuffer();
+ const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
+ const parsedResponse = ErrorResponse.getRootAsErrorResponse(fbBuffer);
+ const errorMessage = parsedResponse.errorMessage();
+ this.errorMessage = `Received ${res.status} ${res.statusText}: "${errorMessage}"`;
+ } else {
+ const resBuffer = await res.arrayBuffer();
+ const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
+ const parsedResponse =
+ RequestCurrentScoutingResponse.getRootAsRequestCurrentScoutingResponse(
+ fbBuffer
+ );
+ const collectedBy = [];
+ for (let i = 0; i < parsedResponse.collectedByLength(); i++) {
+ collectedBy.push(parsedResponse.collectedBy(i).name());
+ }
+ this.duplicateSearchTimer = setInterval(() => {
+ if (this.searchForDuplicateScouting && collectedBy.length != 0) {
+ if (
+ confirm(
+ 'This team is currently being scouted by ' +
+ collectedBy +
+ '. Would you like to receive more alerts?'
+ ) != true
+ ) {
+ this.searchForDuplicateScouting = false;
+ }
+ }
+ }, 10000);
+ }
+ }
+
// This gets called when the user changes something on the Init screen.
// It makes sure that the user can't click "Next" until the information is
// valid, or this is for pre-scouting or practice matches.
@@ -314,6 +370,11 @@
this.updateQrCodeValuePieceSize();
}
+ if (target == 'Init') {
+ this.searchForDuplicateScouting = true;
+ this.findOthersScoutingThisRobot();
+ }
+
this.section = target;
}
@@ -457,6 +518,7 @@
this.compType = 'Regular';
this.matchStartTimestamp = 0;
this.selectedValue = 0;
+ this.searchForDuplicateScouting = false;
} else {
const resBuffer = await res.arrayBuffer();
const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
diff --git a/vm/README.md b/vm/README.md
deleted file mode 100644
index ee9d9aa..0000000
--- a/vm/README.md
+++ /dev/null
@@ -1,180 +0,0 @@
-Setting up a Virtual Machine (VM)
-================================================================================
-This document tries to document three ways in which you can set up a
-development environment. The third is essentially the same as the second so
-this document will just focus on the first and second way.
-
-1. Use the vagrant scripts to automatically create everything.
-2. Create a VM manually and set it up manually.
-3. Install Debian natively and set it up manually.
-
-Using the vagrant scripts requires more setup, but generally is more hands-off.
-Setting up a VM manually can be more rewarding and interesting, but requires
-more manual steps and generally takes longer.
-
-Command line knowledge
---------------------------------------------------------------------------------
-Some basic knowledge of using your terminal is required. On Windows, cmd.exe is
-a good start. I would recommend setting up git-bash because it will resemble
-the environment inside the VM much more closely than cmd.exe.
-
-Whenever you see `$` in a code segment below, please type that into your
-terminal. `$` is just a generic representation of what we call the "command
-prompt". On Windows' cmd.exe it would look something like this:
-
- C:\Users\YourName>
-
-On a UNIX-like Operating System (e.g. Linux, OSX) it may look more like this:
-
- yourname@hostname ~ $
-
-The `$` is just a shortcut to represent any style of prompt. When you see
-something like `$ echo Hello` below please type everything after the `$ ` into
-your terminal. In this case that means typing "echo Hello" and pressing Enter.
-
-Access to the Gerrit repository
---------------------------------------------------------------------------------
-In order to use the setup scripts you'll need access to the 971-Robot-Code
-repository on gerrit:
-<https://robotics.mvla.net/gerrit/#/admin/projects/971-Robot-Code>
-
-Please ask your mentors about getting access. If you already have access,
-great!
-
-In general I recommend setting up an SSH key to pull from and push to the
-repository. You can also use HTTPS-based passwords, but it's a little more
-annoying to use in the long term. See the "How to Generate an SSH key" section
-on [gerrit's SSH page](https://robotics.mvla.net/gerrit/#/settings/ssh-keys)
-for more details.
-
-
-Using Vagrant
-================================================================================
-
-Requirements
---------------------------------------------------------------------------------
-These requirements apply to all Operating Systems. The individual setup steps
-may differ. For example, on Debian you can run `apt-get install virtualbox`
-whereas on Windows and OSX you have to download a dedicated installer.
-
-1. Basic knowledge of the command line. See the "Command line knowledge"
- section above.
-
-2. Install Vagrant <https://www.vagrantup.com/downloads.html>
- - Please install this from the website as anything in, say, an apt repo
- would be quite outdated.
-
-3. Install VirtualBox <https://www.virtualbox.org/wiki/Downloads>
- - On Debian you should install this via `apt-get` since it's integrated
- really well. On another OS please use the downloaded installer.
-
-4. Install git <https://git-scm.com/downloads>
- - On Debian you should install this via `apt-get`. On another OS please use
- the downloaded installer.
- - On Windows, I would recommend installing something called "git-bash" at
- the same time. It will provide you with a better terminal experience than
- `cmd.exe` to perform the majority of the remaining steps.
-
-5. Add `vagrant`, `VBoxManage`, and `git` to your PATH.
- - This is most likely already done by the installation binaries.
- It's added to the system path.
- - To test this, type these commands in a terminal:
-
- $ vagrant --version
- Vagrant 1.8.1
- $ VBoxManage --version
- 5.0.14r105127
- $ git --version
- git version 2.11.0
-
- - You may need to log out and back in for the PATH modifications to take
- effect.
-
-Usage
---------------------------------------------------------------------------------
-1. Check this folder out on your computer somewhere.
-
- $ git clone ssh://USERNAME@robotics.mvla.net:29418/971-Robot-Code
-
- where you replace `USERNAME` with your own username. Keep in mind that you
- need your SVN and Gerrit account set up for this to work. Ask the mentors or
- other students about this if you don't have one yet.
-
-2. Go into the directory and build the VM.
-
- $ cd 971-Robot-Code/vm/
- $ vagrant up
-
- Some errors during the `vagrant up` process can be addressed by
- re-provisioning the vagrant box. This is useful if, for example, an
- `apt-get` invocation timed out and caused the provisioning process to abort.
-
- $ vagrant provision
-
-3. Once built, reboot the VM so it starts the GUI properly.
-
- $ vagrant reload
-
-4. You can then log in and open a terminal. The username and password are both
- `user`.
-
-5. Download the code.
-
- $ git clone https://USERNAME@robotics.mvla.net/gerrit/971-Robot-Code
- $ cd 971-Robot-Code
-
-6. Build the code.
-
- $ bazel build //y2017/...
-
- Replace `//y2017` with the appropriate year's folder. For 2018 the build
- target would be `//y2018` for example.
-
-
-Setting up a VM manually
-================================================================================
-This section is lacking a lot of detail, but that's largely because you can
-find most of the information on other websites in a lot more detail.
-
-Requirements
---------------------------------------------------------------------------------
-1. Basic knowledge of the command line. See the "Command line knowledge"
- section above.
-
-2. Install VirtualBox <https://www.virtualbox.org/wiki/Downloads>
-
- See the details from the "Using Vagrant" section above.
-
-3. Download a Debian 8 ISO. You can find one online. The following link may or
- may not work:
- <https://cdimage.debian.org/cdimage/archive/8.9.0/amd64/iso-cd/debian-8.9.0-amd64-netinst.iso>
-
-Usage
---------------------------------------------------------------------------------
-1. Start VirtualBox and create a new VM. Make sure to mount the ISO in the
- virtual CD/DVD drive of the VM.
-
- There are a lot of guides online for creating a VM and can change between
- VirtualBox versions. If VirtualBox asks for the type of VM, select "Debian
- 64-bit".
-
-2. Boot the VM and go through the guided installation steps to install Debian.
- Once the installation completes, reboot to boot into your newly installed
- system. This will be part of the guided installation.
-
-3. Check this folder out on your computer somewhere.
-
- $ git clone ssh://USERNAME@robotics.mvla.net:29418/971-Robot-Code
-
- where you replace `USERNAME` with your own username. Keep in mind that you
- need your SVN and Gerrit account set up for this to work. Ask the mentors or
- other students about this if you don't have one yet.
-
-4. Run the setup script so you can start building our code.
-
- $ cd 971-Robot-Code/vm/
- $ sudo ./setup_code_building.sh
-
-5. Now you can build code. For example, to build all the 2017 code.
-
- $ bazel build //y2017/...
diff --git a/vm/Vagrantfile b/vm/Vagrantfile
deleted file mode 100644
index 1404131..0000000
--- a/vm/Vagrantfile
+++ /dev/null
@@ -1,57 +0,0 @@
-# Vagrantfile API/syntax version. Don't touch unless you know what you're
-# doing!
-VAGRANTFILE_API_VERSION = "2"
-
-# Install the necessary plugins.
-required_plugins = %w( vagrant-persistent-storage )
-required_plugins.each do |plugin|
- unless Vagrant.has_plugin? plugin || ARGV[0] == 'plugin' then
- exec "vagrant plugin install #{plugin};vagrant #{ARGV.join(" ")}"
- end
-end
-
-Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
- # All Vagrant configuration is done here. The most common configuration
- # options are documented and commented below. For a complete reference,
- # please see the online documentation at vagrantup.com.
-
- # Every Vagrant virtual environment requires a box to build off of.
- config.vm.box = "debian/jessie64"
-
- config.vm.provider "virtualbox" do |vb|
- # Don't boot with headless mode
- vb.gui = true
- vb.name = "FRC971-Development-2017"
-
- # There are two shortcuts for modifying number of CPUs and amount of
- # memory. Modify them to your liking.
- vb.cpus = 2
- vb.memory = 1024 * 2
- end
-
- # Use rsync to sync the /vagrant folder.
- # NOTE: If you change these settings they will not take effect until you
- # reboot the VM -- i.e. run a "vagrant reload".
- config.vm.synced_folder ".", "/vagrant", type: "rsync",
- rsync__exclude: [".git/", ".svn/", "workspace.vdi"], rsync__verbose: true
-
- # Set up apt and install packages necessary for building the code.
- config.vm.provision :shell, inline: "/vagrant/setup_apt.sh"
- config.vm.provision :shell, inline: "/vagrant/setup_extra_storage.sh"
- config.vm.provision :shell, inline: "/vagrant/setup_code_building.sh"
- config.vm.provision :shell, inline: "/vagrant/setup_scouting.sh"
- config.vm.provision :shell, inline: "/vagrant/setup_desktop.sh"
- config.vm.provision :shell, inline: "/vagrant/setup_misc_packages.sh"
- config.vm.provision :shell, inline: "/vagrant/setup_vbox_guest_additions.sh"
-
- # Add a second disk so we have plenty of space to compile the code.
- config.persistent_storage.enabled = true
- config.persistent_storage.location = "workspace.vdi"
- config.persistent_storage.size = 40000 # MiB
- config.persistent_storage.use_lvm = false
- config.persistent_storage.filesystem = 'ext4'
- config.persistent_storage.mountpoint = '/home/user'
-
- # Forward the scouting app's port.
- config.vm.network :forwarded_port, guest: 5000, host: 5000, auto_correct: true
-end
diff --git a/vm/setup_apt.sh b/vm/setup_apt.sh
deleted file mode 100755
index d31a372..0000000
--- a/vm/setup_apt.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -u
-
-export DEBIAN_FRONTEND=noninteractive
-
-# Set up contrib and non-free so we can install some more interesting programs.
-cat > /etc/apt/sources.list.d/contrib.list <<EOT
-deb http://ftp.us.debian.org/debian/ jessie contrib non-free
-deb-src http://ftp.us.debian.org/debian/ jessie contrib non-free
-EOT
-
-# Get a list of the latest packages.
-apt-get update
diff --git a/vm/setup_code_building.sh b/vm/setup_code_building.sh
deleted file mode 100755
index cbb8fcd..0000000
--- a/vm/setup_code_building.sh
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -u
-
-export DEBIAN_FRONTEND=noninteractive
-
-readonly PKGS=(
- bazel
- clang-3.6
- clang-format-3.5
- gfortran
- git
- libblas-dev
- liblapack-dev
- libpython3-dev
- libpython-dev
- python3
- python3-matplotlib
- python3-numpy
- python3-scipy
- python-matplotlib
- python-scipy
- resolvconf
- ruby
-)
-
-# Set up the backports repo.
-cat > /etc/apt/sources.list.d/backports.list <<EOT
-deb http://http.debian.net/debian jessie-backports main
-EOT
-
-# Set up the LLVM repo.
-cat > /etc/apt/sources.list.d/llvm-3.6.list <<EOT
-deb http://llvm.org/apt/jessie/ llvm-toolchain-jessie-3.6 main
-deb-src http://llvm.org/apt/jessie/ llvm-toolchain-jessie-3.6 main
-EOT
-
-# Set up the 971-managed bazel repo.
-cat > /etc/apt/sources.list.d/bazel-971.list <<EOT
-deb http://robotics.mvla.net/files/frc971/packages jessie main
-EOT
-
-# Enable user namespace for sandboxing.
-cat > /etc/sysctl.d/99-enable-user-namespaces.conf <<EOT
-kernel.unprivileged_userns_clone = 1
-EOT
-
-# We need to explicitly pull in the java certificates from backports. Otherwise
-# bazel won't install properly.
-cat > /etc/apt/preferences.d/java_certificates <<EOT
-Package: ca-certificates-java
-Pin: release a=jessie-backports
-Pin-Priority: 900
-EOT
-
-# Accept the LLVM GPG key so we can install their packages.
-wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | apt-key add -
-
-# Install all the packages that we need/want.
-apt-get update
-for pkg in "${PKGS[@]}"; do
- apt-get install -y -f --force-yes "$pkg"
-done
diff --git a/vm/setup_desktop.sh b/vm/setup_desktop.sh
deleted file mode 100755
index d713856..0000000
--- a/vm/setup_desktop.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -u
-
-export DEBIAN_FRONTEND=noninteractive
-
-readonly PKGS=(
- iceweasel
- lightdm
- mousepad
- xfce4
- xfce4-terminal
-)
-
-# Install all the packages that we need/want.
-for pkg in "${PKGS[@]}"; do
- apt-get install -y -f "$pkg"
-done
diff --git a/vm/setup_extra_storage.sh b/vm/setup_extra_storage.sh
deleted file mode 100755
index 5fcf4cb..0000000
--- a/vm/setup_extra_storage.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -u
-
-readonly EXTRA_USER=user
-readonly EXTRA_STORAGE=/home/"${EXTRA_USER}"
-
-if ! grep -q "$EXTRA_STORAGE" /etc/passwd; then
- PASSWORD="$(echo "$EXTRA_USER" | mkpasswd -s)"
- useradd \
- --home="$EXTRA_STORAGE" -M \
- --password="$PASSWORD" \
- --shell=/bin/bash \
- "$EXTRA_USER"
- chown "$EXTRA_USER:$EXTRA_USER" "$EXTRA_STORAGE"
-fi
-
-usermod -a -G sudo "$EXTRA_USER"
diff --git a/vm/setup_misc_packages.sh b/vm/setup_misc_packages.sh
deleted file mode 100755
index 691b2be..0000000
--- a/vm/setup_misc_packages.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -u
-
-export DEBIAN_FRONTEND=noninteractive
-
-readonly PKGS=(
- colordiff
- tmux
- vim
-)
-
-# Install all the packages that we want.
-for pkg in "${PKGS[@]}"; do
- apt-get install -y -f "$pkg"
-done
diff --git a/vm/setup_scouting.sh b/vm/setup_scouting.sh
deleted file mode 100755
index 3360ff5..0000000
--- a/vm/setup_scouting.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -u
-
-export DEBIAN_FRONTEND=noninteractive
-
-readonly PKGS=(
- python3
- python3-flask
-)
-
-# Install all the packages that we need/want.
-apt-get update
-for pkg in "${PKGS[@]}"; do
- apt-get install -y -f --force-yes "$pkg"
-done
diff --git a/vm/setup_vbox_guest_additions.sh b/vm/setup_vbox_guest_additions.sh
deleted file mode 100755
index c9f4b09..0000000
--- a/vm/setup_vbox_guest_additions.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -u
-
-export DEBIAN_FRONTEND=noninteractive
-
-# Install the kernel sources before the guest additions to guarantee that
-# we can compile the kernel module.
-apt-get install -q -y linux-headers-amd64
-
-# Now we can install the guest additions.
-apt-get install -q -y \
- virtualbox-guest-dkms \
- virtualbox-guest-x11
diff --git a/y2024/constants/971.json b/y2024/constants/971.json
index 5145613..a7b089c 100644
--- a/y2024/constants/971.json
+++ b/y2024/constants/971.json
@@ -40,20 +40,20 @@
"altitude_constants": {
{% set _ = altitude_zero.update(
{
- "measured_absolute_position" : 0.183060873152545
+ "measured_absolute_position" : 0.41553229640555134
}
) %}
"zeroing_constants": {{ altitude_zero | tojson(indent=2)}},
- "potentiometer_offset": {{ -0.18953940426369 }}
+ "potentiometer_offset": {{ -0.18953940426369 - 1.4610389049095576 }}
},
"turret_constants": {
{% set _ = turret_zero.update(
{
- "measured_absolute_position" : 1.01975376211353
+ "measured_absolute_position" : 0.2693990653670759
}
) %}
"zeroing_constants": {{ turret_zero | tojson(indent=2)}},
- "potentiometer_offset": {{ -6.47164779835404 - 0.0711209027239817 + 1.0576004531907 - 0.343 - 0.05 + 0.72907099601435 - 0.0499928122527711 + 0.037944928379006 }}
+ "potentiometer_offset": {{ -6.47164779835404 - 0.0711209027239817 + 1.0576004531907 - 0.343 - 0.05 + 0.72907099601435 - 0.0499928122527711 + 0.037944928379006 + 0.21956382487163306 }}
},
"extend_constants": {
{% set _ = extend_zero.update(
diff --git a/y2024/y2024_orin1.json b/y2024/y2024_orin1.json
index 280d8fe..df4fbdd 100644
--- a/y2024/y2024_orin1.json
+++ b/y2024/y2024_orin1.json
@@ -12,7 +12,7 @@
"source_node": "orin1",
"frequency": 50,
"num_senders": 30,
- "max_size": 8192
+ "max_size": 8552
},
{
"name": "/orin1/aos",
@@ -27,7 +27,7 @@
"source_node": "orin1",
"frequency": 50,
"num_senders": 20,
- "max_size": 4096
+ "max_size": 6144
},
{
"name": "/orin1/aos",
diff --git a/y2024/y2024_roborio.json b/y2024/y2024_roborio.json
index e0e1131..bb7739e 100644
--- a/y2024/y2024_roborio.json
+++ b/y2024/y2024_roborio.json
@@ -52,7 +52,7 @@
"source_node": "roborio",
"frequency": 50,
"num_senders": 20,
- "max_size": 2000
+ "max_size": 4504
},
{
"name": "/roborio/aos",