Skip to content
This repository has been archived by the owner on Jun 19, 2024. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into refactor/controller
Browse files Browse the repository at this point in the history
  • Loading branch information
Tropix126 committed Mar 10, 2024
2 parents b7ff159 + 3d86c15 commit 0f46832
Show file tree
Hide file tree
Showing 88 changed files with 1,884 additions and 962 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
toolchain: nightly-2024-02-07
override: true

- name: Check
Expand All @@ -33,7 +33,7 @@ jobs:
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
toolchain: nightly-2024-02-07
override: true

- name: Setup | Install Rustfmt
Expand All @@ -57,4 +57,4 @@ jobs:
with:
reporter: 'github-pr-check'
github_token: ${{ secrets.GITHUB_TOKEN }}
clippy_flags: --all-targets --all-features
clippy_flags: --all-targets --all-features
43 changes: 41 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,32 @@ Before releasing:

## [Unreleased]

### Added

### Fixed

### Changed

### Removed

## [0.8.0]

### Added
- Added feedforward motor controllers (#80)
- Lightly document all APIs with missing documentation. (#70)
- Added `Debug`, `Copy`, and `Clone` derives for common structs (#70)

- Screen drawing API. (#81)
- Added screen field to `Peripherals` and `DynamicPeripherals::take_screen` method. (#81)
- Added `AdiSolenoid`, a wrapper over `AdiDigitalOut` for actuating SMC pneumatic solenoids. (#61)
- Added `AdiSwitch`, another `AdiDigitalOut` wrapper that abstracts bumper switches and limit switches. (#61)
- Added `AdiLineTracker` for abstracting the EDR line tracker sensor.

### Fixed

- Fix error handling and error type variats in ADI bindings
- Fix `AsynRobot` only running opcontrol
- Properly handle `EADDRINUSE` return for smart port errors (**Breaking Change**) (#97)

### Changed

- Re-exported printing macros from `pros::io`. (#82)
Expand All @@ -40,6 +56,26 @@ Before releasing:
- The VEXOS target has been updated to improve file size and floating point operation speed. (#81)
- `Peripherals::new()` is no longer const (**Breaking Change) (#81)
- Updated panic handler to print to the brain display as well as over serial (#81)
- Refactors digital and analog ADI input/output. (**Breaking Change**) (#61)
- Adds LogicLevel rather than bools for controlling digital devices.
- Adds 0-5V voltage getters and setters for analog ADI.
- Changed analog getters and setters to use `u16` data.
- Changed `AdiPotentiometer` to return degrees rather than tenth degrees (**Breaking Change**) (#61).
- Renamed `AdiPotentiometer::value` to `AdiPotentiometer::angle`.
- Refactors `AdiMotor` to match the smart motor APIs, having output/raw output getters/setters.
- Renamed `AdiUltrasonic::value` to `AdiUltrasonic::distance` (**Breaking Change**) (#61).
- Renamed `AdiEncoder::value` to `AdiEncoder::position` (**Breaking Change**) (#61).
- Repurposed `AdiAnalogOut` as `AdiPwmOut` to correct match port output. (**Breaking Change**) (#90).
- Moved most device-related constants into their associated struct `impl` (**Breaking Change**) (#98).
- Renamed IMU_RESET_TIMEOUT to `InertialSensor::CALIBRATION_TIMEOUT` (**Breaking Change**) (#98).
- Repurposed the `pros` crate as a metapackage without any code of its own. (**Breaking Change**) (#86)
- Split the pros-rs into several small subcrates. (**Breaking Change**) (#86)
- `pros-async` with the async executor and robot trait.
- `pros-devices` for device bindings.
- `pros-sync` for the sync robot trait.
- `pros-core` with basic abstractions over `pros-sys` needed to compile a program to the brain.
- `pros-math` with commonly used controllers and other mathematical models.
- `pros-panic` for the panic handler implementation.

### Removed

Expand All @@ -48,6 +84,7 @@ Before releasing:
- Re-exported printing macros from `pros::io`. (#82)
- Applied several lints to improve code quality. (#70)
- Removed the confusingly named `write`, `ewrite`, `writeln`, and `ewriteln` macros. (**Breaking Change**) (#82)
- Removed AdiDigitalIn::new_press, instead swapping it for AdiSwitch::was_pressed. (**Breaking Change**) (#61)

## [0.7.0]

Expand All @@ -66,6 +103,7 @@ Before releasing:
- All ADI device bindings (#55)
- `LocalKey` now has `Cell`/`RefCell`-specific methods for setting and taking values. (#42)
- `Peripherals` and `DynamicPeripherals` structs to ensure that you have only registered one device on a given smart or ADI port. (#53)
- Support for ADI Expander modules with `AdiExpander`. (#63)

### Fixed

Expand Down Expand Up @@ -150,8 +188,9 @@ Before releasing:

### Removed

[unreleased]: https://github.com/pros-rs/pros-rs/compare/v0.7.0...HEAD
[unreleased]: https://github.com/pros-rs/pros-rs/compare/v0.8.0...HEAD
[0.4.0]: https://github.com/pros-rs/pros-rs/releases/tag/v0.4.0
[0.5.0]: https://github.com/pros-rs/pros-rs/compare/v0.4.0...v0.5.0
[0.6.0]: https://github.com/pros-rs/pros-rs/compare/v0.5.0...v0.6.0
[0.7.0]: https://github.com/pros-rs/pros-rs/compare/v0.6.0...v0.7.0
[0.8.0]: https://github.com/pros-rs/pros-rs/compare/v0.7.0...v0.8.0
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
[workspace]
members = ["packages/*"]
resolver = "2"

[workspace.lints.rust]
rust_2018_idioms = "warn"
missing_docs = "warn"
unsafe_op_in_unsafe_fn = "warn"

[workspace.lints.clippy]
missing_const_for_fn = "warn"
29 changes: 29 additions & 0 deletions packages/pros-async/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[package]
name = "pros-async"
version = "0.1.0"
edition = "2021"
license = "MIT"
description = "A simple async executor for pros-rs"
keywords = ["PROS", "Robotics", "bindings", "async", "vex", "v5"]
categories = [
"no-std",
"science::robotics",
"Asynchronous"
]
repository = "https://github.com/gavin-niederman/pros-rs"
authors = [
"pros-rs",
"Gavin Niederman <[email protected]>",
"doinkythederp <[email protected]>",
]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
async-task = { version = "4.5.0", default-features = false }
pros-core = { version = "0.1.0", path = "../pros-core" }
waker-fn = "1.1.1"
pros-sys = { version = "0.7.0", path = "../pros-sys" }

[lints]
workspace = true
6 changes: 6 additions & 0 deletions packages/pros-async/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# pros-async

Tiny async runtime and robot traits for `pros-rs`.
The async executor supports spawning tasks and blocking on futures.
It has a reactor to improve the performance of some futures.
FreeRTOS tasks can still be used, but it is recommended to use only async tasks for performance.
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ use core::{
};

use async_task::{Runnable, Task};
use pros_core::{os_task_local, task::delay};
use waker_fn::waker_fn;

use super::reactor::Reactor;
use crate::{os_task_local, task::delay};

os_task_local! {
pub(crate) static EXECUTOR: Executor = Executor::new();
Expand Down
203 changes: 203 additions & 0 deletions packages/pros-async/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
//! Tiny async runtime and robot traits for `pros-rs`.
//! The async executor supports spawning tasks and blocking on futures.
//! It has a reactor to improve the performance of some futures.
//! It is recommended to use the `AsyncRobot` trait to run robot code.
//! FreeRTOS tasks can still be used, but it is recommended to use only async tasks for performance.
#![no_std]
#![feature(negative_impls)]

extern crate alloc;

use core::{future::Future, task::Poll};

use async_task::Task;
use executor::EXECUTOR;
use pros_core::error::Result;

mod executor;
mod reactor;

/// Runs a future in the background without having to await it
/// To get the the return value you can await a task.
pub fn spawn<T>(future: impl Future<Output = T> + 'static) -> Task<T> {
executor::EXECUTOR.with(|e| e.spawn(future))
}

/// Blocks the current task untill a return value can be extracted from the provided future.
/// Does not poll all futures to completion.
pub fn block_on<F: Future + 'static>(future: F) -> F::Output {
executor::EXECUTOR.with(|e| e.block_on(spawn(future)))
}

/// A future that will complete after the given duration.
/// Sleep futures that are closer to completion are prioritized to improve accuracy.
#[derive(Debug)]
pub struct SleepFuture {
target_millis: u32,
}
impl Future for SleepFuture {
type Output = ();

fn poll(
self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>,
) -> core::task::Poll<Self::Output> {
if self.target_millis < unsafe { pros_sys::millis() } {
Poll::Ready(())
} else {
EXECUTOR.with(|e| {
e.reactor
.borrow_mut()
.sleepers
.push(cx.waker().clone(), self.target_millis)
});
Poll::Pending
}
}
}

/// Returns a future that will complete after the given duration.
pub fn sleep(duration: core::time::Duration) -> SleepFuture {
SleepFuture {
target_millis: unsafe { pros_sys::millis() + duration.as_millis() as u32 },
}
}

/// A trait for robot code that spins up the pros-rs async executor.
/// This is the preferred trait to run robot code.
pub trait AsyncRobot {
/// Runs during the operator control period.
/// This function may be called more than once.
/// For that reason, do not use `Peripherals::take`in this function.
fn opcontrol(&mut self) -> impl Future<Output = Result> {
async { Ok(()) }
}
/// Runs during the autonomous period.
fn auto(&mut self) -> impl Future<Output = Result> {
async { Ok(()) }
}
/// Runs continuously during the disabled period.
fn disabled(&mut self) -> impl Future<Output = Result> {
async { Ok(()) }
}
/// Runs once when the competition system is initialized.
fn comp_init(&mut self) -> impl Future<Output = Result> {
async { Ok(()) }
}
}

#[doc(hidden)]
#[macro_export]
macro_rules! __gen_async_exports {
($rbt:ty) => {
pub static mut ROBOT: Option<$rbt> = None;

#[doc(hidden)]
#[no_mangle]
extern "C" fn opcontrol() {
$crate::block_on(<$rbt as $crate::AsyncRobot>::opcontrol(unsafe {
ROBOT
.as_mut()
.expect("Expected initialize to run before opcontrol")
}))
.unwrap();
}

#[doc(hidden)]
#[no_mangle]
extern "C" fn autonomous() {
$crate::block_on(<$rbt as $crate::AsyncRobot>::auto(unsafe {
ROBOT
.as_mut()
.expect("Expected initialize to run before auto")
}))
.unwrap();
}

#[doc(hidden)]
#[no_mangle]
extern "C" fn disabled() {
$crate::block_on(<$rbt as $crate::AsyncRobot>::disabled(unsafe {
ROBOT
.as_mut()
.expect("Expected initialize to run before disabled")
}))
.unwrap();
}

#[doc(hidden)]
#[no_mangle]
extern "C" fn competition_initialize() {
$crate::block_on(<$rbt as $crate::AsyncRobot>::comp_init(unsafe {
ROBOT
.as_mut()
.expect("Expected initialize to run before comp_init")
}))
.unwrap();
}
};
}

/// Allows your async robot code to be executed by the pros kernel.
/// If your robot struct implements Default then you can just supply this macro with its type.
/// If not, you can supply an expression that returns your robot type to initialize your robot struct.
/// The code that runs to create your robot struct will run in the initialize function in PROS.
///
/// Example of using the macro with a struct that implements Default:
/// ```rust
/// use pros::prelude::*;
/// #[derive(Default)]
/// struct ExampleRobot;
/// #[async_trait]
/// impl AsyncRobot for ExampleRobot {
/// asnyc fn opcontrol(&mut self) -> pros::Result {
/// println!("Hello, world!");
/// Ok(())
/// }
/// }
/// async_robot!(ExampleRobot);
/// ```
///
/// Example of using the macro with a struct that does not implement Default:
/// ```rust
/// use pros::prelude::*;
/// struct ExampleRobot {
/// x: i32,
/// }
/// #[async_trait]
/// impl AsyncRobot for ExampleRobot {
/// async fn opcontrol(&mut self) -> pros::Result {
/// println!("Hello, world! {}", self.x);
/// Ok(())
/// }
/// }
/// impl ExampleRobot {
/// pub fn new() -> Self {
/// Self { x: 5 }
/// }
/// }
/// async_robot!(ExampleRobot, ExampleRobot::new());
#[macro_export]
macro_rules! async_robot {
($rbt:ty) => {
$crate::__gen_async_exports!($rbt);

#[no_mangle]
extern "C" fn initialize() {
unsafe {
ROBOT = Some(Default::default());
}
}
};
($rbt:ty, $init:expr) => {
$crate::__gen_async_exports!($rbt);

#[no_mangle]
extern "C" fn initialize() {
unsafe {
ROBOT = Some($init);
}
}
};
}
Loading

0 comments on commit 0f46832

Please sign in to comment.