IoT的価値

来年は更にネットにつながるデバイス、いわゆるIoT端末というのが溢れてくると思われる。開発を行う拠点も、DMM.make Akiba品川産業支援交流施設SHIPTechshop(富士通)とか出来てきている。

モノ系スタートアップの支援や、Yahoo Japanも電通もIoTと言っている状況で、周りをざらっと見た感じだとIoTと言っている所が非常に多い。けど、ぶっちゃけ実際のモノ、IoTデバイスというカテゴリに類するもので出回っているのはまだそんなに無い。まさにこれから産声を上げていくといった感はある。

■ モノの価値
先日の展示で見せてきたポスト君もそうだし、AccessさんがBeacon端末を無料で配るというのもだけど、いわゆる原価がいくらで実際の売値がいくら?というのは、非常に考える点が多いと思っている。ネットに接続してあれこれやる、いわゆるIoTデバイスは、

・モノ
・ネットワーク
・サーバ

といった所がプレイヤーとして出て来る。ここで、モノは現物で売値がいくら?という点があって、ネットワークはWiFi/BTを使えばOK、そして最後のサーバ(WebAPとか)は何気に効いて来る。今までのモノは売っていくら?だったのが、そこにランニングとしてのサーバやWebAPが継続して乗ってくるわけで、いつまでサポートするの?サービスの継続期間は?とか考えると、初期の売値で回収すんの?売切りで良いの?って気がするわけで。モノの価値というのは、サービスのランニングも込みで決めないといけない。

■ モノは激安、広告・月額いくら?
初期の価格にサーバとかのランニングも載せるというのは現実的ではないし、じゃあどうすんの?というと広告やアプリを介してサービスを利用する時に月額課金といった方法が考えられる。そして初期のモノの値段は激安で。原価がいくらだから最低限この値段で売らないと採算が…というのはいわゆる旧来の売り方から考え方が抜け切れていないと思っている。

そう、IoT、Internet of Thingsというネットのサービスを利用するのに、原価がいくらで?というのは要素の1つとして考えられる訳だけど、ネットサービスなのにそっちは考えてないの?というかサービスで対価を頂くんだよね?という点が抜け落ちているよーな気がする。

■ ネット・Webとの連携
モノを作るときはメーカー寄りの人だったり、実際にモノ作りに携わっている人との関わりが多いけど、IoTというシーンではネットやWeb側の広告や月額いくら?でサービスをやっている方との連携が必ず必要になる。それはモノの価値、値段決めという点においても。原価がいくらだから、この値段で売らないと…というよりも売値は押さえて、サービスで対価を頂くモデルが主流になると思う。

モノとサービスが主体になるIoTという形態では、作り手と同じくらいネット・Web側との連携、サービス作りが大切になると考えている。ネットにつながるからIoTデバイスで…というんじゃなくってね。サービスを提供して利用者にどんなメリットが?そして、その対価としてのサービス利用料や広告を出させて頂くといった、ネット・Web側で培われてきたノウハウというのが一体となって実現するのがIoTなる物だと考えている。

(追記) 上記のような、サービスモデル以外にも、Web側のデータ保全やIoT的端末からアクセス集中した時の冗長化、システムを落とさない為の運用…etc とか端末/ハードとは違う、ネット側で培われた知見は必要になってくる部分と思っている。ハードだけでもなく、Web側・ソフト側…といった様々な要素が必要になるでしょう。それはWeb側のサービスと、現実世界にあるモノとして使う人への最終的な価値の提供といった側面に反映されてくる部分でもある。
あと、このIoTというバズワードが自分的にWeb2.0とかビックデータといった歴代のバズワードに比べて現実味を帯びているのは、Web/ネット上の状態を表した言葉じゃなく、現実世界にあるモノ、目の前に現物として存在している状態という所が大きいような気がしている。

ポスト君

ポスト君という物を作りました。アナログな郵便箱を、電子メールのようにプッシュで通知して電子メールボックスとしての役割にしてくれる、IoT的なアイテムです。

– 通知方法
iBeacon(BLE)、またはメール。
メールの場合は、端末がWiFiに接続されている必要があります。

– 動作
1. 郵便箱にガジェットを入れて起動する。
2. 起動時に赤外線センサーで郵便箱の中の距離を一定時間測定する。
3. 監視スタート、たまに監視を行なってポストに郵便が投函されて、距離に変化が起きたら郵便が来たと判断して通知を行なう。通知はiBeacon、メールの何れか。
4. 郵便を取って、郵便箱の中が元の状態と同じ感じになったら、また監視を開始する。

– 利用シーン
1. 郵便が届いたらメールが来る。(WiFiタイプ)
2. 家に帰る途中で、郵便が届いていたら、ケータイに通知が来る(iBeacon)。
3. 空の郵便箱を開けて確認する必要が無くなる。
4. 家でゴロゴロしている時でも、郵便が来たら通知をしてくれる。

動作は非常に簡単で、こんなサイズの物を郵便ポストに入れておくだけ。普通の郵便箱に設置できます。
名称未設定

こちらはgugen 2014で展示してきた時のもの。

よくあった質問としては…

– 電池ってどの位持つの?
デモの時はリアルタイムで監視をしていたので、すぐ電池が切れちゃうけど、郵便が来たかどうか?をリアルタイムで確認したい!!という高い欲求のある人はあまり居なくて、30分に1回確認をする位ならかなり電池が持ちます。逆に設定で、リアルタイムで確認をしたい!!という場合は、すぐ電池が無くなってしまいます。これはアプリ側から設定を行なって調整できるようにする感じですね。

– チラシとかも反応するんじゃ?
反応します。自分の場合は都内に住んでいるですが、チラシが全然来ないです。もちろん実家では来た事が殆ど無いですし、むしろチラシが来たら嬉しい位で、この点は受取手側の状態に依存します。また、チラシ状の封書であっても本当に欲しい郵便の場合もあるので、今の方法では判別不可能です。
そこでどうするか?というと、特注の郵便箱を作って、郵便が入ってきた時に、入って来た郵便物をスキャンして内容を確認するという方法で、来た物の属性を判断していく事も可能になるでしょう。つまり郵便箱の入ってくる口の部分をスキャナーのようにする、といった感じです。そこまでする必要があるかどうか?というのがポイントになります。

ODROID U3 and OpenNI2/Xtion Pro Live

here is how to use OpenNI2/Xtion Pro live on ODROID-U3. environment is here.

os : xubuntu-13.10-desktop-armhf_odroidu_20140107.img.xz
OpenNI2(build from https://github.com/OpenNI/OpenNI2)

# install library
apt-get update
apt-get upgrade
apt-get install g++ python libusb-1.0-0-dev libudev-dev openjdk-6-jdk freeglut3-dev doxygen graphviz

# build OpenNI2
mkdir work
cd work
git clone https://github.com/OpenNI/OpenNI2
cd OpenNI2

# default OpenNI repository build will fail, so I change following. here is diff.
diff --git a/Packaging/ReleaseVersion.py b/Packaging/ReleaseVersion.py
index e2fdf5f..710f590 100755
--- a/Packaging/ReleaseVersion.py
+++ b/Packaging/ReleaseVersion.py
@@ -163,11 +163,12 @@ elif platform.system() == 'Windows':
 elif platform.system() == 'Linux' or platform.system() == 'Darwin':
 
     devNull = open('/dev/null', 'w')
-    subprocess.check_call(['make', '-C', '../', '-j' + calc_jobs_number(), 'PLATFORM=' + plat, 'clean'], stdout=devNull, stderr=devNull)
+    # subprocess.check_call(['make', '-C', '../', '-j' + calc_jobs_number(), 'PLATFORM=' + plat, 'clean'], stdout=devNull, stderr=devNull)
+    subprocess.check_call(['make', '-C', '../', '-j1', 'PLATFORM=' + plat, 'clean'], stdout=devNull, stderr=devNull)
     devNull.close()
     
     buildLog = open(origDir + '/build.release.' + plat + '.log', 'w')
-    subprocess.check_call(['make', '-C', '../', '-j' + calc_jobs_number(), 'PLATFORM=' + plat, 'release'], stdout=buildLog, stderr=buildLog)
+    subprocess.check_call(['make', '-C', '../', '-j1', 'PLATFORM=' + plat, 'release'], stdout=buildLog, stderr=buildLog)
     buildLog.close()
     
     # everything OK, can remove build log
diff --git a/ThirdParty/PSCommon/BuildSystem/Platform.Arm b/ThirdParty/PSCommon/BuildSystem/Platform.Arm
index c4a112d..cd12569 100644
--- a/ThirdParty/PSCommon/BuildSystem/Platform.Arm
+++ b/ThirdParty/PSCommon/BuildSystem/Platform.Arm
@@ -1,7 +1,8 @@
 ifeq "$(CFG)" "Release"
 
     # Hardware specifying flags
-    CFLAGS += -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=softfp #-mcpu=cortex-a8
+    # CFLAGS += -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=softfp #-mcpu=cortex-a8
+    CFLAGS += -march=armv7-a -mtune=cortex-a9 -mfpu=neon -Wno-unused-local-typedefs #-mcpu=cortex-a8
 
     # Optimization level, minus currently buggy optimizing methods (which break bit-exact)
     CFLAGS += -O3 -fno-tree-pre -fno-strict-aliasing


# build OpenNI
cd OpenNI2/Packaging
python ReleaseVersion.py  Arm

# maybe 1 hour needed, check build status "tail -f build.release.Arm.log" 

# install OpenNI
cd Final
tar -jxvf OpenNI-Linux-Arm-2.2.tar.bz2 
cd OpenNI-Linux-Arm-2.2
sh install.sh
source OpenNIDevEnvironment

# run sample application.
cd Samples/Bin
./SimpleRead

# use dual xtion depth stream sample
cd Samples/MultipleStreamRead/
vi main.cpp
#include <OpenNI.h>
#include <iostream>
#include <vector>
#include "OniSampleUtilities.h"

using namespace openni;
using namespace std;

class DepthSensor {
private:
    openni::Device device;
    openni::VideoStream depthStream;
    vector<openni::VideoStream*> streams;
 
public:
    DepthSensor() {}
 
    void open( const char* uri ) {
        Status ret = device.open( uri );
        depthStream.create( device, SENSOR_DEPTH );
        depthStream.start();
        streams.push_back( &depthStream );
    }
 
    void run() {
        int changedIndex;
        openni::OpenNI::waitForAnyStream( &streams[0], streams.size(), &changedIndex );
        if ( changedIndex == 0 ) {
            openni::VideoFrameRef depthFrame;
            depthStream.readFrame( &depthFrame );
            if ( depthFrame.isValid() ) {
            }
        }
    }
};
 
int main() {
    try {
        openni::OpenNI::initialize();
        openni::Array<openni::DeviceInfo> deviceInfoList;
        openni::OpenNI::enumerateDevices( &deviceInfoList );
 
        DepthSensor* sensor = new DepthSensor[deviceInfoList.getSize()];
        for ( int i = 0; i < deviceInfoList.getSize(); ++i )
            sensor[i].open( deviceInfoList[i].getUri() );
 
        while ( 1 ) {
            for ( int i = 0; i < deviceInfoList.getSize(); ++i ) {
                sensor[i].run();
            }
 
        }
        delete[] sensor;
    } catch ( exception& ) {
        cout << openni::OpenNI::getExtendedError() << endl;
    }
    return 0;
}
make
cd Bin/Arm-Release
./MultipleStreamRead

# like this.


オムロン HVC-Cを使った開発

HVC-Cを使った開発について備忘録で記載しておきます。

一般的にはSDKについている通りに作れば良いんだろうけど、iPhone/Androidのコードだけなのでやっぱり色んな環境で動かしたいよね…ということで、とりあえずopenFrameworks上を使うことに。

あと、SDKを見てみると、特にソースはBluetoothとの通信のコマンドとかそのまま見れる。という事で…Edison + NodeJSでも動かそうとして書いてあったのもあったんだけど、今見たらrmしちゃったようで、存在が無くなっていた…orz 方法的には「インテルEdison + BLEで、konashi/SBBLEを動かしてみた。」を参考にnobleとかで作れる。

一般的な作りとしての参考情報はこちらを。
HVC-C iOS SDKサンプルプロジェクトの起動
集中力を測定するCencentMeter – べるべる研究日誌
OKAO Visionがやってきた!!(4)

んで自分のアプリの環境、構成は以下の通り。

– センサ
HVC-C
モバイルバッテリ

– iPhone側
Mac OS 10.9.5
Xcode 6.1
openFrameworks 0.8.4(ios)
MQTT Kit

– 光りモノ側
Spark Core + LED沢山
MQTT Client

– 全体構成

iPhone/Server/Spark間はもちろんWiFiで、それぞれのパーツが無線で通信する。最近、自分はMQTTが好きでよく使う。MQTTを利用するとセンサーの値をsubscribeしている端末(ここではSpark)のMQTT側にpublishできるから以下のような感じにも。

MQTTを利用するとセンサーデータをpublishすればあとは、そのデータをsubscribeしている方に処理をまかせる事が出来るから、センサーデータを使ったアプリをネットワークを介してリアルタイムで行いたい時にはとっても便利。例えばHVC-Cを使う場合、取得できる人の数・顔の位置・表情の状態…etc をpublishしておけばあとは使いたい方で、好きなような処理を行うことが出来るという感じ。
別にSpark Coreを使わなくてもOKで、MQTTで受けれる物であればAndroid/iPhone/Win/Mac…etcなんでもsubscribeしておけばpublishされたデータが一斉に流れてくる。iPhoneとServer間は矢印が一方通行で書いちゃったけど、もちろんここも双方向。

んで、次にopenFrameworks側との合体については以下のような感じ。HVCのSDKに入っているソースコードを一式持ってきて(多少修正は入るけど)、oF側からコールするだけ。

これを動かすとこんな感じ。表情で色を変えているだけの単純な物だけど。

んで、oF側も出来て端末側(HVC-C/openFrameworks)は完成。つぎにモノ側、SparkのMQTTの処理はこんな感じのコールバックを書くだけ。

void callback(char* topic, byte* payload, unsigned int length);
MQTT client("hogehoge.com", 1883, callback);

int faceflg = 0;
// HVC-Cからpublishされてきたデータ
void callback(char* topic, byte* payload, unsigned int length) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;
    String message(p);

    if (message.equals("SURPRISE"))         faceflg = 0;
    else if (message.equals("NEUTRAL"))     faceflg = 1;
    else if (message.equals("HAPPINESS"))   faceflg = 2;
    else if (message.equals("ANGER"))       faceflg = 3;
    else if (message.equals("SADNESS"))     faceflg = 4;
}
void setup() {
    RGB.control(true);
    RGB.color(0, 0, 0);

    // connect to the mqtt server
    client.connect("sparkclient");

    // subscribeする
    if (client.isConnected()) {
        client.subscribe("/HVC/spark");
    }
}

void loop() {
    if (client.isConnected())
        client.loop();

    // 表情で何らかの処理(LEDピカー!!とかサーボ動かしたりやりたい放題)
    switch (faceflg) {
    .....
}

ちなみに、iOS側のpublish側はSDKに付いている内容だと、こんな感じでサクッと。

                NSString *expression;
                switch(fd.exp.expression){
                    case HVC_EX_NEUTRAL:
                        expression = @"NEUTRAL";
                        break;
                    case HVC_EX_HAPPINESS:
                        expression = @"HAPPINESS";
                        break;
                    case HVC_EX_SURPRISE:
                        expression = @"SURPRISE";
                        break;
                    case HVC_EX_ANGER:
                        expression = @"ANGER";
                        break;
                    case HVC_EX_SADNESS:
                        expression = @"SADNESS";
                        break;
                }

                [client connectToHost:@"hogehoge.com"
                    completionHandler:^(MQTTConnectionReturnCode code) {
                        if (code == ConnectionAccepted) {
                            [client publishString:expression
                                          toTopic:@"/HVC/spark"
                                          withQos:AtMostOnce
                                           retain:NO
                                completionHandler:^(int mid) {
                                    NSLog(@"message has been delivered");
                                }];
                        }
                    }];

この部分はopenFrameworks側で処理をしても問題無い(というか、その方が分離という意味では良いと思われ)。普通のMacOS上でも多分、少し修正すれば動くと思うけど、NodeJS/nobleとかでチョコチョコっといじって動かした方が便利だと思う。

といった感じで全部構成完了という感じ。このMQTTを使うパターンは他でもわりと使っていて、何気に自分は好き。サクッと配信して使いたい・処理したい人だけsubscribeすれば良いからね。

Android 3D Sensor

We(SIProp) developed many Android/ARM platform with 3D Sensor Application. Here is our deveop history about the Android/ARM with 3D sensor 😛

– Nexus7(Android 4.4.2), DepthSense DS325 ToF Camera, OpenNI2, Point Cloud(with openFrameworks), 2014

– ODROID U3(Android 4.4.2), DepthSense DS325, OpenNI2, Point Cloud(with openFrameworks), 2014

– Pandaboard(Android 4.2), Kinect, OpenNI2, 2013

– Raspberry PI, Xtion Pro Live, OpenNI2, 2013

– Pandaboard(Android 4.0.x), Xtion Pro Live, OpenNI, 2012

– Auto Chasing Turtle(beagleboard-xM, Ubuntu 10.10/Android 2.2), Kinect v1, OpenKinect, 2011

– ofxkinectxandroid(armadillo/beagleboard-xM, Android 2.2), Kinect v1, OpenKinect, 2011