Compare commits

..
26 Commits
Author SHA1 Message Date
Laurens Valk 796c600d72 v4.1.0b1 2026-08-25 13:56:58 +02:00
Laurens Valk 226e811c7b ubuiltins: Fix typing self imports. 2026-08-25 13:52:54 +02:00
Laurens Valk 9086eb696f workflows: Match in local build script.
Also copy to Pybricks Code for local testing.
2026-08-25 13:22:50 +02:00
Laurens Valk 4241fe3607 all: More ruff fixes. 2026-08-25 12:53:19 +02:00
Laurens Valk e0821fade4 all: Drop legacy Tuple. 2026-08-25 12:39:49 +02:00
Laurens Valk d3ba6154f0 all: More ruff fixes.
Apply  ruff check --fix --unsafe-fixes

and then update the pytests to match.
2026-08-25 12:30:08 +02:00
Laurens Valk d00bf35c66 all: ruff check --fix.
Mainly fixes and sorts imports.
2026-08-25 12:22:28 +02:00
Laurens Valk d661fa1838 jedi/tests: Modernize type signatures.
In one go with:

sed -i \
 -e 's/Optional\[Union\[Collection\[int\], Collection\[Collection\[int\]\]\]\]/Collection[int] | Collection[Collection[int]] | None/g' \
 -e 's/Optional\[Union\[Button, Iterable\[Button\]\]\]/Button | Iterable[Button] | None/g' \
 -e 's/Optional\[Union\[Number, Tuple\[Number, Number\]\]\]/Number | Tuple[Number, Number] | None/g' \
 -e 's/Optional\[int | str\]/int | str | None/g' \
 -e 's/Optional\[str\]/str | None/g' \
 -e 's/Optional\[Number\]/Number | None/g' \
 -e 's/Union\[Number, Tuple\[Number, Number, Number, Number\]\]/Number | Tuple[Number, Number, Number, Number]/g' \
 -e 's/Union\[Number, Tuple\[Number, Number, Number\]\]/Number | Tuple[Number, Number, Number]/g' \
 -e 's/Union\[Color, Collection\[Color\]\]/Color | Collection[Color]/g' \
 -e 's/Union\[int, Tuple\[int, int\]\]/int | Tuple[int, int]/g' \
 -e 's/\bTuple\[/tuple[/g' \
 -e 's/\bSet\[/set[/g' \
 jedi/tests/test_get_signature.py
2026-08-25 12:21:14 +02:00
Laurens Valk 97564e33c5 pybricks.parameters: Fix tests for imports. 2026-08-25 12:19:24 +02:00
Laurens Valk a59a567967 requirements: Add EV3. 2026-08-25 12:03:03 +02:00
Laurens Valk adf8ed6b56 pybricks.hubs: Enable EV3.
First pass including Image and ImageFile. Largely migrated from old ev3dev version. We can refine this for the embedded version in the next commits.
2026-08-25 11:42:05 +02:00
Laurens Valk 6a70707f67 pybricks: Clean up typing. 2026-08-25 10:50:19 +02:00
Laurens Valk 4ade3939ae pybricks.nxtdevices: Fix awaitability.
Some are, and some are not.
2026-08-25 10:19:53 +02:00
Laurens Valk 6cd0c3b136 pybricks._common.Motor: Enable on EV3 and NXT.
Use a shared include and only index the pupdevices Motor.
2026-08-25 10:13:58 +02:00
Laurens Valk bd4a26f6ac pybricks._common.Motor: Fix nested attributes.
Now we can use relative paths, which should help when sharing the motor class contents.
2026-08-25 09:54:02 +02:00
Laurens Valk 8dba975894 pybricks.ev3devices: Re-enable.
Also split out to separate class files like we did for pupdevices.

Also make various EV3 and NXT sensor methods awaitable.
2026-08-25 09:26:17 +02:00
Laurens Valk bc70549edd pyproject: Re-enable rtd-theme. 2026-08-24 17:28:00 +02:00
Laurens Valk 37664889c6 github/workflows: Always build. 2026-08-24 17:18:57 +02:00
Laurens Valk b04e318c3c github/workflows: Modernize toolchain. 2026-08-24 11:32:27 +02:00
Laurens Valk 7398f2df1a npm/images: Drop this.
This was consumed only by Pybricks Code, which now just vendors them in.
2026-08-24 11:31:50 +02:00
Laurens Valk 421e589408 jedi: Bump to modern Python. 2026-08-24 11:30:14 +02:00
Laurens Valk 9bd82f7246 doc: Replace fork with extensions.
Use clean upstream Sphinx and use extensions for the awaitable types and work around a Sphinx docstring parsing bug.
2026-08-24 11:01:50 +02:00
Laurens Valk 1fca5c8ad9 all: Build with plain modern sphinx.
Updated for various Sphinx API changes.

Also drop rendered math. Simpler and makes the plain Python docstrings look better in jedi.

```
:math:`0 \leq x \leq 255`.
```

just becomes 0 ≤ x ≤ 255.

Also drop Latex dependencies. We don't rely on the PDF and don't need it for math anymore.
2026-08-24 10:30:57 +02:00
Laurens Valk cab110d4c1 all: Format with ruff. 2026-08-24 09:28:29 +02:00
Laurens Valk 1df788d716 poetry: Drop customizations.
Prepare for an updated Sphinx with a modern theme.
2026-08-24 09:27:25 +02:00
Bert 7e79c20f7d pybricks.messaging: Fix a few minor typos in docstrings.
A few docstrings contained spelling and grammar mistakes. These changes improve readability and do not affect functionality.
2026-06-27 11:17:32 -05:00
208 changed files with 2725 additions and 5103 deletions
+6 -25
View File
@@ -1,47 +1,28 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
name: Build Python package and docs
on:
push:
tags-ignore:
- '**'
pull_request:
paths:
- doc/**
- src/**
- poetry.lock
- poetry.toml
- pyproject.toml
- setup.cfg
on: push
jobs:
build:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- name: Install dependencies
run: |
pip install poetry
poetry run python -m pip install --upgrade pip
poetry run python -m pip install --upgrade setuptools
pipx install poetry
poetry install
- name: Lint Python code
run: poetry run flake8
run: poetry run ruff check
- name: Check Python formatting
run: poetry run ruff format --check
- name: Build package
run: poetry build
- name: Lint docs
run: poetry run doc8
- name: Build html docs for Read the Docs
run: poetry run make -C doc html
- name: Install IDE docs dependencies
run: |
sudo apt-get update
sudo apt-get install dvisvgm preview-latex-style texlive texlive-fonts-extra texlive-latex-extra
- name: Build html docs for Pybricks Code IDE
run: poetry run make -C doc html TAG=ide
+1 -1
View File
@@ -5,7 +5,7 @@ on: [push, pull_request]
jobs:
test:
if: github.ref_type != 'tag'
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- run: pipx install poetry
+3 -13
View File
@@ -11,7 +11,7 @@ permissions:
jobs:
publish_ide_docs:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Get version from tag
run: |
@@ -20,24 +20,14 @@ jobs:
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "NPM_VERSION=$NPM_VERSION" >> $GITHUB_ENV
echo "NPM_TAG=$(echo "$NPM_VERSION" | grep -q '-' && echo 'next' || echo 'latest')" >> $GITHUB_ENV
- name: Ubuntu packages
run: |
sudo apt-get update
sudo apt-get install -y dvisvgm preview-latex-style texlive texlive-fonts-extra texlive-latex-extra
- uses: actions/checkout@v6
with:
submodules: recursive
- name: Set up Python 3.8
uses: actions/setup-python@v5
with:
python-version: 3.8
- name: Install dependencies
run: |
pip install poetry
poetry run python -m pip install --upgrade pip
poetry run python -m pip install --upgrade setuptools
pipx install poetry
poetry install --only=doc
- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: '24'
registry-url: 'https://registry.npmjs.org'
-23
View File
@@ -1,23 +0,0 @@
name: Release @pybricks/images
on:
push:
tags:
- '@pybricks/images/**'
jobs:
publish_ide_docs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v6
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v4
with:
node-version: '22.x'
registry-url: 'https://registry.npmjs.org'
- run: ./build.py
working-directory: npm/images
- run: yarn publish
working-directory: npm/images/build
env:
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
+2 -6
View File
@@ -11,7 +11,7 @@ permissions:
jobs:
publish_jedi:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: Get version from tag
@@ -21,10 +21,6 @@ jobs:
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "NPM_VERSION=$NPM_VERSION" >> $GITHUB_ENV
echo "NPM_TAG=$(echo "$NPM_VERSION" | grep -q '-' && echo 'next' || echo 'latest')" >> $GITHUB_ENV
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install poetry
run: pipx install poetry
- name: Set pybricks-jedi version
@@ -34,7 +30,7 @@ jobs:
run: |
poetry version "$VERSION"
sed -i "s/^pybricks = \".*\"/pybricks = \"$VERSION\"/" jedi/pyproject.toml
- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: '24'
registry-url: 'https://registry.npmjs.org'
+2 -2
View File
@@ -11,7 +11,7 @@ permissions:
jobs:
create_release:
name: Create release on GitHub
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v6
@@ -36,7 +36,7 @@ jobs:
-F CHANGELOG.md \
$PRERELEASE_FLAG
build_and_publish:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- run: pipx run poetry build
+2 -6
View File
@@ -6,9 +6,9 @@
version: 2
build:
os: "ubuntu-22.04"
os: "ubuntu-24.04"
tools:
python: "3.10"
python: "3.12"
jobs:
post_create_environment:
- pip install poetry
@@ -18,7 +18,3 @@ build:
# Build documentation in the doc/main/ directory with Sphinx
sphinx:
configuration: doc/main/conf.py
# Optionally build your docs in additional formats such as PDF
formats:
- pdf
+2 -2
View File
@@ -5,9 +5,9 @@
// List of extensions which should be recommended for users of this workspace.
"recommendations": [
"ms-python.python",
"ms-python.black-formatter"
"charliermarsh.ruff"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": [
]
}
}
+1 -6
View File
@@ -4,14 +4,9 @@
},
"python.defaultInterpreterPath": ".venv/bin/python",
"python.autoComplete.extraPaths": ["jedi/src"],
"python.formatting.provider": "none",
"python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true,
"python.linting.pycodestyleEnabled": false,
"python.linting.enabled": true,
"[python]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "ms-python.black-formatter"
"editor.defaultFormatter": "charliermarsh.ruff"
},
"python.languageServer": "Pylance",
"python.testing.pytestArgs": [
+52 -5
View File
@@ -4,6 +4,26 @@ set -euo pipefail
REPO_ROOT="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
# Option: --pybricks-code <path> copies built npm packages into that
# checkout's node_modules/@pybricks/ for easy local testing.
PYBRICKS_CODE=""
while [[ $# -gt 0 ]]; do
case "$1" in
--pybricks-code)
PYBRICKS_CODE="$(realpath "$2")"
shift 2
;;
*)
echo "usage: $0 [--pybricks-code <path-to-pybricks-code-checkout>]" >&2
exit 1
;;
esac
done
if [[ -n "$PYBRICKS_CODE" && ! -d "$PYBRICKS_CODE/node_modules/@pybricks" ]]; then
echo "error: $PYBRICKS_CODE/node_modules/@pybricks not found (run yarn install there first)" >&2
exit 1
fi
# Activate the project venv so python/make/etc. all use it without poetry run
source "$REPO_ROOT/.venv/bin/activate"
@@ -13,13 +33,19 @@ VERSION=$(grep '^version = ' "$REPO_ROOT/pyproject.toml" | head -1 | sed 's/vers
NPM_VERSION=$(echo "$VERSION" | sed 's/\([0-9]\)a\([0-9]\)/\1-alpha.\2/;s/\([0-9]\)b\([0-9]\)/\1-beta.\2/;s/\([0-9]\)rc\([0-9]\)/\1-rc.\2/')
echo "==> Building version $VERSION (npm: $NPM_VERSION)"
# lint
# lint (same as CI build.yml)
echo "==> Linting"
cd "$REPO_ROOT"
flake8
ruff check
ruff format --check
doc8
# pybricks-jedi tests
# Python package
echo "==> Building Python package"
rm -rf "$REPO_ROOT/dist" # stale wheels would get globbed into the jedi npm package
poetry build
# pybricks-jedi tests (own poetry env, same as CI jedi.yml)
echo "==> Testing pybricks-jedi"
cd "$REPO_ROOT/jedi"
poetry run pytest -vv
@@ -27,16 +53,37 @@ poetry run pytest -vv
# @pybricks/jedi npm package
echo "==> Building @pybricks/jedi"
cd "$REPO_ROOT/jedi"
rm -rf dist # build.py globs dist/*.whl, stale wheels would get shipped
python3 build.py "$NPM_VERSION"
# @pybricks/ide-docs npm package
echo "==> Building @pybricks/ide-docs"
# html docs for Read the Docs
echo "==> Building Read the Docs html docs"
cd "$REPO_ROOT"
make -C doc clean html
# @pybricks/ide-docs npm package (builds the TAG=ide docs)
echo "==> Building @pybricks/ide-docs"
make -C doc clean
cd "$REPO_ROOT/npm/ide-docs"
yarn build
echo ""
echo "Build complete."
echo " python package : dist/"
echo " jedi npm package : jedi/npm-build/"
echo " ide-docs : npm/ide-docs/html/"
if [[ -n "$PYBRICKS_CODE" ]]; then
DEST="$PYBRICKS_CODE/node_modules/@pybricks"
echo "==> Copying packages to $DEST"
rm -rf "$DEST/jedi" "$DEST/ide-docs"
mkdir -p "$DEST/jedi" "$DEST/ide-docs"
cp -r "$REPO_ROOT/jedi/npm-build/." "$DEST/jedi/"
cp -r "$REPO_ROOT/npm/ide-docs/package.json" \
"$REPO_ROOT/npm/ide-docs/LICENSE" \
"$REPO_ROOT/npm/ide-docs/README.md" \
"$REPO_ROOT/npm/ide-docs/html" \
"$DEST/ide-docs/"
echo "Copied @pybricks/jedi and @pybricks/ide-docs. Restart the dev server to pick them up."
fi
+30 -91
View File
@@ -22,6 +22,7 @@
import os
import re
import sys
import tomllib
from docutils import nodes
from docutils.parsers.rst.directives import flag
@@ -30,7 +31,6 @@ from sphinx.application import Sphinx
from sphinx.addnodes import pending_xref
from sphinx.environment import BuildEnvironment
from sphinx.util.nodes import make_refnode
import toml
TOP_DIR = os.path.abspath(os.path.join("..", ".."))
sys.path.insert(0, os.path.join(TOP_DIR, "src"))
@@ -40,7 +40,8 @@ sys.path.append(os.path.abspath("../common/extensions"))
# this line of code grabbed from docs.readthedocs.org
ON_RTD = os.environ.get("READTHEDOCS", None) == "True"
_pyproject = toml.load(os.path.join(TOP_DIR, "pyproject.toml"))
with open(os.path.join(TOP_DIR, "pyproject.toml"), "rb") as _f:
_pyproject = tomllib.load(_f)
# -- General configuration ------------------------------------------------
@@ -55,11 +56,13 @@ extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.napoleon",
"sphinx.ext.todo",
"sphinx.ext.mathjax",
# Custom Pybricks extensions
"awaitable",
"blockimg",
"color",
"classlink",
"docstring_signature",
"nestedmethod",
"requirements",
"requirements-static",
"versionchanged",
@@ -71,8 +74,7 @@ templates_path = ["../common/_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = ".rst"
source_suffix = {".rst": "restructuredtext"}
# The master toctree document.
master_doc = "index"
@@ -134,6 +136,15 @@ nitpick_ignore = [
# not sure why, but this is needed for typing.IO in uselect
nitpick_ignore.append(("py:obj", "typing.IO"))
# MaybeAwaitable* stub types have no documented target; the awaitable
# extension renders them as an "await" prefix instead, but the raw names can
# still leak into signatures (e.g. overloads), so suppress those warnings.
# Likewise, collections.abc types have no link target without intersphinx.
nitpick_ignore_regex = [
("py:class", r"MaybeAwaitable\w*"),
("py:class", r"collections\.abc\.\w+"),
]
# -- Autodoc options ------------------------------------------------------
autodoc_member_order = "bysource"
@@ -146,10 +157,18 @@ add_module_names = False # Hide module name
# -- Options for HTML output ----------------------------------------------
import sphinx_rtd_theme
# The theme to use for HTML and HTML Help pages. Since sphinx-rtd-theme 1.2
# themes are registered via entry points, so setting html_theme is all that
# is needed (no extensions entry or html_theme_path).
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {
# Hide the next/previous buttons at the bottom of each page.
"prev_next_buttons_location": None,
}
html_show_sourcelink = False
html_copy_source = False
@@ -158,38 +177,11 @@ html_context = {
"disclaimer": _DISCLAIMER,
}
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
# html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
html_theme_options = {
"style_external_links": True,
"logo_only": True,
"style_nav_header_background": "#0088ce", # Pybricks blue
}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["../common/_static"]
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# This is required for the alabaster theme
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
html_sidebars = {
"**": [
"relations.html", # needs 'show_related': True theme option to display
"searchbox.html",
]
}
# Don't hyperlink to larger images for scaled images.
html_scaled_image_link = False
@@ -199,64 +191,11 @@ html_scaled_image_link = False
htmlhelp_basename = "Pybricksdoc"
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
"preamble": r"""
\usepackage{CJKutf8}
\makeatletter
\fancypagestyle{normal}{
\fancyhf{}
\fancyfoot[R]{{\py@HeaderFamily\thepage}}
\fancyfoot[C]{\raisebox{-7mm}{\tiny %(disclaimer)s}}
\fancyhead[L]{{\py@HeaderFamily \@title}}
\fancyhead[R]{{\py@HeaderFamily \py@release}}
\renewcommand{\headrulewidth}{0.4pt}
\renewcommand{\footrulewidth}{0.4pt}
}
\fancypagestyle{plain}{
\fancyhf{}
\fancyfoot[R]{{\py@HeaderFamily\thepage}}
\fancyfoot[C]{\raisebox{-7mm}{\tiny %(disclaimer)s}}
\renewcommand{\headrulewidth}{0.4pt}
\renewcommand{\footrulewidth}{0.4pt}
}
\makeatother
"""
% {
"disclaimer": " ".join((_DISCLAIMER, "©", copyright)),
},
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
"extraclassoptions": "openany,oneside",
"releasename": "Version",
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, "".join([project, "-v", version, ".tex"]), _TITLE, author, "manual"),
]
# -- Content control -----------------------------------------------------
exclude_patterns = [
"ev3devices.rst",
"hubs/ev3brick.rst",
"media.rst",
"messaging.rst",
"nxtdevices.rst",
"tools/datalog.rst",
"*.rst.txt",
]
@@ -368,7 +307,7 @@ def on_build_finished(app: Sphinx, exception):
if exception or app.builder.name != "html":
return
import json
from sphinx.ext.intersphinx import InventoryFile
from sphinx.util.inventory import InventoryFile
inv_path = os.path.join(app.outdir, "objects.inv")
if not os.path.exists(inv_path):
@@ -381,8 +320,8 @@ def on_build_finished(app: Sphinx, exception):
for type_key, entries in inv.items():
if not type_key.startswith("py:"):
continue
for name, (project, version, url, display) in entries.items():
index[name] = url
for name, item in entries.items():
index[name] = item.uri
out_path = os.path.join(app.outdir, "namespace_index.json")
with open(out_path, "w") as f:
+61
View File
@@ -0,0 +1,61 @@
"""Show ``await`` in front of multitasking functions and methods.
The Pybricks API returns awaitable objects when a run loop is active but
blocks otherwise. Such functions are annotated with ``MaybeAwaitable*``
return types. This extension:
* makes autodoc treat functions/methods returning ``MaybeAwaitable*`` as
async (there is no public hook for this, so ``is_async`` is patched);
* renders the signature prefix as ``await`` (linked to the multitasking
section in tools) instead of ``async``, which better matches how users
call these functions.
"""
from collections.abc import Sequence
from docutils import nodes
from sphinx.addnodes import desc_sig_keyword
from sphinx.application import Sphinx
from sphinx.domains.python import PyFunction, PyMethod, type_to_xref
from sphinx.ext.autodoc._property_types import _FunctionDefProperties
def _is_async(self: _FunctionDefProperties) -> bool:
if "async" in self.properties:
return True
try:
return_type = self._obj.__annotations__["return"]
except (AttributeError, KeyError):
return False
return "MaybeAwaitable" in str(return_type)
class _AwaitPrefixMixin:
"""Replaces the ``async`` keyword prefix with a linked ``await``."""
def get_signature_prefix(self, sig: str) -> Sequence[nodes.Node]:
prefix = []
for node in super().get_signature_prefix(sig):
if isinstance(node, desc_sig_keyword) and node.astext() == "async":
node = type_to_xref("await", self.env, suppress_prefix=True)
prefix.append(node)
return prefix
class PybricksPyFunction(_AwaitPrefixMixin, PyFunction):
pass
class PybricksPyMethod(_AwaitPrefixMixin, PyMethod):
pass
def setup(app: Sphinx):
_FunctionDefProperties.is_async = property(_is_async)
app.add_directive_to_domain("py", "function", PybricksPyFunction, override=True)
app.add_directive_to_domain("py", "method", PybricksPyMethod, override=True)
return {"parallel_read_safe": True}
+3 -2
View File
@@ -1,7 +1,8 @@
from docutils.parsers.rst import Directive
from docutils import nodes
from pathlib import Path
from docutils import nodes
from docutils.parsers.rst import Directive
SPHINX_IMAGE_PATH = "blockimg"
+1 -2
View File
@@ -3,7 +3,6 @@ from docutils.parsers.rst import Directive
class PybricksClasslinkDirective(Directive):
required_arguments = 1
optional_arguments = 1
@@ -13,7 +12,7 @@ class PybricksClasslinkDirective(Directive):
link = name if len(self.arguments) == 1 else self.arguments[1]
html = (
'<a href="{0}.html">'.format(link.lower())
f'<a href="{link.lower()}.html">'
+ '<dl class="py class">'
+ "<dt>"
+ '<em class="property">class </em>'
+6 -7
View File
@@ -1,11 +1,12 @@
from colorsys import hsv_to_rgb
from docutils import nodes
from docutils.parsers.rst import Directive
from pybricks.parameters import Color
from colorsys import hsv_to_rgb
class PybricksColorDirective(Directive):
required_arguments = 1
def run(self):
@@ -19,19 +20,17 @@ class PybricksColorDirective(Directive):
r, g, b = hsv_to_rgb(color.h / 360, color.s / 100, color.v / 100)
# Convert RGB to HEX
rgbhex = "#{0:02x}{1:02x}{2:02x}".format(
round(r * 255), round(g * 255), round(b * 255)
)
rgbhex = f"#{round(r * 255):02x}{round(g * 255):02x}{round(b * 255):02x}"
# Render a small block of the given color
css = "background-color: {0}; color: {0}; width: 50px;".format(rgbhex)
css = f"background-color: {rgbhex}; color: {rgbhex}; width: 50px;"
if name == "WHITE":
css += (
"border-style: solid; border-width: 0.5px;" + "border-color: #666666;"
)
html = '<div id="test" style="{0}">_</div>'.format(css)
html = f'<div id="test" style="{css}">_</div>'
# Return the node
node = nodes.raw("", html, format="html")
@@ -0,0 +1,51 @@
"""Make explicit docstring signatures win over ``@overload`` signatures.
Workaround for https://github.com/sphinx-doc/sphinx/issues/10436: when a
function or method has overloads, autodoc unconditionally replaces the
signature(s) found in the docstring with the overload signatures. Classes
already behave correctly, so this only patches the function/method path. There
is no event hook for this in autodoc's new (Sphinx 9) pipeline, so
``_format_signatures`` is wrapped: when a docstring signature is present,
``autodoc_typehints`` is set to ``'none'`` for that single call, which
disables only the overload substitution branch.
"""
from sphinx.application import Sphinx
from sphinx.ext.autodoc._dynamic import _loader, _signatures
from sphinx.ext.autodoc._shared import _AutodocConfig
_orig_format_signatures = _signatures._format_signatures
def _format_signatures(**kwargs):
config: _AutodocConfig = kwargs["config"]
docstrings = kwargs.get("docstrings")
options = kwargs["options"]
props = kwargs["props"]
if (
kwargs.get("args") is None
and docstrings
and config.autodoc_docstring_signature
and config.autodoc_typehints != "none"
and props.obj_type in {"function", "method", "decorator"}
):
# Probe on a copy: extraction strips signature lines from docstrings.
docstring_signatures = _signatures._extract_signatures_from_docstrings(
[list(lines) for lines in docstrings],
props=props,
tab_width=options._tab_width,
)
if docstring_signatures:
values = {name: getattr(config, name) for name in _AutodocConfig.__slots__}
values["autodoc_typehints"] = "none"
kwargs["config"] = _AutodocConfig(**values)
return _orig_format_signatures(**kwargs)
def setup(app: Sphinx):
_signatures._format_signatures = _format_signatures
_loader._format_signatures = _format_signatures
return {"parallel_read_safe": True}
+41
View File
@@ -0,0 +1,41 @@
"""Provides the ``autonestedmethod`` directive.
Like ``automethod``, but resolves dotted names such as ``control.limits``
relative to the class documented by the enclosing ``autoclass`` directive.
Plain ``automethod`` treats everything before the last dot as a module/class
path, so ``control.limits`` would be looked up as an attribute of the current
*module* instead of the current class. Resolving the class here keeps shared
include fragments module-neutral.
"""
from sphinx.util import logging
from sphinx.util.docutils import SphinxDirective
logger = logging.getLogger(__name__)
class AutoNestedMethodDirective(SphinxDirective):
required_arguments = 1
has_content = False
def run(self):
current = self.env.current_document
module = current.autodoc_module or self.env.ref_context.get("py:module")
cls = current.autodoc_class or self.env.ref_context.get("py:class")
if not module or not cls:
logger.warning(
"autonestedmethod:: %s used outside of an autoclass context",
self.arguments[0],
location=self.get_location(),
)
return []
return self.parse_text_to_nodes(
f".. automethod:: {module}::{cls}.{self.arguments[0]}"
)
def setup(app):
app.add_directive("autonestedmethod", AutoNestedMethodDirective)
return {"parallel_read_safe": True}
+27 -19
View File
@@ -1,8 +1,7 @@
from os import path, makedirs
from os import makedirs, path
from docutils import nodes
from docutils.parsers.rst import Directive
from sphinx.util.osutil import copyfile
# Base feature set.
@@ -17,35 +16,44 @@ FEATURES_MEDIUM = FEATURES_SMALL | {
"pybricks-frozen",
}
# Large feature set.
FEATURES_LARGE = FEATURES_MEDIUM | {
"ble-extra", # Extra features such as pairing or multiple connections.
}
# Features per hub.
HUB_FEATURES = {
"movehub": {"movehub", "pup"} | FEATURES_SMALL,
"cityhub": {"cityhub", "pup"} | FEATURES_MEDIUM,
"technichub": {"technichub", "gyro", "xbox-controller", "pup"} | FEATURES_MEDIUM,
"movehub": {"movehub", "ble", "pupdevices"} | FEATURES_SMALL,
"cityhub": {"cityhub", "ble", "pupdevices"} | FEATURES_MEDIUM,
"technichub": {"technichub", "gyro", "xbox-controller", "ble", "pupdevices"}
| FEATURES_MEDIUM,
"primehub": {
"primehub",
"inventorhub",
"light-matrix",
"gyro",
"xbox-controller",
"pup",
"ble",
"ble-extra",
"pupdevices",
}
| FEATURES_LARGE,
| FEATURES_MEDIUM,
"inventorhub": {
"primehub",
"inventorhub",
"light-matrix",
"gyro",
"xbox-controller",
"pup",
"ble",
"ble-extra",
"pupdevices",
}
| FEATURES_LARGE,
"essentialhub": {"essentialhub", "gyro", "xbox-controller", "pup"} | FEATURES_LARGE,
| FEATURES_MEDIUM,
"essentialhub": {
"essentialhub",
"gyro",
"xbox-controller",
"ble",
"ble-extra",
"pupdevices",
}
| FEATURES_MEDIUM,
"ev3brick": {"ev3devices", "nxtdevices", "image"} | FEATURES_MEDIUM,
}
@@ -63,7 +71,7 @@ class PybricksRequirementsStaticDirective(Directive):
makedirs(destdir)
for hub in HUB_FEATURES:
uri = "compat_{0}.png".format(hub)
uri = f"compat_{hub}.png"
src_uri = path.join(env.app.builder.srcdir, "diagrams", uri)
build_uri = path.join(env.app.builder.outdir, "_images", uri)
copyfile(src_uri, build_uri)
@@ -94,17 +102,17 @@ class PybricksRequirementsStaticDirective(Directive):
)
# Generate full table.
html = """
html = f"""
<div class="wy-table-responsive">
<table class="docutils align-default requirements-table">
<tbody>
<tr>
{0}
{compat_row}
</tr>
</tbody>
</table>
</div>
""".format(compat_row)
"""
# Return the node.
node = nodes.raw("", html, format="html")
+7 -6
View File
@@ -22,12 +22,13 @@
import os
from docutils.parsers.rst import Directive, directives
from docutils import nodes
from docutils.statemachine import StringList
from sphinx.util.osutil import copyfile
from sphinx.util import logging
from typing import ClassVar
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.statemachine import StringList
from sphinx.util import logging
from sphinx.util.osutil import copyfile
CSS_FILE = "requirements.css"
JS_FILE = "requirements.js"
@@ -35,7 +36,7 @@ JS_FILE = "requirements.js"
class PybricksRequirementsDirective(Directive):
has_content = True
option_spec = {"header": directives.unchanged}
option_spec: ClassVar = {"header": directives.unchanged}
required_arguments = 0
optional_arguments = 10
+2 -2
View File
@@ -4,12 +4,12 @@
* deprecated
when building documentation with the 'ide' tag.
"""
from docutils import nodes
from docutils.parsers.rst import Directive
class PybricksVersionDirective(Directive):
has_content = True
def run(self):
@@ -19,7 +19,7 @@ class PybricksVersionDirective(Directive):
def setup(app):
if "ide" in app.tags.tags:
if app.tags.has("ide"):
app.add_directive_to_domain(
"py", "deprecated", PybricksVersionDirective, override=True
)
+124
View File
@@ -0,0 +1,124 @@
.. rubric:: Measuring
.. blockimg:: pybricks_blockMotorMeasure_motor_angle
.. automethod:: angle
.. blockimg:: pybricks_blockMotorResetAngle
.. automethod:: reset_angle
.. blockimg:: pybricks_blockMotorMeasure_motor_speed
.. blockimg:: pybricks_blockMotorMeasure_motor_get_speed_average
.. automethod:: speed
.. blockimg:: pybricks_blockMotorMeasure_motor_load
.. automethod:: load
.. blockimg:: pybricks_blockMotorMeasure_motor_stalled
.. automethod:: stalled
.. rubric:: Stopping
.. blockimg:: pybricks_blockMotorStop_Motor_coast
.. automethod:: stop
.. blockimg:: pybricks_blockMotorStop_Motor_brake
.. automethod:: brake
.. blockimg:: pybricks_blockMotorStop_Motor_hold
.. automethod:: hold
.. rubric:: Running forever
.. blockimg:: pybricks_blockMotorRun_run
.. automethod:: run
.. blockimg:: pybricks_blockMotorDuty_Motor
.. automethod:: dc
.. rubric:: Running by a fixed amount
.. automethod:: run_time
.. blockimg:: pybricks_blockMotorRun_run_angle
.. automethod:: run_angle
.. blockimg:: pybricks_blockMotorRun_run_target
.. automethod:: run_target
.. blockimg:: pybricks_blockMotorRun_run_until_stalled
.. automethod:: run_until_stalled
.. blockimg:: pybricks_blockMotorTrack
.. automethod:: track_target
.. automethod:: done
.. rubric:: Motor settings
.. blockimg:: pybricks_blockMotorConfigure_motor_max_voltage
.. automethod:: settings
.. automethod:: close
.. rubric:: Control settings
.. pybricks-requirements:: pybricks-common-control
.. blockimg:: pybricks_blockMotorConfigure_motor_max_speed
.. blockimg:: pybricks_blockMotorConfigure_motor_acceleration
.. blockimg:: pybricks_blockMotorConfigure_motor_max_torque
.. autonestedmethod:: control.limits
.. pybricks-requirements:: pybricks-common-control
.. autonestedmethod:: control.pid
.. pybricks-requirements:: pybricks-common-control
.. blockimg:: pybricks_blockMotorConfigure_motor_target_tolerances
.. autonestedmethod:: control.target_tolerances
.. pybricks-requirements:: pybricks-common-control
.. autonestedmethod:: control.stall_tolerances
.. pybricks-requirements:: pybricks-common-control
.. attribute:: control.scale
Number of degrees that the motor turns to complete one degree at the
output of the gear train. This is the gear ratio determined from the
``gears`` argument when initializing the motor.
.. versionchanged:: 3.2
The :meth:`done`, :meth:`stalled` and :meth:`load` methods have been
moved.
.. pybricks-requirements:: pybricks-common-control
.. autonestedmethod:: model.state
.. pybricks-requirements:: pybricks-common-control
.. autonestedmethod:: model.settings
+6 -20
View File
@@ -1,5 +1,3 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Pybricks documentation build configuration file
#
@@ -8,17 +6,15 @@ import sys
# General information about the project.
project = "pybricks"
copyright = "2018-2023 The Pybricks Authors"
copyright = "2018-2026 The Pybricks Authors"
author = ""
_TITLE = "Pybricks Modules and Examples"
_DISCLAIMER = "LEGO, the LEGO logo, MINDSTORMS and the MINDSTORMS EV3 logo are\
trademarks and/or copyrights of the LEGO Group of companies \
which does not sponsor, authorize or endorse this site."
html_favicon = "../common/images/favicon.ico"
html_logo = "../common/images/pybricks-logo-rtd.png"
latex_logo = "../common/images/pybricks-logo-large.png"
# Build main docs for RTD by default.
# Since tags cannot be passed via the TAG make variable on read the docs,
@@ -29,29 +25,19 @@ if os.environ.get("READTHEDOCS", None) == "True":
# HACK: this allows Number type alias to be imported by Sphinx
os.environ["SPHINX_BUILD"] = "True"
html_css_files = ["css/blocks.css"]
html_css_files = ["css/theme_overrides.css", "css/blocks.css"]
# Additional configuration of the IDE docs
if "ide" in tags.tags: # noqa F821
if tags.has("ide"): # noqa F821
_DISCLAIMER = ""
html_show_copyright = False
html_show_sphinx = False
html_css_files.append("css/ide.css")
html_js_files = ["js/ide.js"]
imgmath_image_format = "svg"
imgmath_use_preview = True # requires Sphinx v3
imgmath_latex_preamble = r"""
\usepackage{newtxsf}
"""
exec(open(os.path.abspath("../common/conf.py")).read())
# Additional configuration of the IDE docs
if "ide" in tags.tags: # noqa F821
extensions.remove("sphinx.ext.mathjax") # noqa F821
extensions.append("sphinx.ext.imgmath") # noqa F821
html_theme_options["prev_next_buttons_location"] = None # noqa F821
# Shared config must run in this namespace so it sees the globals above.
with open(os.path.abspath("../common/conf.py")) as _f:
exec(_f.read()) # noqa: S102
# Build hub specific example scripts.
sys.path.append(os.path.abspath("../../examples/pup/hub_common"))
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

-134
View File
@@ -1,134 +0,0 @@
:mod:`ev3devices <pybricks.ev3devices>` -- EV3 devices
======================================================
.. automodule:: pybricks.ev3devices
:no-members:
Motors
^^^^^^^^^^^^
.. _fig_ev3motors:
.. figure:: ../main/diagrams/ev3motors.png
:width: 100 %
EV3-compatible motors. The arrows indicate the default positive direction.
.. autoclass:: pybricks.ev3devices.Motor
:noindex:
:no-members:
.. rubric:: Measuring
.. automethod:: pybricks.ev3devices.Motor.angle
.. automethod:: pybricks.ev3devices.Motor.reset_angle
.. automethod:: pybricks.ev3devices.Motor.speed
.. automethod:: pybricks.ev3devices.Motor.load
.. automethod:: pybricks.ev3devices.Motor.stalled
.. rubric:: Stopping
.. automethod:: pybricks.ev3devices.Motor.stop
.. automethod:: pybricks.ev3devices.Motor.brake
.. automethod:: pybricks.ev3devices.Motor.hold
.. rubric:: Running forever
.. automethod:: pybricks.ev3devices.Motor.run
.. automethod:: pybricks.ev3devices.Motor.dc
.. rubric:: Running by a fixed amount
.. automethod:: pybricks.ev3devices.Motor.run_time
.. automethod:: pybricks.ev3devices.Motor.run_angle
.. automethod:: pybricks.ev3devices.Motor.run_target
.. automethod:: pybricks.ev3devices.Motor.track_target
.. automethod:: pybricks.ev3devices.Motor.run_until_stalled
.. automethod:: pybricks.ev3devices.Motor.done
.. rubric:: Motor settings
.. automethod:: pybricks.ev3devices.Motor.settings
.. rubric:: Control settings
.. automethod:: pybricks.ev3devices::Motor.control.limits
.. automethod:: pybricks.ev3devices::Motor.control.pid
.. automethod:: pybricks.ev3devices::Motor.control.target_tolerances
.. automethod:: pybricks.ev3devices::Motor.control.stall_tolerances
.. attribute:: control.scale
Number of degrees that the motor turns to complete one degree at the
output of the gear train. This is the gear ratio determined from the
``gears`` argument when initializing the motor.
Touch Sensor
^^^^^^^^^^^^
.. figure:: ../main/cad/output/ev3device-touch.png
:width: 18 %
.. autoclass:: pybricks.ev3devices.TouchSensor
Color Sensor
^^^^^^^^^^^^
.. figure:: ../main/cad/output/ev3device-color.png
:width: 18 %
.. autoclass:: pybricks.ev3devices.ColorSensor
Infrared Sensor and Beacon
^^^^^^^^^^^^^^^^^^^^^^^^^^
Each method of this class puts the sensor in a different *mode*. Switching
modes takes about one second on this sensor. To make sure that your program
runs quickly, use only of these methods in your program.
.. figure:: ../main/cad/output/ev3device-infrared.png
:width: 60 %
.. autoclass:: pybricks.ev3devices.InfraredSensor
Ultrasonic Sensor
^^^^^^^^^^^^^^^^^
.. figure:: ../main/cad/output/ev3device-ultrasonic.png
:width: 22 %
.. autoclass:: pybricks.ev3devices.UltrasonicSensor
Gyroscopic Sensor
^^^^^^^^^^^^^^^^^
.. figure:: ../main/cad/output/ev3device-gyro.png
:width: 18 %
.. autoclass:: pybricks.ev3devices.GyroSensor
:no-members:
.. automethod:: pybricks.ev3devices.GyroSensor.speed
.. automethod:: pybricks.ev3devices.GyroSensor.angle
If you use the :meth:`.angle` method, you cannot use the
:meth:`.speed` method in the same program. Doing so would reset the
sensor angle to zero every time you read the speed.
.. automethod:: pybricks.ev3devices.GyroSensor.reset_angle
+9
View File
@@ -0,0 +1,9 @@
.. pybricks-requirements:: ev3devices
Color Sensor
^^^^^^^^^^^^^^^^^^^^^^^^^
.. figure:: ../../main/cad/output/ev3device-color.png
:width: 18 %
.. autoclass:: pybricks.ev3devices.ColorSensor
+16
View File
@@ -0,0 +1,16 @@
.. pybricks-requirements:: ev3devices
Gyroscopic Sensor
^^^^^^^^^^^^^^^^^
.. figure:: ../../main/cad/output/ev3device-gyro.png
:width: 18 %
.. autoclass:: pybricks.ev3devices.GyroSensor
:no-members:
.. automethod:: pybricks.ev3devices.GyroSensor.speed
.. automethod:: pybricks.ev3devices.GyroSensor.angle
.. automethod:: pybricks.ev3devices.GyroSensor.reset_angle
+54
View File
@@ -0,0 +1,54 @@
.. pybricks-requirements:: ev3devices
:mod:`ev3devices <pybricks.ev3devices>` -- EV3 motors and sensors
=================================================================
.. automodule:: pybricks.ev3devices
:no-members:
.. toctree::
:maxdepth: 1
:hidden:
motor
touchsensor
colorsensor
infraredsensor
ultrasonicsensor
gyrosensor
.. pybricks-classlink:: Motor ../ev3devices/motor
.. figure:: ../../main/cad/output/ev3device-motors.png
:width: 100 %
:target: ../ev3devices/motor.html
.. pybricks-classlink:: TouchSensor
.. figure:: ../../main/cad/output/ev3device-touch.png
:width: 18 %
:target: touchsensor.html
.. pybricks-classlink:: ColorSensor
.. figure:: ../../main/cad/output/ev3device-color.png
:width: 18 %
:target: colorsensor.html
.. pybricks-classlink:: InfraredSensor
.. figure:: ../../main/cad/output/ev3device-infrared.png
:width: 60 %
:target: infraredsensor.html
.. pybricks-classlink:: UltrasonicSensor
.. figure:: ../../main/cad/output/ev3device-ultrasonic.png
:width: 22 %
:target: ultrasonicsensor.html
.. pybricks-classlink:: GyroSensor
.. figure:: ../../main/cad/output/ev3device-gyro.png
:width: 18 %
:target: gyrosensor.html
+13
View File
@@ -0,0 +1,13 @@
.. pybricks-requirements:: ev3devices
Infrared Sensor and Beacon
^^^^^^^^^^^^^^^^^^^^^^^^^^
Each method of this class puts the sensor in a different *mode*. Switching
modes takes about one second on this sensor. To make sure that your program
runs quickly, use only one of these methods in your program.
.. figure:: ../../main/cad/output/ev3device-infrared.png
:width: 60 %
.. autoclass:: pybricks.ev3devices.InfraredSensor
+21
View File
@@ -0,0 +1,21 @@
.. pybricks-requirements:: ev3devices
Motors with rotation sensors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. _fig_ev3motors:
.. figure:: ../../main/diagrams/ev3motors.png
:width: 100 %
:alt: ev3motors
EV3 and NXT motors with rotation sensors. The arrows indicate the default
positive direction.
.. blockimg:: pybricks_variables_set_motor
.. autoclass:: pybricks.ev3devices.Motor
:no-members:
:no-index:
.. include:: ../common/motor_members.rst.txt
+9
View File
@@ -0,0 +1,9 @@
.. pybricks-requirements:: ev3devices
Touch Sensor
^^^^^^^^^^^^^^^^^^^^^^^^^
.. figure:: ../../main/cad/output/ev3device-touch.png
:width: 18 %
.. autoclass:: pybricks.ev3devices.TouchSensor
+9
View File
@@ -0,0 +1,9 @@
.. pybricks-requirements:: ev3devices
Ultrasonic Sensor
^^^^^^^^^^^^^^^^^
.. figure:: ../../main/cad/output/ev3device-ultrasonic.png
:width: 22 %
.. autoclass:: pybricks.ev3devices.UltrasonicSensor
+9 -125
View File
@@ -1,4 +1,4 @@
MINDSTORMS EV3 Brick
EV3 Brick
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. figure:: ../../main/cad/output/ev3device-ev3.png
@@ -17,20 +17,18 @@ MINDSTORMS EV3 Brick
.. automethod:: pybricks.hubs::EV3Brick.light.off
.. automethod:: pybricks.hubs::EV3Brick.light.blink
.. automethod:: pybricks.hubs::EV3Brick.light.animate
.. rubric:: Using the speaker
.. automethod:: pybricks.hubs::EV3Brick.speaker.volume
.. automethod:: pybricks.hubs::EV3Brick.speaker.beep
.. automethod:: pybricks.hubs::EV3Brick.speaker.play_notes
.. automethod:: pybricks.hubs::EV3Brick.speaker.play_file
.. automethod:: pybricks.hubs::EV3Brick.speaker.say
.. automethod:: pybricks.hubs::EV3Brick.speaker.set_speech_options
.. automethod:: pybricks.hubs::EV3Brick.speaker.set_volume
.. rubric:: Using the screen
.. |this image| replace:: the screen
@@ -60,10 +58,10 @@ MINDSTORMS EV3 Brick
.. automethod:: pybricks.hubs::EV3Brick.screen.draw_circle
.. autoattribute:: pybricks.hubs::EV3Brick.screen.width
:annotation: = 178
.. autoattribute:: pybricks.hubs::EV3Brick.screen.height
.. automethod:: pybricks.hubs::EV3Brick.screen.save
:annotation: = 128
.. rubric:: Using the battery
@@ -83,122 +81,8 @@ Turn the light on and change the color
Screen examples
---------------------
Show an image on the screen
***************************
.. literalinclude::
../../../examples/ev3/screen_image/main.py
Drawing shapes on the screen
****************************
.. literalinclude::
../../../examples/ev3/screen_draw/main.py
Using different fonts
*********************
.. raw:: latex
\begin{CJK}{UTF8}{gbsn}
.. literalinclude::
../../../examples/ev3/screen_print/main.py
.. raw:: latex
\end{CJK}
.. rubric:: Available languages and voices for speech
.. [#espeak_lang]
You can choose the following languages:
- ``'af'``: Afrikaans
- ``'an'``: Aragonese
- ``'bg'``: Bulgarian
- ``'bs'``: Bosnian
- ``'ca'``: Catalan
- ``'cs'``: Czech
- ``'cy'``: Welsh
- ``'da'``: Danish
- ``'de'``: German
- ``'el'``: Greek
- ``'en'``: English (default)
- ``'en-gb'``: English (United Kingdom)
- ``'en-sc'``: English (Scotland)
- ``'en-uk-north'``: English (United Kingdom, Northern)
- ``'en-uk-rp'``: English (United Kingdom, Received Pronunciation)
- ``'en-uk-wmids'``: English (United Kingdom, West Midlands)
- ``'en-us'``: English (United States)
- ``'en-wi'``: English (West Indies)
- ``'eo'``: Esperanto
- ``'es'``: Spanish
- ``'es-la'``: Spanish (Latin America)
- ``'et'``: Estonian
- ``'fa'``: Persian
- ``'fa-pin'``: Persian
- ``'fi'``: Finnish
- ``'fr-be'``: French (Belgium)
- ``'fr-fr'``: French (France)
- ``'ga'``: Irish
- ``'grc'``: Greek
- ``'hi'``: Hindi
- ``'hr'``: Croatian
- ``'hu'``: Hungarian
- ``'hy'``: Armenian
- ``'hy-west'``: Armenian (Western)
- ``'id'``: Indonesian
- ``'is'``: Icelandic
- ``'it'``: Italian
- ``'jbo'``: Lojban
- ``'ka'``: Georgian
- ``'kn'``: Kannada
- ``'ku'``: Kurdish
- ``'la'``: Latin
- ``'lfn'``: Lingua Franca Nova
- ``'lt'``: Lithuanian
- ``'lv'``: Latvian
- ``'mk'``: Macedonian
- ``'ml'``: Malayalam
- ``'ms'``: Malay
- ``'ne'``: Nepali
- ``'nl'``: Dutch
- ``'no'``: Norwegian
- ``'pa'``: Punjabi
- ``'pl'``: Polish
- ``'pt-br'``: Portuguese (Brazil)
- ``'pt-pt'``: Portuguese (Portugal)
- ``'ro'``: Romanian
- ``'ru'``: Russian
- ``'sk'``: Slovak
- ``'sq'``: Albanian
- ``'sr'``: Serbian
- ``'sv'``: Swedish
- ``'sw'``: Swahili
- ``'ta'``: Tamil
- ``'tr'``: Turkish
- ``'vi'``: Vietnamese
- ``'vi-hue'``: Vietnamese (Hue)
- ``'vi-sgn'``: Vietnamese (Saigon)
- ``'zh'``: Mandarin Chinese
- ``'zh-yue'``: Cantonese Chinese
You can choose the following voices:
- ``'f1'``: female variant 1
- ``'f2'``: female variant 2
- ``'f3'``: female variant 3
- ``'f4'``: female variant 4
- ``'f5'``: female variant 5
- ``'m1'``: male variant 1
- ``'m2'``: male variant 2
- ``'m3'``: male variant 3
- ``'m4'``: male variant 4
- ``'m5'``: male variant 5
- ``'m6'``: male variant 6
- ``'m7'``: male variant 7
- ``'croak'``: croak
- ``'whisper'``: whisper
- ``'whisperf'``: female whisper
+9
View File
@@ -14,6 +14,7 @@
technichub
primehub
essentialhub
ev3brick
.. pybricks-classlink:: MoveHub
@@ -50,3 +51,11 @@
.. figure:: ../../main/cad/output/hub-essential.png
:width: 25%
:target: essentialhub.html
.. pybricks-classlink:: EV3Brick
.. figure:: ../../main/cad/output/ev3device-ev3.png
:width: 25%
:target: ev3brick.html
+8
View File
@@ -54,6 +54,12 @@ above to reveal this menu.
:width: 70 %
:target: pupdevices/dcmotor.html
.. rubric:: EV3 motors and sensors
.. figure:: ../main/cad/output/ev3device-all.png
:width: 100 %
:target: ev3devices/index.html
.. toctree::
:maxdepth: 1
:caption: Table of contents
@@ -66,6 +72,8 @@ above to reveal this menu.
hubs/index
pupdevices/index
ev3devices/index
nxtdevices/index
iodevices/index
parameters/index
tools/index
+4 -4
View File
@@ -41,7 +41,7 @@ LEGO protocol devices
:width: 80 %
:target: lwp3device.html
.. pybricks-requirements:: ev3 pybricks-iodevices
.. pybricks-requirements:: pybricks-iodevices
.. pybricks-classlink:: LUMPDevice
@@ -83,7 +83,7 @@ Generic protocols
|uart-wired| |uart-wireless|
.. pybricks-requirements:: ev3 pybricks-iodevices
.. pybricks-requirements:: pybricks-iodevices
.. pybricks-classlink:: I2CDevice
@@ -91,7 +91,7 @@ Generic protocols
:width: 20 %
:target: i2cdevice.html
.. pybricks-requirements:: ev3 pybricks-iodevices
.. pybricks-requirements:: pybricks-iodevices
.. pybricks-classlink:: AnalogSensor
@@ -99,7 +99,7 @@ Generic protocols
:width: 20 %
:target: analogsensor.html
.. pybricks-requirements:: ev3 pybricks-iodevices
.. pybricks-requirements:: pybricks-iodevices
.. pybricks-classlink:: DCMotor
-1679
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -4,7 +4,7 @@
.. automodule:: pybricks.messaging
:no-members:
.. pybricks-requirements:: pup
.. pybricks-requirements:: ble
.. blockimg:: pybricks_variables_set_ble_radio
-101
View File
@@ -1,101 +0,0 @@
:mod:`nxtdevices <pybricks.nxtdevices>` -- NXT devices
======================================================
.. automodule:: pybricks.nxtdevices
:no-members:
NXT Motor
^^^^^^^^^^^^^^^^
This motor works just like a LEGO MINDSTORMS EV3 Large Motor. You can use it in
your programs using the :mod:`Motor <.ev3devices>` class.
NXT Touch Sensor
^^^^^^^^^^^^^^^^
.. figure:: ../main/cad/output/nxtdevice-touch.png
:width: 18 %
.. autoclass:: pybricks.nxtdevices.TouchSensor
:no-members:
.. automethod:: pybricks.nxtdevices.TouchSensor.pressed
NXT Light Sensor
^^^^^^^^^^^^^^^^
.. figure:: ../main/cad/output/nxtdevice-light.png
:width: 18 %
.. autoclass:: pybricks.nxtdevices.LightSensor
NXT Color Sensor
^^^^^^^^^^^^^^^^
.. figure:: ../main/cad/output/nxtdevice-color.png
:width: 18 %
.. autoclass:: pybricks.nxtdevices.ColorSensor
:no-members:
.. automethod:: pybricks.nxtdevices.ColorSensor.color
.. automethod:: pybricks.nxtdevices.ColorSensor.ambient
.. automethod:: pybricks.nxtdevices.ColorSensor.reflection
.. automethod:: pybricks.nxtdevices.ColorSensor.rgb
.. rubric:: Advanced color sensing
.. automethod:: pybricks.nxtdevices.ColorSensor.hsv
.. automethod:: pybricks.nxtdevices.ColorSensor.detectable_colors
.. rubric:: Built-in light
This sensor has a built-in light. You can make it red, green, blue, or turn
it off.
.. automethod:: pybricks.nxtdevices::ColorSensor.light.on
.. automethod:: pybricks.nxtdevices::ColorSensor.light.off
NXT Ultrasonic Sensor
^^^^^^^^^^^^^^^^^^^^^
.. figure:: ../main/cad/output/nxtdevice-ultrasonic.png
:width: 24 %
.. autoclass:: pybricks.nxtdevices.UltrasonicSensor
NXT Sound Sensor
^^^^^^^^^^^^^^^^^^^^^
.. figure:: ../main/cad/output/nxtdevice-sound.png
:width: 18 %
.. autoclass:: pybricks.nxtdevices.SoundSensor
NXT Temperature Sensor
^^^^^^^^^^^^^^^^^^^^^^
.. figure:: ../main/cad/output/nxtdevice-temperature.png
:width: 32 %
.. autoclass:: pybricks.nxtdevices.TemperatureSensor
NXT Energy Meter
^^^^^^^^^^^^^^^^^
.. figure:: ../main/cad/output/nxtdevice-energy.png
:width: 30 %
.. autoclass:: pybricks.nxtdevices.EnergyMeter
Vernier Adapter
^^^^^^^^^^^^^^^^^
.. autoclass:: pybricks.nxtdevices.VernierAdapter
**Example: Using the Surface Temperature Sensor.**
.. literalinclude:: ../../examples/ev3/vernier_surface_temperature/main.py
+33
View File
@@ -0,0 +1,33 @@
.. pybricks-requirements:: nxtdevices
NXT Color Sensor
^^^^^^^^^^^^^^^^
.. figure:: ../../main/cad/output/nxtdevice-color.png
:width: 18 %
.. autoclass:: pybricks.nxtdevices.ColorSensor
:no-members:
.. automethod:: pybricks.nxtdevices.ColorSensor.color
.. automethod:: pybricks.nxtdevices.ColorSensor.ambient
.. automethod:: pybricks.nxtdevices.ColorSensor.reflection
.. automethod:: pybricks.nxtdevices.ColorSensor.rgb
.. rubric:: Advanced color sensing
.. automethod:: pybricks.nxtdevices.ColorSensor.hsv
.. automethod:: pybricks.nxtdevices.ColorSensor.detectable_colors
.. rubric:: Built-in light
This sensor has a built-in light. You can make it red, green, blue, or turn
it off.
.. automethod:: pybricks.nxtdevices::ColorSensor.light.on
.. automethod:: pybricks.nxtdevices::ColorSensor.light.off
+9
View File
@@ -0,0 +1,9 @@
.. pybricks-requirements:: nxtdevices
NXT Energy Meter
^^^^^^^^^^^^^^^^
.. figure:: ../../main/cad/output/nxtdevice-energy.png
:width: 30 %
.. autoclass:: pybricks.nxtdevices.EnergyMeter
+71
View File
@@ -0,0 +1,71 @@
.. pybricks-requirements:: nxtdevices
:mod:`nxtdevices <pybricks.nxtdevices>` -- NXT motors and sensors
=================================================================
.. automodule:: pybricks.nxtdevices
:no-members:
.. toctree::
:maxdepth: 1
:hidden:
motor
touchsensor
lightsensor
colorsensor
ultrasonicsensor
soundsensor
temperaturesensor
energymeter
vernieradapter
.. pybricks-classlink:: Motor ../nxtdevices/motor
.. figure:: ../../main/cad/output/ev3device-motors.png
:width: 100 %
:target: ../nxtdevices/motor.html
.. pybricks-classlink:: TouchSensor
.. figure:: ../../main/cad/output/nxtdevice-touch.png
:width: 18 %
:target: touchsensor.html
.. pybricks-classlink:: LightSensor
.. figure:: ../../main/cad/output/nxtdevice-light.png
:width: 18 %
:target: lightsensor.html
.. pybricks-classlink:: ColorSensor
.. figure:: ../../main/cad/output/nxtdevice-color.png
:width: 18 %
:target: colorsensor.html
.. pybricks-classlink:: UltrasonicSensor
.. figure:: ../../main/cad/output/nxtdevice-ultrasonic.png
:width: 24 %
:target: ultrasonicsensor.html
.. pybricks-classlink:: SoundSensor
.. figure:: ../../main/cad/output/nxtdevice-sound.png
:width: 18 %
:target: soundsensor.html
.. pybricks-classlink:: TemperatureSensor
.. figure:: ../../main/cad/output/nxtdevice-temperature.png
:width: 32 %
:target: temperaturesensor.html
.. pybricks-classlink:: EnergyMeter
.. figure:: ../../main/cad/output/nxtdevice-energy.png
:width: 30 %
:target: energymeter.html
.. pybricks-classlink:: VernierAdapter
+9
View File
@@ -0,0 +1,9 @@
.. pybricks-requirements:: nxtdevices
NXT Light Sensor
^^^^^^^^^^^^^^^^
.. figure:: ../../main/cad/output/nxtdevice-light.png
:width: 18 %
.. autoclass:: pybricks.nxtdevices.LightSensor
+21
View File
@@ -0,0 +1,21 @@
.. pybricks-requirements:: ev3devices nxtdevices
Motors with rotation sensors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. _fig_nxtmotors:
.. figure:: ../../main/diagrams/ev3motors.png
:width: 100 %
:alt: ev3motors
EV3 and NXT motors with rotation sensors. The arrows indicate the default
positive direction.
.. blockimg:: pybricks_variables_set_motor
.. autoclass:: pybricks.nxtdevices.Motor
:no-members:
:no-index:
.. include:: ../common/motor_members.rst.txt
+9
View File
@@ -0,0 +1,9 @@
.. pybricks-requirements:: nxtdevices
NXT Sound Sensor
^^^^^^^^^^^^^^^^
.. figure:: ../../main/cad/output/nxtdevice-sound.png
:width: 18 %
.. autoclass:: pybricks.nxtdevices.SoundSensor
@@ -0,0 +1,9 @@
.. pybricks-requirements:: nxtdevices
NXT Temperature Sensor
^^^^^^^^^^^^^^^^^^^^^^
.. figure:: ../../main/cad/output/nxtdevice-temperature.png
:width: 32 %
.. autoclass:: pybricks.nxtdevices.TemperatureSensor
+12
View File
@@ -0,0 +1,12 @@
.. pybricks-requirements:: nxtdevices
NXT Touch Sensor
^^^^^^^^^^^^^^^^
.. figure:: ../../main/cad/output/nxtdevice-touch.png
:width: 18 %
.. autoclass:: pybricks.nxtdevices.TouchSensor
:no-members:
.. automethod:: pybricks.nxtdevices.TouchSensor.pressed
+9
View File
@@ -0,0 +1,9 @@
.. pybricks-requirements:: nxtdevices
NXT Ultrasonic Sensor
^^^^^^^^^^^^^^^^^^^^^
.. figure:: ../../main/cad/output/nxtdevice-ultrasonic.png
:width: 24 %
.. autoclass:: pybricks.nxtdevices.UltrasonicSensor
+15
View File
@@ -0,0 +1,15 @@
.. pybricks-requirements:: nxtdevices
Vernier Adapter
^^^^^^^^^^^^^^^
.. autoclass:: pybricks.nxtdevices.VernierAdapter
Examples
-------------------
Using the Surface Temperature Sensor
************************************
.. literalinclude::
../../../examples/ev3/vernier_surface_temperature/main.py
+31
View File
@@ -0,0 +1,31 @@
.. pybricks-requirements:: image
Font
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: pybricks.parameters.Font
:no-members:
.. autoattribute:: pybricks.parameters.Font.DEFAULT
:annotation:
.. autoattribute:: pybricks.parameters.Font.TERMINUS_16
:annotation:
.. autoattribute:: pybricks.parameters.Font.LIBERATIONSANS_14
:annotation:
.. autoattribute:: pybricks.parameters.Font.MONO_8X5_8
:annotation:
.. autoattribute:: pybricks.parameters.Font.family
.. autoattribute:: pybricks.parameters.Font.style
.. autoattribute:: pybricks.parameters.Font.width
.. autoattribute:: pybricks.parameters.Font.height
.. automethod:: pybricks.parameters.Font.text_width
.. automethod:: pybricks.parameters.Font.text_height
+59
View File
@@ -0,0 +1,59 @@
.. pybricks-requirements:: image
Image
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. |this image| replace:: this image
.. autoclass:: pybricks.parameters.Image
:no-members:
.. automethod:: pybricks.parameters.Image.empty
.. rubric:: Drawing text
There are two ways to draw text on images. :meth:`draw_text` lets text be
placed precisely on the image or :meth:`print` can be used to automatically
print text on a new line.
.. automethod:: pybricks.parameters.Image.draw_text
.. automethod:: pybricks.parameters.Image.print
.. automethod:: pybricks.parameters.Image.set_font
.. rubric:: Drawing images
A copy of another image can be drawn on an image. Also consider using
sub-images to copy part of an image.
.. automethod:: pybricks.parameters.Image.draw_image
.. rubric:: Drawing shapes
These are the methods to draw basic shapes, including points, lines,
rectangles and circles.
.. automethod:: pybricks.parameters.Image.draw_pixel
.. automethod:: pybricks.parameters.Image.draw_line
.. automethod:: pybricks.parameters.Image.draw_box
.. automethod:: pybricks.parameters.Image.draw_circle
.. rubric:: Image properties
.. autoattribute:: pybricks.parameters.Image.width
.. autoattribute:: pybricks.parameters.Image.height
.. rubric:: Replacing the entire image
.. automethod:: pybricks.parameters.Image.clear
.. automethod:: pybricks.parameters.Image.load_image
+209
View File
@@ -0,0 +1,209 @@
.. pybricks-requirements:: image
ImageFile
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Not all images are included in the firmware yet. This is a work in progress.
.. currentmodule:: pybricks.parameters
.. class:: ImageFile
.. rubric:: **Information**
.. data:: ACCEPT
.. image:: ../../../media/ev3dev-media/images/mono/information/accept.png
:width: 15 %
.. data:: BACKWARD
.. image:: ../../../media/ev3dev-media/images/mono/information/backward.png
:width: 15 %
.. data:: DECLINE
.. image:: ../../../media/ev3dev-media/images/mono/information/decline.png
:width: 15 %
.. data:: FORWARD
.. image:: ../../../media/ev3dev-media/images/mono/information/forward.png
:width: 15 %
.. data:: LEFT
.. image:: ../../../media/ev3dev-media/images/mono/information/left.png
:width: 15 %
.. data:: NO_GO
.. image:: ../../../media/ev3dev-media/images/mono/information/no_go.png
:width: 15 %
.. data:: QUESTION_MARK
.. image:: ../../../media/ev3dev-media/images/mono/information/question_mark.png
:width: 15 %
.. data:: RIGHT
.. image:: ../../../media/ev3dev-media/images/mono/information/right.png
:width: 15 %
.. data:: STOP_1
.. image:: ../../../media/ev3dev-media/images/mono/information/stop_1.png
:width: 15 %
.. data:: STOP_2
.. image:: ../../../media/ev3dev-media/images/mono/information/stop_2.png
:width: 15 %
.. data:: THUMBS_DOWN
.. image:: ../../../media/ev3dev-media/images/mono/information/thumbs_down.png
:width: 15 %
.. data:: THUMBS_UP
.. image:: ../../../media/ev3dev-media/images/mono/information/thumbs_up.png
:width: 15 %
.. data:: WARNING
.. image:: ../../../media/ev3dev-media/images/mono/information/warning.png
:width: 15 %
.. rubric:: **LEGO**
.. data:: EV3
.. image:: ../../../media/ev3dev-media/images/mono/lego/ev3.png
:width: 15 %
.. data:: EV3_ICON
.. image:: ../../../media/ev3dev-media/images/mono/lego/ev3_icon.png
:width: 15 %
.. rubric:: **Objects**
.. data:: TARGET
.. image:: ../../../media/ev3dev-media/images/mono/objects/target.png
:width: 15 %
.. rubric:: **Eyes**
.. data:: ANGRY
.. image:: ../../../media/ev3dev-media/images/mono/eyes/angry.png
:width: 15 %
.. data:: AWAKE
.. image:: ../../../media/ev3dev-media/images/mono/eyes/awake.png
:width: 15 %
.. data:: BOTTOM_LEFT
.. image:: ../../../media/ev3dev-media/images/mono/eyes/bottom_left.png
:width: 15 %
.. data:: BOTTOM_RIGHT
.. image:: ../../../media/ev3dev-media/images/mono/eyes/bottom_right.png
:width: 15 %
.. data:: CRAZY_1
.. image:: ../../../media/ev3dev-media/images/mono/eyes/crazy_1.png
:width: 15 %
.. data:: CRAZY_2
.. image:: ../../../media/ev3dev-media/images/mono/eyes/crazy_2.png
:width: 15 %
.. data:: DIZZY
.. image:: ../../../media/ev3dev-media/images/mono/eyes/dizzy.png
:width: 15 %
.. data:: DOWN
.. image:: ../../../media/ev3dev-media/images/mono/eyes/down.png
:width: 15 %
.. data:: EVIL
.. image:: ../../../media/ev3dev-media/images/mono/eyes/evil.png
:width: 15 %
.. data:: KNOCKED_OUT
.. image:: ../../../media/ev3dev-media/images/mono/eyes/knocked_out.png
:width: 15 %
.. data:: MIDDLE_LEFT
.. image:: ../../../media/ev3dev-media/images/mono/eyes/middle_left.png
:width: 15 %
.. data:: MIDDLE_RIGHT
.. image:: ../../../media/ev3dev-media/images/mono/eyes/middle_right.png
:width: 15 %
.. data:: NEUTRAL
.. image:: ../../../media/ev3dev-media/images/mono/eyes/neutral.png
:width: 15 %
.. data:: PINCHED_LEFT
.. image:: ../../../media/ev3dev-media/images/mono/eyes/pinched_left.png
:width: 15 %
.. data:: PINCHED_MIDDLE
.. image:: ../../../media/ev3dev-media/images/mono/eyes/pinched_middle.png
:width: 15 %
.. data:: PINCHED_RIGHT
.. image:: ../../../media/ev3dev-media/images/mono/eyes/pinched_right.png
:width: 15 %
.. data:: SLEEPING
.. image:: ../../../media/ev3dev-media/images/mono/eyes/sleeping.png
:width: 15 %
.. data:: TIRED_LEFT
.. image:: ../../../media/ev3dev-media/images/mono/eyes/tired_left.png
:width: 15 %
.. data:: TIRED_MIDDLE
.. image:: ../../../media/ev3dev-media/images/mono/eyes/tired_middle.png
:width: 15 %
.. data:: TIRED_RIGHT
.. image:: ../../../media/ev3dev-media/images/mono/eyes/tired_right.png
:width: 15 %
.. data:: UP
.. image:: ../../../media/ev3dev-media/images/mono/eyes/up.png
:width: 15 %
.. data:: WINKING
.. image:: ../../../media/ev3dev-media/images/mono/eyes/winking.png
:width: 15 %
+9
View File
@@ -14,7 +14,10 @@
button
color
direction
font
icon
image
imagefile
port
side
stop
@@ -27,8 +30,14 @@
.. pybricks-classlink:: Direction
.. pybricks-classlink:: Font
.. pybricks-classlink:: Icon
.. pybricks-classlink:: Image
.. pybricks-classlink:: ImageFile
.. pybricks-classlink:: Port
.. pybricks-classlink:: Side
+1 -1
View File
@@ -1,4 +1,4 @@
.. pybricks-requirements::
.. pybricks-requirements:: pupdevices
Color and Distance Sensor
^^^^^^^^^^^^^^^^^^^^^^^^^
+1 -1
View File
@@ -1,4 +1,4 @@
.. pybricks-requirements::
.. pybricks-requirements:: pupdevices
Color Light Matrix
^^^^^^^^^^^^^^^^^^
+1 -1
View File
@@ -1,4 +1,4 @@
.. pybricks-requirements::
.. pybricks-requirements:: pupdevices
Color Sensor
^^^^^^^^^^^^^^^^^^^^^^^^^
+1 -1
View File
@@ -1,4 +1,4 @@
.. pybricks-requirements::
.. pybricks-requirements:: pupdevices
Motors without rotation sensors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1 -1
View File
@@ -1,4 +1,4 @@
.. pybricks-requirements::
.. pybricks-requirements:: pupdevices
Force Sensor
^^^^^^^^^^^^^^^^^^^^^^^^^
+1 -1
View File
@@ -1,4 +1,4 @@
.. pybricks-requirements::
.. pybricks-requirements:: pupdevices
:mod:`pupdevices <pybricks.pupdevices>` -- Motors, sensors, lights
==================================================================
+1 -1
View File
@@ -1,4 +1,4 @@
.. pybricks-requirements::
.. pybricks-requirements:: pupdevices
Infrared Sensor
^^^^^^^^^^^^^^^^^^^^^^^^^
+1 -1
View File
@@ -1,4 +1,4 @@
.. pybricks-requirements::
.. pybricks-requirements:: pupdevices
Light
^^^^^^^^^^^^^^^^^^^^^^^^^
+2 -127
View File
@@ -1,4 +1,4 @@
.. pybricks-requirements::
.. pybricks-requirements:: pupdevices
Motors with rotation sensors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -18,132 +18,7 @@ Motors with rotation sensors
.. autoclass:: pybricks.pupdevices.Motor
:no-members:
.. rubric:: Measuring
.. blockimg:: pybricks_blockMotorMeasure_motor_angle
.. automethod:: pybricks.pupdevices.Motor.angle
.. blockimg:: pybricks_blockMotorResetAngle
.. automethod:: pybricks.pupdevices.Motor.reset_angle
.. blockimg:: pybricks_blockMotorMeasure_motor_speed
.. blockimg:: pybricks_blockMotorMeasure_motor_get_speed_average
.. automethod:: pybricks.pupdevices.Motor.speed
.. blockimg:: pybricks_blockMotorMeasure_motor_load
.. automethod:: pybricks.pupdevices.Motor.load
.. blockimg:: pybricks_blockMotorMeasure_motor_stalled
.. automethod:: pybricks.pupdevices.Motor.stalled
.. rubric:: Stopping
.. blockimg:: pybricks_blockMotorStop_Motor_coast
.. automethod:: pybricks.pupdevices.Motor.stop
.. blockimg:: pybricks_blockMotorStop_Motor_brake
.. automethod:: pybricks.pupdevices.Motor.brake
.. blockimg:: pybricks_blockMotorStop_Motor_hold
.. automethod:: pybricks.pupdevices.Motor.hold
.. rubric:: Running forever
.. blockimg:: pybricks_blockMotorRun_run
.. automethod:: pybricks.pupdevices.Motor.run
.. blockimg:: pybricks_blockMotorDuty_Motor
.. automethod:: pybricks.pupdevices.Motor.dc
.. rubric:: Running by a fixed amount
.. automethod:: pybricks.pupdevices.Motor.run_time
.. blockimg:: pybricks_blockMotorRun_run_angle
.. automethod:: pybricks.pupdevices.Motor.run_angle
.. blockimg:: pybricks_blockMotorRun_run_target
.. automethod:: pybricks.pupdevices.Motor.run_target
.. blockimg:: pybricks_blockMotorRun_run_until_stalled
.. automethod:: pybricks.pupdevices.Motor.run_until_stalled
.. blockimg:: pybricks_blockMotorTrack
.. automethod:: pybricks.pupdevices.Motor.track_target
.. automethod:: pybricks.pupdevices.Motor.done
.. _settings:
.. rubric:: Motor settings
.. blockimg:: pybricks_blockMotorConfigure_motor_max_voltage
.. automethod:: pybricks.pupdevices.Motor.settings
.. automethod:: pybricks.pupdevices.Motor.close
.. rubric:: Control settings
.. pybricks-requirements:: pybricks-common-control
.. blockimg:: pybricks_blockMotorConfigure_motor_max_speed
.. blockimg:: pybricks_blockMotorConfigure_motor_acceleration
.. blockimg:: pybricks_blockMotorConfigure_motor_max_torque
.. automethod:: pybricks.pupdevices::Motor.control.limits
.. pybricks-requirements:: pybricks-common-control
.. automethod:: pybricks.pupdevices::Motor.control.pid
.. pybricks-requirements:: pybricks-common-control
.. blockimg:: pybricks_blockMotorConfigure_motor_target_tolerances
.. automethod:: pybricks.pupdevices::Motor.control.target_tolerances
.. pybricks-requirements:: pybricks-common-control
.. automethod:: pybricks.pupdevices::Motor.control.stall_tolerances
.. pybricks-requirements:: pybricks-common-control
.. attribute:: control.scale
Number of degrees that the motor turns to complete one degree at the
output of the gear train. This is the gear ratio determined from the
``gears`` argument when initializing the motor.
.. versionchanged:: 3.2
The :meth:`done`, :meth:`stalled` and :meth:`load` methods have been
moved.
.. pybricks-requirements:: pybricks-common-control
.. automethod:: pybricks.pupdevices::Motor.model.state
.. pybricks-requirements:: pybricks-common-control
.. automethod:: pybricks.pupdevices::Motor.model.settings
.. include:: ../common/motor_members.rst.txt
Initialization examples
-----------------------
+1 -1
View File
@@ -1,4 +1,4 @@
.. pybricks-requirements::
.. pybricks-requirements:: pupdevices
Power Functions
^^^^^^^^^^^^^^^^^^^^^^^^^
+1 -1
View File
@@ -1,4 +1,4 @@
.. pybricks-requirements::
.. pybricks-requirements:: pupdevices
Remote Control
^^^^^^^^^^^^^^^^^^^^^^^^^
+1 -1
View File
@@ -1,4 +1,4 @@
.. pybricks-requirements::
.. pybricks-requirements:: pupdevices
Tilt Sensor
^^^^^^^^^^^^^^^^^^^^^^^^^
+1 -1
View File
@@ -1,4 +1,4 @@
.. pybricks-requirements::
.. pybricks-requirements:: pupdevices
Ultrasonic Sensor
^^^^^^^^^^^^^^^^^^^^^^^^^
+12 -14
View File
@@ -67,8 +67,7 @@ rotational acceleration: deg/s²
Rotational acceleration, or *angular acceleration* describes how fast the
rotational speed changes. This is expressed as the change of the number of
degrees per second, during one second (deg/s²). This is also commonly written
as :math:`deg/s^2`.
degrees per second, during one second (deg/s²).
For example, you can adjust the rotational acceleration setting of a ``Motor``
to change how smoothly or
@@ -125,7 +124,6 @@ linear acceleration: mm/s²
Linear acceleration describes how fast the speed changes. This is expressed as
the change of the millimeters per second, during one second (mm/s²).
This is also commonly written as :math:`mm/s^2`.
For example, you can adjust the acceleration setting of a
:class:`DriveBase <.robotics.DriveBase>` to change how
@@ -181,15 +179,15 @@ Force values are expressed in newtons (N).
While we recommend working with newtons in your programs, you can use the
following table to convert to and from other units.
+---------+------+-------+-----------------------------+
| | mN | N | lbf |
+---------+------+-------+-----------------------------+
| 1 mN = | 1 | 0.001 | :math:`2.248 \cdot 10^{-4}` |
+---------+------+-------+-----------------------------+
| 1 N = | 1000 | 1 | 0.2248 |
+---------+------+-------+-----------------------------+
| 1 lbf = | 4448 | 4.448 | 1 |
+---------+------+-------+-----------------------------+
+---------+------+-------+------------+
| | mN | N | lbf |
+---------+------+-------+------------+
| 1 mN = | 1 | 0.001 | 2.248·10⁻⁴ |
+---------+------+-------+------------+
| 1 N = | 1000 | 1 | 0.2248 |
+---------+------+-------+------------+
| 1 lbf = | 4448 | 4.448 | 1 |
+---------+------+-------+------------+
.. _torque:
@@ -251,9 +249,9 @@ temperature: °C
Temperature is measured in degrees Celsius (°C). To convert to degrees
Fahrenheit (°F) or Kelvin (K), you can use the following conversion formulas:
:math:`^{\circ}\kern1pt\!F =\kern1pt^{\circ}\kern1pt\!C \cdot \frac{9}{5} + 32`.
°F = °C · 9/5 + 32.
:math:`K =\kern1pt^{\circ}\kern1pt\!C + 273.15`.
K = °C + 273.15.
.. _hue:
-2
View File
@@ -1,5 +1,3 @@
#!/usr/bin/env pybricks-micropython
# Before running this program, make sure the client and server EV3 bricks are
# paired using Bluetooth, but do NOT connect them. The program will take care
# of establishing the connection.
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
from pybricks.messaging import BluetoothMailboxClient, TextMailbox
# This demo makes your PC talk to an EV3 over Bluetooth.
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
from pybricks.messaging import BluetoothMailboxServer, TextMailbox
# This demo makes your PC talk to an EV3 over Bluetooth.
@@ -10,7 +10,7 @@ remain a strict subset of that implementation when it comes to low-level
implementation details.
"""
from socket import socket, AF_BLUETOOTH, BTPROTO_RFCOMM, SOCK_STREAM
from socket import AF_BLUETOOTH, BTPROTO_RFCOMM, SOCK_STREAM, socket
from socketserver import ThreadingMixIn
@@ -2,12 +2,12 @@
# Copyright (C) 2020,2023 The Pybricks Authors
from errno import ECONNRESET
from struct import pack, unpack
from socket import BDADDR_ANY
from socketserver import StreamRequestHandler
from struct import pack, unpack
from threading import Lock
from .bluetooth import ThreadingRFCOMMServer, ThreadingRFCOMMClient
from .bluetooth import ThreadingRFCOMMClient, ThreadingRFCOMMServer
def resolve(brick):
@@ -128,7 +128,7 @@ class TextMailbox(Mailbox):
"""
def encode(self, value):
return ("{}\0".format(value)).encode("utf-8")
return (f"{value}\0").encode()
def decode(self, payload):
return payload.decode().strip("\0")
@@ -158,7 +158,7 @@ class MailboxHandler(StreamRequestHandler):
raise
(size,) = unpack("<H", buf)
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:
raise ValueError("Bad message type")
if cmd != WRITEMAILBOX:
@@ -217,7 +217,7 @@ class MailboxHandlerMixIn:
mbox_len = len(mbox) + 1
payload_len = len(payload)
send_len = 7 + mbox_len + payload_len
fmt = "<HHBBB{}sH{}s".format(mbox_len, payload_len)
fmt = f"<HHBBB{mbox_len}sH{payload_len}s"
data = pack(
fmt,
send_len,
@@ -239,7 +239,7 @@ class MailboxHandlerMixIn:
addr = resolve(brick)
self._addresses[brick] = addr
if addr is None:
raise ValueError('no paired devices matching "{}"'.format(brick))
raise ValueError(f'no paired devices matching "{brick}"')
self._clients[addr].send(data)
def wait_for_mailbox_update(self, mbox):
@@ -334,7 +334,7 @@ class BluetoothMailboxClient(MailboxHandlerMixIn):
"""
addr = resolve(brick)
if addr is None:
raise ValueError('no paired devices matching "{}"'.format(brick))
raise ValueError(f'no paired devices matching "{brick}"')
client = MailboxRFCOMMClient(self, addr)
if self._clients.setdefault(addr, client) is not client:
raise ValueError("connection with this address already exists")
@@ -1,10 +1,10 @@
from uctypes import addressof, sizeof, struct
from usocket import socket, SOCK_STREAM
from _thread import start_new_thread
from pybricks.bluetooth import str2ba, sockaddr_rc, AF_BLUETOOTH, BTPROTO_RFCOMM
from pybricks.tools import wait, StopWatch
from pybricks.bluetooth import AF_BLUETOOTH, BTPROTO_RFCOMM, sockaddr_rc, str2ba
from uctypes import addressof, sizeof, struct
from usocket import SOCK_STREAM, socket
from pybricks.tools import StopWatch, wait
def get_bluetooth_rfcomm_socket(address, channel):
@@ -24,9 +24,9 @@ class SpikePrimeStreamReader:
try:
self.sock = get_bluetooth_rfcomm_socket(address, 1)
except OSError as e:
except OSError:
print("Turn on Bluetooth on the EV3 and on SPIKE.")
raise e
raise
self._values = None
@@ -37,7 +37,7 @@ class SpikePrimeStreamReader:
if self.values() is not None:
return
wait(100)
raise IOError("No data received")
raise OSError("No data received")
def disconnect(self):
self.sock.close()
+2 -3
View File
@@ -1,9 +1,8 @@
#!/usr/bin/env pybricks-micropython
from connection import SpikePrimeStreamReader
from pybricks.hubs import EV3Brick
from pybricks.tools import wait
from connection import SpikePrimeStreamReader
# Beep!
ev3 = EV3Brick()
ev3.speaker.beep()
+6 -7
View File
@@ -1,12 +1,11 @@
#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.tools import wait
from pybricks.ev3devices import Motor
from pybricks.robotics import DriveBase
from pybricks.parameters import Port
from connection import SpikePrimeStreamReader
from pybricks.ev3devices import Motor
from pybricks.hubs import EV3Brick
from pybricks.parameters import Port
from pybricks.robotics import DriveBase
from pybricks.tools import wait
# Beep!
ev3 = EV3Brick()
ev3.speaker.beep()
-2
View File
@@ -1,5 +1,3 @@
#!/usr/bin/env pybricks-micropython
# Before running this program, make sure the client and server EV3 bricks are
# paired using Bluetooth, but do NOT connect them. The program will take care
# of establishing the connection.
+1 -3
View File
@@ -1,8 +1,6 @@
#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.tools import wait
from pybricks.parameters import Button
from pybricks.tools import wait
# Initialize the EV3
ev3 = EV3Brick()
+1 -3
View File
@@ -1,10 +1,8 @@
#!/usr/bin/env pybricks-micropython
from menu import wait_for_button
from pybricks.hubs import EV3Brick
from pybricks.parameters import Button
from menu import wait_for_button
# Initialize the EV3.
ev3 = EV3Brick()
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env pybricks-micropython
from pybricks.ev3devices import Motor
from pybricks.parameters import Port
from pybricks.tools import DataLog, StopWatch, wait
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env pybricks-micropython
from pybricks.parameters import Color
from pybricks.tools import DataLog
-3
View File
@@ -1,3 +0,0 @@
__pycache__/
*.pyc
venv/
-13
View File
@@ -1,13 +0,0 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
// List of extensions which should be recommended for users of this workspace.
"recommendations": [
"lego-education.ev3-micropython"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": [
"ms-python.python"
]
}
-20
View File
@@ -1,20 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Main Example",
"type": "ev3devBrowser",
"request": "launch",
"program": "/home/robot/${workspaceRootFolderName}/main.py"
},
{
"name": "Class Example",
"type": "ev3devBrowser",
"request": "launch",
"program": "/home/robot/${workspaceRootFolderName}/class_example.py"
}
]
}
-6
View File
@@ -1,6 +0,0 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.eol": "\n",
"debug.openDebug": "neverOpen",
"python.linting.enabled": false
}
@@ -1,46 +0,0 @@
#!/usr/bin/env pybricks-micropython
from pybricks.parameters import Port
from pybricks.iodevices import Ev3devSensor
class MySensor(Ev3devSensor):
"""Example of extending the Ev3devSensor class."""
def __init__(self, port):
"""Initialize the sensor."""
# Initialize the parent class.
super().__init__(port)
# Get the sysfs path.
self.path = "/sys/class/lego-sensor/sensor" + str(self.sensor_index)
def get_modes(self):
"""Get a list of mode strings so we don't have to look them up."""
# The path of the modes file.
modes_path = self.path + "/modes"
# Open the modes file.
with open(modes_path, "r") as m:
# Read the contents.
contents = m.read()
# Strip the newline symbol, and split at every space symbol.
return contents.strip().split(" ")
# Initialize the sensor
sensor = MySensor(Port.S3)
# Show where this sensor can be found
print(sensor.path)
# Print the available modes
modes = sensor.get_modes()
print(modes)
# Read mode 0 of this sensor
val = sensor.read(modes[0])
print(val)
-19
View File
@@ -1,19 +0,0 @@
#!/usr/bin/env pybricks-micropython
from pybricks.parameters import Port
from pybricks.tools import wait
from pybricks.iodevices import Ev3devSensor
# Initialize an Ev3devSensor.
# In this example we use the
# LEGO MINDSTORMS EV3 Color Sensor.
sensor = Ev3devSensor(Port.S3)
while True:
# Read the raw RGB values
r, g, b = sensor.read("RGB-RAW")
# Print results
print("R: {0}\t G: {1}\t B: {2}".format(r, g, b))
# Wait
wait(200)
+1 -2
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.ev3devices import Motor
from pybricks.hubs import EV3Brick
from pybricks.parameters import Port
# Create your objects here
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.iodevices import I2CDevice
from pybricks.parameters import Port
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.iodevices import I2CDevice
from pybricks.parameters import Port
+1 -3
View File
@@ -1,8 +1,6 @@
#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.tools import wait
from pybricks.parameters import Color
from pybricks.tools import wait
# Initialize the EV3
ev3 = EV3Brick()
-3
View File
@@ -1,3 +0,0 @@
__pycache__/
*.pyc
.venv/
-13
View File
@@ -1,13 +0,0 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
// List of extensions which should be recommended for users of this workspace.
"recommendations": [
"lego-education.ev3-micropython"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": [
"ms-python.python"
]
}
-15
View File
@@ -1,15 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Download and Run",
"type": "ev3devBrowser",
"request": "launch",
"program": "/home/robot/${workspaceRootFolderName}/main.py",
"interactiveTerminal": false
}
]
}
-7
View File
@@ -1,7 +0,0 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.eol": "\n",
"debug.openDebug": "neverOpen",
"python.linting.enabled": false,
"python.languageServer": "None"
}
-146
View File
@@ -1,146 +0,0 @@
#!/usr/bin/env pybricks-micropython
from pybricks.ev3devices import Motor
from pybricks.parameters import Port
import struct
# This program uses the two PS4 sticks to control two EV3 Large Servo Motors
# using tank like controls. For a full map of all PS4 buttons, trackpad, and
# motion checkout: https://github.com/codeadamca/python-connect-ps4
# Initialize EV3 motors
left_motor = Motor(Port.B)
right_motor = Motor(Port.C)
left_speed = 0
right_speed = 0
# Locate the event file you want to react to, on my setup the PS4 controller
# button events are located in /dev/input/event4
infile_path = "/dev/input/event4"
in_file = open(infile_path, "rb")
# Define the format the event data will be read.
# https://docs.python.org/3/library/struct.html#format-characters
FORMAT = "llHHi"
EVENT_SIZE = struct.calcsize(FORMAT)
event = in_file.read(EVENT_SIZE)
# A helper function for converting stick values (0 to 255) to more usable
# numbers (-100 to 100)
def scale(val, src, dst):
result = float(val - src[0]) / (src[1] - src[0])
result = result * (dst[1] - dst[0]) + dst[0]
return result
# Create a loop to react to events
# This loop reacts to all main PS4 button and stick events. I have left out
# buttons like share and options, but can easily be added in by referring
# to the table at: https://github.com/codeadamca/python-connect-ps4
while event:
# Place event data into variables
(tv_sec, tv_usec, ev_type, code, value) = struct.unpack(FORMAT, event)
# If a button was pressed or released
if ev_type == 1:
# React to the X button
if code == 304 and value == 0:
print("The X button was released")
elif code == 304 and value == 1:
print("The X button was pressed")
# React to the Circle button
elif code == 305 and value == 0:
print("The Circle button was released")
elif code == 305 and value == 1:
print("The Circle button was pressed")
# React to the Triangle button
elif code == 307 and value == 0:
print("The Triangle button was released")
elif code == 307 and value == 1:
print("The Triangle button was pressed")
# React to the Square button
elif code == 308 and value == 0:
print("The Square button was released")
elif code == 308 and value == 1:
print("The Square button was pressed")
# React to the L1 button
elif code == 310 and value == 0:
print("The L1 button was released")
elif code == 310 and value == 1:
print("The L1 button was pressed")
# React to the R1 button
elif code == 311 and value == 0:
print("The R1 button was released")
elif code == 311 and value == 1:
print("The R1 button was pressed")
# React to the L2 button
elif code == 312 and value == 0:
print("The L2 button was released")
elif code == 312 and value == 1:
print("The L2 button was pressed")
# React to the R2 button
elif code == 313 and value == 0:
print("The R2 button was released")
elif code == 313 and value == 1:
print("The R2 button was pressed")
elif ev_type == 3:
# The sticks often trigger non-stop events, comment this out if you are
# not using the sticks as part of your project, or it becomes hard to
# read other data
# React to the left stick vertical
if code == 1:
print("The left stick vertical is at ", value)
left_speed = scale(value, (0, 255), (100, -100))
# React to the left stick horizontal
elif code == 0:
print("The left stick horizontal is at ", value)
# React to the right stick vertical
elif code == 4:
print("The right stick vertical is at ", value)
right_speed = scale(value, (0, 255), (100, -100))
# React to the right stick horizontal
elif code == 3:
print("The right stick horizontal is at ", value)
# React to the Directional pad
if code == 16 and value == -1:
print("The horizontal directional pad is left")
elif code == 16 and value == 1:
print("The horizontal directional pad is right")
elif code == 16 and value == 0:
print("The horizontal directional pad is released")
elif code == 17 and value == -1:
print("The vertical directional pad is up")
elif code == 17 and value == 1:
print("The horizontal directional pad is down")
elif code == 17 and value == 0:
print("The horizontal directional pad is released")
# Set motor speed
left_motor.dc(left_speed)
right_motor.dc(right_speed)
# Read the next event
event = in_file.read(EVENT_SIZE)
in_file.close()
+1 -2
View File
@@ -1,7 +1,6 @@
#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.iodevices import AnalogSensor
from pybricks.parameters import Port, Color
from pybricks.parameters import Color, Port
from pybricks.tools import wait
-3
View File
@@ -1,9 +1,6 @@
#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.tools import wait
# Initialize the EV3
ev3 = EV3Brick()
+3 -5
View File
@@ -1,12 +1,10 @@
#!/usr/bin/env pybricks-micropython
import math
from pybricks.media.ev3dev import Font, Image
from pybricks.hubs import EV3Brick
from pybricks.parameters import Color
from pybricks.tools import wait
from pybricks.media.ev3dev import Font, Image
# Initialize the EV3
ev3 = EV3Brick()
@@ -65,7 +63,7 @@ for t in range(200):
# Print every 10th value on right side
if t % 10 == 0:
right.print("{:10.2f}{:10.2f}".format(x1, y1))
right.print(f"{x1:10.2f}{y1:10.2f}")
wait(100)
+1 -2
View File
@@ -1,8 +1,7 @@
#!/usr/bin/env pybricks-micropython
from pybricks.media.ev3dev import Image, ImageFile
from pybricks.hubs import EV3Brick
from pybricks.tools import wait
from pybricks.media.ev3dev import Image, ImageFile
# It takes some time to load images from the SD card, so it is best to load
# them once at the beginning of a program like this:
+1 -2
View File
@@ -1,8 +1,7 @@
#!/usr/bin/env pybricks-micropython
from pybricks.media.ev3dev import Font
from pybricks.hubs import EV3Brick
from pybricks.tools import wait
from pybricks.media.ev3dev import Font
# It takes some time for fonts to load from file, so it is best to only
# load them once at the beginning of the program like this:

Some files were not shown because too many files have changed in this diff Show More