1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ここでは、Windows11で、Sony toio を活用し、PhysicalAIを目指したロボットシミュレーションの検証結果を報告します。

最近では PhysicalAIが注目されており、自分もロボットシミュレーションを試したいと思いました。ここでは、Windows11で、Sony製ロボット「toio:トイオ」を活用する手順を記録してゆきます。

まず、この記事はPythonによる制御の、以下の手順の続きです。

Pythonプログラミングで活用する情報は、以下のウエブ「github - toio.py」が基本情報です。
https://github.com/toio/toio.py/blob/main/README.ja.md

ここでは、「セットアップとチュートリアル」を解説した、以下の「セットアップガイド」にある、「Jupyterによるチュートリアルの実行」を用いた「toio.pyプログラミング」を検証します。
チュートリアルの実行

この資料は、上記で公開されているファイル「tutorial.ja.py」の内容を引用し、これに自分の検証結果を補足しています。動作させているPythonコードは、この記事には示さないので、コードセル内の記述を確認してください。

チュートリアルの準備と実行

リンク「toio.py のチュートリアル tutorial.ja.py」 をダウンロードし、Python作業フォルダ「C:\SonyToio\PythonWork」に保存します。

念の為、Visual Studio Code(以下VScode)で、jupyterを利用する追加の準備を行います。

python -m pip install jupyter

このファイル「tutorial.ja.py」を、PythonとJupyterに対応した「Visual Studio Code」で開きます。最初に起動するとき、ネットワークの接続を確認されますが、「許可」で進めます。

正しく設定されたVScode環境で読み込むと、いくつかの青色(VScodeの背景が白色の場合)の水平線で区切られたコードセルとして表示され、セルの左上に「Run Cell」(VScodeの日本語環境では「セルの実行」)が、表示されます。

自分の環境では、Visual Studio Codeの準備が不完全なのか、ファイルを読み込んだ時に、表示されない場合がありました。その時は、以下の手順で再設定しました。

Ctrl + Shift + X で Extensions を開く。
Python / Microsoft をアンインストール。
Jupyter / Microsoft もアンインストール。
VS Code を完全に終了。
VS Code を再起動。
Extensions から、まず Python / Microsoft (ms-python.python) をインストール。
次に Jupyter / Microsoft (ms-toolsai.jupyter) をインストール。
Ctrl + Shift + P → Developer: Reload Window。

そのあと tutorial.ja.py ファイルを開きます。最初の行の左上に 「Run Cell(セルの実行)」 が表示されたら、クリックします。

以下の表示になれば、準備成功です。

image.png

【 toio.py チュートリアル (v1.1)の実行 】

それでは準備ができたので、「toio.py チュートリアル (v1.1)」を進めてゆきます。ここでは、一つのキューブAをマットの上に置くと、もう一つのキューブBが置かれたキューブに寄ってくる、という動作をするプログラムを作ります。
ここでの動作には、「toioキューブAB2個」と「単体キューブ付属の簡易プレイマット」を使います。
このマットは、用意した「トイオ・プレイグラウンド ベーシック デビューセット」の、toioコアキューブの箱の中にある「方眼状の簡易プレイマット」です。

なお、このチュートリアルはPythonの基礎的知識を持っている人を対象としているので、Pythonの文法や基本的な使い方などについては、各自で確認してください、とのことです。
ただし、コードを理解するために必要な、重要な用語については、簡単に補足説明しています。

■ 必要となるパッケージのインストール

既に、パッケージがインストール済みですが、念の為、「Run Cell(セルの実行)」を実行し、必要とするスクリプトをVScodeのコードセルで実行し、その導入状況を確認します。エラーとかなければよいと思います。

コードセルを実行するには、VSCode上で Run Cell(セルの実行) と表示されている部分をクリックします。このチュートリアルではコードセルを使って動作確認を行います。ここでコードセルの実行方法を確認しておきます。

なお、以下の「Windows11でのSony toioの活用【02:Pythonによる制御】」で導入が確認してあれば、このセルの実行は飛ばしても良いと思います。

■ 環境の確認

下記のスクリプトをVSCodeのコードセルで Run Cell(セルの実行)します。すべて OK と表示されれば必要なソフトウェアが正しくインストールできています。

以下のように、Pyton, bleak, toioの3つの導入を確認します。
image.png

Pythonのみ、メジャーバージョン3の、マイナーバージョン8-12であることを確認しますが、肝心なbleakは確かめていません。自分で、PowerShellから、必要とする「0.22.1」であることを、確かめてください。もし最新の「3.0.2」に、先の導入で更新されてしまっていたら、再インストールしてください。

PS C:\SonyToio\PythonWork> pip show bleak
Name: bleak
Version: 3.0.2
PS C:\SonyToio\PythonWork> pip install bleak==0.22.1
Collecting bleak==0.22.1

PS C:\SonyToio\PythonWork> pip show bleak
Name: bleak
Version: 0.22.1

■ キューブのスキャン、接続、切断

ToioCoreCube.scan()

ToioCoreCube.connect()

ToioCoreCube.disconnect()

使用例と説明

   await cube.scan()
   await cube.connect()
   await cube.disconnect()

ToioCoreCubeのインスタンスを生成し、キューブのスキャン、接続、切断を行います。
具体的には、cubescan() を呼び出した後に connect() を呼び出してキューブと接続し通信が行えるようにします。
切断するときは cubedisconnect() を呼び出します。
scan()connect()disconnect() は非同期関数なので await で完了を待ちます。

非同期関数とは、時間のかかる処理を待っている間も、プログラム全体を止めずに別の処理を進められる関数です。toioでは、Bluetooth通信の待ち時間などに使います。

このコードはキューブと接続し、1秒後に切断します。tryで「エラーが起きるかもしれない処理」を実行し、エラーが起きたらexceptで受け取って処理します。toioでは、Bluetooth通信の失敗などに対応できます。

まずキューブAの電源を入れて、 Run Cell(セルの実行)してみます。ここでは、まだマットは利用していません。キューブの青色点滅は、待機状態です。

以下の結果となります。
image.png

ちなみに、用意したキューブABの2つの電源を入れて実行してみると、同じ表示なので、このコードでは、1つのキューブしか接続していないようです。

■ コンテキストマネージャによるキューブのスキャン、接続、切断

ToioCoreCube()

使用例と説明

   async with ToioCoreCube()

ToioCoreCube クラスはコンテキストマネージャなので、async with 文を使うことでキューブのスキャン、接続、切断を簡単に行うことができます。
コンテキストマネージャとは、処理の「開始」と「終了」を自動的に管理する仕組みです。 with や async with を使い、終了時の後片付けを自動で行います。toioでは、Bluetooth接続を開始し、処理終了時に切断する、といった管理に使います。

こののコードはキューブと接続し、1秒後に切断します。

まずキューブAの電源を入れて、 Run Cell(セルの実行)してみます。ここでは、まだマットは利用していません。

以下の結果となります。
image.png

■ 複数のキューブのスキャン、接続、切断

MultipleToioCoreCubes()

使用例と説明

   async with MultipleToioCoreCubes()

MultipleToioCoreCubes クラスを使うことで、複数のキューブに対してのスキャン、接続、切断を行うことができます。
MultipleToioCoreCubes クラスは ToioCoreCube クラスと同様にコンテキストマネージャなので async with 文を使うことでキューブのスキャン、接続、切断を簡単に行うことができます。

こののコードは2台のキューブABと接続し、1秒後に切断します。

ここでは2台のキューブABの電源を入れて、 Run Cell(セルの実行)してみます。ここでは、まだマットは利用していません。

以下の結果となります。
image.png

2台のキューブABに接続していることが分かります。この表示の「T12, T0k」は、キューブの更新をしたときに、表示されたキューブの名称です。Bluetooth上のデバイス名となり、キューブ個別の識別情報になります。

ちなみに、1台のキューブAのみ電源を入れて実行すると、以下のように、2台目の情報が得られずエラーとなります。
image.png

■ キューブの各機能へのアクセス

キューブのスキャン、接続、切断ができるようになりました。次はキューブが持つ各種機能の制御を行います。
実際に機能制御を行う前に、toio.py でどのように機能にアクセスするのか、その概要を説明します。

ToioCoreCube クラスは api サブクラスを持っています。キューブの機能制御を行うクラスや関数は、この api サブクラス以下に集約されています。

ToioCoreCube.api

ToioCoreCube.api クラスはキューブの各種機能にアクセスするためのインターフェースクラスを集めたクラスです。

ToioCoreCube.api.(インターフェースクラス名)

各種機能にアクセスするためのインターフェースクラスです。
インターフェースクラスは技術仕様書のキャラクタリスティックごとに作られています。
各インターフェースクラスが持つ機能については、各クラスのDocStringを参照してください。

インターフェースクラスの例

  • id_information: IDの読み出し機能を扱うクラス
  • indicator: キューブのランプを制御するクラス
  • motor: キューブのモーターを制御するクラス

ここでは1台のキューブAの電源を入れて、 Run Cell(セルの実行)してみます。ここでは、まだマットは利用していません。

以下の結果となります。
image.png

この表示では、cubeが持つインターフェイスクラスの一覧が表示されます。

■ インターフェースクラス

各種機能にアクセスするためのインターフェースクラスは、いくつかの共通したメソッドを持ちます。

共通のスタティックメソッド

is_my_data(data: bytearray)

各キャラクタリスティクに対応するインターフェースクラスは is_my_data(data: bytearray) スタティックメソッドを持ちます。
is_my_data() は、引数のデータが自キャラクタリスティクの読み出しまたは通知データの場合にはデータに対応するオブジェクトを返し、それ以外では None を返します。

共通のメソッド

register_notification_handler(handler: CubeNotificationHandler)

通知ハンドラ関数(後述)を登録します。

unregister_notification_handler(handler: CubeNotificationHandler)

通知ハンドラ関数(後述)を登録解除します。

ここでは、 Run Cell(セルの実行)しても、動作はありません。

■ IDの読み出し

この検証では、PositionIdを確認するので、「1台のキューブA」と「方眼状の簡易プレイマット」を用意します。このマットは、「toio」の水色の文字が左下にあり、読める状態に置いてください。

ToioCoreCube.api.id_information.read()

使用例と説明

   read_data = await cube.api.id_information.read()

ID Information キャラクタリスティクからの読み出しを行います。

'read_data' は下記いずれかのオブジェクトまたは None です。
'read_data' が下記に示されるどのオブジェクトのフォーマットとも一致しない場合、read() の返値は None になります。
id_information.read() は内部でキャラクタリスティクのスタティックメソッド IdInformation.is_my_data() を呼び出しています)

  • PositionId
  • StandardId
  • PositionIdMissed
  • StandardIdMissed
id_information.read() が返すオブジェクト
PositionId

キューブがPosition IDを検出したことを表すオブジェクトです。

PositionId のアトリビュート

アトリビュート名
center CubeLocation キューブの中心位置座標
sensor CubeLocation キューブの読み取りセンサ位置座標
StandardId

キューブがStandard IDを検出したことを表すオブジェクトです。

StandardId のアトリビュート

アトリビュート名
value int Standard IDの種類
angle int キューブの角度
PositionIdMissed

キューブが Position ID の上から取り除かれたことを表すオブジェクトです。

StandardIdMissed

キューブが Standard ID の上から取り除かれたことを表すオブジェクトです。

このコードは id_information.read() を200回行い、随時、読み出した内容を表示します。

ここでは1台のキューブAの電源を入れて、方眼状の簡易プレイマットの上に置いてから、 Run Cell(セルの実行)してみます。

以下の結果となります。
image.png
image.png

PositionIdを、200回スキャンしています、以下の例を見ると「point=Point (x=168→167, y=217→219), angle=337→336」のように変化していることが分かります。

10 <class 'toio.cube.api.id_information.PositionId'> {'center': CubeLocation(point=Point(x=168, y=217), angle=337),
 'sensor': CubeLocation(point=Point(x=158, y=214), angle=337)}
11 <class 'toio.cube.api.id_information.PositionId'> {'center': CubeLocation(point=Point(x=167, y=219), angle=336),
 'sensor': CubeLocation(point=Point(x=157, y=216), angle=336)}

■ 通知ハンドラ関数によるIDの読み出し

ToioCoreCube.api.id_information.register_notification_handler()

ToioCoreCube.api.id_information.unregister_notification_handler()

使用例と説明

   await cube.api.id_information.register_notification_handler(handler)
   await cube.api.id_information.unregister_notification_handler(handler)

read() で得られる情報は、read()を行ったタイミングでキューブが持っている情報です。
read() では直近の情報しか得られないため、複数回 read() を行ったとしても、各呼び出しの間に変化した情報を得られません。

キューブには通知機能があり、検知した情報を自発的に送信します。
通知ハンドラ関数を設定することにより、キューブが検出した情報を漏らさずPython側で受け取れます。

register_notification_handler() は通知ハンドラ関数を登録します。
unregister_notification_handler() は通知ハンドラ関数を登録解除します。

通知ハンドラ関数

通知ハンドラ関数は bytearray を引数に取り、返値を持ちません。

通常の関数だけでなく非同期関数もハンドラ関数として使えます。通知ハンドラ関数が非同期関数の場合、通知ハンドラ関数は内部で await を使用した処理を実行することができます。

通知ハンドラ関数の引数はキューブから通知されたバイト列のデータです。

このコードは id_information にハンドラ関数を登録し、キューブからの通知を10秒間受けて表示します。

ここでは1台のキューブAの電源を入れて、方眼状の簡易プレイマットの上に置いてから、 Run Cell(セルの実行)してみます。

以下の結果となります。
image.png

image.png

キューブを動かしてみると、通知ハンドラを用いて「point=Point(x=172, y=217), angle=267」の情報が変化していることが分かります。

■ モーター制御

ToioCoreCube.api.motor.motor_control()

使用例と説明

   await cube.api.motor.motor_control(10, 10)
   await cube.api.motor.motor_control(0, 0)
   await cube.api.motor.motor_control(50, -50, 1000)

左右のモーター速度を指定してキューブを動かします。

第3引数はオプションで、モーターの駆動時間を指定します。単位はミリ秒[ms]です。(1秒間動かしたい場合は1000を指定します)

このコードはキューブを速度10で2秒間前進(左右のモーター速度10)させた後、速度50で1秒間回転(左右のモーター速度50,-50の反転)させます。

ここでは1台のキューブAの電源を入れて、方眼状の簡易プレイマットの上に置いてから、 Run Cell(セルの実行)してみます。
(実はここでは、位置情報を利用していないため、マットは利用しなくても動作します。)

以下の結果となります。
image.png

指定通りにキューブが動きました。なお、マットに折り目で山になっていると、乗り越えられない時がありました。
このコードでは、モーターの動きを指示したあとsleep(2)で2秒間動作する方法と、motor_control(50, -50, 1000)でモーターの動きと動作時間を同時に指定する方法、2つがあります。

■ モーター制御(指定位置へ移動)

ToioCoreCube.api.motor.motor_control_target()

使用例と説明

   await cube.api.motor.motor_control_target(
       timeout=5,
       movement_type=MovementType.Linear,
       speed=Speed(
           max=100, speed_change_type=SpeedChangeType.AccelerationAndDeceleration
       ),
       target=TargetPosition(
           cube_location=CubeLocation(point=Point(x=200, y=200), angle=0),
           rotation_option=RotationOption.AbsoluteOptimal,
       ),
   )

このコードでは、マット上の指定した座標へ、任意の初期状態にある1台のキューブを移動させます。

引数

timeout

タイムアウト時間を指定します。単位は秒[s]です。10 を指定した場合、タイムアウト時間は 10 秒になります。タイムアウト時間 0 秒は指定できません。

movement_type

移動タイプを指定します。

説明
MovementType.Curve 回転しながら移動
MovementType.CurveWithoutReverse 回転しながら移動(後退なし)
MovementType.Linear 移動してから回転
speed

スピードパラメータを指定します。スピードパラメータは maxspeed_change_type で構成されます。

max

最高スピードを指定します。スピードは 0 から 255 の範囲で指定します。

speed_change_type

速度変化タイプを指定します。

説明
SpeedChangeType.Constant 速度一定
SpeedChangeType.Acceleration 目標地点まで徐々に加速
SpeedChangeType.Deceleration 目標地点まで徐々に減速
SpeedChangeType.AccelerationAndDeceleration 中間地点まで徐々に加速し、そこから目標地点まで減速
target

目標位置パラメータを指定します。目標位置パラメータは cube_locationrotation_option で構成されます。

cube_location

キューブの位置情報を指定します。キューブの位置情報は Pointangle で構成されます。

Point

キューブの座標を x y で指定します。

angle

キューブの角度を指定します。 0 から 360 の間で指定します。

rotation_option

目標地点でのキューブの角度に関する追加情報を指定します。

角度の意味 回転方向
RotationOption.AbsoluteOptimal 絶対角度 回転量が少ない方向
RotationOption.AbsolutePositive 絶対角度 正方向
RotationOption.AbsoluteNegative 絶対角度 負方向
RotationOption.RelativePositive 絶対角度 正方向
RotationOption.RelativeNegative 相対角度 負方向
RotationOption.WithoutRotation 角度指定なし 回転しない
RotationOption.SameAsWriting 書き込み時と同じ角度 回転量が少ない方向

このコードは、キューブを簡易プレイマット上の座標 (200, 200)へ移動させます。移動の結果は、通知ハンドラ関数「def notification_handler(payload: bytearray)」で取得します。

簡易プレイマットを、左下に「toio」の文字がある状態にして、この上にキューブAを、任意の位置と方向に置いてから、 Run Cell(セルの実行)してみます。

コードの設定から、移動の具体的な設定を確認します。

  • 初期地点から目標地点に向けて、「movement_type=MovementType.Linear」なので、まずキューブの方向へ回転し、直進移動してから、目標地点で指定方向に回転します。
  • 「speed_change_type=SpeedChangeType.AccelerationAndDeceleration」で、中間地点まで徐々に加速し、そこから目標地点まで減速目標地点に移動だけします。
  • 「rotation_option=RotationOption.AbsoluteOptimal」として、「絶対角度指定で回転量が少ない指定した方向」に回転します。

簡易プレイマットは、方眼状のA3用紙の大きさです。下図に示すように、実際のmm寸法ではなく、独自の座標系「X=98~402(304)右向き正」「Y=142~358(216)下向き正」を持っています。マット中央は(250,250)になります。

座標 (200, 300) に移動させるようにコードを修正し実行すると、下図の「位置のイメージ図」の場所(point=Point(x=200, y=300))で止まります。
止まった時に右を向いていますが、これは移動の角度「angle=0」により、X軸+方向から時計方向に、0度で指定した結果です。
初期の位置と方向が、どんな状態でも、指定した位置と方向に、移動しています。

toio管理プレイマットの座標系:PositionID.png

初期状態として、色々な位置や方向に置いて、目標とする位置や方向をコードの記述して、座標や角度を確認してください。

「toio」は、一般的な移動ロボットのように車輪の回転量やカメラ・GPSなど特別な装置から位置を推定するのではなく、toio本体の底面にある光学センサーが、専用マットに印刷された特殊なパターンを読み取ることで、絶対位置と向きを直接取得できる点が大きな利点です。
累積誤差が生じにくく、PCからリアルタイムに位置を取得できるため、ロボット制御やPhysicalAIのSim-to-Real実験に適しています。

■ ふたつのキューブの制御

ここでは、方眼状の簡易プレイマットを左下に「toio」の文字がある状態にして、2台のキューブABの電源を入れて、簡易プレイマットの任意の位置の2つ置きます。

今までの機能を組み合わせて完成を目指します。ふたつのキューブABをスキャンして接続します。
ひとつめのキューブAのランプを緑色に点灯させ、通知ハンドラ関数を登録して座標情報を読み込むようにします。
キューブAからの通知が Position ID の場合は、キューブAの中心座標を グローバル変数 green_cube_location に保存しておきます。

ふたつめのキューブBのランプは赤色に点灯させ、1 秒間回転させます。
キューブBが接続してから 10 秒後に全てのキューブABとの通信を切断して終了します。

具体的な設定は、コードを確認してください。
準備ができたら、 Run Cell(セルの実行)してみます。

以下の結果となります。
image.png
image.png

キューブAを手で移動させてると、位置や方向が、随時表示されています。キューブABとの通信を切断すると、青色ランプの点滅になり、待機状態となります。

■ 完成

まず、任意の位置に2つのキューブABを、方眼状の簡易プレイマット上に置きます。
2つのキューブを「MultipleToioCoreCubes(cubes=2)」で認識して、ひとつめのキューブA(ランプ緑色)が、目標位置です。
ふたつめのキューブB(ランプ赤色)の移動方法を、単純なモーター制御から指定座標への移動へ変更します。
ふたつめのキューブBの目標位置は、ひとつめのキューブAの通知ハンドラで取得した座標です。
座標はグローバル変数 green_cube_location を介して共有します。

具体的な設定は、コードを確認してください。
準備ができたら、 Run Cell(セルの実行)してみます。

以下の結果となります。
image.png
image.png

実行してみたところ、キューブA(ランプ緑色)に向かって、キューブB(ランプ赤色)が向かってゆくのですが、衝突してから押し出すように動きます。
まるで、キューブA(ランプ緑色)の位置を目指して、キューブB(ランプ赤色)押しのけています。
これでキューブA(ランプ緑色)が押されて動くと、さらにキューブB(ランプ赤色)が向かって追突して移動させ、これらが繰り返されます。
まあ確かに、キューブA(ランプ緑色)の周辺で、停止するような設定ではないので、こうなるかもです。

このコードでは、「for _ in range(30):」なので、この「追跡・衝突・移動」を、30回繰り返すようです。これを「range(3)」にしてみると、この動作はすぐに終わります。

■ チュートリアル終了

おつかれさまでした。チュートリアルはこれで完了です。Pythonを用いて、toio.pyで目的を持ったプログラムを作ることができました。

このチュートリアルの完成コードをコードセル機能ではなく一つのプログラムとして実行できるようにしたものが example ディレクトリの tutorial_pursuer.py です。

他にも example ディレクトリには、いくつかのサンプルプログラムがあります。次のステップとして、下表のサンプルプログラムを、自分で改造してみるのもよいでしょう。

サンプルプログラム一覧

サンプルプログラム 説明
examples/detect_mat.py 読み取った座標から、使われているマットの種類を表示します
examples/motor_control.py モーター制御(移動、目標指定移動、複数目標指移動)
examples/multi.py 複数台Cubeへのスキャンと接続(現状は無く別の3つ)
examples/read_position.py ID 読み取り
examples/scan_and_connect.py スキャンと接続
examples/tutorial_pursuer.py このチュートリアルで作成したプログラム(単独実行版)

2026/08/08にダウンロードした「tutorial.ja.py」では、上記の6個が紹介されています。

■ サンプルプログラムの確認

サンプルプログラムの入手

助言にある通り、githubを確認するとディレクトリ「example」があります。これを入手して、確かめてみます。
まず、toio.pyのgithubに、ブラウザから接続します。右上の緑色ボタン「<>Code」を押して、メニューの「Download ZIP」から、ダウンロードします。
ダウンロードフォルダに「toio.py-main.zip」が保存されます。これを、フォルダ「C:\SonyToio」に移動して、「すべて展開」よりフォルダ「C:\SonyToio\」に展開します。
フォルダ「toio.py-main」が作られ、この中にフォルダ「example」があり、上記の説明6個を含めて10個のPythonの例題プログラム(2026/08/13時点)があります。さらにフォルダ「examples-simple」には、単純な動作を行う13個の例題プログラム(2026/08/13時点)があります。
ファイルを変更するといけないので、この2つのフォルダの中のPythonファイルを、フォルダ「C:\SonyToio\PythonWork」の中に、フォルダ「toio-example」を作り、ここにコピーして、このファイルを使って検証します。

ファイルの説明として、フォルダ「example」残り5個。

サンプルプログラム 説明
multi_cubes_with_attribute.py 2つのキューブで別の色のランプを点灯
multi_cubes_with_named.py 2つのキューブで別の色のランプを点灯 (これが以前のmulti.py)
async_gather_multi.py 4つのキューブを2グループで接続する(ここでは実行不可)
async_gather.py 2つのキューブで別の色のランプを点灯
async_task_group.py 2つのキューブで別の色のランプを点灯

ファイルの説明として、フォルダ「examples-simple」の12個。

サンプルプログラム 説明
angle_control.py キューブを水平右向きの角度0の状態から色々な角度に回転
basic_motor_control.py 1つのキューブのモーターの制御(マットなしでも実行可能)
concurrent_futures_simple.py 2つのキューブへのスキャンと接続(キューブごと色違いランプ点灯しボタンで解除)
get_current_grid.py 1台のキューブの置かれたグリッドの状態を確認する(ボタンで解除)
get_information_1.py 1台のキューブの置かれた座標とグリッドの状態を確認する(ボタンで解除)
get_information_2.py 1台のキューブの置かれた角度と姿勢と磁気センサの状態を確認する(ボタンで解除)
get_standard_id.py 1台のキューブの名称と専用カード読取の状態を確認する(Ctrl+Cで解除)
goto_a_gird.py 1台のキューブをランダムでいろいろなグリッドに移動させる
lamp.py 1台のキューブのランプを白色赤色緑色青色に変化させる
move_to.py 1台のキューブをマット中央を原点として4角形の頂点に移動させる
multi_cubes_async_simple.py 2つのキューブに3つの動作させる
sound.py 1台のキューブに指定した時間だけブザーを鳴らす
step.py 1台のキューブに指定した位置との間で往復移動する

サンプルプログラムの実行

簡易プレイマットの上にキューブ1つを置いて、電源を入れておきます。
PowerShellを起動して、例題Pythonファイルがあるフォルダ「C:\SonyToio\PythonWork\toio-example」に移動します。

まず、チュートリアル「tutorial.ja.py」に紹介されている、6個の例題を試してみます。

【01: detect_mat.py】
読み取った座標から、使われているマットの種類を表示します

PS C:\SonyToio\PythonWork\toio-example> python .\detect_mat.py
toio-T12 on Toio Collection (ring): (45, 45) - (455, 455) mat
toio-T12 on Simple mat: (98, 142) - (402, 358) mat
{'center': CubeLocation(point=Point(x=220, y=259), angle=270),
 'sensor': CubeLocation(point=Point(x=213, y=267), angle=270)}
 :
 Ctrl-C

結果を見ると、キューブ「toio-T12」がマット「Simple mat: (98, 142) - (402, 358) mat」に置かれ、キューブが位置Point(x=220, y=259)で角度angle=270の状態です。この確認がずっと続くので、Ctrl-Cで終了します。

【02: motor_control.py】
モーター制御(移動、目標指定移動、複数目標指移動)

PS C:\SonyToio\PythonWork\toio-example> python .\motor_control.py
1: motor_control()
2: motor_control_target()
toio-T12 <class 'toio.cube.api.motor.ResponseMotorControlTarget'> {'request_id': 0, 'response_code': <MotorResponseCode.SUCCESS: 0>}
3: motor_control_multiple_targets()
toio-T12 <class 'toio.cube.api.motor.ResponseMotorControlMultipleTargets'> {'request_id': 0, 'response_code': <MotorResponseCode.SUCCESS: 0>}

3つの連続した動作をします。その1:2秒間前進する、その2:(200,200)の位置に移動し角度0を向く、その3:(250,250)に移動して次に(120,170)に移動してそれぞれの位置で角度0を向く、です。

チュートリアルファイルの解説では「multi.py」とあるのですが、実際に「example」のフォルダにはこのファイルがなく、代わりに「multi_cubes_async_simple.py・multi_cubes_with_attribute.py・multi_cubes_with_named.py」の3つのファイルがあります。
これらを順にみてゆきます。2つのキューブABに電源を入れて、マットの上に置きます。最初は、青色の点滅の状態です。

【03: multi.py(multi_cubes_with_named.py)】
複数台Cubeへのスキャンと接続(キューブごと色違いランプ点灯)
ここでは、キューブ2つの電源を入れて、マットの任意の位置に置きます。

PS C:\SonyToio\PythonWork\toio-example> python .\multi_cubes_with_named.py
connecting...

キューブABにぞれぞれ名前「taro・jiro」を付けて、それぞれに「紫色・水色」のランプを点灯させます。3秒待って接続を解除します。Pythonコードを見ると、これが以前の「multi.py」のようでした。

【04: read_position.py】
キューブを接続し状態の確認と表示が継続する(Ctrl+Cで終了)

PS C:\SonyToio\PythonWork\toio-example> python .\read_position.py
toio-T12 {'center': CubeLocation(point=Point(x=224, y=288), angle=269),
 'sensor': CubeLocation(point=Point(x=217, y=296), angle=269)}
Ctrl-C

結果を見ると、キューブ「toio-T12」の動作にともなって、位置(x=224, y=288)や角度angle=269の状態の表示がずっと続くので、Ctrl-Cで終了します。

【05: scan_and_connect.py】
スキャンと接続と解除の手順の確認

PS C:\SonyToio\PythonWork\toio-example> python .\scan_and_connect.py
connecting...
connected
disconnecting...
disconnected

単純にキューブに接続し解除します。

【06: tutorial_pursuer.py】
チュートリアルで作成したプログラム(単独実行版)
ここでは、キューブ2つの電源を入れて、マットの任意の位置に置きます。

PS C:\SonyToio\PythonWork\toio-example> python .\tutorial_pursuer.py
start
red cube: move to CubeLocation(point=Point(x=335, y=302), angle=271)
{'request_id': 0, 'response_code': <MotorResponseCode.ERROR_TIMEOUT: 1>}
:
red cube: move to CubeLocation(point=Point(x=374, y=334), angle=313)
{'request_id': 0, 'response_code': <MotorResponseCode.ERROR_TIMEOUT: 1>}
end

実行してみたところ、キューブA(ランプ緑色)に向かって、キューブB(ランプ赤色)が向かってゆくのですが、衝突してから押し出すように動きます。
これでキューブA(ランプ緑色)が押されて動くと、さらにキューブB(ランプ赤色)が向かって追突して移動させ、これらが繰り返されます。
このコードでは、「for _ in range(30):」なので、この「追跡・衝突・移動」を、30回繰り返すようです。

次に、フォルダ「example」に追加されている、5個の例題を試してみます。

【01: multi_cubes_with_attribute.py】
複数台Cubeへのスキャンと接続(キューブごと色違いランプ点灯)
ここでは、キューブ2つの電源を入れて、マットの任意の位置に置きます。

PS C:\SonyToio\PythonWork\toio-example> python .\multi_cubes_with_attribute.py
connecting...

キューブABにぞれぞれ名前「taro・jiro」を付けて、それぞれに「紫色・水色」のランプを点灯させます。3秒待って接続を解除します。

【02: multi_cubes_with_named.py(multi.py)】
チュートリアル「tutorial.ja.py」の例題「multi.py」で解説しています。
ここでは、キューブ2つの電源を入れて、マットの任意の位置に置きます。

【03: async_gather_multi.py】
複数台Cubeへのスキャンと接続(キューブが4台必要)

PS C:\SonyToio\PythonWork\toio-example> python .\async_gather_multi.py
cube group 1 connecting...
cube group 2 connecting...
cube1-0 toio-T12
cube1-1 toio-T0k
Exception in callback Future.set_result(<Future cancelled>, <winrt._winrt...001C4025B1030>)
handle: <Handle Future.set_result(<Future cancelled>, <winrt._winrt...001C4025B1030>)>

これは複数キューブを複数グループで接続します。実行結果を確認すると、2つのグループ「group 1,2」を接続しようとし、グループ1「cube-1」の2台「toio-T12・toio-T0k」は接続できましたが、ここでは2台しかないので、グループ2「cube-2」が接続できずエラーになります。

【04: multi_cubes_with_named.py(multi.py)】
複数台Cubeへのスキャンと接続(キューブごと色違いランプ点灯)
ここでは、キューブ2つの電源を入れて、マットの任意の位置に置きます。

PS C:\SonyToio\PythonWork\toio-example> python .\async_gather.py
cube1 connecting...
cube2 connecting...
cube1 toio-T12
cube2 toio-T0k
cube1 disconnecting
cube1 disconnected
cube2 disconnecting
cube2 disconnected
end

2つのキューブをスキャンして、1つ目に接続したキューブAに対して黄色ランプを点灯させ、少し待って、2つ目に接続したキューブBに対して水色ランプを点灯させます。
まず、キューブAを持ち上げて、黄色ランプのボタンを押して、切断します。次にキューブBを持ち上げて、水色ランプのボタンを押して、切断します。

【05: multi_cubes_with_named.py(multi.py)】
複数台Cubeへのスキャンと接続(キューブごと色違いランプ点灯)
ここでは、キューブ2つの電源を入れて、マットの任意の位置に置きます。

PS C:\SonyToio\PythonWork\toio-example> python .\async_task_group.py
cube1 connecting...
cube2 connecting...
cube1 toio-T12
cube2 toio-T0k
cube1 disconnecting
cube2 disconnecting
cube1 disconnected
cube2 disconnected

2つのキューブをスキャンして、1つ目に接続したキューブAに対して黄色ランプを点灯させ、少し待って、2つ目に接続したキューブBに対して水色ランプを点灯させます。
まず、キューブAを持ち上げて、黄色ランプのボタンを押して、切断します。次にキューブBを持ち上げて、水色ランプのボタンを押して、切断します。

最後に、フォルダ「example-simple」にある、13個の例題を試してみます。

簡易プレイマットの上にキューブ2つを置いて、電源を入れておきます。

【01: angle_control.py】
キューブを水平右向きの角度0の状態から、色々な角度に回転します。

PS C:\SonyToio\PythonWork\toio-example> python .\angle_control.py
** ACTIVATE
** CONNECTED
** ZERO
** SET DIRECTION (POSITIVE ANGLE)
** SET DIRECTION (NEGATIVE ANGLE)
** TURN (POSITIVE ANGLE)
** TURN (NEGATIVE ANGLE)
** SET ORIENTATION 90
** STOP MOTOR
** DISCONNECTED
** END

【02: basic_motor_control.py】
1つのキューブのモーターの制御(マットなしでも実行可能)

PS C:\SonyToio\PythonWork\toio-example> python .\basic_motor_control.py
** ACTIVATE
simple:1:2026-08-14 05:06:41,289    INFO initialized
simple:1:2026-08-14 05:06:41,289    INFO start to connect
simple:1:2026-08-14 05:06:41,289    INFO try to lock
simple:1:2026-08-14 05:06:41,289    INFO enter critical section
simple:1:2026-08-14 05:06:41,289    INFO scanning
simple:1:2026-08-14 05:06:46,594    INFO connecting
simple:1:2026-08-14 05:06:49,951    INFO connected (toio-T12)
simple:1:2026-08-14 05:06:51,427    INFO setup completed
simple:1:2026-08-14 05:06:51,428    INFO exit critical section
simple:1:2026-08-14 05:06:51,428    INFO release lock
** CONNECTED
** MOVE
** SPIN
** RUN MOTOR
** STOP MOTOR
** DISCONNECTED
** END

【03: concurrent_futures_simple.py】
2つのキューブへのスキャンと接続(キューブごと色違いランプ点灯しボタンで解除)

PS C:\SonyToio\PythonWork\toio-example> python .\concurrent_futures_simple.py
** ACTIVATE
simple:1:2026-08-14 05:10:14,244    INFO initialized
simple:2:2026-08-14 05:10:14,244    INFO initialized
simple:1:2026-08-14 05:10:14,244    INFO start to connect
simple:1:2026-08-14 05:10:14,244    INFO try to lock
simple:1:2026-08-14 05:10:14,244    INFO enter critical section
simple:1:2026-08-14 05:10:14,244    INFO scanning
simple:1:2026-08-14 05:10:19,546    INFO connecting
simple:1:2026-08-14 05:10:22,945    INFO connected (toio-T12)
simple:1:2026-08-14 05:10:24,149    INFO setup completed
simple:1:2026-08-14 05:10:24,150    INFO exit critical section
simple:1:2026-08-14 05:10:24,150    INFO release lock
jiro toio-T12
simple:2:2026-08-14 05:10:24,152    INFO start to connect
simple:2:2026-08-14 05:10:24,152    INFO try to lock
simple:2:2026-08-14 05:10:24,153    INFO enter critical section
simple:2:2026-08-14 05:10:24,153    INFO scanning
simple:2:2026-08-14 05:10:29,228    INFO connecting
simple:2:2026-08-14 05:10:32,080    INFO connected (toio-T0k)
simple:2:2026-08-14 05:10:33,335    INFO setup completed
simple:2:2026-08-14 05:10:33,335    INFO exit critical section
simple:2:2026-08-14 05:10:33,335    INFO release lock
taro toio-T0k
jiro disconnecting
taro disconnecting
jiro disconnected
taro disconnected
** DISCONNECTED
** END

【04: get_current_grid.py】
1台のキューブの置かれたグリッドの状態を確認する(ボタンで解除)

PS C:\SonyToio\PythonWork\toio-example> python .\get_current_grid.py
** ACTIVATE
** CONNECTED
(-1, 0)
** DISCONNECTING (PLEASE WAIT)
** DISCONNECTED
** END

【05: get_information_1.py】
1台のキューブの置かれた座標とグリッドの状態を確認する(ボタンで解除)

PS C:\SonyToio\PythonWork\toio-example> python .\get_information_1.py
** ACTIVATE
** CONNECTED
CUBE NAME: toio-T0k
POSITION: (0, -54) 0 -54 -1 GRID: (0, -1) 0 -1 BATTERY 70 BUTTON 0
:
POSITION: None None None None GRID: None None None BATTERY 70 BUTTON 128
exit
** DISCONNECTED
** END

【06: get_information_2.py】
1台のキューブの置かれた角度と姿勢と磁気センサの状態を確認する(ボタンで解除)

PS C:\SonyToio\PythonWork\toio-example> python .\get_information_2.py
** ACTIVATE
** CONNECTED
CUBE NAME: toio-T0k
ANGLE: (-1, 2, 24) POSTURE: 1 MAGNET 0
:
ANGLE: (88, 6, 49) POSTURE: 6 MAGNET 0
exit
** DISCONNECTED
** END

【07: get_standard_id.py】
1台のキューブの名称と専用カード読取の状態を確認する(Ctrl+Cで解除)

PS C:\SonyToio\PythonWork\toio-example> python .\get_standard_id.py
** ACTIVATE
** CONNECTED
CUBE NAME: toio-T0k
CARD: None
:
CARD: None
Ctrl-C
** DISCONNECTED
** END

【08: goto_a_gird.py】
1台のキューブをランダムでいろいろなグリッドに移動させる

PS C:\SonyToio\PythonWork\toio-example> python .\goto_a_gird.py
** ACTIVATE
** CONNECTED
move to (0, -1)
result of move_to_grid_cell: True
result of is_on_the_grid_cell: True
move to (-1, -2)
:
result of move_to_grid_cell: False
result of is_on_the_grid_cell: False
** DISCONNECTED
** END

【09: lamp.py】
1台のキューブのランプを白色赤色緑色青色に変化させる

PS C:\SonyToio\PythonWork\toio-example> python .\lamp.py
** ACTIVATE
** CONNECTED
** CUBE NAME: toio-T0k
** WHITE
** RED
** GREEN
** BLUE
** OFF
** DISCONNECTED
** END

【10: move_to.py】
1台のキューブをマット中央を原点として4角形の頂点に移動させる

PS C:\SonyToio\PythonWork\toio-example> python .\move_to.py
** ACTIVATE
** CONNECTED
move to (30, 30)
arrival: True
move to (30, -30)
arrival: True
move to (-30, -30)
arrival: True
move to (-30, 30)
arrival: True
move to (30, 30)
arrival: True
** DISCONNECTED
** END

【11: multi_cubes_async_simple.py】
複数台Cubeへのスキャンと接続(色違いランプ点灯で3つの動作を行う)
ここでは、キューブ2つの電源を入れて、マットの任意の位置に置きます。

PS C:\SonyToio\PythonWork\toio-example> python .\multi_cubes_async_simple.py
** ACTIVATE 1
simple:1:2026-08-13 13:57:34,105    INFO initialized
simple:1:2026-08-13 13:57:34,107    INFO start to connect
simple:1:2026-08-13 13:57:34,107    INFO try to lock
simple:1:2026-08-13 13:57:34,107    INFO enter critical section
simple:1:2026-08-13 13:57:34,107    INFO scanning
** ACTIVATE 2
simple:2:2026-08-13 13:57:34,215    INFO initialized
simple:2:2026-08-13 13:57:34,215    INFO start to connect
simple:2:2026-08-13 13:57:34,215    INFO try to lock
simple:1:2026-08-13 13:57:39,308    INFO connecting
simple:1:2026-08-13 13:57:42,613    INFO connected (toio-T0k)
simple:1:2026-08-13 13:57:43,864    INFO setup completed
simple:1:2026-08-13 13:57:43,866    INFO exit critical section
simple:1:2026-08-13 13:57:43,866    INFO release lock
simple:2:2026-08-13 13:57:43,866    INFO enter critical section
simple:2:2026-08-13 13:57:43,866    INFO scanning
cube_1: toio-T0k
simple:2:2026-08-13 13:57:48,907    INFO connecting
simple:2:2026-08-13 13:57:51,406    INFO connected (toio-T12)
simple:2:2026-08-13 13:57:52,672    INFO setup completed
simple:2:2026-08-13 13:57:52,672    INFO exit critical section
simple:2:2026-08-13 13:57:52,672    INFO release lock
cube_2: toio-T12
cube_1: button pressed
** DISCONNECTED 1
cube_2: button pressed
** DISCONNECTED 2
** END

2つのキューブをスキャンして、1つ目に接続したキューブAに対して水色ランプを点灯させ、少し待って、2つ目に接続したキューブBに対して黄色ランプを点灯させます。
まず、キューブAを持ち上げて、水色ランプのボタンを押して、切断します。次にキューブBを持ち上げて、黄色ランプのボタンを押して、切断します。

【12: sound.py】
1台のキューブに指定した時間だけブザーを鳴らす

PS C:\SonyToio\PythonWork\toio-example> python .\sound.py
** ACTIVATE
** CONNECTED
CUBE NAME: toio-T0k
pp-- 2.55[s]
stop
pp-- 0.5[s]
stop
wait 3 sec
disconnecting
** DISCONNECTED
** END

【13: step.py】
1台のキューブに指定した位置との間で往復移動する

PS C:\SonyToio\PythonWork\toio-example> python .\step.py
** ACTIVATE
** CONNECTED
** MOVE STEPS
** END

■ 補足情報:コードセルを使わない非同期処理の実行方法

コードセル機能を使わないでtoio.pyのような非同期処理を扱うプログラムを作るときには、いくつかの注意点があります。

await は非同期関数内でしか使えません。(コードセル機能では直接呼び出せます)

toio.pyのような非同期処理を使う場合は、まず非同期関数を作り、その非同期関数を asyncio.run() で実行します。

例:非同期処理を実行する簡単な Python プログラム

#!/usr/bin/env python

import asyncio
from toio import *

async def cube_functions():
    dev_list = await BLEScanner.scan(1)
    assert len(dev_list)
    cube = ToioCoreCube(dev_list[0].interface)
    await cube.connect()
    await cube.disconnect()

asyncio.run(cube_functions())
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?