Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 16 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,18 @@
<a href="#about">About</a> •
<a href="#how-to-use">How To Use</a> •
<a href="#examples">Examples</a> •
<a href="#customs">Customs</a> •
<a href="https://toio.io/blog/detail/20210412_toioClub.html">Community</a> •
<a href="https://github.com/Yoshi-0921/toio_API/blob/main/LICENSE">License</a>
</p>
</div>

## About
This is unofficial toio control API for python users. Suitable to handle asynchronous operations using several toio cubes.
This is unofficial toio control API for python users. Suitable to handle asynchronous operations using several toio cubes.

これはtoio好きのtoio好きによるtoio好きのための非公式APIです。Pythonで複数のtoioキューブを非同期制御したい方向けのライブラリです。

## How To Use
基本的に`$ python main.py`または`$ python gui_main.py`で実行できます。toioの行動パターンは実装した「シナリオ」に基づいており、例として以下の4つのシナリオを用意しています。
基本的に`$ python main.py`または`$ python gui_main.py`で実行できます。toioキューブの行動パターンは実装した「シナリオ」に基づいており、例として以下の4つのシナリオを用意しています。

<p align="center">
<a href="#spin">spin</a> •
Expand All @@ -33,7 +32,7 @@ This is unofficial toio control API for python users. Suitable to handle asynchr
<a href="#collision-avoidance">collision_avoidance</a>
</p>

`main.py`では`make_scenario(scenario_name='spin', ...)`がデフォルトで設定されていますが、その他のシナリオでtoioを制御したい場合は該当するシナリオ名に変更してください
`main.py`では`make_scenario(scenario_name='spin', ...)`がデフォルトで設定されていますが、その他のシナリオでtoioキューブを制御したい場合は該当するシナリオ名に変更してください

```py
# main.py
Expand All @@ -45,23 +44,23 @@ from toio_API.utils.general import create_toios, discover_toios

if __name__ == '__main__':
toio_addresses = asyncio.run(discover_toios())
toios = create_toios(toio_addresses=toio_addresses, toio_names=['Yoshi', 'Moto'])
toios = create_toios(toio_addresses=toio_addresses)
scenario = make_scenario(scenario_name='spin', toios=toios)

scenario.run()
```
#### その他
- `asyncio.run(discover_toios())`: 接続可能なtoioを見つけます。発見できた場合、そのtoioのBLE_addressがリスト型で返されます
- `create_toios(toio_addresses)`: 見つけたtoioのBLE_addresを基にtoio制御クラスを作成します。引数に名前も設定できます
- `make_scenario(toios)`: toioの行動パターンを決めるシナリオを作成します。この時、自動的にtoioとのBLE通信が開始されます
- `asyncio.run(discover_toios())`: 接続可能なtoioキューブを見つけます。発見できた場合、そのtoioキューブのBLE_addressがリスト型で返されます
- `create_toios(toio_addresses)`: 見つけたtoioキューブのBLE_addresを基にtoio制御クラスを作成します。引数に名前`(toio_names)`も設定できます
- `make_scenario(toios)`: toioの行動パターンを決めるシナリオを作成します。この時、自動的にtoioキューブとのBLE通信が開始されます
- `scenario.run()`: 作成したシナリオを実行します。 

`gui_main.py`を実行すると以下のようなGUIがが出力されます。左下のバーより任意のシナリオを選択して`Run toio`を押してください。
<p align="center"><img width="300" alt="GUI" src="https://user-images.githubusercontent.com/60799014/119652718-6cb77680-be61-11eb-8661-cab4ecc277fa.png"></p>


## Examples
4つのシナリオの実装コードです。たったの数行のコードでtoioを簡単に制御できます
4つのシナリオの実装コードです。たったの数行のコードでtoioキューブを簡単に制御できます

### Spin
toioがグルグルとその場で回転して、5秒後に停止します。
Expand All @@ -79,7 +78,7 @@ class Spin(AbstractSenario):
[Demo video clip](https://youtu.be/rINq-bm9uKI)

### Run and Spin
toioが1秒間走り、その後1秒間スピンします
toioキューブが1秒間走り、その後1秒間スピンします

```py
# scenarios/examples/run_spin.py
Expand All @@ -98,7 +97,7 @@ class RunSpin(AbstractSenario):
[Demo video clip](https://youtu.be/3fU0nKxnZRQ)

### Chase
2体以上のtoioが必要です。1体のtoioに目掛けてその他のtoioが追いかけます
2体以上のtoioキューブが必要です。1体のtoioキューブに目掛けてその他のtoioキューブが追いかけます

```py
# scenarios/examples/chase.py
Expand All @@ -124,7 +123,7 @@ class Chase(AbstractSenario):
[Demo video clip](https://youtu.be/juGjJ5iSx_k)

### Collision Avoidance
2体のtoioが必要です。toioを互いの正面に向き合わせて実行します。初めに直進しますが、近づいたら衝突回避行動をします。
2体のtoioキューブが必要です。toioキューブを互いの正面に向き合わせて実行します。初めに直進しますが、近づいたら衝突回避行動をします。

```py
# scenarios/examples/collision_avoidance.py
Expand All @@ -149,13 +148,9 @@ class CollisionAvoidance(AbstractSenario):

[Demo video clip](https://youtu.be/1LJGxODB4vM)

## Customs
自分のオリジナルコードでtoioを制御する場合、`scenarios/customs/`に用意したカスタムシナリオにコーディングしてください(Custom1 ~ Custom3まで実装できます)。完成したら`main.py`でシナリオ名を'custom1'に変更して実行してみましょう!

```
# scenarios/customs/custom1.py

class Custom1(AbstractSenario):
async def _main(self):
raise NotImplementedError()
```
## Joy Stick Control
複数台のPS3コントローラーでtoioキューブを非同期操作することができます。
- まず、通常のBluetooth通信でマシンとPS3コントローラーを接続します。
- `scenario_name='joy_stick'`と設定し、`main.py`を実行します。
<p align="center"><img width="300" alt="GUI" src="https://user-images.githubusercontent.com/60799014/150722667-dcd925c0-9fe5-41b8-b969-7ecf1ae8b4d4.png"></p>
5 changes: 4 additions & 1 deletion gui_main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
"""Source code for the GUI main entry.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

from toio_API.utils.tkinter_setup import toioDefaultWindow

Expand Down
13 changes: 10 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
"""Source code for the main entry.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

import asyncio

Expand All @@ -7,5 +10,9 @@

if __name__ == "__main__":
toio_addresses = asyncio.run(discover_toios())
toios = create_toios(toio_addresses=toio_addresses, toio_names=["Yoshi", "Moto"])
scenario = make_scenario(scenario_name="spin", toios=toios)
toios = create_toios(
toio_addresses=toio_addresses
)
scenario = make_scenario(scenario_name="joy_stick", toios=toios)

scenario.run()
3 changes: 1 addition & 2 deletions toio_API/characteristics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
from .id_information import Reader
from .light_control import Lamp
from .motor_control import Motor
from .sensor_information import MotionSensor
from .sensor_information import MagneticSensor
from .sensor_information import MagneticSensor, MotionSensor
from .sound_control import Sound

__all__ = [
Expand Down
5 changes: 4 additions & 1 deletion toio_API/characteristics/abstract_characteristic.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
"""Source code for the abstract characteristic class.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

from abc import ABC
from typing import Dict
Expand Down
5 changes: 4 additions & 1 deletion toio_API/characteristics/battery_information.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
"""Source code for the Battery characteristic class.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

from typing import Dict

Expand Down
5 changes: 4 additions & 1 deletion toio_API/characteristics/button_information.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
"""Source code for the Button characteristic class.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

from typing import Dict

Expand Down
5 changes: 4 additions & 1 deletion toio_API/characteristics/configuration.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
"""Source code for the Configuration characteristic class.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

from typing import Dict

Expand Down
5 changes: 4 additions & 1 deletion toio_API/characteristics/id_information.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
"""Source code for the Reader characteristic class.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

from typing import Dict

Expand Down
5 changes: 4 additions & 1 deletion toio_API/characteristics/light_control.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
"""Source code for the Lamp characteristic class.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

from typing import List

Expand Down
7 changes: 5 additions & 2 deletions toio_API/characteristics/motor_control.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
"""Source code for the Motor characteristic class.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

from typing import Dict, List

Expand Down Expand Up @@ -233,7 +236,7 @@ async def acceleration_control(
- The acceleration should be [0, 255] and 0 is for constant speed.
- Defaults to 5.
rotation_speed (int, optional): Rotationalal speed of toio.
- Set it in [0, 65535] and the unit is degrees/sec.
- Set it in [0, 65535] and the unit is degrees/sec.
- Defaults to 15.
rotation_direction (int, optional): Rotationalal direction of toio.
- Set 0 for veering clockwise.
Expand Down
5 changes: 4 additions & 1 deletion toio_API/characteristics/sensor_information.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
"""Source code for the MotionSensor characteristic class.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

from typing import Dict

Expand Down
5 changes: 4 additions & 1 deletion toio_API/characteristics/sound_control.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
"""Source code for the Sound characteristic class.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

from typing import List

Expand Down
17 changes: 5 additions & 12 deletions toio_API/scenarios/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# -*- coding: utf-8 -*-

from typing import List

from toio_API.utils.logging import initialize_logging
from toio_API.utils.toio import Toio

from .examples import BallChase, Chase, CollisionAvoidance, RunSpin, Spin, AimDests
from .customs import Custom1, Custom2, Custom3
from .examples import (AimDests, BallChase, Chase, CollisionAvoidance,
JoyStickControl, RunSpin, Spin)

logger = initialize_logging(__name__)

Expand All @@ -18,6 +16,7 @@
"collision_avoidance",
"run_spin",
"spin",
"control",
]


Expand All @@ -40,14 +39,8 @@ def make_scenario(scenario_name: str = "spin", toios: List[Toio] = None):
elif scenario_name == "spin":
scenario = Spin(toios=toios)

elif scenario_name == "custom_1":
scenario = Custom1(toios=toios)

elif scenario_name == "custom_2":
scenario = Custom2(toios=toios)

elif scenario_name == "custom_3":
scenario = Custom3(toios=toios)
elif scenario_name == "joy_stick":
scenario = JoyStickControl(toios=toios)

else:
logger.warn(f"Invalid scenario name is given. scenario_name: {scenario_name}")
Expand Down
7 changes: 5 additions & 2 deletions toio_API/scenarios/abstract_scenario.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
"""Source code for the abstract scenario class.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

import asyncio
from abc import ABC, abstractmethod
Expand All @@ -8,7 +11,7 @@
from toio_API.utils.toio import Toio


class AbstractSenario(ABC):
class AbstractScenario(ABC):
def __init__(self, toios: List[Toio]) -> None:
self.__toios = toios
self.__num_toios = len(self.__toios)
Expand Down
7 changes: 0 additions & 7 deletions toio_API/scenarios/customs/__init__.py

This file was deleted.

8 changes: 0 additions & 8 deletions toio_API/scenarios/customs/custom1.py

This file was deleted.

8 changes: 0 additions & 8 deletions toio_API/scenarios/customs/custom2.py

This file was deleted.

8 changes: 0 additions & 8 deletions toio_API/scenarios/customs/custom3.py

This file was deleted.

13 changes: 10 additions & 3 deletions toio_API/scenarios/examples/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
# -*- coding: utf-8 -*-

from .aim_dests import AimDests
from .ball_chase import BallChase
from .chase import Chase
from .collision_avoidance import CollisionAvoidance
from .run_spin import RunSpin
from .spin import Spin
from .joy_stick_toio import JoyStickControl

__all__ = ["AimDests", "BallChase", "Chase", "CollisionAvoidance", "RunSpin", "Spin"]
__all__ = [
"AimDests",
"BallChase",
"Chase",
"CollisionAvoidance",
"RunSpin",
"Spin",
"JoyStickControl",
]
9 changes: 6 additions & 3 deletions toio_API/scenarios/examples/aim_dests.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# -*- coding: utf-8 -*-
"""Source code for the AimDests scenario class.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

import asyncio
import math
from toio_API.scenarios.abstract_scenario import AbstractSenario
from toio_API.scenarios.abstract_scenario import AbstractScenario
from toio_API.utils.general import read_information
from toio_API.utils.toio import Toio
from copy import deepcopy
Expand All @@ -11,7 +14,7 @@
IMAGE_WIDTH = 600


class AimDests(AbstractSenario):
class AimDests(AbstractScenario):
async def _main(self, **kwargs):
print(kwargs["converted_ovals"])
self.dests = [
Expand Down
9 changes: 6 additions & 3 deletions toio_API/scenarios/examples/ball_chase.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
# -*- coding: utf-8 -*-
"""Source code for the BallChase scenario class.

Author: Yoshinari Motokawa <yoshinari.moto@fuji.waseda.jp>
"""

import asyncio
import cv2
from toio_API.camera.ball import convert_ball_position, get_ball_center
from toio_API.scenarios.abstract_scenario import AbstractSenario
from toio_API.scenarios.abstract_scenario import AbstractScenario
from toio_API.utils.general import read_information
from toio_API.utils.toio import Toio
import math


class BallChase(AbstractSenario):
class BallChase(AbstractScenario):
async def _main(self, **kwargs):
capture = cv2.VideoCapture(1)

Expand Down
Loading