diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3887c2ad8..352725477 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -25,7 +25,6 @@ "UBCSailbot/boat_simulator": {"permissions": "write-all"}, "UBCSailbot/controller": {"permissions": "write-all"}, "UBCSailbot/custom_interfaces": {"permissions": "write-all"}, - "UBCSailbot/docs": {"permissions": "write-all"}, "UBCSailbot/local_pathfinding": {"permissions": "write-all"}, "UBCSailbot/network_systems": {"permissions": "write-all"}, "UBCSailbot/notebooks": {"permissions": "write-all"}, diff --git a/.devcontainer/docker-compose.docs.yml b/.devcontainer/docker-compose.docs.yml index 4bd4d734d..b1e4be2df 100644 --- a/.devcontainer/docker-compose.docs.yml +++ b/.devcontainer/docker-compose.docs.yml @@ -8,7 +8,7 @@ services: context: .. dockerfile: .devcontainer/docs/docs.Dockerfile volumes: - - ../src/docs:/docs:cached + - ..:/docs:cached # Runs on the same network as the workspace container, allows "forwardPorts" in devcontainer.json function. network_mode: service:sailbot-workspace diff --git a/.devcontainer/docs/docs.Dockerfile b/.devcontainer/docs/docs.Dockerfile index 2622f81ac..324c87478 100644 --- a/.devcontainer/docs/docs.Dockerfile +++ b/.devcontainer/docs/docs.Dockerfile @@ -1,7 +1,7 @@ FROM squidfunk/mkdocs-material # get docs requirements file -COPY ./src/docs/docs/requirements.txt /requirements.txt +COPY ./docs/requirements.txt /requirements.txt # install requirements RUN pip install -Ur /requirements.txt diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5761d6a1d..cb5366a99 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -6,3 +6,6 @@ # these owners will be requested for # review when someone opens a pull request. * @patrick-5546 + +# docs +/docs/ @DFriend01 diff --git a/.github/actions/ament-lint/run.sh b/.github/actions/ament-lint/run.sh index 4bc8efe99..aae11d7dc 100755 --- a/.github/actions/ament-lint/run.sh +++ b/.github/actions/ament-lint/run.sh @@ -54,7 +54,7 @@ if [[ $LOCAL_RUN != "true" ]]; then fi # Exclude repos and files we don't want to lint -VALID_SRC_DIRS=$(ls src | grep -v -e virtual_iridium -e docs -e raye-local-pathfinding -e website -e notebooks -e polaris.repos) +VALID_SRC_DIRS=$(ls src | grep -v -e virtual_iridium -e raye-local-pathfinding -e website -e notebooks -e polaris.repos) lint_errors=0 # Loop over each directory and lint it diff --git a/.github/actions/docs-lint/action.yml b/.github/actions/docs-lint/action.yml new file mode 100644 index 000000000..eb3e71ff9 --- /dev/null +++ b/.github/actions/docs-lint/action.yml @@ -0,0 +1,7 @@ +name: 'Lint New Tab Links' +description: 'Check links to external sites redirect to a new tab' +runs: + using: "composite" + steps: + - run: python3 $GITHUB_ACTION_PATH/lint_links.py -r $ROOT -c $CONFIG_FILE + shell: bash diff --git a/.github/actions/docs-lint/lint_links.py b/.github/actions/docs-lint/lint_links.py new file mode 100644 index 000000000..3a85f1169 --- /dev/null +++ b/.github/actions/docs-lint/lint_links.py @@ -0,0 +1,236 @@ +## IMPORTS +import os +import sys +import re +import json +import argparse + +## CONSTANTS +REGEX_PATTERN = r"(? Embed > iFrame, and deselecting Layers, Tags, and Edit --> + + diff --git a/docs/current/sailbot_workspace/deployment.md b/docs/current/sailbot_workspace/deployment.md new file mode 100644 index 000000000..c03613ff2 --- /dev/null +++ b/docs/current/sailbot_workspace/deployment.md @@ -0,0 +1,7 @@ +!!! quote "Source code" + + The [source code for deployment](https://github.com/UBCSailbot/sailbot_workspace/tree/main/.devcontainer/deployment){target=_blank} + can be found in the [sailbot_workspace](https://github.com/UBCSailbot/sailbot_workspace){target=_blank} + GitHub repository. Its README has been copied below. + +--8<-- "https://raw.githubusercontent.com/UBCSailbot/sailbot_workspace/main/.devcontainer/deployment/README.md" diff --git a/docs/current/sailbot_workspace/docker_images.md b/docs/current/sailbot_workspace/docker_images.md new file mode 100644 index 000000000..de293d928 --- /dev/null +++ b/docs/current/sailbot_workspace/docker_images.md @@ -0,0 +1,35 @@ +# Docker Images + +A table detailing the Docker images used to create the Dev Container can be found below. +Click on an image to learn more about its features and how to update it. + +| Image | Parent Image | Source Code | Why it is Rebuilt | Where it is Built | +| --------------------------------------------- | --------------------------------------------------- | ----------------------------------------------------------- | -------------------------------- | -------------------------------------- | +| [`pre-base`][pre-base]{target=_blank} | [Ubuntu 22.04][Ubuntu Image]{target=_blank} | [`base-dev.Dockerfile`][base-dev.Dockerfile]{target=_blank} | To install ROS or OMPL | Personal computer | +| [`base`][base]{target=_blank} | [`pre-base`][pre-base]{target=_blank} | [`base-dev.Dockerfile`][base-dev.Dockerfile]{target=_blank} | To install core dependencies | Workflow dispatch | +| [`local-base`][local-base]{target=_blank} | [`base`][base]{target=_blank} | [`base-dev.Dockerfile`][base-dev.Dockerfile]{target=_blank} | To install core dev dependencies | Workflow dispatch | +| [`dev`][dev]{target=_blank} | [`local-base`][local-base]{target=_blank} | [`base-dev.Dockerfile`][base-dev.Dockerfile]{target=_blank} | To install dev dependencies | Workflow dispatch | +| [Dev Container][Dev Container]{target=_blank} | [`dev`][dev]{target=_blank} | [`Dockerfile`][Dockerfile]{target=_blank} | To configure the Dev Container | VS Code | +| [`docs`][docs]{target=_blank} | [`mkdocs-material`][mkdocs-material]{target=_blank} | [`docs.Dockerfile`][docs.Dockerfile]{target=_blank} | To install and run docs site | VS Code ([optional][o]{target=_blank}) | +| [`website`][website]{target=_blank} | [`javascript-node`][javascript-node]{target=_blank} | [`website.Dockerfile`][website.Dockerfile]{target=_blank} | To install and run website | VS Code ([optional][o]{target=_blank}) | + + +[Ubuntu image]: +[pre-base]: +[base]: +[local-base]: +[dev]: +[docs]: +[mkdocs-material]: +[website]: +[javascript-node]: +[Dev Container]: + + +[base-dev.Dockerfile]: +[docs.Dockerfile]: +[website.Dockerfile]: +[Dockerfile]: + + +[o]: ./how_to.md#run-optional-programs diff --git a/docs/current/sailbot_workspace/how_to.md b/docs/current/sailbot_workspace/how_to.md new file mode 100644 index 000000000..e8956e018 --- /dev/null +++ b/docs/current/sailbot_workspace/how_to.md @@ -0,0 +1,335 @@ +# How-To's + +## Run VS Code commands, tasks, and launch configurations + +!!! tip "MacOS keyboard shortcuts" + + For keyboard shortcuts on MacOS, substitute ++ctrl++ with ++cmd++. + +VS Code commands can be run in the Command Palette. +Open the Command Palette from the `View` menu or with ++ctrl+shift+p++. + +Tasks can be run using the `Tasks: Run Task` VS Code command. Build tasks can be run with ++ctrl+shift+b++. + +Launch configurations can be run from the [Run and Debug view](https://code.visualstudio.com/docs/editor/debugging#_run-and-debug-view){target=_blank}. + +You can also run VS Code commands, tasks, launch configurations, and much more by typing their prefixes +into an empty Command Palette. Open an empty Command Palette with ++ctrl+p++ or by clicking the box in the center +of the title bar. See the list below for some prefixes and their functions. +For prefixes that are words, you will have to append a space to them to bring up their functions. + +- Nothing: files +- `>`: VS Code commands +- `task`: tasks +- `debug`: launch configurations +- `?`: list all prefixes and their functions + +## Work with containerized applications + +!!! info "" + + New in [:octicons-tag-24: v1.1.0](https://github.com/UBCSailbot/sailbot_workspace/releases/tag/v1.1.0){target=_blank} + +We have containerized the following applications for a variety of reasons: + +- [MongoDB database](https://www.mongodb.com/){target=_blank} +- [Docs site](https://github.com/UBCSailbot/docs){target=_blank} +- [Website](https://github.com/UBCSailbot/website){target=_blank} + +### Running containerized applications + +In the first section of `dockerComposeFile` of `.devcontainer/devcontainer.json`, there is a list of files: +each file contains the configuration for one or more applications. + +The ones that are commented out are not run. To run them: + +1. Uncomment the Docker Compose file(s) that the application(s) you desire to run are defined in + - Programs that are defined in the uncommented Docker Compose files will be started and stopped with Sailbot Workspace +2. Run the `Dev Containers: Rebuild Container` VS Code command to restart Sailbot Workspace + +To stop running them: + +1. Comment out the corresponding Docker Compose file +2. Stop the application's container: see [Managing containerized applications](#managing-containerized-applications) + +### Viewing MongoDB data + +Connect the [MongoDB VS Code extension](https://www.mongodb.com/products/vs-code){target=_blank} to the running database: +[Create a Connection for Deployment](https://www.mongodb.com/docs/mongodb-vscode/connect/#create-a-connection-to-a-deployment){target=_blank} + +- Use the default methods: "Paste Connection String" and "Open from Overview Page" +- Our database's connection string is `mongodb://localhost:27017` +- See the [MongoDB VS Code extension docs](https://www.mongodb.com/docs/mongodb-vscode/){target=_blank} for how + to use it to navigate or explore the database + +### Opening Docs or Website + +Docs runs on port 8000 and Website 3005. You can see them in your browser at `localhost:`. To open them using VS Code: + +1. Run the `Ports: Focus on Ports View` VS Code command +2. Open the site by hovering over its local address and clicking either "Open in Browser" or "Preview in Editor" + - The local address of Docs is the line with a port of 8000 + - The local address of Website is the line with a port of 3005 + +!!! tip "Turn off auto saving" + + Changes made to their files are loaded when they are saved, so **if Auto Save is on, turn it off** + so that the Docs/Website servers aren't continuously reloading. Auto Save is on by default in GitHub Codespaces + +### Managing containerized applications + +Each application runs in a Docker container. Containers can be managed using Docker Desktop or CLI commands: + +- View Sailbot Workspace containers + + === ":material-docker: Docker Desktop" + + 1. Select "Containers" in the top right + 2. Expand "sailbot_workspace_devcontainer" + - The "Status" column shows whether a container is running or not + + === ":octicons-terminal-24: CLI Commands" + + ``` + docker ps -a + ``` + + - Sailbot Workspace containers should be named something like `sailbot_workspace_devcontainer--` + - The `STATUS` column shows whether a container is running or not + +- View a container's logs, the output of the container (including errors that caused it to stop) + + === ":material-docker: Docker Desktop" + + 1. Click on a container + 2. Navigate to the "Logs" view if not already on it + + === ":octicons-terminal-24: CLI Commands" + + ``` + docker logs + ``` + +- Start a container that is not running + + === ":material-docker: Docker Desktop" + + 1. Click start :material-play: + + === ":octicons-terminal-24: CLI Commands" + + ``` + docker start + ``` + +- Stop a container that is running + + === ":material-docker: Docker Desktop" + + 1. Click stop :material-stop: + + === ":octicons-terminal-24: CLI Commands" + + ``` + docker stop + ``` + +## Manage software packages + +!!! warning "Why can't I just install the dependencies myself in the command line interface with `pip` or `apt`?" + + Although this will temporarily work, installing apt and/or Python dependencies directly in sailbot workspace using + the commandline interface will not persist between container instances. The dependencies will need to be manually + installed every single time you create a new instance of sailbot workspace, which is not feasible when we start to + use many dependencies at once. + + Of course, one could also install dependencies inside the sailbot workspace Docker images to allow such dependencies + to persist across container instances. However, putting dependencies inside `package.xml` distinguishes between + what dependencies are needed for ROS packages and what dependencies are needed for infrastructure purposes. + +### Add apt or python dependencies to ROS packages + +If running your ROS packages requires external dependencies from an apt repository or python package, **one** of the following +tags should be added to the `package.xml` file in the root directory of the ROS package: + +```xml +ROSDEP_KEY +ROSDEP_KEY +ROSDEP_KEY +ROSDEP_KEY +ROSDEP_KEY +``` + +- Learn what each tag is used for [here](https://docs.ros.org/en/humble/Tutorials/Intermediate/Rosdep.html#id4){target=_blank}. + +- Replace `ROSDEP_KEY` with the rosdep key for the dependency, which can be found online. + - Use the key associated with **ubuntu** since sailbot workspace uses Ubuntu, or **debian** which Ubuntu is based on + - Do not include the square brackets in `package.xml` + + === ":material-ubuntu: Apt Dependencies" + - Rosdep keys for apt repositories can be found [here](https://github.com/ros/rosdistro/blob/master/rosdep/base.yaml){target=_blank} + + === ":material-language-python: Python Dependencies" + - Rosdep keys for python packages can be found [here](https://github.com/ros/rosdistro/blob/master/rosdep/python.yaml){target=_blank} + - Since we use Python 3, look for the packages that start with `python3-` (`python-` is usually for Python 2) + +- If there isn't rosdep key for the dependency, you can add your own to `custom-rosdep.yaml` + in the root directory of the ROS package + +After completing these steps, [run the `setup` task](#run-vs-code-commands-tasks-and-launch-configurations) and the +desired dependencies should be installed. ROS uses a dependency management utility, rosdep, to handle the installation +of dependencies. In addition to runtime dependencies, rosdep also handles dependencies for build time, dependencies for +testing, sharing dependencies between ROS packages, and more. +See the [ROS documentation on rosdep](https://docs.ros.org/en/humble/Tutorials/Intermediate/Rosdep.html){target=_blank} +to learn more. + +### Add dependencies to a Docker image + +There are a couple cases where you would want to add dependencies to a Docker image instead of ROS package: + +1. The dependency is not used to build/run/test a ROS package +2. There is no apt or pip package for your dependency so you have to build from source + +To verify your changes, you can add them to `.devcontainer/Dockerfile` then +run the `Dev Containers: Rebuild Container` VS Code command. Once verified, migrate the changes to one of the upstream +[images](./docker_images.md){target=_blank}: `base`, `local-base`, `dev`, or `pre-base`. + +## Enable GitHub Copilot in Sailbot Workspace + +[^1]: [GitHub Copilot Quickstart Guide](https://docs.github.com/en/copilot/quickstart){target=_blank} + +GitHub Copilot is an AI paired programming tool that can help you accelerate your development by providing suggestions +for whole lines or entire functions inside your editor.[^1] To enable GitHub Copilot: + +1. [Apply to GitHub Global Campus as a student](https://docs.github.com/en/education/explore-the-benefits-of-teaching-and-learning-with-github-education/github-global-campus-for-students/apply-to-github-global-campus-as-a-student){target=_blank} +to use GitHub Copilot and get other student benefits for free. It may take a few days for your student status to be +verified. In the meantime, you can still continue with the next steps. However, you will need to use the GitHub Copilot +free trial until your account is verified. + +2. [Sign up for GitHub Copilot for your personal account](https://docs.github.com/en/copilot/quickstart#signing-up-for-github-copilot-for-your-personal-account){target=_blank}. +If it offers a free trial, then take it. You should see a page telling you that you can use GitHub Copilot for free +(if you have a verified student account). + +3. Uncomment the `github.copilot` extension in `.devcontainer/devcontainer.json` and run the + `Dev Containers: Rebuild Container` VS Code command + +4. Sign into your GitHub account in VS Code. The GitHub Copilot extension should automatically prompt you to sign into +your account if you are not already. + + ??? warning "VS Code is not prompting me to sign into my account" + You may already be signed in into your GitHub account. You can check by clicking on the :octicons-person-16: + **Accounts** icon in the bottom-left corner in VS Code and verify that you see your GitHub account. + + If you do not see your account, you can get the sign in prompt by trying: + + - Reloading the VS Code window: ++ctrl+shift+p++ and select `Developer: Reload Window` + - Rebuilding the devcontainer: ++ctrl+shift+p++ and select `Dev Containers: Rebuild Container` + - If using a Mac, use ++cmd++ instead of ++ctrl++ + +5. If all the previous steps were done correctly, you should see the :octicons-copilot-48: **GitHub Copilot** icon in +the bottom-right corner of VS Code without any error messages. For more information on how to use Copilot and a tutorial, +refer to: + + - [The GitHub Copilot Getting Started Guide](https://docs.github.com/en/copilot/getting-started-with-github-copilot){target=_blank} + - [Configuring GitHub Copilot in your Environment](https://docs.github.com/en/copilot/configuring-github-copilot/configuring-github-copilot-in-your-environment){target=_blank} + +## Use your dotfiles + +Dotfiles are configuration files for various programs.[^2] + +??? info "More about dotfiles" + + - They are called dotfiles because their filenames start with a dot (`.`) + - On Linux and MacOS, files and directories that begin with a dot are hidden by default + - To list dotfiles using the `ls` command, specify the `-a` argument: `ls -a` + +Dotfiles that are commonly modified include: + +- Bash: `~/.bashrc` +- Git: `~/.gitconfig` +- Vim: `~/.vimrc` + +To use your dotfiles: + +1. Ensure that the `base`, `local-base`, or `dev` [image](./docker_images.md){target=_blank} + installs the programs that the dotfiles correspond to +2. Copy the dotfiles to the `.devcontainer/config/` directory. + If a dotfile is located in a child directory, you will have to created it. + For example, if a dotfile's path is `~/.config/ex_dotfile`, you will need to copy it to `.devcontainer/config/.config/ex_dotfile` + + !!! warning "Special cases" + + - `~/.gitconfig`: there is no need copy your Git dotfile, as Dev Containers do this automatically + - `~/.bashrc`: don't copy your Bash dotfile, as it would override the one created in the `dev` image. + Instead, add your bash configuration `.aliases.bash` or `.functions.bash` in the config directory, as these are sourced + by the created Bash dotfile. + +3. Run the `Dev Containers: Rebuild Container` VS Code command + +[^2]: [Dotfiles – What is a Dotfile and How to Create it in Mac and Linux](https://www.freecodecamp.org/news/dotfiles-what-is-a-dot-file-and-how-to-create-it-in-mac-and-linux/){target=_blank} + +## Run Raye's software + +Raye was our previous project. Her software can be run in the `raye` branch: + +1. Switch to the `raye` branch: `git switch raye` +2. Rebuild the Dev Container: run the `Dev Containers: Rebuild Container` VS Code command +3. If you want to run [Raye's local pathfinding visualizer](https://github.com/UBCSailbot/raye-local-pathfinding?tab=readme-ov-file#visualizing-the-simulation){target=_blank}, + complete [step 2 of the setup instructions](./setup.md#2-setup-x11-forwarding){target=_blank} + +!!! warning "`raye` branch disclaimers" + + 1. Since `raye` (and Raye's codebase in general) is not in active development, it may not be 100% functional + or contain all the features in `main` + 2. `raye` is more memory intensive than `main` because the parent image of its Dev Container is much larger; + this may lead to worse performance + +### Build Raye's ROS packages + +To build Raye's ROS packages, run the following commands: + +```bash +roscd +catkin_make +``` + +### Run packages from different workspaces + +The `raye` branch has two ROS workspaces: one for Raye and one for the new project. +To run ROS packages, you will have to source the overlay of the workspace that it is in: + +=== "New Project" + + ``` + srcnew + ``` + +=== "Raye" + + ``` + srcraye + ``` + +Then you can run launch files or package-specific executables in that workspace with: + +=== "New Project" + + `ros2 launch ...` or `ros2 run ...`, respectively. + +=== "Raye" + + `roslaunch ...` or `rosrun ...`, respectively. + +### Raye's known issues + +!!! bug "Run commands for Raye packages are very slow" + + On non-Ubuntu-based Linux operating systems, Run commands for Raye packages may take a long time to start-up. + This is because the system has trouble resolving the local hostname. + + To resolve this bug, run the commands below in the Dev Container: + + ```bash + echo 'export ROS_HOSTNAME=localhost' >> ~/.bashrc + echo 'export ROS_MASTER_URI=http://localhost:11311' >> ~/.bashrc + ``` diff --git a/docs/current/sailbot_workspace/launch_files.md b/docs/current/sailbot_workspace/launch_files.md new file mode 100644 index 000000000..b2dbf5458 --- /dev/null +++ b/docs/current/sailbot_workspace/launch_files.md @@ -0,0 +1,185 @@ +# ROS Launch Files in Sailbot Workspace + +ROS 2 Launch files allow us to programatically start up and configure multiple ROS nodes.[^1] +Within Sailbot Workspace, ROS launch files are used to start up our ROS packages with ease. +Additionally, we take advantage of the hierarchical properties of launch files by defining a global +entry point that invokes the launch files of all ROS packages in the system. + +## Launch File Architecture + +There are two launch processes that we utilize: namely the Package Launch Process and the Global launch process. + +### The Package Launch Process + + + + + +The package launch process is intended to start up a specific ROS package by directly using the package launch file. +The process is as follows: + +1. The package launch file is invoked with the user passing arguments via the CLI and specifying a configuration file. +2. Global argument declarations and environment variables are loaded into the launch process. +3. Local arguments, specific to the package, are declared. +4. Both global and local arguments are parsed based on the argument declarations and are set for use upon start up. +5. The ROS nodes belonging to the package begin execution, utilizing the ROS parameters from the configuration file. + +??? warning "When launching individual packages, be aware of dependencies between ROS packages" + Some packages rely on the data produced by other packages in the system. This may cause only + partial functionality of the ROS node(s) that are running inside the launched package. Therefore, + it may be necessary to launch multiple packages manually to get the desired functionality. + +### The Global Launch Process + + + + + +The global launch process is intended to start up the entire system (both the development and production environments). +This process invokes the package launch files for each ROS package used in the system through a global launch file. +The process is as follows: + +1. The global launch file is invoked with the user passing arguments via the CLI and specifying a configuration file. +2. Environment variables common to all ROS packages are declared. In addition, the global arguments common across +all ROS packages are declared. +3. For each package launch file: + - The CLI arguments, global argument declarations, and environment variables are passed into the package launch + file. + - Local arguments, specific to the package, are declared. Both the global and local arguments are parsed based on the + argument declarations and are set for use upon start up. + - The ROS nodes belonging to the package begin execution, utilizing the ROS parameters from the configuration file. + +## Invoking Launch Files + +??? tip "Stopping the execution of a launch file" + Entering ++ctrl+c++ in the terminal where the launch file was invoked will stop all associated + ROS packages from running. + > Use ++command+c++ for Mac OS + +### Package Launch + +At the bare minimum, the following packages need to be built with the `Build` or `Build All` VS Code task before launching: + +- `custom_interfaces` +- The package you want to launch + +Packages only need to be rebuilt either when the workspace is first set up, or if any changes are made to the ROS +package. Once built, the package launch file can be invoked either in the CLI or using a VS Code command: + +=== ":octicons-command-palette-16: CLI" + Either the package and launch file name, or the path to the launch file can be used: + + - **Method 1:** `ros2 launch `. This method can only be used when a launch file + is part of a built ROS package. + - **Method 2:** `ros2 launch `. This method can be used regardless if a launch file + is in a ROS package or not. + + !!! example "Launch via CLI Examples" + Let's launch local pathfinding using both CLI methods: + + **Method 1** + ```sh + ros2 launch local_pathfinding main_launch.py + ``` + + **Method 2** + ```sh + ros2 launch $ROS_WORKSPACE/src/local_pathfinding/launch/main_launch.py + ``` + +=== ":material-microsoft-visual-studio-code: VS Code" + Run the following VS Code command from the **Run and Debug** tab: `ROS: Launch (workspace)` + + There will be a prompt to select which launch file to run. Select the desired launch file. + +### Global Launch + +Before running the system, be sure to run the `Build All` VS Code task to build all ROS packages. If the ROS launch +debug configuration is being used, then this step is not necessary as the `Build All` task is ran automatically before +launch. + +=== ":octicons-command-palette-16: CLI" + + Run the entire system with the following CLI command: + + ```sh + ros2 launch $ROS_WORKSPACE/src/global_launch/main_launch.py + ``` + +=== ":material-microsoft-visual-studio-code: VS Code" + Run the following VS Code command from the **Run and Debug** tab: `ROS: Launch (workspace)` + + There will be a prompt to select which launch file to run. Select the desired launch file. + +Remember to that you need to potentially reload the window if the nodes are not being detected +by VS Code. This usually happens when somebody build for the first time. Also, note that the global +launch file is not part of a ROS package, so the path to the global launch file always +must be provided. This is not always the case when a launch file is contained within a ROS package. + +### Using CLI Arguments + +Invoking the launch files as is will provide the system with the default CLI arguments. As an example, +the following command will launch local pathfinding while setting the log level to "debug": + +```sh +ros2 launch local_pathfinding main_launch.py log_level:=debug +``` + +It can also be ran with the VS Code command named **ROS: Launch**. + +Passing arguments takes the form of `:=`. To list the arguments that a launch file takes, +simply add the `-s` flag at the end of the launch command. + +??? example "Example using the `-s` flag in a launch command" + Let's add the `-s` flag after the global launch command to see the list of arguments: + + ```sh + ros2 launch $ROS_WORKSPACE/src/global_launch/main_launch.py -s + ``` + + The following output is observed in the terminal (as of September 2023): + + ``` + Arguments (pass arguments as ':='): + + 'config': + Path to ROS parameter config file. Controls ROS parameters passed into ROS nodes + (default: '/workspaces/sailbot_workspace/src/global_launch/config/globals.yaml') + + 'log_level': + Logging severity level. A logger will only process log messages with severity levels at or higher than the + specified severity. Valid choices are: ['debug', 'info', 'warn', 'error', 'fatal'] + (default: 'info') + + 'mode': + System mode. Decides whether the system is ran with development or production interfaces. Valid choices are: + ['production', 'development'] + (default: 'development') + ``` + +??? example "Example using multiple CLI arguments" + + ```sh + ros2 launch local_pathfinding main_launch.py log_level:=debug mode:=production + ``` + +??? example "Example passing local launch arguments to the global launch file" + As long as an argument is valid inside one of the package launch files, it may be passed to the global launch + file without generating any errors. This is valid even though the argument doesn't show up in the argument list for + the global launch file. For example, the following will run: + + ```sh + ros2 launch $ROS_WORKSPACE/src/global_launch/main_launch.py enable_sim_multithreading:=true + ``` + + Compare the argument list between the global launch file and the package launch file for the `boat_simulator` + package. It will be observed that the argument `enable_sim_multithreading` shows up in the `boat_simulator` + package argument list, but not for the global launch file. + +## ROS Parameter Config File + +All launch files in Sailbot Workspace accept a configuration file, which controls the ROS parameters that the ROS nodes +in the system have access to. This makes our system highly configurable and customizable during development and testing. +See more about [ROS parameters](https://docs.ros.org/en/humble/Concepts/Basic/About-Parameters.html){target=_blank}. + +[^1]: [ROS Launch File Documentation](https://docs.ros.org/en/humble/Tutorials/Intermediate/Launch/Launch-Main.html){target=_blank} diff --git a/docs/current/sailbot_workspace/overview.md b/docs/current/sailbot_workspace/overview.md new file mode 100644 index 000000000..84e9faef9 --- /dev/null +++ b/docs/current/sailbot_workspace/overview.md @@ -0,0 +1,7 @@ +!!! quote "Source code" + + The source code for Sailbot Workspace can be found in the + [sailbot_workspace](https://github.com/UBCSailbot/sailbot_workspace){target=_blank} GitHub repository. + Its README has been copied below. + +--8<-- "https://raw.githubusercontent.com/UBCSailbot/sailbot_workspace/main/README.md" diff --git a/docs/current/sailbot_workspace/parameters.md b/docs/current/sailbot_workspace/parameters.md new file mode 100644 index 000000000..3b9f5b46a --- /dev/null +++ b/docs/current/sailbot_workspace/parameters.md @@ -0,0 +1,7 @@ +!!! quote "Source code" + + The [README for ROS parameterization](https://github.com/UBCSailbot/sailbot_workspace/blob/main/src/global_launch/config/README.md){target=_blank} + can be found in the [sailbot_workspace](https://github.com/UBCSailbot/sailbot_workspace){target=_blank} + GitHub repository. Its README has been copied below. + +--8<-- "https://raw.githubusercontent.com/UBCSailbot/sailbot_workspace/main/src/global_launch/config/README.md" diff --git a/docs/current/sailbot_workspace/setup.md b/docs/current/sailbot_workspace/setup.md new file mode 100644 index 000000000..37d9e2a55 --- /dev/null +++ b/docs/current/sailbot_workspace/setup.md @@ -0,0 +1,305 @@ +# Setup Instructions + +Sailbot Workspace can be run on Windows, Linux, or macOS, but is the easiest to set up and performs the best on +[Ubuntu](https://ubuntu.com/){target=_blank} and [its derivatives](https://distrowatch.com/search.php?basedon=Ubuntu){target=_blank}. +The workspace may not perform well on Windows computers with 8GB of memory or less; +in this case, please check out our recommendations in the [Performance Issues](./workflow.md#performance-issues){target=_blank} +section. + +## 1. Setup prerequisites + +### Docker + +[Docker](https://www.docker.com/){target=_blank} is a platform that uses OS-level virtualization[^1] to develop, ship, and +run applications.[^2] We use it to separate our applications from our infrastructure[^2] so that we can update and +version control our infrastructure for every use case (software members, CI, deployment) in one place: this repository. + +[Docker Engine](https://docs.docker.com/engine/){target=_blank} is a software used to run Docker. +However, it can only be installed on Linux. +[Docker Desktop](https://docs.docker.com/desktop/){target=_blank} is a software used to run Docker in a VM,[^3] +allowing it to be installed on Windows and macOS in addition to Linux. + +[^1]: [Wikipedia Docker page](https://en.wikipedia.org/wiki/Docker_(software)){target=_blank} +[^2]: [Get Docker](https://docs.docker.com/get-docker/){target=_blank} +[^3]: [What is the difference between Docker Desktop for Linux and Docker Engine](https://docs.docker.com/desktop/faqs/linuxfaqs/#what-is-the-difference-between-docker-desktop-for-linux-and-docker-engine){target=_blank} + +=== ":material-microsoft-windows: Windows" + + 1. Set up prerequisites, WSL and Ubuntu: + + 1. In PowerShell, run `wsl --install Ubuntu`, then `exit`, `wsl --update`, and `wsl --set-default Ubuntu` + + ??? warning "Ubuntu is already installed?" + + If Ubuntu is already installed, check that it is the right WSL version: + + 1. Check the WSL versions of Linux distributions with `wsl -l -v` + 2. If Ubuntu's `VERSION` is 1, upgrade it to WSL 2 with `wsl --set-version Ubuntu 2` + + 2. Open the Ubuntu app to set up or verify its configuration: + 1. If you are opening Ubuntu for the first time, a setup process will run; + follow the prompts to finish setting it up + 2. Run `whoami` to verify that it returns your Ubuntu username + + ??? bug "`whoami` returns `root`" + + If `whoami` returns `root`: + + 1. [Create a non-root user with sudo privileges](https://www.digitalocean.com/community/tutorials/how-to-add-and-delete-users-on-ubuntu-20-04){target=_blank} + 2. Change the default Ubuntu user to this newly-created user: run `ubuntu config --default-user ` + in PowerShell, replacing `` with the name of the newly-created user + 3. Run `whoami` after closing and reopening Ubuntu, verifying that it returns your Ubuntu username + + 2. [Install Docker Desktop](https://docs.docker.com/desktop/install/windows-install/){target=_blank} + with the WSL 2 backend + + ??? bug "Docker Desktop - Unexpected WSL Error" + + ![image](../../assets/images/sailbot_workspace/workflow/sailbot_bug.png) + + If the above error shows when trying to start Docker Desktop on your laptop: + + 1. For windows users navigate to `C:\Users\user_name` and delete the .Docker folder + 2. Restart Docker Desktop + + ??? bug "Docker Desktop can't start up and WSL hangs when restarting" + + If Ubuntu can't start up and WSL hangs when restarting: + + 1. Open command prompt as administrator and run the command `netsh winsock reset` + 2. Uninstall and reinstall Docker Desktop + 3. Restart your computer + + More potential solutions can be found here: + [Link](https://github.com/docker/for-win/issues/13273){target=_blank} + +=== ":material-apple: macOS" + + [Install Docker Desktop](https://docs.docker.com/desktop/install/mac-install/){target=_blank} for your computer's CPU. + +=== ":material-linux: Linux" + + 1. [Install Docker Engine](https://docs.docker.com/engine/install/){target=_blank} + - As of February 2023, Sailbot Workspace (more specifically its use of VS Code Dev Containers) isn't compatible + with Docker Desktop for Linux; if you have Docker Desktop installed, uninstall it and install Docker Engine instead. + 2. [Manage Docker as a non-root user](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user){target=_blank} + 3. [Configure Docker to start on boot](https://docs.docker.com/engine/install/linux-postinstall/#configure-docker-to-start-on-boot){target=_blank} + +### VS Code + +[Visual Studio Code](https://code.visualstudio.com/){target=_blank} is a powerful and customizable code editor for +Windows, Linux, and macOS. We strongly recommend that you use this editor to develop our software so that you can +use all the features of Sailbot Workspace. + +1. [Install VS Code](https://code.visualstudio.com/docs/setup/setup-overview){target=_blank} +2. Install the [Remote Development Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack){target=_blank} + +### Git + +Git is a free and open source distributed version control system designed to handle everything from +small to very large projects with speed and efficiency.[^4] + +1. Check if Git is installed with `git --version` (on Windows, run command in PowerShell) + - If not installed, download and install it from [Git Downloads](https://git-scm.com/download){target=_blank} +2. Configure your name and email: [Git config file setup](https://learn.microsoft.com/en-us/windows/wsl/tutorials/wsl-git#git-config-file-setup){target=_blank} + (on Windows, run commands in Ubuntu) +3. Login to GitHub + + === ":material-microsoft-windows: Windows" + + 1. Run the `git config` command for your Git version in [Git Credential Manager setup](https://learn.microsoft.com/en-us/windows/wsl/tutorials/wsl-git#git-credential-manager-setup){target=_blank} (run command in Ubuntu) + + !!! warning "Which Git to check" + + Git is installed seperately in Windows and Ubuntu, so they could be at different versions. + We want to check the version of Git on Windows, not Ubuntu: + run `git --version` in PowerShell and not Ubuntu. + However, the `git config` command itself is run in Ubuntu. + + === ":material-apple: macOS / :material-linux: Linux" + + 1. Install the GitHub CLI: [Installation](https://github.com/cli/cli#installation){target=_blank} + 2. Run `gh auth login` and select the first option for all choices + +4. Verify that you have successfully logged in to GitHub by cloning a private GitHub repository (run command in Ubuntu) + 1. If you are a part of the [UBCSailbot Software GitHub team](https://github.com/orgs/UBCSailbot/teams/software-team){target=_blank}, + you shouldn't see any errors running `git clone https://github.com/UBCSailbot/raye-ais.git` + 2. You can delete this repository with `rm -rf raye-ais` + +[^4]: [Git SCM](https://git-scm.com){target=_blank} + +## 2. Setup X11 forwarding + +X11 forwarding is a mechanism that enables Sailbot Workspace to run GUI applications. + +!!! warning "" + + You can skip this step since we currently aren't running any GUI applications + +??? info "Setup instructions for X11 forwarding" + + 1. Ensure that the versions of VS Code and its Dev Containers extension support X11 forwarding: + 1. VS Code version >= 1.75 + 2. Dev Containers version >= 0.275.1 + 2. Verify that `echo $DISPLAY` returns something like `:0` + + ??? warning "`echo $DISPLAY` doesn't return anything" + + If `echo $DISPLAY` doesn't return anything, set it to `:0` on shell initialization: + + 1. Find out what shell you are using with `echo $SHELL` + 1. Most Linux distributions use Bash by default, whose rc file path is `~/.bashrc` + 2. macOS uses Zsh by default, whose rc file path is: `~/.zshrc` + 2. Run `echo 'export DISPLAY=:0' >> `, replacing `` + with the path to your shell's rc file + 3. Run `echo $DISPLAY` after closing and reopening your terminal, verifying it returns something like `:0` + + 3. Install a X11 server + + === ":material-microsoft-windows: Windows" + + WSL includes a X11 server. + + === ":material-apple: macOS" + + 1. Set up XQuartz following [this guide](https://gist.github.com/sorny/969fe55d85c9b0035b0109a31cbcb088){target=_blank} + 2. Copy the default xinitrc to your home directory: `cp /opt/X11/etc/X11/xinit/xinitrc ~/.xinitrc` + 3. Add `xhost +localhost` to `~/.xinitrc` after its first line + + === ":material-linux: Linux" + + === ":material-linux: General" + + As of February 2023, almost all Linux distributions include a X11 server, Xorg. + This may change in the future as Wayland matures. + + === ":material-arch: Arch Linux" + + 1. Install xhost: `sudo pacman -S xorg-xhost` + 2. Copy the default xinitrc to your home directory: `cp /etc/X11/xinit/xinitrc ~/.xinitrc` + 3. Add `xhost +local:docker` to `~/.xinitrc` after its first line + + 4. Verify that X11 forwarding works: + 1. Install `x11-apps` + + === ":material-microsoft-windows: Windows" + + In Ubuntu, `sudo apt install x11-apps`. + + === ":material-apple: macOS" + + XQuartz includes `x11-apps`. Ensure that XQuartz is running. + + === ":material-linux: Linux" + + Install `x11-apps` using your desired package manager. + + 2. Verify that running `xcalc` opens a calculator and that you can use it + +## 3. Clone Sailbot Workspace + +!!! tip "Where to clone on Windows" + + **Run the command below in the Ubuntu app** to clone it in the Ubuntu file system, otherwise sailbot workspace will not work. + Windows has a native file system as well as file systems for each WSL distribution. + +```sh +git clone https://github.com/UBCSailbot/sailbot_workspace.git +``` + +## 4. Open Sailbot Workspace in VS Code + +1. Install `code` command in `PATH` + + === ":material-microsoft-windows: Windows" + + The `code` command is installed by default. + + === ":material-apple: macOS" + + See [launching from the command line](https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line){target=_blank}. + + === ":material-linux: Linux" + + The `code` command is installed by default. + +2. Open the `sailbot_workspace/` directory in VS Code: run `code ` + - For example, if you just cloned the repository, the command would be `code sailbot_workspace` + +## 5. Open the workspace file + +Click the popup to `Open Workspace`. If there isn't a popup: + +1. Open the file `sailbot.code-workspace` in VS Code +2. Click `Open Workspace` + +## 6. Open Sailbot Workspace in a Dev Container + +1. Ensure that Docker is running +2. Click the popup to `Reopen in Container`. If there isn't a popup, + run the `Dev Containers: Reopen in Container` VS Code command + +## 7. Run the `setup` task + +The `setup` task clones the repositories defined in `src/polaris.repos` and updates dependencies of the ROS packages. +If you don't know how to run a VS Code task, see [How to run VS Code commands, tasks, and launch configurations](./how_to.md#run-vs-code-commands-tasks-and-launch-configurations). + +??? bug "Can't see the `setup` task" + + If you can't see the `setup` task, run the `Developer: Reload Window` VS Code command. + This may occur when the workspace file is opened for the first time. + +## 8. Run the `Build All` task + +The `Build All` task builds all the ROS packages. + +## 9. Reload the VS Code terminals and window + +Delete all open terminals and run the `Developer: Reload Window` VS Code command +to detect the files that were generated from building. + +## 10. Start the system + +Run the entire system to verify everything is working using the following command in the VS Code terminal: + +```sh +ros2 launch $ROS_WORKSPACE/src/global_launch/main_launch.py +``` + +Use ++ctrl+c++ in the terminal to stop the system. + +## Setup Sailbot Workspace in a GitHub Codespace + +A codespace is a development environment that's hosted in the cloud.[^5] +Since Sailbot Workspace is resource intensive, it has high hardware requirements and power consumption, +which aren't ideal for development on laptops. GitHub Codespaces provide a seamless experience to work on repositories +off-device, especially if they specify a Dev Container like Sailbot Workspace. Codespaces can run in VS Code +or even in a browser for times when you aren't on your programming computer. + +1. Create a GitHub Codespace following the steps in the relevant GitHub Docs page: +[create a codespace for a repository](https://docs.github.com/en/codespaces/developing-in-codespaces/creating-a-codespace-for-a-repository#creating-a-codespace-for-a-repository){target=_blank}. +A couple things to note: + - For the best Sailbot Workspace development experience, select the high-spec machine available + - There are usage limits if you don't want to pay: + [monthly included storage and core hours for personal accounts](https://docs.github.com/en/billing/managing-billing-for-github-codespaces/about-billing-for-github-codespaces#monthly-included-storage-and-core-hours-for-personal-accounts){target=_blank} + - Upgrade to a Pro account for increased usage limits (this is free for students): + [apply to GitHub Global Campus as a student](https://docs.github.com/en/education/explore-the-benefits-of-teaching-and-learning-with-github-education/github-global-campus-for-students/apply-to-github-global-campus-as-a-student){target=_blank} + - Stop your codespace as soon as you are done using it: + [stopping a codespace](https://docs.github.com/en/codespaces/developing-in-codespaces/stopping-and-starting-a-codespace#stopping-a-codespace){target=_blank} + - Delete codespaces that you do not plan to use anymore: + [deleting a codespace](https://docs.github.com/en/codespaces/developing-in-codespaces/deleting-a-codespace#deleting-a-codespace){target=_blank} +2. Follow the local setup instructions starting from [5. Open the workspace file](#5-open-the-workspace-file) + +Once you have a codespace set up: + +- Open it by following the steps in the relevant GitHub Docs page: +[reopening a codespace](https://docs.github.com/en/codespaces/developing-in-codespaces/opening-an-existing-codespace#reopening-a-codespace){target=_blank} +- Close it by running the `Codespaces: Stop Current Codespace` VS Code command + +!!! warning "Known limitations of running Sailbot Workspace in a GitHub Codespace" + + - Does not support X11 forwarding to run GUI applications + - High-spec machines not available: as of March 2023, the highest-spec machine that is publically available + has a 4-core CPU and 8GB of RAM + +[^5]: [GitHub Codespaces overview](https://docs.github.com/en/codespaces/overview){target=_blank} diff --git a/docs/current/sailbot_workspace/workflow.md b/docs/current/sailbot_workspace/workflow.md new file mode 100644 index 000000000..073893715 --- /dev/null +++ b/docs/current/sailbot_workspace/workflow.md @@ -0,0 +1,224 @@ +# Development Workflow + +## 1. Open Sailbot Workspace + +Once you have [set up Sailbot Workspace](setup.md), you can open it by opening a new VS Code window and selecting: + +``` +File > Open Recent > /workspaces/sailbot_workspace/.devcontainer/config/sailbot_workspace (Workspace) [Dev Container: Sailbot Workspace] +``` + +??? tip "Another way to open Sailbot Workspace on Windows" + + 1. Pin VS Code to the taskbar + 2. Right-click VS Code in the taskbar and pin `sailbot_workspace (Workspace) [Dev Container]` + + Then you can open Sailbot Workspace by selecting it from the "Pinned" section of the VS Code taskbar icon's + right-click menu. + +## 2. Update Sailbot Workspace + +Sailbot Workspace is still in active development, check out its [recent releases](https://github.com/UBCSailbot/sailbot_workspace/releases){target=_blank} +and [commit history](https://github.com/UBCSailbot/sailbot_workspace/commits/main){target=_blank}. +If there are new features or bug fixes that you want to try, you will need to update your local version of Sailbot Workspace: + +1. Switch Sailbot Workspace to the main branch if you aren't in it already + + ??? tip "If you running Git commands in the CLI, make sure that you are in the correct repository" + + Sailbot Workspace contains other repositories in the `src/` directory, so if you are in one of its subdirectories + you may be in the wrong repository. + + To check which repository you are in, run `git remote -v`; if its output contains `sailbot_workspace`, + you are good to go. + If not, you can navigate the root directory of the Sailbot Workspace repository with `cd $ROS_WORKSPACE`, + or open a new terminal in its root directory with ++ctrl+shift+grave++ then ++enter++. + + - If you are unable to switch branches because you have uncommitted changes, stash them + +2. Pull the latest changes + - If you stashed your uncommitted changes, pop them +3. If prompted, rebuild the Dev Container + + ??? question "When does the Dev Container need to be rebuilt?" + + To apply the modifications to its configuration files in `.devcontainer/` that occurred since it was last built. + + VS Code will prompt you to rebuild when `devcontainer.json`, `Dockerfile`, or `docker-compose*.yml`. + These file may be modified if you: + + - Pull the lastest changes of a branch + - Switch branches + - Update a file in `.devcontainer/` yourself + + However, there may be changes to the Dev Container that VS Code can't detect. + To rebuild it yourself, run the `Dev Containers: Rebuild Container` VS Code command. + +4. If you aren't working in any other branches, + run the `setup` task to switch the branches of all sub-repositories to their default specified in `src/polaris.repos` + and pull their latest changes +5. If you want to run our docs, website, or other optional programs, see [How to run optional programs](./how_to.md#run-optional-programs){target=_blank} + +## 3. Make your changes + +We make changes to our software following our [GitHub development workflow](https://ubcsailbot.github.io/docs/reference/github/workflow/overview/){target=_blank}. +Of particular relevance is the [Developing on Branches page](https://ubcsailbot.github.io/docs/reference/github/workflow/branches/){target=_blank}. + +!!! tip "Git interfaces" + + One way to interface with Git is through CLI commands. However, you may find it faster to use + [VS Code's interface](https://code.visualstudio.com/docs/sourcecontrol/overview){target=_blank}, + especially when working with multiple repositories. + +Things to note when making changes: + +- When C++ or Python files are saved, you may notice that some lines change. We use formatters to help fix lint errors; + not all lint errors can be fixed by formatters, so you may have to resolve some manually +- When changing a package's source files, you likely should update its test files accordingly + +## 4. Build your changes + +!!! info "" + + Revamped in [:octicons-tag-24: v1.2.0](https://github.com/UBCSailbot/sailbot_workspace/releases/tag/v1.2.0){target=_blank} + +In general, changes need to be built before they can be run. You can skip this step if you only modified Python source +or test files (in `python_package/python_package/` or `python_package/test`, respectively), or are running a launch type +launch configuration. + +1. Depending on which packages you modified, run the `Build All` or `Build Package` task + 1. Unless you want to run `clang-tidy`, use the `-q` build argument (default) for quicker build times + +## 5. Verify your changes + +!!! info "" + + Revamped in [:octicons-tag-24: v1.2.0](https://github.com/UBCSailbot/sailbot_workspace/releases/tag/v1.2.0){target=_blank} + +??? tip "Running GUI applications on macOS" + + If you want to run GUI applications on macOS, ensure that XQuartz is running. + +### Lint and Test + +Run lint and test tasks to make sure you changes will pass our CI: + +- `ament lint` +- For C++ packages, `clang-tidy` +- `test` + +In addition to VS Code tasks, the :fontawesome-solid-flask: **Testing** tab on the VS Code primary sidebar +contains individual tests. One can run specific unit tests by clicking the :material-play-outline: **Run Test** +icon beside the test name. + +VS Code Test Tab + +### Run a Package + +To verify that your changes do what you expect, you may want to run the package you modified. The run commands for each +package should be documented in their READMEs, but in general they can be run using a CLI or VS Code command: + +=== ":octicons-command-palette-16: CLI" + - Launch files: + - `ros2 launch ` + - `ros2 launch ` + - Nodes: + - `ros2 run ` + + ??? tip "CLI features" + + There are many commands that can be autocompleted in the terminal. + Take advantage of this so that you run commands faster and memorize less syntax. + If there is only one possibility, pressing tab once will complete it. + If there is more than one possibility, pressing tab again will list them out. + + Some tab completion use cases: + + - View available commands: lists all `ros2` commands + + ```console + $ ros2 + action extension_points multicast security + bag extensions node service + ... + ``` + + - Complete commands: runs `ros2 launch local_pathfinding main_launch.py` + + ```console + $ ros2lalocm + ``` + + - Navigate to directories: runs `cd .devcontainer/config` from the root directory of Sailbot Workspace + + ```console + $ cd .dc + ``` + + Furthermore, navigate past commands with ++arrow-up++ and ++arrow-down++ and search through them with ++ctrl+r++. + +=== ":material-microsoft-visual-studio-code: VS Code" + - Launch files: `ROS: Run a ROS launch file (roslaunch)` + - Nodes: `ROS: Run a ROS executable (rosrun)` + +For more information on launch file use in our system, see [this page](./launch_files.md){target=_blank}. + +### Run the System + +To verify that you didn't break anything, you may want to run the entire system. See +[Invoking Launch Files](./launch_files.md#invoking-launch-files) for more information +on running the system. + +### Debugging + +Debug your changes if they aren't behaving how you expect by setting breakpoints and running one of our launch +configurations in the **Run and Debug** tab on the VS Code primary sidebar. The launch configuration types are: + +- Launch: runs the desired launch file or executable + - For launch files, `ROS: Launch` + - For C++ executables, `C++ (GDB): Launch` +- Attach: attaches to a running executable + - `ROS: Attach` + +## Troubleshooting + +If you are having some trouble running our software, here are some things you can try: + +- Build from scratch + 1. Run the `clean` task to delete C++ generated files + 2. Run the `purge` task to delete ROS generated files + 3. Run the `Build All` task to rebuild +- Rebuild the Dev Container: run the `Dev Containers: Rebuild Container` VS Code command +- Reload VS Code: run the `Developer: Reload Window` VS Code command +- Delete Docker files + + ??? tip "Running Docker CLI commands on Windows" + + On Windows, Docker CLI commands should be run in the Ubuntu terminal while Docker Desktop is running. + + - Run `docker system prune` to remove all unused containers, networks, and dangling and unreferenced images + - Add `--all` to additionally remove unused images (don't have a container associated with them) + - Add `--volumes` to additionally remove volumes (makes Bash history and ROS logs persist across containers) + - Run `docker rmi -f $(docker images -aq)` to remove all images + +## Performance Issues + +If you are not satisfied with the performance of Sailbot Workspace, here are some things you can try: + +- Free up memory: close programs that you aren't using +- Free up disk space: permanently delete large programs and files that you don't need anymore +- Run Sailbot Workspace in a GitHub Codespace + - In a codespace with 8GB of RAM, building all packages from scratch with the `-q` argument takes about a minute. + If your computer takes longer than, or you want to free up memory and disk space, you can + [setup Sailbot Workspace in a GitHub Codespace](./setup.md#setup-sailbot-workspace-in-a-github-codespace){target=_blank} +- If you are running Sailbot Workspace on Windows, dual boot Ubuntu and run Sailbot Workspace there + - Sailbot Workspace performs worse on Windows than bare metal Linux because it uses Docker, which is not natively supported. + - Here is a guide to dual boot the operating systems we recommend: [How to Dual Boot Ubuntu 22.04 LTS and Windows 11](https://www.linuxtechi.com/dual-boot-ubuntu-22-04-and-windows-11/){target=_blank} + - We recommend allocating at least 50 GB to Ubuntu to leave some wiggle room for Docker + - The process is similar for other Ubuntu and Windows versions, + but feel free to search for a guide specific to the combination you want to dual boot + - Since Sailbot Workspace uses Docker, it should be able to run on any Linux distribution, not just Ubuntu. + However, we may not be able to provide support if you encounter any difficulties with this diff --git a/docs/current/website/overview.md b/docs/current/website/overview.md new file mode 100644 index 000000000..102298480 --- /dev/null +++ b/docs/current/website/overview.md @@ -0,0 +1,7 @@ +!!! quote "Source code" + + The source code for Website can be found in the + [website](https://github.com/UBCSailbot/website){target=_blank} GitHub repository. + Its README has been copied below. + +--8<-- "https://raw.githubusercontent.com/UBCSailbot/website/main/README.md" diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..cf49b45eb --- /dev/null +++ b/docs/index.md @@ -0,0 +1,39 @@ +--- +hide: + - navigation + - toc +--- + +# UBCSailbot Software Team Docs + +Welcome to the UBC Sailbot software team docs :wave: + +Looking to get started with running the Sailbot codebase? Start by setting up the Sailbot Workspace: + +[:octicons-arrow-right-24: Getting Started](./current/sailbot_workspace/setup.md){target=_blank} + +## :fontawesome-solid-circle-info: What information is on this website? + +Information on our current project is contained on this website. In particular, information on each of our major software +projects are provided in detail. + +[:octicons-arrow-right-24: Current Project Overview](./current/overview.md){target=_blank} + +References to the software tools that we use are also provided on this website. This includes basic information on these +tools, how we use these tools on UBC Sailbot, and external links to helpful references and tutorials. + +[:octicons-arrow-right-24: Software Team References](./reference/cpp/start.md){target=_blank} + +## :octicons-people-24: Who is this website for? + +The docs site is primarily for the members on the UBC Sailbot software team. However, curious members of the public and/or +those who are interested in contributing to our open source software would also benefit from this site. + +## :material-sail-boat: Prospective Members + +Are you a member of the UBC community? Are you interested in what we do at UBC Sailbot? We are always looking for motivated +students to help us tackle the challenge of autonomous sailing. Learn more below! + +[:octicons-arrow-right-24: Software Team Posting](https://docs.google.com/document/d/1bToOV3JvMZFJ9jotrjlFIvDgY8xiXfH7Yg1wkGm8Qf4/edit?usp=sharing){target=_blank} + +[:octicons-arrow-right-24: Apply to join UBC Sailbot](https://www.ubcsailbot.org/recruitment){target=_blank} diff --git a/docs/javascripts/mathjax.js b/docs/javascripts/mathjax.js new file mode 100644 index 000000000..080801efb --- /dev/null +++ b/docs/javascripts/mathjax.js @@ -0,0 +1,16 @@ +window.MathJax = { + tex: { + inlineMath: [["\\(", "\\)"]], + displayMath: [["\\[", "\\]"]], + processEscapes: true, + processEnvironments: true + }, + options: { + ignoreHtmlClass: ".*|", + processHtmlClass: "arithmatex" + } +}; + +document$.subscribe(() => { + MathJax.typesetPromise() +}) diff --git a/docs/javascripts/table_of_contents_themes.js b/docs/javascripts/table_of_contents_themes.js new file mode 100644 index 000000000..037d8ba45 --- /dev/null +++ b/docs/javascripts/table_of_contents_themes.js @@ -0,0 +1,55 @@ +const LIGHT_MODE = 0; +const DARK_MODE = 1; +const LIGHT_MODE_TABLE_OF_CONTENTS_LINK_COLOR = "#000000"; // Black +const DARK_MODE_TABLE_OF_CONTENTS_LINK_COLOR = "#ffffff"; // White +const SAILBOT_BLUE = "#2f97ec"; + +// Sets the theme given a mode +function set_table_of_content_link_color(mode) { + let linkColor = ""; + switch (mode) { + case LIGHT_MODE: + linkColor = LIGHT_MODE_TABLE_OF_CONTENTS_LINK_COLOR; + break; + case DARK_MODE: + linkColor = DARK_MODE_TABLE_OF_CONTENTS_LINK_COLOR; + break; + default: + console.log("Error determining website theme. Defaulting table of content link color to sailbot blue."); + linkColor = SAILBOT_BLUE; + break; + } + document.documentElement.style.setProperty("--md-table-of-contents-link-color", linkColor); +} + +// Returns the new theme index given the current theme +function toggle_table_of_contents_link_color(current_mode) { + switch (current_mode) { + case LIGHT_MODE: + return DARK_MODE; + case DARK_MODE: + return LIGHT_MODE; + default: + return -1; + } +} + +// An enslosure that keeps track of the mode and toggles the theme accordingly +const theme_enclosure = function(initial_mode) { + let current_mode = initial_mode; + return { + setLinkColor: () => {set_table_of_content_link_color(current_mode);}, + toggleLinkColor: () => {current_mode = toggle_table_of_contents_link_color(current_mode); set_table_of_content_link_color(current_mode);} + }; +}; + +// Set the theme upon the window loading +var initial_mode = __md_get("__palette").index; +table_of_contents_theme = theme_enclosure(initial_mode); +table_of_contents_theme.setLinkColor(); + +// Set the theme when the light/dark mode button is clicked +const buttons = document.querySelectorAll("form.md-header__option > label.md-header__button"); +buttons.forEach((button) => { + button.addEventListener('click', table_of_contents_theme.toggleLinkColor); +}); diff --git a/docs/overrides/main.html b/docs/overrides/main.html new file mode 100644 index 000000000..d75754906 --- /dev/null +++ b/docs/overrides/main.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} + +{% block outdated %} + You're not viewing the version in the main branch. + + Click here to go to main. + +{% endblock %} diff --git a/docs/reference/cpp/differences.md b/docs/reference/cpp/differences.md new file mode 100644 index 000000000..9cdbe9ad1 --- /dev/null +++ b/docs/reference/cpp/differences.md @@ -0,0 +1,280 @@ +# Differences Between C and C++ + +For most use cases, you can think of C++ as a superset of C. While this is not technically true, more often than not +you are able to write standard C code for a C++ program without issues. However, doing so ignores a lot of the benefits +and reasons to use C++. + +## Classes and Structs + +In C structs can only contain member variables, but in C++ structs are basically classes but with a default member +visibility of public instead of private. + +???+ example + The following code blocks are equivalent. + + ```C++ + struct foo { + private: + int x; + void helper(void); + public: + foo(int y); + } + ``` + + ```C++ + class foo { + private: + int x; + void helper(void); + public: + foo(int y); + } + ``` + +## Namespaces + +One problem that is prevalent in C concerns the scoping of names. For example, let there be two files `A.h` and `B.h` +and a program `ighxy.c`, and let them both contain a `float x` and `int bar(void)`. + +Our program cannot compile because the linker cannot distinguish which `bar()` function we want to use! One way to fix +this in a C program would be to rename them `a_bar()` and `b_bar()`. Although this fix seems trivial for this example, +applying it to a file that has potentially 100 functions can be a lot more difficult, especially if two files just +happen to share the same prefix for their functions! + +C++ introduces namespaces to tackle this problem. With namespaces, we can deal with naming conflicts much more easily. +Though be aware that namespaces are not necessary everywhere. See the following code snippet to see how they work. + +??? Example + + === "C" + + ```C title="A.h" + float x; + int bar(void); + ``` + + ```C title="B.h" + float x; + int bar(void); + ``` + + ```C title="ighxy.c" + #include "A.h" + #include "B.h" + + int main(void) { + int a = bar(); + ... + } + /* Error, does not compile*/ + ``` + + === "C++" + + ```C++ title="A.h" + namespace a { + float x; + int bar(void); + } + ``` + + ```C++ title="B.h" + namespace b { + float x; + int bar(void); + } + ``` + + ```C++ title="ighxy.cpp" + #include "A.h" + #include "B.h" + + int main(void) { + int a = a::bar(); + int b = b::bar(); + float xa = a::x; + float xb = b::x; + /* No problem! */ + ... + } + ``` + +???+ warning + You may come across something like: + + ```C++ title="example.cpp" + using namespace std; + namespace io = std::filesystem; + + int main(int argc, char* argv[]) { + bool isDirectory = io::is_directory(argv[1]); // Equivalent to std::filesystem::is_directory(argv[1]) + cout << isDirectory << endl; + return 0; + } + ``` + + There are two things going on here. + + First, `using namespace std` makes all functions and types defined within the standard namespace and included via + `#include` directives visible to `example.cpp`. If you are familiar with Python, the Python equivalent of this would + be `import std as *`. However, it is considered *bad* practice to do this as it eliminates the point of using + namespaces. + + === "OK" + + ```C++ + class string { + // Insert implementation here + } + + int main(void) { + string ourString = "Our own string implementation"; + std::string stdString = "Standard Library string implementation"; + ... + } + ``` + + === "Not OK" + + ```C++ + using namespace std; + + // ERROR - multiple definitions of type string + class string { + + } + ``` + + The compiler cannot infer which implementation we want. + + Secondly, `namespace io = std::filesystem` is basically an alias for the `std::filesystem` namespace. This practice + is acceptable for long namespace identifiers, but be careful as it can still run into namespace conflicts if your + alias is the same as another namespace or alias. + +## Constant Expressions + +In C, if we want to declare a constant or a function/expression that we want to be evaluated at compile time, we need +to use `#define` statements. One of the problems with `#define` statements is that they perform a simple copy paste +wherever they're used. For example: + +=== "Before Precompile" + + ```C + #define PI 3.14F + #define AREA_OF_CIRCLE(radius) ((PI) * (radius) * (radius)) + + int main(void) { + float area = AREA_OF_CIRCLE(2.5F); + ... + } + ``` + +=== "After Precompile" + + ```C++ + int main(void) { + float area = ((3.14F) * (2.5F) * (2.5F)); + ... + } + + ``` + +!!! note + `AREA_OF_CIRCLE` is a macro with arguments. If you are confused by it, [this resource](https://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)Macros.html){target=_blank} + has a detailed explanation on how they work. + +Because of this copy-pasting, you need to be very careful with syntax, sometimes necessitating an ugly +[`do {} while(0)` wrapper](https://stackoverflow.com/questions/1067226/c-multi-line-macro-do-while0-vs-scope-block){target=_blank}. +Moreover, symbols declared with `#define` are always globally visible, ignoring namespaces! + +In C++, the use of constant expressions are preferred. + +```C++ +constexpr float pi = 3.14F; +constexpr float area_of_circle(float radius) { + return pi * radius * radius; +} +``` + +Constant expressions do *not* get copy pasted, and are instead placed in program memory just like a normal variable +or function. They also respect namespaces and function scopes, meaning the following code compiles. + +```C++ title="Constant Expression Scoping" +void foo(void) { + constexpr float rand = 123.456; + ... +} + +void bar (void) { + constexpr float rand = 789.123; + ... +} +``` + +## Lambdas + +Lambdas are primarily useful when you need to register a callback function one time and don't feel it's necessary to +write out a full function. They are in no way required though, so do not worry about learning them. However, it's +necessary to know that they exist such that you don't get confused when reading code. For more information, [go here](https://learn.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=msvc-170){target=_blank} +for Microsoft's explanation. + +## Misc + +### Arrays + +Using the [C++ implementation of arrays](https://en.cppreference.com/w/cpp/container/array#:~:text=std%3A%3Aarray%20is%\20a%20container%20that%20encapsulates%20fixed%20size,C-style%20array%2C%20it%20doesn%27t%20decay%20to%20T%2A%20automatically.){target=_blank} +is preferred over C arrays. It is simply easier and safer to work with than a standard C array without any performance +costs. + +???+ example + + Passing an array to a function an iterating over it + + === "C" + + ```C + #include "stdio.h" + + void print_contents(int *arr, int size) { + for (int i = 0; i < size; i++) { + printf("%d\n", *arr); + } + } + + int main(void) { + int arr[5] = {0, 1, 2, 3, 4}; + foo(arr, 5); + return 0; + } + ``` + We can't even guarantee that the integer pointer `arr` is an array! + + === "C++" + + C++ 20 makes passing arrays around a lot simpler. Do not worry about understanding the code shown below. It uses + some fairly advanced concepts and exists to illustrate how different such a simple operation can be. + + ```C++ + #include + #include + #include + + void print_contents(std::span container) { + for (const auto &e : container) { + std::cout << e << std::endl; + } + } + + int main(void) { + std::array arr = {0, 1, 2, 3, 4}; + foo(arr); + return 0; + } + ``` + + The advantages of the C++ version are: + + * Size is implicitly part of the object + * We guarantee that foo takes a container, but it does not care if it's an array or, say, a vector, which is + preferable in this scenario where we simply iterate through the container's existing elements diff --git a/docs/reference/cpp/start.md b/docs/reference/cpp/start.md new file mode 100644 index 000000000..76383bdf3 --- /dev/null +++ b/docs/reference/cpp/start.md @@ -0,0 +1,31 @@ +# Getting Started + +UBC Sailbot's Network Systems team uses C++ for its software. If you know already know C, then you already know the +bare minimum to write C++. This is a good starting point, but the additional features C++ provides allow for safer +programming practices. + +## For C/C++ Beginners + +If you just need to know how C++ is different from C, then see the [Differences Between C and C++](./differences.md). +You should also look at it if you go through and finish this section. + +If you are new to C and C++, then this the best place to start. The tutorials provided in this section will help you +learn the fundamentals of the language. Do not feel pressured to do all the tutorials! Just get comfortable with the +syntax and the mechanisms of the language. + +!!! note + The hardest part about this will likely be pointers and dynamic memory, so pay close attention to tutorials + concerning them! Additionally, dynamic memory requires the usage of pointers, but pointers do not require dynamic + memory! + +!!! tip + Dynamic memory is much more prone to error than statically allocated memory, so try to use static allocation + whenever possible + +| Resource | Description | +| :--------------------- | :------------------------------------------------------------------------------------------ | +| [w3schools Tutorial](https://www.w3schools.com/cpp/default.asp){target=_blank} | A structured tutorial that goes through basic concepts in C++. It's good to do up to the section on Classes. | +| [YouTube Tutorial](https://youtu.be/vLnPwxZdW4Y){target=_blank} | If you prefer video tutorial, then this is a comprehensive 4 hour video covering similar concepts to the one above. It is 4 hours long though. | +| [Dynamic Memory Overview](https://www.tutorialspoint.com/cplusplus/cpp_dynamic_memory.htm){target=_blank} | A page going over how dynamic memory works in C++. | + +Feel free to add other resources other than the ones listed above if you find any that you like! diff --git a/docs/reference/cpp/tools.md b/docs/reference/cpp/tools.md new file mode 100644 index 000000000..750b20511 --- /dev/null +++ b/docs/reference/cpp/tools.md @@ -0,0 +1,127 @@ +# Tools + +A lot goes into making a well structured C++ project, much more than any one team should have to do. + +## CMake + +CMake is a powerfull build automation tool that makes compiling code for large projects with a lot of interoperating +files a lot easier. Steps 1-3 of the [official tutorial](https://cmake.org/cmake/help/latest/guide/tutorial/index.html){target=_blank} +are great for understanding the basics. + +## GDB + +The [GNU Project Debugger](https://www.sourceware.org/gdb/){target=_blank} is the most commonly debugger for the C +language family. +VSCode also has a degree of integration with GDB that allows an easy to use GUI. This [GDB cheat sheet](https://darkdust.net/files/GDB%20Cheat%20Sheet.pdf){target=_blank} +has all the GDB comands you will need to know. Be aware the VSCode has GUI buttons for some of these commands that are +easier to use. + + + +## GoogleTest + +[GoogleTest](https://github.com/google/googletest){target=_blank} is the C++ unit testing framework we will be using. +The [GoogleTest Primer](https://google.github.io/googletest/primer.html){target=_blank} is a good place to start. + +??? example + + === "Cached Fibonacci Program" + + ```C++ title="cached_fib.h" + #include + class CachedFib { + public: + void CachedFib(int n); + int getFib(int n); + private: + std::vector cache; + } + ``` + + ```C++ title="cached_fib.cpp" + #include + #include + #include "cached_fib.h" + + void CachedFib::CachedFib(int n) { + cache.push_back(0); + cache.push_back(1); + for (int i = 2; i < n; i++) { + cache.push_back(cache[i - 1] + cache[i - 2]); + } + } + + int CachedFib::getFib(int n) { + if (cache.size() < n) { + for (int i = cache.size(); i < n; i++) { + cache.push_back(cache[i-1] + cache[i-2]); + } + } + std::cout << cache[n - 1] << std::endl; + } + ``` + + === "Test Cached Fibonacci Program" + + ```C++ title="test_cached_fib.cpp" + + #include "cached_fib.h" + #include "gtest/gtest.h" + + CachedFib::testFib; + + class TestFib : public ::testing::Test { + protected: + void Setup override { + // Every time a test is started, testFib is reinitialized with a constructor parameter of 5 + testFib = CachedFib(5); + } + } + + TEST_F(TestFib, TestBasic) { + ASSERT_EQ(getFib(5), 3) << "5th fibonacci number must be 3!"; + } + + // more tests + + ``` + + + +## Google Protocol Buffer + +[Google Protocol Buffer](https://developers.google.com/protocol-buffers){target=_blank} (Protobuf) is a portable data serialization +method. We use it over other methods like JSON and XML because it produces smaller binaries, an important consideration +when sending data across an ocean. Unfortunately, there does not seem to be a easy to follow tutorial for using them, +but here are the [C++ basics](https://developers.google.com/protocol-buffers/docs/cpptutorial){target=_blank}. The page +is quite dense and can be hard to follow, so do not worry if you do not understand it. + +## Clang + +In its most basic form, [Clang](https://clang.llvm.org/){target=_blank} is a compiler for the C language family. +Clang has multiple +benefits like easier portability compared to, for example, GCC. Clang is actually "half" the compiler, the other half +being LLVM. Without going into unnecessary detail, Clang compiles C++ code to a generic language before LLVM compiles +it to machine specific language. + +### Clangd + +[Clangd](https://clangd.llvm.org/){target=_blank} is the Clang language server. It provides a much more powerful +intellisense than the default one used in VSCode's C/C++ extension. + +### Clang-Tidy + +[Clang-Tidy](https://clang.llvm.org/extra/clang-tidy/){target=_blank} is a linting tool, who's main purpose is to catch potential +programming errors caused by bad programming style/practices using just static analysis. + +### Clang Format + +An autoformatting tool that makes enforcing style guidelines much easier. When se tup, it corrects formatting as soon +as you hit save. + +## llvm-cov + +We will use [llvm-cov](https://llvm.org/docs/CommandGuide/llvm-cov.html){target=_blank} to evaluate our test coverage. +When used with +[genhtml](https://www.systutorials.com/docs/linux/man/1-genhtml/){target=_blank}, we can generate HTML reports that that +show our line, function, and branch coverage line-by-line. diff --git a/docs/reference/github/workflow/branches.md b/docs/reference/github/workflow/branches.md new file mode 100644 index 000000000..759a66f0c --- /dev/null +++ b/docs/reference/github/workflow/branches.md @@ -0,0 +1,129 @@ +# Developing on Branches + +We use branching to work on issues without modifying the main line. This ensures that the main line only +contains functional code and handles merge conflicts that arise +when multiple people are developing at the same time. For a quick rundown on branching in git, +consult the official [git documentation](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell){target=_blank}. + +## Creating a branch + +When starting a new issue, you will want to create a new branch for it: + +!!! caution + + When creating branches locally, it uses your **local copy** to create the new branch. Remember to do a `git pull` + if you intend on using the latest changes from the remote branch you are creating from. + +```bash title="Creating a new branch from main" +# Switch to main +git switch main + +# Update your local copy +git pull + +# Clone a new branch from main +git switch -c +``` + +**IMPORTANT:** When creating a new branch for an issue, you must create the branch from `main`. + +## Branch naming convention + +When working on a new issue, you will want to create a branch to work on it. We have the following branch +naming convention: + +``` +user//- +``` + +!!! example + + If Jill (GitHub Username: jill99) is going to take on an issue titled "Fix bug on pathfinding software" + and the issue number is 39, then the branch named can be named something like `user/jill99/39-fix-pathfinding-bug`. + +If the branch that you are creating is not tied to an issue, then you **do not** need to put an issue number. +A descriptive title will suffice. + +## Tracking and committing changes + +All files where new changes have been made must first be "staged" in order to make commits: + +``` +git add +``` + +Files that are staged will be part of your next commit. Once you are confident in your changes and you are ready +to finalize them, then you should commit your changes: + +``` +git commit -m "" +``` + +Be sure to add a commit message that is descriptive of the changes that you made. It is encouraged that you make commits +often so you can keep track of your changes more easily and avoid overwhelmingly large commits when you look back on your +version history. + +When you are ready to move your local changes to a remote branch, you want to push to the correct branch +and potentially set the upstream if it does not yet exist: + +``` +git push -u origin +``` + +## Merging branches + +There may be times where you want to merge two branches together, whether you diverged on some ideas and finally +want to synthesize them, or you just want to update your issue's branch with the main branch. In any case, merging +branches will be inevitable as part of the development process, so it is essential to understand how to merge branches. + +=== "Merge Local Branch" + + ``` bash + # Checkout to destination branch + git checkout + + # Merge with local copy of other branch + git merge + ``` + +=== "Merge Remote Branch" + + ``` bash + # Checkout to destination branch + git checkout + + # Fetch from remote + git fetch + + # Merge remote copy of other branch + git merge origin/ + ``` + +!!! info + + Merging a remote branch into its local counterpart using the method above is essentially + the same operation as `git pull`. + +Once the merge operation is complete, your destination branch should have updates both from itself and the other +branch that you merge. If you do a `git log`, you will also see a new commit that indicates that the merge happened. + +## Resolving merge conflicts + +Merging two branches is not always easy since the commit history for both branches could look quite different, and +therefore conflicting changes can easily be made. If you run into a scenario like this, you may get something like this: + +![image](../../../assets/images/github/workflow/merge_conflict.png) + +Upon inspecting `bar.txt`, we see the following: + +![image](../../../assets/images/github/workflow/merge_conflict_file.png) + +Resolving merge conflicts is not always a trivial task, but there are many ways to resolve them which include: + +- [Resolving on GitHub](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-on-github){target=_blank} +(recommended) +- [Resolving in Command Line](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line){target=_blank} + +!!! tip + + If you cannot resolve a merge conflict on your own, reach out to your lead for help! diff --git a/docs/reference/github/workflow/issues.md b/docs/reference/github/workflow/issues.md new file mode 100644 index 000000000..8b9997e22 --- /dev/null +++ b/docs/reference/github/workflow/issues.md @@ -0,0 +1,102 @@ +# Creating Issues + +GitHub issues lets us plan and track our work on GitHub. + +## Getting started with issue templates + +An issue is associated with a specific repository. To open the issues page for a given repository, click on +the issues tab in the repository navigation bar. + +![image](../../../assets/images/github/workflow/issue_tab.png) + +You will see a list of current issues (if any) for the repository. To create a new issue, click on the +`New issue` button in the upper right corner. + +![image](../../../assets/images/github/workflow/issue_list.png) + +When creating a new issue, you will see a few issue templates. Since issues can be created for a variety of reasons, +issues may therefore be structured differently and contain different kinds of information. Issue templates were +introduced to give us a quick and structured way to writing issues. + +![image](../../../assets/images/github/workflow/issue_template_list.png) + +!!! note + + GitHub issues are written using GitHub-flavoured markdown. To add a little spice to your issues, refer + to the official [GitHub documentation](https://docs.github.com/en/get-started/writing-on-github){target=_blank} + for some quick tips and tricks on how to write awesome markdown! + +Click on the `Get started` button to open the issue template. For this example, let's go with the `New Feature` +issue template. Upon opening the issue template, you should see a page like the one below: + +![image](../../../assets/images/github/workflow/new_feature_template.png) + +At this point, you should give a succinct title and describe the issue in the textbox. You will also see some templated +sections to fill out. Try to give only the necessary details to make a clear and concise issue. If you are unsure on how +to construct your issue, take a look at current or past issues and ask the software leads for further guidance if necessary. + +Finally, feel free to [make suggestions](https://github.com/UBCSailbot/.github/issues/templates/edit){target=_blank} +on new templates or changing current templates! + +!!! tip + + We understand that some issues may need extra sections to describe the issue further, or some of + the templated sections might not be relevant at all! Add or remove sections as necessary to get your + point across. The goal of the issue templates is to provide guidance, not police your documentation + methodologies! + +## Adding issues to a project + +We use projects to plan and track the status of our issues and pull requests. +To add an issue to an existing project, click on the gear icon in the `Projects` section and add it to your desired +project. You will almost always want to add your issue to the Software organization project. + +![image](../../../assets/images/github/workflow/gh_project.png) + +To verify that your issue has been added to your desired project, go to the UBC Sailbot organization, go +to the `Projects` tab on the organization banner, and select the project that it is added to. When added +to a project, it should show up under the `General` tab (depending on the project, this might not always +be the case). + +## Adding issues to a milestone + +We use milestones to track progress on groups of issues or pull requests that we want to complete by a certain date. +Since our projects span over many years, it is important to work incrementally with small, +yet achievable goals. If your issue should belong to a milestone, simply add it to a milestone by clicking +on the gear icon in the `Milestone` section and add it to your desired milestone. + +![image](../../../assets/images/github/workflow/gh_milestone.png) + +!!! note + + Unlike projects, milestones are strictly associated with a repository. + +## Labelling issues + +GitHub allows us to label our issues so that we can categorize them. It helps us identify at first glance what +kind of a problem that an issue aims to solve and which issues are more important. To add a label to your issue, +click on the gear icon in the `Labels` section and add your desired label(s). + +![image](../../../assets/images/github/workflow/gh_labels.png) + +The issue templates will already have labels assigned to them, but you should add or remove labels as you see fit +to make them as relevant as possible. + +!!! note + + Each repository might have different labels available, so be sure to check out all of the labels + at least once in the repository that you are working in. Feel free to suggest additional labels + as well! + +## Adding assignees + +Every issue should be assigned to at least one person to work on it. If you are not sure who should be assigned +the issue initially, then don't worry about it for now since you can assign someone to the issue later on. To +assign someone an issue, click on the gear icon in the `Assignees` section and add the desired people. + +![image](../../../assets/images/github/workflow/gh_assignee.png) + +## Submit the issue + +Once you are finished writing your issue, click on the `Submit new issue` button. You should now see your issue +in the issues list and in the UBC Sailbot software project. diff --git a/docs/reference/github/workflow/overview.md b/docs/reference/github/workflow/overview.md new file mode 100644 index 000000000..1f9c518eb --- /dev/null +++ b/docs/reference/github/workflow/overview.md @@ -0,0 +1,43 @@ +# Development Workflow Overview + +``` mermaid +graph LR + B[Problem Conception] --> C{Small Fix?}; + C --> |Yes| E[Development]; + C --> |No| D[Issue Creation]; + D --> E; + E --> F[Pull Request]; + F --> G{Approved?}; + G --> |No| E; + G --> |Yes| H[Merge PR into Main]; +``` + +A good development workflow is essential to maintain a robust codebase and stay organized. The above +diagram is a high level overview of how our development process works, and parts of this process +are explained in subsequent sections. + +## Version control: Git + +We use git to help us keep track of the version history of our codebase. Git is a free and open source +distributed version control system, and it is commonly used by many developers to keep track of changes +to their code over time. As a member of the software team on UBC Sailbot, it is absolutely necessary that +you know git. If you are unfamiliar with git, here are a few resources to help you get started: + +| Resource | Description | +| :----------------------------------------------------- | :----------------------------------------------------- | +| [Beginners Tutorial](https://youtu.be/HVsySz-h9r4){target=_blank} | A 30 minute video on git for beginners. Good if you want to learn git quickly and nail all the fundamentals. | +| [Pro Git book](https://git-scm.com/book/en/v2){target=_blank} | A textbook on using git. Good if you are a completionist and want to deep dive into how git works (and if you have some time on your hands). | +| [Common Git Commands](https://patrick-5546.github.io/notes/reference/git/git_commands/){target=_blank} | A condensed summary of some common git commands. Good to refer to once you are familiar with the fundamentals of git. | + +## Remote server: GitHub + +We use GitHub as our remote server where we store our codebase. In addition to using it for storage, we also +leverage many of GitHub's features to make for a smoother development process. Some examples of features +that we use are: + +- [Issues](./issues.md#creating-issues) +- [Projects](./issues.md#adding-issues-to-a-project) +- [Milestones](./issues.md#adding-issues-to-a-milestone) +- GitHub Organizations +- Repository Permissions and Branch Protection Rules +- And more! diff --git a/docs/reference/github/workflow/pr.md b/docs/reference/github/workflow/pr.md new file mode 100644 index 000000000..f0740bd91 --- /dev/null +++ b/docs/reference/github/workflow/pr.md @@ -0,0 +1,84 @@ +# Pull Requests + +Pull requests are used to verify code functionality and quality of a development branch before merging into the main branch, +accomplished through CI and code reviews. + +!!! note + + Pull requests are much like issues where we can do many of the same things. This goes for creating + comments in markdown, assigning reviewers, adding labels, adding projects, or adding milestones. + Sometimes we skip writing an issue when the change is relatively small. + +## Creating a pull request + +To create a pull request in a repository, to go the `Pull requests` tab and then click `New pull request`: + +![image](../../../assets/images/github/workflow/create_pr.png) + +On the next screen, you need to select the base branch that you are merging into, and the branch that you +are comparing. For the most part, the base branch will be the main branch, and the branch that you are comparing +will be the issue branch. + +![image](../../../assets/images/github/workflow/branch_comparison.png) + +Once you have decided on your base and compare branches, click on `Create pull request`. You should see +the page below (looking in the dropdown menu, you can open the pull request as a draft to avoid notifying +reviewers until you are ready): + +![image](../../../assets/images/github/workflow/pr_example.png) + +Notice how this is remarkably similar to the page of an issue. To link a pull request to an issue, simply add +` #` to the initial comment in the pull request. A list of valid keywords can be found +[here](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue){target=_blank}. + +!!! example + + "This issue resolves #49. Please review my pull request!" + +Observe that the right-hand side banner contains the following: + +| Field | Description | +| :------------------ | :----------------------------------------------------------------------------------------------| +| Reviewers | Assign reviewers to review your pull request. Always try to assign at least one reviewer. | +| Assignees | Assign the people who worked on the issue. | +| Labels | Assign labels to categorize pull requests. | +| Projects | Assign a pull request to a project. | +| Milestone | Assign a pull request to a milestone. | + +!!! attention + + If you linked the pull request to an issue, you **should not** add the pull request to a project or a milestone to + avoid duplicate cards. + +## Merging into main + +Once the pull request and code reviews are complete, it is time to merge the changes in the pull request into the main +branch! However, this can only be done when the following conditions are met: + +1. All CI checks pass (look for a green checkmark beside your latest commit on GitHub). +2. All reviewers have reviewed the PR and approved the PR. +3. There are no unresolved comments and suggestions from the reviewers. +4. There are no merge conflicts with the main branch. + +If all of these conditions are met, confirm that the merge is good to go by clicking `Squash and merge`: + +![image](../../../assets/images/github/workflow/pr_merge.png) + +## Reviewing a pull request + +A common activity that you will participate in is reviewing pull requests to give your feedback on other's code. +You will be notified when you have been requested to review a pull request and should promptly review it as +soon as time permits. + +![image](../../../assets/images/github/workflow/pr_comment_snippet.png) + +In particular, you will most likely be doing the following in a pull request: + +- **Asking Questions:** Clarify your understanding about something that you are not sure about. +- **Providing Suggestions:** Give some ideas about how to improve the current implementation and provide feedback to +your peers. This is a good opportunity to share your knowledge with others. +- **Verify Implementations:** Identify potential bugs in the implementation and raise your concerns with the person +who developed the solution. This will reduce the likelihood of bugs and significantly bring down the number of issues +in the future. +- **Documentation:** Record why certain changes were made, especially if this diverges from the proposed solution +in the linked issue (if any). diff --git a/docs/reference/markdown.md b/docs/reference/markdown.md new file mode 100644 index 000000000..2781dcbe7 --- /dev/null +++ b/docs/reference/markdown.md @@ -0,0 +1,107 @@ +# Markdown + +Markdown is a lightweight markup language that you can use to add formatting elements to plaintext text documents.[^1] +You can do anything with Markdown, from creating websites to PDF documents, all in a clean format that is easy to +learn. [Many of your favorite services use Markdown](https://www.markdownguide.org/tools/){target=_blank}, so it would +be useful to pick it up to write technical documentation. + +Markdown is not standardized across services. Many services that support Markdown have their +own "flavour" of Markdown. Be sure to know the Markdown features of the service +you are using so that your Markdown renders properly. + +## Getting Started + +We recommend [markdownguide.org](https://www.markdownguide.org/){target=_blank} to be your first point of reference if\ +you are learning Markdown for the first time. It covers topics like what Markdown is, its syntax, advanced tips, and the +different services that support Markdown. Flavours of Markdown specific to a service build on top of these basics. + +## Sailbot and Markdown + +We write Markdown for GitHub and Material for MkDocs. The following sections +detail how Markdown is used in these services. + +### GitHub + +We use Markdown in GitHub for technical documentation and collaboration. This includes: + +- `README.md` files +- Issues +- Pull Requests + +Almost all places where text is written in GitHub support Markdown. GitHub also allows you to preview +your Markdown before you submit any comments. + +=== "Before Rendering" + + ![image](../assets/images/markdown/issue_md_text.png) + +=== "After Rendering" + + ![image](../assets/images/markdown/issue_md_rendered.png) + +The image above shows an example of a "write" and a "preview" tab for writing a comment on an issue. It might look +different depending on where you are writing, but there usually exists a preview option! + +!!! note "GitHub-Flavoured Markdown" + + GitHub uses its own "flavour" of Markdown. Certain features, like using HTML, are excluded for security reasons. + Visit the [official GitHub Markdown guide](https://docs.github.com/en/get-started/writing-on-github){target=_blank} + for more information on the available features. + +### Material for MkDocs + +We use Markdown in Material for MkDocs to create this website! Since it is written in Markdown, no frontend +experience is required to contribute to our docs. + +Material for MkDocs supports powerful features purpose-built to take technical documentation to the next level. +Feel free to browse this site to see how we use these features, exploring their syntax in the +[source code](https://github.com/UBCSailbot/docs/tree/main/docs){target=_blank}. Since GitHub renders Markdown files automatically +you will need to click the "Raw" button to view their contents. + +!!! note "Material-Flavoured Markdown" + + Material for MkDocs' flavour of Markdown extends upon vanilla Markdown, adding features such as admonitions + (like this note) and content tabs. Refer to the + [official Material for MkDocs reference page](https://squidfunk.github.io/mkdocs-material/reference/){target=_blank} + for more information on the available features. + +## Rendering Markdown + +You have a few choices to render Markdown on your computer. +Be advised that if you are using an extended version of Markdown, you will +need to consult the documentation from the service provider to render their flavour of Markdown properly. The following +resources are good for rendering Markdown: + +=== ":simple-markdown: Vanilla" + - [VS Code](https://code.visualstudio.com/docs/languages/markdown#_markdown-preview){target=_blank}: Markdown + rendering is supported + out of the box. + - [Markdown Live Preview](https://markdownlivepreview.com/){target=_blank}: An online rendering tool. + +=== ":simple-github: Github" + - [Markdown Preview GitHub Styling](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-preview-github-styles){target=_blank}: + VS Code extension that renders GitHub-flavoured markdown. + - Create a draft issue on GitHub and preview the markdown to see how it renders. + +=== ":logo: Material for MkDocs" + - UBC Sailbot Docs: To preview your changes when working on this site, + refer to the [run instructions in the `README.md`](https://github.com/UBCSailbot/docs#run){target=_blank}. + - Material for MkDocs sites in general: If you ever decide to write your own documentation using Material for MkDocs, + refer to the [official "Getting Started" guide](https://squidfunk.github.io/mkdocs-material/getting-started/){target=_blank}. + +Other resources exist to render Markdown like browser extensions that render Markdown as HTML and GitHub repositories +that contain source code to render your Markdown. Feel free +to browse around for the solution that suits your needs. + +## Linting + +We lint our Markdown files to reduce errors and increase readability. In particular, we use two tools: + +1. [markdownlint](https://github.com/DavidAnson/markdownlint){target=_blank} is +used to enforce a style guide. Its configuration file for this repository is [`.markdownlint.json`](https://github.com/UBCSailbot/docs/blob/main/.markdownlint.json){target=_blank}. +If you use VS Code, there is a [markdownlint extension](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint){target=_blank}. + +2. [markdown-link-check](https://github.com/tcort/markdown-link-check){target=_blank} is +used to check for broken links. Its configuration file for this repository is [`.markdown-link-check.json`](https://github.com/UBCSailbot/docs/blob/main/.markdown-link-check.json){target=_blank}. + +[^1]: diff --git a/docs/reference/python/conventions.md b/docs/reference/python/conventions.md new file mode 100644 index 000000000..18abcc41d --- /dev/null +++ b/docs/reference/python/conventions.md @@ -0,0 +1,246 @@ +# Conventions + +At UBC Sailbot, we follow standards in how we code to maintain a clean and comprehensible codebase. +This page addresses what conventions we use specifically when programming in Python and the tools to help us maintain +these conventions. + +## Style guide + +### Linting + +To ensure that the codebase stays clean, we use [flake8](https://flake8.pycqa.org/en/5.0.4/#){target=_blank}, which is a +tool for style guide enforcement mostly based off [pep8](https://peps.python.org/pep-0008/){target=_blank}. To automate +most of this process, we use [autopep8](https://github.com/hhatto/autopep8){target=_blank}, which is a tool that resolves +most style issues. However, there will be some issues that must be resolved by you! + +Refer to this [guide](https://realpython.com/python-pep8/){target=_blank} on how to write readable code in python with the +pep8 style guide. + +!!! note + + Our CI automatically checks that your code follows the pep8 standard. If it does not, your pull requests will + be blocked from being merged until those issues are resolved! + +### Type hinting + +Even though Python is a dynamically typed language, newer versions support type hinting. Type hinting catches +errors, documents code, improves IDEs and linters, and helps build and maintain a clean software architecture.[^1] +Expanding on how it catches errors, a static type checker such as [`mypy`](https://mypy.readthedocs.io/en/stable/index.html){target=_blank} +can be used. + +There is some syntax to get familiar in order to use type checking. We recommend the following resources: + +- [mypy Typing Cheatsheet](https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html){target=_blank} +- [PEP 483: The Theory of Type Hints (A Simplified Guide)](https://peps.python.org/pep-0483/){target=_blank} +- [PEP 484: Type Hints (Fully Comprehensive Guide)](https://peps.python.org/pep-0484/){target=_blank} + +Below are a few examples of using type hinting: + +???+ example "Return the sum of a sequence" + + ```python + from typing import Sequence, Union + + + Number = Union[int, float] + + + def sumseq(seq : Sequence[Number]) -> Number: + return sum(seq) + ``` + +???+ example "Function with optional parameters and default values" + + ```python + from typing import Optional + + + def printArgs(a : str, b : str="World", c : Optional[str]=None) -> None: + print(f"Value of a: {a}") + print(f"Value of b: {b}") + if c is not None: + print(f"Value of c: {c}") + ``` + +??? example "Function with custom class" + + ```python + class MyClass: + def __init__(self) -> None: + pass + + + def foo(a : MyClass) -> None: + print(a) + ``` + +??? example "Forward referencing a class" + + === "With `__future__`" + + ```python + from __future__ import annotations + + + def foo(a : MyClass) -> None: + print(a) + + + class MyClass: + def __init__(self) -> None: + pass + ``` + + === "Without `__future__`" + + ```python + def foo(a : 'MyClass') -> None: + print(a) + + + class MyClass: + def __init__(self) -> None: + pass + ``` + +??? example "Function that never returns" + + ```python + from typing import NoReturn + + + def bar() -> NoReturn: + while True: + print("Hello World!") + ``` + +## Documentation + +Code is written once and read a thousand times, so it is important to provide good documentation for current +and future members of the software team. The major things that we document in our code are: + +1. **Classes and Objects:** + - What does it represent? What is it used for? + - What are its member variables? What are they used for? +2. **Functions:** + - What are the inputs and outputs? + - What is the overall behavior and purpose of the function? +3. **Code:** + - Is a line of code obscure and/or not clear? Add an inline comment to clear things up. + - Break down a large process. + +Ideally, the third point should be avoided as much as possible since we would want our code to be +self explanatory. It should be done only when absolutely necessary. + +### Generating docstrings + +We use a vscode extension called [autoDocstring](https://marketplace.visualstudio.com/items?itemName=njpwerner.autodocstring){target=_blank} +which autogenerates docstrings that we use to document our code. To install this extension, go to the `Extensions` tab in +vscode and search `autoDocstring` in the marketplace. + +To generate docstrings, type `"""` at the beginning of the function that you want to document and the template +will be generated for you! If you use [type hinting](#type-hinting), this extention will autofill some of the +documentation for you! + +!!! note + + The autoDocstring extension only works for functions. It does not work for classes and objects, so documenting these + will have to be done manually. Be sure to follow the same format used by functions. + +### Example on documentation + +It's hard to imagine what good documentation looks like. We provide a few examples below of documenting code using the +autoDocstring extension. The extension uses [Google style docstrings](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings){target=_blank} +by default. + +???+ example "Documentation example on a function" + + ```python + from typing import List + def inner_product(v1 : List[float], v2 : List[float]) -> float: + """ + Computes the inner product between two 1D real vectors. Input vectors should have the + same dimensions. + + Args: + v1 (List[float]): The first vector of real numbers. + v2 (List[float]): The second vector of real numbers. + + Returns: + float : The inner product between v1 and v2 + """ + assert (len(v1) == len(v2)), "Input lists must have same length" + + # Iterate through elementwise pairs + summation = 0 + for e1, e2 in zip(v1, v2): + summation += (e1 * e2) + return float(summation) + ``` + +??? example "Documentation example with a stack" + + ```python + from typing import Any + class Stack: + + """ + This class represents a stack, which is an abstract data type that serves as a collection of + elements. The stack is a LIFO datastructure defined by two main operations: Push and Pop. + + Attributes: + __stack (List[Any]): A list containing the elements on the stack. + """ + + def __init__(self): + """ + Initializes the Stack object. + """ + self.__stack = [] + + def push(self, element : Any) -> Any: + """ + Pushes an element to the top of the stack. + + Args: + element (Any): The element to be pushed on to the stack. + """ + self.__stack.append(element) + + def pop(self) -> Any: + """ + Removes the element at the top of the stack and returns it. If the stack is empty, + then None is returned. + + Returns: + Any, NoneType: The element at the top of the stack. + """ + if self.is_empty(): + return None + else: + return self.__stack.pop() + + def is_empty(self) -> bool: + """ + Determines whether the stack is empty or not. + + Returns: + bool: Returns True if the stack is empty, and False otherwise. + """ + empty = (len(self.__stack) == 0) + return empty + + def __len__(self) -> int: + """ + Gets the number of elements on the stack. + + Returns: + int: The number of elements on the stack. + """ + length = len(self.__stack) + return length + ``` + +For more examples, see [Example Google Style Python Docstrings](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html){target=_blank}. + +[^1]: diff --git a/docs/reference/python/start.md b/docs/reference/python/start.md new file mode 100644 index 000000000..100336fcd --- /dev/null +++ b/docs/reference/python/start.md @@ -0,0 +1,21 @@ +# Getting Started + +We use Python 3 to write the majority of our software at UBC Sailbot. Pathfinding and Controls mainly use Python 3, +so it is critical that you are familiar with the language if you are on one of these sub-teams. + +## Python tutorials + +We understand that not everyone who joins Sailbot has Python in their toolkit, nor do we expect it either! Whether you +are learning Python for the first time or you just want to brush up, we have provided some resources below. You may not +learn absolutely everything from the resources below, but it is a good starting point. You will mostly learn through doing, +as you would with most technical skills! + +| Resource | Description | +| :--------------------- | :------------------------------------------------------------------------------------------ | +| [The Python Tutorial](https://docs.python.org/3/tutorial/){target=_blank} | The official python tutorial. Good if you have some time on your hands and you are a completionist. Sections 1 - 5 and 9 are the most relevant. | +| [w3schools Tutorial](https://www.w3schools.com/python/default.asp){target=_blank} | Good if you want a more brief introduction to Python. It breaks down a lot of concepts into sections. Everything up to Python Classes/Objects is relevant. | +| [YouTube Tutorial](https://youtu.be/t8pPdKYpowI){target=_blank} | If you like video tutorials, then we recommend this tutorial. This video is about 5 hours long, but it pretty much covers everything that you'll need to know for Python and there are some hands on projects. | +| [Shorter YouTube Tutorial](https://youtu.be/kqtD5dpn9C8){target=_blank} | A shorter alternative YouTube tutorial condensed into 1 hour. It covers less material but still covers many of the essentials. | +| [CodingBat Practice](https://codingbat.com/python){target=_blank} | Good resource to put your Python skills to practice on some simple coding problems. Note that this resource does not teach you python. | + +Feel free to add other resources other than the ones listed above if you find any that you like! diff --git a/docs/reference/python/virtual-environments.md b/docs/reference/python/virtual-environments.md new file mode 100644 index 000000000..7019c3a98 --- /dev/null +++ b/docs/reference/python/virtual-environments.md @@ -0,0 +1,270 @@ +# Virtual Environments + +The Python virtual environment is a tool for dependency management and project isolation. They solve many +common issues, including: + +- **Dependency Resolution:** A project might want a package with version A while another project might want +a package with version B. With a virtual environment, you can separate which packages that you want to use +for a given project. + +- **Project Isolation:** The environment for your project is self-contained and reproducible by capturing all +dependencies in a configuration file. + +- **Housekeeping:** Virtual environments allow you to keep your global workspace tidy. + +There are two main methods of creating virtual environments: [virtualenv](https://pypi.org/project/virtualenv/){target=_blank} +and [Anaconda](https://www.anaconda.com/){target=_blank}. Each have their own benefits and drawbacks. Here are some differences +between the two: + +| Virtualenv | Anaconda | +| :------------------------------------------------ | :------------------------------------------------------- | +| Environment files are local. | Environment files are available globally. | +| Must activate environment by giving the path. | Can activate the environment without knowing the path, but only the name. | +| Can only use `pip` to install packages. | Can either use `pip` or built-in `conda` package manager.| +| Installation is very simple. | Installation takes more effort. | +| Can only install python packages. | In addition to packages, you can download many data science tools.| + +We recommend **virtualenv** over Anaconda because of its simplicity. However, feel free to appeal to your preferences. + +## Installation + +=== ":material-language-python: Virtualenv" + + If you already have python and the pip package manager installed, just execute the following: + + ```bash title="Using pip to install virtualenv" + pip install virtualenv + ``` + +=== ":simple-anaconda: Anaconda" + + Go to the official [Anaconda website](https://www.anaconda.com/){target=_blank} and follow the installation + instructions for your operating system. + +## Using virtual environments + +The name of a virtual environment is configurable. For the purposes of this site, we will use `env` as the environment +name unless specified otherwise. + +### Creating a virtual environment + +=== ":material-language-python: Virtualenv" + + Since virtualenv creates the environment directory in a specific location, make sure that you + are in the located in the project that you want to work on. + + ```bash title="Create virtual environment with virtualenv" + # Go to desired location + cd + + # Create the environment with the name env + python3 -m venv env + ``` + + Verify that your environment is created by examining your current directory and look for the directory + that matches the name of your virtual environment. + +=== ":simple-anaconda: Anaconda" + + Since the environment will be available globally, there is no need to go to a specific location to create + it. + + ``` bash title="Create virtual environment with Anaconda" + # Create environment with name env and python version + conda env create -n env python= + ``` + + If you don't specify a python version, the default is the version you used when you downloaded and installed Anaconda. + Verify that your environment is created by executing `conda env list`. + +### Activating the virtual environment + +To use the virtual environment, you must activate it. + +=== ":material-language-python: Virtualenv" + + === ":material-microsoft-windows: Windows" + + ```batch title="Activation for Windows" + env\Scripts\activate + ``` + + === ":material-apple: macOS" + + ```bash title="Activation for macOS" + source env/bin/activate + ``` + === ":material-linux: Linux" + + ```bash title="Activation for Linux" + source env/bin/activate + ``` + +=== ":simple-anaconda: Anaconda" + + ```bash title="Activation for Anaconda" + conda activate env + ``` + +After activating your virtual environment, you might see `(env)` on your terminal before or after +your current line. Now you are in your virtual environment! + +### Installing dependencies + +Any dependencies that you install while your virtual environment is activated are only available in your virtual +environment. If you deactivate your environment and try to use those dependencies, you will find that you will get +errors because they will not be found unless you install those dependencies in the other environment! + +=== ":material-language-python: Virtualenv" + + Use the `pip` package manager to install python dependencies. Before installing any Python dependencies, it is good + practice to upgrade `pip`: + + ```bash title="Upgrade pip" + pip install --upgrade pip + ``` + + Now, install any Python dependencies `pip`: + + ```bash title="Install dependency with pip" + pip install + ``` + +=== ":simple-anaconda: Anaconda" + + === "Option 1: pip" + + Use the `pip` package manager to install python dependencies. + + ```bash title="Install dependency with pip" + # Install pip using conda + conda install pip + + # Install python packages using pip + pip install + ``` + + === "Option 2: conda" + + Use the built-in `conda` package manager to install python dependencies. + + ```bash title="Install dependency with conda" + conda install -c + ``` + + Sometimes, installing a package like this simply won't work because you are not installing + from the correct [channel](https://conda.io/projects/conda/en/latest/user-guide/concepts/channels.html){target=_blank}. + You usually will have to google the command to use in order to install your package correctly because + it usually comes from a specific channel that you don't know about. Some common channels to try are: + + - conda-forge + - anaconda + - bioconda + - r + +### Deactivating the virtual environment + +When you are finished using your virtual environment, you will need to deactivate it. + +=== ":material-language-python: Virtualenv" + + ```bash title="Deactivate virtualenv environment" + deactivate + ``` + +=== ":simple-anaconda: Anaconda" + + ```bash title="Deactivate anaconda environment" + conda deactivate + ``` + +## Reproducing your virtual environment + +When you want to share your code with others, it is important for others to be able to reproduce the environment +that you worked in. We discuss two topics in this section: exporting your environment and reproducing the environment. + +### Exporting your virtual environment + +In order to reproduce your virtual environment, you need to export some information about your environment. +Be sure to follow the instructions below **while your environment is activated**. + +=== ":material-language-python: Virtualenv" + + You will create a `requirements.txt` file, which essentially lists all of your python dependencies in one + file: + + ```bash title="Creating requirements file" + pip freeze > requirements.txt + ``` + + The `pip freeze` command prints all of your pip dependencies, and `> requirements.txt` redirects the output + to a text file. + +=== ":simple-anaconda: Anaconda" + + Anaconda uses configuration files to recreate an environment. + + === ":material-microsoft-windows: Windows" + + Execute the following command to create a file called `environment.yml`: + + ```batch title="Create config file" + conda env export > environment.yml + ``` + + Then, open the `environment.yml` file and delete the line with `prefix:`. + + === ":material-apple: macOS" + + Execute the following command to create a file called `environment.yml`: + + ```bash title="Create config file" + conda env export | grep -v "^prefix: " > environment.yml + ``` + + === ":material-linux: Linux" + + Execute the following command to create a file called `environment.yml`: + + ```bash title="Create config file" + conda env export | grep -v "^prefix: " > environment.yml + ``` + +### Reproducing the environment + +You can reproduce your virtual environment when given the information about it. The steps above tell you how +to extract the information, and now we will use that information to recreate the virtual environment. +Remember to **deactivate the current environment** before making a new environment. + +=== ":material-language-python: Virtualenv" + + We use the `requirements.txt` file that we generated earlier to recreate the environment. + + ```bash title="Recreate virtualenv environment" + # Create the new environment + python -m venv + + # Activate the environment + source /bin/activate + + # Install dependencies + pip install -r + ``` + +=== ":simple-anaconda: Anaconda" + + We use the `environment.yml` file that we generated earlier to recreate the environment. + + ```bash title="Recreate the conda environment" + # Create the new environment with the dependencies + conda env create -f -n + ``` + +## Official references + +In this section, we summarized what virtual environments are, why they are used, and how to use them. We did not +cover all of the functions of virtual environments, but feel free to consult the official references to learn +about virtual environments more in depth. + +- [Virtualenv Reference](https://docs.python.org/3/library/venv.html#module-venv){target=_blank} +- [Anaconda Reference](https://conda.io/projects/conda/en/latest/user-guide/concepts/environments.html#){target=_blank} diff --git a/docs/reference/ros.md b/docs/reference/ros.md new file mode 100644 index 000000000..139ecaee3 --- /dev/null +++ b/docs/reference/ros.md @@ -0,0 +1,94 @@ +# Robot Operating System + +Robot Operating System (ROS) is a set of software libraries and tools for building robot applications.[^1] +It provides functionality for hardware abstraction, device drivers, communication between processes over +multiple machines, tools for testing and visualization, and much more.[^2] + +We use ROS because it is open-source, language-agnostic, and built with cross-collaboration in mind. +It enables our sub-teams to work independently on well-defined components of our software system +without having to worry about the hardware it runs on or the implementation of other components. + +[The official ROS 2 documentation](https://docs.ros.org/en/humble/index.html){target=_blank} contains everything you need +to get started using ROS. From it we have hand-picked the resources that are most relevant to our current and expected +future usage of ROS assuming that you use [our preconfigured workspace](https://github.com/UBCSailbot/sailbot_workspace){target=_blank}. +To run our software on your device without our workspace, you would have to [install ROS](https://docs.ros.org/en/humble/Installation.html){target=_blank} +and the dependencies that are in [our Docker images](https://github.com/UBCSailbot/sailbot_workspace/tree/main/.devcontainer){target=_blank} +yourself. + +## Workspace Configuration + +To get our workspace configuration running on your computer: + +1. Set it up by following the [setup instructions](../current/sailbot_workspace/setup.md) +2. Uncomment the ROS 2 tutorials section in [`.devcontainer/Dockerfile`](https://github.com/UBCSailbot/sailbot_workspace/blob/main/.devcontainer/Dockerfile){target=_blank}, + then run the "Dev Containers: Rebuild Container" VS Code command, to install the tutorials' dependencies +3. Uncomment the ROS 2 tutorials section in [`src/polaris.repos`](https://github.com/UBCSailbot/sailbot_workspace/blob/main/src/polaris.repos){target=_blank}, + then run the "setup" VS Code task, to clone the repositories used in the tutorials + +Our workspace configuration contains easier methods of accomplishing some of the tutorial steps, or eliminates the need +for them altogether. + +| Tutorial step | Sailbot Workspace configuration | +| ----------------------------------- | ----------------------------------------------------------------------- | +| Install a package | All packages used in the tutorials are already installed (step 2 above) | +| Clone a sample repo (ros_tutorials) | ros_tutorials is already cloned (step 3 above) | +| Resolve dependencies | Run the "install dependencies" VS Code task | +| Build the workspace | Run the "Build" VS Code task, AKA ++ctrl+shift+b++ | +| Source the overlay | Run the `srcnew` terminal command | +| Create a package with a node | Run the "new ament_(python\|cmake) package with a node" VS Code task | + +## Tutorials + +We encourage all software members to work through the [ROS tutorials](https://docs.ros.org/en/humble/Tutorials.html){target=_blank} +that are listed below in order. For tutorials that have both C++ and Python versions, +NET members should do the C++ version while CTRL and PATH members should do the Python version. + +- Beginner: CLI tools + - Introducing `turtlesim` and `rqt` + - Understanding nodes + - Understanding topics + - Understanding services + - Understanding parameters + - Understanding actions + - Using `rqt_console` to view logs + - Recording and playing back data +- Beginner: Client libraries + - Creating a workspace + - Creating a package + - Writing a simple publisher and subscriber (C++ or Python) + - Writing a simple service and client (C++ or Python) + - Using parameters in a class (C++ or Python) + - Using `ros2doctor` to identify issues +- Intermediate + - Launch + - Testing +- Demos + - Logging + +## Concepts + +We encourage all software members to read the following documentation on key [ROS concepts](https://docs.ros.org/en/humble/Concepts.html){target=_blank}: + +- About logging and logger configuration +- About ROS 2 interfaces +- About parameters in ROS 2 + +## ROS 1 Bridge + +There are two major versions of ROS, aptly named ROS 1 and ROS 2. Our previous project, Raye, +uses ROS 1 because it was the only version available during her design process. Our new project will +use ROS 2, a complete re-design of the framework that tackles the shortcomings of ROS 1 to bring it up +to industry needs and standards.[^3] If you are curious about the changes made in ROS 2 compared to 1, +[this article](http://design.ros2.org/articles/changes.html){target=_blank} is a worthwhile read. + +ROS 2 includes the ROS 1 Bridge, a collection of packages that can be installed alongside ROS 1 to help migrate code +from ROS 1 to ROS 2. As we will be reusing parts of Raye's codebase, it is essential to know how to use these packages. +Until we are completely done with Raye, our preconfigured workspace will have ROS 1, ROS 1 Bridge, and ROS 2 installed. + +We encourage all software members work through the [ROS 1 Bridge README](https://github.com/ros2/ros1_bridge/blob/master/README.md){target=_blank}. +For PATH members, the [Migrating launch files from ROS 1 to ROS 2 page](https://docs.ros.org/en/humble/Tutorials/Launch-files-migration-guide.html){target=_blank} +will be a helpful reference when we do so. + +[^1]: +[^2]: +[^3]: diff --git a/docs/reference/sailing/ais_terms.md b/docs/reference/sailing/ais_terms.md new file mode 100644 index 000000000..7b8833131 --- /dev/null +++ b/docs/reference/sailing/ais_terms.md @@ -0,0 +1,39 @@ +# AIS Terms + +This section explains the most unfamiliar fields that we receive from the AIS. + +## MMSI a.k.a ID + +A 9-digit, unique identification number for the ship. + +## COG: Course over Ground + +The direction the boat is travelling, relative to the sea floor. This is the direction of the rate of change +of the [Track Made Good](miscellaneous.md/#track-made-good). + +This is measured with the navigational angle convention, where 0° is towards the North, and angles increase in the +clockwise direction. If we make the slight simplification of neglecting the effect of the wind, then + +- If the boatspeed is positive and there is no current, the boat's Course over Ground will be the same as the Heading. +- If the boatspeed is zero and there is positive current, the boat's Course over Ground will be the same direction as the +current is flowing. + +## SOG: Speed over Ground + +The speed the boat is travelling at, relative to the sea floor. This is the magnitude of the rate of change +of the [Track Made Good](miscellaneous.md/#track-made-good). + +$\begin{align*} +\text{SoG} &= \left|\frac{d}{dt} \overrightarrow{(\text{Track Made Good})} \right|\\ +\end{align*}$ + +If we make the slight simplification of neglecting the effect of the wind, then + +- If the boatspeed is positive and there is no current, the boat's Speed over Ground will be the same as the speed of water +hitting your hand, if you were sitting on the boat and put your hand in the water. +- If the boatspeed is zero and there is positive current, the boat's Speed over Ground will be the same speed as the +current. + +## RoT: Rate of Turn + +The angular velocity of the boat (how fast it's turning), measured in degrees per minute. diff --git a/docs/reference/sailing/boat_parts.md b/docs/reference/sailing/boat_parts.md new file mode 100644 index 000000000..10aa3d4f2 --- /dev/null +++ b/docs/reference/sailing/boat_parts.md @@ -0,0 +1,97 @@ +# Parts of a Sailboat + +This page names some important parts of a sailboat, and explains what the part is for. +Read the descriptions of the parts below, and refer to the image to see where the part fits in. + +![image](../../assets/images/sailing/parts_of_boat.jpg) + +## Hull + +The ***Hull*** is the "boat" part of the boat, which displaces water to create buoyancy. The following parts of the boat +are attached to the hull: + +- ***Keel***: The keel has a large mass on the end, which keeps the sailboat upright. The fin-like shape of the +keel provides *lateral resistance* to prevent the boat from slipping sideways through the water. +- ***Rudder***: Raye has two rudders for redundancy. The rudders can angle side to side to steer the boat. +To steer the boat effectively, the rudders need enough water flowing over them to create a pressure difference when they +angle sideways. Controls sends commands to the rudder to steer the boat. + +It is also helpful to know the names of the following "regions" of the hull: + +- ***Bow***: The front of the boat. +- ***Stern***: The back of the boat. + - *Aft* means "backwards towards the stern". +- ***Starboard***: The side of the boat which is on the **right**, for someone standing on the boat facing the bow. +- ***Port***: The side of the boat which is on the **left**, for someone standing on the boat facing the bow. + - To remember which is which between starboard and port, remember that "port" and "left" both have 4 letters. + +The image below shows a birds-eye view of the outline of a hull of a sailboat, +where the "regions" of the hull are labeled. + +![image](../../assets/images/sailing/regions_of_hull.jpg) + +## Jib + +The ***Jib*** is the sail located near the bow, and is the smaller of the two sails. + +- *Jib Sheet*: In general, *sheets* are ropes that pull a sail in to the boat, and the jib sheet does this for the jib. +On Raye, the jib sheet connects to the back bottom corner of the jib, through a pulley near the bottom of the mast to +the Jib Winch. Most sailboats have two jib sheets, one on either side, but Raye is designed differently for autonomy. +- The ***Jib Winch*** is a motor-driven device that tightens or pulls in the jib by pulling on the jib sheet. +Controls sends commands to the winches. +- The *jib halyard*: In general, a *halyard* is a rope that pulls a sail up. The jib halyard pulls up the jib. +It connects to the top of the jib, runs through a pulley near the top of the mast, and is tied off +near the bottom of the mast. + +## Mast + +The ***Mast*** is the long vertical pole which connects to hull. It holds up the sails and some instruments. + +The following instruments are at the top of the mast: + +- One of the 3 ***Wind Sensors***. The top of the mast is a good location to measure undisturbed wind. +Pathfinding and Controls both use data from the wind sensors. +- The ***AIS antenna***. AIS ("Autonomous Identification System") is a system by which ships +communicate their location, speed, and other information to surrounding ships via radio signals. +Pathfinding uses AIS data to avoid other ships. + +The mast is held upright by three lines: + +- The *forestay* connects the mast from the top of the jib to the bow, and runs parallel to the front edge of the jib. +- The two *shrouds* connect the mast from the top of the jib to the outside edges of the hull slightly aft of the mast. +There is one shroud on the startboard side and one on the port side. + +## Main Sail + +The ***Main Sail*** is the larger of the two sails, and is located aft of the mast. +Most of the boat's propulsion comes from the main sail. + +- The *Boom* is the horizontal pole that holds the bottom corner of the main sail out from the mast. +- *Main Sheet* is the rope that pulls the main sail in towards the center of the boat. It connects from the back end of +the boom, through a pulley on the stern, to the Main Winch. +- The ***Main Winch*** is a motor-driven device that pulls in the main sail by pulling on the main sheet. +Controls sends commands to the main winch. +- The *main halyard* is the line used to hoist the main sail. + +## Conclusion + +Hopefully this section helped you gain familiarity with some common sailing terms. +It likely feels like this section contains a lot of new information. It's unrealistic to remember it all perfectly, +but make an effort to remember the terms which are ***Bolded and Italicized***. + +## Keywords on this Page + +- Hull +- Keel +- Rudder +- Bow +- Stern +- Starboard +- Port +- Jib +- Jib winch +- Mast +- Wind Sensor +- AIS Antenna +- Main Sail +- Main Winch diff --git a/docs/reference/sailing/miscellaneous.md b/docs/reference/sailing/miscellaneous.md new file mode 100644 index 000000000..7dacc869f --- /dev/null +++ b/docs/reference/sailing/miscellaneous.md @@ -0,0 +1,121 @@ +# Miscellaneous Sailing Knowledge + +This section covers some other useful information. + +## Wind Direction Convention + +Generally speaking, there are two ways to use an angle to describe the wind direction. + +1. The angle tells you which way the wind is **blowing towards**. For example, 0° means the wind is blowing from North +to South. +2. The angle tells you which way the wind is **coming from**. For example, 0° means the wind is blowing from South to North. + +In sailing, we normally talk about "where the wind is **coming from**". Somehow this ends up being more intuitive when +talking about maneuvers or sail angle adjustments. + +However, when describing the wind as a vector, it can make more sense for the vector to represent the actual +speed and direction the air is flowing. Make sure to document which convention you are using in your work when +its applicable, and don't be afraid to ask someone to clarify which convention they are using in their work. + +## Navigation Terms + +### Heading + +In navigation generally (outside of Sailbot), the ***Heading*** is the direction the bow of the boat is pointing +towards. Headings are typically (but not always at Sailbot) measured relative to true North in the clockwise direction. + +### Bearing + +A ***Bearing*** is used to describe one point in relation to another: the Bearing of point "A" from point "B" +is the direction you would would look towards if you wanted to see point "A" while standing at point "B". A *Range* +is the distance between points "A" and "B", so that a Bearing and Range together can locate point "A" relative to point +"B" in polar co-ordinates. There are two main ways of measuring bearings: + +- A *True Bearing* is a bearing where the angle convention is as follows: 0° is towards the **North**, +angles increase in the clockwise direction, and angles are typically bounded within [0°, 360°)] +- A *Relative Bearing* is a bearing where the angle convention is as follows: 0° is **straight forwards relative to the +boat**, and angle measurements increase in the clockwise direction. Angles may be bounded in [-180°, 180°) or [0°, 360°) + +In the example below, the boat "B" has a Heading (H) of 30°. The True Bearing ($B_t$) of the Lighthouse "A" +from the boat is 90°. The Relative Bearing ($B_r$) of the lighthouse from the boat is 60°. + +![image](../../assets/images/sailing/bearing_vs_heading.jpg) + +### Track Made Good + +Boats do not necessarily travel in the same direction as their ***Heading***, due to the effects of ocean current and +wind. The path the boat has traveled relative to the sea floor is called the ***Track Made Good***. This is the +same as if you measured motion compared to land or with a GPS. + +![image](../../assets/images/sailing/track_made_good.jpg) + +### Heading and Bearing in Raye Project + +In Sailbot's Raye project, ***Heading*** and ***Bearing*** are used to refer to different conventions for describing +which way the boat is pointing. +The following 3 pieces of information are needed to unambiguously define an angle measuring convention: + +- What does 0° mean? If 0° is North, is it **towards** the North or **away** from the North? +- Do the angle measurements increase in the clockwise or counter-clockwise direction? +- What range should the angles be bounded to? This part is often unimportant if the angles are only used in +trigonometry functions. + +Some common examples of angle measuring conventions which we use are: + +- 0° means towards the East, angles increase in the counter-clockwise direction, and angles are bounded in +[-180°, 180°). This is effectively the main angle convention used in most math courses. +- 0° means towards the North, angles increase in the clockwise direction, and angles are bounded in [0°, 360°). This +angle convention is more commonly used by navigators. + +The specific angle conventions which we call Heading and Bearing can be ambiguous, and may be subject to change, +so they are deliberately omitted here. Refer to the applicable source code to determine what the angle conventions are. + +## True, Apparent, and Boat Wind + +- *True Wind* is the wind vector (speed and direction) which you would measure while standing on land (or motionless at +sea with unchanging GPS co-ordinates). In sailbot code, this may be referred to as ***Global Wind***. When people +refer to "the wind", they normally mean True Wind. +- *Boat Wind* is the wind vector which you would measure while standing on a moving boat when the True Wind speed is 0. +This means that boat wind always blows straight onto the bow of the boat, and the magnitude of the boat wind is equal to +the speed of the boat. +- ***Apparent Wind*** is the vector sum of the True Wind and the Boat Wind. This is the wind that you would measure while +standing on a moving boat more generally, even if there is non-zero wind. The apparent wind is also what our wind +sensors measure, and what our sails feel. In Sailbot code, Apparent Wind may be referred to as ***Measured Wind***. + +In the example below, suppose the wind is blowing from the North at 4 m/s, and suppose the boat is moving **towards** +the East at 3 m/s. + +- The True Wind everywhere is blowing at 4 m/s from the North +- The Boat Wind onboard the boat is blowing **from** the East at 3 m/s +- The Apparent Wind onboard the boat is has a magnitude of $\sqrt{3^2 + 4^2} = 5 \text{ m/s}$, +and is coming from a true bearing of $\arctan{(\frac{3}{4})} = 36.9°$. + +![image](../../assets/images/sailing/wind_types.jpg) + +## Tack + +In the [Types of Turn](./turning.md#tacking) +page, we discussed how a ***Tack*** is a type of turn. Weirdly, the word "tack" actually has two +more distinct meanings in sailing. The word "Tack" can refer to: + +- the type of turn, as covered before. +- *Starboard Tack* vs *Port Tack*: The tack is basically the side of the boat which is further upwind. More thoroughly, +the tack is the opposite side to the sail. This means that boats change tack when the sail switches sides. + - In the diagram below, + the 3 boats on the left of the diagram are on Starboard Tack, and the 3 boats on the right side are on Port Tack. + - The tack of a boat in *Irons* is undefined. + - The boat in the diagram on a run is on Port Tack. If the boat continued straight but the sail switched sides into + the position shown by the **dashed** line, the boat would be on Starboard Tack. + +![image](../../assets/images/sailing/tack_other_meaning.jpg) + +- Finally, the Tack can refer to particular region of the main sail. This is not important for software members. + +## Keywords on this Page + +- Heading +- Bearing +- Track Made Good +- Global Wind (aka True Wind) +- Measured Wind (aka Apparent Wind) +- Tack diff --git a/docs/reference/sailing/overview.md b/docs/reference/sailing/overview.md new file mode 100644 index 000000000..400a63184 --- /dev/null +++ b/docs/reference/sailing/overview.md @@ -0,0 +1,10 @@ +# Sailing Knowledge Section Overview + +In order to make high-quality contributions to Sailbot's Software teams, it is extremely helpful to have some +understanding of sailing. This section introduces important parts of a sailboat, explains the 4 types of turns, +discusses upwind and downwind sailing, and covers some other helpful knowledge. + +In this section, terms which are ***Bolded and Italicized*** are the most important terms to know. +These terms are listed at the bottom of each page. +Terms that are only *Italicized* are other helpful sailing terms. +Words that are **bolded** are meant to be emphasized, but are not necessarily considered important vocabulary. diff --git a/docs/reference/sailing/points_of_sail.md b/docs/reference/sailing/points_of_sail.md new file mode 100644 index 000000000..348cd6780 --- /dev/null +++ b/docs/reference/sailing/points_of_sail.md @@ -0,0 +1,47 @@ +# Points of Sail + +In sailing, we sometimes talk about different angles that we can sail on with respect to the wind. +Ranges of angles which are close together have special names. These ranges are called *points of sail*. +The discussion below coveres the most important points of sail for software members to understand. + +Notice how for *higher* points of sail (points of sail closer to straight into the wind), the sail is pulled tightly +in to the boat. If the boat is on a *lower* point of sail, the sails should be let further out of the boat. For any +point of sail, there is an optimum angle that the sail should be adjusted to. If the sails are adjusted too far in +or too far out, the boat will not go as fast as it could if the sails were adjusted correctly. + +![image](../../assets/images/sailing/points_of_sail.jpg) + +## Irons + +The range of angles where the boat is roughly pointing straight into the wind are called ***Irons***, or the +***No-Go Zone***. +If the boat is pointing in these directions, the sails will be flapping regardless of how the sheets are adjusted. +When the sails are flapping, they are not catching the wind in a way that can propell the boat forwards. +When the boat looses propulsion, water stops flowing over the rudder, and the boat loses steering. +This is why we want our sailbots to avoid being stuck in irons. + +## Upwind Sailing + +If we want to sail to a destination that is not on too high or low of an angle upwind or downwind from our starting +position, we can just point our boat in that direction, adjust our sails, and go there. + +However, sometimes we want to sail to a destination that is straight upwind of our starting position. +To get there, we will need to do upwind sailing. +Since we can't point our boat directly into the wind, we need to sail on an angle on the edge of irons. +We will need to tack back and forth every now and then if we want to go directly upwind. +The point of sail on the edge of Irons is called ***Close Hauled***. + +## Downwind Sailing + +Raye also avoids sailing straight downwind. This means that to reach a goal downwind of the starting position, +we need to gybe back and forth in a zig-zag pattern. The point of sail straight +downwind is called a *run*, and the next point of sail higher than a *run* is called a *broad reach*. + +![image](../../assets/images/sailing/upwind_downwind_sailing.jpg) + +## Keywords on this Page + +- Irons (aka No-Go Zone) +- Upwind Sailing +- Close Hauled +- Downwind Sailing diff --git a/docs/reference/sailing/turning.md b/docs/reference/sailing/turning.md new file mode 100644 index 000000000..b9257bbf0 --- /dev/null +++ b/docs/reference/sailing/turning.md @@ -0,0 +1,111 @@ +# Types of Turns + +In sailing, there are 4 distinct types of turns. Read the descriptions below, and observe how they fit into the diagrams. + +Note that any of these types of turn can be done in either the clockwise or counter-clockwise directions. + +## Classifying Types Of Turns Summary + +The following flowchart summarizes how to distinguish between different types of turns. Note: + +- to point ***higher*** means to steer your boat to point in a direction closer to straight into the wind +- to point ***lower*** means to steer your boat to point in a direction closer towards to straight downwind + +``` mermaid +graph LR + B[Classify a Turn] --> C{Does the sail change
sides during the turn?}; + C --> |Yes| E{Which end of
the boat is upwind
during the turn?}; + C --> |No| D{Does the
boat point higher
or lower at the end
of the turn?}; + D --> |Higher| F[Heading Up]; + D --> |Lower| G[Bearing Off]; + E --> |Bow| H[Tack]; + E --> |Stern| I[Gybe]; +``` + +The diagrams in this section show outlines of the hull of a boat and its main sail going through turns. +As is common in these types of diagrams, assume that the wind is blowing down from the top of the screen unless +there is an arrow that indicates otherwise. + +![image](../../assets/images/sailing/types_of_turn.jpg) + +## Heading Up + +When the boat makes any turn as follows, it is called ***Heading Up***: + +- At the end of the turn, the boat is pointing *higher*. +- Throughout the turn, the sails stay on the same side of the boat. In other words, the sails do **not** cross between +the starboard and port sides. + +Unlike some of the other turns listed here, heading up can be a large turn or a small course adjustment of just a few +degrees. + +The image below shows a boat heading up. Notice how the sail stays on the starboard side of the boat. + +![image](../../assets/images/sailing/head_up.jpg) + +## Bearing Off + +When the boat makes any turn as follows, it is called ***Bearing Off***: + +- At the end of the turn, the boat is pointing *lower*. +- Throughout the turn, the sails stays on the same side of the boat (port or starboard). + +Like heading up, bearing off can be a small course adjustment. + +![image](../../assets/images/sailing/bear_off.jpg) + +## Tacking + +When the boat makes any turn as follows, it is called a ***Tack*** or ***Tacking***: + +- The sails change sides. +- Through the turn, the wind hits the **bow** of the boat before the stern. You can also say that the bow is *upwind* or +*windward* of the stern. + +Notice how at some point throughout this turn, the boat will be pointing straight into the wind. +While the boat points nearly straight into the wind, the sails don't generate any forward propulsion. +This means that a tack must be a large (at least ~90°) turn all at once, so that the boat's momentum carries it through +the range of angles where it does not get propulsion. + +![image](../../assets/images/sailing/tack.jpg) + +## Gybing + +When the boat makes any turn as follows, it is called a ***Gybe*** or ***Gybing***. + +- The sails change sides. +- Through the turn, the wind hits the **stern** of the boat before the bow. You can also say that the bow of the boat is +*downwind* or *leeward* of the stern. + +When sailing on most angles relative to the wind, the sail is always blown to the downwind side of the boat. +However, sailing nearly straight downwind, both sides of the boat are equally "downwind" relative to eachother. +This means that the sail can be on either side of the boat. + +The sail propells the boat throughout a gybe, so it is possible to conduct the turn more gradually than a tack. +However, because the sail can be on either side, the sails can switch sides in an uncontrolled way as the boat moves in +the waves. For this reason, Raye avoids sailing on angles close to straight downwind, and gybes by doing a quick ~60° +turn. + +Note that "gybe" is the spelling used in Canadian and British english, whereas in American english it is spelled "**Jibe**" + +![image](../../assets/images/sailing/gybe.jpg) + +## Combinations of Turns + +Of course, it is possible to do two or more of these types of turns in one continuous motion. +What two types of turns does the boat do in the image below? + +![image](../../assets/images/sailing/bear_off_then_gybe.jpg) + +Answer: In the turn shown by the first arrow, the sail stays on the port side of the boat while it steers to point further +downwind. This means that the first part of the maneuver is **bearing off**. In the next part of the maneuver, the sail +changes sides and the stern of the boat is upwind of the bow. This part of the maneuver is a **gybe**. + +## Keywords on this Page + +- Higher (in relation to pointing) +- Lower (in relation to pointing) +- Heading Up +- Bearing Off +- Tack +- Gybe (aka Jibe) diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 000000000..b8f560561 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,5 @@ +cairosvg +mkdocs-git-revision-date-localized-plugin==1.* +mkdocs-material==9.* +mike +pillow diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 000000000..3c68478c4 --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,26 @@ +:root > * { + --md-primary-fg-color: #1665a2; + --md-primary-fg-color--light: #73a3c7; + --md-primary-fg-color--dark: #0d3d61; +} + +[data-md-color-scheme="slate"] { + --md-hue: 200; +} + +/* Styling for left navigation panel*/ +.md-sidebar__inner > .md-nav > .md-nav__list > .md-nav__item > .md-nav__link { color: #2f97ec; } +.md-nav__link:hover { color: #2f97ec; } +.md-nav__link.md-nav__link--active { color: #2f97ec; } + +/* Styling for links embedded in text*/ +.md-content__inner a {color: #2f97ec;} +.md-content__inner a:hover {color: #2f97ec;} +.md-content__inner a:focus {color: #2f97ec;} + +/* Styling for right navigation panel (Table of Contents) controlled by javascripts/table_of_contents_themes.js */ +nav.md-nav.md-nav--secondary > .md-nav__list > .md-nav__item > .md-nav__link {color: var(--md-table-of-contents-link-color);} +nav.md-nav.md-nav--secondary > .md-nav__list > .md-nav__item > .md-nav__link:hover {color: #2f97ec;} +nav.md-nav.md-nav--secondary > .md-nav__list > .md-nav__item > .md-nav__link.md-nav__link--passed.md-nav__link--active {color: #2f97ec;} +.md-nav__link--passed {color: var(--md-table-of-contents-link-color);} +.md-nav__link--passed:hover {color: #2f97ec;} diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 000000000..4d981e893 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,176 @@ +# Project information +site_name: UBCSailbot Software Team Docs +site_url: https://UBCSailbot.github.io/docs/ +site_author: UBCSailbot Software Team + +# Repository +repo_name: UBCSailbot/docs +repo_url: https://github.com/UBCSailbot/docs +edit_uri: "edit/main/docs/" + +# Configuration +theme: + name: material + custom_dir: docs/overrides + logo: assets/ubcsailbot-white.png + features: + - content.action.edit + - content.action.view + - content.code.annotate + - content.code.copy + - content.tabs.link + - navigation.expand + - navigation.footer + - navigation.instant + - navigation.tabs + - navigation.tabs.sticky + - navigation.top + - search.highlight + - search.share + - search.suggest + - toc.follow + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/brightness-4 + name: Switch to light mode + +# Plugins +plugins: + - git-revision-date-localized: + timezone: America/Vancouver + - search: + separator: '[\s\-,:!=\[\]()"/]+|(?!\b)(?=[A-Z][a-z])|\.(?!\d)|&[lg]t;' + - social: + cards_layout_options: + background_color: "#1665A2" + +# Customization +extra: + social: + - icon: material/sail-boat + link: https://www.ubcsailbot.org/ + - icon: material/instagram + link: https://www.instagram.com/ubcsailbot/ + - icon: material/linkedin + link: https://www.linkedin.com/company/ubc-sailbot/ + - icon: material/github + link: https://github.com/UBCSailbot + - icon: material/email + link: mailto:software@ubcsailbot.org + version: + provider: mike + +extra_css: + - stylesheets/extra.css + +extra_javascript: + - javascripts/mathjax.js + - javascripts/table_of_contents_themes.js + - https://polyfill.io/v3/polyfill.min.js?features=es6 + - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js + +# Extensions +markdown_extensions: + # Python Markdown + - abbr + - admonition + - attr_list + - def_list + - footnotes + - md_in_html + - toc: + permalink: true + + # Python Markdown Extensions + - pymdownx.arithmatex: + generic: true + - pymdownx.betterem: + smart_enable: all + - pymdownx.caret + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + options: + custom_icons: + - overrides/.icons + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.keys + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.snippets: + url_download: true + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tabbed: + alternate_style: true + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.tilde + +# Page tree +nav: + - Home: index.md + - Current Project: + - Overview: current/overview.md + - Sailbot Workspace: + - Overview: current/sailbot_workspace/overview.md + - Setup: current/sailbot_workspace/setup.md + - Parameters: current/sailbot_workspace/parameters.md + - Workflow: current/sailbot_workspace/workflow.md + - How-To's: current/sailbot_workspace/how_to.md + - Deployment: current/sailbot_workspace/deployment.md + - Images: current/sailbot_workspace/docker_images.md + - Launch Files: current/sailbot_workspace/launch_files.md + - Boat Simulator: + - Overview: current/boat_simulator/overview.md + - Controller: + - Overview: current/controller/overview.md + - Custom Interfaces: + - Overview: current/custom_interfaces/overview.md + - Docs: + - Overview: current/docs/overview.md + - Local Pathfinding: + - Overview: current/local_pathfinding/overview.md + - Network Systems: + - Overview: current/network_systems/overview.md + - Notebooks: + - Overview: current/notebooks/overview.md + - Website: + - Overview: current/website/overview.md + - Reference: + - C++: + - Getting Started: reference/cpp/start.md + - Differences: reference/cpp/differences.md + - Tools: reference/cpp/tools.md + - GitHub: + - Development Workflow: + - Overview: reference/github/workflow/overview.md + - Creating Issues: reference/github/workflow/issues.md + - Developing on Branches: reference/github/workflow/branches.md + - Pull Requests: reference/github/workflow/pr.md + - Markdown: reference/markdown.md + - Python: + - Getting Started: reference/python/start.md + - Conventions: reference/python/conventions.md + - Virtual Environments: reference/python/virtual-environments.md + - Robot Operating System: reference/ros.md + - Sailing Knowledge: + - Overview: reference/sailing/overview.md + - Parts of a Sailboat: reference/sailing/boat_parts.md + - Types of Turns: reference/sailing/turning.md + - Points of Sail: reference/sailing/points_of_sail.md + - AIS Terms: reference/sailing/ais_terms.md + - Miscellaneous: reference/sailing/miscellaneous.md diff --git a/sailbot.code-workspace b/sailbot.code-workspace index f0596ea67..7d4c06398 100644 --- a/sailbot.code-workspace +++ b/sailbot.code-workspace @@ -3,6 +3,9 @@ { "path": "." }, + { + "path": "docs" + }, { "path": "src/boat_simulator" }, @@ -15,9 +18,6 @@ { "path": "src/diagnostics" }, - { - "path": "src/docs" - }, { "path": "src/global_launch" }, @@ -58,7 +58,11 @@ "autopep", "bsoncxx", "buildx", + "Clangd", "cmake", + "completionist", + "conda", + "cout", "cppcheck", "cppdbg", "cpplint", @@ -66,8 +70,12 @@ "deque", "devcontainer", "dtype", + "endl", "gaurav", + "gtest", + "ighxy", "ints", + "iostream", "isort", "kmph", "mkdocs", @@ -76,6 +84,7 @@ "noqa", "OMPL", "pallete", + "Protobuf", "protofiles", "pytest", "Raye", @@ -83,17 +92,28 @@ "rclpy", "rcutils", "repos", + "roscd", "rosdep", "rosdistro", "rosidl", + "roslaunch", + "rosrun", "RTPS", "srcnew", "srcraye", + "struct", + "Structs", "ubcsailbot", "uncrustify", + "virtualenv", "Wextra", "Wpedantic", - "xmllint" + "xcalc", + "xhost", + "xinit", + "xinitrc", + "xmllint", + "xorg" ], "editor.inlayHints.enabled": "off", "editor.renderWhitespace": "trailing", @@ -258,8 +278,11 @@ "https://squidfunk.github.io/mkdocs-material/schema.json": "mkdocs.yml" }, "yaml.customTags": [ - "tag:yaml.org,2002:python/name:materialx.emoji.twemoji", - "tag:yaml.org,2002:python/name:materialx.emoji.to_svg", + "!ENV scalar", + "!ENV sequence", + "!relative scalar", + "tag:yaml.org,2002:python/name:material.extensions.emoji.to_svg", + "tag:yaml.org,2002:python/name:material.extensions.emoji.twemoji", "tag:yaml.org,2002:python/name:pymdownx.superfences.fence_code_format" ], diff --git a/src/polaris.repos b/src/polaris.repos index 65bc55fa0..1801e178a 100644 --- a/src/polaris.repos +++ b/src/polaris.repos @@ -37,11 +37,6 @@ repositories: url: https://github.com/UBCSailbot/diagnostics version: main - docs: - type: git - url: https://github.com/UBCSailbot/docs - version: main - local_pathfinding: type: git url: https://github.com/UBCSailbot/local_pathfinding