Move the computer folder up - a bit easier to manage.

Integrate fixes found in earlier examples.
This commit is contained in:
Danny Staple
2022-12-28 11:27:16 +00:00
parent 9cff9fe1f1
commit c87ef96477
12 changed files with 165 additions and 371 deletions
@@ -1,89 +0,0 @@
import asyncio
import json
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
from robot_ble_connection import BleConnection
class RobotDisplay:
def __init__(self):
self.ble_connection = BleConnection(self.handle_data)
self.line = ""
self.arena = {}
self.display_closed = False
self.fig, self.ax = plt.subplots()
self.poses = np.zeros([200, 3], dtype=np.int16)
self.motion = np.zeros([200, 3], dtype=float)
def handle_close(self, _):
self.display_closed = True
def handle_data(self, data):
self.line += data.decode("utf-8")
# print(f"Received data: {data.decode('utf-8')}")
# print(f"Line is now: {self.line}")
while "\n" in self.line:
line, self.line = self.line.split("\n", 1)
print(f"Received line: {line}")
try:
message = json.loads(line)
except ValueError:
print("Error parsing JSON")
return
if "arena" in message:
self.arena = message
if "poses" in message:
print(message)
incoming_poses = np.array(message["poses"], dtype=np.int16)
print("Incoming poses shape", incoming_poses.shape)
print("Existing poses shape", self.poses.shape)
self.poses[message["offset"]: message["offset"] + incoming_poses.shape[0]] = incoming_poses
if "motion" in message:
np.roll(self.motion, 1, axis=0)
self.motion[0] = [message["motion"]["rot1"], message["motion"]["trans"], message["motion"]["rot2"]]
def draw(self):
self.ax.clear()
if self.arena:
for line in self.arena["arena"]:
self.ax.plot(
[line[0][0], line[1][0]], [line[0][1], line[1][1]], color="black"
)
self.ax.scatter(self.poses[:,0], self.poses[:,1], color="blue")
async def send_command(self, command):
#+ "\n" - why does adding this (which sounds right) cause the ble stack (on the robot or computer? ) not to work any more?
request = (json.dumps({"command": command}) ).encode()
print(f"Sending request: {request}")
await self.ble_connection.send_uart_data(request)
def start(self, _):
self.button_task = asyncio.create_task(self.send_command("start"))
# def stop(self, _):
# self.button_task = asyncio.create_task(self.send_command("stop"))
async def main(self):
plt.ion()
await self.ble_connection.connect()
try:
await self.send_command("arena")
self.fig.canvas.mpl_connect("close_event", self.handle_close)
start_button = Button(plt.axes([0.7, 0.05, 0.1, 0.075]), "Start")
start_button.on_clicked(self.start)
# stop_button = Button(plt.axes([0.81, 0.05, 0.1, 0.075]), "Stop")
# stop_button.on_clicked(self.stop)
while not self.display_closed:
self.draw()
plt.draw()
plt.pause(0.05)
await asyncio.sleep(0.01)
finally:
await self.ble_connection.close()
robot_display = RobotDisplay()
asyncio.run(robot_display.main())
-24
View File
@@ -1,24 +0,0 @@
from unittest import TestCase
import math
import arena
class TestArena(TestCase):
def test_get_point_to_distance_segment_1(self):
segment = ((0, 0), (0, 1500))
for x in range(0, 1500):
for y in (0, 500, 1000):
self.assertEqual(arena.get_point_distance_to_segment(x, y, segment), x)
def test_get_point_to_distance_segment_2(self):
segment = ((0, 0), (1500, 0))
for y in range(0, 1500):
for x in (0, 500, 1000):
self.assertEqual(arena.get_point_distance_to_segment(x, y, segment), y)
def test_get_point_distance_to_nearest_segment(self):
segments = [
[(0, 1500), (1500, 1500)],
]
for y in range(1500):
for x in (0, 500, 1000):
self.assertEqual(arena.get_point_distance_to_nearest_segment(segments, x, y), 1500 - y)
@@ -10,23 +10,21 @@ from robot_ble_connection import BleConnection
class RobotDisplay: class RobotDisplay:
def __init__(self): def __init__(self):
self.ble_connection = BleConnection(self.handle_data) self.ble_connection = BleConnection(self.handle_data)
self.line = "" self.buffer = ""
self.arena = {} self.arena = {}
self.display_closed = False self.closed = False
self.fig, self.ax = plt.subplots() self.fig, self.ax = plt.subplots()
self.poses = np.zeros([200, 2], dtype=np.int16) self.poses = np.zeros([20, 2], dtype=np.int16)
self.motion = np.zeros([200, 3], dtype=float) self.motion = np.zeros([200, 3], dtype=float)
def handle_close(self, _): def handle_close(self, _):
self.display_closed = True self.closed = True
def handle_data(self, data): def handle_data(self, data):
self.line += data.decode("utf-8") self.buffer += data.decode("utf-8")
# print(f"Received data: {data.decode('utf-8')}") while "\n" in self.buffer:
# print(f"Line is now: {self.line}") line, self.buffer = self.buffer.split("\n", 1)
while "\n" in self.line: print(f"Received data: {line}")
line, self.line = self.line.split("\n", 1)
print(f"Received line: {line}")
try: try:
message = json.loads(line) message = json.loads(line)
except ValueError: except ValueError:
@@ -47,9 +45,7 @@ class RobotDisplay:
) )
self.ax.scatter(self.poses[:,0], self.poses[:,1], color="blue") self.ax.scatter(self.poses[:,0], self.poses[:,1], color="blue")
async def send_command(self, command): async def send_command(self, command):
#+ "\n" - why does adding this (which sounds right) cause the ble stack (on the robot or computer? ) not to work any more?
request = (json.dumps({"command": command}) ).encode() request = (json.dumps({"command": command}) ).encode()
print(f"Sending request: {request}") print(f"Sending request: {request}")
await self.ble_connection.send_uart_data(request) await self.ble_connection.send_uart_data(request)
@@ -70,7 +66,7 @@ class RobotDisplay:
start_button.on_clicked(self.start) start_button.on_clicked(self.start)
# stop_button = Button(plt.axes([0.81, 0.05, 0.1, 0.075]), "Stop") # stop_button = Button(plt.axes([0.81, 0.05, 0.1, 0.075]), "Stop")
# stop_button.on_clicked(self.stop) # stop_button.on_clicked(self.stop)
while not self.display_closed: while not self.closed:
self.draw() self.draw()
plt.draw() plt.draw()
plt.pause(0.05) plt.pause(0.05)
@@ -8,7 +8,7 @@ python-versions = ">=3.6"
[[package]] [[package]]
name = "black" name = "black"
version = "22.10.0" version = "22.12.0"
description = "The uncompromising code formatter." description = "The uncompromising code formatter."
category = "dev" category = "dev"
optional = false optional = false
@@ -99,7 +99,7 @@ python-versions = ">=3.6"
[[package]] [[package]]
name = "dbus-fast" name = "dbus-fast"
version = "1.64.0" version = "1.83.0"
description = "A faster version of dbus-next" description = "A faster version of dbus-next"
category = "main" category = "main"
optional = false optional = false
@@ -158,14 +158,6 @@ pyparsing = ">=2.2.1"
python-dateutil = ">=2.7" python-dateutil = ">=2.7"
setuptools_scm = ">=7" setuptools_scm = ">=7"
[[package]]
name = "msgpack"
version = "1.0.4"
description = "MessagePack serializer"
category = "main"
optional = false
python-versions = "*"
[[package]] [[package]]
name = "mypy-extensions" name = "mypy-extensions"
version = "0.4.3" version = "0.4.3"
@@ -184,18 +176,15 @@ python-versions = ">=3.8"
[[package]] [[package]]
name = "packaging" name = "packaging"
version = "21.3" version = "22.0"
description = "Core utilities for Python packages" description = "Core utilities for Python packages"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.7"
[package.dependencies]
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
[[package]] [[package]]
name = "pathspec" name = "pathspec"
version = "0.10.1" version = "0.10.3"
description = "Utility library for gitignore style pattern matching of file paths." description = "Utility library for gitignore style pattern matching of file paths."
category = "dev" category = "dev"
optional = false optional = false
@@ -215,15 +204,15 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa
[[package]] [[package]]
name = "platformdirs" name = "platformdirs"
version = "2.5.2" version = "2.6.0"
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
[package.extras] [package.extras]
docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"] docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"]
test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
[[package]] [[package]]
name = "pyobjc-core" name = "pyobjc-core"
@@ -291,7 +280,7 @@ six = ">=1.5"
[[package]] [[package]]
name = "setuptools" name = "setuptools"
version = "65.5.0" version = "65.6.3"
description = "Easily download, build, install, upgrade, and uninstall Python packages" description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "main" category = "main"
optional = false optional = false
@@ -299,12 +288,12 @@ python-versions = ">=3.7"
[package.extras] [package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mock", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
[[package]] [[package]]
name = "setuptools-scm" name = "setuptools-scm"
version = "7.0.5" version = "7.1.0"
description = "the blessed package to manage your versions by scm tags" description = "the blessed package to manage your versions by scm tags"
category = "main" category = "main"
optional = false optional = false
@@ -313,7 +302,7 @@ python-versions = ">=3.7"
[package.dependencies] [package.dependencies]
packaging = ">=20.0" packaging = ">=20.0"
setuptools = "*" setuptools = "*"
tomli = ">=1.0.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
typing-extensions = "*" typing-extensions = "*"
[package.extras] [package.extras]
@@ -347,7 +336,7 @@ python-versions = ">=3.7"
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.9" python-versions = "^3.9"
content-hash = "a2ae390fc260b23b2aea772611acac3c8626867abcb0e477875407c9f24a5fa6" content-hash = "4ec6eb3464cbb49afad347e67bdf7c353d7ea4030fd8ed4257098a5df334eb99"
[metadata.files] [metadata.files]
async-timeout = [ async-timeout = [
@@ -355,27 +344,18 @@ async-timeout = [
{file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"},
] ]
black = [ black = [
{file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"},
{file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"},
{file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"},
{file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"},
{file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"},
{file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"},
{file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"},
{file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"},
{file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"},
{file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"},
{file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"},
{file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"},
{file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"},
{file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"},
{file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"},
{file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"},
{file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"},
{file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"},
{file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"},
{file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"},
{file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"},
] ]
bleak = [ bleak = [
{file = "bleak-0.19.0-py3-none-any.whl", hash = "sha256:ccdba0d17dcceb1326e4e46600b37e9019cd52ce01948e2a3dbd6c94d1e4de01"}, {file = "bleak-0.19.0-py3-none-any.whl", hash = "sha256:ccdba0d17dcceb1326e4e46600b37e9019cd52ce01948e2a3dbd6c94d1e4de01"},
@@ -478,34 +458,34 @@ cycler = [
{file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"}, {file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"},
] ]
dbus-fast = [ dbus-fast = [
{file = "dbus_fast-1.64.0-cp310-cp310-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:d6ee2acd48a6f22836a0782786c0f617a70bd33353100028a26b351e653c83a4"}, {file = "dbus_fast-1.83.0-cp310-cp310-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:41fd66ed9298869f135c43a6f22f3790d4b765a6a593fb415322e4dabe6f5452"},
{file = "dbus_fast-1.64.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff97c83a30ccf9ffe43df1721f0bff90fdfbe39a583c77a52932046b5f707b9c"}, {file = "dbus_fast-1.83.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dedfbede7c7fc3d026014e5eedaf67b58c91806c86e435896c37060d9afac6c4"},
{file = "dbus_fast-1.64.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6d912844d3763140fdb4d9c474d1d86e8129c9a498e1cbcdf54ac71811a081df"}, {file = "dbus_fast-1.83.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3445f2e3377f30d2d24de7b5dd378d18ce71263ec96c932cd1abea5396440a2a"},
{file = "dbus_fast-1.64.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48248467c8cc25af0bf42676f337ee8b56a2c8c3b9df1eb7a51f649e74401343"}, {file = "dbus_fast-1.83.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:40189a5f578fca92251bfecb4a26da3f7752f0db52b6bcff9784407d45232d2e"},
{file = "dbus_fast-1.64.0-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:f44e5b3025db2f0c689afc34478fa3d522c45af5721aacebcfc4c3e9c268b23a"}, {file = "dbus_fast-1.83.0-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:822e58c7d530b8b4dc79a54fe1718cda78feab9d64e8f6623f3a0b477b6443a3"},
{file = "dbus_fast-1.64.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:939417ecc4ea438ba9287f2a8df92329eb87179c69f627d3eb27af609ac59446"}, {file = "dbus_fast-1.83.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc5c48ac4472ec5ba059a29e95328d06e224b03d5b0d5f1e1cd718213aa324d0"},
{file = "dbus_fast-1.64.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3cace85b55be5f82f2bb51f98d834f92e572668a05f6492e96ea90a8728a2983"}, {file = "dbus_fast-1.83.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ca4aad792dd1fce92bc4da353f424db3195bd5f8750e1c98c27ed49bec0f650b"},
{file = "dbus_fast-1.64.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fa2e77bef181d3e9f72176ad750da2b448b2000238cef56dafa1b08093a78a90"}, {file = "dbus_fast-1.83.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d428b34bdd6eb7bb35a9ca750530e8ef675e056de2ad4551bc56850264e18d35"},
{file = "dbus_fast-1.64.0-cp37-cp37m-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:5b04c84d0345fba5ceb6bb56bfa5c3f34a3a9995a2d1ea17857c1e2e50cc4a26"}, {file = "dbus_fast-1.83.0-cp37-cp37m-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:b053c4c2f2ca4c0f0f6928346b621f2cac77f08c03a8ced530d47c2faa46408b"},
{file = "dbus_fast-1.64.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72275f7054c683b2c340d0a6baf922fa0d0cef9ec00cb2262d2242d3c428b8d8"}, {file = "dbus_fast-1.83.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2ccf9563b6a926d46d0b546e57526556c24848127e9997a868e78d16f150297"},
{file = "dbus_fast-1.64.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b235c111dd9746f3d2a4c2ce1f9d7c255fe6ba64537551154d10599f9aef279c"}, {file = "dbus_fast-1.83.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a79c27ed8bb71c89c557398b61bb53d60f4d1de1c52c33386b8504ec65b0a299"},
{file = "dbus_fast-1.64.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fad7108eddd552ccca7a7b49bd61848bc6936bdaf1dd9a4e4c6b031c25b61c9c"}, {file = "dbus_fast-1.83.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:94c9ec8b3639cee94691e5788d6db6a5b502834968888f1a8be38fd0c4806e7c"},
{file = "dbus_fast-1.64.0-cp38-cp38-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:76301537ebf0ca4fe9b42f1463038386728d5655817639b1f62737126f85ed09"}, {file = "dbus_fast-1.83.0-cp38-cp38-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:5ca89e42bba8954f75eca52a3f2d1e3ecf6bbf19f17c543de122ccf82dabb65b"},
{file = "dbus_fast-1.64.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99eda460d32673d1261cfa9422d356f5d09dc10dd094158a9e8e19903991af3c"}, {file = "dbus_fast-1.83.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9c87ab1546a38b5a2b4170fb9eee2e40ef82961b714eefa46674f066b255ff1"},
{file = "dbus_fast-1.64.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:78cee1896db352fbddac0c3eb91f0c97f93627b6f010b4987ac0b724a88020fa"}, {file = "dbus_fast-1.83.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7283ff647b1dff8cdbd98edda8d73c86e4d619f774ad574c72fb8c8056baadfa"},
{file = "dbus_fast-1.64.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:660f824f3a13d5b18140ee356823ae0fb263d4c182451130fd2b1e594b9bad1a"}, {file = "dbus_fast-1.83.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1f9b6ea977feeb816f5d74578d67ac713a8134726257112693ed685e975585d3"},
{file = "dbus_fast-1.64.0-cp39-cp39-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:838254b626427d919c652fe3fc5841a6c6f20b3c12e5335d7d32124111161461"}, {file = "dbus_fast-1.83.0-cp39-cp39-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:5b12f018d6fedf0ffba3d8e2d25a1f436c4b100c95d925e6cea8c2aceb475fed"},
{file = "dbus_fast-1.64.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb73f5a364ab22151892d349991ae57a3d4e18fa4c6a6d0134f5a0b8cfaefc8"}, {file = "dbus_fast-1.83.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3491e38e58bc1c4aeab67994b5bba6d663c0d8999d3a1f5aae23afe392d6099"},
{file = "dbus_fast-1.64.0-cp39-cp39-manylinux_2_31_x86_64.whl", hash = "sha256:c0d3e18a2b793e7e774773190db631b729bd7ca0b88c63415e286fbe7f4c8320"}, {file = "dbus_fast-1.83.0-cp39-cp39-manylinux_2_31_x86_64.whl", hash = "sha256:4306b87f88546d9645b6b1ccdc863e410798c1c1ad7312ed6b210aa8a1b23dde"},
{file = "dbus_fast-1.64.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a0a4e64ac5a994239cb1200cfc7ce9d2173233c9a5f3f48dca3bf3ca3e8e132a"}, {file = "dbus_fast-1.83.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:463ea272c36cc55dc4d3b3d55d17738fd06c1f870c5d9f2d5727c50554461aa5"},
{file = "dbus_fast-1.64.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d27260f6998f614dfb9c9fa2c9674402134e8a221b57f52a7dfecce2bed2df37"}, {file = "dbus_fast-1.83.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6f0b9e74e190a10a93a3831c91b7289bedbcd51dc20aa4326ee723e89bf12c26"},
{file = "dbus_fast-1.64.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:735feead084951a1daf9c71480f4bfe84b127cacd9af0fddf70cdf7043f7a29c"}, {file = "dbus_fast-1.83.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:f6c82bc159817f4ded469ca75af79bdb1b94699546232ea8b43c809cb1b157c2"},
{file = "dbus_fast-1.64.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:025583c613beb58abd24e993e3be6098002eac9d01afff1e7180e5ddbbf74772"}, {file = "dbus_fast-1.83.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fb9eaed1af93b021e45e6b4dec0fbbba7ab7de6710c890df486a9aa2de1851b"},
{file = "dbus_fast-1.64.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:09488197ffc535ad62d048e532e127d12e4878a3af8b7cd5cf34819f1bd6ddca"}, {file = "dbus_fast-1.83.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:cce251b7e7ebbdbc858abc2eaed781bda44999ec61ed77c637da0384eb74a0a0"},
{file = "dbus_fast-1.64.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9d395687bcd0098cdacdfb8c1897c81998aabd07c13dd599e8fa2e73f04f704"}, {file = "dbus_fast-1.83.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50729191ff9045566f960142c1b7ef284178924fc514d71f92e5a9486d83267d"},
{file = "dbus_fast-1.64.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:830f028efa0753f6833a7f6491789436cfc63debdfac697465e334f3dd7c14d6"}, {file = "dbus_fast-1.83.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:4a4c1bca00c7b7fde4b72e4f8553c3d42d8459dcf475f94a7ffd8eab56e6ae9b"},
{file = "dbus_fast-1.64.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d2cec285c42c1fe4921ae879e975693376bd9c815494c354aa1b63fb40bbfaf"}, {file = "dbus_fast-1.83.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88697f7b1616aa980e59648d469edba30a46393a23155c3246d7e2a7224bbbd6"},
{file = "dbus_fast-1.64.0.tar.gz", hash = "sha256:794d67fc6369962bb291edf68c76a4b10a5f019c6c9b0458ca22c0d318cea659"}, {file = "dbus_fast-1.83.0.tar.gz", hash = "sha256:6a1a96725f1c91157fab94ab0bf2a5ddfdf0ed5fb68510980698d8180f51c848"},
] ]
fonttools = [ fonttools = [
{file = "fonttools-4.38.0-py3-none-any.whl", hash = "sha256:820466f43c8be8c3009aef8b87e785014133508f0de64ec469e4efb643ae54fb"}, {file = "fonttools-4.38.0-py3-none-any.whl", hash = "sha256:820466f43c8be8c3009aef8b87e785014133508f0de64ec469e4efb643ae54fb"},
@@ -624,60 +604,6 @@ matplotlib = [
{file = "matplotlib-3.6.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5f97141e05baf160c3ec125f06ceb2a44c9bb62f42fcb8ee1c05313c73e99432"}, {file = "matplotlib-3.6.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5f97141e05baf160c3ec125f06ceb2a44c9bb62f42fcb8ee1c05313c73e99432"},
{file = "matplotlib-3.6.1.tar.gz", hash = "sha256:e2d1b7225666f7e1bcc94c0bc9c587a82e3e8691da4757e357e5c2515222ee37"}, {file = "matplotlib-3.6.1.tar.gz", hash = "sha256:e2d1b7225666f7e1bcc94c0bc9c587a82e3e8691da4757e357e5c2515222ee37"},
] ]
msgpack = [
{file = "msgpack-1.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250"},
{file = "msgpack-1.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88"},
{file = "msgpack-1.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467"},
{file = "msgpack-1.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6"},
{file = "msgpack-1.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa"},
{file = "msgpack-1.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6"},
{file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba"},
{file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e"},
{file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db"},
{file = "msgpack-1.0.4-cp310-cp310-win32.whl", hash = "sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef"},
{file = "msgpack-1.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075"},
{file = "msgpack-1.0.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52"},
{file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9"},
{file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9"},
{file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08"},
{file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8"},
{file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6"},
{file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae"},
{file = "msgpack-1.0.4-cp36-cp36m-win32.whl", hash = "sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6"},
{file = "msgpack-1.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661"},
{file = "msgpack-1.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c"},
{file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0"},
{file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227"},
{file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff"},
{file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd"},
{file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e"},
{file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236"},
{file = "msgpack-1.0.4-cp37-cp37m-win32.whl", hash = "sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44"},
{file = "msgpack-1.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1"},
{file = "msgpack-1.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d"},
{file = "msgpack-1.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab"},
{file = "msgpack-1.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb"},
{file = "msgpack-1.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9"},
{file = "msgpack-1.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e"},
{file = "msgpack-1.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1"},
{file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e"},
{file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43"},
{file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243"},
{file = "msgpack-1.0.4-cp38-cp38-win32.whl", hash = "sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2"},
{file = "msgpack-1.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6"},
{file = "msgpack-1.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae"},
{file = "msgpack-1.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55"},
{file = "msgpack-1.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da"},
{file = "msgpack-1.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f"},
{file = "msgpack-1.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92"},
{file = "msgpack-1.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f"},
{file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624"},
{file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8"},
{file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae"},
{file = "msgpack-1.0.4-cp39-cp39-win32.whl", hash = "sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c"},
{file = "msgpack-1.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce"},
{file = "msgpack-1.0.4.tar.gz", hash = "sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f"},
]
mypy-extensions = [ mypy-extensions = [
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
@@ -713,12 +639,12 @@ numpy = [
{file = "numpy-1.23.4.tar.gz", hash = "sha256:ed2cc92af0efad20198638c69bb0fc2870a58dabfba6eb722c933b48556c686c"}, {file = "numpy-1.23.4.tar.gz", hash = "sha256:ed2cc92af0efad20198638c69bb0fc2870a58dabfba6eb722c933b48556c686c"},
] ]
packaging = [ packaging = [
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, {file = "packaging-22.0-py3-none-any.whl", hash = "sha256:957e2148ba0e1a3b282772e791ef1d8083648bc131c8ab0c1feba110ce1146c3"},
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, {file = "packaging-22.0.tar.gz", hash = "sha256:2198ec20bd4c017b8f9717e00f0c8714076fc2fd93816750ab48e2c41de2cfd3"},
] ]
pathspec = [ pathspec = [
{file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, {file = "pathspec-0.10.3-py3-none-any.whl", hash = "sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6"},
{file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, {file = "pathspec-0.10.3.tar.gz", hash = "sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6"},
] ]
Pillow = [ Pillow = [
{file = "Pillow-9.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:0b7257127d646ff8676ec8a15520013a698d1fdc48bc2a79ba4e53df792526f2"}, {file = "Pillow-9.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:0b7257127d646ff8676ec8a15520013a698d1fdc48bc2a79ba4e53df792526f2"},
@@ -782,8 +708,8 @@ Pillow = [
{file = "Pillow-9.3.0.tar.gz", hash = "sha256:c935a22a557a560108d780f9a0fc426dd7459940dc54faa49d83249c8d3e760f"}, {file = "Pillow-9.3.0.tar.gz", hash = "sha256:c935a22a557a560108d780f9a0fc426dd7459940dc54faa49d83249c8d3e760f"},
] ]
platformdirs = [ platformdirs = [
{file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, {file = "platformdirs-2.6.0-py3-none-any.whl", hash = "sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca"},
{file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, {file = "platformdirs-2.6.0.tar.gz", hash = "sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e"},
] ]
pyobjc-core = [ pyobjc-core = [
{file = "pyobjc-core-8.5.1.tar.gz", hash = "sha256:f8592a12de076c27006700c4a46164478564fa33d7da41e7cbdd0a3bf9ddbccf"}, {file = "pyobjc-core-8.5.1.tar.gz", hash = "sha256:f8592a12de076c27006700c4a46164478564fa33d7da41e7cbdd0a3bf9ddbccf"},
@@ -830,12 +756,12 @@ python-dateutil = [
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
] ]
setuptools = [ setuptools = [
{file = "setuptools-65.5.0-py3-none-any.whl", hash = "sha256:f62ea9da9ed6289bfe868cd6845968a2c854d1427f8548d52cae02a42b4f0356"}, {file = "setuptools-65.6.3-py3-none-any.whl", hash = "sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54"},
{file = "setuptools-65.5.0.tar.gz", hash = "sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17"}, {file = "setuptools-65.6.3.tar.gz", hash = "sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75"},
] ]
setuptools-scm = [ setuptools-scm = [
{file = "setuptools_scm-7.0.5-py3-none-any.whl", hash = "sha256:7930f720905e03ccd1e1d821db521bff7ec2ac9cf0ceb6552dd73d24a45d3b02"}, {file = "setuptools_scm-7.1.0-py3-none-any.whl", hash = "sha256:73988b6d848709e2af142aa48c986ea29592bbcfca5375678064708205253d8e"},
{file = "setuptools_scm-7.0.5.tar.gz", hash = "sha256:031e13af771d6f892b941adb6ea04545bbf91ebc5ce68c78aaf3fff6e1fb4844"}, {file = "setuptools_scm-7.1.0.tar.gz", hash = "sha256:6c508345a771aad7d56ebff0e70628bf2b0ec7573762be9960214730de278f27"},
] ]
six = [ six = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
@@ -11,7 +11,6 @@ python = "^3.9"
matplotlib = "3.6.1" matplotlib = "3.6.1"
numpy = "1.23.4" numpy = "1.23.4"
bleak = "0.19.0" bleak = "0.19.0"
msgpack = "^1.0.4"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
+5 -5
View File
@@ -1,4 +1,4 @@
"""Represent the lines and target zone of the arena""" """Represent the lines of the arena"""
try: try:
from ulab import numpy as np from ulab import numpy as np
except ImportError: except ImportError:
@@ -16,8 +16,7 @@ boundary_lines = [
width = 1500 width = 1500
height = 1500 height = 1500
# need to state clearly the orientation of the heading # 0, 0 is bottom left. Heading 0 is right, with heading increasing anticlockwise. Standard position angles.
# if coordinates 0, 0 is bottom left, then heading 0 is right, with heading increasing anticlockwise.
def point_is_inside_arena(x, y): def point_is_inside_arena(x, y):
"""Return True if the point is inside the arena. """Return True if the point is inside the arena.
@@ -67,11 +66,12 @@ def make_distance_grid():
"""Take the boundary lines. With and overscan of 10 cells, and grid cell size of 5cm (50mm), """Take the boundary lines. With and overscan of 10 cells, and grid cell size of 5cm (50mm),
make a grid of the distance to the nearest boundary line. make a grid of the distance to the nearest boundary line.
""" """
grid = np.zeros((width // grid_cell_size + 2 * overscan, height // grid_cell_size + 2 * overscan), dtype=np.float) grid = np.zeros((width // grid_cell_size + 2 * overscan, height // grid_cell_size + 2 * overscan), dtype=np.uint8)
# 4kb as floats, 1 kb as uint8s.
for x in range(grid.shape[0]): for x in range(grid.shape[0]):
column_x = x * grid_cell_size - (overscan * grid_cell_size) column_x = x * grid_cell_size - (overscan * grid_cell_size)
for y in range(grid.shape[1]): for y in range(grid.shape[1]):
value = get_point_decay_from_nearest_segment(boundary_lines, column_x, y * grid_cell_size - (overscan * grid_cell_size)) value = int(get_point_decay_from_nearest_segment(boundary_lines, column_x, y * grid_cell_size - (overscan * grid_cell_size)) * 255)
grid[x, y] = value grid[x, y] = value
return grid return grid
+80 -93
View File
@@ -2,34 +2,49 @@ import asyncio
import json import json
import random import random
from ulab import numpy as np from ulab import numpy as np
import arena import arena
import robot import robot
class CollisionAvoid: class DistanceSensorTracker:
def __init__(self): def __init__(self):
robot.left_distance.distance_mode = 2
robot.right_distance.distance_mode = 2
robot.left_distance.timing_budget = 50
robot.right_distance.timing_budget = 50
self.left = 300
self.right = 300
async def main(self):
robot.left_distance.start_ranging()
robot.right_distance.start_ranging()
while True:
if robot.left_distance.data_ready and robot.left_distance.distance:
self.left = robot.left_distance.distance * 10 # convert to mm
robot.left_distance.clear_interrupt()
if robot.right_distance.data_ready and robot.right_distance.distance:
self.right = robot.right_distance.distance * 10
robot.right_distance.clear_interrupt()
await asyncio.sleep(0.01)
class CollisionAvoid:
def __init__(self, distance_sensors):
self.speed = 0.6 self.speed = 0.6
self.left_distance = 300 self.distance_sensors = distance_sensors
self.right_distance = 300
def update(self, left_distance, right_distance): async def main(self):
self.left_distance = left_distance
self.right_distance = right_distance
async def run(self):
while True: while True:
robot.set_right(self.speed) robot.set_right(self.speed)
while self.left_distance < 300 or self.right_distance < 300: while self.distance_sensors.left < 300 or \
robot.set_left(-0.6) self.distance_sensors.right < 300:
robot.set_left(-self.speed)
await asyncio.sleep(0.3) await asyncio.sleep(0.3)
robot.set_left(self.speed) robot.set_left(self.speed)
await asyncio.sleep(0) await asyncio.sleep(0)
def get_scaled_sample_around_mean(mean, scale):
triangular_proportion = np.sqrt(6) / 2 return mean + (random.uniform(-scale, scale) + random.uniform(-scale, scale)) / 2
def get_triangular_sample(mean, standard_deviation):
base = triangular_proportion * (random.uniform(-standard_deviation, standard_deviation) + random.uniform(-standard_deviation, standard_deviation))
return mean + base
def convert_to_standard_position(true_bearing): def convert_to_standard_position(true_bearing):
standard_position = 90 - true_bearing standard_position = 90 - true_bearing
@@ -43,22 +58,29 @@ def convert_to_standard_position(true_bearing):
def send_json(data): def send_json(data):
robot.uart.write((json.dumps(data) + "\n").encode()) robot.uart.write((json.dumps(data) + "\n").encode())
def read_json():
try:
data = robot.uart.readline()
decoded = data.decode()
return json.loads(decoded)
except (UnicodeError, ValueError):
print("Invalid data")
return None
def send_poses(samples): def send_poses(samples):
send_json({ send_json({
"poses": samples[:,:2].tolist(), "poses": np.array(samples[:,:2], dtype=np.int16).tolist(),
}) })
class Simulation: class Simulation:
def __init__(self): def __init__(self):
self.population_size = 300 self.population_size = 200
self.left_distance = 100
self.right_distance = 100
self.imu_mix = 0.3 * 0.5 self.imu_mix = 0.3 * 0.5
self.encoder_mix = 0.7 self.encoder_mix = 0.7
self.rotation_standard_dev = 2 # degrees self.rotation_scale = 0.5 # degrees
self.speed_standard_dev = 5 # mm self.speed_scale = 3 # mm
# Poses - each an array of [x, y, heading] # Poses - each an array of [x, y, heading]
self.poses = np.array( self.poses = np.array(
@@ -66,9 +88,12 @@ class Simulation:
int(random.uniform(0, arena.width)), int(random.uniform(0, arena.width)),
int(random.uniform(0, arena.height)), int(random.uniform(0, arena.height)),
int(random.uniform(0, 360))) for _ in range(self.population_size)], int(random.uniform(0, 360))) for _ in range(self.population_size)],
dtype=np.int16, dtype=np.float,
) )
self.collision_avoider = CollisionAvoid() self.distance_sensors = DistanceSensorTracker()
self.collision_avoider = CollisionAvoid(self.distance_sensors)
self.last_encoder_left = robot.left_encoder.read()
self.last_encoder_right = robot.right_encoder.read()
async def apply_sensor_model(self): async def apply_sensor_model(self):
# Based on vl53l1x sensor readings, create weight for each pose. # Based on vl53l1x sensor readings, create weight for each pose.
@@ -90,15 +115,15 @@ class Simulation:
distance_sensor_left[:, 0] = self.poses[:, 0] + np.cos(poses_left_90) * robot.distance_sensor_from_middle distance_sensor_left[:, 0] = self.poses[:, 0] + np.cos(poses_left_90) * robot.distance_sensor_from_middle
distance_sensor_left[:, 1] = self.poses[:, 1] + np.sin(poses_left_90) * robot.distance_sensor_from_middle distance_sensor_left[:, 1] = self.poses[:, 1] + np.sin(poses_left_90) * robot.distance_sensor_from_middle
# now project forward by distance sensor range # now project forward by distance sensor range
distance_sensor_left[:, 0] += np.cos(self.poses[:, 2]) * self.left_distance distance_sensor_left[:, 0] += np.cos(self.poses[:, 2]) * self.distance_sensors.left
distance_sensor_left[:, 1] += np.sin(self.poses[:, 2]) * self.left_distance distance_sensor_left[:, 1] += np.sin(self.poses[:, 2]) * self.distance_sensors.left
# right sensor # right sensor
poses_right_90 = np.radians(self.poses[:, 2] - 90) poses_right_90 = np.radians(self.poses[:, 2] - 90)
distance_sensor_right[:, 0] = self.poses[:, 0] + np.cos(poses_right_90) * robot.distance_sensor_from_middle distance_sensor_right[:, 0] = self.poses[:, 0] + np.cos(poses_right_90) * robot.distance_sensor_from_middle
distance_sensor_right[:, 1] = self.poses[:, 1] + np.sin(poses_right_90) * robot.distance_sensor_from_middle distance_sensor_right[:, 1] = self.poses[:, 1] + np.sin(poses_right_90) * robot.distance_sensor_from_middle
# now project forward by distance sensor range # now project forward by distance sensor range
distance_sensor_right[:, 0] += np.cos(self.poses[:, 2]) * self.left_distance distance_sensor_right[:, 0] += np.cos(self.poses[:, 2]) * self.distance_sensors.right
distance_sensor_right[:, 1] += np.sin(self.poses[:, 2]) * self.left_distance distance_sensor_right[:, 1] += np.sin(self.poses[:, 2]) * self.distance_sensors.right
await asyncio.sleep(0) await asyncio.sleep(0)
# weighted poses a numpy array of weights for each pose # weighted poses a numpy array of weights for each pose
@@ -134,15 +159,14 @@ class Simulation:
return np.array([self.poses[n] for n in samples]) return np.array([self.poses[n] for n in samples])
def convert_odometry_to_motion(self, left_encoder_delta, right_encoder_delta): def convert_odometry_to_motion(self, left_encoder_delta, right_encoder_delta):
# convert odometry to motion """
# left_encoder is the change in the left encoder left_encoder is the change in the left encoder
# right_encoder is the change in the right encoder right_encoder is the change in the right encoder
# returns rot1, trans, rot2 returns rot1, trans, rot2
# rot1 is the rotation of the robot in radians before the translation rot1 is the rotation of the robot in degrees before the translation
# trans is the distance the robot has moved in mm trans is the distance the robot has moved in mm
# rot2 is the rotation of the robot in radians rot2 is the rotation of the robot in degrees
"""
# convert encoder counts to mm
left_mm = left_encoder_delta * robot.ticks_to_mm left_mm = left_encoder_delta * robot.ticks_to_mm
right_mm = right_encoder_delta * robot.ticks_to_mm right_mm = right_encoder_delta * robot.ticks_to_mm
@@ -150,13 +174,13 @@ class Simulation:
# no rotation # no rotation
return 0, left_mm, 0 return 0, left_mm, 0
# calculate the ICC # calculate the radius of the arc
radius = (robot.wheelbase_mm / 2) * (left_mm + right_mm) / (right_mm - left_mm) radius = (robot.wheelbase_mm / 2) * (left_mm + right_mm) / (right_mm - left_mm)
## arc length/radius = angle ## angle = difference in steps / wheelbase
theta = (right_mm - left_mm) / robot.wheelbase_mm d_theta = (right_mm - left_mm) / robot.wheelbase_mm
# For a small enough motion, assume that the chord length = arc length # For a small enough motion, assume that the chord length = arc length
arc_length = theta * radius arc_length = d_theta * radius
rot1 = np.degrees(theta/2) rot1 = np.degrees(d_theta/2)
rot2 = rot1 rot2 = rot1
return rot1, arc_length, rot2 return rot1, arc_length, rot2
@@ -166,7 +190,6 @@ class Simulation:
new_encoder_left = robot.left_encoder.read() new_encoder_left = robot.left_encoder.read()
new_encoder_right = robot.right_encoder.read() new_encoder_right = robot.right_encoder.read()
await asyncio.sleep(0)
rot1, trans, rot2 = self.convert_odometry_to_motion( rot1, trans, rot2 = self.convert_odometry_to_motion(
new_encoder_left - self.last_encoder_left, new_encoder_left - self.last_encoder_left,
new_encoder_right - self.last_encoder_right) new_encoder_right - self.last_encoder_right)
@@ -187,66 +210,31 @@ class Simulation:
else: else:
print("Failed to get heading") print("Failed to get heading")
await asyncio.sleep(0) await asyncio.sleep(0)
rot1_model = np.array([get_triangular_sample(rot1, self.rotation_standard_dev) for _ in range(self.poses.shape[0])]) rot1_model = np.array([get_scaled_sample_around_mean(rot1, self.rotation_scale) for _ in range(self.poses.shape[0])])
trans_model = np.array([get_triangular_sample(trans, self.speed_standard_dev) for _ in range(self.poses.shape[0])]) trans_model = np.array([get_scaled_sample_around_mean(trans, self.speed_scale) for _ in range(self.poses.shape[0])])
rot2_model = np.array([get_triangular_sample(rot2, self.rotation_standard_dev) for _ in range(self.poses.shape[0])]) rot2_model = np.array([get_scaled_sample_around_mean(rot2, self.rotation_scale) for _ in range(self.poses.shape[0])])
self.poses[:,2] += rot1_model self.poses[:,2] += rot1_model
rot1_radians = np.radians(self.poses[:,2]) rot1_radians = np.radians(self.poses[:,2])
self.poses[:,0] += trans_model * np.cos(rot1_radians) self.poses[:,0] += trans_model * np.cos(rot1_radians)
self.poses[:,1] += trans_model * np.sin(rot1_radians) self.poses[:,1] += trans_model * np.sin(rot1_radians)
self.poses[:,2] += rot2_model self.poses[:,2] += rot2_model
self.poses[:,2] = np.vectorize(lambda n: float(n % 360))(self.poses[:,2]) self.poses[:,2] = np.array([float(theta % 360) for theta in self.poses[:,2]])
self.poses = np.array(self.poses, dtype=np.int16)
async def distance_sensor_updater(self): async def main(self):
robot.left_distance.distance_mode = 2 asyncio.create_task(self.distance_sensors.main())
robot.right_distance.distance_mode = 2 asyncio.create_task(self.collision_avoider.main())
robot.left_distance.timing_budget = 50
robot.right_distance.timing_budget = 50
robot.left_distance.start_ranging()
robot.right_distance.start_ranging()
while True:
if robot.left_distance.data_ready and robot.left_distance.distance:
self.left_distance = robot.left_distance.distance * 10 # convert to mm
robot.left_distance.clear_interrupt()
if robot.right_distance.data_ready and robot.right_distance.distance:
self.right_distance = robot.right_distance.distance * 10
robot.right_distance.clear_interrupt()
self.collision_avoider.update(self.left_distance, self.right_distance)
await asyncio.sleep(0.01)
async def run(self):
asyncio.create_task(self.distance_sensor_updater())
asyncio.create_task(self.collision_avoider.run())
self.last_heading = robot.imu.euler[0] self.last_heading = robot.imu.euler[0]
self.last_encoder_left = robot.left_encoder.read()
self.last_encoder_right = robot.right_encoder.read()
try: try:
while True: while True:
weights = await self.apply_sensor_model() weights = await self.apply_sensor_model()
send_poses(self.resample(weights, 20)) send_poses(self.resample(weights, 20))
self.poses = self.resample(weights, self.population_size) self.poses = self.resample(weights, self.population_size)
await asyncio.sleep(0)
await self.motion_model() await self.motion_model()
finally: finally:
robot.stop() robot.stop()
def read_command():
data = robot.uart.readline()
try:
decoded = data.decode()
except UnicodeError:
print("UnicodeError decoding :")
print(data)
return None
try:
request = json.loads(decoded)
except ValueError:
print("ValueError reading json from:")
print(decoded)
return None
return request
async def updater(simulation): async def updater(simulation):
@@ -274,21 +262,20 @@ async def command_handler(simulation):
while True: while True:
if robot.uart.in_waiting: if robot.uart.in_waiting:
print("Receiving data...") print("Receiving data...")
request = read_command() request = read_json()
if not request: if not request:
print("no request") print("no request")
continue continue
print("Received: ", request)
if request["command"] == "arena": if request["command"] == "arena":
send_json( send_json({
{ "arena": arena.boundary_lines,
"arena": arena.boundary_lines })
}
)
if not update_task: if not update_task:
update_task = asyncio.create_task(updater(simulation)) update_task = asyncio.create_task(updater(simulation))
elif request["command"] == "start": elif request["command"] == "start":
if not simulation_task: if not simulation_task:
simulation_task = asyncio.create_task(simulation.run()) simulation_task = asyncio.create_task(simulation.main())
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
+1 -4
View File
@@ -4,7 +4,6 @@ import pio_encoder
import busio import busio
import adafruit_vl53l1x import adafruit_vl53l1x
import math import math
import busio
import adafruit_bno055 import adafruit_bno055
uart = busio.UART(board.GP12, board.GP13, baudrate=9600) uart = busio.UART(board.GP12, board.GP13, baudrate=9600)
@@ -18,6 +17,7 @@ ticks_to_mm = wheel_circumference_mm / ticks_per_revolution
ticks_to_m = ticks_to_mm / 1000 ticks_to_m = ticks_to_mm / 1000
m_to_ticks = 1 / ticks_to_m m_to_ticks = 1 / ticks_to_m
wheelbase_mm = 170 wheelbase_mm = 170
distance_sensor_from_middle = 40 # approx mm
motor_A2 = pwmio.PWMOut(board.GP17, frequency=100) motor_A2 = pwmio.PWMOut(board.GP17, frequency=100)
motor_A1 = pwmio.PWMOut(board.GP16, frequency=100) motor_A1 = pwmio.PWMOut(board.GP16, frequency=100)
@@ -36,10 +36,7 @@ i2c1 = busio.I2C(sda=board.GP2, scl=board.GP3)
left_distance = adafruit_vl53l1x.VL53L1X(i2c0) left_distance = adafruit_vl53l1x.VL53L1X(i2c0)
right_distance = adafruit_vl53l1x.VL53L1X(i2c1) right_distance = adafruit_vl53l1x.VL53L1X(i2c1)
distance_sensor_from_middle = 40 # approx mm
imu = adafruit_bno055.BNO055_I2C(i2c0) imu = adafruit_bno055.BNO055_I2C(i2c0)
imu.mode = adafruit_bno055.NDOF_MODE # should be in chapter 12!
def stop(): def stop():
motor_A1.duty_cycle = 0 motor_A1.duty_cycle = 0
@@ -19,7 +19,9 @@ class BleConnection:
async def connect(self): async def connect(self):
print("Scanning for devices...") print("Scanning for devices...")
devices = await bleak.BleakScanner.discover(service_uuids=[self.ble_uuid]) devices = await bleak.BleakScanner.discover(
service_uuids=[self.ble_uuid]
)
print(f"Found {len(devices)} devices") print(f"Found {len(devices)} devices")
print([device.name for device in devices]) print([device.name for device in devices])
ble_device_info = [device for device in devices if device.name==self.ble_name][0] ble_device_info = [device for device in devices if device.name==self.ble_name][0]