This is unofficial toio control API for python users. Suitable to handle asynchronous operations using several toio cubes.
これはtoio好きのtoio好きによるtoio好きのための非公式APIです。Pythonで複数のtoioキューブを非同期制御したい方向けのライブラリです。
基本的に$ python main.py
または$ python gui_main.py
で実行できます。toioの行動パターンは実装した「シナリオ」に基づいており、例として以下の4つのシナリオを用意しています。
spin • run_spin • chase • collision_avoidance
main.py
ではmake_scenario(scenario_name='spin', ...)
がデフォルトで設定されていますが、その他のシナリオでtoioを制御したい場合は該当するシナリオ名に変更してください。
# main.py
import asyncio
from toio_API.scenarios import make_scenario
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'])
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通信が開始されます。scenario.run()
: 作成したシナリオを実行します。
gui_main.py
を実行すると以下のようなGUIがが出力されます。左下のバーより任意のシナリオを選択してRun toio
を押してください。
4つのシナリオの実装コードです。たったの数行のコードでtoioを簡単に制御できます。
toioがグルグルとその場で回転して、5秒後に停止します。
# scenarios/examples/spin.py
class Spin(AbstractSenario):
async def _main(self):
for _ in range(50):
await asyncio.gather(*[toio.motor.control() for toio in self.toios])
await asyncio.sleep(0.1)
toioが1秒間走り、その後1秒間スピンします。
# scenarios/examples/run_spin.py
class RunSpin(AbstractSenario):
async def _main(self):
await asyncio.gather(*[self.__run_spin(toio) for toio in self.toios])
async def __run_spin(self, toio: Toio):
await toio.motor.control(left_speed=100, right_speed=100)
await asyncio.sleep(1)
await toio.motor.control(left_speed=-100, right_speed=100)
await asyncio.sleep(1)
2体以上のtoioが必要です。1体のtoioに目掛けてその他のtoioが追いかけます。
# scenarios/examples/chase.py
class Chase(AbstractSenario):
async def _main(self):
for _ in range(50):
response = await read_information(self.toios)
await asyncio.gather(*[self.__chase(toio, toio_idx, **response) for toio_idx, toio in enumerate(self.toios)])
await asyncio.sleep(0.1)
async def __chase(self, toio: Toio, toio_idx: int, **kwargs):
if toio_idx == 0:
await toio.motor.acceleration_control(rotation_speed=90)
else:
await toio.motor.target_control(
max_speed=50,
x_coordinate=kwargs[self.toios[0].name]['center_x'],
y_coordinate=kwargs[self.toios[0].name]['center_y']
)
2体のtoioが必要です。toioを互いの正面に向き合わせて実行します。初めに直進しますが、近づいたら衝突回避行動をします。
# scenarios/examples/collision_avoidance.py
class CollisionAvoidance(AbstractSenario):
async def _main(self):
for _ in range(50):
response = await read_information(self.toios)
await asyncio.gather(*[self.__chase(toio, toio_idx, **response) for toio_idx, toio in enumerate(self.toios)])
await asyncio.sleep(0.01)
async def __chase(self, toio: Toio, toio_idx: int, **kwargs):
distance = math.dist(
[kwargs[self.toios[0].name]['center_x'], kwargs[self.toios[0].name]['center_y']],
[kwargs[self.toios[1].name]['center_x'], kwargs[self.toios[1].name]['center_y']]
)
if distance < 70:
await toio.motor.control(-10, -10)
else:
await toio.motor.control(left_speed=50, right_speed=50)
自分のオリジナルコードでtoioを制御する場合、scenarios/customs/
に用意したカスタムシナリオにコーディングしてください(Custom1 ~ Custom3まで実装できます)。完成したらmain.py
でシナリオ名を'custom1'に変更して実行してみましょう!
# scenarios/customs/custom1.py
class Custom1(AbstractSenario):
async def _main(self):
raise NotImplementedError()