mirror of
https://github.com/pybricks/pybricks-api.git
synced 2026-09-12 01:24:17 +00:00
298 lines
8.3 KiB
Python
298 lines
8.3 KiB
Python
# SPDX-License-Identifier: MIT
|
||
# Copyright (c) 2018-2023 The Pybricks Authors
|
||
|
||
"""Common tools for timing, data logging, and linear algebra."""
|
||
|
||
from __future__ import annotations
|
||
|
||
from typing import TYPE_CHECKING, Any, Optional, Sequence, Tuple, overload, Coroutine
|
||
|
||
if TYPE_CHECKING:
|
||
from ._common import MaybeAwaitable, MaybeAwaitableTuple
|
||
from .parameters import Number
|
||
|
||
|
||
def wait(time: Number) -> MaybeAwaitable:
|
||
"""wait(time)
|
||
|
||
Pauses the user program for a specified amount of time.
|
||
|
||
Arguments:
|
||
time (Number, ms): How long to wait.
|
||
"""
|
||
|
||
|
||
class StopWatch:
|
||
"""A stopwatch to measure time intervals. Similar to the stopwatch
|
||
feature on your phone."""
|
||
|
||
def __init__(self): ...
|
||
|
||
def time(self) -> int:
|
||
"""time() -> int: ms
|
||
|
||
Gets the current time of the stopwatch.
|
||
|
||
Returns:
|
||
Elapsed time.
|
||
"""
|
||
|
||
def pause(self) -> None:
|
||
"""pause()
|
||
|
||
Pauses the stopwatch."""
|
||
|
||
def resume(self) -> None:
|
||
"""resume()
|
||
|
||
Resumes the stopwatch."""
|
||
|
||
def reset(self) -> None:
|
||
"""reset()
|
||
|
||
Resets the stopwatch time to 0.
|
||
|
||
The run state is unaffected:
|
||
|
||
* If it was paused, it stays paused (but now at 0).
|
||
* If it was running, it stays running (but starting again from 0).
|
||
"""
|
||
|
||
|
||
class DataLog:
|
||
"""Create a file and log data."""
|
||
|
||
def __init__(
|
||
self,
|
||
*headers: str,
|
||
name: str = "log",
|
||
timestamp: bool = True,
|
||
extension: str = "csv",
|
||
append: bool = False,
|
||
):
|
||
"""DataLog(*headers, name='log', timestamp=True, extension='csv', append=False)
|
||
|
||
Arguments:
|
||
headers (str, str, ...): Column headers. These are the
|
||
names of the data columns. For example, choose ``'time'`` and
|
||
``'angle'``.
|
||
name (str): Name of the file.
|
||
timestamp (bool): Choose ``True`` to add the date and time to the
|
||
file name. This way, your file has a unique name.
|
||
Choose ``False`` to omit the timestamp.
|
||
extension (str): File extension.
|
||
append (bool): Choose ``True`` to reopen an existing data log file
|
||
and append data to it. Choose ``False`` to clear existing
|
||
data. If the file does not exist yet, an empty file will be
|
||
created either way.
|
||
"""
|
||
|
||
def log(self, *values: Any) -> None:
|
||
"""log(value1, value2, ...)
|
||
|
||
Saves one or more values on a new line in the file.
|
||
|
||
Arguments:
|
||
values (object, object, ...): One or more objects or values.
|
||
"""
|
||
|
||
|
||
class Matrix:
|
||
"""Mathematical representation of a matrix. It supports
|
||
addition (``A + B``), subtraction (``A - B``),
|
||
and matrix multiplication (``A * B``) for matrices of compatible size.
|
||
|
||
It also supports scalar multiplication (``c * A`` or ``A * c``)
|
||
and scalar division (``A / c``).
|
||
|
||
A :class:`.Matrix` object is immutable."""
|
||
|
||
def __add__(self, other) -> Matrix: ...
|
||
|
||
def __iadd__(self, other) -> Matrix: ...
|
||
|
||
def __sub__(self, other) -> Matrix: ...
|
||
|
||
def __isub__(self, other) -> Matrix: ...
|
||
|
||
def __mul__(self, other) -> Matrix: ...
|
||
|
||
def __rmul__(self, other) -> Matrix: ...
|
||
|
||
def __imul__(self, other) -> Matrix: ...
|
||
|
||
def __truediv__(self, other) -> Matrix: ...
|
||
|
||
def __itruediv__(self, other) -> Matrix: ...
|
||
|
||
def __floordiv__(self, other) -> Matrix: ...
|
||
|
||
def __ifloordiv__(self, other) -> Matrix: ...
|
||
|
||
def __init__(self, rows: Sequence[Sequence[float]]):
|
||
"""Matrix(rows)
|
||
|
||
Arguments:
|
||
rows (list): List of rows. Each row is itself a list of numbers.
|
||
|
||
"""
|
||
|
||
@property
|
||
def T(self) -> Matrix: # noqa: N802
|
||
"""Returns a new :class:`.Matrix` that is the transpose of the
|
||
original."""
|
||
|
||
@property
|
||
def shape(self) -> Tuple[int, int]:
|
||
"""Returns a tuple (``m``, ``n``),
|
||
where ``m`` is the number of rows and ``n`` is the number of columns.
|
||
"""
|
||
|
||
|
||
@overload
|
||
def vector(x: float, y: float) -> Matrix:
|
||
"""
|
||
Convenience function to create a :class:`.Matrix` with the shape (``2``, ``1``).
|
||
|
||
Arguments:
|
||
x (float): x-coordinate of the vector.
|
||
y (float): y-coordinate of the vector.
|
||
|
||
Returns:
|
||
A matrix with the shape of a column vector.
|
||
"""
|
||
|
||
|
||
@overload
|
||
def vector(x: float, y: float, z: float) -> Matrix:
|
||
"""
|
||
Convenience function to create a :class:`.Matrix` with the shape (``3``, ``1``).
|
||
|
||
Arguments:
|
||
x (float): x-coordinate of the vector.
|
||
y (float): y-coordinate of the vector.
|
||
z (float): z-coordinate of the vector.
|
||
|
||
Returns:
|
||
A matrix with the shape of a column vector.
|
||
"""
|
||
|
||
|
||
def vector(*args):
|
||
"""
|
||
vector(x, y) -> Matrix
|
||
vector(x, y, z) -> Matrix
|
||
|
||
Convenience function to create a :class:`.Matrix` with the
|
||
shape (``2``, ``1``) or (``3``, ``1``).
|
||
|
||
Arguments:
|
||
x (float): x-coordinate of the vector.
|
||
y (float): y-coordinate of the vector.
|
||
z (float): z-coordinate of the vector (optional).
|
||
|
||
Returns:
|
||
A matrix with the shape of a column vector.
|
||
"""
|
||
|
||
|
||
def cross(a: Matrix, b: Matrix) -> Matrix:
|
||
"""
|
||
cross(a, b) -> Matrix
|
||
|
||
Gets the cross product ``a`` × ``b`` of two vectors.
|
||
|
||
Arguments:
|
||
a (Matrix): A three-dimensional vector.
|
||
b (Matrix): A three-dimensional vector.
|
||
|
||
Returns:
|
||
The cross product, also a three-dimensional vector.
|
||
"""
|
||
|
||
|
||
def read_input_byte(last: bool = False, chr: bool = False) -> Optional[int | str]:
|
||
"""
|
||
read_input_byte() -> int | str | None
|
||
|
||
Reads one byte from standard input without blocking and removes it from the
|
||
input buffer.
|
||
|
||
Arguments:
|
||
last (bool): Choose ``True`` to read the last (most recent) byte in the buffer and discard the rest.
|
||
Choose ``False`` to read only the first (oldest) byte.
|
||
chr (bool): Choose ``True`` to convert the result to a one-character string.
|
||
|
||
Returns:
|
||
The byte that was read, as a numeric value (``0`` to ``255``) or
|
||
string (e.g. ``"B"``). Returns ``None`` if no data is available. If
|
||
``chr=True``, it also return ``None`` if the byte that was read is not
|
||
printable as a character.
|
||
"""
|
||
|
||
|
||
def hub_menu(*symbols: int | str) -> int | str:
|
||
"""
|
||
hub_menu(symbol1, symbol2, ...) -> int | str
|
||
|
||
Shows a menu on the hub display and waits for the user to select an item
|
||
using the buttons. Can be used in your own menu-program that lets you
|
||
choose which of your other programs to run.
|
||
|
||
Note that this is just a convenience function that combines the display,
|
||
buttons, and waits to make a simple menu. This means that it can be used
|
||
anywhere in a program, not just at the start.
|
||
|
||
Arguments:
|
||
symbol1 (int or str): The first symbol to show in the menu.
|
||
symbol2 (int or str): The second symbol, and so on...
|
||
|
||
Returns:
|
||
The selected symbol.
|
||
"""
|
||
|
||
|
||
def multitask(*coroutines: Coroutine, race=False) -> MaybeAwaitableTuple:
|
||
"""
|
||
multitask(coroutine1, coroutine2, ...) -> Tuple
|
||
|
||
Runs multiple coroutines concurrently. This creates a new coroutine that
|
||
can be used like any other, including in another ``multitask`` statement.
|
||
|
||
Arguments:
|
||
coroutines (coroutine, coroutine, ...): One or more coroutines to run
|
||
in parallel.
|
||
race (bool): Choose ``False`` to wait for all coroutines to finish.
|
||
Choose ``True`` to wait for one coroutine to finish and then
|
||
cancel the others, as if it's a "race".
|
||
|
||
Returns:
|
||
Tuple of the return values of each coroutine. Unfinished coroutines
|
||
will have ``None`` as their return value.
|
||
"""
|
||
|
||
|
||
def run_task(coroutine: Coroutine) -> Optional[bool]:
|
||
"""
|
||
run_task(coroutine) -> bool | None
|
||
|
||
Runs a coroutine from start to finish while blocking the rest of the
|
||
program. This is used primarily to run the main coroutine of a program.
|
||
|
||
Calls to this function are not allowed to be nested.
|
||
|
||
Arguments:
|
||
coroutine (coroutine): The main coroutine to run.
|
||
|
||
Returns:
|
||
If no ``coroutine`` is given, this function returns whether the
|
||
run loop is currently active (``True``) or not (``False``).
|
||
"""
|
||
|
||
|
||
# HACK: hide from jedi
|
||
if TYPE_CHECKING:
|
||
del Number
|
||
del MaybeAwaitable
|
||
del MaybeAwaitableTuple
|