From 88d78bab4b747fc976ac97231407408ca8d2329f Mon Sep 17 00:00:00 2001 From: ci-bot Date: Sat, 2 Nov 2024 22:38:07 +0000 Subject: [PATCH] Deployed 1df7584f to pr-454 with MkDocs 1.6.1 and mike 2.1.3 --- .../current/sailbot_workspace/reference/parameters/index.html | 4 +++- pr-454/search/search_index.json | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pr-454/current/sailbot_workspace/reference/parameters/index.html b/pr-454/current/sailbot_workspace/reference/parameters/index.html index 3cf17036..e175dd7c 100644 --- a/pr-454/current/sailbot_workspace/reference/parameters/index.html +++ b/pr-454/current/sailbot_workspace/reference/parameters/index.html @@ -2613,9 +2613,11 @@

physics_engine_nodeWelcome to the UBC Sailbot software team docs

Looking to get started with running the Sailbot codebase? Start by setting up the Sailbot Workspace:

Getting Started

"},{"location":"#what-information-is-on-this-website","title":"What information is on this website?","text":"

Information on our current project is contained on this website. In particular, information on each of our major software projects are provided in detail.

Current Project Overview

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.

Software Team References

"},{"location":"#who-is-this-website-for","title":"Who is this website for?","text":"

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.

"},{"location":"#prospective-members","title":"Prospective Members","text":"

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!

Software Team Posting

Apply to join UBC Sailbot

"},{"location":"about_us/","title":"About Us","text":"

UBC Sailbot is an engineering design team at The University of British Columbia that designs, constructs, and tests autonomous sailboats. We have 3 technical sub-teams: Mechanical, Electrical, and Software.

This repository, sailbot_workspace, contains all the code, infrastructure, and documentation for the project we are currently working on, Polaris.

To learn more about what the UBC Sailbot Software Team does, read our Team Posting. If you are a UBC student interested in joining, you can apply here.

"},{"location":"current/overview/","title":"Current Project Overview","text":"

Our current project, Polaris, is an autonomous research vessel capable of collecting oceanic and atmospheric data. With our expertise in autonomous sailing, the goal is to monitor the health of our oceans while collaborating with stakeholders and researchers involved in climate science and oceanography.

The software team is responsible for designing, implementing, and testing the software system of our autonomous sailboats. We work on both low-level and high-level integration, from interfacing with sensors to planning sea routes with pathfinding algorithms.

"},{"location":"current/overview/#dataflow","title":"Dataflow","text":"

The software architecture for our next autonomous sailboat is split across two computers: the on board computer on board and the remote server off board. The following paragraphs will follow the flow of data between the software components (bolded) on each computer.

On the remote server, global pathfinding uses the A* pathfinding algorithm to create a sailing path, a list of global waypoints from the current position to destination. Global sailing paths are sent via the Remote Transceiver to the Local Transceiver on the on board computer.

On the on board computer, the CAN Transceiver receives GPS and wind data from their respective sensors. This raw data is filtered before being used in the other software components. Local Pathfinding uses GPS and wind data, as well as the global path and AIS data from the AIS Receiver, to create a local path, a list of local waypoints from the current position to the next global waypoint. The Controller uses wind data and the relative bearing to the local path to adjust the rudder and sails accordingly. The state of the boat and research data we collect is sent via the Local Transceiver to the Remote Transceiver on the remote server.

Back on the remote server, the Website presents the boat state and research data for monitoring and analysis purposes. The Remote Transceiver additionally includes manual overrides such as resetting the boat state and modifying the global path.

As for the communication mediums, the computers communicate via satellite, and components on the on board computer communicate through the Robot Operating System framework, or ROS for short.

For software development purposes, all software components will be able to run and communicate with each other locally. To accomplish this, we will:

  1. Create a development environment that has all software component dependencies: Sailbot Workspace.
  2. Develop accurate simulations of the environment and hardware: Simulator, Mock AIS, Mock Global Pathfinding.
  3. Add configuration options to select between real and simulated hardware as well as running remote server components remotely or locally.
"},{"location":"current/overview/#diagrams","title":"Diagrams","text":"

In these diagrams, the bubbles represent components of our software system, and the direction of arrows connecting the bubbles represent the flow of data between them. The color of the bubbles denote the sub-team leading their development:

  • Purple: Controls
  • Green: Network Systems
  • Blue: Pathfinding
  • Red: Website
  • White: Not a part of the Software Team's codebase

Components that are used in both the production and development environments are darker, while ones that are only used in one are lighter.

Interacting with the diagram

  • To switch between the production and development environment diagrams, hover over the image to make the toolbar visible and navigate with the arrows on the left side
"},{"location":"current/boat_simulator/overview/","title":"Overview","text":"

Source code

The source code for Boat Simulator can be found in src/boat_simulator. Its README has been copied below.

"},{"location":"current/boat_simulator/overview/#ubc-sailbot-boat-simulator","title":"UBC Sailbot Boat Simulator","text":"

UBC Sailbot's boat simulator for the new project. This repository contains a ROS package boat_simulator. This README contains only setup and run instructions. Further information on the boat simulator can be found on the software team's docs website.

"},{"location":"current/boat_simulator/overview/#setup","title":"Setup","text":"

The boat simulator is meant to be ran inside the Sailbot Workspace development environment. Follow the setup instructions for the Sailbot Workspace here to get started and build all the necessary ROS packages.

"},{"location":"current/boat_simulator/overview/#run","title":"Run","text":"

The launch/ folder contains a ROS 2 launch file responsible for starting up the boat simulator. To run the boat simulator standalone, execute the launch file after building the boat_simulator package:

ros2 launch boat_simulator main_launch.py [OPTIONS]...\n

To see a list of options for simulator configuration, add the -s flag at the end of the above command.

"},{"location":"current/boat_simulator/overview/#test","title":"Test","text":"

Run the test task in the Sailbot Workspace. See here on how to run vscode tasks.

"},{"location":"current/controller/overview/","title":"Overview","text":"

Source code

The source code for Controller can be found in src/controller. Its README has been copied below.

"},{"location":"current/controller/overview/#controller","title":"Controller","text":"

UBC Sailbot's controller for the new project. This repository contains a ROS package controller. This README contains only setup and run instructions. Further information on the controller can be found on the software team's docs website.

"},{"location":"current/controller/overview/#setup","title":"Setup","text":"

The controller is meant to be ran inside the Sailbot Workspace development environment. Follow the setup instructions for the Sailbot Workspace here to get started and build all the necessary ROS packages.

"},{"location":"current/controller/overview/#run","title":"Run","text":"

The launch/ folder contains a ROS 2 launch file responsible for starting up the controller. To run the controller standalone, execute the launch file after building the controller package:

ros2 launch controller main_launch.py [OPTIONS]...\n

To see a list of options for configuration, add the -s flag at the end of the above command.

"},{"location":"current/controller/overview/#test","title":"Test","text":"

Run the test task in the Sailbot Workspace. See here on how to run vscode tasks.

"},{"location":"current/custom_interfaces/overview/","title":"Overview","text":"

Source code

The source code for Custom Interfaces can be found in src/custom_interfaces. Its README has been copied below.

"},{"location":"current/custom_interfaces/overview/#custom-interfaces","title":"Custom Interfaces","text":"

UBC Sailbot's custom interfaces ROS package. To add custom_interfaces to another ROS package, follow the instructions here.

The terminology that we use in this document are the following:

  • External Interface: An interface used to communicate data between nodes and ROS packages.
  • Internal Interface: An interface used to standardize conventions across external interfaces. Standards are documented in the .msg or .srv file associated with that interface.
"},{"location":"current/custom_interfaces/overview/#project-wide-interfaces","title":"Project-wide Interfaces","text":"

ROS messages and services used across many ROS packages in the project.

"},{"location":"current/custom_interfaces/overview/#project-wide-external-interfaces","title":"Project-wide External Interfaces","text":""},{"location":"current/custom_interfaces/overview/#project-wide-internal-interfaces","title":"Project-wide Internal Interfaces","text":"Interface Used In HelperAISShip AISShips HelperBattery Batteries HelperDimension HelperAISShip HelperGenericSensor GenericSensors HelperHeading DesiredHeading, GPS, HelperAISShip HelperLatLon GPS, HelperAISShip, Path HelperROT HelperAISShip HelperSpeed GPS, HelperAISShip, WindSensor"},{"location":"current/custom_interfaces/overview/#boat-simulator-interfaces","title":"Boat Simulator Interfaces","text":"

ROS messages and services used in our boat simulator.

"},{"location":"current/custom_interfaces/overview/#boat-simulator-external-interfaces","title":"Boat Simulator External Interfaces","text":"Topic Type Publisher Subscriber(s) mock_kinematics SimWorldState Simulator Physics Engine Simulator Visualizer"},{"location":"current/custom_interfaces/overview/#boat-simulator-actions","title":"Boat Simulator Actions","text":"Action Client Node Server Node SimRudderActuation Simulator Physics Engine Simulator Low Level Controller SimSailTrimTabActuation Simulator Physics Engine Simulator Low Level Controller"},{"location":"current/custom_interfaces/overview/#resources","title":"Resources","text":""},{"location":"current/custom_interfaces/overview/#common-interfaces","title":"Common Interfaces","text":"

The ROS2 common_interfaces repository defines a set of packages which contain common interface files. Since we are using the Humble version of ROS2, see the humble branch. These interfaces can be used in this repository or as a reference for ideas and best practices.

Package Possible Usage diagnostic_msgs Could be used for website sensors geometry_msgs Simulator, Local Pathfinding sensor_msgs Reference for CAN Transceiver std_msgs Reference std_srvs Reference visualization_msgs Reference

For more detail on the usefulness of each package, see this issue comment. If you are interested in creating your own custom message or service, see the ROS Humble documentation.

"},{"location":"current/local_pathfinding/overview/","title":"Overview","text":"

Source code

The source code for Local Pathfinding can be found in src/local_pathfinding. Its README has been copied below.

"},{"location":"current/local_pathfinding/overview/#local-pathfinding","title":"Local Pathfinding","text":"

UBC Sailbot's local pathfinding ROS package

"},{"location":"current/local_pathfinding/overview/#run","title":"Run","text":"

Using main launch file: ros2 launch local_pathfinding main_launch.py

"},{"location":"current/local_pathfinding/overview/#launch-parameters","title":"Launch Parameters","text":"

Launch arguments are added to the run command in the format <name>:=<value>.

name description value log_level Logging level A severity level (case insensitive)"},{"location":"current/local_pathfinding/overview/#server-files","title":"Server Files","text":"

The server files: get_server.py and post_server.py are basic http server files which are used for testing the global_path module's GET and POST methods.

"},{"location":"current/network_systems/overview/","title":"Overview","text":"

Source code

The source code for Network Systems can be found in src/network_systems. Its README has been copied below.

"},{"location":"current/network_systems/overview/#network-systems","title":"Network Systems","text":"

This repository contains the source code for all of UBC Sailbot's Network Systems programs. It is made to work as part of Sailbot Workspace, and is not meant to be built as an independent project.

"},{"location":"current/network_systems/overview/#setup","title":"Setup","text":"

For comprehensive setup instructions, follow our setup guide.

"},{"location":"current/network_systems/overview/#building","title":"Building","text":"

Option A: With sailbot_workspace open, invoke the VSCode build or debug task.

Option B: Run /workspaces/sailbot_workspace/build.sh

"},{"location":"current/network_systems/overview/#running","title":"Running","text":""},{"location":"current/network_systems/overview/#ros-launch","title":"ROS Launch","text":"

Instructions found here.

For example:

ros2 launch network_systems main_launch.py\n

This is the best option if multiple modules need to be run at once. Launch configurations are found under the config folder. These configurations define which modules to enable/disable and what parameters to use.

"},{"location":"current/network_systems/overview/#ros-run","title":"ROS Run","text":"

If you just want to run a single module, then this is a direct and easy way to do it.

For example:

ros2 run network_systems example --ros-args -p enabled:=true\n
"},{"location":"current/network_systems/overview/#binary","title":"Binary","text":"

Not recommended as you cannot pass ROS parameters, so modules may not work by default. Binaries for each module found under projects can be found under /workspaces/sailbot_workspace/build/network_systems/projects/{module_name}/{module_name}.

For example:

/workspaces/sailbot_workspace/build/network_systems/projects/example/example\n
"},{"location":"current/network_systems/overview/#testing","title":"Testing","text":"

Unit tests specific to Network Systems is done using GoogleTest. Unit tests are defined per module. For example, under projects/example/test/.

"},{"location":"current/network_systems/overview/#run-all-tests","title":"Run All Tests","text":"

Option A: With sailbot_workspace open, invoke the VSCode test task.

Option B: Under the sailbot_workspace directory, run /workspaces/sailbot_workspace/scripts/test.sh

Both options will run all of UBC Sailbot's tests, including those from other projects. More often than not, this is unnecessary.

"},{"location":"current/network_systems/overview/#run-and-debug-specific-tests","title":"Run and Debug Specific Tests","text":"

This is the preferred way to run and debug tests. When you open a test source file like the example's, there will be green arrows next to each TEST_F macro. Clicking a double green arrow runs a test suite, while clicking single green arrow runs one unit test. Right clicking either arrow will open a prompt with a debug test option. When running a test via the debug option, we can set breakpoints and step through our code line by line to resolve issues.

This convenient testing frontend is thank's to the TestMate extension.

Warning: Large failing tests can crash VSCode. If this happens, either lower the size of the tests (ex. reduce the number of iterations) or run the test binary directly.

"},{"location":"current/network_systems/overview/#run-test-binaries","title":"Run Test Binaries","text":"

Test binaries for each module found under projects can be found under /workspaces/sailbot_workspace/build/network_systems/projects/{module_name}/test_{module_name}.

For example:

/workspaces/sailbot_workspace/build/network_systems/projects/example/test_example\n
"},{"location":"current/sailbot_workspace/overview/","title":"Overview","text":"

Source code

The Sailbot Workspace README has been copied below.

"},{"location":"current/sailbot_workspace/overview/#sailbot-workspace","title":"Sailbot Workspace","text":"

This repository will get you set up to develop UBCSailbot's software on VS Code. It is based on athackst's vscode_ros2_workspace.

"},{"location":"current/sailbot_workspace/overview/#features","title":"Features","text":"

An overview of Sailbot Workspace's features can be found below. See our docs site for how to use these features.

"},{"location":"current/sailbot_workspace/overview/#style","title":"Style","text":"

C++ and Python linters and formatters are integrated into Sailbot Workspace:

  • ament_flake8
  • ament_lint_cmake
  • ament_xmllint
  • black
  • clang-tidy
  • isort

The ament linters are configured to be consistent with the ROS style guide.

"},{"location":"current/sailbot_workspace/overview/#dev-container","title":"Dev Container","text":"

Dev Containers enable us to use a Docker container as a fully-featured development environment containing all our configuration and dependencies. Our Dev Container configuration can be found in .devcontainer/.

"},{"location":"current/sailbot_workspace/overview/#multi-root-workspace","title":"Multi-Root Workspace","text":"

Workspaces are VS Code instances that contain one or more folders. Our workspace configuration file can be found at sailbot.code-workspace.

Our software spans many repositories: software team repositories. Multi-root workspaces make it easy to work with multiple repositories at the same time. Our roots are defined in the folders section of our workspace file.

"},{"location":"current/sailbot_workspace/overview/#debugging","title":"Debugging","text":"

Launch configurations have been created to debug our software. They are defined in the launch section of our workspace file.

"},{"location":"current/sailbot_workspace/overview/#tasks","title":"Tasks","text":"

Tasks provide an alternative to memorizing the multitude of CLI commands we use to setup, build, lint, test, and run our software. They are defined in tasks section of our workspace file.

"},{"location":"current/sailbot_workspace/overview/#continuous-integration","title":"Continuous Integration","text":"

Actions were used to build our Docker containers and lint and test our code the same way it is done locally in Sailbot Workspace on GitHub. We use a reusable workflow to create a single source of truth for our tests across all our repositories. Our CI can be found in .github/workflows/.

"},{"location":"current/sailbot_workspace/overview/#customization","title":"Customization","text":"

This repository supports user-specific configuration files. To set this up, see How to use your dotfiles.

"},{"location":"current/sailbot_workspace/overview/#run-rayes-software","title":"Run Raye's Software","text":"

Raye was our previous project. Her software can be run in the raye branch following the instructions in How to run Raye's software. The initial differences between the main and raye branches are summarized in this PR.

"},{"location":"current/sailbot_workspace/overview/#documentation","title":"Documentation","text":"

Further documentation, including setup and run instructions, can be found on our Docs website.

"},{"location":"current/sailbot_workspace/overview/#tutorial","title":"Tutorial","text":"

Disclaimer

This tutorial was done a while ago, so some parts may no longer be relevant. For the most up to date information, consult the docs pages and the software leads.

"},{"location":"current/sailbot_workspace/scripts/","title":"Scripts","text":"

Source code

Our scripts can be found in scripts. Its README has been copied below.

"},{"location":"current/sailbot_workspace/scripts/#scripts","title":"Scripts","text":""},{"location":"current/sailbot_workspace/scripts/#how-to-run","title":"how to run","text":"

All scripts in this directory should be able to be run with ./path/to/script (excluding arguments). For this to work, the script will need to have a shebang and be executable. For more details, see this tutorial.

"},{"location":"current/sailbot_workspace/scripts/#ament-lintsh","title":"ament-lint.sh","text":"

Script to lint source code in all ROS packages.

"},{"location":"current/sailbot_workspace/scripts/#buildsh","title":"build.sh","text":"

Script to build all ROS packages in the Sailbot Workspace.

"},{"location":"current/sailbot_workspace/scripts/#clang-tidysh","title":"clang-tidy.sh","text":"

Script to run Clang-Tidy using ament_clang_tidy.py.

"},{"location":"current/sailbot_workspace/scripts/#run_virtual_iridiumsh","title":"run_virtual_iridium.sh","text":"
./run_virtual_iridium.sh <(optional) webhook server url> <(optional) virtual iridium http server port>\n

Creates a pair of socat sockets $LOCAL_TRANSCEIVER_TEST_PORT and $VIRTUAL_IRIDIUM_PORT and binds the latter to a virtual iridium server running on localhost:8080, which substitutes the Rockblock HTTP server used in deployment. Allows testing of satellite code without needing physical hardware.

Optional argument - webhook server url:

  • Specify where the URL where the Remote Transceiver or whatever other HTTP server is running.
  • Default is http://127.0.0.1:8081, which assumes fully local testing.

Optional argument - virtual iridium server port

  • Specify which localhost port the virtual iridium runs on.
  • Default is 8080.

$LOCAL_TRANSCEIVER_TEST_PORT acts as the serial port for AT commands. For example, to test via CLI:

  1. ./run_virtual_iridium.sh
  2. To monitor just the $LOCAL_TRANSCEIVER_TEST_PORT without extra debug messages, in a new terminal run cat $LOCAL_TRANSCEIVER_TEST_PORT. What you see output from this command will be what the Local Transceiver reads and sends.
  3. To issue CLI commands, open a new terminal and run stty 19200 < $LOCAL_TRANSCEIVER_TEST_PORT to set the baud rate.
  4. printf \"at+sbdix\\r\" > $LOCAL_TRANSCEIVER_TEST_PORT. This command queries the (currently empty) mailbox.
  5. curl -X POST -F \"test=1234\" http://localhost:8080 (this is garbage data - it doesn't mean anything). You should see the original terminal print that it received a POST request.
  6. printf \"at+sbdix\\r\" > $LOCAL_TRANSCEIVER_TEST_PORT to view the mailbox again. It will now indicate that it has the data.

Other relevant commands include (but are not limited to):

  • at+sbdwb=<msg_length>\\r: Setup the port to receive binary data of length msg_length on next input.
  • at+sbdrb\\r: Read binary content in the mailbox.
  • at+sbdd2\\r: Clear all buffers.
"},{"location":"current/sailbot_workspace/scripts/#run-testssh","title":"run-tests.sh","text":"

Script to setup, build, and test all ROS packages.

"},{"location":"current/sailbot_workspace/scripts/#run_softwaresh","title":"run_software.sh","text":"

Script to setup, build, and run all ROS packages.

"},{"location":"current/sailbot_workspace/scripts/#setupsh","title":"setup.sh","text":"

Script to handle ROS setup.

"},{"location":"current/sailbot_workspace/scripts/#testsh","title":"test.sh","text":"

Script to run tests in all ROS packages.

"},{"location":"current/sailbot_workspace/reference/deployment/","title":"Deployment","text":"

Source code

The source code for deployment can be found in scripts/deployment. Its README has been copied below.

"},{"location":"current/sailbot_workspace/reference/deployment/#deployment","title":"Deployment","text":"

Deploying our software to our autonomous sailboat's main computer.

"},{"location":"current/sailbot_workspace/reference/deployment/#scripts","title":"Scripts","text":""},{"location":"current/sailbot_workspace/reference/deployment/#setup_bootsh","title":"setup_boot.sh","text":"

Configures programs and scripts that need to run when the main computer boots. Only needs to be run once unless the script is updated. Does not need to be rerun if any scripts or programs it targets are updated, with the exception of renaming or moving the file.

Usage:

  • Must be run as root: sudo ./setup_boot.sh
"},{"location":"current/sailbot_workspace/reference/deployment/#start_containerssh","title":"start_containers.sh","text":"

Runs our Docker Compose files. You may have to install commands like wget. Would recommend running this script in its own clone of sailbot_workspace (not the one you open in VS Code).

Usage:

  • Runs the global launch file by default: ./start_containers.sh
  • Add the --website argument to additionally run the website container
  • Add the --interactive argument to manually run commands in the sailbot workspace container
  • Add the --help argument to see all available arguments
"},{"location":"current/sailbot_workspace/reference/docker_images/","title":"Docker Images","text":"

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 Ubuntu 22.04 base-dev.Dockerfile To install ROS or OMPL Personal computer base pre-base base-dev.Dockerfile To install core dependencies Workflow dispatch local-base base base-dev.Dockerfile To install core dev dependencies Workflow dispatch dev local-base base-dev.Dockerfile To install dev dependencies Workflow dispatch Dev Container dev Dockerfile To configure the Dev Container VS Code docs mkdocs-material docs.Dockerfile To install and run docs site VS Code (optional) website javascript-node website.Dockerfile To install and run website VS Code (optional)"},{"location":"current/sailbot_workspace/reference/docs_site/","title":"Docs Site","text":"

UBCSailbot software team's documentation site. It is meant to be developed in Sailbot Workspace in conjunction with our other software, but doesn't have to be. There are instructions for both cases below.

"},{"location":"current/sailbot_workspace/reference/docs_site/#setup","title":"Setup","text":""},{"location":"current/sailbot_workspace/reference/docs_site/#setup-in-sailbot-workspace","title":"Setup in Sailbot Workspace","text":"
  1. Uncomment docs/docker-compose.docs.yml in .devcontainer/devcontainer.json
  2. Uncomment 8000:8000 in .devcontainer/docker-compose.yml
  3. Rebuild the Dev Container

Refer to How to work with containerized applications for more details.

"},{"location":"current/sailbot_workspace/reference/docs_site/#setup-standalone","title":"Setup Standalone","text":"
  1. Manually install social plugin OS dependencies

  2. Install Python dependencies

    pip install --upgrade pip pip install -Ur docs/requirements.txt

    • Can do this in a Python virtual environment
"},{"location":"current/sailbot_workspace/reference/docs_site/#run","title":"Run","text":""},{"location":"current/sailbot_workspace/reference/docs_site/#run-in-sailbot-workspace","title":"Run in Sailbot Workspace","text":"

After setup, the Docs site should be running on port 8000.

Refer to How to work with containerized applications for more details.

"},{"location":"current/sailbot_workspace/reference/docs_site/#run-standalone","title":"Run Standalone","text":"
mkdocs serve\n
"},{"location":"current/sailbot_workspace/reference/docs_site/#update-dependencies","title":"Update Dependencies","text":"

This site is built using the latest versions of dependencies in docs/requirements.txt at the time of the most recent commit to the main branch. To see exactly how the site will look when deployed, ensure your local dependencies are up to date.

"},{"location":"current/sailbot_workspace/reference/docs_site/#update-dependencies-in-sailbot-workspace","title":"Update Dependencies in Sailbot Workspace","text":"

Rebuild the Dev Container.

"},{"location":"current/sailbot_workspace/reference/docs_site/#update-dependencies-by-itself","title":"Update Dependencies By Itself","text":"
pip install -Ur docs/requirements.txt\n
"},{"location":"current/sailbot_workspace/reference/docs_site/#maintain","title":"Maintain","text":""},{"location":"current/sailbot_workspace/reference/docs_site/#contribute-to-this-site","title":"Contribute to This Site","text":"

Read our Markdown Reference Page for the syntax supported by this site.

"},{"location":"current/sailbot_workspace/reference/docs_site/#delete-docs-versions","title":"Delete Docs Versions","text":"

A version of the docs site is created when a PR is open, and is deleted when it is merged or closed. However, the CI that does this is very finicky, so if 2 PR's are trying to update the site at the exact same time one might fail.

This is especially annoying if this happens to be one that deletes a version, because this means that there is a version still open for a merged/closed PR. To manually clean up these PR's, run the following commands in the docs container (in Docker Desktop, the exec tab):

git config user.name <your github username>\ngit config user.email <your github email>\nmike delete --push pr-<number>\n

If you get an error that your local copy of the gh-pages branch has diverged from the remote, you can delete it with git branch -D gh-pages and rerun the mike delete command above.

It will probably ask you to login to GitHub: enter your username then a GitHub access token with write permission.

"},{"location":"current/sailbot_workspace/reference/launch_files/","title":"ROS Launch Files in Sailbot Workspace","text":"

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.

"},{"location":"current/sailbot_workspace/reference/launch_files/#tutorial","title":"Tutorial","text":""},{"location":"current/sailbot_workspace/reference/launch_files/#launch-file-architecture","title":"Launch File Architecture","text":"

There are two launch processes that we utilize: namely the Package Launch Process and the Global launch process.

"},{"location":"current/sailbot_workspace/reference/launch_files/#the-package-launch-process","title":"The Package Launch Process","text":"

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.
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.

"},{"location":"current/sailbot_workspace/reference/launch_files/#the-global-launch-process","title":"The Global Launch Process","text":"

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.
"},{"location":"current/sailbot_workspace/reference/launch_files/#invoking-launch-files","title":"Invoking Launch Files","text":"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 Cmd+C for Mac OS

"},{"location":"current/sailbot_workspace/reference/launch_files/#package-launch","title":"Package Launch","text":"

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:

CLI VS Code

Either the package and launch file name, or the path to the launch file can be used:

  • Method 1: ros2 launch <package> <launch file>. This method can only be used when a launch file is part of a built ROS package.
  • Method 2: ros2 launch <path to launch file>. This method can be used regardless if a launch file is in a ROS package or not.

Launch via CLI Examples

Let's launch local pathfinding using both CLI methods:

Method 1

ros2 launch local_pathfinding main_launch.py\n

Method 2

ros2 launch $ROS_WORKSPACE/src/local_pathfinding/launch/main_launch.py\n

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.

"},{"location":"current/sailbot_workspace/reference/launch_files/#global-launch","title":"Global Launch","text":"

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.

CLI VS Code

Run the entire system with the following CLI command:

ros2 launch $ROS_WORKSPACE/src/global_launch/main_launch.py\n

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.

"},{"location":"current/sailbot_workspace/reference/launch_files/#using-cli-arguments","title":"Using CLI Arguments","text":"

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\":

ros2 launch local_pathfinding main_launch.py log_level:=debug\n

It can also be ran with the VS Code command named ROS: Launch.

Passing arguments takes the form of <arg name>:=<arg value>. To list the arguments that a launch file takes, simply add the -s flag at the end of the launch command.

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:

ros2 launch $ROS_WORKSPACE/src/global_launch/main_launch.py -s\n

The following output is observed in the terminal (as of September 2023):

Arguments (pass arguments as '<name>:=<value>'):\n\n'config':\n    Path to ROS parameter config file. Controls ROS parameters passed into ROS nodes\n    (default: '/workspaces/sailbot_workspace/src/global_launch/config/globals.yaml')\n\n'log_level':\n    Logging severity level. A logger will only process log messages with severity levels at or higher than the\n    specified severity. Valid choices are: ['debug', 'info', 'warn', 'error', 'fatal']\n    (default: 'info')\n\n'mode':\n    System mode. Decides whether the system is ran with development or production interfaces. Valid choices are:\n    ['production', 'development']\n    (default: 'development')\n
Example using multiple CLI arguments
ros2 launch local_pathfinding main_launch.py log_level:=debug mode:=production\n
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:

ros2 launch $ROS_WORKSPACE/src/global_launch/main_launch.py enable_sim_multithreading:=true\n

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.

"},{"location":"current/sailbot_workspace/reference/launch_files/#ros-parameter-config-file","title":"ROS Parameter Config File","text":"

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.

  1. ROS Launch File Documentation \u21a9

"},{"location":"current/sailbot_workspace/reference/notebooks/","title":"Notebooks","text":"

Source code

The source code for Notebooks can be found in notebooks. Its README has been copied below.

"},{"location":"current/sailbot_workspace/reference/notebooks/#notebooks","title":"Notebooks","text":"

UBC Sailbot's Jupyter notebooks for researching and exporing implementations.

"},{"location":"current/sailbot_workspace/reference/notebooks/#standards","title":"Standards","text":"
  1. In addition to the dependencies installed in Sailbot Workspace, notebooks may have additional dependencies that are installed in the first code block
  2. Implementations in notebooks should be complete: do not import functions from other UBC Sailbot repositories
  3. Notebooks should be organized into directories named like the UBC Sailbot repositories they correspond to
"},{"location":"current/sailbot_workspace/reference/parameters/","title":"Parameters","text":"

Source code

Our ROS parameters can be found in src/global_launch/config. Its README has been copied below.

"},{"location":"current/sailbot_workspace/reference/parameters/#sailbot-ros-parameter-configuration","title":"Sailbot ROS Parameter Configuration","text":"

The description of each parameter contained in globals.yaml are described in this README. Descriptions of parameters for each node are included. These parameters can be changed dynamically as well via the command line interface. To learn more, see the ROS 2 documentation on ROS 2 Parameters.

Each parameter is specified in the following format:

  • Description: The description of the parameter.
  • Datatype: The datatype. If it happens to be an array, the datatype of the elements should be specified and the length of the array.
  • Range/Acceptable Values: Ranges of integers and floating point values are specified with interval notation. Namely, [] denotes inclusive boundaries, while () denotes non-inclusive boundaries. For strings, the acceptable values are listed.

Additional information may be included when necessary.

[!IMPORTANT] This document should be updated when any changes occur to the ROS parameters specified in globals.yaml.

"},{"location":"current/sailbot_workspace/reference/parameters/#global-parameters","title":"Global Parameters","text":"

ROS parameters common across all ROS nodes in the network.

pub_period_sec

  • Description: The period at which the publishers publish.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)
"},{"location":"current/sailbot_workspace/reference/parameters/#local-pathfinding-parameters","title":"Local Pathfinding Parameters","text":"

ROS parameters specific to the nodes in the local_pathfinding package.

"},{"location":"current/sailbot_workspace/reference/parameters/#mgp_main","title":"mgp_main","text":"

global_path_filepath

  • Description: The absolute filepath to a global path csv file.
  • Datatype: string
  • Acceptable Values: Any valid filepath to a properly formatted csv file.

interval_spacing

  • Description: The upper bound on spacing between each point in the global path in km.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

write

  • Description: Whether or not to write a generated global path to a new csv file.
  • Datatype: boolean
  • Acceptable Values: true, false

gps_threshold

  • Description: A new path will be generated if the GPS position changed by more thangps_threshold*interval_spacing.
  • Datatype: double
  • Acceptable Values: (1.0, MAX_DOUBLE)

force

  • Description: Force the mock global path callback to update the global path when set to true.
  • Datatype: boolean
  • Acceptable Values: true, false
"},{"location":"current/sailbot_workspace/reference/parameters/#navigate_main","title":"navigate_main","text":"

path_planner

  • Description: The path planner to use. Planners are from OMPL Library.
  • Datatype: string
  • Acceptable Values: \"bitstar\", \"bfmtstar\", \"fmtstar\", \"informedrrtstar\", \"lazylbtrrt\", \"lazyprmstar\", \"lbtrrt\", \"prmstar\", \"rrtconnect\", \"rrtsharp\", \"rrtstar\", \"rrtxstatic\", \"sorrtstar\"
"},{"location":"current/sailbot_workspace/reference/parameters/#controller-parameters","title":"Controller Parameters","text":"

ROS parameters specific to the nodes in the Controller.

"},{"location":"current/sailbot_workspace/reference/parameters/#wingsail_ctrl_node","title":"wingsail_ctrl_node","text":"

reynolds_number

  • Description: The Reynolds number of the wind.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

angle_of_attack

  • Description: The angle of attack of the sail.
  • Datatype: double
  • Range: (-180.0, 180.0]
"},{"location":"current/sailbot_workspace/reference/parameters/#boat-simulator-parameters","title":"Boat Simulator Parameters","text":"

ROS parameters specific to the nodes in the boat simulator.

"},{"location":"current/sailbot_workspace/reference/parameters/#low_level_control_node","title":"low_level_control_node","text":"

info_log_throttle_period_sec

  • Description: Limits the info logs to avoid overwhelming the terminal.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

logging_throttle_period_sec

  • Description: Controls the message logging throttle period.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

qos_depth

  • Description: The maximum number of subscription messages to queue for further processing.
  • Datatype: int
  • Range: [1, MAX_INT)

rudder.actuation_execution_period_sec

  • Description: The period at which the main loop in the rudder action server executes in seconds.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

rudder.disable_actuation

  • Description: Controls whether or not rudder actuation is disabled. If true, the rudder angle is fixed to some value. Otherwise, the PID mechanism is used to control the rudder angle.
  • Datatype: boolean
  • Acceptable Values: true, false

rudder.fixed_angle_deg

  • Description: The angle to fix the rudder in degrees. Only used if rudder.disable_actuation is true.
  • Datatype: double
  • Range: [-45.0, 45.0]

rudder.pid.buffer_size

  • Description: The buffer size of PID that stores previously computed errors over time.
  • Datatype: int
  • Range: [1, MAX_INT)

rudder.pid.kd

  • Description: The PID Derivative constant for the rudder. Only used if rudder.disable_actuation is false.
  • Datatype: double
  • Range: [0.0, MAX_DOUBLE)

rudder.pid.ki

  • Description: The PID Integral constant for the rudder. Only used if rudder.disable_actuation is false.
  • Datatype: double
  • Range: [0.0, MAX_DOUBLE)

rudder.pid.kp

  • Description: The PID Proportionality constant for the rudder. Only used if rudder.disable_actuation is false.
  • Datatype: double
  • Range: [0.0, MAX_DOUBLE)

wingsail.actuation_execution_period_sec

  • Description: The period at which the main loop in the sail action server executes in seconds.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

wingsail.actuation_speed_deg_per_sec

  • Description: The speed at which the wingsail trim tab actuates in degrees per second.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

wingsail.disable_actuation

  • Description: Controls whether or not wingsail trim tab actuation is disabled. If true, the trim tab is fixed to some value. Otherwise, the trim tab angle is determined by the wingsail controller.
  • Datatype: boolean
  • Acceptable Values: true, false

wingsail.fixed_angle_degree

  • Description: Fixed the wingsail trim tab to some angle in degrees. Only used if wingsail.disable_actuation is true.
  • Datatype: double
  • Range: [-180.0, 180.0)
"},{"location":"current/sailbot_workspace/reference/parameters/#physics_engine_node","title":"physics_engine_node","text":"

action_send_goal_timeout_sec

  • Description: How long the action clients wait for the action server to respond to a request before timing out in seconds.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

info_log_throttle_period_sec

  • Description: Limits the info logs to avoid overwhelming the terminal.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

logging_throttle_period_sec

  • Description: Controls the message logging throttle period.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

qos_depth

  • Description: The maximum number of subscription messages to queue for further processing.
  • Datatype: int
  • Range: [1, MAX_INT)

rudder.actuation_request_period_sec

  • Description: How often the rudder action client requests a rudder actuation in seconds.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

wingsail.actuation_request_period_sec

  • Description: How often the sail action server requests a wingsail actuation.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

wind_sensor.constant_params.value

  • Description: Specifies the constant vector returned by the constant generator that represents the wind velocity in kmph. Namely, the same value is fixed in the wind sensors. The value is an array containing the x and y components of the velocity. Only used if wind_sensor.generator_type is constant.
  • Datatype: double array, length 2
  • Range: (MIN_DOUBLE, MAX_DOUBLE)

wind_sensor.gaussian_params.corr_xy

  • Description: The correlation coefficient between x and y components of the wind velocity. Only used if wind_sensor.generator_type is gaussian.
  • Datatype: double
  • Range: [-1.0, 1.0]

wind_sensor.gaussian_params.mean

  • Description: The mean wind velocity parameter in kmph for the gaussian generator. The mean is an array containing the x and y components of the velocity. Only used if wind_sensor.generator_type is gaussian.
  • Datatype: double array, length 2
  • Range: (MIN_DOUBLE, MAX_DOUBLE)

wind_sensor.gaussian_params.std_dev

  • Description: The standard deviation parameters in kmph for the gaussian generator. There are two standard deviations specified within an array: one for the x component, and one for the y component. Only used if wind_sensor.generator_type is gaussian.
  • Datatype: double array, length 2
  • Range: (0.0, MAX_DOUBLE)
  • If a standard deviation of zero is desired, then consider using the constant generator instead.

wind_sensor.generator_type

  • Description: Determines the type of random number generator that will be used to generate wind sensor data.
  • Datatype: string
  • Acceptable Values: gaussian, constant

wind_generation.mvgaussian_params.mean

  • Description: The mean value for the wind generated, expressed in kilometers per hour (km/h), for the multivariate Gaussian generator.
  • Datatype: double array, length 2
  • Range: (0.0, MAX_DOUBLE)

wind_generation.mvgaussian_params.cov

  • Description: The covariance matrix for the generated wind, represented as a string formatted as a 2D double array, since ROS parameters do not support native 2D array types.
  • Datatype: string
  • Range: (0.0, MAX_DOUBLE)

current_generation.mvgaussian_params.mean

  • Description: The mean value for the current generated, expressed in kilometers per hour (km/h), for the multivariate Gaussian generator.
  • Datatype: double array, length 2
  • Range: (0.0, MAX_DOUBLE)

current_generation.mvgaussian_params.cov

  • Description: The covariance matrix for the generated current, represented as a string formatted as a 2D double array, since ROS parameters do not support native 2D array types.
  • Datatype: string
  • Range: (0.0, MAX_DOUBLE)
"},{"location":"current/sailbot_workspace/reference/parameters/#data_collection_node","title":"data_collection_node","text":"

file_name

  • Description: The name of the file in which the data is saved, excluding the file extension.
  • Datatype: string
  • Acceptable Values: Any valid file name.

qos_depth

  • Description: The maximum number of subscription messages to queue for further processing.
  • Datatype: int
  • Range: [1, MAX_INT)

topics

  • Description: Specifies the topics to subscribe to. It should adhere to the format ['topic_name_1', 'topic_type_1', ...].
  • Datatype: string array with an even length
  • Acceptable Values: Each pair within the array must consist of a valid topic name as the first string and the corresponding correct type as the second string.

bag

  • Description: Determines whether to save recorded data as a ROS bag.
  • Datatype: boolean
  • Acceptable Values: true, false

json

  • Description: Determines whether to save recorded data as a JSON file.
  • Datatype: boolean
  • Acceptable Values: true, false

write_period_sec

  • Description: The interval (in seconds) for writing queued data to the JSON file.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)
"},{"location":"current/sailbot_workspace/usage/help/","title":"Help","text":""},{"location":"current/sailbot_workspace/usage/help/#performance-issues","title":"Performance Issues","text":"

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
  • 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
      • 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
"},{"location":"current/sailbot_workspace/usage/help/#troubleshooting","title":"Troubleshooting","text":"

If you are having some trouble running our software, here are some things you can try:

"},{"location":"current/sailbot_workspace/usage/help/#sailbot-workspace-troubleshooting","title":"Sailbot Workspace Troubleshooting","text":"
  • Update Sailbot Workspace
  • Run the setup task to update package dependencies
  • 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
"},{"location":"current/sailbot_workspace/usage/help/#vs-code-troubleshooting","title":"VS Code Troubleshooting","text":"
  • Rebuild the Dev Container: run the Dev Containers: Rebuild Container VS Code command
  • Reload VS Code: run the Developer: Reload Window VS Code command
  • Identify broken extension: run the Help: Start Extension Bisect VS Code command
    • Once you have identified a broken extension, you can install a previous version until the issue is fixed in a new release
"},{"location":"current/sailbot_workspace/usage/help/#system-troubleshooting","title":"System Troubleshooting","text":"
  • Restart WSL: close Sailbot Workspace and Docker Desktop then run wsl --shutdown in PowerShell
  • Restart computer
"},{"location":"current/sailbot_workspace/usage/help/#docker-troubleshooting","title":"Docker Troubleshooting","text":"
  • Delete Docker files

    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
    • Install a previous version of Docker Desktop
"},{"location":"current/sailbot_workspace/usage/help/#shrink-wsl-distributions-size","title":"Shrink WSL Distributions' Size","text":"

After using Docker and Ubuntu for a while, you may notice that the vdisks are very large. As of May 2024, they are located at C:\\Users\\<user>\\AppData\\Local\\Docker\\wsl\\data\\ext4.vhdx and C:\\Users\\<user>\\AppData\\Local\\Packages\\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\\LocalState\\ext4.vhdx, respectively.

The problem is that these vdisks can automatically grow but not shrink, so if you download large files (like Docker images) and delete them once they're not needed the space is not freed. You can shrink vdisk using these commands.

"},{"location":"current/sailbot_workspace/usage/how_to/","title":"How-To's","text":""},{"location":"current/sailbot_workspace/usage/how_to/#run-vs-code-commands-tasks-and-launch-configurations","title":"Run VS Code commands, tasks, and launch configurations","text":"

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.

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
"},{"location":"current/sailbot_workspace/usage/how_to/#work-with-containerized-applications","title":"Work with containerized applications","text":"

We have containerized the following applications for a variety of reasons:

  • MongoDB database
  • Docs site
  • Website
"},{"location":"current/sailbot_workspace/usage/how_to/#running-containerized-applications","title":"Running containerized applications","text":"

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. Uncomment the port mapping(s) of the application(s) you want to run in .devcontainer/docker-compose.yml
    • Uncommented port mappings exposed ports to the host operating system; e.g., so that web applications can be opened in your browser
  3. 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 in .devcontainer/devcontainer.json and port mapping in .devcontainer/docker-compose.yml
  2. Stop the application's container: see Managing containerized applications
"},{"location":"current/sailbot_workspace/usage/how_to/#viewing-mongodb-data","title":"Viewing MongoDB data","text":"

Connect the MongoDB VS Code extension to the running database: Create a Connection for Deployment

  • 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 for how to use it to navigate or explore the database
"},{"location":"current/sailbot_workspace/usage/how_to/#opening-docs-or-website","title":"Opening Docs or Website","text":"

Docs runs on port 8000 and Website 3005. You can see them in your browser at localhost:<port>. 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

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

"},{"location":"current/sailbot_workspace/usage/how_to/#managing-containerized-applications","title":"Managing containerized applications","text":"

Each application runs in a Docker container. Containers can be managed using Docker Desktop or CLI commands:

  • View Sailbot Workspace containers

    Docker Desktop CLI Commands
    1. Select \"Containers\" in the top right
    2. Expand \"sailbot_workspace_devcontainer\"
      • The \"Status\" column shows whether a container is running or not
    docker ps -a\n
    • Sailbot Workspace containers should be named something like sailbot_workspace_devcontainer-<application>-<number>
    • 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)

    Docker Desktop CLI Commands
    1. Click on a container
    2. Navigate to the \"Logs\" view if not already on it
    docker logs <container>\n
  • Start a container that is not running

    Docker Desktop CLI Commands
    1. Click start
    docker start <container>\n
  • Stop a container that is running

    Docker Desktop CLI Commands
    1. Click stop
    docker stop <container>\n
"},{"location":"current/sailbot_workspace/usage/how_to/#manage-software-packages","title":"Manage software packages","text":"

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.

"},{"location":"current/sailbot_workspace/usage/how_to/#add-apt-or-python-dependencies-to-ros-packages","title":"Add apt or python dependencies to ROS packages","text":"

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:

<depend>ROSDEP_KEY</depend>\n<build_depend>ROSDEP_KEY</build_depend>\n<build_export_depend>ROSDEP_KEY</build_export_depend>\n<exec_depend>ROSDEP_KEY</exec_depend>\n<test_depend>ROSDEP_KEY</test_depend>\n
  • Learn what each tag is used for here.

  • 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
    Apt Dependencies Python Dependencies
    • Rosdep keys for apt repositories can be found here
    • Rosdep keys for python packages can be found here
    • 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 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 to learn more.

"},{"location":"current/sailbot_workspace/usage/how_to/#add-dependencies-to-a-docker-image","title":"Add dependencies to a Docker image","text":"

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: base, local-base, dev, or pre-base.

"},{"location":"current/sailbot_workspace/usage/how_to/#enable-github-copilot-in-sailbot-workspace","title":"Enable GitHub Copilot in Sailbot Workspace","text":"

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 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. 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.

    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 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 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
    • Configuring GitHub Copilot in your Environment
"},{"location":"current/sailbot_workspace/usage/how_to/#use-your-dotfiles","title":"Use your dotfiles","text":"

Dotfiles are configuration files for various programs.2

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 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

    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

"},{"location":"current/sailbot_workspace/usage/how_to/#run-rayes-software","title":"Run Raye's software","text":"

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, complete step 2 of the setup instructions

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
"},{"location":"current/sailbot_workspace/usage/how_to/#build-rayes-ros-packages","title":"Build Raye's ROS packages","text":"

To build Raye's ROS packages, run the following commands:

roscd\ncatkin_make\n
"},{"location":"current/sailbot_workspace/usage/how_to/#run-packages-from-different-workspaces","title":"Run packages from different workspaces","text":"

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 ProjectRaye
srcnew\n
srcraye\n

Then you can run launch files or package-specific executables in that workspace with:

New ProjectRaye

ros2 launch ... or ros2 run ..., respectively.

roslaunch ... or rosrun ..., respectively.

"},{"location":"current/sailbot_workspace/usage/how_to/#rayes-known-issues","title":"Raye's known issues","text":"

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:

echo 'export ROS_HOSTNAME=localhost' >> ~/.bashrc\necho 'export ROS_MASTER_URI=http://localhost:11311' >> ~/.bashrc\n
  1. GitHub Copilot Quickstart Guide \u21a9

  2. Dotfiles \u2013 What is a Dotfile and How to Create it in Mac and Linux \u21a9

"},{"location":"current/sailbot_workspace/usage/setup/","title":"Setup Instructions","text":"

Sailbot Workspace can be run on Windows, Linux, or macOS, but is the easiest to set up and performs the best on Ubuntu and its derivatives. 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 section.

"},{"location":"current/sailbot_workspace/usage/setup/#1-setup-prerequisites","title":"1. Setup prerequisites","text":""},{"location":"current/sailbot_workspace/usage/setup/#docker","title":"Docker","text":"

Docker is a platform that uses OS-level virtualization1 to develop, ship, and run applications.2 We use it to separate our applications from our infrastructure2 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 is a software used to run Docker. However, it can only be installed on Linux. Docker Desktop is a software used to run Docker in a VM,3 allowing it to be installed on Windows and macOS in addition to Linux.

Windows macOS Linux
  1. Set up prerequisites, WSL and Ubuntu:

    1. In PowerShell, run wsl --install Ubuntu, then exit, wsl --update, and wsl --set-default Ubuntu

      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

        whoami returns root

        If whoami returns root:

        1. Create a non-root user with sudo privileges
        2. Change the default Ubuntu user to this newly-created user: run ubuntu config --default-user <username> in PowerShell, replacing <username> 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 with the WSL 2 backend

    Docker Desktop - Unexpected WSL Error

    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
    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

Install Docker Desktop for your computer's CPU.

  1. Install Docker Engine
    • 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
  3. Configure Docker to start on boot
"},{"location":"current/sailbot_workspace/usage/setup/#vs-code","title":"VS Code","text":"

Visual Studio Code 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
  2. Install the Remote Development Extension Pack
"},{"location":"current/sailbot_workspace/usage/setup/#git","title":"Git","text":"

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
  2. Configure your name and email: Git config file setup (on Windows, run commands in Ubuntu)
  3. Login to GitHub

    Windows macOS / Linux
    1. Run the git config command for your Git version in Git Credential Manager setup (run command in Ubuntu)

      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.

    1. Install the GitHub CLI: Installation
    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, 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
"},{"location":"current/sailbot_workspace/usage/setup/#2-setup-x11-forwarding","title":"2. Setup X11 forwarding","text":"

X11 forwarding is a mechanism that enables Sailbot Workspace to run GUI applications.

You can skip this step since we currently aren't running any GUI applications

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

    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' >> <rc file path>, replacing <rc file path> 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

    Windows macOS Linux

    WSL includes a X11 server.

    1. Set up XQuartz following this guide
    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
    General Arch Linux

    As of February 2023, almost all Linux distributions include a X11 server, Xorg. This may change in the future as Wayland matures.

    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

      Windows macOS Linux

      In Ubuntu, sudo apt install x11-apps.

      XQuartz includes x11-apps. Ensure that XQuartz is running.

      Install x11-apps using your desired package manager.

    2. Verify that running xcalc opens a calculator and that you can use it

"},{"location":"current/sailbot_workspace/usage/setup/#3-clone-sailbot-workspace","title":"3. Clone Sailbot Workspace","text":"

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.

git clone https://github.com/UBCSailbot/sailbot_workspace.git\n
"},{"location":"current/sailbot_workspace/usage/setup/#4-open-sailbot-workspace-in-vs-code","title":"4. Open Sailbot Workspace in VS Code","text":"
  1. Install code command in PATH

    Windows macOS Linux

    The code command is installed by default.

    See launching from the command line.

    The code command is installed by default.

  2. Open the sailbot_workspace/ directory in VS Code: run code <relative path to sailbot workspace>

    • For example, if you just cloned the repository, the command would be code sailbot_workspace
"},{"location":"current/sailbot_workspace/usage/setup/#5-open-the-workspace-file","title":"5. Open the workspace file","text":"

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
"},{"location":"current/sailbot_workspace/usage/setup/#6-open-sailbot-workspace-in-a-dev-container","title":"6. Open Sailbot Workspace in a Dev Container","text":"
  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
"},{"location":"current/sailbot_workspace/usage/setup/#7-run-the-build-all-task","title":"7. Run the Build All task","text":"

Wait before running

Ensure that the postCreateCommand from devcontainer.json has completed before running this task.

The Build All task builds all the ROS packages.

"},{"location":"current/sailbot_workspace/usage/setup/#8-reload-the-vs-code-terminals-and-window","title":"8. Reload the VS Code terminals and window","text":"

Delete all open terminals and run the Developer: Reload Window VS Code command to detect the files that were generated from building.

"},{"location":"current/sailbot_workspace/usage/setup/#9-start-the-system","title":"9. Start the system","text":"

Run the entire system to verify everything is working using the following command in the VS Code terminal:

ros2 launch $ROS_WORKSPACE/src/global_launch/main_launch.py\n

Use Ctrl+C in the terminal to stop the system.

"},{"location":"current/sailbot_workspace/usage/setup/#setup-sailbot-workspace-in-a-github-codespace","title":"Setup Sailbot Workspace in a GitHub Codespace","text":"

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. 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
      • Upgrade to a Pro account for increased usage limits (this is free for students): apply to GitHub Global Campus as a student
      • Stop your codespace as soon as you are done using it: stopping a codespace
      • Delete codespaces that you do not plan to use anymore: deleting a codespace
  2. Follow the local setup instructions starting from 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
  • Close it by running the Codespaces: Stop Current Codespace VS Code command

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
  1. Wikipedia Docker page \u21a9

  2. Get Docker \u21a9\u21a9

  3. What is the difference between Docker Desktop for Linux and Docker Engine \u21a9

  4. Git SCM \u21a9

  5. GitHub Codespaces overview \u21a9

"},{"location":"current/sailbot_workspace/usage/workflow/","title":"Development Workflow","text":""},{"location":"current/sailbot_workspace/usage/workflow/#1-open-sailbot-workspace","title":"1. Open Sailbot Workspace","text":"

Once you have set up Sailbot Workspace, 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]\n
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.

"},{"location":"current/sailbot_workspace/usage/workflow/#2-update-sailbot-workspace","title":"2. Update Sailbot Workspace","text":"

Sailbot Workspace is still in active development, check out its recent releases and commit history. 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

    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+` 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

    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 want to run our docs or website, see How to work with containerized applications

"},{"location":"current/sailbot_workspace/usage/workflow/#3-make-your-changes","title":"3. Make your changes","text":"

We make changes to our software following our GitHub development workflow. Of particular relevance is the Developing on Branches page.

Git interfaces

One way to interface with Git is through CLI commands. However, you may find it faster to use VS Code's interface, 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
"},{"location":"current/sailbot_workspace/usage/workflow/#4-build-your-changes","title":"4. Build your changes","text":"

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
"},{"location":"current/sailbot_workspace/usage/workflow/#5-verify-your-changes","title":"5. Verify your changes","text":"Running GUI applications on macOS

If you want to run GUI applications on macOS, ensure that XQuartz is running.

"},{"location":"current/sailbot_workspace/usage/workflow/#lint-and-test","title":"Lint and Test","text":"

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 Testing tab on the VS Code primary sidebar contains individual tests. One can run specific unit tests by clicking the Run Test icon beside the test name.

"},{"location":"current/sailbot_workspace/usage/workflow/#run-a-package","title":"Run a Package","text":"

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:

CLI VS Code
  • Launch files:
    • ros2 launch <package> <launch file>
    • ros2 launch <path to launch file>
  • Nodes:
    • ros2 run <package> <executable>
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

    $ ros2 <tab><tab>\naction                          extension_points                multicast                       security\nbag                             extensions                      node                            service\n...\n
  • Complete commands: runs ros2 launch local_pathfinding main_launch.py

    $ ros2<tab>la<tab>loc<tab>m<tab>\n
  • Navigate to directories: runs cd .devcontainer/config from the root directory of Sailbot Workspace

    $ cd .d<tab>c<tab>\n

Furthermore, navigate past commands with Up and Down and search through them with Ctrl+R.

  • 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.

"},{"location":"current/sailbot_workspace/usage/workflow/#run-the-system","title":"Run the System","text":"

To verify that you didn't break anything, you may want to run the entire system. See Invoking Launch Files for more information on running the system.

"},{"location":"current/sailbot_workspace/usage/workflow/#debugging","title":"Debugging","text":"

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
"},{"location":"current/website/overview/","title":"Overview","text":"

Source code

The source code for Website can be found in src/website. Its README has been copied below.

"},{"location":"current/website/overview/#website","title":"Website","text":"

In the website development timeline, we are currently evaluating the folllowing software stack: Next.js website (this repository), Typescript, React + Redux, and the MongoDB database. The easiest way to evaluate these potential solutions for our purposes is in sailbot_workspace.

"},{"location":"current/website/overview/#database","title":"Database","text":"

MongoDB is a general purpose, document-based, distributed database built for modern application developers and for the cloud era. If you want to learn more about MongoDB, visit their docs site: MongoDB Documentation.

"},{"location":"current/website/overview/#setup","title":"Setup","text":""},{"location":"current/website/overview/#environment-variables","title":"Environment variables","text":"

We have two separate configurations: one for development .env.development, the other for production .env.production. The values may vary, but the environment variables are the same. See below:

  • MONGODB_URI: Your MongoDB connection string. Use mongodb://localhost:27017/<DB_NAME> to establish a connection with the local database.
  • NEXT_PUBLIC_SERVER_HOST: The host URL of the website.
  • NEXT_PUBLIC_SERVER_PORT: The port number of the website.
  • NEXT_PUBLIC_POLLING_TIME_MS: The time interval for polling the database in milliseconds.
"},{"location":"current/website/overview/#package-installation","title":"Package installation","text":"

The following command installs all required dependencies listed in the package.json file:

npm install\n

Once the installation is complete, you should see a node_modules directory in the project's root. This directory contains all installed packages.

When installing a new package to the website, please follow the steps below:

  1. Access the terminal of the website container on Docker.

  2. Run the command npm install <package-name>. Replace <package-name> with the actual name of the package you want to add.

  3. Should you encounter errors related to resolving peer dependencies, please re-run the command with the header --legacy-peer-deps. Do not to use --force unless you're well aware of the potential consequences.

  4. Review the package.json file to ensure the new package and its version have been added to the dependencies section.

  5. Confirm that package-lock.json has also been updated. This file holds specific version information to ensure consistent installations across different environments.
  6. Once the installation process is finished, please make sure to commit the files package.json and package-lock.json. These files are essential for version controlling the dependencies that have been added.
"},{"location":"current/website/overview/#run","title":"Run","text":"

Using Sailbot Workspace, the website should be up and running on http://localhost:3005.

Otherwise, you execute the following commands to run it in development mode:

npm run dev\n
"},{"location":"current/website/overview/#linters","title":"Linters","text":"

Before merging in new changes to the repository, please execute the following commands in order:

npm run format\n

This command runs Prettier to automatically format the code according to the rules defined in the configuration file .prettierrc.

npm run lint\n

This command runs ESLint to analyze the code for potential errors and enforce coding style based on the rules defined in the configuration file .eslintrc.

"},{"location":"reference/docker/","title":"Docker","text":"

Docker is a platform that uses OS-level virtualization1 to develop, ship, and run applications.2

"},{"location":"reference/docker/#tutorial","title":"Tutorial","text":"
  1. Wikipedia Docker page \u21a9

  2. Get Docker \u21a9

"},{"location":"reference/linux_commands/","title":"Linux Commands","text":""},{"location":"reference/linux_commands/#tutorial","title":"Tutorial","text":""},{"location":"reference/markdown/","title":"Markdown","text":"

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, 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.

"},{"location":"reference/markdown/#getting-started","title":"Getting Started","text":"

We recommend markdownguide.org 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.

"},{"location":"reference/markdown/#sailbot-and-markdown","title":"Sailbot and Markdown","text":"

We write Markdown for GitHub and Material for MkDocs. The following sections detail how Markdown is used in these services.

"},{"location":"reference/markdown/#github","title":"GitHub","text":"

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 RenderingAfter Rendering

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!

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 for more information on the available features.

"},{"location":"reference/markdown/#material-for-mkdocs","title":"Material for MkDocs","text":"

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. Since GitHub renders Markdown files automatically you will need to click the \"Raw\" button to view their contents.

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 for more information on the available features.

"},{"location":"reference/markdown/#rendering-markdown","title":"Rendering Markdown","text":"

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:

Vanilla Github Material for MkDocs
  • VS Code: Markdown rendering is supported out of the box.
  • Markdown Live Preview: An online rendering tool.
  • Markdown Preview GitHub Styling: VS Code extension that renders GitHub-flavoured markdown.
  • Create a draft issue on GitHub and preview the markdown to see how it renders.
  • UBC Sailbot Docs: To preview your changes when working on this site, refer to the How to work with containerized applications.
  • 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.

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.

"},{"location":"reference/markdown/#linting","title":"Linting","text":"

We lint our Markdown files to reduce errors and increase readability. In particular, we use two tools:

  1. markdownlint is used to enforce a style guide. Its configuration file for this repository is .markdownlint.json. If you use VS Code, there is a markdownlint extension.

  2. markdown-link-check is used to check for broken links. Its configuration file for this repository is .markdown-link-check.json.

  1. https://www.markdownguide.org/getting-started/ \u21a9

"},{"location":"reference/ros/","title":"Robot Operating System","text":"

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 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. To run our software on your device without our workspace, you would have to install ROS and the dependencies that are in our Docker images yourself.

"},{"location":"reference/ros/#tutorial","title":"Tutorial","text":""},{"location":"reference/ros/#workspace-configuration","title":"Workspace Configuration","text":"

To get our workspace configuration running on your computer:

  1. Set it up by following the setup instructions
  2. Uncomment the ROS 2 tutorials section in .devcontainer/Dockerfile, then run the \"Dev Containers: Rebuild Container\" VS Code command, to install the tutorials' dependencies
  3. Clone the repositories used in the tutuorials: ros_tutorials (humble branch), py_pubsub_ex, and cpp_pubsub_ex, then run the setup VS Code task to install their dependencies

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"},{"location":"reference/ros/#tutorials","title":"Tutorials","text":"

We encourage all software members to work through the ROS tutorials 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
"},{"location":"reference/ros/#concepts","title":"Concepts","text":"

We encourage all software members to read the following documentation on key ROS concepts:

  • About logging and logger configuration
  • About ROS 2 interfaces
  • About parameters in ROS 2
"},{"location":"reference/ros/#ros-1-bridge","title":"ROS 1 Bridge","text":"

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 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. For PATH members, the Migrating launch files from ROS 1 to ROS 2 page will be a helpful reference when we do so.

  1. https://docs.ros.org/en/humble/index.html \u21a9

  2. https://www.toptal.com/robotics/introduction-to-robot-operating-system \u21a9

  3. https://ubuntu.com/robotics/what-is-ros \u21a9

"},{"location":"reference/cpp/differences/","title":"Differences Between C and C++","text":"

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++.

"},{"location":"reference/cpp/differences/#classes-and-structs","title":"Classes and Structs","text":"

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.

struct foo {\nprivate:\n    int x;\n    void helper(void);\npublic:\n    foo(int y);\n}\n
class foo {\nprivate:\n    int x;\n    void helper(void);\npublic:\n    foo(int y);\n}\n
"},{"location":"reference/cpp/differences/#namespaces","title":"Namespaces","text":"

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 CC++ A.h
float x;\nint bar(void);\n
B.h
float x;\nint bar(void);\n
ighxy.c
#include \"A.h\"\n#include \"B.h\"\n\nint main(void) {\n    int a = bar();\n    ...\n}\n/* Error, does not compile*/\n
A.h
namespace a {\nfloat x;\nint bar(void);\n}\n
B.h
namespace b {\nfloat x;\nint bar(void);\n}\n
ighxy.cpp
#include \"A.h\"\n#include \"B.h\"\n\nint main(void) {\n    int a = a::bar();\n    int b = b::bar();\n    float xa = a::x;\n    float xb = b::x;\n    /* No problem! */\n    ...\n}\n
Warning

You may come across something like:

example.cpp
using namespace std;\nnamespace io = std::filesystem;\n\nint main(int argc, char* argv[]) {\n    bool isDirectory = io::is_directory(argv[1]);  // Equivalent to std::filesystem::is_directory(argv[1])\n    cout << isDirectory << endl;\n    return 0;\n}\n

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.

OKNot OK
    class string {\n        // Insert implementation here\n    }\n\n    int main(void) {\n        string ourString = \"Our own string implementation\";\n        std::string stdString = \"Standard Library string implementation\";\n        ...\n    }\n
    using namespace std;\n\n    // ERROR - multiple definitions of type string\n    class string {\n\n    }\n

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.

"},{"location":"reference/cpp/differences/#constant-expressions","title":"Constant Expressions","text":"

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 PrecompileAfter Precompile
#define PI 3.14F\n#define AREA_OF_CIRCLE(radius) ((PI) * (radius) * (radius))\n\nint main(void) {\n    float area = AREA_OF_CIRCLE(2.5F);\n    ...\n}\n
int main(void) {\n    float area = ((3.14F) * (2.5F) * (2.5F));\n    ...\n}\n

Note

AREA_OF_CIRCLE is a macro with arguments. If you are confused by it, this resource 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. Moreover, symbols declared with #define are always globally visible, ignoring namespaces!

In C++, the use of constant expressions are preferred.

constexpr float pi = 3.14F;\nconstexpr float area_of_circle(float radius) {\n    return pi * radius * radius;\n}\n

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.

Constant Expression Scoping
void foo(void) {\n    constexpr float rand = 123.456;\n    ...\n}\n\nvoid bar (void) {\n    constexpr float rand = 789.123;\n    ...\n}\n
"},{"location":"reference/cpp/differences/#lambdas","title":"Lambdas","text":"

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 for Microsoft's explanation.

"},{"location":"reference/cpp/differences/#misc","title":"Misc","text":""},{"location":"reference/cpp/differences/#arrays","title":"Arrays","text":"

Using the C++ implementation of arrays 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

CC++

#include \"stdio.h\"\n\nvoid print_contents(int *arr, int size) {\n    for (int i = 0; i < size; i++) {\n        printf(\"%d\\n\", *arr);\n    }\n}\n\nint main(void) {\n    int arr[5] = {0, 1, 2, 3, 4};\n    foo(arr, 5);\n    return 0;\n}\n
We can't even guarantee that the integer pointer arr is an array!

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.

#include <iostream>\n#include <array>\n#include <span>\n\nvoid print_contents(std::span<int> container) {\n    for (const auto &e : container) {\n        std::cout << e << std::endl;\n    }\n}\n\nint main(void) {\n    std::array<int, 5> arr = {0, 1, 2, 3, 4};\n    foo(arr);\n    return 0;\n}\n

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
"},{"location":"reference/cpp/start/","title":"Getting Started","text":"

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.

"},{"location":"reference/cpp/start/#for-cc-beginners","title":"For C/C++ Beginners","text":"

If you just need to know how C++ is different from C, then see the Differences Between C and C++. 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 A structured tutorial that goes through basic concepts in C++. It's good to do up to the section on Classes. YouTube Tutorial 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 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!

"},{"location":"reference/cpp/tools/","title":"Tools","text":"

A lot goes into making a well structured C++ project, much more than any one team should have to do.

"},{"location":"reference/cpp/tools/#cmake","title":"CMake","text":"

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 are great for understanding the basics.

"},{"location":"reference/cpp/tools/#gdb","title":"GDB","text":"

The GNU Project Debugger 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 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.

"},{"location":"reference/cpp/tools/#googletest","title":"GoogleTest","text":"

GoogleTest is the C++ unit testing framework we will be using. The GoogleTest Primer is a good place to start.

Example Cached Fibonacci ProgramTest Cached Fibonacci Program cached_fib.h
#include <vector>\nclass CachedFib {\npublic:\n    void CachedFib(int n);\n    int  getFib(int n);\nprivate:\n    std::vector<int> cache;\n}\n
cached_fib.cpp
#include <iostream>\n#include <vector>\n#include \"cached_fib.h\"\n\nvoid CachedFib::CachedFib(int n) {\n    cache.push_back(0);\n    cache.push_back(1);\n    for (int i = 2; i < n; i++) {\n        cache.push_back(cache[i - 1] + cache[i - 2]);\n    }\n}\n\nint CachedFib::getFib(int n) {\n    if (cache.size() < n) {\n        for (int i = cache.size(); i < n; i++) {\n            cache.push_back(cache[i-1] + cache[i-2]);\n        }\n    }\n    std::cout << cache[n - 1] << std::endl;\n}\n
test_cached_fib.cpp
#include \"cached_fib.h\"\n#include \"gtest/gtest.h\"\n\nCachedFib::testFib;\n\nclass TestFib : public ::testing::Test {\nprotected:\n    void Setup override {\n        // Every time a test is started, testFib is reinitialized with a constructor parameter of 5\n        testFib = CachedFib(5);\n    }\n}\n\nTEST_F(TestFib, TestBasic) {\n    ASSERT_EQ(getFib(5), 3) << \"5th fibonacci number must be 3!\";\n}\n\n// more tests\n
"},{"location":"reference/cpp/tools/#google-protocol-buffer","title":"Google Protocol Buffer","text":"

Google Protocol Buffer (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. The page is quite dense and can be hard to follow, so do not worry if you do not understand it.

"},{"location":"reference/cpp/tools/#clang","title":"Clang","text":"

In its most basic form, Clang 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.

"},{"location":"reference/cpp/tools/#clangd","title":"Clangd","text":"

Clangd is the Clang language server. It provides a much more powerful intellisense than the default one used in VSCode's C/C++ extension.

"},{"location":"reference/cpp/tools/#clang-tidy","title":"Clang-Tidy","text":"

Clang-Tidy is a linting tool, who's main purpose is to catch potential programming errors caused by bad programming style/practices using just static analysis.

"},{"location":"reference/cpp/tools/#clang-format","title":"Clang Format","text":"

An autoformatting tool that makes enforcing style guidelines much easier. When se tup, it corrects formatting as soon as you hit save.

"},{"location":"reference/cpp/tools/#llvm-cov","title":"llvm-cov","text":"

We will use llvm-cov to evaluate our test coverage. When used with genhtml, we can generate HTML reports that that show our line, function, and branch coverage line-by-line.

"},{"location":"reference/github/advanced_git/","title":"Advanced Git","text":""},{"location":"reference/github/advanced_git/#tutorial","title":"Tutorial","text":""},{"location":"reference/github/github_actions/","title":"GitHub Actions","text":""},{"location":"reference/github/github_actions/#tutorial","title":"Tutorial","text":""},{"location":"reference/github/workflow/branches/","title":"Developing on Branches","text":"

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.

"},{"location":"reference/github/workflow/branches/#creating-a-branch","title":"Creating a branch","text":"

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.

Creating a new branch from main
# Switch to main\ngit switch main\n\n# Update your local copy\ngit pull\n\n# Clone a new branch from main\ngit switch -c <branch_name>\n

IMPORTANT: When creating a new branch for an issue, you must create the branch from main.

"},{"location":"reference/github/workflow/branches/#branch-naming-convention","title":"Branch naming convention","text":"

When working on a new issue, you will want to create a branch to work on it. We have the following branch naming convention:

<github_username>/<issue_number>-<issue_description>\n

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.

"},{"location":"reference/github/workflow/branches/#tracking-and-committing-changes","title":"Tracking and committing changes","text":"

All files where new changes have been made must first be \"staged\" in order to make commits:

git add <FILES>\n

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 \"<commit_message>\"\n

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 <current_branch_name>\n
"},{"location":"reference/github/workflow/branches/#merging-branches","title":"Merging branches","text":"

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 BranchMerge Remote Branch
# Checkout to destination branch\ngit checkout <dest_branch>\n\n# Merge with local copy of other branch\ngit merge <other_branch>\n
# Checkout to destination branch\ngit checkout <dest_branch>\n\n# Fetch from remote\ngit fetch\n\n# Merge remote copy of other branch\ngit merge origin/<other_branch>\n

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.

"},{"location":"reference/github/workflow/branches/#resolving-merge-conflicts","title":"Resolving merge conflicts","text":"

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:

Upon inspecting bar.txt, we see the following:

Resolving merge conflicts is not always a trivial task, but there are many ways to resolve them which include:

  • Resolving on GitHub (recommended)
  • Resolving in Command Line

Tip

If you cannot resolve a merge conflict on your own, reach out to your lead for help!

"},{"location":"reference/github/workflow/issues/","title":"Creating Issues","text":"

GitHub issues lets us plan and track our work on GitHub.

"},{"location":"reference/github/workflow/issues/#getting-started-with-issue-templates","title":"Getting started with issue templates","text":"

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.

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.

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.

Note

GitHub issues are written using GitHub-flavoured markdown. To add a little spice to your issues, refer to the official GitHub documentation 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:

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 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!

"},{"location":"reference/github/workflow/issues/#adding-issues-to-a-project","title":"Adding issues to a project","text":"

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.

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).

"},{"location":"reference/github/workflow/issues/#adding-issues-to-a-milestone","title":"Adding issues to a milestone","text":"

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.

Note

Unlike projects, milestones are strictly associated with a repository.

"},{"location":"reference/github/workflow/issues/#labelling-issues","title":"Labelling issues","text":"

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).

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!

"},{"location":"reference/github/workflow/issues/#adding-assignees","title":"Adding assignees","text":"

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.

"},{"location":"reference/github/workflow/issues/#submit-the-issue","title":"Submit the issue","text":"

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.

"},{"location":"reference/github/workflow/overview/","title":"Development Workflow Overview","text":"
graph LR\n    B[Problem Conception] --> C{Small Fix?};\n    C --> |Yes| E[Development];\n    C --> |No| D[Issue Creation];\n    D --> E;\n    E --> F[Pull Request];\n    F --> G{Approved?};\n    G --> |No| E;\n    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.

"},{"location":"reference/github/workflow/overview/#tutorial","title":"Tutorial","text":""},{"location":"reference/github/workflow/overview/#version-control-git","title":"Version control: Git","text":"

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 A 30 minute video on git for beginners. Good if you want to learn git quickly and nail all the fundamentals. Pro Git book 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 A condensed summary of some common git commands. Good to refer to once you are familiar with the fundamentals of git."},{"location":"reference/github/workflow/overview/#remote-server-github","title":"Remote server: GitHub","text":"

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
  • Projects
  • Milestones
  • GitHub Organizations
  • Repository Permissions and Branch Protection Rules
  • And more!
"},{"location":"reference/github/workflow/pr/","title":"Pull Requests","text":"

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.

"},{"location":"reference/github/workflow/pr/#creating-a-pull-request","title":"Creating a pull request","text":"

To create a pull request in a repository, to go the Pull requests tab and then click New pull request:

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.

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):

Notice how this is remarkably similar to the page of an issue. To link a pull request to an issue, simply add <KEYWORD> #<ISSUE NUMBER> to the initial comment in the pull request. A list of valid keywords can be found here.

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.

"},{"location":"reference/github/workflow/pr/#merging-into-main","title":"Merging into main","text":"

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:

"},{"location":"reference/github/workflow/pr/#reviewing-a-pull-request","title":"Reviewing a pull request","text":"

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.

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).
"},{"location":"reference/python/conventions/","title":"Conventions","text":"

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.

"},{"location":"reference/python/conventions/#style-guide","title":"Style guide","text":""},{"location":"reference/python/conventions/#linting","title":"Linting","text":"

To ensure that the codebase stays clean, we use flake8, which is a tool for style guide enforcement mostly based off pep8. To automate most of this process, we use autopep8, 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 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!

"},{"location":"reference/python/conventions/#type-hinting","title":"Type hinting","text":"

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 can be used.

There is some syntax to get familiar in order to use type checking. We recommend the following resources:

  • mypy Typing Cheatsheet
  • PEP 483: The Theory of Type Hints (A Simplified Guide)
  • PEP 484: Type Hints (Fully Comprehensive Guide)

Below are a few examples of using type hinting:

Return the sum of a sequence
from typing import Sequence, Union\n\n\nNumber = Union[int, float]\n\n\ndef sumseq(seq : Sequence[Number]) -> Number:\n    return sum(seq)\n
Function with optional parameters and default values
from typing import Optional\n\n\ndef printArgs(a : str, b : str=\"World\", c : Optional[str]=None) -> None:\n    print(f\"Value of a: {a}\")\n    print(f\"Value of b: {b}\")\n    if c is not None:\n        print(f\"Value of c: {c}\")\n
Function with custom class
class MyClass:\n    def __init__(self) -> None:\n        pass\n\n\ndef foo(a : MyClass) -> None:\n    print(a)\n
Forward referencing a class With __future__Without __future__
from __future__ import annotations\n\n\ndef foo(a : MyClass) -> None:\n    print(a)\n\n\nclass MyClass:\n    def __init__(self) -> None:\n        pass\n
def foo(a : 'MyClass') -> None:\n    print(a)\n\n\nclass MyClass:\n    def __init__(self) -> None:\n        pass\n
Function that never returns
from typing import NoReturn\n\n\ndef bar() -> NoReturn:\n    while True:\n        print(\"Hello World!\")\n
"},{"location":"reference/python/conventions/#documentation","title":"Documentation","text":"

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.

"},{"location":"reference/python/conventions/#generating-docstrings","title":"Generating docstrings","text":"

We use a vscode extension called autoDocstring 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, 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.

"},{"location":"reference/python/conventions/#example-on-documentation","title":"Example on documentation","text":"

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 by default.

Documentation example on a function
from typing import List\ndef inner_product(v1 : List[float], v2 : List[float]) -> float:\n    \"\"\"\n    Computes the inner product between two 1D real vectors. Input vectors should have the\n    same dimensions.\n\n    Args:\n        v1 (List[float]): The first vector of real numbers.\n        v2 (List[float]): The second vector of real numbers.\n\n    Returns:\n        float : The inner product between v1 and v2\n    \"\"\"\n    assert (len(v1) == len(v2)), \"Input lists must have same length\"\n\n    # Iterate through elementwise pairs\n    summation = 0\n    for e1, e2 in zip(v1, v2):\n        summation += (e1 * e2)\n    return float(summation)\n
Documentation example with a stack
from typing import Any\nclass Stack:\n\n    \"\"\"\n    This class represents a stack, which is an abstract data type that serves as a collection of\n    elements. The stack is a LIFO datastructure defined by two main operations: Push and Pop.\n\n    Attributes:\n        __stack (List[Any]): A list containing the elements on the stack.\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"\n        Initializes the Stack object.\n        \"\"\"\n        self.__stack = []\n\n    def push(self, element : Any) -> Any:\n        \"\"\"\n        Pushes an element to the top of the stack.\n\n        Args:\n            element (Any): The element to be pushed on to the stack.\n        \"\"\"\n        self.__stack.append(element)\n\n    def pop(self) -> Any:\n        \"\"\"\n        Removes the element at the top of the stack and returns it. If the stack is empty,\n        then None is returned.\n\n        Returns:\n            Any, NoneType: The element at the top of the stack.\n        \"\"\"\n        if self.is_empty():\n            return None\n        else:\n            return self.__stack.pop()\n\n    def is_empty(self) -> bool:\n        \"\"\"\n        Determines whether the stack is empty or not.\n\n        Returns:\n            bool: Returns True if the stack is empty, and False otherwise.\n        \"\"\"\n        empty = (len(self.__stack) == 0)\n        return empty\n\n    def __len__(self) -> int:\n        \"\"\"\n        Gets the number of elements on the stack.\n\n        Returns:\n            int: The number of elements on the stack.\n        \"\"\"\n        length = len(self.__stack)\n        return length\n

For more examples, see Example Google Style Python Docstrings.

  1. https://realpython.com/lessons/pros-and-cons-type-hints/ \u21a9

"},{"location":"reference/python/start/","title":"Getting Started","text":"

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.

"},{"location":"reference/python/start/#python-tutorials","title":"Python tutorials","text":"

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 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 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 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 A shorter alternative YouTube tutorial condensed into 1 hour. It covers less material but still covers many of the essentials. CodingBat Practice 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!

"},{"location":"reference/python/virtual-environments/","title":"Virtual Environments","text":"

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 and Anaconda. 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.

"},{"location":"reference/python/virtual-environments/#installation","title":"Installation","text":"Virtualenv Anaconda

If you already have python and the pip package manager installed, just execute the following:

Using pip to install virtualenv
pip install virtualenv\n

Go to the official Anaconda website and follow the installation instructions for your operating system.

"},{"location":"reference/python/virtual-environments/#using-virtual-environments","title":"Using virtual environments","text":"

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.

"},{"location":"reference/python/virtual-environments/#creating-a-virtual-environment","title":"Creating a virtual environment","text":"Virtualenv Anaconda

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.

Create virtual environment with virtualenv
# Go to desired location\ncd <PATH TO DIRECTORY>\n\n# Create the environment with the name env\npython3 -m venv env\n

Verify that your environment is created by examining your current directory and look for the directory that matches the name of your virtual environment.

Since the environment will be available globally, there is no need to go to a specific location to create it.

Create virtual environment with Anaconda
# Create environment with name env and python version\nconda env create -n env python=<PYTHON VERSION NUM>\n

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.

"},{"location":"reference/python/virtual-environments/#activating-the-virtual-environment","title":"Activating the virtual environment","text":"

To use the virtual environment, you must activate it.

Virtualenv Anaconda Windows macOS Linux Activation for Windows
env\\Scripts\\activate\n
Activation for macOS
source env/bin/activate\n
Activation for Linux
source env/bin/activate\n
Activation for Anaconda
conda activate env\n

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!

"},{"location":"reference/python/virtual-environments/#installing-dependencies","title":"Installing dependencies","text":"

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!

Virtualenv Anaconda

Use the pip package manager to install python dependencies. Before installing any Python dependencies, it is good practice to upgrade pip:

Upgrade pip
pip install --upgrade pip\n

Now, install any Python dependencies pip:

Install dependency with pip
pip install <PACKAGE>\n
Option 1: pipOption 2: conda

Use the pip package manager to install python dependencies.

Install dependency with pip
# Install pip using conda\nconda install pip\n\n# Install python packages using pip\npip install <PACKAGE>\n

Use the built-in conda package manager to install python dependencies.

Install dependency with conda
conda install -c <CHANNEL> <PACKAGE>\n

Sometimes, installing a package like this simply won't work because you are not installing from the correct channel. 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
"},{"location":"reference/python/virtual-environments/#deactivating-the-virtual-environment","title":"Deactivating the virtual environment","text":"

When you are finished using your virtual environment, you will need to deactivate it.

Virtualenv Anaconda Deactivate virtualenv environment
deactivate\n
Deactivate anaconda environment
conda deactivate\n
"},{"location":"reference/python/virtual-environments/#reproducing-your-virtual-environment","title":"Reproducing your virtual environment","text":"

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.

"},{"location":"reference/python/virtual-environments/#exporting-your-virtual-environment","title":"Exporting your virtual environment","text":"

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.

Virtualenv Anaconda

You will create a requirements.txt file, which essentially lists all of your python dependencies in one file:

Creating requirements file
pip freeze > requirements.txt\n

The pip freeze command prints all of your pip dependencies, and > requirements.txt redirects the output to a text file.

Anaconda uses configuration files to recreate an environment.

Windows macOS Linux

Execute the following command to create a file called environment.yml:

Create config file
conda env export > environment.yml\n

Then, open the environment.yml file and delete the line with prefix:.

Execute the following command to create a file called environment.yml:

Create config file
conda env export | grep -v \"^prefix: \" > environment.yml\n

Execute the following command to create a file called environment.yml:

Create config file
conda env export | grep -v \"^prefix: \" > environment.yml\n
"},{"location":"reference/python/virtual-environments/#reproducing-the-environment","title":"Reproducing the environment","text":"

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.

Virtualenv Anaconda

We use the requirements.txt file that we generated earlier to recreate the environment.

Recreate virtualenv environment
# Create the new environment\npython -m venv <NEW ENV NAME>\n\n# Activate the environment\nsource <NEW ENV NAME>/bin/activate\n\n# Install dependencies\npip install -r <PATH TO requirements.txt file>\n

We use the environment.yml file that we generated earlier to recreate the environment.

Recreate the conda environment
# Create the new environment with the dependencies\nconda env create -f <PATH TO environment.yml> -n <ENV NAME>\n
"},{"location":"reference/python/virtual-environments/#official-references","title":"Official references","text":"

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
  • Anaconda Reference
"},{"location":"reference/sailing/ais_terms/","title":"AIS Terms","text":"

This section explains the most unfamiliar fields that we receive from the AIS.

"},{"location":"reference/sailing/ais_terms/#mmsi-aka-id","title":"MMSI a.k.a ID","text":"

A 9-digit, unique identification number for the ship.

"},{"location":"reference/sailing/ais_terms/#cog-course-over-ground","title":"COG: Course over Ground","text":"

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.

This is measured with the navigational angle convention, where 0\u00b0 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.
"},{"location":"reference/sailing/ais_terms/#sog-speed-over-ground","title":"SOG: Speed over Ground","text":"

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.

\\(\\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.
"},{"location":"reference/sailing/ais_terms/#rot-rate-of-turn","title":"RoT: Rate of Turn","text":"

The angular velocity of the boat (how fast it's turning), measured in degrees per minute.

"},{"location":"reference/sailing/boat_parts/","title":"Parts of a Sailboat","text":"

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.

"},{"location":"reference/sailing/boat_parts/#hull","title":"Hull","text":"

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.

"},{"location":"reference/sailing/boat_parts/#jib","title":"Jib","text":"

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.
"},{"location":"reference/sailing/boat_parts/#mast","title":"Mast","text":"

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.
"},{"location":"reference/sailing/boat_parts/#main-sail","title":"Main Sail","text":"

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.
"},{"location":"reference/sailing/boat_parts/#conclusion","title":"Conclusion","text":"

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.

"},{"location":"reference/sailing/boat_parts/#keywords-on-this-page","title":"Keywords on this Page","text":"
  • Hull
  • Keel
  • Rudder
  • Bow
  • Stern
  • Starboard
  • Port
  • Jib
  • Jib winch
  • Mast
  • Wind Sensor
  • AIS Antenna
  • Main Sail
  • Main Winch
"},{"location":"reference/sailing/miscellaneous/","title":"Miscellaneous Sailing Knowledge","text":"

This section covers some other useful information.

"},{"location":"reference/sailing/miscellaneous/#wind-direction-convention","title":"Wind Direction Convention","text":"

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\u00b0 means the wind is blowing from North to South.
  2. The angle tells you which way the wind is coming from. For example, 0\u00b0 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.

"},{"location":"reference/sailing/miscellaneous/#navigation-terms","title":"Navigation Terms","text":""},{"location":"reference/sailing/miscellaneous/#heading","title":"Heading","text":"

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.

"},{"location":"reference/sailing/miscellaneous/#bearing","title":"Bearing","text":"

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\u00b0 is towards the North, angles increase in the clockwise direction, and angles are typically bounded within [0\u00b0, 360\u00b0)]
  • A Relative Bearing is a bearing where the angle convention is as follows: 0\u00b0 is straight forwards relative to the boat, and angle measurements increase in the clockwise direction. Angles may be bounded in [-180\u00b0, 180\u00b0) or [0\u00b0, 360\u00b0)

In the example below, the boat \"B\" has a Heading (H) of 30\u00b0. The True Bearing (\\(B_t\\)) of the Lighthouse \"A\" from the boat is 90\u00b0. The Relative Bearing (\\(B_r\\)) of the lighthouse from the boat is 60\u00b0.

"},{"location":"reference/sailing/miscellaneous/#track-made-good","title":"Track Made Good","text":"

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.

"},{"location":"reference/sailing/miscellaneous/#heading-and-bearing-in-raye-project","title":"Heading and Bearing in Raye Project","text":"

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\u00b0 mean? If 0\u00b0 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\u00b0 means towards the East, angles increase in the counter-clockwise direction, and angles are bounded in [-180\u00b0, 180\u00b0). This is effectively the main angle convention used in most math courses.
  • 0\u00b0 means towards the North, angles increase in the clockwise direction, and angles are bounded in [0\u00b0, 360\u00b0). 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.

"},{"location":"reference/sailing/miscellaneous/#true-apparent-and-boat-wind","title":"True, Apparent, and Boat Wind","text":"
  • 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\u00b0\\).

"},{"location":"reference/sailing/miscellaneous/#tack","title":"Tack","text":"

In the Types of Turn 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.

  • Finally, the Tack can refer to particular region of the main sail. This is not important for software members.
"},{"location":"reference/sailing/miscellaneous/#keywords-on-this-page","title":"Keywords on this Page","text":"
  • Heading
  • Bearing
  • Track Made Good
  • Global Wind (aka True Wind)
  • Measured Wind (aka Apparent Wind)
  • Tack
"},{"location":"reference/sailing/overview/","title":"Sailing Knowledge Section Overview","text":"

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.

"},{"location":"reference/sailing/overview/#tutorial","title":"Tutorial","text":""},{"location":"reference/sailing/points_of_sail/","title":"Points of Sail","text":"

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.

"},{"location":"reference/sailing/points_of_sail/#irons","title":"Irons","text":"

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.

"},{"location":"reference/sailing/points_of_sail/#upwind-sailing","title":"Upwind Sailing","text":"

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.

"},{"location":"reference/sailing/points_of_sail/#downwind-sailing","title":"Downwind Sailing","text":"

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.

"},{"location":"reference/sailing/points_of_sail/#keywords-on-this-page","title":"Keywords on this Page","text":"
  • Irons (aka No-Go Zone)
  • Upwind Sailing
  • Close Hauled
  • Downwind Sailing
"},{"location":"reference/sailing/turning/","title":"Types of Turns","text":"

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.

"},{"location":"reference/sailing/turning/#classifying-types-of-turns-summary","title":"Classifying Types Of Turns Summary","text":"

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
graph LR\n    B[Classify a Turn] --> C{Does the sail change<br/>sides during the turn?};\n    C --> |Yes| E{Which end of<br/>the boat is upwind<br/>during the turn?};\n    C --> |No| D{Does the<br/>boat point higher<br/>or lower at the end<br/>of the turn?};\n    D --> |Higher| F[Heading Up];\n    D --> |Lower| G[Bearing Off];\n    E --> |Bow| H[Tack];\n    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.

"},{"location":"reference/sailing/turning/#heading-up","title":"Heading Up","text":"

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.

"},{"location":"reference/sailing/turning/#bearing-off","title":"Bearing Off","text":"

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.

"},{"location":"reference/sailing/turning/#tacking","title":"Tacking","text":"

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\u00b0) turn all at once, so that the boat's momentum carries it through the range of angles where it does not get propulsion.

"},{"location":"reference/sailing/turning/#gybing","title":"Gybing","text":"

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\u00b0 turn.

Note that \"gybe\" is the spelling used in Canadian and British english, whereas in American english it is spelled \"Jibe\"

"},{"location":"reference/sailing/turning/#combinations-of-turns","title":"Combinations of Turns","text":"

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?

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.

"},{"location":"reference/sailing/turning/#keywords-on-this-page","title":"Keywords on this Page","text":"
  • Higher (in relation to pointing)
  • Lower (in relation to pointing)
  • Heading Up
  • Bearing Off
  • Tack
  • Gybe (aka Jibe)
"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-,:!=\\[\\]()\"/]+|(?!\\b)(?=[A-Z][a-z])|\\.(?!\\d)|&[lg]t;","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"UBCSailbot Software Team Docs","text":"

Welcome to the UBC Sailbot software team docs

Looking to get started with running the Sailbot codebase? Start by setting up the Sailbot Workspace:

Getting Started

"},{"location":"#what-information-is-on-this-website","title":"What information is on this website?","text":"

Information on our current project is contained on this website. In particular, information on each of our major software projects are provided in detail.

Current Project Overview

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.

Software Team References

"},{"location":"#who-is-this-website-for","title":"Who is this website for?","text":"

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.

"},{"location":"#prospective-members","title":"Prospective Members","text":"

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!

Software Team Posting

Apply to join UBC Sailbot

"},{"location":"about_us/","title":"About Us","text":"

UBC Sailbot is an engineering design team at The University of British Columbia that designs, constructs, and tests autonomous sailboats. We have 3 technical sub-teams: Mechanical, Electrical, and Software.

This repository, sailbot_workspace, contains all the code, infrastructure, and documentation for the project we are currently working on, Polaris.

To learn more about what the UBC Sailbot Software Team does, read our Team Posting. If you are a UBC student interested in joining, you can apply here.

"},{"location":"current/overview/","title":"Current Project Overview","text":"

Our current project, Polaris, is an autonomous research vessel capable of collecting oceanic and atmospheric data. With our expertise in autonomous sailing, the goal is to monitor the health of our oceans while collaborating with stakeholders and researchers involved in climate science and oceanography.

The software team is responsible for designing, implementing, and testing the software system of our autonomous sailboats. We work on both low-level and high-level integration, from interfacing with sensors to planning sea routes with pathfinding algorithms.

"},{"location":"current/overview/#dataflow","title":"Dataflow","text":"

The software architecture for our next autonomous sailboat is split across two computers: the on board computer on board and the remote server off board. The following paragraphs will follow the flow of data between the software components (bolded) on each computer.

On the remote server, global pathfinding uses the A* pathfinding algorithm to create a sailing path, a list of global waypoints from the current position to destination. Global sailing paths are sent via the Remote Transceiver to the Local Transceiver on the on board computer.

On the on board computer, the CAN Transceiver receives GPS and wind data from their respective sensors. This raw data is filtered before being used in the other software components. Local Pathfinding uses GPS and wind data, as well as the global path and AIS data from the AIS Receiver, to create a local path, a list of local waypoints from the current position to the next global waypoint. The Controller uses wind data and the relative bearing to the local path to adjust the rudder and sails accordingly. The state of the boat and research data we collect is sent via the Local Transceiver to the Remote Transceiver on the remote server.

Back on the remote server, the Website presents the boat state and research data for monitoring and analysis purposes. The Remote Transceiver additionally includes manual overrides such as resetting the boat state and modifying the global path.

As for the communication mediums, the computers communicate via satellite, and components on the on board computer communicate through the Robot Operating System framework, or ROS for short.

For software development purposes, all software components will be able to run and communicate with each other locally. To accomplish this, we will:

  1. Create a development environment that has all software component dependencies: Sailbot Workspace.
  2. Develop accurate simulations of the environment and hardware: Simulator, Mock AIS, Mock Global Pathfinding.
  3. Add configuration options to select between real and simulated hardware as well as running remote server components remotely or locally.
"},{"location":"current/overview/#diagrams","title":"Diagrams","text":"

In these diagrams, the bubbles represent components of our software system, and the direction of arrows connecting the bubbles represent the flow of data between them. The color of the bubbles denote the sub-team leading their development:

  • Purple: Controls
  • Green: Network Systems
  • Blue: Pathfinding
  • Red: Website
  • White: Not a part of the Software Team's codebase

Components that are used in both the production and development environments are darker, while ones that are only used in one are lighter.

Interacting with the diagram

  • To switch between the production and development environment diagrams, hover over the image to make the toolbar visible and navigate with the arrows on the left side
"},{"location":"current/boat_simulator/overview/","title":"Overview","text":"

Source code

The source code for Boat Simulator can be found in src/boat_simulator. Its README has been copied below.

"},{"location":"current/boat_simulator/overview/#ubc-sailbot-boat-simulator","title":"UBC Sailbot Boat Simulator","text":"

UBC Sailbot's boat simulator for the new project. This repository contains a ROS package boat_simulator. This README contains only setup and run instructions. Further information on the boat simulator can be found on the software team's docs website.

"},{"location":"current/boat_simulator/overview/#setup","title":"Setup","text":"

The boat simulator is meant to be ran inside the Sailbot Workspace development environment. Follow the setup instructions for the Sailbot Workspace here to get started and build all the necessary ROS packages.

"},{"location":"current/boat_simulator/overview/#run","title":"Run","text":"

The launch/ folder contains a ROS 2 launch file responsible for starting up the boat simulator. To run the boat simulator standalone, execute the launch file after building the boat_simulator package:

ros2 launch boat_simulator main_launch.py [OPTIONS]...\n

To see a list of options for simulator configuration, add the -s flag at the end of the above command.

"},{"location":"current/boat_simulator/overview/#test","title":"Test","text":"

Run the test task in the Sailbot Workspace. See here on how to run vscode tasks.

"},{"location":"current/controller/overview/","title":"Overview","text":"

Source code

The source code for Controller can be found in src/controller. Its README has been copied below.

"},{"location":"current/controller/overview/#controller","title":"Controller","text":"

UBC Sailbot's controller for the new project. This repository contains a ROS package controller. This README contains only setup and run instructions. Further information on the controller can be found on the software team's docs website.

"},{"location":"current/controller/overview/#setup","title":"Setup","text":"

The controller is meant to be ran inside the Sailbot Workspace development environment. Follow the setup instructions for the Sailbot Workspace here to get started and build all the necessary ROS packages.

"},{"location":"current/controller/overview/#run","title":"Run","text":"

The launch/ folder contains a ROS 2 launch file responsible for starting up the controller. To run the controller standalone, execute the launch file after building the controller package:

ros2 launch controller main_launch.py [OPTIONS]...\n

To see a list of options for configuration, add the -s flag at the end of the above command.

"},{"location":"current/controller/overview/#test","title":"Test","text":"

Run the test task in the Sailbot Workspace. See here on how to run vscode tasks.

"},{"location":"current/custom_interfaces/overview/","title":"Overview","text":"

Source code

The source code for Custom Interfaces can be found in src/custom_interfaces. Its README has been copied below.

"},{"location":"current/custom_interfaces/overview/#custom-interfaces","title":"Custom Interfaces","text":"

UBC Sailbot's custom interfaces ROS package. To add custom_interfaces to another ROS package, follow the instructions here.

The terminology that we use in this document are the following:

  • External Interface: An interface used to communicate data between nodes and ROS packages.
  • Internal Interface: An interface used to standardize conventions across external interfaces. Standards are documented in the .msg or .srv file associated with that interface.
"},{"location":"current/custom_interfaces/overview/#project-wide-interfaces","title":"Project-wide Interfaces","text":"

ROS messages and services used across many ROS packages in the project.

"},{"location":"current/custom_interfaces/overview/#project-wide-external-interfaces","title":"Project-wide External Interfaces","text":""},{"location":"current/custom_interfaces/overview/#project-wide-internal-interfaces","title":"Project-wide Internal Interfaces","text":"Interface Used In HelperAISShip AISShips HelperBattery Batteries HelperDimension HelperAISShip HelperGenericSensor GenericSensors HelperHeading DesiredHeading, GPS, HelperAISShip HelperLatLon GPS, HelperAISShip, Path HelperROT HelperAISShip HelperSpeed GPS, HelperAISShip, WindSensor"},{"location":"current/custom_interfaces/overview/#boat-simulator-interfaces","title":"Boat Simulator Interfaces","text":"

ROS messages and services used in our boat simulator.

"},{"location":"current/custom_interfaces/overview/#boat-simulator-external-interfaces","title":"Boat Simulator External Interfaces","text":"Topic Type Publisher Subscriber(s) mock_kinematics SimWorldState Simulator Physics Engine Simulator Visualizer"},{"location":"current/custom_interfaces/overview/#boat-simulator-actions","title":"Boat Simulator Actions","text":"Action Client Node Server Node SimRudderActuation Simulator Physics Engine Simulator Low Level Controller SimSailTrimTabActuation Simulator Physics Engine Simulator Low Level Controller"},{"location":"current/custom_interfaces/overview/#resources","title":"Resources","text":""},{"location":"current/custom_interfaces/overview/#common-interfaces","title":"Common Interfaces","text":"

The ROS2 common_interfaces repository defines a set of packages which contain common interface files. Since we are using the Humble version of ROS2, see the humble branch. These interfaces can be used in this repository or as a reference for ideas and best practices.

Package Possible Usage diagnostic_msgs Could be used for website sensors geometry_msgs Simulator, Local Pathfinding sensor_msgs Reference for CAN Transceiver std_msgs Reference std_srvs Reference visualization_msgs Reference

For more detail on the usefulness of each package, see this issue comment. If you are interested in creating your own custom message or service, see the ROS Humble documentation.

"},{"location":"current/local_pathfinding/overview/","title":"Overview","text":"

Source code

The source code for Local Pathfinding can be found in src/local_pathfinding. Its README has been copied below.

"},{"location":"current/local_pathfinding/overview/#local-pathfinding","title":"Local Pathfinding","text":"

UBC Sailbot's local pathfinding ROS package

"},{"location":"current/local_pathfinding/overview/#run","title":"Run","text":"

Using main launch file: ros2 launch local_pathfinding main_launch.py

"},{"location":"current/local_pathfinding/overview/#launch-parameters","title":"Launch Parameters","text":"

Launch arguments are added to the run command in the format <name>:=<value>.

name description value log_level Logging level A severity level (case insensitive)"},{"location":"current/local_pathfinding/overview/#server-files","title":"Server Files","text":"

The server files: get_server.py and post_server.py are basic http server files which are used for testing the global_path module's GET and POST methods.

"},{"location":"current/network_systems/overview/","title":"Overview","text":"

Source code

The source code for Network Systems can be found in src/network_systems. Its README has been copied below.

"},{"location":"current/network_systems/overview/#network-systems","title":"Network Systems","text":"

This repository contains the source code for all of UBC Sailbot's Network Systems programs. It is made to work as part of Sailbot Workspace, and is not meant to be built as an independent project.

"},{"location":"current/network_systems/overview/#setup","title":"Setup","text":"

For comprehensive setup instructions, follow our setup guide.

"},{"location":"current/network_systems/overview/#building","title":"Building","text":"

Option A: With sailbot_workspace open, invoke the VSCode build or debug task.

Option B: Run /workspaces/sailbot_workspace/build.sh

"},{"location":"current/network_systems/overview/#running","title":"Running","text":""},{"location":"current/network_systems/overview/#ros-launch","title":"ROS Launch","text":"

Instructions found here.

For example:

ros2 launch network_systems main_launch.py\n

This is the best option if multiple modules need to be run at once. Launch configurations are found under the config folder. These configurations define which modules to enable/disable and what parameters to use.

"},{"location":"current/network_systems/overview/#ros-run","title":"ROS Run","text":"

If you just want to run a single module, then this is a direct and easy way to do it.

For example:

ros2 run network_systems example --ros-args -p enabled:=true\n
"},{"location":"current/network_systems/overview/#binary","title":"Binary","text":"

Not recommended as you cannot pass ROS parameters, so modules may not work by default. Binaries for each module found under projects can be found under /workspaces/sailbot_workspace/build/network_systems/projects/{module_name}/{module_name}.

For example:

/workspaces/sailbot_workspace/build/network_systems/projects/example/example\n
"},{"location":"current/network_systems/overview/#testing","title":"Testing","text":"

Unit tests specific to Network Systems is done using GoogleTest. Unit tests are defined per module. For example, under projects/example/test/.

"},{"location":"current/network_systems/overview/#run-all-tests","title":"Run All Tests","text":"

Option A: With sailbot_workspace open, invoke the VSCode test task.

Option B: Under the sailbot_workspace directory, run /workspaces/sailbot_workspace/scripts/test.sh

Both options will run all of UBC Sailbot's tests, including those from other projects. More often than not, this is unnecessary.

"},{"location":"current/network_systems/overview/#run-and-debug-specific-tests","title":"Run and Debug Specific Tests","text":"

This is the preferred way to run and debug tests. When you open a test source file like the example's, there will be green arrows next to each TEST_F macro. Clicking a double green arrow runs a test suite, while clicking single green arrow runs one unit test. Right clicking either arrow will open a prompt with a debug test option. When running a test via the debug option, we can set breakpoints and step through our code line by line to resolve issues.

This convenient testing frontend is thank's to the TestMate extension.

Warning: Large failing tests can crash VSCode. If this happens, either lower the size of the tests (ex. reduce the number of iterations) or run the test binary directly.

"},{"location":"current/network_systems/overview/#run-test-binaries","title":"Run Test Binaries","text":"

Test binaries for each module found under projects can be found under /workspaces/sailbot_workspace/build/network_systems/projects/{module_name}/test_{module_name}.

For example:

/workspaces/sailbot_workspace/build/network_systems/projects/example/test_example\n
"},{"location":"current/sailbot_workspace/overview/","title":"Overview","text":"

Source code

The Sailbot Workspace README has been copied below.

"},{"location":"current/sailbot_workspace/overview/#sailbot-workspace","title":"Sailbot Workspace","text":"

This repository will get you set up to develop UBCSailbot's software on VS Code. It is based on athackst's vscode_ros2_workspace.

"},{"location":"current/sailbot_workspace/overview/#features","title":"Features","text":"

An overview of Sailbot Workspace's features can be found below. See our docs site for how to use these features.

"},{"location":"current/sailbot_workspace/overview/#style","title":"Style","text":"

C++ and Python linters and formatters are integrated into Sailbot Workspace:

  • ament_flake8
  • ament_lint_cmake
  • ament_xmllint
  • black
  • clang-tidy
  • isort

The ament linters are configured to be consistent with the ROS style guide.

"},{"location":"current/sailbot_workspace/overview/#dev-container","title":"Dev Container","text":"

Dev Containers enable us to use a Docker container as a fully-featured development environment containing all our configuration and dependencies. Our Dev Container configuration can be found in .devcontainer/.

"},{"location":"current/sailbot_workspace/overview/#multi-root-workspace","title":"Multi-Root Workspace","text":"

Workspaces are VS Code instances that contain one or more folders. Our workspace configuration file can be found at sailbot.code-workspace.

Our software spans many repositories: software team repositories. Multi-root workspaces make it easy to work with multiple repositories at the same time. Our roots are defined in the folders section of our workspace file.

"},{"location":"current/sailbot_workspace/overview/#debugging","title":"Debugging","text":"

Launch configurations have been created to debug our software. They are defined in the launch section of our workspace file.

"},{"location":"current/sailbot_workspace/overview/#tasks","title":"Tasks","text":"

Tasks provide an alternative to memorizing the multitude of CLI commands we use to setup, build, lint, test, and run our software. They are defined in tasks section of our workspace file.

"},{"location":"current/sailbot_workspace/overview/#continuous-integration","title":"Continuous Integration","text":"

Actions were used to build our Docker containers and lint and test our code the same way it is done locally in Sailbot Workspace on GitHub. We use a reusable workflow to create a single source of truth for our tests across all our repositories. Our CI can be found in .github/workflows/.

"},{"location":"current/sailbot_workspace/overview/#customization","title":"Customization","text":"

This repository supports user-specific configuration files. To set this up, see How to use your dotfiles.

"},{"location":"current/sailbot_workspace/overview/#run-rayes-software","title":"Run Raye's Software","text":"

Raye was our previous project. Her software can be run in the raye branch following the instructions in How to run Raye's software. The initial differences between the main and raye branches are summarized in this PR.

"},{"location":"current/sailbot_workspace/overview/#documentation","title":"Documentation","text":"

Further documentation, including setup and run instructions, can be found on our Docs website.

"},{"location":"current/sailbot_workspace/overview/#tutorial","title":"Tutorial","text":"

Disclaimer

This tutorial was done a while ago, so some parts may no longer be relevant. For the most up to date information, consult the docs pages and the software leads.

"},{"location":"current/sailbot_workspace/scripts/","title":"Scripts","text":"

Source code

Our scripts can be found in scripts. Its README has been copied below.

"},{"location":"current/sailbot_workspace/scripts/#scripts","title":"Scripts","text":""},{"location":"current/sailbot_workspace/scripts/#how-to-run","title":"how to run","text":"

All scripts in this directory should be able to be run with ./path/to/script (excluding arguments). For this to work, the script will need to have a shebang and be executable. For more details, see this tutorial.

"},{"location":"current/sailbot_workspace/scripts/#ament-lintsh","title":"ament-lint.sh","text":"

Script to lint source code in all ROS packages.

"},{"location":"current/sailbot_workspace/scripts/#buildsh","title":"build.sh","text":"

Script to build all ROS packages in the Sailbot Workspace.

"},{"location":"current/sailbot_workspace/scripts/#clang-tidysh","title":"clang-tidy.sh","text":"

Script to run Clang-Tidy using ament_clang_tidy.py.

"},{"location":"current/sailbot_workspace/scripts/#run_virtual_iridiumsh","title":"run_virtual_iridium.sh","text":"
./run_virtual_iridium.sh <(optional) webhook server url> <(optional) virtual iridium http server port>\n

Creates a pair of socat sockets $LOCAL_TRANSCEIVER_TEST_PORT and $VIRTUAL_IRIDIUM_PORT and binds the latter to a virtual iridium server running on localhost:8080, which substitutes the Rockblock HTTP server used in deployment. Allows testing of satellite code without needing physical hardware.

Optional argument - webhook server url:

  • Specify where the URL where the Remote Transceiver or whatever other HTTP server is running.
  • Default is http://127.0.0.1:8081, which assumes fully local testing.

Optional argument - virtual iridium server port

  • Specify which localhost port the virtual iridium runs on.
  • Default is 8080.

$LOCAL_TRANSCEIVER_TEST_PORT acts as the serial port for AT commands. For example, to test via CLI:

  1. ./run_virtual_iridium.sh
  2. To monitor just the $LOCAL_TRANSCEIVER_TEST_PORT without extra debug messages, in a new terminal run cat $LOCAL_TRANSCEIVER_TEST_PORT. What you see output from this command will be what the Local Transceiver reads and sends.
  3. To issue CLI commands, open a new terminal and run stty 19200 < $LOCAL_TRANSCEIVER_TEST_PORT to set the baud rate.
  4. printf \"at+sbdix\\r\" > $LOCAL_TRANSCEIVER_TEST_PORT. This command queries the (currently empty) mailbox.
  5. curl -X POST -F \"test=1234\" http://localhost:8080 (this is garbage data - it doesn't mean anything). You should see the original terminal print that it received a POST request.
  6. printf \"at+sbdix\\r\" > $LOCAL_TRANSCEIVER_TEST_PORT to view the mailbox again. It will now indicate that it has the data.

Other relevant commands include (but are not limited to):

  • at+sbdwb=<msg_length>\\r: Setup the port to receive binary data of length msg_length on next input.
  • at+sbdrb\\r: Read binary content in the mailbox.
  • at+sbdd2\\r: Clear all buffers.
"},{"location":"current/sailbot_workspace/scripts/#run-testssh","title":"run-tests.sh","text":"

Script to setup, build, and test all ROS packages.

"},{"location":"current/sailbot_workspace/scripts/#run_softwaresh","title":"run_software.sh","text":"

Script to setup, build, and run all ROS packages.

"},{"location":"current/sailbot_workspace/scripts/#setupsh","title":"setup.sh","text":"

Script to handle ROS setup.

"},{"location":"current/sailbot_workspace/scripts/#testsh","title":"test.sh","text":"

Script to run tests in all ROS packages.

"},{"location":"current/sailbot_workspace/reference/deployment/","title":"Deployment","text":"

Source code

The source code for deployment can be found in scripts/deployment. Its README has been copied below.

"},{"location":"current/sailbot_workspace/reference/deployment/#deployment","title":"Deployment","text":"

Deploying our software to our autonomous sailboat's main computer.

"},{"location":"current/sailbot_workspace/reference/deployment/#scripts","title":"Scripts","text":""},{"location":"current/sailbot_workspace/reference/deployment/#setup_bootsh","title":"setup_boot.sh","text":"

Configures programs and scripts that need to run when the main computer boots. Only needs to be run once unless the script is updated. Does not need to be rerun if any scripts or programs it targets are updated, with the exception of renaming or moving the file.

Usage:

  • Must be run as root: sudo ./setup_boot.sh
"},{"location":"current/sailbot_workspace/reference/deployment/#start_containerssh","title":"start_containers.sh","text":"

Runs our Docker Compose files. You may have to install commands like wget. Would recommend running this script in its own clone of sailbot_workspace (not the one you open in VS Code).

Usage:

  • Runs the global launch file by default: ./start_containers.sh
  • Add the --website argument to additionally run the website container
  • Add the --interactive argument to manually run commands in the sailbot workspace container
  • Add the --help argument to see all available arguments
"},{"location":"current/sailbot_workspace/reference/docker_images/","title":"Docker Images","text":"

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 Ubuntu 22.04 base-dev.Dockerfile To install ROS or OMPL Personal computer base pre-base base-dev.Dockerfile To install core dependencies Workflow dispatch local-base base base-dev.Dockerfile To install core dev dependencies Workflow dispatch dev local-base base-dev.Dockerfile To install dev dependencies Workflow dispatch Dev Container dev Dockerfile To configure the Dev Container VS Code docs mkdocs-material docs.Dockerfile To install and run docs site VS Code (optional) website javascript-node website.Dockerfile To install and run website VS Code (optional)"},{"location":"current/sailbot_workspace/reference/docs_site/","title":"Docs Site","text":"

UBCSailbot software team's documentation site. It is meant to be developed in Sailbot Workspace in conjunction with our other software, but doesn't have to be. There are instructions for both cases below.

"},{"location":"current/sailbot_workspace/reference/docs_site/#setup","title":"Setup","text":""},{"location":"current/sailbot_workspace/reference/docs_site/#setup-in-sailbot-workspace","title":"Setup in Sailbot Workspace","text":"
  1. Uncomment docs/docker-compose.docs.yml in .devcontainer/devcontainer.json
  2. Uncomment 8000:8000 in .devcontainer/docker-compose.yml
  3. Rebuild the Dev Container

Refer to How to work with containerized applications for more details.

"},{"location":"current/sailbot_workspace/reference/docs_site/#setup-standalone","title":"Setup Standalone","text":"
  1. Manually install social plugin OS dependencies

  2. Install Python dependencies

    pip install --upgrade pip pip install -Ur docs/requirements.txt

    • Can do this in a Python virtual environment
"},{"location":"current/sailbot_workspace/reference/docs_site/#run","title":"Run","text":""},{"location":"current/sailbot_workspace/reference/docs_site/#run-in-sailbot-workspace","title":"Run in Sailbot Workspace","text":"

After setup, the Docs site should be running on port 8000.

Refer to How to work with containerized applications for more details.

"},{"location":"current/sailbot_workspace/reference/docs_site/#run-standalone","title":"Run Standalone","text":"
mkdocs serve\n
"},{"location":"current/sailbot_workspace/reference/docs_site/#update-dependencies","title":"Update Dependencies","text":"

This site is built using the latest versions of dependencies in docs/requirements.txt at the time of the most recent commit to the main branch. To see exactly how the site will look when deployed, ensure your local dependencies are up to date.

"},{"location":"current/sailbot_workspace/reference/docs_site/#update-dependencies-in-sailbot-workspace","title":"Update Dependencies in Sailbot Workspace","text":"

Rebuild the Dev Container.

"},{"location":"current/sailbot_workspace/reference/docs_site/#update-dependencies-by-itself","title":"Update Dependencies By Itself","text":"
pip install -Ur docs/requirements.txt\n
"},{"location":"current/sailbot_workspace/reference/docs_site/#maintain","title":"Maintain","text":""},{"location":"current/sailbot_workspace/reference/docs_site/#contribute-to-this-site","title":"Contribute to This Site","text":"

Read our Markdown Reference Page for the syntax supported by this site.

"},{"location":"current/sailbot_workspace/reference/docs_site/#delete-docs-versions","title":"Delete Docs Versions","text":"

A version of the docs site is created when a PR is open, and is deleted when it is merged or closed. However, the CI that does this is very finicky, so if 2 PR's are trying to update the site at the exact same time one might fail.

This is especially annoying if this happens to be one that deletes a version, because this means that there is a version still open for a merged/closed PR. To manually clean up these PR's, run the following commands in the docs container (in Docker Desktop, the exec tab):

git config user.name <your github username>\ngit config user.email <your github email>\nmike delete --push pr-<number>\n

If you get an error that your local copy of the gh-pages branch has diverged from the remote, you can delete it with git branch -D gh-pages and rerun the mike delete command above.

It will probably ask you to login to GitHub: enter your username then a GitHub access token with write permission.

"},{"location":"current/sailbot_workspace/reference/launch_files/","title":"ROS Launch Files in Sailbot Workspace","text":"

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.

"},{"location":"current/sailbot_workspace/reference/launch_files/#tutorial","title":"Tutorial","text":""},{"location":"current/sailbot_workspace/reference/launch_files/#launch-file-architecture","title":"Launch File Architecture","text":"

There are two launch processes that we utilize: namely the Package Launch Process and the Global launch process.

"},{"location":"current/sailbot_workspace/reference/launch_files/#the-package-launch-process","title":"The Package Launch Process","text":"

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.
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.

"},{"location":"current/sailbot_workspace/reference/launch_files/#the-global-launch-process","title":"The Global Launch Process","text":"

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.
"},{"location":"current/sailbot_workspace/reference/launch_files/#invoking-launch-files","title":"Invoking Launch Files","text":"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 Cmd+C for Mac OS

"},{"location":"current/sailbot_workspace/reference/launch_files/#package-launch","title":"Package Launch","text":"

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:

CLI VS Code

Either the package and launch file name, or the path to the launch file can be used:

  • Method 1: ros2 launch <package> <launch file>. This method can only be used when a launch file is part of a built ROS package.
  • Method 2: ros2 launch <path to launch file>. This method can be used regardless if a launch file is in a ROS package or not.

Launch via CLI Examples

Let's launch local pathfinding using both CLI methods:

Method 1

ros2 launch local_pathfinding main_launch.py\n

Method 2

ros2 launch $ROS_WORKSPACE/src/local_pathfinding/launch/main_launch.py\n

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.

"},{"location":"current/sailbot_workspace/reference/launch_files/#global-launch","title":"Global Launch","text":"

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.

CLI VS Code

Run the entire system with the following CLI command:

ros2 launch $ROS_WORKSPACE/src/global_launch/main_launch.py\n

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.

"},{"location":"current/sailbot_workspace/reference/launch_files/#using-cli-arguments","title":"Using CLI Arguments","text":"

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\":

ros2 launch local_pathfinding main_launch.py log_level:=debug\n

It can also be ran with the VS Code command named ROS: Launch.

Passing arguments takes the form of <arg name>:=<arg value>. To list the arguments that a launch file takes, simply add the -s flag at the end of the launch command.

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:

ros2 launch $ROS_WORKSPACE/src/global_launch/main_launch.py -s\n

The following output is observed in the terminal (as of September 2023):

Arguments (pass arguments as '<name>:=<value>'):\n\n'config':\n    Path to ROS parameter config file. Controls ROS parameters passed into ROS nodes\n    (default: '/workspaces/sailbot_workspace/src/global_launch/config/globals.yaml')\n\n'log_level':\n    Logging severity level. A logger will only process log messages with severity levels at or higher than the\n    specified severity. Valid choices are: ['debug', 'info', 'warn', 'error', 'fatal']\n    (default: 'info')\n\n'mode':\n    System mode. Decides whether the system is ran with development or production interfaces. Valid choices are:\n    ['production', 'development']\n    (default: 'development')\n
Example using multiple CLI arguments
ros2 launch local_pathfinding main_launch.py log_level:=debug mode:=production\n
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:

ros2 launch $ROS_WORKSPACE/src/global_launch/main_launch.py enable_sim_multithreading:=true\n

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.

"},{"location":"current/sailbot_workspace/reference/launch_files/#ros-parameter-config-file","title":"ROS Parameter Config File","text":"

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.

  1. ROS Launch File Documentation \u21a9

"},{"location":"current/sailbot_workspace/reference/notebooks/","title":"Notebooks","text":"

Source code

The source code for Notebooks can be found in notebooks. Its README has been copied below.

"},{"location":"current/sailbot_workspace/reference/notebooks/#notebooks","title":"Notebooks","text":"

UBC Sailbot's Jupyter notebooks for researching and exporing implementations.

"},{"location":"current/sailbot_workspace/reference/notebooks/#standards","title":"Standards","text":"
  1. In addition to the dependencies installed in Sailbot Workspace, notebooks may have additional dependencies that are installed in the first code block
  2. Implementations in notebooks should be complete: do not import functions from other UBC Sailbot repositories
  3. Notebooks should be organized into directories named like the UBC Sailbot repositories they correspond to
"},{"location":"current/sailbot_workspace/reference/parameters/","title":"Parameters","text":"

Source code

Our ROS parameters can be found in src/global_launch/config. Its README has been copied below.

"},{"location":"current/sailbot_workspace/reference/parameters/#sailbot-ros-parameter-configuration","title":"Sailbot ROS Parameter Configuration","text":"

The description of each parameter contained in globals.yaml are described in this README. Descriptions of parameters for each node are included. These parameters can be changed dynamically as well via the command line interface. To learn more, see the ROS 2 documentation on ROS 2 Parameters.

Each parameter is specified in the following format:

  • Description: The description of the parameter.
  • Datatype: The datatype. If it happens to be an array, the datatype of the elements should be specified and the length of the array.
  • Range/Acceptable Values: Ranges of integers and floating point values are specified with interval notation. Namely, [] denotes inclusive boundaries, while () denotes non-inclusive boundaries. For strings, the acceptable values are listed.

Additional information may be included when necessary.

[!IMPORTANT] This document should be updated when any changes occur to the ROS parameters specified in globals.yaml.

"},{"location":"current/sailbot_workspace/reference/parameters/#global-parameters","title":"Global Parameters","text":"

ROS parameters common across all ROS nodes in the network.

pub_period_sec

  • Description: The period at which the publishers publish.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)
"},{"location":"current/sailbot_workspace/reference/parameters/#local-pathfinding-parameters","title":"Local Pathfinding Parameters","text":"

ROS parameters specific to the nodes in the local_pathfinding package.

"},{"location":"current/sailbot_workspace/reference/parameters/#mgp_main","title":"mgp_main","text":"

global_path_filepath

  • Description: The absolute filepath to a global path csv file.
  • Datatype: string
  • Acceptable Values: Any valid filepath to a properly formatted csv file.

interval_spacing

  • Description: The upper bound on spacing between each point in the global path in km.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

write

  • Description: Whether or not to write a generated global path to a new csv file.
  • Datatype: boolean
  • Acceptable Values: true, false

gps_threshold

  • Description: A new path will be generated if the GPS position changed by more thangps_threshold*interval_spacing.
  • Datatype: double
  • Acceptable Values: (1.0, MAX_DOUBLE)

force

  • Description: Force the mock global path callback to update the global path when set to true.
  • Datatype: boolean
  • Acceptable Values: true, false
"},{"location":"current/sailbot_workspace/reference/parameters/#navigate_main","title":"navigate_main","text":"

path_planner

  • Description: The path planner to use. Planners are from OMPL Library.
  • Datatype: string
  • Acceptable Values: \"bitstar\", \"bfmtstar\", \"fmtstar\", \"informedrrtstar\", \"lazylbtrrt\", \"lazyprmstar\", \"lbtrrt\", \"prmstar\", \"rrtconnect\", \"rrtsharp\", \"rrtstar\", \"rrtxstatic\", \"sorrtstar\"
"},{"location":"current/sailbot_workspace/reference/parameters/#controller-parameters","title":"Controller Parameters","text":"

ROS parameters specific to the nodes in the Controller.

"},{"location":"current/sailbot_workspace/reference/parameters/#wingsail_ctrl_node","title":"wingsail_ctrl_node","text":"

reynolds_number

  • Description: The Reynolds number of the wind.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

angle_of_attack

  • Description: The angle of attack of the sail.
  • Datatype: double
  • Range: (-180.0, 180.0]
"},{"location":"current/sailbot_workspace/reference/parameters/#boat-simulator-parameters","title":"Boat Simulator Parameters","text":"

ROS parameters specific to the nodes in the boat simulator.

"},{"location":"current/sailbot_workspace/reference/parameters/#low_level_control_node","title":"low_level_control_node","text":"

info_log_throttle_period_sec

  • Description: Limits the info logs to avoid overwhelming the terminal.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

logging_throttle_period_sec

  • Description: Controls the message logging throttle period.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

qos_depth

  • Description: The maximum number of subscription messages to queue for further processing.
  • Datatype: int
  • Range: [1, MAX_INT)

rudder.actuation_execution_period_sec

  • Description: The period at which the main loop in the rudder action server executes in seconds.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

rudder.disable_actuation

  • Description: Controls whether or not rudder actuation is disabled. If true, the rudder angle is fixed to some value. Otherwise, the PID mechanism is used to control the rudder angle.
  • Datatype: boolean
  • Acceptable Values: true, false

rudder.fixed_angle_deg

  • Description: The angle to fix the rudder in degrees. Only used if rudder.disable_actuation is true.
  • Datatype: double
  • Range: [-45.0, 45.0]

rudder.pid.buffer_size

  • Description: The buffer size of PID that stores previously computed errors over time.
  • Datatype: int
  • Range: [1, MAX_INT)

rudder.pid.kd

  • Description: The PID Derivative constant for the rudder. Only used if rudder.disable_actuation is false.
  • Datatype: double
  • Range: [0.0, MAX_DOUBLE)

rudder.pid.ki

  • Description: The PID Integral constant for the rudder. Only used if rudder.disable_actuation is false.
  • Datatype: double
  • Range: [0.0, MAX_DOUBLE)

rudder.pid.kp

  • Description: The PID Proportionality constant for the rudder. Only used if rudder.disable_actuation is false.
  • Datatype: double
  • Range: [0.0, MAX_DOUBLE)

wingsail.actuation_execution_period_sec

  • Description: The period at which the main loop in the sail action server executes in seconds.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

wingsail.actuation_speed_deg_per_sec

  • Description: The speed at which the wingsail trim tab actuates in degrees per second.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

wingsail.disable_actuation

  • Description: Controls whether or not wingsail trim tab actuation is disabled. If true, the trim tab is fixed to some value. Otherwise, the trim tab angle is determined by the wingsail controller.
  • Datatype: boolean
  • Acceptable Values: true, false

wingsail.fixed_angle_degree

  • Description: Fixed the wingsail trim tab to some angle in degrees. Only used if wingsail.disable_actuation is true.
  • Datatype: double
  • Range: [-180.0, 180.0)
"},{"location":"current/sailbot_workspace/reference/parameters/#physics_engine_node","title":"physics_engine_node","text":"

action_send_goal_timeout_sec

  • Description: How long the action clients wait for the action server to respond to a request before timing out in seconds.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

info_log_throttle_period_sec

  • Description: Limits the info logs to avoid overwhelming the terminal.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

logging_throttle_period_sec

  • Description: Controls the message logging throttle period.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

qos_depth

  • Description: The maximum number of subscription messages to queue for further processing.
  • Datatype: int
  • Range: [1, MAX_INT)

rudder.actuation_request_period_sec

  • Description: How often the rudder action client requests a rudder actuation in seconds.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

wingsail.actuation_request_period_sec

  • Description: How often the sail action server requests a wingsail actuation.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)

wind_sensor.constant_params.value

  • Description: Specifies the constant vector returned by the constant generator that represents the wind velocity in kmph. Namely, the same value is fixed in the wind sensors. The value is an array containing the x and y components of the velocity. Only used if wind_sensor.generator_type is constant.
  • Datatype: double array, length 2
  • Range: (MIN_DOUBLE, MAX_DOUBLE)

wind_sensor.gaussian_params.corr_xy

  • Description: The correlation coefficient between x and y components of the wind velocity. Only used if wind_sensor.generator_type is gaussian.
  • Datatype: double
  • Range: [-1.0, 1.0]

wind_sensor.gaussian_params.mean

  • Description: The mean wind velocity parameter in kmph for the gaussian generator. The mean is an array containing the x and y components of the velocity. Only used if wind_sensor.generator_type is gaussian.
  • Datatype: double array, length 2
  • Range: (MIN_DOUBLE, MAX_DOUBLE)

wind_sensor.gaussian_params.std_dev

  • Description: The standard deviation parameters in kmph for the gaussian generator. There are two standard deviations specified within an array: one for the x component, and one for the y component. Only used if wind_sensor.generator_type is gaussian.
  • Datatype: double array, length 2
  • Range: (0.0, MAX_DOUBLE)
    • If a standard deviation of zero is desired, then consider using the constant generator instead.

wind_sensor.generator_type

  • Description: Determines the type of random number generator that will be used to generate wind sensor data.
  • Datatype: string
  • Acceptable Values: gaussian, constant

wind_generation.mvgaussian_params.mean

  • Description: The mean value for the wind generated, expressed in kilometers per hour (km/h), for the multivariate Gaussian generator.
  • Datatype: double array, length 2
  • Range: (0.0, MAX_DOUBLE)

wind_generation.mvgaussian_params.cov

  • Description: The covariance matrix for the generated wind, represented as a string formatted as a 2D double array, since ROS parameters do not support native 2D array types.
  • Datatype: string
  • Range: (0.0, MAX_DOUBLE)

current_generation.mvgaussian_params.mean

  • Description: The mean value for the current generated, expressed in kilometers per hour (km/h), for the multivariate Gaussian generator.
  • Datatype: double array, length 2
  • Range: (0.0, MAX_DOUBLE)

current_generation.mvgaussian_params.cov

  • Description: The covariance matrix for the generated current, represented as a string formatted as a 2D double array, since ROS parameters do not support native 2D array types.
  • Datatype: string
  • Range: (0.0, MAX_DOUBLE)
"},{"location":"current/sailbot_workspace/reference/parameters/#data_collection_node","title":"data_collection_node","text":"

file_name

  • Description: The name of the file in which the data is saved, excluding the file extension.
  • Datatype: string
  • Acceptable Values: Any valid file name.

qos_depth

  • Description: The maximum number of subscription messages to queue for further processing.
  • Datatype: int
  • Range: [1, MAX_INT)

topics

  • Description: Specifies the topics to subscribe to. It should adhere to the format ['topic_name_1', 'topic_type_1', ...].
  • Datatype: string array with an even length
  • Acceptable Values: Each pair within the array must consist of a valid topic name as the first string and the corresponding correct type as the second string.

bag

  • Description: Determines whether to save recorded data as a ROS bag.
  • Datatype: boolean
  • Acceptable Values: true, false

json

  • Description: Determines whether to save recorded data as a JSON file.
  • Datatype: boolean
  • Acceptable Values: true, false

write_period_sec

  • Description: The interval (in seconds) for writing queued data to the JSON file.
  • Datatype: double
  • Range: (0.0, MAX_DOUBLE)
"},{"location":"current/sailbot_workspace/usage/help/","title":"Help","text":""},{"location":"current/sailbot_workspace/usage/help/#performance-issues","title":"Performance Issues","text":"

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
  • 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
      • 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
"},{"location":"current/sailbot_workspace/usage/help/#troubleshooting","title":"Troubleshooting","text":"

If you are having some trouble running our software, here are some things you can try:

"},{"location":"current/sailbot_workspace/usage/help/#sailbot-workspace-troubleshooting","title":"Sailbot Workspace Troubleshooting","text":"
  • Update Sailbot Workspace
  • Run the setup task to update package dependencies
  • 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
"},{"location":"current/sailbot_workspace/usage/help/#vs-code-troubleshooting","title":"VS Code Troubleshooting","text":"
  • Rebuild the Dev Container: run the Dev Containers: Rebuild Container VS Code command
  • Reload VS Code: run the Developer: Reload Window VS Code command
  • Identify broken extension: run the Help: Start Extension Bisect VS Code command
    • Once you have identified a broken extension, you can install a previous version until the issue is fixed in a new release
"},{"location":"current/sailbot_workspace/usage/help/#system-troubleshooting","title":"System Troubleshooting","text":"
  • Restart WSL: close Sailbot Workspace and Docker Desktop then run wsl --shutdown in PowerShell
  • Restart computer
"},{"location":"current/sailbot_workspace/usage/help/#docker-troubleshooting","title":"Docker Troubleshooting","text":"
  • Delete Docker files

    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
    • Install a previous version of Docker Desktop
"},{"location":"current/sailbot_workspace/usage/help/#shrink-wsl-distributions-size","title":"Shrink WSL Distributions' Size","text":"

After using Docker and Ubuntu for a while, you may notice that the vdisks are very large. As of May 2024, they are located at C:\\Users\\<user>\\AppData\\Local\\Docker\\wsl\\data\\ext4.vhdx and C:\\Users\\<user>\\AppData\\Local\\Packages\\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\\LocalState\\ext4.vhdx, respectively.

The problem is that these vdisks can automatically grow but not shrink, so if you download large files (like Docker images) and delete them once they're not needed the space is not freed. You can shrink vdisk using these commands.

"},{"location":"current/sailbot_workspace/usage/how_to/","title":"How-To's","text":""},{"location":"current/sailbot_workspace/usage/how_to/#run-vs-code-commands-tasks-and-launch-configurations","title":"Run VS Code commands, tasks, and launch configurations","text":"

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.

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
"},{"location":"current/sailbot_workspace/usage/how_to/#work-with-containerized-applications","title":"Work with containerized applications","text":"

We have containerized the following applications for a variety of reasons:

  • MongoDB database
  • Docs site
  • Website
"},{"location":"current/sailbot_workspace/usage/how_to/#running-containerized-applications","title":"Running containerized applications","text":"

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. Uncomment the port mapping(s) of the application(s) you want to run in .devcontainer/docker-compose.yml
    • Uncommented port mappings exposed ports to the host operating system; e.g., so that web applications can be opened in your browser
  3. 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 in .devcontainer/devcontainer.json and port mapping in .devcontainer/docker-compose.yml
  2. Stop the application's container: see Managing containerized applications
"},{"location":"current/sailbot_workspace/usage/how_to/#viewing-mongodb-data","title":"Viewing MongoDB data","text":"

Connect the MongoDB VS Code extension to the running database: Create a Connection for Deployment

  • 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 for how to use it to navigate or explore the database
"},{"location":"current/sailbot_workspace/usage/how_to/#opening-docs-or-website","title":"Opening Docs or Website","text":"

Docs runs on port 8000 and Website 3005. You can see them in your browser at localhost:<port>. 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

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

"},{"location":"current/sailbot_workspace/usage/how_to/#managing-containerized-applications","title":"Managing containerized applications","text":"

Each application runs in a Docker container. Containers can be managed using Docker Desktop or CLI commands:

  • View Sailbot Workspace containers

    Docker Desktop CLI Commands
    1. Select \"Containers\" in the top right
    2. Expand \"sailbot_workspace_devcontainer\"
      • The \"Status\" column shows whether a container is running or not
    docker ps -a\n
    • Sailbot Workspace containers should be named something like sailbot_workspace_devcontainer-<application>-<number>
    • 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)

    Docker Desktop CLI Commands
    1. Click on a container
    2. Navigate to the \"Logs\" view if not already on it
    docker logs <container>\n
  • Start a container that is not running

    Docker Desktop CLI Commands
    1. Click start
    docker start <container>\n
  • Stop a container that is running

    Docker Desktop CLI Commands
    1. Click stop
    docker stop <container>\n
"},{"location":"current/sailbot_workspace/usage/how_to/#manage-software-packages","title":"Manage software packages","text":"

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.

"},{"location":"current/sailbot_workspace/usage/how_to/#add-apt-or-python-dependencies-to-ros-packages","title":"Add apt or python dependencies to ROS packages","text":"

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:

<depend>ROSDEP_KEY</depend>\n<build_depend>ROSDEP_KEY</build_depend>\n<build_export_depend>ROSDEP_KEY</build_export_depend>\n<exec_depend>ROSDEP_KEY</exec_depend>\n<test_depend>ROSDEP_KEY</test_depend>\n
  • Learn what each tag is used for here.

  • 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
    Apt Dependencies Python Dependencies
    • Rosdep keys for apt repositories can be found here
    • Rosdep keys for python packages can be found here
    • 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 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 to learn more.

"},{"location":"current/sailbot_workspace/usage/how_to/#add-dependencies-to-a-docker-image","title":"Add dependencies to a Docker image","text":"

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: base, local-base, dev, or pre-base.

"},{"location":"current/sailbot_workspace/usage/how_to/#enable-github-copilot-in-sailbot-workspace","title":"Enable GitHub Copilot in Sailbot Workspace","text":"

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 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. 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.

    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 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 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
    • Configuring GitHub Copilot in your Environment
"},{"location":"current/sailbot_workspace/usage/how_to/#use-your-dotfiles","title":"Use your dotfiles","text":"

Dotfiles are configuration files for various programs.2

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 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

    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

"},{"location":"current/sailbot_workspace/usage/how_to/#run-rayes-software","title":"Run Raye's software","text":"

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, complete step 2 of the setup instructions

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
"},{"location":"current/sailbot_workspace/usage/how_to/#build-rayes-ros-packages","title":"Build Raye's ROS packages","text":"

To build Raye's ROS packages, run the following commands:

roscd\ncatkin_make\n
"},{"location":"current/sailbot_workspace/usage/how_to/#run-packages-from-different-workspaces","title":"Run packages from different workspaces","text":"

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 ProjectRaye
srcnew\n
srcraye\n

Then you can run launch files or package-specific executables in that workspace with:

New ProjectRaye

ros2 launch ... or ros2 run ..., respectively.

roslaunch ... or rosrun ..., respectively.

"},{"location":"current/sailbot_workspace/usage/how_to/#rayes-known-issues","title":"Raye's known issues","text":"

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:

echo 'export ROS_HOSTNAME=localhost' >> ~/.bashrc\necho 'export ROS_MASTER_URI=http://localhost:11311' >> ~/.bashrc\n
  1. GitHub Copilot Quickstart Guide \u21a9

  2. Dotfiles \u2013 What is a Dotfile and How to Create it in Mac and Linux \u21a9

"},{"location":"current/sailbot_workspace/usage/setup/","title":"Setup Instructions","text":"

Sailbot Workspace can be run on Windows, Linux, or macOS, but is the easiest to set up and performs the best on Ubuntu and its derivatives. 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 section.

"},{"location":"current/sailbot_workspace/usage/setup/#1-setup-prerequisites","title":"1. Setup prerequisites","text":""},{"location":"current/sailbot_workspace/usage/setup/#docker","title":"Docker","text":"

Docker is a platform that uses OS-level virtualization1 to develop, ship, and run applications.2 We use it to separate our applications from our infrastructure2 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 is a software used to run Docker. However, it can only be installed on Linux. Docker Desktop is a software used to run Docker in a VM,3 allowing it to be installed on Windows and macOS in addition to Linux.

Windows macOS Linux
  1. Set up prerequisites, WSL and Ubuntu:

    1. In PowerShell, run wsl --install Ubuntu, then exit, wsl --update, and wsl --set-default Ubuntu

      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

        whoami returns root

        If whoami returns root:

        1. Create a non-root user with sudo privileges
        2. Change the default Ubuntu user to this newly-created user: run ubuntu config --default-user <username> in PowerShell, replacing <username> 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 with the WSL 2 backend

    Docker Desktop - Unexpected WSL Error

    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
    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

Install Docker Desktop for your computer's CPU.

  1. Install Docker Engine
    • 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
  3. Configure Docker to start on boot
"},{"location":"current/sailbot_workspace/usage/setup/#vs-code","title":"VS Code","text":"

Visual Studio Code 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
  2. Install the Remote Development Extension Pack
"},{"location":"current/sailbot_workspace/usage/setup/#git","title":"Git","text":"

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
  2. Configure your name and email: Git config file setup (on Windows, run commands in Ubuntu)
  3. Login to GitHub

    Windows macOS / Linux
    1. Run the git config command for your Git version in Git Credential Manager setup (run command in Ubuntu)

      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.

    1. Install the GitHub CLI: Installation
    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, 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
"},{"location":"current/sailbot_workspace/usage/setup/#2-setup-x11-forwarding","title":"2. Setup X11 forwarding","text":"

X11 forwarding is a mechanism that enables Sailbot Workspace to run GUI applications.

You can skip this step since we currently aren't running any GUI applications

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

    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' >> <rc file path>, replacing <rc file path> 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

    Windows macOS Linux

    WSL includes a X11 server.

    1. Set up XQuartz following this guide
    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
    General Arch Linux

    As of February 2023, almost all Linux distributions include a X11 server, Xorg. This may change in the future as Wayland matures.

    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

      Windows macOS Linux

      In Ubuntu, sudo apt install x11-apps.

      XQuartz includes x11-apps. Ensure that XQuartz is running.

      Install x11-apps using your desired package manager.

    2. Verify that running xcalc opens a calculator and that you can use it

"},{"location":"current/sailbot_workspace/usage/setup/#3-clone-sailbot-workspace","title":"3. Clone Sailbot Workspace","text":"

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.

git clone https://github.com/UBCSailbot/sailbot_workspace.git\n
"},{"location":"current/sailbot_workspace/usage/setup/#4-open-sailbot-workspace-in-vs-code","title":"4. Open Sailbot Workspace in VS Code","text":"
  1. Install code command in PATH

    Windows macOS Linux

    The code command is installed by default.

    See launching from the command line.

    The code command is installed by default.

  2. Open the sailbot_workspace/ directory in VS Code: run code <relative path to sailbot workspace>

    • For example, if you just cloned the repository, the command would be code sailbot_workspace
"},{"location":"current/sailbot_workspace/usage/setup/#5-open-the-workspace-file","title":"5. Open the workspace file","text":"

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
"},{"location":"current/sailbot_workspace/usage/setup/#6-open-sailbot-workspace-in-a-dev-container","title":"6. Open Sailbot Workspace in a Dev Container","text":"
  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
"},{"location":"current/sailbot_workspace/usage/setup/#7-run-the-build-all-task","title":"7. Run the Build All task","text":"

Wait before running

Ensure that the postCreateCommand from devcontainer.json has completed before running this task.

The Build All task builds all the ROS packages.

"},{"location":"current/sailbot_workspace/usage/setup/#8-reload-the-vs-code-terminals-and-window","title":"8. Reload the VS Code terminals and window","text":"

Delete all open terminals and run the Developer: Reload Window VS Code command to detect the files that were generated from building.

"},{"location":"current/sailbot_workspace/usage/setup/#9-start-the-system","title":"9. Start the system","text":"

Run the entire system to verify everything is working using the following command in the VS Code terminal:

ros2 launch $ROS_WORKSPACE/src/global_launch/main_launch.py\n

Use Ctrl+C in the terminal to stop the system.

"},{"location":"current/sailbot_workspace/usage/setup/#setup-sailbot-workspace-in-a-github-codespace","title":"Setup Sailbot Workspace in a GitHub Codespace","text":"

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. 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
      • Upgrade to a Pro account for increased usage limits (this is free for students): apply to GitHub Global Campus as a student
      • Stop your codespace as soon as you are done using it: stopping a codespace
      • Delete codespaces that you do not plan to use anymore: deleting a codespace
  2. Follow the local setup instructions starting from 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
  • Close it by running the Codespaces: Stop Current Codespace VS Code command

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
  1. Wikipedia Docker page \u21a9

  2. Get Docker \u21a9\u21a9

  3. What is the difference between Docker Desktop for Linux and Docker Engine \u21a9

  4. Git SCM \u21a9

  5. GitHub Codespaces overview \u21a9

"},{"location":"current/sailbot_workspace/usage/workflow/","title":"Development Workflow","text":""},{"location":"current/sailbot_workspace/usage/workflow/#1-open-sailbot-workspace","title":"1. Open Sailbot Workspace","text":"

Once you have set up Sailbot Workspace, 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]\n
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.

"},{"location":"current/sailbot_workspace/usage/workflow/#2-update-sailbot-workspace","title":"2. Update Sailbot Workspace","text":"

Sailbot Workspace is still in active development, check out its recent releases and commit history. 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

    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+` 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

    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 want to run our docs or website, see How to work with containerized applications

"},{"location":"current/sailbot_workspace/usage/workflow/#3-make-your-changes","title":"3. Make your changes","text":"

We make changes to our software following our GitHub development workflow. Of particular relevance is the Developing on Branches page.

Git interfaces

One way to interface with Git is through CLI commands. However, you may find it faster to use VS Code's interface, 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
"},{"location":"current/sailbot_workspace/usage/workflow/#4-build-your-changes","title":"4. Build your changes","text":"

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
"},{"location":"current/sailbot_workspace/usage/workflow/#5-verify-your-changes","title":"5. Verify your changes","text":"Running GUI applications on macOS

If you want to run GUI applications on macOS, ensure that XQuartz is running.

"},{"location":"current/sailbot_workspace/usage/workflow/#lint-and-test","title":"Lint and Test","text":"

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 Testing tab on the VS Code primary sidebar contains individual tests. One can run specific unit tests by clicking the Run Test icon beside the test name.

"},{"location":"current/sailbot_workspace/usage/workflow/#run-a-package","title":"Run a Package","text":"

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:

CLI VS Code
  • Launch files:
    • ros2 launch <package> <launch file>
    • ros2 launch <path to launch file>
  • Nodes:
    • ros2 run <package> <executable>
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

    $ ros2 <tab><tab>\naction                          extension_points                multicast                       security\nbag                             extensions                      node                            service\n...\n
  • Complete commands: runs ros2 launch local_pathfinding main_launch.py

    $ ros2<tab>la<tab>loc<tab>m<tab>\n
  • Navigate to directories: runs cd .devcontainer/config from the root directory of Sailbot Workspace

    $ cd .d<tab>c<tab>\n

Furthermore, navigate past commands with Up and Down and search through them with Ctrl+R.

  • 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.

"},{"location":"current/sailbot_workspace/usage/workflow/#run-the-system","title":"Run the System","text":"

To verify that you didn't break anything, you may want to run the entire system. See Invoking Launch Files for more information on running the system.

"},{"location":"current/sailbot_workspace/usage/workflow/#debugging","title":"Debugging","text":"

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
"},{"location":"current/website/overview/","title":"Overview","text":"

Source code

The source code for Website can be found in src/website. Its README has been copied below.

"},{"location":"current/website/overview/#website","title":"Website","text":"

In the website development timeline, we are currently evaluating the folllowing software stack: Next.js website (this repository), Typescript, React + Redux, and the MongoDB database. The easiest way to evaluate these potential solutions for our purposes is in sailbot_workspace.

"},{"location":"current/website/overview/#database","title":"Database","text":"

MongoDB is a general purpose, document-based, distributed database built for modern application developers and for the cloud era. If you want to learn more about MongoDB, visit their docs site: MongoDB Documentation.

"},{"location":"current/website/overview/#setup","title":"Setup","text":""},{"location":"current/website/overview/#environment-variables","title":"Environment variables","text":"

We have two separate configurations: one for development .env.development, the other for production .env.production. The values may vary, but the environment variables are the same. See below:

  • MONGODB_URI: Your MongoDB connection string. Use mongodb://localhost:27017/<DB_NAME> to establish a connection with the local database.
  • NEXT_PUBLIC_SERVER_HOST: The host URL of the website.
  • NEXT_PUBLIC_SERVER_PORT: The port number of the website.
  • NEXT_PUBLIC_POLLING_TIME_MS: The time interval for polling the database in milliseconds.
"},{"location":"current/website/overview/#package-installation","title":"Package installation","text":"

The following command installs all required dependencies listed in the package.json file:

npm install\n

Once the installation is complete, you should see a node_modules directory in the project's root. This directory contains all installed packages.

When installing a new package to the website, please follow the steps below:

  1. Access the terminal of the website container on Docker.

  2. Run the command npm install <package-name>. Replace <package-name> with the actual name of the package you want to add.

  3. Should you encounter errors related to resolving peer dependencies, please re-run the command with the header --legacy-peer-deps. Do not to use --force unless you're well aware of the potential consequences.

  4. Review the package.json file to ensure the new package and its version have been added to the dependencies section.

  5. Confirm that package-lock.json has also been updated. This file holds specific version information to ensure consistent installations across different environments.
  6. Once the installation process is finished, please make sure to commit the files package.json and package-lock.json. These files are essential for version controlling the dependencies that have been added.
"},{"location":"current/website/overview/#run","title":"Run","text":"

Using Sailbot Workspace, the website should be up and running on http://localhost:3005.

Otherwise, you execute the following commands to run it in development mode:

npm run dev\n
"},{"location":"current/website/overview/#linters","title":"Linters","text":"

Before merging in new changes to the repository, please execute the following commands in order:

npm run format\n

This command runs Prettier to automatically format the code according to the rules defined in the configuration file .prettierrc.

npm run lint\n

This command runs ESLint to analyze the code for potential errors and enforce coding style based on the rules defined in the configuration file .eslintrc.

"},{"location":"reference/docker/","title":"Docker","text":"

Docker is a platform that uses OS-level virtualization1 to develop, ship, and run applications.2

"},{"location":"reference/docker/#tutorial","title":"Tutorial","text":"
  1. Wikipedia Docker page \u21a9

  2. Get Docker \u21a9

"},{"location":"reference/linux_commands/","title":"Linux Commands","text":""},{"location":"reference/linux_commands/#tutorial","title":"Tutorial","text":""},{"location":"reference/markdown/","title":"Markdown","text":"

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, 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.

"},{"location":"reference/markdown/#getting-started","title":"Getting Started","text":"

We recommend markdownguide.org 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.

"},{"location":"reference/markdown/#sailbot-and-markdown","title":"Sailbot and Markdown","text":"

We write Markdown for GitHub and Material for MkDocs. The following sections detail how Markdown is used in these services.

"},{"location":"reference/markdown/#github","title":"GitHub","text":"

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 RenderingAfter Rendering

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!

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 for more information on the available features.

"},{"location":"reference/markdown/#material-for-mkdocs","title":"Material for MkDocs","text":"

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. Since GitHub renders Markdown files automatically you will need to click the \"Raw\" button to view their contents.

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 for more information on the available features.

"},{"location":"reference/markdown/#rendering-markdown","title":"Rendering Markdown","text":"

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:

Vanilla Github Material for MkDocs
  • VS Code: Markdown rendering is supported out of the box.
  • Markdown Live Preview: An online rendering tool.
  • Markdown Preview GitHub Styling: VS Code extension that renders GitHub-flavoured markdown.
  • Create a draft issue on GitHub and preview the markdown to see how it renders.
  • UBC Sailbot Docs: To preview your changes when working on this site, refer to the How to work with containerized applications.
  • 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.

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.

"},{"location":"reference/markdown/#linting","title":"Linting","text":"

We lint our Markdown files to reduce errors and increase readability. In particular, we use two tools:

  1. markdownlint is used to enforce a style guide. Its configuration file for this repository is .markdownlint.json. If you use VS Code, there is a markdownlint extension.

  2. markdown-link-check is used to check for broken links. Its configuration file for this repository is .markdown-link-check.json.

  1. https://www.markdownguide.org/getting-started/ \u21a9

"},{"location":"reference/ros/","title":"Robot Operating System","text":"

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 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. To run our software on your device without our workspace, you would have to install ROS and the dependencies that are in our Docker images yourself.

"},{"location":"reference/ros/#tutorial","title":"Tutorial","text":""},{"location":"reference/ros/#workspace-configuration","title":"Workspace Configuration","text":"

To get our workspace configuration running on your computer:

  1. Set it up by following the setup instructions
  2. Uncomment the ROS 2 tutorials section in .devcontainer/Dockerfile, then run the \"Dev Containers: Rebuild Container\" VS Code command, to install the tutorials' dependencies
  3. Clone the repositories used in the tutuorials: ros_tutorials (humble branch), py_pubsub_ex, and cpp_pubsub_ex, then run the setup VS Code task to install their dependencies

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"},{"location":"reference/ros/#tutorials","title":"Tutorials","text":"

We encourage all software members to work through the ROS tutorials 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
"},{"location":"reference/ros/#concepts","title":"Concepts","text":"

We encourage all software members to read the following documentation on key ROS concepts:

  • About logging and logger configuration
  • About ROS 2 interfaces
  • About parameters in ROS 2
"},{"location":"reference/ros/#ros-1-bridge","title":"ROS 1 Bridge","text":"

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 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. For PATH members, the Migrating launch files from ROS 1 to ROS 2 page will be a helpful reference when we do so.

  1. https://docs.ros.org/en/humble/index.html \u21a9

  2. https://www.toptal.com/robotics/introduction-to-robot-operating-system \u21a9

  3. https://ubuntu.com/robotics/what-is-ros \u21a9

"},{"location":"reference/cpp/differences/","title":"Differences Between C and C++","text":"

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++.

"},{"location":"reference/cpp/differences/#classes-and-structs","title":"Classes and Structs","text":"

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.

struct foo {\nprivate:\n    int x;\n    void helper(void);\npublic:\n    foo(int y);\n}\n
class foo {\nprivate:\n    int x;\n    void helper(void);\npublic:\n    foo(int y);\n}\n
"},{"location":"reference/cpp/differences/#namespaces","title":"Namespaces","text":"

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 CC++ A.h
float x;\nint bar(void);\n
B.h
float x;\nint bar(void);\n
ighxy.c
#include \"A.h\"\n#include \"B.h\"\n\nint main(void) {\n    int a = bar();\n    ...\n}\n/* Error, does not compile*/\n
A.h
namespace a {\nfloat x;\nint bar(void);\n}\n
B.h
namespace b {\nfloat x;\nint bar(void);\n}\n
ighxy.cpp
#include \"A.h\"\n#include \"B.h\"\n\nint main(void) {\n    int a = a::bar();\n    int b = b::bar();\n    float xa = a::x;\n    float xb = b::x;\n    /* No problem! */\n    ...\n}\n
Warning

You may come across something like:

example.cpp
using namespace std;\nnamespace io = std::filesystem;\n\nint main(int argc, char* argv[]) {\n    bool isDirectory = io::is_directory(argv[1]);  // Equivalent to std::filesystem::is_directory(argv[1])\n    cout << isDirectory << endl;\n    return 0;\n}\n

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.

OKNot OK
    class string {\n        // Insert implementation here\n    }\n\n    int main(void) {\n        string ourString = \"Our own string implementation\";\n        std::string stdString = \"Standard Library string implementation\";\n        ...\n    }\n
    using namespace std;\n\n    // ERROR - multiple definitions of type string\n    class string {\n\n    }\n

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.

"},{"location":"reference/cpp/differences/#constant-expressions","title":"Constant Expressions","text":"

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 PrecompileAfter Precompile
#define PI 3.14F\n#define AREA_OF_CIRCLE(radius) ((PI) * (radius) * (radius))\n\nint main(void) {\n    float area = AREA_OF_CIRCLE(2.5F);\n    ...\n}\n
int main(void) {\n    float area = ((3.14F) * (2.5F) * (2.5F));\n    ...\n}\n

Note

AREA_OF_CIRCLE is a macro with arguments. If you are confused by it, this resource 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. Moreover, symbols declared with #define are always globally visible, ignoring namespaces!

In C++, the use of constant expressions are preferred.

constexpr float pi = 3.14F;\nconstexpr float area_of_circle(float radius) {\n    return pi * radius * radius;\n}\n

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.

Constant Expression Scoping
void foo(void) {\n    constexpr float rand = 123.456;\n    ...\n}\n\nvoid bar (void) {\n    constexpr float rand = 789.123;\n    ...\n}\n
"},{"location":"reference/cpp/differences/#lambdas","title":"Lambdas","text":"

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 for Microsoft's explanation.

"},{"location":"reference/cpp/differences/#misc","title":"Misc","text":""},{"location":"reference/cpp/differences/#arrays","title":"Arrays","text":"

Using the C++ implementation of arrays 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

CC++

#include \"stdio.h\"\n\nvoid print_contents(int *arr, int size) {\n    for (int i = 0; i < size; i++) {\n        printf(\"%d\\n\", *arr);\n    }\n}\n\nint main(void) {\n    int arr[5] = {0, 1, 2, 3, 4};\n    foo(arr, 5);\n    return 0;\n}\n
We can't even guarantee that the integer pointer arr is an array!

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.

#include <iostream>\n#include <array>\n#include <span>\n\nvoid print_contents(std::span<int> container) {\n    for (const auto &e : container) {\n        std::cout << e << std::endl;\n    }\n}\n\nint main(void) {\n    std::array<int, 5> arr = {0, 1, 2, 3, 4};\n    foo(arr);\n    return 0;\n}\n

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
"},{"location":"reference/cpp/start/","title":"Getting Started","text":"

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.

"},{"location":"reference/cpp/start/#for-cc-beginners","title":"For C/C++ Beginners","text":"

If you just need to know how C++ is different from C, then see the Differences Between C and C++. 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 A structured tutorial that goes through basic concepts in C++. It's good to do up to the section on Classes. YouTube Tutorial 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 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!

"},{"location":"reference/cpp/tools/","title":"Tools","text":"

A lot goes into making a well structured C++ project, much more than any one team should have to do.

"},{"location":"reference/cpp/tools/#cmake","title":"CMake","text":"

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 are great for understanding the basics.

"},{"location":"reference/cpp/tools/#gdb","title":"GDB","text":"

The GNU Project Debugger 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 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.

"},{"location":"reference/cpp/tools/#googletest","title":"GoogleTest","text":"

GoogleTest is the C++ unit testing framework we will be using. The GoogleTest Primer is a good place to start.

Example Cached Fibonacci ProgramTest Cached Fibonacci Program cached_fib.h
#include <vector>\nclass CachedFib {\npublic:\n    void CachedFib(int n);\n    int  getFib(int n);\nprivate:\n    std::vector<int> cache;\n}\n
cached_fib.cpp
#include <iostream>\n#include <vector>\n#include \"cached_fib.h\"\n\nvoid CachedFib::CachedFib(int n) {\n    cache.push_back(0);\n    cache.push_back(1);\n    for (int i = 2; i < n; i++) {\n        cache.push_back(cache[i - 1] + cache[i - 2]);\n    }\n}\n\nint CachedFib::getFib(int n) {\n    if (cache.size() < n) {\n        for (int i = cache.size(); i < n; i++) {\n            cache.push_back(cache[i-1] + cache[i-2]);\n        }\n    }\n    std::cout << cache[n - 1] << std::endl;\n}\n
test_cached_fib.cpp
#include \"cached_fib.h\"\n#include \"gtest/gtest.h\"\n\nCachedFib::testFib;\n\nclass TestFib : public ::testing::Test {\nprotected:\n    void Setup override {\n        // Every time a test is started, testFib is reinitialized with a constructor parameter of 5\n        testFib = CachedFib(5);\n    }\n}\n\nTEST_F(TestFib, TestBasic) {\n    ASSERT_EQ(getFib(5), 3) << \"5th fibonacci number must be 3!\";\n}\n\n// more tests\n
"},{"location":"reference/cpp/tools/#google-protocol-buffer","title":"Google Protocol Buffer","text":"

Google Protocol Buffer (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. The page is quite dense and can be hard to follow, so do not worry if you do not understand it.

"},{"location":"reference/cpp/tools/#clang","title":"Clang","text":"

In its most basic form, Clang 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.

"},{"location":"reference/cpp/tools/#clangd","title":"Clangd","text":"

Clangd is the Clang language server. It provides a much more powerful intellisense than the default one used in VSCode's C/C++ extension.

"},{"location":"reference/cpp/tools/#clang-tidy","title":"Clang-Tidy","text":"

Clang-Tidy is a linting tool, who's main purpose is to catch potential programming errors caused by bad programming style/practices using just static analysis.

"},{"location":"reference/cpp/tools/#clang-format","title":"Clang Format","text":"

An autoformatting tool that makes enforcing style guidelines much easier. When se tup, it corrects formatting as soon as you hit save.

"},{"location":"reference/cpp/tools/#llvm-cov","title":"llvm-cov","text":"

We will use llvm-cov to evaluate our test coverage. When used with genhtml, we can generate HTML reports that that show our line, function, and branch coverage line-by-line.

"},{"location":"reference/github/advanced_git/","title":"Advanced Git","text":""},{"location":"reference/github/advanced_git/#tutorial","title":"Tutorial","text":""},{"location":"reference/github/github_actions/","title":"GitHub Actions","text":""},{"location":"reference/github/github_actions/#tutorial","title":"Tutorial","text":""},{"location":"reference/github/workflow/branches/","title":"Developing on Branches","text":"

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.

"},{"location":"reference/github/workflow/branches/#creating-a-branch","title":"Creating a branch","text":"

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.

Creating a new branch from main
# Switch to main\ngit switch main\n\n# Update your local copy\ngit pull\n\n# Clone a new branch from main\ngit switch -c <branch_name>\n

IMPORTANT: When creating a new branch for an issue, you must create the branch from main.

"},{"location":"reference/github/workflow/branches/#branch-naming-convention","title":"Branch naming convention","text":"

When working on a new issue, you will want to create a branch to work on it. We have the following branch naming convention:

<github_username>/<issue_number>-<issue_description>\n

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.

"},{"location":"reference/github/workflow/branches/#tracking-and-committing-changes","title":"Tracking and committing changes","text":"

All files where new changes have been made must first be \"staged\" in order to make commits:

git add <FILES>\n

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 \"<commit_message>\"\n

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 <current_branch_name>\n
"},{"location":"reference/github/workflow/branches/#merging-branches","title":"Merging branches","text":"

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 BranchMerge Remote Branch
# Checkout to destination branch\ngit checkout <dest_branch>\n\n# Merge with local copy of other branch\ngit merge <other_branch>\n
# Checkout to destination branch\ngit checkout <dest_branch>\n\n# Fetch from remote\ngit fetch\n\n# Merge remote copy of other branch\ngit merge origin/<other_branch>\n

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.

"},{"location":"reference/github/workflow/branches/#resolving-merge-conflicts","title":"Resolving merge conflicts","text":"

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:

Upon inspecting bar.txt, we see the following:

Resolving merge conflicts is not always a trivial task, but there are many ways to resolve them which include:

  • Resolving on GitHub (recommended)
  • Resolving in Command Line

Tip

If you cannot resolve a merge conflict on your own, reach out to your lead for help!

"},{"location":"reference/github/workflow/issues/","title":"Creating Issues","text":"

GitHub issues lets us plan and track our work on GitHub.

"},{"location":"reference/github/workflow/issues/#getting-started-with-issue-templates","title":"Getting started with issue templates","text":"

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.

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.

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.

Note

GitHub issues are written using GitHub-flavoured markdown. To add a little spice to your issues, refer to the official GitHub documentation 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:

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 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!

"},{"location":"reference/github/workflow/issues/#adding-issues-to-a-project","title":"Adding issues to a project","text":"

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.

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).

"},{"location":"reference/github/workflow/issues/#adding-issues-to-a-milestone","title":"Adding issues to a milestone","text":"

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.

Note

Unlike projects, milestones are strictly associated with a repository.

"},{"location":"reference/github/workflow/issues/#labelling-issues","title":"Labelling issues","text":"

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).

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!

"},{"location":"reference/github/workflow/issues/#adding-assignees","title":"Adding assignees","text":"

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.

"},{"location":"reference/github/workflow/issues/#submit-the-issue","title":"Submit the issue","text":"

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.

"},{"location":"reference/github/workflow/overview/","title":"Development Workflow Overview","text":"
graph LR\n    B[Problem Conception] --> C{Small Fix?};\n    C --> |Yes| E[Development];\n    C --> |No| D[Issue Creation];\n    D --> E;\n    E --> F[Pull Request];\n    F --> G{Approved?};\n    G --> |No| E;\n    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.

"},{"location":"reference/github/workflow/overview/#tutorial","title":"Tutorial","text":""},{"location":"reference/github/workflow/overview/#version-control-git","title":"Version control: Git","text":"

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 A 30 minute video on git for beginners. Good if you want to learn git quickly and nail all the fundamentals. Pro Git book 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 A condensed summary of some common git commands. Good to refer to once you are familiar with the fundamentals of git."},{"location":"reference/github/workflow/overview/#remote-server-github","title":"Remote server: GitHub","text":"

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
  • Projects
  • Milestones
  • GitHub Organizations
  • Repository Permissions and Branch Protection Rules
  • And more!
"},{"location":"reference/github/workflow/pr/","title":"Pull Requests","text":"

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.

"},{"location":"reference/github/workflow/pr/#creating-a-pull-request","title":"Creating a pull request","text":"

To create a pull request in a repository, to go the Pull requests tab and then click New pull request:

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.

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):

Notice how this is remarkably similar to the page of an issue. To link a pull request to an issue, simply add <KEYWORD> #<ISSUE NUMBER> to the initial comment in the pull request. A list of valid keywords can be found here.

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.

"},{"location":"reference/github/workflow/pr/#merging-into-main","title":"Merging into main","text":"

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:

"},{"location":"reference/github/workflow/pr/#reviewing-a-pull-request","title":"Reviewing a pull request","text":"

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.

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).
"},{"location":"reference/python/conventions/","title":"Conventions","text":"

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.

"},{"location":"reference/python/conventions/#style-guide","title":"Style guide","text":""},{"location":"reference/python/conventions/#linting","title":"Linting","text":"

To ensure that the codebase stays clean, we use flake8, which is a tool for style guide enforcement mostly based off pep8. To automate most of this process, we use autopep8, 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 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!

"},{"location":"reference/python/conventions/#type-hinting","title":"Type hinting","text":"

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 can be used.

There is some syntax to get familiar in order to use type checking. We recommend the following resources:

  • mypy Typing Cheatsheet
  • PEP 483: The Theory of Type Hints (A Simplified Guide)
  • PEP 484: Type Hints (Fully Comprehensive Guide)

Below are a few examples of using type hinting:

Return the sum of a sequence
from typing import Sequence, Union\n\n\nNumber = Union[int, float]\n\n\ndef sumseq(seq : Sequence[Number]) -> Number:\n    return sum(seq)\n
Function with optional parameters and default values
from typing import Optional\n\n\ndef printArgs(a : str, b : str=\"World\", c : Optional[str]=None) -> None:\n    print(f\"Value of a: {a}\")\n    print(f\"Value of b: {b}\")\n    if c is not None:\n        print(f\"Value of c: {c}\")\n
Function with custom class
class MyClass:\n    def __init__(self) -> None:\n        pass\n\n\ndef foo(a : MyClass) -> None:\n    print(a)\n
Forward referencing a class With __future__Without __future__
from __future__ import annotations\n\n\ndef foo(a : MyClass) -> None:\n    print(a)\n\n\nclass MyClass:\n    def __init__(self) -> None:\n        pass\n
def foo(a : 'MyClass') -> None:\n    print(a)\n\n\nclass MyClass:\n    def __init__(self) -> None:\n        pass\n
Function that never returns
from typing import NoReturn\n\n\ndef bar() -> NoReturn:\n    while True:\n        print(\"Hello World!\")\n
"},{"location":"reference/python/conventions/#documentation","title":"Documentation","text":"

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.

"},{"location":"reference/python/conventions/#generating-docstrings","title":"Generating docstrings","text":"

We use a vscode extension called autoDocstring 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, 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.

"},{"location":"reference/python/conventions/#example-on-documentation","title":"Example on documentation","text":"

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 by default.

Documentation example on a function
from typing import List\ndef inner_product(v1 : List[float], v2 : List[float]) -> float:\n    \"\"\"\n    Computes the inner product between two 1D real vectors. Input vectors should have the\n    same dimensions.\n\n    Args:\n        v1 (List[float]): The first vector of real numbers.\n        v2 (List[float]): The second vector of real numbers.\n\n    Returns:\n        float : The inner product between v1 and v2\n    \"\"\"\n    assert (len(v1) == len(v2)), \"Input lists must have same length\"\n\n    # Iterate through elementwise pairs\n    summation = 0\n    for e1, e2 in zip(v1, v2):\n        summation += (e1 * e2)\n    return float(summation)\n
Documentation example with a stack
from typing import Any\nclass Stack:\n\n    \"\"\"\n    This class represents a stack, which is an abstract data type that serves as a collection of\n    elements. The stack is a LIFO datastructure defined by two main operations: Push and Pop.\n\n    Attributes:\n        __stack (List[Any]): A list containing the elements on the stack.\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"\n        Initializes the Stack object.\n        \"\"\"\n        self.__stack = []\n\n    def push(self, element : Any) -> Any:\n        \"\"\"\n        Pushes an element to the top of the stack.\n\n        Args:\n            element (Any): The element to be pushed on to the stack.\n        \"\"\"\n        self.__stack.append(element)\n\n    def pop(self) -> Any:\n        \"\"\"\n        Removes the element at the top of the stack and returns it. If the stack is empty,\n        then None is returned.\n\n        Returns:\n            Any, NoneType: The element at the top of the stack.\n        \"\"\"\n        if self.is_empty():\n            return None\n        else:\n            return self.__stack.pop()\n\n    def is_empty(self) -> bool:\n        \"\"\"\n        Determines whether the stack is empty or not.\n\n        Returns:\n            bool: Returns True if the stack is empty, and False otherwise.\n        \"\"\"\n        empty = (len(self.__stack) == 0)\n        return empty\n\n    def __len__(self) -> int:\n        \"\"\"\n        Gets the number of elements on the stack.\n\n        Returns:\n            int: The number of elements on the stack.\n        \"\"\"\n        length = len(self.__stack)\n        return length\n

For more examples, see Example Google Style Python Docstrings.

  1. https://realpython.com/lessons/pros-and-cons-type-hints/ \u21a9

"},{"location":"reference/python/start/","title":"Getting Started","text":"

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.

"},{"location":"reference/python/start/#python-tutorials","title":"Python tutorials","text":"

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 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 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 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 A shorter alternative YouTube tutorial condensed into 1 hour. It covers less material but still covers many of the essentials. CodingBat Practice 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!

"},{"location":"reference/python/virtual-environments/","title":"Virtual Environments","text":"

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 and Anaconda. 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.

"},{"location":"reference/python/virtual-environments/#installation","title":"Installation","text":"Virtualenv Anaconda

If you already have python and the pip package manager installed, just execute the following:

Using pip to install virtualenv
pip install virtualenv\n

Go to the official Anaconda website and follow the installation instructions for your operating system.

"},{"location":"reference/python/virtual-environments/#using-virtual-environments","title":"Using virtual environments","text":"

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.

"},{"location":"reference/python/virtual-environments/#creating-a-virtual-environment","title":"Creating a virtual environment","text":"Virtualenv Anaconda

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.

Create virtual environment with virtualenv
# Go to desired location\ncd <PATH TO DIRECTORY>\n\n# Create the environment with the name env\npython3 -m venv env\n

Verify that your environment is created by examining your current directory and look for the directory that matches the name of your virtual environment.

Since the environment will be available globally, there is no need to go to a specific location to create it.

Create virtual environment with Anaconda
# Create environment with name env and python version\nconda env create -n env python=<PYTHON VERSION NUM>\n

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.

"},{"location":"reference/python/virtual-environments/#activating-the-virtual-environment","title":"Activating the virtual environment","text":"

To use the virtual environment, you must activate it.

Virtualenv Anaconda Windows macOS Linux Activation for Windows
env\\Scripts\\activate\n
Activation for macOS
source env/bin/activate\n
Activation for Linux
source env/bin/activate\n
Activation for Anaconda
conda activate env\n

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!

"},{"location":"reference/python/virtual-environments/#installing-dependencies","title":"Installing dependencies","text":"

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!

Virtualenv Anaconda

Use the pip package manager to install python dependencies. Before installing any Python dependencies, it is good practice to upgrade pip:

Upgrade pip
pip install --upgrade pip\n

Now, install any Python dependencies pip:

Install dependency with pip
pip install <PACKAGE>\n
Option 1: pipOption 2: conda

Use the pip package manager to install python dependencies.

Install dependency with pip
# Install pip using conda\nconda install pip\n\n# Install python packages using pip\npip install <PACKAGE>\n

Use the built-in conda package manager to install python dependencies.

Install dependency with conda
conda install -c <CHANNEL> <PACKAGE>\n

Sometimes, installing a package like this simply won't work because you are not installing from the correct channel. 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
"},{"location":"reference/python/virtual-environments/#deactivating-the-virtual-environment","title":"Deactivating the virtual environment","text":"

When you are finished using your virtual environment, you will need to deactivate it.

Virtualenv Anaconda Deactivate virtualenv environment
deactivate\n
Deactivate anaconda environment
conda deactivate\n
"},{"location":"reference/python/virtual-environments/#reproducing-your-virtual-environment","title":"Reproducing your virtual environment","text":"

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.

"},{"location":"reference/python/virtual-environments/#exporting-your-virtual-environment","title":"Exporting your virtual environment","text":"

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.

Virtualenv Anaconda

You will create a requirements.txt file, which essentially lists all of your python dependencies in one file:

Creating requirements file
pip freeze > requirements.txt\n

The pip freeze command prints all of your pip dependencies, and > requirements.txt redirects the output to a text file.

Anaconda uses configuration files to recreate an environment.

Windows macOS Linux

Execute the following command to create a file called environment.yml:

Create config file
conda env export > environment.yml\n

Then, open the environment.yml file and delete the line with prefix:.

Execute the following command to create a file called environment.yml:

Create config file
conda env export | grep -v \"^prefix: \" > environment.yml\n

Execute the following command to create a file called environment.yml:

Create config file
conda env export | grep -v \"^prefix: \" > environment.yml\n
"},{"location":"reference/python/virtual-environments/#reproducing-the-environment","title":"Reproducing the environment","text":"

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.

Virtualenv Anaconda

We use the requirements.txt file that we generated earlier to recreate the environment.

Recreate virtualenv environment
# Create the new environment\npython -m venv <NEW ENV NAME>\n\n# Activate the environment\nsource <NEW ENV NAME>/bin/activate\n\n# Install dependencies\npip install -r <PATH TO requirements.txt file>\n

We use the environment.yml file that we generated earlier to recreate the environment.

Recreate the conda environment
# Create the new environment with the dependencies\nconda env create -f <PATH TO environment.yml> -n <ENV NAME>\n
"},{"location":"reference/python/virtual-environments/#official-references","title":"Official references","text":"

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
  • Anaconda Reference
"},{"location":"reference/sailing/ais_terms/","title":"AIS Terms","text":"

This section explains the most unfamiliar fields that we receive from the AIS.

"},{"location":"reference/sailing/ais_terms/#mmsi-aka-id","title":"MMSI a.k.a ID","text":"

A 9-digit, unique identification number for the ship.

"},{"location":"reference/sailing/ais_terms/#cog-course-over-ground","title":"COG: Course over Ground","text":"

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.

This is measured with the navigational angle convention, where 0\u00b0 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.
"},{"location":"reference/sailing/ais_terms/#sog-speed-over-ground","title":"SOG: Speed over Ground","text":"

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.

\\(\\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.
"},{"location":"reference/sailing/ais_terms/#rot-rate-of-turn","title":"RoT: Rate of Turn","text":"

The angular velocity of the boat (how fast it's turning), measured in degrees per minute.

"},{"location":"reference/sailing/boat_parts/","title":"Parts of a Sailboat","text":"

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.

"},{"location":"reference/sailing/boat_parts/#hull","title":"Hull","text":"

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.

"},{"location":"reference/sailing/boat_parts/#jib","title":"Jib","text":"

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.
"},{"location":"reference/sailing/boat_parts/#mast","title":"Mast","text":"

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.
"},{"location":"reference/sailing/boat_parts/#main-sail","title":"Main Sail","text":"

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.
"},{"location":"reference/sailing/boat_parts/#conclusion","title":"Conclusion","text":"

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.

"},{"location":"reference/sailing/boat_parts/#keywords-on-this-page","title":"Keywords on this Page","text":"
  • Hull
  • Keel
  • Rudder
  • Bow
  • Stern
  • Starboard
  • Port
  • Jib
  • Jib winch
  • Mast
  • Wind Sensor
  • AIS Antenna
  • Main Sail
  • Main Winch
"},{"location":"reference/sailing/miscellaneous/","title":"Miscellaneous Sailing Knowledge","text":"

This section covers some other useful information.

"},{"location":"reference/sailing/miscellaneous/#wind-direction-convention","title":"Wind Direction Convention","text":"

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\u00b0 means the wind is blowing from North to South.
  2. The angle tells you which way the wind is coming from. For example, 0\u00b0 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.

"},{"location":"reference/sailing/miscellaneous/#navigation-terms","title":"Navigation Terms","text":""},{"location":"reference/sailing/miscellaneous/#heading","title":"Heading","text":"

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.

"},{"location":"reference/sailing/miscellaneous/#bearing","title":"Bearing","text":"

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\u00b0 is towards the North, angles increase in the clockwise direction, and angles are typically bounded within [0\u00b0, 360\u00b0)]
  • A Relative Bearing is a bearing where the angle convention is as follows: 0\u00b0 is straight forwards relative to the boat, and angle measurements increase in the clockwise direction. Angles may be bounded in [-180\u00b0, 180\u00b0) or [0\u00b0, 360\u00b0)

In the example below, the boat \"B\" has a Heading (H) of 30\u00b0. The True Bearing (\\(B_t\\)) of the Lighthouse \"A\" from the boat is 90\u00b0. The Relative Bearing (\\(B_r\\)) of the lighthouse from the boat is 60\u00b0.

"},{"location":"reference/sailing/miscellaneous/#track-made-good","title":"Track Made Good","text":"

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.

"},{"location":"reference/sailing/miscellaneous/#heading-and-bearing-in-raye-project","title":"Heading and Bearing in Raye Project","text":"

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\u00b0 mean? If 0\u00b0 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\u00b0 means towards the East, angles increase in the counter-clockwise direction, and angles are bounded in [-180\u00b0, 180\u00b0). This is effectively the main angle convention used in most math courses.
  • 0\u00b0 means towards the North, angles increase in the clockwise direction, and angles are bounded in [0\u00b0, 360\u00b0). 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.

"},{"location":"reference/sailing/miscellaneous/#true-apparent-and-boat-wind","title":"True, Apparent, and Boat Wind","text":"
  • 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\u00b0\\).

"},{"location":"reference/sailing/miscellaneous/#tack","title":"Tack","text":"

In the Types of Turn 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.

  • Finally, the Tack can refer to particular region of the main sail. This is not important for software members.
"},{"location":"reference/sailing/miscellaneous/#keywords-on-this-page","title":"Keywords on this Page","text":"
  • Heading
  • Bearing
  • Track Made Good
  • Global Wind (aka True Wind)
  • Measured Wind (aka Apparent Wind)
  • Tack
"},{"location":"reference/sailing/overview/","title":"Sailing Knowledge Section Overview","text":"

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.

"},{"location":"reference/sailing/overview/#tutorial","title":"Tutorial","text":""},{"location":"reference/sailing/points_of_sail/","title":"Points of Sail","text":"

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.

"},{"location":"reference/sailing/points_of_sail/#irons","title":"Irons","text":"

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.

"},{"location":"reference/sailing/points_of_sail/#upwind-sailing","title":"Upwind Sailing","text":"

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.

"},{"location":"reference/sailing/points_of_sail/#downwind-sailing","title":"Downwind Sailing","text":"

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.

"},{"location":"reference/sailing/points_of_sail/#keywords-on-this-page","title":"Keywords on this Page","text":"
  • Irons (aka No-Go Zone)
  • Upwind Sailing
  • Close Hauled
  • Downwind Sailing
"},{"location":"reference/sailing/turning/","title":"Types of Turns","text":"

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.

"},{"location":"reference/sailing/turning/#classifying-types-of-turns-summary","title":"Classifying Types Of Turns Summary","text":"

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
graph LR\n    B[Classify a Turn] --> C{Does the sail change<br/>sides during the turn?};\n    C --> |Yes| E{Which end of<br/>the boat is upwind<br/>during the turn?};\n    C --> |No| D{Does the<br/>boat point higher<br/>or lower at the end<br/>of the turn?};\n    D --> |Higher| F[Heading Up];\n    D --> |Lower| G[Bearing Off];\n    E --> |Bow| H[Tack];\n    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.

"},{"location":"reference/sailing/turning/#heading-up","title":"Heading Up","text":"

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.

"},{"location":"reference/sailing/turning/#bearing-off","title":"Bearing Off","text":"

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.

"},{"location":"reference/sailing/turning/#tacking","title":"Tacking","text":"

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\u00b0) turn all at once, so that the boat's momentum carries it through the range of angles where it does not get propulsion.

"},{"location":"reference/sailing/turning/#gybing","title":"Gybing","text":"

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\u00b0 turn.

Note that \"gybe\" is the spelling used in Canadian and British english, whereas in American english it is spelled \"Jibe\"

"},{"location":"reference/sailing/turning/#combinations-of-turns","title":"Combinations of Turns","text":"

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?

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.

"},{"location":"reference/sailing/turning/#keywords-on-this-page","title":"Keywords on this Page","text":"
  • Higher (in relation to pointing)
  • Lower (in relation to pointing)
  • Heading Up
  • Bearing Off
  • Tack
  • Gybe (aka Jibe)
"}]} \ No newline at end of file