Overview
Before embarking on this subteam bootcamp, please ensure you’ve completed these instructions: Bootcamper Onboarding.
This bootcamp is in effect starting 2023-09-06 . If you are doing the Autonomy bootcamp, you are at the right place! Create a post in the #auto-bootcamps forum to get started! You can ask for help there and notify the Autonomy bootcamp reviewers when you are done.
Setup
Dear WARG Bootcamper,
Congratulations and welcome to the AutoBots family! We're excited to have you on the team. I'll be sending you our onboarding documents soon, please feel free to get a head start on that.
Yours sincerely,
Jane Doe
VP of Human Resources
AutoBots
Git and GitHub
“I’m still waiting for QA to give me back my code [on the USB stick].” - Overheard at the water cooler
Git is a powerful version control system that Autonomy uses to organize many members contributing to the same codebase. Think of it as undo/redo, copying and renaming files to save an older version, and branching all rolled into one.
GitHub is a source code hosting and sharing website owned by Microsoft.
Forking
Create a personal copy of the repository by forking it.
If you haven’t already, create an account on GitHub. You can use either your UW email or something else. Otherwise, log in with the GitHub account you would like to use with WARG.
Click on the Fork button (towards the top right, above the About section).
Click on the green Create fork button.
GitHub redirects you to your own copy of the repository.
Git setup
If you have already setup Git, you do not need to set it up again.
If you haven’t already, download and install Git: https://git-scm.com/
Git should already be installed on Linux and MacOS.
Windows (Linux and MacOS users skip step): Set line endings.
Check:
git config --get core.autocrlf
If it is
true
orinput
, you do not need to set anything.
Set:
git config --global core.autocrlf [setting]
.--global
is optional, and replace[setting]
with eithertrue
orinput
When in doubt, use
input
Additional information here: https://www.git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#_core_autocrlf
Configure Git with your name and email: https://linuxize.com/post/how-to-configure-git-username-and-email/
--global
if you want to use it as the default, otherwise it will just be for the current repository.You can use your anonymous GitHub no-reply email.
Cloning the repository
Go to GitHub and navigate to your copy of the repository, under your account. Do not go to WARG’s copy of the repository!
Click on the green Code button.
In the dropdown, you can copy either the HTTPS or SSH link.
Windows and MacOS: Copy the HTTPS link (although you can copy the SSH link if you desire).
Linux: Copy the SSH link.
If you really want to use HTTPS on Linux, you have to install the Git Credential Manager or create a Personal Access Token on GitHub. How to do this is left as an exercise for you.
If you’re using the SSH link (HTTPS link users skip this):
If you haven’t already, create a new SSH key and add it to your GitHub account:
If you add a password to your SSH key, you will have to type it in every time you use Git to interact with GitHub (e.g. cloning, pulling, pushing). You can always delete and create a new SSH key if you change your mind later.
Pick a parent directory to clone (download the code) into.
Example: Cloning in
C:\Users\Username\
will create a folder and then populate it:C:\Users\Username\computer-vision-python\[files]
Open the console in the parent directory.
Windows: Command prompt or Powershell.
Linux and MacOS: Terminal.
Clone the repository:
git clone [link you copied]
, where[link you copied]
is the link you copied in step 2.HTTPS link users: You will be prompted to log into your GitHub account. Do so.
Update the repository submodules: Run the project setup scripts (If provided)
Windows:
.\setup_project.ps1
Linux/Mac:
source ./setup_project.sh
Done!
Python and virtual environment
“It’s fine, it works on my machine.” - Overheard in the software development cubicle farm
Python is the programming language this bootcamp uses.
A Python virtual environment is a self contained environment with a specific Python version and package versions. Different virtual environments can be used for different projects to maintain consistency.
If you haven’t already, download and install Python 3.11 : https://www.python.org/
If you have a different version of Python installed:
Python 3.9 or lower: You must install Python 3.11 (you do not need to uninstall the other version(s)). This is because of a language feature dependency (specifically, match statements introduced in Python 3.10 : https://docs.python.org/3.10/tutorial/controlflow.html#match-statements ).
Python 3.10: You’re probably fine. Probably. Use at your own risk.
Python 3.12 or higher: You’re probably fine. Probably. Use at your own risk.
Open the console in the repository root.
Example:
C:\Users\Username\computer-vision-python
Create a virtual environment called
venv
by running:[python] -m venv venv/
, where[python]
is Python 3.11 (e.g.python
,python311
).You can check which version of Python it is by running
[python] --version
If you move the repository to a different path after creating a virtual environment, you will have to delete the
venv
directory and repeat this step. Additionally, if your virtual environment breaks for any reason, you can always delete thevenv
directory and repeat this step for a fresh environment.If you have to change the Python version of your virtual environment, delete it and repeat this step with the new Python version.
Do not use any name other than
venv
. Otherwise the linters and formatters will break.
Activate the Python virtual environment
If you haven’t already, activate the virtual environment:
Windows command prompt:
venv\Scripts\activate.bat
Windows Powershell:
.\venv\Scripts\Activate.ps1
If you get an error with:
running scripts is disabled on this system
Run:
Set-ExecutionPolicy Unrestricted
This allows you to run any Powershell scripts at will. For more detail: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.3
Linux and MacOS:
source venv/bin/activate
You should now see
(venv)
in the prompt line.Confirm the virtual environment uses Python 3.11:
python --version
Literally use
python
, none of the fancy stuff above.Example output:
Python 3.11.9
When you’re done developing, make sure to either close the terminal or run:
Windows command prompt:
venv\Scripts\deactivate.bat
Everything else:
deactivate
This is important to avoid going to a different project and then accidentally polluting your current project’s virtual environment.
Install packages
Open
requirements.txt
MacOS: Remove the line containing
--extra-index-url [link]
Windows and Linux:
If you have a CUDA capable GPU but don’t want to use it for some reason, remove the line containing
--extra-index-url [link]
If you don’t have a CUDA capable GPU, don’t change anything.
If you haven’t already, activate the virtual environment.
Download and install required packages:
pip install -r requirements.txt
This will install in your virtual environment under
venv
. The rest of your system is unaffected.
Done!
Directory
“I keep all my files in the recycle bin because they’re easier to get to.” - Overheard near the Director of Finance’s office
Now that you have everything needed to start, take a quick look at what you’re working with.
The repository is divided into 3 sections:
modules/
's free floating files contains the common classes that are passed around the interfaces.modules/bootcamp/
is where you will write your code.modules/private/
is the black box to control. The bootcamp is completable without ever looking here. In fact, we encourage you to hold off until after completing all the tasks.
Why would you tell me not to do that? Now I really want to see what’s in there: https://www.reddit.com/r/MemeTemplatesOfficial/comments/ej4rr5/well_now_i_am_not_doing_it_pingu/
The reason for not looking through modules/private/
is teach you to rely solely on the documentation, provided interfaces, and behaviour of the system after interacting with the interfaces. Many systems Autonomy interacts with are basically black boxed, which is why this is an important skill to learn.
Each file has a docstring header that will contain one of the following:
BOOTCAMPERS DO NOT MODIFY THIS FILE.
: Do not modify this file! Your submission will not be accepted if these files are modified.BOOTCAMPERS TO COMPLETE.
: Search forBOOTCAMPERS MODIFY BELOW THIS COMMENT
(there may be multiple) and follow the instructions.
Do not commit extra files! Your submission will not be accepted if you have extra files.
Do not import any additional libraries. The bootcamp is completable as is.
Development
“If it compiles, then it works, right?” - Top 10 moments before disaster
Every time you want to change code in your repository.
If you haven’t already, activate the virtual environment.
Follow the instructions in the tasks below.
Code away! Run the tests! Please follow our style guide: Python Style Convention
Ask questions if you need help!
Linter and formatter commands for reference:
black .
flake8 .
pylint modules
Make a commit:
Check which files have changed:
git status
Run:
git add [files you changed]
, where[files you changed]
are the files you want to add to the commit.Use
git add .
if you want to add all of them (the dot means wildcard in Git).
Run:
git commit -m "Your commit message"
When you’re ready to push your latest commits to GitHub:
git push
No harm in doing this after every commit.
When you’re done, make sure to either close the terminal or run:
Windows command prompt:
venv\Scripts\deactivate.bat
Everything else:
deactivate
This is important to avoid going to a different project and then accidentally polluting your current project’s virtual environment.
Optionally, you can also create new branches for yourself if you want to be more organized. You can search for git branch information online.
Windows Subsystem for Linux (WSL)
We do not recommend using WSL at this time because of several environment issues. You are free to make the attempt if you’re willing to encounter them (and if you solve them, please tell us). All Autonomy projects are currently cross platform so using Windows is perfectly fine.
CUDA issues:
If you have a CUDA capable GPU, you may encounter this error: Can't initialize NVML
in torch/cuda/__init__.py:497
The current workaround is to hide the GPU: export CUDA_VISIBLE_DEVICES=-1
This is not ideal since you are removing a hardware advantage.
MobaXterm display issues:
If you are using MobaXterm, we suggest using a different display server. MobaXterm's display window flashes and moves towards the bottom right as OpenCV redraws the image.
This issue does not occur with a different display server: Xming version 6.9.0.31 (most recent we could find) and running: export DISPLAY=:0
This may not be necessary depending on whether you have WSLg already.
Submission and pull request
“LGTM” - Every pull request ever.
LGTM is an initialism for Looks Good To Me.
Once your submission is ready for review, open a pull request (PR) from your fork to the WARG repository.
Navigate to WARG’s copy of the repository: https://github.com/UWARG/autonomy-bootcamp-2023
At the top, click Pull requests.
To the right, click the green New pull request button.
Under Compare changes, click the “compare across forks” link.
The 3rd from the left: Click the head repository dropdown and select your repository (you can search for your username).
The 4th from the left: Click the compare dropdown and select the branch you want to submit.
Do not open more than 1 pull request! The branch you select should contain (or eventually contain) all tasks which will be reviewed.
Once you have an open PR, you can keep updating the same branch as you get feedback. You do not need to open another PR.
Click on the green Create pull request button.
Once you have an open PR and are ready for review, go to your Discord bootcamp thread and send this message:
@AUTO-Bootcamp Reviewer My bootcamp is ready for review: [link to your PR on GitHub]
The Autonomy bootcamp reviewers will review your PR (a message will be sent on Discord, and the comments will be on GitHub).
Read the feedback and go back to development. If any of the feedback is unclear or confusing, don’t hesitate to ask for clarification (make sure to send a message on Discord as well for visibility (e.g.
I asked some questions as replies on GitHub
).Please do not click on Resolve conversation for any of the comments that the reviewers may leave! It causes confusion for the reviewers since they use the resolved/unresolved state to confirm that the code meets the quality to their satisfaction. Instead, you can use a reaction or reply to the comment for your own tracking purposes.
If you are ready for another review, repeat step 8 (you do not need to open a new PR).
Once your review is fully complete and you’re done with the bootcamp, please follow the steps in New Member Onboarding to onboard to the team.
Tasks
Hi WARG Bootcamper,
Welcome to the team. I've taken the liberty of compiling some starter tasks to get you up to speed. They should be pretty easy to complete. Feel free to reach out if you have any questions.
Brian J. Smith, Ph.D.
Senior Manager, Software Development
AutoBots
Can I ask other people for help?
We expect you to complete these bootcamp tasks on your own. You can ask for general advice, but please do not share code or look at other submissions. The bootcamp (and WARG in general) exists for you to learn and develop (and possibly also put something great into the sky while at it).
Can I use AI to write code for me?
We ask that you avoid using ML code generators such as ChatGPT or GitHub Copilot. Going through the iteration process (design, implementation, test, debug) yourself and gaining experience is much more valuable than completing the bootcamp faster. It also takes the fun out of doing it yourself; is it really an accomplishment if you just copy pasted code someone else wrote?
Do not raise exceptions. The only exception are assertions, and only for quieting the linter (e.g. assert value is not None
on Pylance). An assertion used in this way must be impossible to fail.
What’s wrong with exceptions?
Exceptions are computationally expensive to catch, which is why the Autonomy coding style often uses result booleans and/or default values instead. While the Autonomy bootcamp program will not crash if your code raises an exception, it will cause an early (graceful) exit.
Additionally, exceptions are difficult to reason about. An exception bypasses the call stack, making it difficult to determine where and why it is originally thrown (especially if caught and rethrown).
Task 1: Implementing ML inference
SOFTDEV-804072
Migrate Landing Pad Detection to Ultralytics
Assignee: WARG Bootcamper
Reporter: Sangeeta Singh
Last updated: 2004-09-06
Start using the Ultralyics YOLOv8 library for model inference
See [2002 Annual Architecture Design Document]
The files to change are:
modules/bootcamp/detect_landing_pad.py
Completion criteria: All tests pass (all green).
From the repository root, try running pylint modules
. You will notice that there are no issues and the code is rated 10.00/10 . Remove the Pylint ignore near the top of the file and run the command again. You will notice that the linter now reports several issues.
What is a linter?
Linters and formatters are tools that enforce a specific coding style. While there are several permutations of source code that result in the same program, standardization of the coding style is important for readability. Readability is important for collaboration, because others (including your future self) will be reading your code.
However, linters and formatters are not magic; it is still possible to write bad code that follows the coding style.
From the repository root, try running pytest modules/bootcamp/tests/test_detect_landing_pad.py
. You will notice that some of the unit tests fail.
What are unit tests?
Unit tests are used to test individual components of a system independently. This makes debugging much easier and faster by quickly narrowing the scope of problems that will develop from a system's increasing scope and complexity. There are many unit test frameworks out there; the most popular are Google Test (for C++) and Pytest (for Python). Autonomy uses Pytest, which you can see in modules/bootcamp/tests/test_detect_landing_pad.py
.
Your task is to implement the code in run()
to correctly identify landing pads.
Once your code is correctly implemented, all tests should pass.
Machine learning uses a LOT of memory (approximately 3-4GB of RAM). Make sure your computer has enough to spare.
The linters and formatters should also pass:
Black:
black .
Black is a formatter that edits the code layout (e.g. indentation, multiline).
Flake8:
flake8 .
Flake8 is a linter that reports whether function and methods are correctly type annotated.
Pylint:
pylint modules
Pylint is a general linter.
I don’t know what to do! I have no idea what’s going on!
When you get stuck, the first thing to do is to find documentation and examples. Then, experiment! Use the debugger and print statements to figure out what’s going on. If you’re still stuck, then reach out for help, bringing the information of what you tried and what worked/didn’t work.
Independence and problem solving skills are important for the Autonomy subteam, as members are students volunteering their limited time, and often themselves don’t know either. That being said, we don’t expect you to know everything about the system from day 1, so asking questions is expected.
The documentation is wrong or missing?
Unfortunately, documentation is not guaranteed to be correct or complete. The only reliable way to know how code behaves is to run it*. Trial and error is important to figure out what is really happening!
*Or to mathematically prove that the code will behave in a certain way using static analysis tools, but this is really hard (if you’re interested in why, search for Halting Problem and Gödel's Incompleteness Theorem).
Hints:
You can use the debugger and set breakpoints to see the object and its attibutes returned by
predict()
.A confidence threshold value of 0.7 works. Other values are also acceptable as long as it’s not too low or high.
Ultralytics documentation is slightly out of date, so some of the requested settings are not included. Try searching outside of the documentation!
Think about what you’re returning. Is it safe to assume that the code that will end up using your returned values has a check for
None
? After all, the method signature promises to return a list ofBoundingBox
, not a list ofBoundingBox | None
.
Task 2: Running the simulator
Hey WARG Bootcamper,
I heard you just joined the team, welcome! I can give you a tour of the office. You should definitely check out the flight simulator, it’s pretty cool!
-Tajel
The files to change are:
modules/bootcamp/tests/run_decision_example.py
Completion criteria: The simulator exits after the drone lands.
The simulator is composed of 5 pipelined stages:
Simulation: Simulates a physical drone.
Detection: Detects landing pad on camera image.
Geolocation: Converts bounding boxes to locations.
Display: Displays the camera image and drone information.
Decision: Commands the drone.
Information moves from each stage to the next, and the loop is completed with commands from Decision to Simulation. Simulation requires a command to be sent from Decision every time step, making the simulator synchronous (in lock step, as opposed to asynchronous). The Decision stage is where you’ll write code for task 3 and task 4.
From the repository root, try running python -m modules.bootcamp.tests.run_decision_example
. It should take about 12.5 seconds wall clock time for the drone to complete its first command (it will be obvious when it does). If the simulator is running too slowly, try increasing the time step size in modules/bootcamp/tests/run_decision_example.py
(reducing the FPS). Take a look at modules/bootcamp/decision_example.py
as well.
The simulator should exit after the drone lands, which occurs about 100 seconds after start. Ctrl-c to stop the simulator early. If the simulator exits early or has some error, then you should go through your task 1 code again and make sure there aren't any bugs. You are encouraged to use the debugger and/or print statements in conjunction with the simulator, as long as you do not breakpoint or step into modules/private/
.
Wait, what? What's wrong with seeing variables and code in there?
For the same reason we encourage you not to look before, in that having the skills to operate black boxed systems is important for Autonomy.
How buggy is the simulator?
Bugs are unlikely. The Autonomy subteam’s coding philosophy is to write lots and lots of tests, and to test often, and this bootcamp is no exception. At least 50% of development time of this bootcamp was spent on writing and running tests. Plus the bootcamp maintainers and Autonomy leads had to write solutions as well. If you do think you've found a bug, please contact the Autonomy leads and we'll take a gander at it.
Hints:
You can ignore these warnings:
Warning: Could not read image file: [n],[m].png
Warning: Loading default
Set Ultralytics verbosity to false (from task 1) to avoid getting spammed with detections.
The Ultralytics documentation for the
predict()
method lacks this as it is slightly outdated.
Task 3: Making the drone move to and land at a waypoint
SOFTDEV-377040
Command Drone to Travel and Land at Designated Waypoint
Assignee: WARG Bootcamper
Reporter: Patrick Khumalo
Last updated: 2001-01-15
Command the drone to move to the waypoint, and then execute landing procedure
See [Drone Expected Behaviour Document 1997]
The files to change are:
modules/bootcamp/decision_simple_waypoint.py
modules/bootcamp/tests/run_decision_simple_waypoint.py
Completion criteria: The simulator exits after the drone lands at the designed waypoint.
From the repository root, try running python -m modules.bootcamp.tests.run_decision_simple_waypoint
. You will notice that the simulator starts but doesn’t do anything before exiting. This is because of the raised NotImplementedError
exception.
The drone reports a status, which you will use to implement the drone decision logic to decide which command to send:
Halted: The drone is not moving.
Moving: The drone is moving.
Landed: The drone has landed and the simulator is ending.
In addition, the drone report also contains its position and global destination (if applicable).
For the Halted and Landed status, the report’s destination is the same as the report’s position.
There are 4 types of commands:
Null: Default. Does nothing but required to advance the simulator.
Set relative destination: Move distance relative to current position of the drone. Requires drone to be halted. The destination must also be within the flight boundary.
The flight boundary is a square from (-60.0, -60.0) to (60.0, 60.0). The drone’s initial position is (0, 0).
The drone halts when it reaches the destination.
Halt: Makes the drone stop immediately at its current position.
Land: Lands the drone at the current position and ends the simulation. Requires drone to be halted.
If an invalid command is sent, it is ignored with a warning.
Why isn't there a set absolute/global destination command? It would make my life much easier.
This is a deliberate bootcamp design choice we made. The systems Autonomy uses can have frustrating interfaces, and we're forced to work around or implement our own solution, so being able to work with what you have is important. Additionally, since a system we might interface with can be owned by another subteam, we might end up making it harder on them by forcing them to implement something that we can do ourselves.
Your task is to implement the code in __init__()
and run()
to travel to and land at the designated waypoint.
Once your code is implemented, the simulator should exit after the drone lands, which should occur within 60 seconds of start. The difference between the coordinates of the drone position and waypoint under the text file in log/
should be less than 0.1 . You can also confirm with the screenshot.
The linters and formatters should also pass.
Hints:
You do not need to use
landing_pad_locations
in this task.You can use the drone report’s destination to see if your relative command is correct.
Ideally, the drone will report Halted at the beginning of the simulation and when it reaches the waypoint. The rest of the time, it will report something that isn’t Halted.
So you’ll have to find a way to know the difference between Halted at initial position and Halted at the waypoint.
Bonus:
While the simulated drone will always successfully complete its movement, what if it was possible for the drone to halt at any time (without your input)? Does your code handle this case?
Task 4: Putting it all together
SOFTDEV-69716810
Integrate waypoint travel and local landing pad
Assignee: WARG Bootcamper
Reporter: Michael Slackenerny
Last updated: 2077-04-20
Drone travels to waypoint then closest landing pad then lands
See [Drone Expected Behaviour Document 1997]
The files to change are:
modules/bootcamp/decision_waypoint_landing_pad.py
modules/bootcamp/tests/run_decision_waypoint_landing_pad.py
Completion criteria: The simulator exits after the drone lands at the correct landing pad.
From the repository root, try running python -m modules.bootcamp.tests.run_decision_waypoint_landing_pads
. You will notice that the simulator starts but doesn’t do anything before exiting. This is because of the raised NotImplementedError
exception.
You can copy and paste your code from the __init__()
and run()
methods of decision_simple_waypoint.py
to see what happens. Do not copy the entire file, as the class name and descriptions are different.
Your task is to implement the code in __init__()
and run()
to travel to the designated waypoint, calculate which landing pad is closest (L-2 norm for the math nerds), and land at that landing pad. You can remove or comment out the NotImplementedError
line.
Once your code is implemented, the simulator should exit after the drone lands, which should occur within 60 seconds of start. The difference between the coordinates of the drone position and the landing pad under the text file in log/
should be less than 0.1 . You can also confirm with the screenshot.
The linters and formatters should also pass.
Hints:
You can write a helper function to calculate the distance between 2 Location objects. This will make the finding closest landing pad code easier to read and write.
You can initialize the distance value with a very large number (e.g. infinity). Then the first landing pad’s distance will definitely be smaller than this. Details of the loop and logic are for you to implement…
Don’t constantly recalculate the distances if you don’t need to.
What if the closest landing pad is directly on the waypoint? Your code needs to handle this case.
Bonus:
Square roots are computationally expensive, is there a way to avoid using it?