-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7a6c93d
commit b0c7285
Showing
21 changed files
with
3,712 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
wheels/ | ||
share/python-wheels/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
MANIFEST | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
|
||
# Installer logs | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.nox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
*.py,cover | ||
.hypothesis/ | ||
.pytest_cache/ | ||
cover/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
db.sqlite3 | ||
db.sqlite3-journal | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
.pybuilder/ | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# IPython | ||
profile_default/ | ||
ipython_config.py | ||
|
||
# pyenv | ||
# For a library or package, you might want to ignore these files since the code is | ||
# intended to run in multiple environments; otherwise, check them in: | ||
# .python-version | ||
|
||
# pipenv | ||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. | ||
# However, in case of collaboration, if having platform-specific dependencies or dependencies | ||
# having no cross-platform support, pipenv may install dependencies that don't work, or not | ||
# install all needed dependencies. | ||
#Pipfile.lock | ||
|
||
# poetry | ||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. | ||
# This is especially recommended for binary packages to ensure reproducibility, and is more | ||
# commonly ignored for libraries. | ||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control | ||
#poetry.lock | ||
|
||
# pdm | ||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. | ||
#pdm.lock | ||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it | ||
# in version control. | ||
# https://pdm.fming.dev/#use-with-ide | ||
.pdm.toml | ||
|
||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm | ||
__pypackages__/ | ||
|
||
# Celery stuff | ||
celerybeat-schedule | ||
celerybeat.pid | ||
|
||
# SageMath parsed files | ||
*.sage.py | ||
|
||
# Environments | ||
.env | ||
.venv | ||
env/ | ||
venv/ | ||
ENV/ | ||
env.bak/ | ||
venv.bak/ | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
.spyproject | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# mkdocs documentation | ||
/site | ||
|
||
# mypy | ||
.mypy_cache/ | ||
.dmypy.json | ||
dmypy.json | ||
|
||
# Pyre type checker | ||
.pyre/ | ||
|
||
# pytype static type analyzer | ||
.pytype/ | ||
|
||
# Cython debug symbols | ||
cython_debug/ | ||
|
||
# PyCharm | ||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can | ||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore | ||
# and can be added to the global gitignore or merged into this file. For a more nuclear | ||
# option (not recommended) you can uncomment the following to ignore the entire idea folder. | ||
#.idea/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Define hooks for code formations | ||
# Will be applied on any updated commit files if a user has installed and linked commit hook | ||
|
||
default_language_version: | ||
python: python3.9 | ||
|
||
repos: | ||
- repo: https://github.com/pre-commit/pre-commit-hooks | ||
rev: v4.4.0 | ||
hooks: | ||
# - id: end-of-file-fixer | ||
- id: trailing-whitespace | ||
- id: check-case-conflict | ||
- id: check-yaml | ||
- id: check-toml | ||
- id: pretty-format-json | ||
- id: check-docstring-first | ||
|
||
# - repo: https://github.com/asottile/pyupgrade | ||
# rev: v3.3.0 | ||
# hooks: | ||
# - id: pyupgrade | ||
# name: Upgrade code | ||
# args: [ --py37-plus ] | ||
|
||
- repo: https://github.com/PyCQA/isort | ||
rev: 5.10.1 | ||
hooks: | ||
- id: isort | ||
name: Sort imports | ||
|
||
- repo: https://github.com/pre-commit/mirrors-yapf | ||
rev: v0.32.0 | ||
hooks: | ||
- id: yapf | ||
name: YAPF formatting | ||
|
||
# - repo: https://github.com/executablebooks/mdformat | ||
# rev: 0.7.16 | ||
# hooks: | ||
# - id: mdformat | ||
# name: MD formatting | ||
# additional_dependencies: | ||
# - mdformat-gfm | ||
# - mdformat-black | ||
# exclude: "README.md|README.zh-CN.md" | ||
|
||
# - repo: https://github.com/asottile/yesqa | ||
# rev: v1.4.0 | ||
# hooks: | ||
# - id: yesqa | ||
|
||
- repo: https://github.com/PyCQA/flake8 | ||
rev: 6.0.0 | ||
hooks: | ||
- id: flake8 | ||
name: PEP8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,75 @@ | ||
# MindstormsDashboard | ||
# MindstormsDashboard | ||
|
||
This project contains a desktop dashboard for connecting with the M.V.P car bot from the Lego Mindstorms Spike Prime collection. It allows the user to control the bot using controller inputs, and see the bot's view from their phone camera. | ||
|
||
In short, it contains the following: | ||
|
||
* [PySide6](https://wiki.qt.io/Qt_for_Python) based GUI application. | ||
* Connection to Spike Prime hub with USB or Bluetooth serial connections using the [mindstorms](https://github.com/noamraph/mindstorms) package. This allows the program to execute commands on the hub using the MicroPython REPL. | ||
* Connection to gamepads using the [pygame](https://github.com/pygame/pygame) library to manually drive the bot. | ||
* Live videostream from webcam or phone camera using [OpenCV](https://opencv.org/). | ||
* [YOLOv5](https://github.com/ultralytics/yolov5) based object detection from the camera view. | ||
|
||
 | ||
|
||
## Installation | ||
|
||
Clone the repository and install the dependencies. | ||
|
||
```bash | ||
git clone ... | ||
pip install -r requirements.txt | ||
``` | ||
|
||
## Usage | ||
|
||
To run the dashboard, execute the `run.py` script: | ||
|
||
```bash | ||
python run.py | ||
``` | ||
|
||
## Hub Connection | ||
|
||
The dasboard can currently connect to Lego car bots using a two motor configuration. Here, one motor is used as the car's engine, and the other to steer the front wheels. | ||
|
||
### Serial Port | ||
|
||
The dasboard can be used to connect to the Spike Prime hub using its serial connection. This can be established using a USB cable or using Bluetooth. The program can autodiscover hubs connected by USB when the `USB` port is selected. For Bluetooth connections, the specific COM port needs to be selected from the dropdown menu. | ||
|
||
### Engine Ports | ||
|
||
The engine ports can be selected using the dropdown menu's. The characters `A` to `F` represent the hub's connection ports. When using the default M.V.P. build, the engine and steer motors should be connected to ports `B` and `A` respectively. | ||
|
||
## Controller connection | ||
|
||
Gamepads can be connected using the PyGame package. Connect your controller and select it from the dropdown menu. The available controls are as follows: | ||
|
||
| Control | Button | | ||
|------------|-------------------| | ||
| Forward | Right-Trigger | | ||
| Backward | Left-Trigger | | ||
| Left/Right | Left-Stick X-axis | | ||
| Beep | A | | ||
|
||
## Video Stream | ||
|
||
### Phone Camera | ||
A video stream is established using OpenCV. By default, the application attempts to connect to a connected webcam. You can use this option to connect to, for example, your phone camera which is mounted to the bot. To do this, follow these steps: | ||
|
||
* Download an IP camera app like [this one](https://play.google.com/store/apps/details?id=com.pas.webcam) and install it on your mobile device. | ||
* Follow the app's instruction to start the server to stream the camera feed | ||
* Note the server's IP address and fill this into the dashboard's `video` field: | ||
``` | ||
http://111.111.1.111:8080/video | ||
``` | ||
* Press `connect` to start the new video stream | ||
### Object Detection | ||
The YOLOv5 object detection model can be used to detect objects from the video feed. To enable this, check the `Object Detection` checkbox. This will use the YOLOv5s COCO model to detect 80 object classes. | ||
## Ideas | ||
* [ ] Sensor panel to monitor the bot's sensors | ||
* [ ] Autonomous mode: Use bot sensors + video stream to avoid obstacles |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import logging | ||
|
||
from mindstorms import Hub | ||
from PySide6.QtCore import QThread | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
class Bot: | ||
|
||
def __init__(self, serial_port: str, motor_speed_port: str, motor_steer_port: str) -> None: | ||
self.serial_port = serial_port | ||
self.motor_speed_port = motor_speed_port | ||
self.motor_steer_port = motor_steer_port | ||
|
||
self.connect_hub() | ||
|
||
def connect_hub(self): | ||
self.hub = Hub(device=self.serial_port) | ||
self.motor_speed = eval(f"self.hub.port.{self.motor_speed_port}.motor") | ||
self.motor_steer = eval(f"self.hub.port.{self.motor_steer_port}.motor") | ||
|
||
QThread.msleep(700) | ||
|
||
self.motor_steer.mode([(1, 0), (2, 0), (3, 0), (0, 0)]) | ||
self.play_sound('/extra_files/Hello') | ||
|
||
def steer(self, position: int): | ||
log.debug(f"Steering to {position}") | ||
self.motor_steer.run_to_position(position) | ||
|
||
def accelerate(self, speed: int): | ||
self.motor_speed.run_at_speed(speed) | ||
|
||
def get_steer_position(self, relative: bool = True, absolute: bool = False): | ||
_, relative_value, absolute_value, _ = self.motor_steer.get() | ||
|
||
ret = [relative_value, absolute_value | ||
] if relative and absolute else relative_value if relative else absolute_value | ||
return ret | ||
|
||
def set_steer_middle(self, value: int): | ||
log.debug(f"Setting steering middle to {value}") | ||
self.motor_steer.preset(value) | ||
|
||
def disconnect_hub(self): | ||
self.hub.close() | ||
|
||
def play_sound(self, path: str): | ||
self.hub.sound.play(path) |
Oops, something went wrong.