mirror of
https://github.com/pybricks/pybricks-api.git
synced 2026-09-13 10:04:45 +00:00
Compare commits
31
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2278c7bcda | ||
|
|
4da3618428 | ||
|
|
5bc11b185d | ||
|
|
be9f99d41b | ||
|
|
870aae83c0 | ||
|
|
9cde749e8a | ||
|
|
8bca5eb6e4 | ||
|
|
95a12a7386 | ||
|
|
d6c78f1f39 | ||
|
|
98f2bb27fe | ||
|
|
fdbd078388 | ||
|
|
ccd2b46819 | ||
|
|
c0cb05dd74 | ||
|
|
b183e1420a | ||
|
|
b311c54261 | ||
|
|
bb37b94f5e | ||
|
|
5b25606afa | ||
|
|
8172d11ef6 | ||
|
|
c415296b71 | ||
|
|
e4650cb1c9 | ||
|
|
91154a394c | ||
|
|
3c36010c04 | ||
|
|
a553df3b03 | ||
|
|
dbd1cc8dc9 | ||
|
|
b40c3989aa | ||
|
|
13612bdb1a | ||
|
|
031e905e12 | ||
|
|
428bca79ab | ||
|
|
0e8b6cfd97 | ||
|
|
eea8ff0924 | ||
|
|
8c673ab280 |
@@ -6,7 +6,7 @@ name: Build Python package and docs
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags-ignore:
|
tags-ignore:
|
||||||
- "*"
|
- "@pybricks/*"
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- doc/**
|
- doc/**
|
||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
python-version: [3.8, 3.9]
|
python-version: [3.8, 3.9]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
|||||||
@@ -7,17 +7,17 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish_ide_docs:
|
publish_ide_docs:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Ubuntu packages
|
- name: Ubuntu packages
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y dvisvgm preview-latex-style texlive texlive-fonts-extra texlive-latex-extra
|
sudo apt-get install -y dvisvgm preview-latex-style texlive texlive-fonts-extra texlive-latex-extra
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Set up Python 3.8
|
- name: Set up Python 3.8
|
||||||
uses: actions/setup-python@v1
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: 3.8
|
python-version: 3.8
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
poetry run python -m pip install --upgrade pip
|
poetry run python -m pip install --upgrade pip
|
||||||
poetry run python -m pip install --upgrade setuptools
|
poetry run python -m pip install --upgrade setuptools
|
||||||
poetry install
|
poetry install
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '14.x'
|
node-version: '14.x'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ jobs:
|
|||||||
publish_jedi:
|
publish_jedi:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
# Setup .npmrc file to publish to npm
|
# Setup .npmrc file to publish to npm
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -4,6 +4,25 @@
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## 3.3.0b4 - 2023-04-21
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Documented `integral_deadzone` in `Control.pid()`.
|
||||||
|
- Documented `Motor.model`. This can be used to view the estimated motor
|
||||||
|
state and change its settings.
|
||||||
|
- Added `rotation`, `orientation`, `ready`, `stationary` and `settings` methods
|
||||||
|
to `IMU` class.
|
||||||
|
- Added `GyroDriveBase` class to `pybricks.robotics`.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Change implementation status of `IMU.heading` and `IMU.reset_heading`. They
|
||||||
|
are now implemented, with some limitations as noted in a note box.
|
||||||
|
- Moved `Matrix` and `vector` from `pybricks.geometry` to `pybricks.tools`.
|
||||||
|
- Moved `Axis` from `pybricks.geometry` to `pybricks.parameters`.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Removed `pybricks.geometry` module.
|
||||||
|
|
||||||
## 3.2.0 - 2022-12-20
|
## 3.2.0 - 2022-12-20
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ used to generate the `official documentation`_.
|
|||||||
See the `contributor's guide <CONTRIBUTING.md>`_ for acceptable changes and
|
See the `contributor's guide <CONTRIBUTING.md>`_ for acceptable changes and
|
||||||
instructions to build the documentation locally.
|
instructions to build the documentation locally.
|
||||||
|
|
||||||
|
You can use the API stubs in this repository for syntax highlighting and code
|
||||||
|
completion when programming the EV3 with VS Code. To enable, remove the
|
||||||
|
``"python.languageServer"="None"`` line in the ``.vscode/settings.json`` file
|
||||||
|
generated by the *LEGO® MINDSTORMS® EV3 MicroPython* extension.
|
||||||
|
|
||||||
For general discussion, please visit the `support`_ issue tracker.
|
For general discussion, please visit the `support`_ issue tracker.
|
||||||
|
|
||||||
.. _Pybricks package: pybricks
|
.. _Pybricks package: pybricks
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ FEATURES_SMALL = set()
|
|||||||
|
|
||||||
# Medium feature set.
|
# Medium feature set.
|
||||||
FEATURES_MEDIUM = FEATURES_SMALL | {
|
FEATURES_MEDIUM = FEATURES_SMALL | {
|
||||||
"pybricks-geometry",
|
|
||||||
"pybricks-common-control",
|
"pybricks-common-control",
|
||||||
"pybricks-iodevices",
|
"pybricks-iodevices",
|
||||||
"stm32-extra",
|
"stm32-extra",
|
||||||
@@ -24,10 +23,10 @@ FEATURES_LARGE = FEATURES_MEDIUM | set()
|
|||||||
HUB_FEATURES = {
|
HUB_FEATURES = {
|
||||||
"movehub": {"movehub"} | FEATURES_SMALL,
|
"movehub": {"movehub"} | FEATURES_SMALL,
|
||||||
"cityhub": {"cityhub"} | FEATURES_MEDIUM,
|
"cityhub": {"cityhub"} | FEATURES_MEDIUM,
|
||||||
"technichub": {"technichub"} | FEATURES_MEDIUM,
|
"technichub": {"technichub", "gyro"} | FEATURES_MEDIUM,
|
||||||
"primehub": {"primehub", "inventorhub", "light-matrix"} | FEATURES_LARGE,
|
"primehub": {"primehub", "inventorhub", "light-matrix", "gyro"} | FEATURES_LARGE,
|
||||||
"inventorhub": {"primehub", "inventorhub", "light-matrix"} | FEATURES_LARGE,
|
"inventorhub": {"primehub", "inventorhub", "light-matrix", "gyro"} | FEATURES_LARGE,
|
||||||
"essentialhub": {"essentialhub"} | FEATURES_LARGE,
|
"essentialhub": {"essentialhub", "gyro"} | FEATURES_LARGE,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1169
-6
File diff suppressed because it is too large
Load Diff
@@ -20,12 +20,12 @@ Motors
|
|||||||
|
|
||||||
.. rubric:: Measuring
|
.. rubric:: Measuring
|
||||||
|
|
||||||
.. automethod:: pybricks.ev3devices.Motor.speed
|
|
||||||
|
|
||||||
.. automethod:: pybricks.ev3devices.Motor.angle
|
.. automethod:: pybricks.ev3devices.Motor.angle
|
||||||
|
|
||||||
.. automethod:: pybricks.ev3devices.Motor.reset_angle
|
.. automethod:: pybricks.ev3devices.Motor.reset_angle
|
||||||
|
|
||||||
|
.. automethod:: pybricks.ev3devices.Motor.speed
|
||||||
|
|
||||||
.. automethod:: pybricks.ev3devices.Motor.load
|
.. automethod:: pybricks.ev3devices.Motor.load
|
||||||
|
|
||||||
.. automethod:: pybricks.ev3devices.Motor.stalled
|
.. automethod:: pybricks.ev3devices.Motor.stalled
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
.. pybricks-requirements:: stm32-float
|
|
||||||
|
|
||||||
:mod:`geometry <pybricks.geometry>` -- Geometry and algebra
|
|
||||||
============================================================
|
|
||||||
|
|
||||||
.. module:: pybricks.geometry
|
|
||||||
|
|
||||||
.. autoclass:: pybricks.geometry.Matrix
|
|
||||||
:no-members:
|
|
||||||
|
|
||||||
.. autoattribute:: pybricks.geometry::Matrix.T
|
|
||||||
|
|
||||||
.. autoattribute:: pybricks.geometry::Matrix.shape
|
|
||||||
|
|
||||||
.. autofunction:: pybricks.geometry.vector
|
|
||||||
|
|
||||||
.. autoclass:: pybricks.geometry.Axis
|
|
||||||
:no-members:
|
|
||||||
|
|
||||||
.. _robotframe:
|
|
||||||
|
|
||||||
Reference frames
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
The Pybricks module and this documentation use the following conventions:
|
|
||||||
|
|
||||||
- X: Positive means forward. Negative means backward.
|
|
||||||
- Y: Positive means to the left. Negative means to the right.
|
|
||||||
- Z: Positive means upward. Negative means downward.
|
|
||||||
|
|
||||||
To make sure that all hub measurements (such as acceleration) have the correct
|
|
||||||
value and sign, you can specify how the hub is mounted in your creation. This
|
|
||||||
adjust the measurements so that it is easy to see how your *robot* is moving,
|
|
||||||
rather than how the *hub* is moving.
|
|
||||||
|
|
||||||
For example, the hub may be mounted upside down in your design. If you
|
|
||||||
configure the settings as shown in :numref:`fig_imuexamples`, the hub
|
|
||||||
measurements will be adjusted accordingly. This way, a positive acceleration
|
|
||||||
value in the X direction means that your *robot* accelerates forward, even
|
|
||||||
though the *hub* accelerates backward.
|
|
||||||
|
|
||||||
.. _fig_imuexamples:
|
|
||||||
|
|
||||||
.. figure:: ../main/diagrams/imuexamples.png
|
|
||||||
:width: 100 %
|
|
||||||
|
|
||||||
How to configure the ``top_side`` and ``front_side`` settings for three
|
|
||||||
different robot designs. The same technique can be applied to other hubs
|
|
||||||
and other creations, by noting which way the top and
|
|
||||||
front :class:`Side <Side>` of the hub are pointing. The example
|
|
||||||
on the left is the default configuration.
|
|
||||||
@@ -25,6 +25,10 @@ Essential Hub
|
|||||||
|
|
||||||
.. rubric:: Using the IMU
|
.. rubric:: Using the IMU
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::EssentialHub.imu.ready
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::EssentialHub.imu.stationary
|
||||||
|
|
||||||
.. automethod:: pybricks.hubs::EssentialHub.imu.up
|
.. automethod:: pybricks.hubs::EssentialHub.imu.up
|
||||||
|
|
||||||
.. automethod:: pybricks.hubs::EssentialHub.imu.tilt
|
.. automethod:: pybricks.hubs::EssentialHub.imu.tilt
|
||||||
@@ -37,6 +41,12 @@ Essential Hub
|
|||||||
|
|
||||||
.. automethod:: pybricks.hubs::EssentialHub.imu.reset_heading
|
.. automethod:: pybricks.hubs::EssentialHub.imu.reset_heading
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::EssentialHub.imu.rotation
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::EssentialHub.imu.orientation
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::EssentialHub.imu.settings
|
||||||
|
|
||||||
.. rubric:: Using the battery
|
.. rubric:: Using the battery
|
||||||
|
|
||||||
.. automethod:: pybricks.hubs::EssentialHub.battery.voltage
|
.. automethod:: pybricks.hubs::EssentialHub.battery.voltage
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ Prime Hub / Inventor Hub
|
|||||||
|
|
||||||
.. rubric:: Using the IMU
|
.. rubric:: Using the IMU
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::PrimeHub.imu.ready
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::PrimeHub.imu.stationary
|
||||||
|
|
||||||
.. automethod:: pybricks.hubs::PrimeHub.imu.up
|
.. automethod:: pybricks.hubs::PrimeHub.imu.up
|
||||||
|
|
||||||
.. automethod:: pybricks.hubs::PrimeHub.imu.tilt
|
.. automethod:: pybricks.hubs::PrimeHub.imu.tilt
|
||||||
@@ -71,6 +75,12 @@ Prime Hub / Inventor Hub
|
|||||||
|
|
||||||
.. automethod:: pybricks.hubs::PrimeHub.imu.reset_heading
|
.. automethod:: pybricks.hubs::PrimeHub.imu.reset_heading
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::PrimeHub.imu.rotation
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::PrimeHub.imu.orientation
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::PrimeHub.imu.settings
|
||||||
|
|
||||||
.. rubric:: Using the speaker
|
.. rubric:: Using the speaker
|
||||||
|
|
||||||
.. automethod:: pybricks.hubs::PrimeHub.speaker.volume
|
.. automethod:: pybricks.hubs::PrimeHub.speaker.volume
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ Technic Hub
|
|||||||
|
|
||||||
.. rubric:: Using the IMU
|
.. rubric:: Using the IMU
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::TechnicHub.imu.ready
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::TechnicHub.imu.stationary
|
||||||
|
|
||||||
.. automethod:: pybricks.hubs::TechnicHub.imu.up
|
.. automethod:: pybricks.hubs::TechnicHub.imu.up
|
||||||
|
|
||||||
.. automethod:: pybricks.hubs::TechnicHub.imu.tilt
|
.. automethod:: pybricks.hubs::TechnicHub.imu.tilt
|
||||||
@@ -33,6 +37,12 @@ Technic Hub
|
|||||||
|
|
||||||
.. automethod:: pybricks.hubs::TechnicHub.imu.reset_heading
|
.. automethod:: pybricks.hubs::TechnicHub.imu.reset_heading
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::TechnicHub.imu.rotation
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::TechnicHub.imu.orientation
|
||||||
|
|
||||||
|
.. automethod:: pybricks.hubs::TechnicHub.imu.settings
|
||||||
|
|
||||||
.. rubric:: Using the battery
|
.. rubric:: Using the battery
|
||||||
|
|
||||||
.. automethod:: pybricks.hubs::TechnicHub.battery.voltage
|
.. automethod:: pybricks.hubs::TechnicHub.battery.voltage
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ above to reveal this menu.
|
|||||||
parameters/index
|
parameters/index
|
||||||
tools/index
|
tools/index
|
||||||
robotics
|
robotics
|
||||||
geometry
|
|
||||||
signaltypes
|
signaltypes
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
.. pybricks-requirements:: stm32-float
|
||||||
|
|
||||||
|
Axis
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. autoclass:: pybricks.parameters.Axis
|
||||||
|
:no-members:
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
:hidden:
|
:hidden:
|
||||||
|
|
||||||
|
axis
|
||||||
button
|
button
|
||||||
color
|
color
|
||||||
direction
|
direction
|
||||||
@@ -18,6 +19,8 @@
|
|||||||
side
|
side
|
||||||
stop
|
stop
|
||||||
|
|
||||||
|
.. pybricks-classlink:: Axis
|
||||||
|
|
||||||
.. pybricks-classlink:: Button
|
.. pybricks-classlink:: Button
|
||||||
|
|
||||||
.. pybricks-classlink:: Color
|
.. pybricks-classlink:: Color
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ Motors with rotation sensors
|
|||||||
|
|
||||||
.. rubric:: Measuring
|
.. rubric:: Measuring
|
||||||
|
|
||||||
.. automethod:: pybricks.pupdevices.Motor.speed
|
|
||||||
|
|
||||||
.. automethod:: pybricks.pupdevices.Motor.angle
|
.. automethod:: pybricks.pupdevices.Motor.angle
|
||||||
|
|
||||||
.. automethod:: pybricks.pupdevices.Motor.reset_angle
|
.. automethod:: pybricks.pupdevices.Motor.reset_angle
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices.Motor.speed
|
||||||
|
|
||||||
.. automethod:: pybricks.pupdevices.Motor.load
|
.. automethod:: pybricks.pupdevices.Motor.load
|
||||||
|
|
||||||
.. automethod:: pybricks.pupdevices.Motor.stalled
|
.. automethod:: pybricks.pupdevices.Motor.stalled
|
||||||
@@ -93,6 +93,14 @@ Motors with rotation sensors
|
|||||||
The :meth:`done`, :meth:`stalled` and :meth:`load` methods have been
|
The :meth:`done`, :meth:`stalled` and :meth:`load` methods have been
|
||||||
moved.
|
moved.
|
||||||
|
|
||||||
|
.. pybricks-requirements:: pybricks-common-control
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices.Motor.model.state
|
||||||
|
|
||||||
|
.. pybricks-requirements:: pybricks-common-control
|
||||||
|
|
||||||
|
.. automethod:: pybricks.pupdevices.Motor.model.settings
|
||||||
|
|
||||||
Initialization examples
|
Initialization examples
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|||||||
+37
-5
@@ -1,11 +1,10 @@
|
|||||||
.. pybricks-requirements::
|
|
||||||
|
|
||||||
:mod:`robotics <pybricks.robotics>` -- Robotics and drive bases
|
:mod:`robotics <pybricks.robotics>` -- Robotics and drive bases
|
||||||
===============================================================
|
===============================================================
|
||||||
|
|
||||||
.. automodule:: pybricks.robotics
|
.. automodule:: pybricks.robotics
|
||||||
:no-members:
|
:no-members:
|
||||||
|
|
||||||
|
.. pybricks-requirements::
|
||||||
|
|
||||||
.. autoclass:: pybricks.robotics.DriveBase
|
.. autoclass:: pybricks.robotics.DriveBase
|
||||||
:no-members:
|
:no-members:
|
||||||
@@ -103,9 +102,6 @@
|
|||||||
the default speed and acceleration for straight maneuvers and turns.
|
the default speed and acceleration for straight maneuvers and turns.
|
||||||
Use the following attributes to adjust more advanced control settings.
|
Use the following attributes to adjust more advanced control settings.
|
||||||
|
|
||||||
You can only change the settings while the robot is stopped. This is
|
|
||||||
either before you begin driving or after you call :meth:`.stop`.
|
|
||||||
|
|
||||||
.. autoattribute:: pybricks.robotics.DriveBase.distance_control
|
.. autoattribute:: pybricks.robotics.DriveBase.distance_control
|
||||||
:annotation:
|
:annotation:
|
||||||
|
|
||||||
@@ -116,11 +112,47 @@
|
|||||||
|
|
||||||
The :meth:`done` and :meth:`stalled` methods have been moved.
|
The :meth:`done` and :meth:`stalled` methods have been moved.
|
||||||
|
|
||||||
|
|
||||||
|
.. pybricks-requirements:: gyro
|
||||||
|
|
||||||
|
.. class:: GyroDriveBase
|
||||||
|
|
||||||
|
This class works just like the :class:`DriveBase`, but it uses the hub's
|
||||||
|
built-in gyroscope to drive straight and turn more accurately.
|
||||||
|
|
||||||
|
If your hub is not mounted flat in your robot, make sure to specify
|
||||||
|
the ``top_side`` and ``front_side`` parameters when you initialize the
|
||||||
|
:class:`PrimeHub() <pybricks.hubs.PrimeHub>`,
|
||||||
|
:class:`InventorHub() <pybricks.hubs.PrimeHub>`,
|
||||||
|
:class:`EssentialHub() <pybricks.hubs.EssentialHub>`, or
|
||||||
|
:class:`TechnicHub() <pybricks.hubs.TechnicHub>`. This way your robot
|
||||||
|
knows which rotation to measure when turning.
|
||||||
|
|
||||||
|
The gyro in each hub is a bit different, which can cause it to be a few
|
||||||
|
degrees off for big turns, or many small turns in the same
|
||||||
|
direction. For example, you may need to use
|
||||||
|
:meth:`turn(357) <pybricks.robotics.DriveBase.turn>` or
|
||||||
|
:meth:`turn(362) <pybricks.robotics.DriveBase.turn>`
|
||||||
|
on your robot to make a full turn.
|
||||||
|
|
||||||
|
By default, this class tries to maintain the robot's position after a move
|
||||||
|
completes. This means the wheels will spin if you pick the robot up, in an
|
||||||
|
effort to maintain its heading angle. To avoid this, you can choose
|
||||||
|
``then=Stop.COAST`` in your last
|
||||||
|
:meth:`straight <pybricks.robotics.DriveBase.straight>`,
|
||||||
|
:meth:`turn <pybricks.robotics.DriveBase.turn>`, or
|
||||||
|
:meth:`curve <pybricks.robotics.DriveBase.curve>` command.
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Driving straight and turning in place
|
Driving straight and turning in place
|
||||||
**********************************************
|
**********************************************
|
||||||
|
|
||||||
|
The following program shows the basics of driving and turning.
|
||||||
|
|
||||||
|
To use the built-in gyro, just replace the two occurences of
|
||||||
|
:class:`DriveBase` with :class:`GyroDriveBase`.
|
||||||
|
|
||||||
.. literalinclude::
|
.. literalinclude::
|
||||||
../../examples/pup/robotics/drivebase_basics.py
|
../../examples/pup/robotics/drivebase_basics.py
|
||||||
|
|||||||
@@ -260,3 +260,36 @@ Fahrenheit (°F) or Kelvin (K), you can use the following conversion formulas:
|
|||||||
hue: deg
|
hue: deg
|
||||||
--------------
|
--------------
|
||||||
Hue of a color (0-359 degrees).
|
Hue of a color (0-359 degrees).
|
||||||
|
|
||||||
|
.. _robotframe:
|
||||||
|
|
||||||
|
Reference frames
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The Pybricks module and this documentation use the following conventions:
|
||||||
|
|
||||||
|
- X: Positive means forward. Negative means backward.
|
||||||
|
- Y: Positive means to the left. Negative means to the right.
|
||||||
|
- Z: Positive means upward. Negative means downward.
|
||||||
|
|
||||||
|
To make sure that all hub measurements (such as acceleration) have the correct
|
||||||
|
value and sign, you can specify how the hub is mounted in your creation. This
|
||||||
|
adjust the measurements so that it is easy to see how your *robot* is moving,
|
||||||
|
rather than how the *hub* is moving.
|
||||||
|
|
||||||
|
For example, the hub may be mounted upside down in your design. If you
|
||||||
|
configure the settings as shown in :numref:`fig_imuexamples`, the hub
|
||||||
|
measurements will be adjusted accordingly. This way, a positive acceleration
|
||||||
|
value in the X direction means that your *robot* accelerates forward, even
|
||||||
|
though the *hub* accelerates backward.
|
||||||
|
|
||||||
|
.. _fig_imuexamples:
|
||||||
|
|
||||||
|
.. figure:: ../main/diagrams/imuexamples.png
|
||||||
|
:width: 100 %
|
||||||
|
|
||||||
|
How to configure the ``top_side`` and ``front_side`` settings for three
|
||||||
|
different robot designs. The same technique can be applied to other hubs
|
||||||
|
and other creations, by noting which way the top and
|
||||||
|
front :class:`Side <Side>` of the hub are pointing. The example
|
||||||
|
on the left is the default configuration.
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
.. pybricks-requirements::
|
.. pybricks-requirements::
|
||||||
|
|
||||||
:mod:`tools <pybricks.tools>` -- Timing tools
|
:mod:`tools <pybricks.tools>` -- General purpose tools
|
||||||
========================================================
|
========================================================
|
||||||
|
|
||||||
.. automodule:: pybricks.tools
|
.. automodule:: pybricks.tools
|
||||||
:no-members:
|
:no-members:
|
||||||
|
|
||||||
|
Timing tools
|
||||||
|
---------------
|
||||||
|
|
||||||
.. autofunction:: wait
|
.. autofunction:: wait
|
||||||
|
|
||||||
.. autoclass:: pybricks.tools.StopWatch
|
.. autoclass:: pybricks.tools.StopWatch
|
||||||
@@ -19,3 +22,24 @@
|
|||||||
|
|
||||||
.. automethod:: pybricks.tools.StopWatch.reset
|
.. automethod:: pybricks.tools.StopWatch.reset
|
||||||
|
|
||||||
|
Linear algebra tools
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
.. versionchanged:: 3.3
|
||||||
|
|
||||||
|
These tools were previously located in the ``pybricks.geometry`` module.
|
||||||
|
|
||||||
|
.. pybricks-requirements:: stm32-float
|
||||||
|
|
||||||
|
.. autoclass:: pybricks.tools.Matrix
|
||||||
|
:no-members:
|
||||||
|
|
||||||
|
.. autoattribute:: pybricks.tools::Matrix.T
|
||||||
|
|
||||||
|
.. autoattribute:: pybricks.tools::Matrix.shape
|
||||||
|
|
||||||
|
.. pybricks-requirements:: stm32-float
|
||||||
|
|
||||||
|
.. autofunction:: pybricks.tools.vector
|
||||||
|
|
||||||
|
.. autofunction:: pybricks.tools.cross
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from pybricks.messaging import BluetoothMailboxServer, TextMailbox
|
||||||
|
|
||||||
|
# This demo makes your PC talk to an EV3 over Bluetooth.
|
||||||
|
#
|
||||||
|
# This is identical to the EV3 server example in ../bluetooth_server
|
||||||
|
#
|
||||||
|
# The only difference is that it runs in Python3 on your computer, thanks to
|
||||||
|
# the Python3 implementation of the messaging module that is included here.
|
||||||
|
# As far as the EV3 is concerned, it thinks it just talks to an EV3 client.
|
||||||
|
#
|
||||||
|
# So, the EV3 client example needs no further modifications. The connection
|
||||||
|
# procedure is also the same as documented in the messaging module docs:
|
||||||
|
# https://docs.pybricks.com/en/latest/messaging.html
|
||||||
|
|
||||||
|
server = BluetoothMailboxServer()
|
||||||
|
mbox = TextMailbox("greeting", server)
|
||||||
|
|
||||||
|
# The server must be started before the client!
|
||||||
|
print("waiting for connection...")
|
||||||
|
server.wait_for_connection()
|
||||||
|
print("connected!")
|
||||||
|
|
||||||
|
# In this program, the server waits for the client to send the first message
|
||||||
|
# and then sends a reply.
|
||||||
|
mbox.wait()
|
||||||
|
print(mbox.read())
|
||||||
|
mbox.send("hello to you!")
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
# Copyright (C) 2020 The Pybricks Authors
|
# Copyright (C) 2020,2023 The Pybricks Authors
|
||||||
|
|
||||||
"""
|
"""
|
||||||
:class:`RFCOMMServer` can be used to communicate with other Bluetooth RFCOMM
|
:class:`RFCOMMServer` can be used to communicate with other Bluetooth RFCOMM
|
||||||
@@ -10,29 +10,13 @@ remain a strict subset of that implementation when it comes to low-level
|
|||||||
implementation details.
|
implementation details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from bluetooth import BluetoothSocket, RFCOMM
|
from socket import socket, AF_BLUETOOTH, BTPROTO_RFCOMM, SOCK_STREAM
|
||||||
from socketserver import ThreadingMixIn
|
from socketserver import ThreadingMixIn
|
||||||
|
|
||||||
BDADDR_ANY = ""
|
|
||||||
|
|
||||||
|
|
||||||
def str2ba(string, ba):
|
|
||||||
"""Convert string to Bluetooth address"""
|
|
||||||
for i, v in enumerate(string.split(":")):
|
|
||||||
ba.b[5 - i] = int(v, 16)
|
|
||||||
|
|
||||||
|
|
||||||
def ba2str(ba):
|
|
||||||
"""Convert Bluetooth address to string"""
|
|
||||||
string = []
|
|
||||||
for b in ba.b:
|
|
||||||
string.append("{:02X}".format(b))
|
|
||||||
string.reverse()
|
|
||||||
return ":".join(string).upper()
|
|
||||||
|
|
||||||
|
|
||||||
class RFCOMMServer:
|
class RFCOMMServer:
|
||||||
"""Object that simplifies setting up an RFCOMM socket server.
|
"""
|
||||||
|
Object that simplifies setting up an RFCOMM socket server.
|
||||||
|
|
||||||
This is based on the ``socketserver.SocketServer`` class in the Python
|
This is based on the ``socketserver.SocketServer`` class in the Python
|
||||||
standard library.
|
standard library.
|
||||||
@@ -44,10 +28,10 @@ class RFCOMMServer:
|
|||||||
self.server_address = server_address
|
self.server_address = server_address
|
||||||
self.RequestHandlerClass = RequestHandlerClass
|
self.RequestHandlerClass = RequestHandlerClass
|
||||||
|
|
||||||
self.socket = BluetoothSocket(RFCOMM)
|
self.socket = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.socket.bind((server_address[0], server_address[1]))
|
self.socket.bind(server_address)
|
||||||
# self.server_address = self.socket.getsockname()
|
# self.server_address = self.socket.getsockname()
|
||||||
self.socket.listen(self.request_queue_size)
|
self.socket.listen(self.request_queue_size)
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -83,50 +67,21 @@ class RFCOMMServer:
|
|||||||
self.socket.close()
|
self.socket.close()
|
||||||
|
|
||||||
|
|
||||||
class StreamRequestHandler:
|
|
||||||
"""Class that handles incoming requests.
|
|
||||||
|
|
||||||
This is based on ``socketserver.StreamRequestHandler`` from the Python
|
|
||||||
standard library.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, request, client_address, server):
|
|
||||||
self.request = request
|
|
||||||
self.client_address = client_address
|
|
||||||
self.server = server
|
|
||||||
self.setup()
|
|
||||||
try:
|
|
||||||
self.handle()
|
|
||||||
finally:
|
|
||||||
self.finish()
|
|
||||||
|
|
||||||
def setup(self):
|
|
||||||
self.wfile = self.request
|
|
||||||
self.rfile = self.request
|
|
||||||
|
|
||||||
def handle(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def finish(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class ThreadingRFCOMMServer(ThreadingMixIn, RFCOMMServer):
|
class ThreadingRFCOMMServer(ThreadingMixIn, RFCOMMServer):
|
||||||
"""Version of :class:`RFCOMMServer` that handles connections in a new
|
|
||||||
thread.
|
|
||||||
"""
|
"""
|
||||||
|
Version of :class:`RFCOMMServer` that handles connections in a new thread.
|
||||||
pass
|
"""
|
||||||
|
daemon_threads = True
|
||||||
|
|
||||||
|
|
||||||
class RFCOMMClient:
|
class RFCOMMClient:
|
||||||
def __init__(self, client_address, RequestHandlerClass):
|
def __init__(self, client_address, RequestHandlerClass):
|
||||||
self.client_address = client_address
|
self.client_address = client_address
|
||||||
self.RequestHandlerClass = RequestHandlerClass
|
self.RequestHandlerClass = RequestHandlerClass
|
||||||
self.socket = BluetoothSocket(RFCOMM)
|
self.socket = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)
|
||||||
|
|
||||||
def handle_request(self):
|
def handle_request(self):
|
||||||
self.socket.connect((self.client_address[0], self.client_address[1]))
|
self.socket.connect(self.client_address)
|
||||||
try:
|
try:
|
||||||
self.process_request(self.socket, self.client_address)
|
self.process_request(self.socket, self.client_address)
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -145,4 +100,7 @@ class RFCOMMClient:
|
|||||||
|
|
||||||
|
|
||||||
class ThreadingRFCOMMClient(ThreadingMixIn, RFCOMMClient):
|
class ThreadingRFCOMMClient(ThreadingMixIn, RFCOMMClient):
|
||||||
pass
|
"""
|
||||||
|
Version of :class:`RFCOMMClient` that handles connections in a new thread.
|
||||||
|
"""
|
||||||
|
daemon_threads = True
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
# Copyright (C) 2020 The Pybricks Authors
|
# Copyright (C) 2020,2023 The Pybricks Authors
|
||||||
|
|
||||||
from _thread import allocate_lock
|
|
||||||
from errno import ECONNRESET
|
from errno import ECONNRESET
|
||||||
from struct import pack, unpack
|
from struct import pack, unpack
|
||||||
|
from socket import BDADDR_ANY
|
||||||
|
from socketserver import StreamRequestHandler
|
||||||
|
from threading import Lock
|
||||||
|
|
||||||
from .bluetooth import (
|
from .bluetooth import ThreadingRFCOMMServer, ThreadingRFCOMMClient
|
||||||
BDADDR_ANY,
|
|
||||||
ThreadingRFCOMMServer,
|
|
||||||
ThreadingRFCOMMClient,
|
|
||||||
StreamRequestHandler,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def resolve(brick):
|
def resolve(brick):
|
||||||
@@ -151,7 +148,7 @@ class MailboxHandler(StreamRequestHandler):
|
|||||||
self.server._clients[self.client_address[0]] = self.request
|
self.server._clients[self.client_address[0]] = self.request
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
buf = self.rfile.recv(2)
|
buf = self.rfile.read(2)
|
||||||
if len(buf) == 0:
|
if len(buf) == 0:
|
||||||
break
|
break
|
||||||
except OSError as ex:
|
except OSError as ex:
|
||||||
@@ -160,7 +157,7 @@ class MailboxHandler(StreamRequestHandler):
|
|||||||
break
|
break
|
||||||
raise
|
raise
|
||||||
(size,) = unpack("<H", buf)
|
(size,) = unpack("<H", buf)
|
||||||
buf = self.rfile.recv(size)
|
buf = self.rfile.read(size)
|
||||||
msg_count, cmd_type, cmd, name_size = unpack("<HBBB", buf[0:5])
|
msg_count, cmd_type, cmd, name_size = unpack("<HBBB", buf[0:5])
|
||||||
if cmd_type != SYSTEM_COMMAND_NO_REPLY:
|
if cmd_type != SYSTEM_COMMAND_NO_REPLY:
|
||||||
raise ValueError("Bad message type")
|
raise ValueError("Bad message type")
|
||||||
@@ -180,7 +177,7 @@ class MailboxHandler(StreamRequestHandler):
|
|||||||
class MailboxHandlerMixIn:
|
class MailboxHandlerMixIn:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# protects against concurrent access of other attributes
|
# protects against concurrent access of other attributes
|
||||||
self._lock = allocate_lock()
|
self._lock = Lock()
|
||||||
# map of mailbox name to raw data
|
# map of mailbox name to raw data
|
||||||
self._mailboxes = {}
|
self._mailboxes = {}
|
||||||
# map of device name/address to object with send() method
|
# map of device name/address to object with send() method
|
||||||
@@ -247,7 +244,7 @@ class MailboxHandlerMixIn:
|
|||||||
|
|
||||||
def wait_for_mailbox_update(self, mbox):
|
def wait_for_mailbox_update(self, mbox):
|
||||||
"""Waits until ``mbox`` receives a value."""
|
"""Waits until ``mbox`` receives a value."""
|
||||||
lock = allocate_lock()
|
lock = Lock()
|
||||||
lock.acquire()
|
lock.acquire()
|
||||||
with self._lock:
|
with self._lock:
|
||||||
self._updates[mbox] = lock
|
self._updates[mbox] = lock
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# ThisHub = TechnicHub PrimeHub EssentialHub
|
# ThisHub = TechnicHub PrimeHub EssentialHub
|
||||||
from pybricks.hubs import ThisHub
|
from pybricks.hubs import ThisHub
|
||||||
from pybricks.tools import wait
|
from pybricks.tools import wait
|
||||||
from pybricks.geometry import Axis
|
from pybricks.parameters import Axis
|
||||||
|
|
||||||
# Initialize the hub.
|
# Initialize the hub.
|
||||||
hub = ThisHub()
|
hub = ThisHub()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# ThisHub = TechnicHub PrimeHub EssentialHub
|
# ThisHub = TechnicHub PrimeHub EssentialHub
|
||||||
from pybricks.hubs import ThisHub
|
from pybricks.hubs import ThisHub
|
||||||
from pybricks.tools import wait
|
from pybricks.tools import wait
|
||||||
from pybricks.geometry import Axis
|
from pybricks.parameters import Axis
|
||||||
|
|
||||||
# Initialize the hub. In this case, specify that the hub is mounted with the
|
# Initialize the hub. In this case, specify that the hub is mounted with the
|
||||||
# top side facing forward and the front side facing to the right.
|
# top side facing forward and the front side facing to the right.
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from pybricks.hubs import PrimeHub
|
from pybricks.hubs import PrimeHub
|
||||||
from pybricks.tools import wait
|
from pybricks.tools import wait, Matrix
|
||||||
from pybricks.geometry import Matrix
|
|
||||||
|
|
||||||
# Initialize the hub.
|
# Initialize the hub.
|
||||||
hub = PrimeHub()
|
hub = PrimeHub()
|
||||||
|
|||||||
@@ -4,19 +4,34 @@ from uerrno import ENODEV
|
|||||||
|
|
||||||
# Dictionary of device identifiers along with their name.
|
# Dictionary of device identifiers along with their name.
|
||||||
device_names = {
|
device_names = {
|
||||||
34: "Wedo 2.0 Tilt Sensor",
|
# pybricks.pupdevices.DCMotor
|
||||||
35: "Wedo 2.0 Infrared Sensor",
|
1: "Wedo 2.0 Medium Motor",
|
||||||
37: "BOOST Color Distance Sensor",
|
2: "Powered Up Train Motor",
|
||||||
|
# pybricks.pupdevices.Light
|
||||||
|
8: "Powered Up Light",
|
||||||
|
# pybricks.pupdevices.Motor
|
||||||
38: "BOOST Interactive Motor",
|
38: "BOOST Interactive Motor",
|
||||||
46: "Technic Large Motor",
|
46: "Technic Large Motor",
|
||||||
47: "Technic Extra Large Motor",
|
47: "Technic Extra Large Motor",
|
||||||
48: "SPIKE Medium Angular Motor",
|
48: "SPIKE Medium Angular Motor",
|
||||||
49: "SPIKE Large Angular Motor",
|
49: "SPIKE Large Angular Motor",
|
||||||
61: "SPIKE Color Sensor",
|
65: "SPIKE Small Angular Motor",
|
||||||
62: "SPIKE Ultrasonic Sensor",
|
|
||||||
63: "SPIKE Force Sensor",
|
|
||||||
75: "Technic Medium Angular Motor",
|
75: "Technic Medium Angular Motor",
|
||||||
76: "Technic Large Angular Motor",
|
76: "Technic Large Angular Motor",
|
||||||
|
# pybricks.pupdevices.TiltSensor
|
||||||
|
34: "Wedo 2.0 Tilt Sensor",
|
||||||
|
# pybricks.pupdevices.InfraredSensor
|
||||||
|
35: "Wedo 2.0 Infrared Motion Sensor",
|
||||||
|
# pybricks.pupdevices.ColorDistanceSensor
|
||||||
|
37: "BOOST Color Distance Sensor",
|
||||||
|
# pybricks.pupdevices.ColorSensor
|
||||||
|
61: "SPIKE Color Sensor",
|
||||||
|
# pybricks.pupdevices.UltrasonicSensor
|
||||||
|
62: "SPIKE Ultrasonic Sensor",
|
||||||
|
# pybricks.pupdevices.ForceSensor
|
||||||
|
63: "SPIKE Force Sensor",
|
||||||
|
# pybricks.pupdevices.ColorLightMatrix
|
||||||
|
64: "SPIKE 3x3 Color Light Matrix",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Make a list of known ports.
|
# Make a list of known ports.
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ drive_base = DriveBase(left_motor, right_motor, wheel_diameter=56, axle_track=11
|
|||||||
# Drive forward by 500mm (half a meter).
|
# Drive forward by 500mm (half a meter).
|
||||||
drive_base.straight(500)
|
drive_base.straight(500)
|
||||||
|
|
||||||
# Turn around clockwise (180 degrees)
|
# Turn around clockwise by 180 degrees.
|
||||||
drive_base.turn(180)
|
drive_base.turn(180)
|
||||||
|
|
||||||
# Drive forward again to drive back.
|
# Drive forward again to get back to the start.
|
||||||
drive_base.straight(500)
|
drive_base.straight(500)
|
||||||
|
|
||||||
# Turn around counterclockwise.
|
# Turn around counterclockwise.
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ from typing_extensions import NotRequired, TypedDict
|
|||||||
PYBRICKS_CODE_PACKAGES = {
|
PYBRICKS_CODE_PACKAGES = {
|
||||||
"micropython",
|
"micropython",
|
||||||
"pybricks",
|
"pybricks",
|
||||||
"pybricks.geometry",
|
|
||||||
"pybricks.hubs",
|
"pybricks.hubs",
|
||||||
"pybricks.iodevices",
|
"pybricks.iodevices",
|
||||||
"pybricks.parameters",
|
"pybricks.parameters",
|
||||||
@@ -489,7 +488,6 @@ def initialize():
|
|||||||
"pybricks._common",
|
"pybricks._common",
|
||||||
"pybricks.ev3dev",
|
"pybricks.ev3dev",
|
||||||
"pybricks.ev3dev.speaker",
|
"pybricks.ev3dev.speaker",
|
||||||
"pybricks.geometry",
|
|
||||||
"pybricks.hubs",
|
"pybricks.hubs",
|
||||||
"pybricks.iodevices",
|
"pybricks.iodevices",
|
||||||
"pybricks.parameters",
|
"pybricks.parameters",
|
||||||
|
|||||||
@@ -79,7 +79,12 @@ def test_hub_dot_imu_dot():
|
|||||||
"acceleration",
|
"acceleration",
|
||||||
"angular_velocity",
|
"angular_velocity",
|
||||||
"heading",
|
"heading",
|
||||||
|
"orientation",
|
||||||
|
"ready",
|
||||||
"reset_heading",
|
"reset_heading",
|
||||||
|
"rotation",
|
||||||
|
"settings",
|
||||||
|
"stationary",
|
||||||
"tilt",
|
"tilt",
|
||||||
"up",
|
"up",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ def test_from_pybricks_import():
|
|||||||
code = "from pybricks import "
|
code = "from pybricks import "
|
||||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||||
assert [c["insertText"] for c in completions] == [
|
assert [c["insertText"] for c in completions] == [
|
||||||
"geometry",
|
|
||||||
"hubs",
|
"hubs",
|
||||||
"iodevices",
|
"iodevices",
|
||||||
"parameters",
|
"parameters",
|
||||||
@@ -74,7 +73,6 @@ def test_from_pybricks_dot():
|
|||||||
code = "from pybricks."
|
code = "from pybricks."
|
||||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||||
assert [c["insertText"] for c in completions] == [
|
assert [c["insertText"] for c in completions] == [
|
||||||
"geometry",
|
|
||||||
"hubs",
|
"hubs",
|
||||||
"iodevices",
|
"iodevices",
|
||||||
"parameters",
|
"parameters",
|
||||||
@@ -84,16 +82,6 @@ def test_from_pybricks_dot():
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_from_pybricks_geometry_import():
|
|
||||||
code = "from pybricks.geometry import "
|
|
||||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
|
||||||
assert [c["insertText"] for c in completions] == [
|
|
||||||
"Axis",
|
|
||||||
"Matrix",
|
|
||||||
"vector",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def test_from_pybricks_hubs_import():
|
def test_from_pybricks_hubs_import():
|
||||||
code = "from pybricks.hubs import "
|
code = "from pybricks.hubs import "
|
||||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||||
@@ -127,6 +115,7 @@ def test_from_pybricks_parameters_import():
|
|||||||
code = "from pybricks.parameters import "
|
code = "from pybricks.parameters import "
|
||||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||||
assert [c["insertText"] for c in completions] == [
|
assert [c["insertText"] for c in completions] == [
|
||||||
|
"Axis",
|
||||||
"Button",
|
"Button",
|
||||||
"Color",
|
"Color",
|
||||||
"Direction",
|
"Direction",
|
||||||
@@ -159,17 +148,18 @@ def test_from_pybricks_pupdevices_import():
|
|||||||
def test_from_pybricks_robotics_import():
|
def test_from_pybricks_robotics_import():
|
||||||
code = "from pybricks.robotics import "
|
code = "from pybricks.robotics import "
|
||||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||||
assert [c["insertText"] for c in completions] == [
|
assert [c["insertText"] for c in completions] == ["DriveBase", "GyroDriveBase"]
|
||||||
"DriveBase",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def test_from_pybricks_tools_import():
|
def test_from_pybricks_tools_import():
|
||||||
code = "from pybricks.tools import "
|
code = "from pybricks.tools import "
|
||||||
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
completions: list[CompletionItem] = json.loads(complete(code, 1, len(code) + 1))
|
||||||
assert [c["insertText"] for c in completions] == [
|
assert [c["insertText"] for c in completions] == [
|
||||||
|
"cross",
|
||||||
"DataLog",
|
"DataLog",
|
||||||
|
"Matrix",
|
||||||
"StopWatch",
|
"StopWatch",
|
||||||
|
"vector",
|
||||||
"wait",
|
"wait",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,12 @@ def test_hub_dot_imu_dot():
|
|||||||
"acceleration",
|
"acceleration",
|
||||||
"angular_velocity",
|
"angular_velocity",
|
||||||
"heading",
|
"heading",
|
||||||
|
"orientation",
|
||||||
|
"ready",
|
||||||
"reset_heading",
|
"reset_heading",
|
||||||
|
"rotation",
|
||||||
|
"settings",
|
||||||
|
"stationary",
|
||||||
"tilt",
|
"tilt",
|
||||||
"up",
|
"up",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -67,7 +67,12 @@ def test_hub_dot_imu_dot():
|
|||||||
"acceleration",
|
"acceleration",
|
||||||
"angular_velocity",
|
"angular_velocity",
|
||||||
"heading",
|
"heading",
|
||||||
|
"orientation",
|
||||||
|
"ready",
|
||||||
"reset_heading",
|
"reset_heading",
|
||||||
|
"rotation",
|
||||||
|
"settings",
|
||||||
|
"stationary",
|
||||||
"tilt",
|
"tilt",
|
||||||
"up",
|
"up",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ def _get_function_signature(module: str, function: str) -> SignatureHelp:
|
|||||||
FUNCTION_PARAMS = [
|
FUNCTION_PARAMS = [
|
||||||
pytest.param("pybricks.tools", "wait", [(["time: Number"], "None")]),
|
pytest.param("pybricks.tools", "wait", [(["time: Number"], "None")]),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
"pybricks.geometry",
|
"pybricks.tools",
|
||||||
"vector",
|
"vector",
|
||||||
[
|
[
|
||||||
(["x: float", "y: float"], "Matrix"),
|
(["x: float", "y: float"], "Matrix"),
|
||||||
@@ -104,6 +104,7 @@ CONSTRUCTOR_PARAMS = [
|
|||||||
"positive_direction: Direction=Direction.CLOCKWISE",
|
"positive_direction: Direction=Direction.CLOCKWISE",
|
||||||
"gears: Optional[Union[Collection[int], Collection[Collection[int]]]]=None",
|
"gears: Optional[Union[Collection[int], Collection[Collection[int]]]]=None",
|
||||||
"reset_angle: bool=True",
|
"reset_angle: bool=True",
|
||||||
|
"profile: Number=None",
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -151,7 +152,7 @@ CONSTRUCTOR_PARAMS = [
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
"pybricks.geometry",
|
"pybricks.tools",
|
||||||
"Matrix",
|
"Matrix",
|
||||||
[["rows: Sequence[Sequence[float]]"]],
|
[["rows: Sequence[Sequence[float]]"]],
|
||||||
),
|
),
|
||||||
@@ -306,12 +307,19 @@ METHOD_PARAMS = [
|
|||||||
[(["axis: Axis"], "float"), ([], "Matrix")],
|
[(["axis: Axis"], "float"), ([], "Matrix")],
|
||||||
),
|
),
|
||||||
pytest.param("pybricks.hubs", "TechnicHub", "imu.heading", [([], "float")]),
|
pytest.param("pybricks.hubs", "TechnicHub", "imu.heading", [([], "float")]),
|
||||||
|
pytest.param("pybricks.hubs", "TechnicHub", "imu.orientation", [([], "Matrix")]),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
"pybricks.hubs",
|
"pybricks.hubs",
|
||||||
"TechnicHub",
|
"TechnicHub",
|
||||||
"imu.reset_heading",
|
"imu.reset_heading",
|
||||||
[(["angle: Number"], "None")],
|
[(["angle: Number"], "None")],
|
||||||
),
|
),
|
||||||
|
pytest.param(
|
||||||
|
"pybricks.hubs",
|
||||||
|
"TechnicHub",
|
||||||
|
"imu.rotation",
|
||||||
|
[(["axis: Axis"], "float")],
|
||||||
|
),
|
||||||
pytest.param("pybricks.hubs", "TechnicHub", "battery.voltage", [([], "int")]),
|
pytest.param("pybricks.hubs", "TechnicHub", "battery.voltage", [([], "int")]),
|
||||||
pytest.param("pybricks.hubs", "TechnicHub", "battery.current", [([], "int")]),
|
pytest.param("pybricks.hubs", "TechnicHub", "battery.current", [([], "int")]),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
@@ -398,12 +406,19 @@ METHOD_PARAMS = [
|
|||||||
[(["axis: Axis"], "float"), ([], "Matrix")],
|
[(["axis: Axis"], "float"), ([], "Matrix")],
|
||||||
),
|
),
|
||||||
pytest.param("pybricks.hubs", "PrimeHub", "imu.heading", [([], "float")]),
|
pytest.param("pybricks.hubs", "PrimeHub", "imu.heading", [([], "float")]),
|
||||||
|
pytest.param("pybricks.hubs", "PrimeHub", "imu.orientation", [([], "Matrix")]),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
"pybricks.hubs",
|
"pybricks.hubs",
|
||||||
"PrimeHub",
|
"PrimeHub",
|
||||||
"imu.reset_heading",
|
"imu.reset_heading",
|
||||||
[(["angle: Number"], "None")],
|
[(["angle: Number"], "None")],
|
||||||
),
|
),
|
||||||
|
pytest.param(
|
||||||
|
"pybricks.hubs",
|
||||||
|
"PrimeHub",
|
||||||
|
"imu.rotation",
|
||||||
|
[(["axis: Axis"], "float")],
|
||||||
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
"pybricks.hubs",
|
"pybricks.hubs",
|
||||||
"PrimeHub",
|
"PrimeHub",
|
||||||
@@ -481,12 +496,19 @@ METHOD_PARAMS = [
|
|||||||
[(["axis: Axis"], "float"), ([], "Matrix")],
|
[(["axis: Axis"], "float"), ([], "Matrix")],
|
||||||
),
|
),
|
||||||
pytest.param("pybricks.hubs", "EssentialHub", "imu.heading", [([], "float")]),
|
pytest.param("pybricks.hubs", "EssentialHub", "imu.heading", [([], "float")]),
|
||||||
|
pytest.param("pybricks.hubs", "EssentialHub", "imu.orientation", [([], "Matrix")]),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
"pybricks.hubs",
|
"pybricks.hubs",
|
||||||
"EssentialHub",
|
"EssentialHub",
|
||||||
"imu.reset_heading",
|
"imu.reset_heading",
|
||||||
[(["angle: Number"], "None")],
|
[(["angle: Number"], "None")],
|
||||||
),
|
),
|
||||||
|
pytest.param(
|
||||||
|
"pybricks.hubs",
|
||||||
|
"EssentialHub",
|
||||||
|
"imu.rotation",
|
||||||
|
[(["axis: Axis"], "float")],
|
||||||
|
),
|
||||||
pytest.param("pybricks.hubs", "EssentialHub", "battery.voltage", [([], "int")]),
|
pytest.param("pybricks.hubs", "EssentialHub", "battery.voltage", [([], "int")]),
|
||||||
pytest.param("pybricks.hubs", "EssentialHub", "battery.current", [([], "int")]),
|
pytest.param("pybricks.hubs", "EssentialHub", "battery.current", [([], "int")]),
|
||||||
pytest.param("pybricks.hubs", "EssentialHub", "charger.connected", [([], "bool")]),
|
pytest.param("pybricks.hubs", "EssentialHub", "charger.connected", [([], "bool")]),
|
||||||
@@ -520,7 +542,12 @@ METHOD_PARAMS = [
|
|||||||
"settings",
|
"settings",
|
||||||
[(["max_voltage: Number"], "None"), ([], "Tuple[int]")],
|
[(["max_voltage: Number"], "None"), ([], "Tuple[int]")],
|
||||||
),
|
),
|
||||||
pytest.param("pybricks.pupdevices", "Motor", "speed", [([], "int")]),
|
pytest.param(
|
||||||
|
"pybricks.pupdevices",
|
||||||
|
"Motor",
|
||||||
|
"speed",
|
||||||
|
[(["window: Number=100"], "int")],
|
||||||
|
),
|
||||||
pytest.param("pybricks.pupdevices", "Motor", "angle", [([], "int")]),
|
pytest.param("pybricks.pupdevices", "Motor", "angle", [([], "int")]),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
"pybricks.pupdevices",
|
"pybricks.pupdevices",
|
||||||
@@ -637,12 +664,12 @@ METHOD_PARAMS = [
|
|||||||
"kp: Optional[Number]=None",
|
"kp: Optional[Number]=None",
|
||||||
"ki: Optional[Number]=None",
|
"ki: Optional[Number]=None",
|
||||||
"kd: Optional[Number]=None",
|
"kd: Optional[Number]=None",
|
||||||
"reserved: Optional[Number]=None",
|
"integral_deadzone: Optional[Number]=None",
|
||||||
"integral_rate: Optional[Number]=None",
|
"integral_rate: Optional[Number]=None",
|
||||||
],
|
],
|
||||||
"None",
|
"None",
|
||||||
),
|
),
|
||||||
([], "Tuple[int, int, int, None, int]"),
|
([], "Tuple[int, int, int, int, int]"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
<!-- refer to https://keepachangelog.com/en/1.0.0/ for guidance -->
|
<!-- refer to https://keepachangelog.com/en/1.0.0/ for guidance -->
|
||||||
|
|
||||||
|
## 2.8.0 - 2023-04-21
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Updated docs to v3.3.0b4.
|
||||||
|
|
||||||
## 2.7.0 - 2022-12-20
|
## 2.7.0 - 2022-12-20
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@pybricks/ide-docs",
|
"name": "@pybricks/ide-docs",
|
||||||
"version": "2.7.0",
|
"version": "2.8.0",
|
||||||
"description": "Special build of Pybricks API docs for embedding in an IDE.",
|
"description": "Special build of Pybricks API docs for embedding in an IDE.",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "pybricks"
|
name = "pybricks"
|
||||||
version = "3.2.0"
|
version = "3.3.0a4"
|
||||||
description = "Documentation and user-API stubs for Pybricks MicroPython"
|
description = "Documentation and user-API stubs for Pybricks MicroPython"
|
||||||
authors = ["The Pybricks Authors <dev@pybricks.com>"]
|
authors = ["The Pybricks Authors <dev@pybricks.com>"]
|
||||||
maintainers = ["Laurens Valk <laurens@pybricks.com>", "David Lechner <david@pybricks.com>" ]
|
maintainers = ["Laurens Valk <laurens@pybricks.com>", "David Lechner <david@pybricks.com>" ]
|
||||||
|
|||||||
+189
-21
@@ -8,8 +8,8 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import Union, Iterable, overload, Optional, Tuple, Collection, TYPE_CHECKING
|
from typing import Union, Iterable, overload, Optional, Tuple, Collection, TYPE_CHECKING
|
||||||
|
|
||||||
from .geometry import Matrix, Axis
|
from .tools import Matrix
|
||||||
from .parameters import Direction, Stop, Button, Port, Color, Side
|
from .parameters import Axis, Direction, Stop, Button, Port, Color, Side
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .parameters import Number
|
from .parameters import Number
|
||||||
@@ -219,18 +219,18 @@ class Control:
|
|||||||
kp: Optional[Number] = None,
|
kp: Optional[Number] = None,
|
||||||
ki: Optional[Number] = None,
|
ki: Optional[Number] = None,
|
||||||
kd: Optional[Number] = None,
|
kd: Optional[Number] = None,
|
||||||
reserved: Optional[Number] = None,
|
integral_deadzone: Optional[Number] = None,
|
||||||
integral_rate: Optional[Number] = None,
|
integral_rate: Optional[Number] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
...
|
...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def pid(self) -> Tuple[int, int, int, None, int]:
|
def pid(self) -> Tuple[int, int, int, int, int]:
|
||||||
...
|
...
|
||||||
|
|
||||||
def pid(self, *args):
|
def pid(self, *args):
|
||||||
"""pid(kp, ki, kd, reserved, integral_rate)
|
"""pid(kp, ki, kd, integral_deadzone, integral_rate)
|
||||||
pid() -> Tuple[int, int, int, None, int]
|
pid() -> Tuple[int, int, int, int, int]
|
||||||
|
|
||||||
Gets or sets the PID values for position and speed control.
|
Gets or sets the PID values for position and speed control.
|
||||||
|
|
||||||
@@ -245,7 +245,8 @@ class Control:
|
|||||||
kd (int): Derivative position (or proportional speed) control
|
kd (int): Derivative position (or proportional speed) control
|
||||||
constant. It is the feedback torque per
|
constant. It is the feedback torque per
|
||||||
unit of speed: µNm/(deg/s).
|
unit of speed: µNm/(deg/s).
|
||||||
reserved: This setting is not used.
|
integral_deadzone (Number, deg or Number, mm): Zone around the
|
||||||
|
target where the error integral does not accumulate errors.
|
||||||
integral_rate (Number, deg/s or Number, mm/s): Maximum rate at
|
integral_rate (Number, deg/s or Number, mm/s): Maximum rate at
|
||||||
which the error integral is allowed to grow.
|
which the error integral is allowed to grow.
|
||||||
"""
|
"""
|
||||||
@@ -303,6 +304,52 @@ class Control:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class Model:
|
||||||
|
"""Class to interact with motor state observer and settings."""
|
||||||
|
|
||||||
|
def state(self) -> Tuple[float, float, float, bool]:
|
||||||
|
"""state() -> Tuple[float, float, float, bool]
|
||||||
|
|
||||||
|
Gets the estimated angle, speed, current, and stall state of the motor,
|
||||||
|
using a simulation model that mimics the real motor.
|
||||||
|
These estimates are updated faster than the real measurements,
|
||||||
|
which can be useful when building your own PID controllers.
|
||||||
|
|
||||||
|
For most applications it is better to used the *measured*
|
||||||
|
:meth:`angle <pybricks.pupdevices.Motor.angle>`,
|
||||||
|
:meth:`speed <pybricks.pupdevices.Motor.speed>`,
|
||||||
|
:meth:`load <pybricks.pupdevices.Motor.load>`, and
|
||||||
|
:meth:`stall <pybricks.pupdevices.Motor.stalled>` state instead.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Tuple with the estimated angle (deg), speed (deg/s), current (mA),
|
||||||
|
and stall state (``True`` or ``False``).
|
||||||
|
"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def settings(self, values: tuple) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def settings(self) -> tuple:
|
||||||
|
...
|
||||||
|
|
||||||
|
def settings(self, speed, time):
|
||||||
|
"""settings(values)
|
||||||
|
settings() -> Tuple
|
||||||
|
|
||||||
|
Gets or sets model settings as a tuple of integers. If no arguments are
|
||||||
|
given, this will return the current values. This method is mainly used
|
||||||
|
to debug the motor model class. Changing these settings should not be
|
||||||
|
needed in user programs.
|
||||||
|
|
||||||
|
.. _model settings: https://docs.pybricks.com/projects/pbio/en/latest/struct__pbio__observer__settings__t.html
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
values (Tuple): Tuple with `model settings`_.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Motor(DCMotor):
|
class Motor(DCMotor):
|
||||||
"""Generic class to control motors with built-in rotation sensors."""
|
"""Generic class to control motors with built-in rotation sensors."""
|
||||||
|
|
||||||
@@ -312,14 +359,18 @@ class Motor(DCMotor):
|
|||||||
``control`` attribute of the motor. See :ref:`control` for an overview
|
``control`` attribute of the motor. See :ref:`control` for an overview
|
||||||
of available methods."""
|
of available methods."""
|
||||||
|
|
||||||
|
model = Model()
|
||||||
|
"""Model representing the observer that estimates the motor state."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
port: Port,
|
port: Port,
|
||||||
positive_direction: Direction = Direction.CLOCKWISE,
|
positive_direction: Direction = Direction.CLOCKWISE,
|
||||||
gears: Optional[Union[Collection[int], Collection[Collection[int]]]] = None,
|
gears: Optional[Union[Collection[int], Collection[Collection[int]]]] = None,
|
||||||
reset_angle: bool = True,
|
reset_angle: bool = True,
|
||||||
|
profile: Number = None,
|
||||||
):
|
):
|
||||||
"""__init__(port, positive_direction=Direction.CLOCKWISE, gears=None, reset_angle=True)
|
"""__init__(port, positive_direction=Direction.CLOCKWISE, gears=None, reset_angle=True, profile=None)
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
port (Port): Port to which the motor is connected.
|
port (Port): Port to which the motor is connected.
|
||||||
@@ -336,12 +387,16 @@ class Motor(DCMotor):
|
|||||||
When you specify a gear train, all motor commands and settings
|
When you specify a gear train, all motor commands and settings
|
||||||
are automatically adjusted to account for the resulting gear
|
are automatically adjusted to account for the resulting gear
|
||||||
ratio. The motor direction remains unchanged by this.
|
ratio. The motor direction remains unchanged by this.
|
||||||
reset_angle(bool):
|
reset_angle (bool):
|
||||||
Choose ``True`` to reset the rotation sensor value to the
|
Choose ``True`` to reset the rotation sensor value to the
|
||||||
absolute marker angle (between -180 and 179).
|
absolute marker angle (between -180 and 179).
|
||||||
Choose ``False`` to keep the
|
Choose ``False`` to keep the
|
||||||
current value, so your program knows where it left off last
|
current value, so your program knows where it left off last
|
||||||
time.
|
time.
|
||||||
|
profile (Number, deg): Precision profile. A lower value
|
||||||
|
means more precise movement; a larger value means
|
||||||
|
smoother movement. If no value is given, a suitable profile for
|
||||||
|
this motor type will be selected automatically.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def angle(self) -> int:
|
def angle(self) -> int:
|
||||||
@@ -353,11 +408,19 @@ class Motor(DCMotor):
|
|||||||
Motor angle.
|
Motor angle.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def speed(self) -> int:
|
def speed(self, window: Number = 100) -> int:
|
||||||
"""speed() -> int: deg/s
|
"""speed(window=100) -> int: deg/s
|
||||||
|
|
||||||
Gets the speed of the motor.
|
Gets the speed of the motor.
|
||||||
|
|
||||||
|
The speed is measured as the change in the motor angle during the
|
||||||
|
given time window. A short window makes the speed value more
|
||||||
|
responsive to motor movement, but less steady. A long window makes the
|
||||||
|
speed value less responsive, but more steady.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
window (Number, ms): The time window used to determine the speed.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Motor speed.
|
Motor speed.
|
||||||
|
|
||||||
@@ -731,7 +794,7 @@ class LightMatrix:
|
|||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
matrices (iter): Sequence of
|
matrices (iter): Sequence of
|
||||||
:class:`Matrix <pybricks.geometry.Matrix>` of intensities.
|
:class:`Matrix <pybricks.tools.Matrix>` of intensities.
|
||||||
interval (Number, ms): Time to display each image in the list.
|
interval (Number, ms): Time to display each image in the list.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -928,22 +991,94 @@ class Accelerometer(SimpleAccelerometer):
|
|||||||
along the x-axis.
|
along the x-axis.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of pitch and roll angles.
|
Tuple of pitch and roll angles in degrees.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class IMU(Accelerometer):
|
class IMU(Accelerometer):
|
||||||
|
def ready(self) -> bool:
|
||||||
|
"""ready() -> bool
|
||||||
|
|
||||||
|
Checks if the device is calibrated and ready for use.
|
||||||
|
|
||||||
|
This becomes ``True`` when the robot has been sitting stationary for a
|
||||||
|
few seconds, which allows the device to re-calibrate. It is ``False``
|
||||||
|
if the hub has just been started, or if it hasn't had a chance to
|
||||||
|
calibrate for more than 10 minutes.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
``True`` if it is ready for use, ``False`` if not.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def stationary(self) -> bool:
|
||||||
|
"""stationary() -> bool
|
||||||
|
|
||||||
|
Checks if the device is currently stationary (not moving).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
``True`` if stationary for at least a second, ``False`` if it is
|
||||||
|
moving.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def settings(
|
||||||
|
self,
|
||||||
|
angular_velocity_threshold: float = None,
|
||||||
|
acceleration_threshold: float = None,
|
||||||
|
) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def settings(self) -> Tuple[float, float]:
|
||||||
|
...
|
||||||
|
|
||||||
|
def settings(self, *args):
|
||||||
|
"""
|
||||||
|
settings(angular_velocity_threshold, acceleration_threshold)
|
||||||
|
settings() -> Tuple[float, float]
|
||||||
|
|
||||||
|
Configures the IMU settings. If no arguments are given,
|
||||||
|
this returns the current values.
|
||||||
|
|
||||||
|
The ``angular_velocity_threshold`` and ``acceleration_threshold``
|
||||||
|
define when the hub is considered stationary. If all
|
||||||
|
measurements stay below these thresholds for one second, the IMU
|
||||||
|
will recalibrate itself.
|
||||||
|
|
||||||
|
In a noisy room with high ambient vibrations (such as a
|
||||||
|
competition hall), it is recommended to increase the thresholds
|
||||||
|
slightly to give your robot the chance to calibrate.
|
||||||
|
To verify that your settings are working as expected, test that
|
||||||
|
the ``stationary()`` method gives ``False`` if your robot is moving,
|
||||||
|
and ``True`` if it is sitting still for at least a second.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
angular_velocity_threshold (Number, deg/s): The threshold for
|
||||||
|
angular velocity. The default value is 1.5 deg/s.
|
||||||
|
acceleration_threshold (Number, mm/s²): The threshold for angular
|
||||||
|
velocity. The default value is 250 mm/s².
|
||||||
|
"""
|
||||||
|
|
||||||
def heading(self) -> float:
|
def heading(self) -> float:
|
||||||
"""heading() -> float: deg
|
"""heading() -> float: deg
|
||||||
|
|
||||||
Gets the heading angle relative to the starting orientation. It is a
|
Gets the heading angle of your robot. A positive value means a
|
||||||
positive rotation around the :ref:`z-axis in the robot
|
clockwise turn.
|
||||||
frame <robotframe>`, prior to applying any tilt rotation.
|
|
||||||
|
|
||||||
For a vehicle viewed from the top, this means that
|
The heading is 0 when your program starts. The value continues to grow
|
||||||
a positive heading value corresponds to a counterclockwise rotation.
|
even as the robot turns more than 180 degrees. It does not wrap around
|
||||||
|
to -180 like it does in some apps.
|
||||||
|
|
||||||
.. note:: This method is not yet implemented.
|
|
||||||
|
.. note:: *For now, this method only keeps track of the heading while
|
||||||
|
the robot is on a flat surface.*
|
||||||
|
|
||||||
|
This means that the value is
|
||||||
|
no longer correct if you lift it from the table. To solve
|
||||||
|
this, you can call ``reset_heading`` to reset the heading to
|
||||||
|
a known value *after* you put it back down. For example, you
|
||||||
|
could align your robot with the side of the competition table
|
||||||
|
and reset the heading 90 degrees as the new starting point.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Heading angle relative to starting orientation.
|
Heading angle relative to starting orientation.
|
||||||
@@ -955,8 +1090,6 @@ class IMU(Accelerometer):
|
|||||||
|
|
||||||
Resets the accumulated heading angle of the robot.
|
Resets the accumulated heading angle of the robot.
|
||||||
|
|
||||||
.. note:: This method is not yet implemented.
|
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
angle (Number, deg): Value to which the heading should be reset.
|
angle (Number, deg): Value to which the heading should be reset.
|
||||||
"""
|
"""
|
||||||
@@ -985,6 +1118,41 @@ class IMU(Accelerometer):
|
|||||||
this returns a vector of accelerations along all axes.
|
this returns a vector of accelerations along all axes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def rotation(self, axis: Axis) -> float:
|
||||||
|
"""
|
||||||
|
rotation(axis) -> float: deg
|
||||||
|
|
||||||
|
Gets the rotation of the device along a given axis in
|
||||||
|
the :ref:`robot reference frame <robotframe>`.
|
||||||
|
|
||||||
|
This value is useful if your robot *only* rotates along the requested
|
||||||
|
axis. For general three-dimensional motion, use the
|
||||||
|
``orientation()`` method instead.
|
||||||
|
|
||||||
|
The value starts counting from ``0`` when you initialize this class.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
axis (Axis): Axis along which the rotation should be measured.
|
||||||
|
Returns:
|
||||||
|
The rotation angle.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def orientation(self) -> Matrix:
|
||||||
|
"""
|
||||||
|
orientation() -> Matrix
|
||||||
|
|
||||||
|
Gets the three-dimensional orientation of the robot in
|
||||||
|
the :ref:`robot reference frame <robotframe>`.
|
||||||
|
|
||||||
|
It returns a rotation matrix whose columns represent the ``X``, ``Y``,
|
||||||
|
and ``Z`` axis of the robot.
|
||||||
|
|
||||||
|
.. note:: This method is not yet implemented.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The rotation matrix.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class CommonColorSensor:
|
class CommonColorSensor:
|
||||||
"""Generic color sensor that supports Pybricks color calibration."""
|
"""Generic color sensor that supports Pybricks color calibration."""
|
||||||
|
|||||||
@@ -168,14 +168,12 @@ class InfraredSensor:
|
|||||||
class GyroSensor:
|
class GyroSensor:
|
||||||
"""LEGO® MINDSTORMS® EV3 Gyro Sensor."""
|
"""LEGO® MINDSTORMS® EV3 Gyro Sensor."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, port: _Port, direction: _Direction = _Direction.CLOCKWISE):
|
||||||
self, port: _Port, positive_direction: _Direction = _Direction.CLOCKWISE
|
|
||||||
):
|
|
||||||
"""GyroSensor(port)
|
"""GyroSensor(port)
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
port (Port): Port to which the sensor is connected.
|
port (Port): Port to which the sensor is connected.
|
||||||
positive_direction (Direction):
|
direction (Direction):
|
||||||
Positive rotation direction when looking at the red dot on top
|
Positive rotation direction when looking at the red dot on top
|
||||||
of the sensor.
|
of the sensor.
|
||||||
|
|
||||||
|
|||||||
@@ -1,132 +0,0 @@
|
|||||||
# SPDX-License-Identifier: MIT
|
|
||||||
# Copyright (c) 2018-2022 The Pybricks Authors
|
|
||||||
|
|
||||||
"""Core linear algebra functionality for orientation sensors and robotics."""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import Sequence, Tuple, overload
|
|
||||||
|
|
||||||
|
|
||||||
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.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class Axis:
|
|
||||||
"""Unit axes of a coordinate system.
|
|
||||||
|
|
||||||
.. data:: X = vector(1, 0, 0)
|
|
||||||
.. data:: Y = vector(0, 1, 0)
|
|
||||||
.. data:: Z = vector(0, 0, 1)
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
X: Matrix = vector(1, 0, 0)
|
|
||||||
Y: Matrix = vector(0, 1, 0)
|
|
||||||
Z: Matrix = vector(0, 0, 1)
|
|
||||||
@@ -4,9 +4,8 @@
|
|||||||
"""LEGO® Programmable Hubs."""
|
"""LEGO® Programmable Hubs."""
|
||||||
from . import _common
|
from . import _common
|
||||||
from .ev3dev import _speaker
|
from .ev3dev import _speaker
|
||||||
from .geometry import Axis
|
|
||||||
from .media.ev3dev import Image as _Image
|
from .media.ev3dev import Image as _Image
|
||||||
from .parameters import Button as _Button
|
from .parameters import Button as _Button, Axis
|
||||||
|
|
||||||
|
|
||||||
class EV3Brick:
|
class EV3Brick:
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from enum import Enum
|
|||||||
from typing import Union, TYPE_CHECKING
|
from typing import Union, TYPE_CHECKING
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from .geometry import Matrix as _Matrix
|
from .tools import Matrix as _Matrix, vector as _vector
|
||||||
|
|
||||||
if TYPE_CHECKING or os.environ.get("SPHINX_BUILD") == "True":
|
if TYPE_CHECKING or os.environ.get("SPHINX_BUILD") == "True":
|
||||||
Number = Union[int, float]
|
Number = Union[int, float]
|
||||||
@@ -57,6 +57,20 @@ class _PybricksEnum(Enum, metaclass=_PybricksEnumMeta):
|
|||||||
return str(self)
|
return str(self)
|
||||||
|
|
||||||
|
|
||||||
|
class Axis:
|
||||||
|
"""Unit axes of a coordinate system.
|
||||||
|
|
||||||
|
.. data:: X = vector(1, 0, 0)
|
||||||
|
.. data:: Y = vector(0, 1, 0)
|
||||||
|
.. data:: Z = vector(0, 0, 1)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
X: _Matrix = _vector(1, 0, 0)
|
||||||
|
Y: _Matrix = _vector(0, 1, 0)
|
||||||
|
Z: _Matrix = _vector(0, 0, 1)
|
||||||
|
|
||||||
|
|
||||||
class Color:
|
class Color:
|
||||||
"""Light or surface color."""
|
"""Light or surface color."""
|
||||||
|
|
||||||
|
|||||||
@@ -38,8 +38,9 @@ class Motor(_common.Motor):
|
|||||||
positive_direction: Direction = Direction.CLOCKWISE,
|
positive_direction: Direction = Direction.CLOCKWISE,
|
||||||
gears: Optional[Union[Collection[int], Collection[Collection[int]]]] = None,
|
gears: Optional[Union[Collection[int], Collection[Collection[int]]]] = None,
|
||||||
reset_angle: bool = True,
|
reset_angle: bool = True,
|
||||||
|
profile: Number = None,
|
||||||
):
|
):
|
||||||
"""__init__(port, positive_direction=Direction.CLOCKWISE, gears=None, reset_angle=True)
|
"""__init__(port, positive_direction=Direction.CLOCKWISE, gears=None, reset_angle=True, profile=None)
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
port (Port): Port to which the motor is connected.
|
port (Port): Port to which the motor is connected.
|
||||||
@@ -56,12 +57,16 @@ class Motor(_common.Motor):
|
|||||||
When you specify a gear train, all motor commands and settings
|
When you specify a gear train, all motor commands and settings
|
||||||
are automatically adjusted to account for the resulting gear
|
are automatically adjusted to account for the resulting gear
|
||||||
ratio. The motor direction remains unchanged by this.
|
ratio. The motor direction remains unchanged by this.
|
||||||
reset_angle(bool):
|
reset_angle (bool):
|
||||||
Choose ``True`` to reset the rotation sensor value to the
|
Choose ``True`` to reset the rotation sensor value to the
|
||||||
absolute marker angle (between -180 and 179).
|
absolute marker angle (between -180 and 179).
|
||||||
Choose ``False`` to keep the
|
Choose ``False`` to keep the
|
||||||
current value, so your program knows where it left off last
|
current value, so your program knows where it left off last
|
||||||
time.
|
time.
|
||||||
|
profile (Number, deg): Precision profile. A lower value
|
||||||
|
means more precise movement; a larger value means
|
||||||
|
smoother movement. If no value is given, a suitable profile for
|
||||||
|
this motor type will be selected automatically.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def reset_angle(self, angle: Optional[Number] = None) -> None:
|
def reset_angle(self, angle: Optional[Number] = None) -> None:
|
||||||
|
|||||||
@@ -28,9 +28,7 @@ class DriveBase:
|
|||||||
|
|
||||||
**Positive** angles and turn rates mean turning **right**.
|
**Positive** angles and turn rates mean turning **right**.
|
||||||
**Negative** means **left**. So when viewed from the top,
|
**Negative** means **left**. So when viewed from the top,
|
||||||
positive means clockwise and negative means counterclockwise. If desired,
|
positive means clockwise and negative means counterclockwise.
|
||||||
you can flip this convention by reversing the ``left_motor`` and
|
|
||||||
``right_motor`` when you initialize this class.
|
|
||||||
|
|
||||||
See the `measuring`_ section for tips to measure and adjust the diameter
|
See the `measuring`_ section for tips to measure and adjust the diameter
|
||||||
and axle track values.
|
and axle track values.
|
||||||
@@ -135,25 +133,30 @@ class DriveBase:
|
|||||||
...
|
...
|
||||||
|
|
||||||
def settings(self, *args):
|
def settings(self, *args):
|
||||||
"""settings(straight_speed, straight_acceleration, turn_rate, turn_acceleration)
|
"""
|
||||||
|
settings(straight_speed, straight_acceleration, turn_rate, turn_acceleration)
|
||||||
settings() -> Tuple[int, int, int, int]
|
settings() -> Tuple[int, int, int, int]
|
||||||
|
|
||||||
Configures the speed and acceleration used
|
Configures the drive base speed and acceleration.
|
||||||
by :meth:`.straight`, :meth:`.turn`, and :meth:`.curve`.
|
|
||||||
|
|
||||||
If you give no arguments, this returns the current values as a tuple.
|
If you give no arguments, this returns the current values as a tuple.
|
||||||
|
|
||||||
The default values are automatically configured based on your wheel
|
The initial values are automatically configured based on your wheel
|
||||||
diameter and axle track. They are selected such that your robot
|
diameter and axle track. They are selected such that your robot
|
||||||
drives at about 40% of its maximum speed.
|
drives at about 40% of its maximum speed.
|
||||||
|
|
||||||
|
The speed values given here do not apply to the :meth:`.drive` method,
|
||||||
|
since you provide your own speed values as arguments in that method.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
straight_speed (Number, mm/s): Straight-line speed of the robot.
|
straight_speed (Number, mm/s): Straight-line speed of the robot.
|
||||||
straight_acceleration (Number, mm/s²): Straight-line
|
straight_acceleration (Number, mm/s²): Straight-line
|
||||||
acceleration and deceleration of the robot.
|
acceleration and deceleration of the robot. Provide a tuple with
|
||||||
|
two values to set acceleration and deceleration separately.
|
||||||
turn_rate (Number, deg/s): Turn rate of the robot.
|
turn_rate (Number, deg/s): Turn rate of the robot.
|
||||||
turn_acceleration (Number, deg/s²): Angular acceleration and
|
turn_acceleration (Number, deg/s²): Angular acceleration and
|
||||||
deceleration of the robot.
|
deceleration of the robot. Provide a tuple with
|
||||||
|
two values to set acceleration and deceleration separately.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def straight(
|
def straight(
|
||||||
@@ -219,6 +222,12 @@ class DriveBase:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class GyroDriveBase(DriveBase):
|
||||||
|
"""A robotic vehicle with two powered wheels and an optional support
|
||||||
|
wheel or caster. It measures the heading using the hub's built-in gyroscope,
|
||||||
|
which can make turning and driving straight more accurate."""
|
||||||
|
|
||||||
|
|
||||||
# HACK: hide from jedi
|
# HACK: hide from jedi
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
del Motor
|
del Motor
|
||||||
|
|||||||
+128
-3
@@ -1,11 +1,11 @@
|
|||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
# Copyright (c) 2018-2022 The Pybricks Authors
|
# Copyright (c) 2018-2023 The Pybricks Authors
|
||||||
|
|
||||||
"""Common tools for timing and data logging."""
|
"""Common tools for timing, data logging, and linear algebra."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any, Sequence, Tuple, overload
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .parameters import Number
|
from .parameters import Number
|
||||||
@@ -97,6 +97,131 @@ class DataLog:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
# HACK: hide from jedi
|
# HACK: hide from jedi
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
del Number
|
del Number
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ def getrandbits(k: int) -> int:
|
|||||||
"""
|
"""
|
||||||
getrandbits(k) -> int
|
getrandbits(k) -> int
|
||||||
|
|
||||||
Gets a random integer :math:`N` satisfying :math:`0 \\leq N < 2^{\\text{bits}}`.
|
Gets a random integer :math:`N` satisfying :math:`0 \\leq N < 2^{\\text{k}}`.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
k (int): How many bits to use for the result.
|
k (int): How many bits to use for the result.
|
||||||
|
|||||||
Reference in New Issue
Block a user