この記事は 「toio™(ロボットトイ | toio(トイオ)) Advent Calendar 2019」の 17日目の記事です。
はじめに
toio の 「toio バリューパック」・「トイオ・コレクション 拡張パック」と「工作生物 ゲズンロイド」を持っています @youtoy です。
また、toio関連では、以下のユーザ会を 3人で共同主催しており、2度ほど LT会を開催したりしました。
▼ toio™で作ってみた!友の会(非公式)
⇒ 【Facebookグループ】
⇒ 【connpassのグループ】
この記事で試す内容について
以前、toio.js を使って、toio と他デバイス(Amazon Echo や micro:bit)と連携させる記事を書いたことがあります。
● #toio を Alexa や micro:bit から操作する 〜概要編〜(JavaScriptライブラリを使ってみた) - Qiita
このときは、キーボード入力で toio を動かすサンプルをベースに、作品を作っていました。
それから時間が経過し、toio の仕様のページや、公式のニュース(タイトル: システムソフトウェアアップデート2019 実施)にも書かれているように、アップデートが行われました。
今回の記事では、アップデートにより追加された内容を試すことにします。
それでは、何を試してみようかと、アップデートされた内容を見ていきたいと思います。
仕様の「アップデートについて」というページの下部を見てみると、以下のような記載があります(2019/12/16時点)。
BLE プロトコルバージョン v2.1.0 では以下のような内容の変更・追加があります。
- ダブルタップ検出・姿勢検出の追加
- モーターの速度指示値の有効範囲の拡大
- 速度指示値の最大値が100から115になり、より速い動作が可能になります
- 速度指示値の最小値が10から8になり、よりゆっくりとした動作が可能になります
- モーター制御のバリエーションの追加
- 目標指定付きモーター制御
- 複数目標指定付きモーター制御
- 加速度指定付きモーター制御
一番上の「ダブルタップ検出・姿勢検出の追加」あたりを試してみるのが、見た目にも分かりやすそうです。
上記の「ダブルタップ検出・姿勢検出の追加」の部分については、仕様の「モーションセンサー」に仕様詳細が記載されていました。以下は、2019/12/16時点でページの一部をキャプチャしたものです。
今回は、ダブルタップ検出・姿勢検出の2つあるうちの「姿勢検出」を試していこうと思います。
toio.js でモーションセンサーを使う
現状のモーションセンサー周りを見てみる
姿勢検出を試していく前に、まずは、現状の toio.js のモーションセンサー周りの処理で実装されている内容を見てみます。
API の情報をたどっていくと、「Globals @toio/cube Cube」の「Class Cube」の中に、「getSlopeStatus」という部分があります。どうやら、傾きをセンサーで検知するもののようです。
この部分には、以下のような記載があります。
そして、上記の「Defined in cube/src/cube.ts:225」の部分をクリックすると、以下のようなソースコードがあります。
さらに、上記の「isSloped」をキーワードにリポジトリ内で検索してみます。
すると、検索結果の中に、以下のような内容がありました。
「const isSloped = buffer.readUInt8(1) === 0」という部分や「const isCollisionDetected = buffer.readUInt8(2) === 1」という部分がありますが、上記の仕様の「モーションセンサー」の部分、もっと具体的に言うと以下の画像の赤枠部分が関連しそうです。
姿勢の検出
ということは、データ位置が 2 に該当する「const isSloped = buffer.readUInt8(1) === 0」のところを、試しに「const isSloped = buffer.readUInt8(4) === 【数値】」としてみれば、特定の姿勢を検出する処理に変わるように思われます。
姿勢の違いを表す数値については、先ほど出てきたページの中で、以下のように書かれています。
この記事では、「底面が上(値 2)」と「正面が上(値 4)」の 2つを試してみることにします。
姿勢検出を試す前のセットアップなど
最終的には姿勢検知を試していくのですが、その前に公式サンプルを動かしてみたり、上記の「getSlopeStatus」を使って傾きを検出するプログラムを試してみます。
公式サンプルを動かしてみる
GitHub の toio.js のページの「💻 Prerequisites」 を見て、事前のセットアップを行ってください。
そして、GitHub の toio.js のページに記載されている、以下の内容を試してみましょう。
▼ How to play sample application
- $ git clone https://github.com/toio/toio.js.git
- $ cd toio.js
- $ yarn install
- $ yarn build
- $ yarn example:keyboard-control
動かしてみたときの様子は以下のとおりです。
toio.js の公式サンプル、#toio をキーボード操作するもの。 pic.twitter.com/qVIs2VZm6h
— you (@youtoy) December 15, 2019
今回の動画では、手順1 でクローンしてきたソースの中の「toio.js/examples/keyboard-control」の直下の「index.js」に少しだけ手を加えています。
具体的には、11行目〜17行目までの、スピードや移動距離に関わるパラメータを、以下のようにしました。
const DURATION = 500 // ms
const SPEED = {
forward: [50, 50],
backward: [-50, -50],
left: [15, 50],
right: [50, 15],
}
また、上記の部分で少し書きかえた「toio.js/examples/keyboard-control」の直下の「index.js」を、以下のソースコードに置きかえて動作させてみたりもしました(※ GitHub の toio.js のページの冒頭のソースで、「cube.move(100, 100, 1000)」の部分を「cube.move(50, 50, 500)」にと、少しだけ変更したものです)。
const { NearestScanner } = require('@toio/scanner')
async function main() {
// start a scanner to find the nearest cube
const cube = await new NearestScanner().start()
// connect to the cube
await cube.connect()
// move cube
cube.move(50, 50, 500)
// | | `--- duration [ms]
// | `--------- right motor speed
// `------------- left motor speed
}
main()
書きかえた後のソースを動かすには$ yarn example:keyboard-control
を実行する必要があります。これにより、変更後の内容が反映されました。
久しぶりに toio.js を触った。#toio pic.twitter.com/np1DjhjbTS
— you (@youtoy) December 15, 2019
モーションセンサーの情報を使う
続いて「getSlopeStatus」を使って傾きを検出するプログラムを試してみます。
なお、普段あまりプログラムを書くことがないため、以下で出てくるプログラムで「もっと良い書き方があるよ」という場合や、「この書き方はまずいよ」という場合などは、コメント欄などで教えていただけると嬉しいです。
では、傾きを検出したか否か(true/false)の出力で、傾いていると検知された場合には「傾いてるぞ!」というテキストが表示されるプログラムを作ってみます。
上で出てきた2つ目のプログラムをベースに書きかえをしました。そして、判定処理は 500msec間隔で20回実行しています。判定処理のところは「getSlopeStatus」の「isSloped」が true か false を見る形です。
const { NearestScanner } = require('@toio/scanner')
async function main() {
let cubeStatus;
const cube = await new NearestScanner().start()
await cube.connect()
for (let i = 0; i < 20; i++) {
cubeStatus = await cube.getSlopeStatus();
if(cubeStatus.isSloped) {
console.log("傾いてるぞ!");
} else {
console.log("...");
}
await new Promise(r => setTimeout(r, 500));
}
console.log("状態チェック、終了。");
}
main()
実際に動作させてみると、以下の動画のようになりました。
toio が傾くと PCの画面に表示されるテキストが変わるのが、動画から分かるかと思います(ちなみに、傾いたかどうかの閾値はデフォルトのままで、その場合は 45度が閾値となるようです)。
toio.js を久しぶりに触っていた話の本命、#toio のモーションセンサーで傾いたかどうかを検知。 pic.twitter.com/SpM0LA4XUU
— you (@youtoy) December 16, 2019
姿勢検出を試してみる
それではいよいよ、姿勢検出へと進みます。
今回は短時間で試すために、(手抜きな感じの)楽な方法を採用します。本来はソースコードの追加や修正等をいろいろと行うべきところを、既存のコードの一部のみ(パラメータのみ)を書きかえることとします。
これだと、メソッド名と処理内容が一致しなくなってしまうのですが・・・(後で、公式でAPIが準備されるだろう、という見込んでの暫定対応ということで)。
具体的には「toio.js/packages/cube/src/characteristics/specs/sensor-spec.ts」の 31・32行目を以下のように書きかえました。
【書きかえ前】
const isSloped = buffer.readUInt8(1) === 0
const isCollisionDetected = buffer.readUInt8(2) === 1
【上記の書きかえ後】
const isSloped = buffer.readUInt8(4) === 2
const isCollisionDetected = buffer.readUInt8(4) === 4
これにより、以下のような動作をするようになるはずです。
「isSloped はキューブの底面が上を向くと true」
「isCollisionDetected はキューブの正面が上を向くと true」
上記の 2つの状態(底面が上/正面が上)が検出された場合に、それぞれに対応したテキストを PC画面上に表示するようにしてみました。
const { NearestScanner } = require('@toio/scanner')
async function main() {
let cubeStatus1, cubeStatus2;
const cube = await new NearestScanner().start()
await cube.connect()
for (let i = 0; i < 20; i++) {
cubeStatus1 = await cube.getSlopeStatus();
cubeStatus2 = await cube.getCollisionStatus();
if(cubeStatus1.isSloped) {
console.log("逆さまになっています");
} else if(cubeStatus2.isCollisionDetected) {
console.log("上向き!");
} else {
console.log("...");
}
await new Promise(r => setTimeout(r, 500));
}
console.log("状態チェック、終了。");
}
main()
実際に動かしてみたのが以下の動画です。
toio.js を使った、#toio のモーションセンサー利用の 2つ目、
— you (@youtoy) December 16, 2019
この前のアップデートで対応されたばかりの姿勢検知。 pic.twitter.com/84sNfs70uH
無事に動いていそうです。
さいごに
今回、 toio.js で傾き検知と姿勢検出を試してみました。
本当は、動画でわかりやすいように「姿勢によって異なる音が鳴る・異なる光り方をする」とか、2台の toio を連携させるような内容をやりたかったのですが、時間の関係でここまでとなりました。
その辺りは、引き続き試していこうと思います!