diff --git a/docs/.readthedocs.yaml b/docs/.readthedocs.yaml new file mode 100644 index 00000000..b67bdf03 --- /dev/null +++ b/docs/.readthedocs.yaml @@ -0,0 +1,19 @@ +# Read the Docs configuration file for MkDocs projects +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.12" + +mkdocs: + configuration: mkdocs.yml + +# Optionally declare the Python requirements required to build your docs +python: + install: + - requirements: docs/requirements.txt \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index 62150a28..00000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = ./ -BUILDDIR = build/ - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index 9757649d..00000000 --- a/docs/conf.py +++ /dev/null @@ -1,56 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -import os -import sys -sys.path.insert(0, os.path.abspath('../executor/')) - - -# -- Project information ----------------------------------------------------- - -project = 'Runtime' -copyright = '2021, Pioneers in Engineering' -author = 'Pioneers in Engineering' - -# The full version, including alpha/beta/rc tags -release = '1.0.1' - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - "sphinx.ext.autodoc" -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'alabaster' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = [] diff --git a/docs/docs/api.md b/docs/docs/api.md new file mode 100644 index 00000000..c654de2f --- /dev/null +++ b/docs/docs/api.md @@ -0,0 +1,297 @@ +# API Reference + +The Student API is the set of functions available to students to communicate with their robots. The api can be split into two distinct class types. The Robot Class used for getting, setting, and running functions; input classes including the Gamepad Class and the Keyboard Class which are used to take student input to control their robots. + +for more information refer to the Student API section of the [Runtime Wiki](https://github.com/pioneers/runtime/wiki) + +# +[//]: # (find better word for code periods later) +* [Run Mode](#run-mode) + * [`Teleop` Period](#teleop-period) + * [`Auto` Period](#auto-period) +* [`Robot` Class](#robot-class) + * [`Robot.get_value(device_id, param)`](#robotget_valuedevice_id-param) + * [`Robot.set_value(device_id, param, value)`](#robotset_valuedevice_id-param-value) + * [`Robot.run(function_name, args...)`](#robotrunfunction_name-args) + * [`Robot.is_running(function_name)`](#robotis_runningfunction_name) + * [`Robot.sleep(seconds)`](#robotsleepseconds) +* [Input Classes](#input-classes) + * [`Gamepad.get_value(name_of_input)`](#gamepadget_valuename_of_input) + * [`Keyboard.get_value(name_of_key)`](#keyboardget_valuename_of_key) + +# Run Mode +The two run modes, `autonomous` and `teleop` are where a majority of student code will be run. These functions are run in the Autonomous period and Teleoperated period of a PiE competition. Autonomous code restricts student's access to the `Keyboard` and `Gamepad` functions, forcing them to write code that will run without any input. The Teleoperated period allows for control from both, giving students more freedom to control their robot through any of the challenges presented in that phase. + + + +## `AUTO` Period +The autonomous or `AUTO` period is used anytime keyboard or controller input is restricted. Within this period you are encouraged to write code that will be able to run without any user input. + +An example of this would be running a robot forward for a set duration within an `AUTO` period + +```py +motor = "//INSERT MOTOR ID HERE//" + +def autonomous_main(): + # keeps motor A running at max speed for 10 seconds + Robot.set_value(motor, velocity_a, 1) + Robot.sleep(10) # stops the execution of any other functions for a specified number of seconds + Robot.set_value(motor, velocity_a, 0) +``` +For more recourses please refer to the [Software Hub Autonomous Guide](https://pioneers.berkeley.edu/competition/SoftwareHub/Teleop/) + + +## `TELEOP` Period + The teleoperated or `TELEOP` period is used anytime remote input via a controller or keyboard is used. The `teleop_main()` function runs in a loop until the teleoperated period has completed. + + This code is most useful when a student would like to use controller or keyboard input to control their robot on the game field. + +```py +motor = "//INSERT MOTOR ID HERE//" + +def teleop_main(): + # sets the motor's velocity to max if the button A is pressed + if(Gamepad.get_value(button_a) == True): + Robot.set_value(motor, velocity_a, 1) +``` + +For more recources please refer to the [Software Hub Teleop Guide](https://pioneers.berkeley.edu/competition/SoftwareHub/Teleop/) +## `SETUP` Phase + The `SETUP` phase prepares for either the `AUTO` or `TELEOP` function to be run. In this phase a student can set or get the value of any lowcar device (any device connected to the robot that can be controlled with the PiE api). + + This function is useful when a student would want to turn off the CURRENTLY BROKEN PiD control on a motor controller +```py +motor = "//INSERT MOTOR ID HERE//" + +def teleop_setup(): # code segment run before the teleop_main() function + Robot.set_value(motor, pid_enabled_a, False) + Robot.set_value(motor, pid_enabled_b, False) + +def autonomous_setup(): # code segment run before the autonomous_main() function + Robot.set_value(motor, pid_enabled_a, False) + Robot.set_value(motor, pid_enabled_b, False) +``` + +# `Robot` Class +The robot class holds all methods for interacting with various arduino devices connected to a student’s robot. These devices include servos, motors, and sensors. + +## `Robot.get_value(device_id, param)` +The get_value function returns the current value of a specified `param` of the device with the specified device_id. + +* `device_id`: the ID that specifies which PiE device will be read +* `param`: identifies which parameter on the specified PiE device will be read. Possible param values depend on the specified device. Find a list of params for each device on the device get page + +The function is useful for checking the current state of devices. For example, getting the current state of the limit switch using its device_id and the param “switch0” will return the value True when pressed down and False if not. + +```py +# first segment of code ran in the teleop process +limit_switch = "//INSERT SWITCH ID HERE//" + +def teleop_setup(): + print("Tele-operated mode has started!") + pass + +def teleop_main(): + # example code for getting the value of a limit switch + + # first parameter is the limit switch's id + # second parameter tells which switch to get the value from + + # in this case the method will return True or False depending on if the switch is pressed down or not + + Robot.get_value(limit_switch, switch0) + pass + +``` +For more examples and devices refer to the devices page in the reference + + +## `Robot.set_value(device_id, param, value)` +The `set_value` function sets a specified value to a device’s parameter + +* `device_id`: the ID that specifies which PiE device will have its parameter set +* `param`: determines which parameter should be set. The parameters depend on the specified Lowcar device and can be found at INCLUDE LINK TO LOWCAR DEVICE PAGE +* `value` - the value to set the parameter to + +This function is useful for setting the state of parts of your robot while driving. For example calling the set_value param `“velocity_a”` with a KoalaBear device (motor controller) with a value of `1` results in the attached motor spinning forwards at full power + + +[//]: <> (MAKE CODE SEGMENTS COLLAPSIBLE) +```py +# first segment of code ran in the teleop process +motor = "//INSERT MOTOR ID HERE//" + +def teleop_setup(): + print("Tele-operated mode has started!") + pass + +def teleop_main(): + # example code for turning a motor forward at full speed + # first parameter is the motor controller's id set as a variable + # second parameter 'velocity_a' tells a motor controller which motor to drive + # third parameter sets the value + + Robot.set_value(motor, velocity_a, 1) + pass + +``` + +## `Robot.run(function_name, args)` +The `Robot.run()` runs another function, passing the `args` fed into the function. The `function_name` is run in parallel to any other code run following the `Robot.run()` function. + +* `function_name`: the name of a function in the student code which will be run simultaneously with the main loop + +* `args`: this is a list of zero or more inputs, which will be passed to the function_name specified previously as arguments (inputs) + +[//]: <> (I want to separate the code example and this line of text. Not exactly sure how to do it so adding this comment to come back to it) +An example of this would if a student would want to run a process alongside the teleop_main loop. Using the Robot.sleep class to define the amount of time a motor should rotate for without stopping the teleop_main loop. +​ + +[//]: <> (FULL CODE WITHOUT ANY REMOVED CODE SEGMENTS //REMOVE//) +```py +ARM_MOTOR = "INSERT MOTOR_ID HERE" +DRIVE_MOTOR = "INSERT MOTOR_ID HERE" + + +def arm_movement(): + # moves arm up for 1 second and then moves it down for 1 second + # assumes arm is attached to motor A of MC "ARM_MOTOR" + if(Gamepad.get_value("button_a")): + Robot.set_value(ARM_MOTOR, "velocity_a", 0.5) + Robot.sleep(1) + Robot.set_value(ARM_MOTOR, "velocity_a", -0.5) + Robot.sleep(1) +​ +def teleop_setup(): + # starts the arm_movement subroutine in parallel to the main thread + Robot.run(arm_movement) + pass +​ +def teleop_main(): + # put your teleop code here and it will run along side the arm_movement thread + if(Gamepad.get_value("button_b")): + Robot.set_value(DRIVE_MOTOR, "velocity_a", 1) + +``` + + +## `Robot.is_running(function_name)` +The `Robot.is_running()` function returns a boolean value (`True` or `False`) for whether or not the specified function is still running. + +`function_name`: the name of a function defined by the student. If run through `Robot.run()` it will be the same inputted `function_name` + +An example usage of this would be to wait for a `Robot.run()` process to finish before allowing user input for another process. + +```py + +def robot_actions(): + # series of actions from the Robot.set_value(). + +def teleop_setup(): + pass + +# if the button A is pressed down and robot_actions are not running. Then the robot will be able to run robot_actions again. Will not run if the button A is not pressed or if robot_actions is running +def teleop_main(): + if Gamepad.get_value(button_a) and not Robot.is_running(robot_actions): + Robot.run(robot_actions) + + +``` + + + +## `Robot.sleep(seconds)` +Pauses the execution of the current function for the specified number of `seconds`. + +`seconds`: the number of `seconds` to pause the execution of the current function for. +It should be emphasized that calling `Robot.sleep` in one function does not cause any other function that is being run by `Robot.run()` or the main loop function to pause. Only the instance of the function that is executing the call to `Robot.sleep` will pause execution. It is highly recommended to not use this function in the setup functions or main loop functions--only in functions executed by `Robot.run()`. + +a great place to use `Robot.sleep()` would be to make a robot go to a specific spot using set motor velocities and ammount of time each function should run. +[//]: <> (could go further and say that `Robot.sleep()` combined with encoder ticks per revolution could allow you to specify a distance your robot could go) + +```py +MOTOR_ID = "INSERT MOTOR_ID HERE" + +def autonomous_setup(): + print("Autonomous mode has started!") + robot.run(autonomous_actions) # runs the autonomous_actions function in parallel to autonomous main + + +def autonomous_main(): + pass + +def autonomous_actions(): + print("Action 1") # action one sets the motor velocities to 1 + Robot.set_value(MOTOR_ID, "velocity_b", 1.0) + Robot.set_value(MOTOR_ID, "velocity_a", 1.0) + Robot.sleep(1.0) # holds the function for one second before running the next lines + print("Action 2") # the following code sets the motor velocities to 0 + Robot.set_value(KOALA_BEAR, "velocity_b", 0) + Robot.set_value(KOALA_BEAR, "velocity_a", 0) + +``` + +# Input Classes +The input classes are both of the input classes that can only be run during the teleoperated game phase. These two classes allow a student to receive a boolean value for whether or not a button is pressed down or not. Most students will use these classes to + +## `Gamepad.get_value(input)` +The `Gamepad` class receives input for when there is a change to a controller. This class is only usable during the teleop phase. + +`input`: identifies which button or joystick will be returned. This function is useful for checking the state of a button or joystick + +For example, if you wanted to print `"hello world"` when the `"button_a"` is pressed and false when it isn't you would use the function as a condition in an if statement + +```py +# segment of code will print "hello world" into the console when button_a is pressed +def teleop_main(): + if Gamepad.get_value("button_a"): + print("hello world") +``` +This function is essential for controlling your robot with the game pad. + +The possible button inputs are: +* "button_a" +* "button_b" +* "button_x" +* "button_y" +* "l_bumper" +* "r_bumper" +* "l_trigger" +* "r_trigger" +* "button_back" +* "button_start" +* "l_stick" +* "r_stick" +* "dpad_up" +* "dpad_down" +* "dpad_left" +* "dpad_right" +* "button_xbox" + +The possible joystick inputs are: +* "joystick_left_x" +* "joystick_left_y" +* "joystick_right_x" +* "joystick_right_y" + +Note that the joysticks function differently from the button inputs. Rather then returning a Boolean `[True or False]`, they return a floating point value ranging from `-1.0 `and` 1.0` (inclusive) + +## `Keyboard.get_value(input)` +The `Keyboard` class allows a student to receive keyboard input. Like the `Gamepad` class, it is only usable during the teleop game phase. + +`input`: identifies which key is being read. When pressed the `get_value` will return a `True` boolean and `False` when not. + +possible keyboard inputs are: +* The letters on the keyboard, lowercase and no spaces `"a"`-`"z"` +* The numbers on the keyboard, no spaces `"0"`-`"9"` +* The punctuation keys `","`, `"."`, `"/"`, `";"`, `"'"`, `"["`, `"]"` +* The four arrow keys `"left_arrow"`, `"right_arrow"`, `"up_arrow"`, `"down_arrow"` + +For example, if you wanted to print `"hello world"` when the `"w"` is pressed and false when it isn't you would use the function as a condition in an if statement + +```py +# segment of code will print "hello world" into the console when the w key is pressed +def teleop_main(): + if Keyboard.get_value("w"): + print("hello world") +``` \ No newline at end of file diff --git a/docs/docs/dawn.png b/docs/docs/dawn.png new file mode 100644 index 00000000..bc33fe80 Binary files /dev/null and b/docs/docs/dawn.png differ diff --git a/docs/docs/dawn_quickstart.md b/docs/docs/dawn_quickstart.md new file mode 100644 index 00000000..73c6b571 --- /dev/null +++ b/docs/docs/dawn_quickstart.md @@ -0,0 +1,58 @@ +# Dawn Tutorial + +Dawn is an essential tool for interfacing with your robot. It is a code editor with features that allow you to upload and download code from your robot. Dawn will also display information about any connected PiE device for example a motor controller or a limit switch. In this tutorial you will learn how to install dawn and upload . + +# Getting Started + +To install dawn you will need a couple of prerequisites +- a mac, linux, or windows computer +- install of dawn + +## Installing Dawn + +To install Dawn, go to https://github.com/pioneers/dawn/releases/ and install the latest release for your corresponding operating system. Extract the file using your operating system's unzipping method and then follow the next os specific steps + +## Windows +To install the windows version first download your correct version highlighted below. +![Alt text](image-3.png) + +After installing dawn-win32-x64.zip unzip the folder. On Windows, you can do this by right clicking on the ZIP file and selecting "Extract all." + +Extracting the ZIP file will create a new folder. Open this folder and find the file "Dawn.exe" (Windows) click on it to start Dawn. + +![Dawn.exe](dawn.png) + +## Linux + +After installing the dawn-linux-x64.zip unzip to your desired install directory. Then with the shell open use the commands + +```console +user@pc:~$ cd [dawn parent directory]\home\sberkun\Documents\pie\dawn\dawn-packaged\dawn-linux-x64 +``` + +After changing the parent directory to match your own install. This command will put you into the working directory of dawn. From there you can start the program by running the script using the following command + +```console +user@pc:~$ ./dawn +``` + +Assuming you have a linux gui, the program will run displaying dawn +# Dawn Instructions + +After installing Dawn you will be presented with Dawn, as well as a interactive guide you can access by clicking on the "Tour button" + +![Dawn Starting guide](image-1.png) + +The tour will go through all of the special features of dawn including the run modes. + +## Getting Connected + +To connect to your robot you will need to know your teams number and your router password. TO connect to your robot, you will first have to connect to your team's router. To do this find the router for your team. Your router should be named "team" followed by your team number, for example "team40". Then find the password located on the back of your router and connect to the network. + +Next with dawn open, navigate to the `robot ip` indicated by this button ![robot ip button](image-2.png). In the opened screen fill in the information for the IP Address and SSH Address. This can depend on your team but it will usually be 192.168.0.[`team number`] or by using team[`team number`].local + +when filled out it should look similar to this: + +![filled out dawn configuration](image.png) + +Now with your information filled out press the update button to save your settings and wait until dawn shows that it's connected to your robot. \ No newline at end of file diff --git a/docs/docs/device.md b/docs/docs/device.md new file mode 100644 index 00000000..8d2ac1cb --- /dev/null +++ b/docs/docs/device.md @@ -0,0 +1,24 @@ +# Lowcar Device reference + +Lowcar is the name given to all of the code in the repo that runs on an Arduino microcontroller, which controls the various devices. Most of your teleoperated code will designed to interface with these lowcar devices. These devices include BatteryBuzzer, KoalaBear (motor controller), LimitSwitch, LineFollower, and ServoControl. In this tutorial, you will find in-depth explanations of each device and how to control them. + +For more detailed information and descriptions on the Lowcar devices please refer to the [runtime wiki](https://github.com/pioneers/runtime/wiki/Lowcar) + +# More Background on the infomration + +in each device page, the device information will be separated into three parts, a photo of the device, the device's parameters, a general description of it's intended usage and other possible applications. + +## Limit Switch +![Limit Switch](https://raw.githubusercontent.com/pioneers/runtime-docs/master/device-pics/LimitSwitch.JPG) + +### Parameters +| Name | Data type | Readable| Writeable | +|---------|-----------|---------|-----------| +| switch0 | BOOL | TRUE | FALSE | +| switch1 | BOOL | TRUE | FALSE | +| switch2 | BOOL | True | FALSE | + + + +A limit switch is a device wired with three switches. These switches, `switch0`, `switch1`, AND `switch2` each have a metal actuator attached to them. The original purpose of a limit switch is to limit an object from going past a certain endpoint. However, it's use isn't limited to limiting the range of an object, for example using it to detect the presence of an object in a certain place or not. + diff --git a/docs/docs/device_get.md b/docs/docs/device_get.md new file mode 100644 index 00000000..cd1c3bb1 --- /dev/null +++ b/docs/docs/device_get.md @@ -0,0 +1,119 @@ +# `Robot.get_value(device, param)` for Lowcar Devices + +## Limit Switch + +![Limit switch](https://raw.githubusercontent.com/pioneers/runtime-docs/master/device-pics/LimitSwitch.JPG) + +Returns a value from a specified `device_id` and `param` + +`param` for a Limit Switch + +- `"switch0"` +- `"switch1"` +- `"switch2"` + +The parameters for a Limit Switch describe which of the three switches is being read. The boolean value will be `True` if the specified switch is being pressed and `False` if it is not. + +**Sample Usage:** + +```py +# returns a boolean for whether or not switch0 is pressed +Robot.get_value(limit_switch_id, "switch0") +``` + +## Line Follower + +![Line Follower](https://raw.githubusercontent.com/pioneers/runtime-docs/master/device-pics/LineFollower.JPG) +Returns a value associated with the `device_id` and `param` specified. + +The device being specified is a Line Follower. + +parameters for a Line Follower: + +- `"left"` +- `"center"` +- `"right"` + +The `param` for a Line Follower describe how much light is being reflected into each sensor. It returns a value between 0 and 1 where a lower value means less light and the sensor is farther off of the reflective tape. + +**Sample Usage:** + +```py +# returns how much light is seen from the center sensor on the line follower +Robot.get_value(line_follower_id, "center") +``` + +## Servo Controller + +![Servo Controller](https://raw.githubusercontent.com/pioneers/runtime-docs/master/device-pics/ServoControl.JPG) +Returns a value associated with the `device` and `param` specified. + +The device being specified is a Servo. + +`param` for a Servo: + +- `"servo0"` +- `"servo1"` + +The parameters for a Servo describes what angle the servo has turned to. It returns a Float from -1 to 1 where both -1 and 1 represent the two end positions for the servo. + +**Sample Usage:** + +```py +# returns the current angle of servo0 +Robot.get_value(servo_id, "servo0") +``` + +## KoalaBear + +![KoalaBear](https://raw.githubusercontent.com/pioneers/runtime-docs/master/device-pics/KoalaBear.JPG) +Returns a value associated with the `device` and `param` specified. + +The device being specified is a YogiBear. + +parameters for a YogiBear: + +Motor A + +- `"velocity_a"` +- `"deadband_a"` +- `"invert_a"` +- `"pid_enabled_a"` +- `"pid_kp_a"` +- `"pid_ki_a"` +- `"pid_kd_a"` +- `"enc_a"` + +Motor B + +- `"velocity_b"` +- `"deadband_b"` +- `"invert_b"` +- `"pid_enabled_b"` +- `"pid_kp_b"` +- `"pid_ki_b"` +- `"pid_kd_b"` +- `"enc_b"` + +The parameters for a KoalaBear can be split into 3 categories: + +Motor Control includes: + +- `"velocity"` which returns a float from -1 to 1 which describes the direction the motor is turning and it's power. +- `"deadband"` which returns the threshold that velocity must pass before a change is made to `"velocity"` + +Encoder Control includes: + +- `"enc"` parameters which return information about the position and velocity of the robot. Position is returned as an integer that represents the number of ticks of the encoder. There are 46 per revolution of the encoder. + +PiD Control includes: + +- `"pid_kp"`, `"pid_ki"`, and `"pid_kd"` parameters which return the proportional, integral, and derivative coefficients on the motor controller. +- `"pid_enabled"` parameter returns whether or not pid is enabled for a motor. + +Sample Usage: + +```py +# returns the current speed of Motor A as a value from -1 to 1 +Robot.get_value(motor_id, "velocity_a") +``` diff --git a/docs/docs/device_set.md b/docs/docs/device_set.md new file mode 100644 index 00000000..4079f167 --- /dev/null +++ b/docs/docs/device_set.md @@ -0,0 +1,72 @@ +# `Robot.set_value(device, param)` for Lowcar Devices + +## Servo Controller + +![Servo Controller](https://raw.githubusercontent.com/pioneers/runtime-docs/master/device-pics/ServoControl.JPG) +sets a value associated with the `device` and `param` specified. + +The device being specified is a Servo. + +`param` for a Servo: + +- `"servo0"` +- `"servo1"` + +Changing values for the `servo` spins the servo to an angle based on the value entered. The values -1 and 1 each refer to the maximum position of the servo in one direction. For example, if we described our minimum position to be 0°, and our maximum to be 180°, then 1 would set the servo to 180°, -1 would set the servo to 0°, and -0.5 would set it to be 45°. + +**Sample Usage:** + +```py +# sets the current angle of servo0 to 180° +Robot.set_value(servo_id, "servo0", 1) +``` + +## KoalaBear + +![KoalaBear](https://raw.githubusercontent.com/pioneers/runtime-docs/master/device-pics/KoalaBear.JPG) +sets a value associated with the `device` and `param` specified. + +The device being specified is a YogiBear. + +parameters for a YogiBear: + +Motor A + +- `"velocity_a"` +- `"deadband_a"` +- `"invert_a"` +- `"pid_enabled_a"` +- `"pid_kp_a"` +- `"pid_ki_a"` +- `"pid_kd_a"` +- `"enc_a"` + +Motor B + +- `"velocity_b"` +- `"deadband_b"` +- `"invert_b"` +- `"pid_enabled_b"` +- `"pid_kp_b"` +- `"pid_ki_b"` +- `"pid_kd_b"` +- `"enc_b"` + +Motor control is handled through changing the values of `"velocity_a"` and `"deadband_a"`. + +- `"velocity"` which sets a float from -1 to 1 which describes the direction the motor is turning and it's power. +- `"deadband"` which sets the threshold that velocity must pass before a change is made to `"velocity"` + +The encoder's value can be set using the `"enc"` parameter. Setting the `"enc"` count allows for someone to change the number of ticks recorded from the encoder. + +PiD Control includes: + +- `"pid_kp"`, `"pid_ki"`, and `"pid_kd"` parameters which set the proportional, integral, and derivative coefficients on the motor controller. Each of these values have to be above zero. +- `"pid_enabled"` parameter sets whether or not pid is enabled for a motor. + +Sample Usage: + +```py +# sets the current speed of Motor A to max speed +Robot.set_value(motor_id, "velocity_a", 1) +``` diff --git a/docs/docs/first_program.md b/docs/docs/first_program.md new file mode 100644 index 00000000..f195583f --- /dev/null +++ b/docs/docs/first_program.md @@ -0,0 +1,148 @@ +# Getting Started + +Python is a interpreted, object-oriented, high-level programming language. All robots in PiE are coded in Python 3 using a Application User Interface (API) known as the the student API. This API includes essential methods such as `Robot.get_value()`, `Robot.set_value()`, `keyboard.get_value()`, and `Gamepad.get_value()`, which you'll frequently use as a student. + +This section is intended for individuals with a basic understanding of Python coding. If you're new to Python, we recommend starting with [The Python Tutorial](https://docs.python.org/3/tutorial/index.html) first to familiarize yourself with the language. +## Teleoperated And Autonomous + +The student rule book outlines two distinct phases: the teleoperated phase and the Autonomous phase. During the Autonomous phase, you are restricted to utilizing only the `Robot` class and it's methods. In contrast to the Teleoperated mode allowing use for all classes and thus the ability to control the robot in real time. + +# Autonomous Mode + +The autonomous mode is the first game phase you will encounter. In this mode, you will be required to navigate a task without the use of any input classes: `gamepad` or `keyboard`. Autonomous actions defined in the `def autonomous_main()` will only run once from top to bottom. In contrast, the Teleoperated phase gives you unrestricted access to all of the Student API classes. This means you're allowed to use input from both the `Keyboard` and `Gamepad` classes. Also keep in mind the function `def teleop_main()` will run in a continuous loop. This is where you can use decision making statements like `if`, `elif`, and/or `else` to control any of the PiE devices. + +## Autonomous Setup + +The autonomous setup phase is what happens before the autonomous main function. Within the function `def autonomous_setup()` any code ran within this function will be done before running the `def autonomous_main()` function. The best use for this would be to set the value of a device before the autonomous main function. + +For instance, if you wanted your motors to drive in the opposite direction as your set velocity you could do something like: + +```py +motor_id = "YOUR MOTOR ID HERE" # variable that holds the motor_id + + +def autonomous_setup(): # setup function + Robot.set_value(motor_id, "invert_a", True) # inverts the direction of the device with a corresponding motor_id +``` + +## Autonomous Main + +Autonomous Main is the function run after `autonomous_setup`. In the function `autonomous_main()` you are allowed to write a sequence of functions that will be run durring this period. While running, main function will sequentially run through the list of operations until completed. This could be useful if you want a sequence of python functions to be run one after another without any delay's in the sequence. + +This sample code uses the `autonomous_main():` function to set the value of a motor to full speed + +```py +motor_id = "YOUR MOTOR ID HERE" # variable that holds the motor_id + +def autonomous_setup(): # setup function runs before autonomous main + pass + +def autonomous_main(): +Robot.set_value(motor_id, "velocity_a", 1) # sets the motor speed to the max speed +``` + +The `autonomous_main` function and `autonomous_setup` aren't very useful alone. However combined with the `Robot.run()` allows for further control over the timings of the code sequence. `Robot.run()` allows someone to run a process on a separate thread (runs the code at the same time as a main loop). This means a student will be able to use `Robot.sleep(seconds)` to wait before running the next function call. + +do note that although it's not required, you're recommended to assign the function type `async` for any function being run within the `Robot.run()` function. This will define the function as a coroutine and make it easier to separate from any of your other functions. + +```py +motor_id = "YOUR MOTOR ID HERE" # variable that holds the motor_id + +async def autonomous_actions(): # a custom asynchronous function with a sequence of actions + Robot.set_value(motor_id, "velocity_a", 1) + Robot.sleep(10) # stops for 10 seconds + Robot.set_value(motor_id, "velocity_a", 0.5) + Robot.sleep(0.5) # stops for 0.5 seconds + Robot.set_value(motor_id, "velocity_a", 0) + # sequence of commands sets the speed of motor A to max speed for ten seconds, then sets the speed to 1/2 of that speed and finally stops the motor + +def autonomous_setup(): # runs before autonomous_main() +# note that you can still call Robot.run() here + +def autonomous_main(): + # where the autonomous actions are ran + Robot.run(autonomous_actions) # runs the function autonomous actions on a separate thread +``` + +# Teleoperated Mode + +Following the Autonomous mode, the Teleoperated Mode happens after the Autonomous phase ends. Within this phase, you are granted the ability to use input from both the `Keyboard` and `Gamepad` classes, allowing you to directly your robot. To use Teleoperated functions, you can use the `def teleop_main()` and `def teleop_setup()` methods, with the former executed after the latter to ensure proper initialization and seamless functionality. + + + +## Teleop Setup + +Just as with the autonomous setup, the Teleop setup and Autonomous setup serve the same purpose. The `def teleop_setup():` function is best used to pre-configure any necessary values or settings prior to executing the `teleop_main` loop. To call the Teleop setup use the function `def telop_setup():`. This function is used to prepare any values before running the main teleop loop. + +A example usage of this would be to turn off the pid on the motor controllers. To do this do: + +```py +motor_id = "YOUR MOTOR ID HERE" # varible that holds the motor_id + +def teleop_setup(): # setup function + Robot.set_value(motor_id, "pid_enabled_a", False) # disables pid on motor 1 + Robot.set_value(motor_id, - "pid_enabled_b", False) # disables pid motor 2 +``` + + +## Teleop Main + +Just as with the `autonomous_main()` the `teleop_main()` function serves as the primary place to execute all of your code. The teleop function is the only function that allows for student input from both the Keyboard and Gamepad classes. Using the teleop main loop, you can create if statements to read your input and thus change the values of any attached robot devices. + +To best take advantage of the teleop_main loop, you can create a control structure using `if`, `elif`, and `else` statements. In this example a Robot is responding to when a keyboard w key is pressed. + +```py +motor_id = "YOUR MOTOR ID HERE" # variable that holds the motor_id + +def teleop_setup(): # setup function + pass + + +def teleop_main(): + if(Keyboard.get_value("w") == True): + Robot.set_value(motor_id, "velocity_a", 1.0) # sets the value of motor 1 to 100% power if w is pressed + else: + Robot.set_value(motor_id, "velocity_a", 0.0) # sets the value of motor 1 to 0% power when w is not pressed +``` + + +# Example Code +Finally this example program combines all of the other elements used in the code. You can expect your code to look similar to this. + +```py +left_motor = "YOUR MOTOR ID HERE" +right_motor = "YOUR MOTOR ID HERE" + + +#--------------- Autonomous Mode ---------------# +def autonomous_setup(): # determines what will be done before `def_autonomous_main():` runs + print("Autonomous mode has started!") + +def autonomous_main(): # where you put a sequence of actions + Robot.run(autonomous_actions) + + +#--------------- Teleoperated Mode ---------------# +def teleop_setup(): + Robot.run(teleop_input) + print("Tele-operated mode has started!") + +def teleop_main(): + if(Keyboard.get_value("w") == True): + Robot.set_value(motor_id, "velocity_a", 1.0) # sets the value of motor 1 to 100% power if w is pressed + else: + Robot.set_value(motor_id, "velocity_a", 0.0) # sets the value of motor 1 to 0% power when w is not pressed + +#--------------- Extra Functions ---------------# +async def autonomous_actions(): # a separate function that runs + print("Autonomous action sequence started") + await Actions.sleep(1.0) + print("1 second has passed in autonomous mode") + +async def teleop_input(): + if(Keyboard.get_value("d") == True): + Robot.set_value(motor_id, "velocity_b", 1.0) # sets the value of motor 2 to 100% power if w is pressed + else: + Robot.set_value(motor_id, "velocity_b", 0.0) # sets the value of motor 3 to 0% power when w is not pressed + +``` diff --git a/docs/docs/image-1.png b/docs/docs/image-1.png new file mode 100644 index 00000000..ff4d29dc Binary files /dev/null and b/docs/docs/image-1.png differ diff --git a/docs/docs/image-2.png b/docs/docs/image-2.png new file mode 100644 index 00000000..f0c76516 Binary files /dev/null and b/docs/docs/image-2.png differ diff --git a/docs/docs/image-3.png b/docs/docs/image-3.png new file mode 100644 index 00000000..dda5ee90 Binary files /dev/null and b/docs/docs/image-3.png differ diff --git a/docs/docs/image.png b/docs/docs/image.png new file mode 100644 index 00000000..2f8fe0e9 Binary files /dev/null and b/docs/docs/image.png differ diff --git a/docs/docs/index.md b/docs/docs/index.md new file mode 100644 index 00000000..c91dae80 --- /dev/null +++ b/docs/docs/index.md @@ -0,0 +1,25 @@ +# Welcome to Student API Docs + +The student API is the set of all functions that the students have available to them to communicate with the robot. Outlined in the glossary will be all relevant information to begin coding a Pioneers In Engineering (PiE) robot. + +This glossary encapsulates all the information relevant to programming your robot. In these docs you will find a collection of pages encapsulating each part of programming a robot from uploading your first script to creating your first student code. You can also find information explaining how to use PiE specific objects including the `Robot`, `Keyboard`, and `Gamepad` classes. It serves as the starting point for anyone venturing into the world of PiE robotics, offering a solid foundation to explore and create within this field. + +## Glossary + +
    +
  1. Welcome
  2. +
  3. Dawn Quickstart
  4. +
  5. First Program
  6. +
  7. Best Coding Practices
  8. +
  9. API Refrence
  10. +
  11. Device Get
  12. +
  13. Device Set
  14. +
+ +## Extra Recources +* [Python Documentation](https://docs.python.org/3/) +* [Software Hub](https://pioneers.berkeley.edu/competition/SoftwareHub) +* [Compatition Infomation](https://pioneers.berkeley.edu/Competition) +* [Runtime Wiki](https://github.com/pioneers/runtime/wiki) +* *game manual someday :)* + diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index d01e9fb0..00000000 --- a/docs/index.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. Runtime documentation master file, created by - sphinx-quickstart on Mon Jan 11 23:53:21 2021. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to Runtime's documentation! -=================================== - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - -.. automodule:: studentapi - :members: - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml new file mode 100644 index 00000000..9e7e31cf --- /dev/null +++ b/docs/mkdocs.yml @@ -0,0 +1,18 @@ +site_name: Pioneers in Engineering Documentation +site_url: https://example.com/ +site_author: Ian Leung +nav: + # introduction + - Home: 'index.md' + # starting your first robot + - Connecting To Your Robot: 'dawn_quickstart.md' + # kit extension + - Dawn Tutorial: 'dawn_quickstart.md' + # software stuff + - Your First Program: 'first_program.md' + - API Reference: 'api.md' + - Device Get: 'device_get.md' + - Device Set: 'device_set.md' + +theme: readthedocs +# to start this server cd into docs and use `mkdocs serve` \ No newline at end of file