LoginSignup
7
2

More than 3 years have passed since last update.

obnizを使ってスマホの傾きでtoioを操作

Last updated at Posted at 2020-12-12

この記事は obniz Advent Calendar 2020 13日目の記事です。

やったこと

obnizを使って、スマホの傾きでtoioをラジコンのように操作できるようにしてみました。
研究室にtoioがたくさん転がっていたので、toioで遊んでみたかったのが動機です。

toioについて

toioはロボットを使った新しいあそびのプラットフォームです。ひとりでもみんなでも、専用タイトルをかえることでゲームや工作、絵本、運転などいろいろあそびを通して楽しむことができます。いよいよ本格化するプログラミング教育に向けて、気軽に楽しく自宅学習にもお使いいただけます。
(HPより抜粋)

まだ触ったばかりで理解は浅いのですが、いくつかのセンサや小さいタイヤのついた、白いキューブを使ったプラットフォームのようです。
予めコンテンツが用意されているのでそのままでも遊べますが、ブロックプログラミングやコーディングによって自分だけの拡張も楽しめます。

材料

  • obniz
  • toio
  • スマートフォン
  • モバイルバッテリー

プログラム

全体の流れは、
1. toioを探してBLEで接続する
2. 接続できたら常にスマホの回転姿勢を取得する
3. 回転姿勢によって左右のタイヤの回転方向・スピードを調整
となっています。

1. toioを探してBLEで接続

obnizのパーツライブラリの toio コア キューブ のページを参考に、toio コア キューブとの接続をしています。
if(Toio_CoreCube.isDevice(peripheral)){...}のところで受信したBLEのアドバタイズがtoioなのかを判定してインスタンスを作り、.connectWait()で接続しています。


await obniz.ble.initWait();
const Toio_CoreCube = Obniz.getPartsClass("toio_CoreCube");

obniz.ble.scan.onfind = async (peripheral) => {
  //toioの探索
  if(Toio_CoreCube.isDevice(peripheral)){
    console.log("find");
    const toio = new Toio_CoreCube(peripheral);

    toio.ondisconnect = (reason) => {
      console.log(reason);
    }
    //toioとの接続
    await toio.connectWait();
    console.log("connected");
    ...
  }
  ...
}

2. スマートフォンの回転姿勢を取得

toioとの接続が完了したら、以下の部分でスマートフォンの回転姿勢を取得しています。
今回はbetagammaの値しか使っていませんが、以下の3つの値を取得できます。

  • alpha: z軸を基準にしたデバイスの角度(画面を水平にしたときの水平回転)
  • beta: x軸を基準にしたデバイスの角度(画面を水平にしたときの前後の傾き)
  • gamma: y軸を基準にしたデバイスの角度(画面を水平にしたときの左右の傾き)

window.addEventListener("deviceorientation", async (e) => {
  //X軸を中心にしたデバイスの角度(画面を水平にしたときの前後の傾き) -180~180
  let beta = e.beta;
  //y軸を中心にしたデバイスの角度(画面を水平にしたときの左右の傾き) -90~90
  let gamma = e.gamma;
  ...
  }
});

3. 左右のタイヤの回転方向・スピードを調整

前節でbetaで前後の傾き、gammaで左右の傾きを取得しました。これらの値に応じて左右のタイヤの回転方向やスピードを調整して、toioの動く方向を制御します。

まずは、betaで前後の傾きを取得し、奥へ傾けたときは前進、手前に傾けたときは後退するように条件分けしました。また、水平からある閾値HORIZONTAL_THRESHOLD(今回は±10度)までは水平とみなし、toioを静止させるようにしました。

if(beta > HORIZONTAL_THRESHOLD){
  //後ろ(手前)に進むように調整
 ...
}else if(beta < -HORIZONTAL_THRESHOLD){
  //前(奥)に進むように調整
  ...
}else{
  //静止
  ...
}

次に、gammaの左右の傾きの値も使って、それぞれの条件の中で左右のタイヤのスピードを計算しています。
計算結果が正の値だとタイヤが前方回転、負の値だと後方回転します。左右どちらかの回転スピードを緩めると、緩めた方に曲がって進みます。

回転姿勢を使ったタイヤの回転の計算方法がわからなかったので、自分でこんな感じの式を立ててみました。
(最大スピード) * (縦の傾き具合0.0〜1.0) ± (横の傾き角度/20)
縦の傾き具合によって、最大スピードの何割で進むのかを決めています。
また、横の傾きを調整した値を足し引きすることによって、曲がる方のタイヤのスピードを緩めています。

if(beta > HORIZONTAL_THRESHOLD){
  //後ろ(手前)に進むとき
  speedLeft = MAX_SPEED * beta / MAX_TILT_BETA - gamma / 20;
  speedRight= MAX_SPEED * beta / MAX_TILT_BETA + gamma / 20;
}else if(beta < -HORIZONTAL_THRESHOLD){
  //前(奥)に進むとき
  speedLeft = MAX_SPEED * beta / MAX_TILT_BETA + gamma / 20;
  speedRight= MAX_SPEED * beta / MAX_TILT_BETA - gamma / 20;
}else{
  //静止
  speedLeft = 0;
  speedRight = 0;
}

最後に、100msおきに、計算した左右のスピードに合わせてtoioを動かしています。

obniz.repeat(async () => {
  await toio.moveAroundWait(speedLeft,speedRight);
}, 100);

完成したコード

<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
    />
    <!--- <link rel="stylesheet" href="/css/starter-sample.css" /> -->
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <script
      src="https://unpkg.com/obniz@3.10.1/obniz.js"
      crossorigin="anonymous"
    ></script>
  </head>
  <body>
    <div id="obniz-debug"></div>

    <div id="ui-buttons" class="text-center">
      <h3 class="text-center">スマホの傾きでtoioを操作</h3>
      <button class="btn btn-primary" id="stop">ストップ(補助用)</button>
    </div>

    <script>
      let obniz = new Obniz("OBNIZ_ID_HERE");
      const HORIZONTAL_THRESHOLD = 10;
      const MAX_SPEED = 255;
      const MAX_TILT_BETA = 180;

      let speedLeft = 0;
      let speedRight = 0;

      obniz.onconnect = async() =>  {
        await obniz.ble.initWait();
        const Toio_CoreCube = Obniz.getPartsClass("toio_CoreCube");

        obniz.ble.scan.onfind = async (peripheral) => {
          //toioの探索
          if(Toio_CoreCube.isDevice(peripheral)){
            console.log("find");
            const toio = new Toio_CoreCube(peripheral);

            toio.ondisconnect = (reason) => {
              console.log(reason);
            }
            //toioとの接続
            await toio.connectWait();
            console.log("connected");

            window.addEventListener("deviceorientation", async (e) => {
              //X軸を中心にしたデバイスの角度(画面を水平にしたときの縦の傾き) -180~180
              let beta = e.beta;
              //y軸を中心にしたデバイスの角度(画面を水平にしたときの横の傾き) -90~90
              let gamma = e.gamma;

              if(beta > HORIZONTAL_THRESHOLD){
                //後ろ(手前)に進むとき
                speedLeft = MAX_SPEED * beta / MAX_TILT_BETA - gamma / 20;
                speedRight= MAX_SPEED * beta / MAX_TILT_BETA + gamma / 20;
              }else if(beta < -HORIZONTAL_THRESHOLD){
                //前(奥)に進むとき
                speedLeft = MAX_SPEED * beta / MAX_TILT_BETA + gamma / 20;
                speedRight= MAX_SPEED * beta / MAX_TILT_BETA - gamma / 20;
              }else{
                //静止
                speedLeft = 0;
                speedRight = 0;
              }
            });

            //緊急ストップ用
            $('#stop').on('click', async () => {
              console.log("stop");
              await toio.moveAroundWait(0,0);
            });

            obniz.repeat(async () => {
              await toio.moveAroundWait(speedLeft,speedRight);
            }, 100);

          }
        };
        await obniz.ble.scan.startWait();
      };


    </script>
  </body>
</html>

さいごに

お疲れであろう同期に、このラジコンtoioで栄養ドリンクを届けてみました...
(危ないので皆さんは真似しないでくださいね。)

7
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
7
2