Quantcast
Channel: その後のその後
Viewing all 317 articles
Browse latest View live

[iOS][Objective-C][Xcode]iOS 8 の新機能のサンプルコード集『iOS8-Sampler』を公開しました

$
0
0

WWDCでのアップルの発表によると、iOS 8 では4000以上もの API が追加されたとのことですが、新しいAPIはどう使うのか、実際に何がどこまでできるのか、といった具体的なところが、英語のドキュメントや動画をながめているだけだと正直あまりよくわかりません。やはり実際にコード書いて動かしてみるのが一番わかりやすい、ということで今年もつくりました、


iOS 8 新機能のサンプルコード寄せ集めアプリ『iOS8-Sampler』




ソースコードは GitHub に置いてあります。


https://github.com/shu223/iOS8-Sampler


※使い方は Xcode 6 でビルドするだけ なので、デザイナーさんやディレクターさんもぜひ最寄りのエンジニアにビルドしてもらってください。


中身について

今回はデザイナー okazu 氏の協力により立派なアイコンやスプラッシュ画像が最初から用意されていますが、中身は何のことはない、iOS 7 のときと同様のテーブルビューです。(※ここで凝るとサンプル追加が大変になる)



今のところ20個のサンプルが入っています。何か調べた折に随時追加していきます。機能追加プルリク大歓迎です!


以下サンプルのリストです。


Audio Effects

iOS の Core Audio においてもっとも低レイヤに位置し、リアルタイムで高度なオーディオ波形処理や、複雑なルーティングによるオーディオ処理を実現することができる Audio Unit というのが従来からあったのですが、これらは AVFoundation 等に比べると少々複雑で、しかもAPIがC言語タイプなので、自分のようなゆとりiOSエンジニアには少しハードルが高い部分がありました。

iOS 8 で追加された AVAudioEngine は、Audio Unit の Objective-C ラッパー的な存在で、上記のAudio Unitのハードルの高さを解消してくれています。


ギターのエフェクターのようにユニットを繋げる楽しさも健在で、本サンプルでは、ディストーションとか、ディレイといったエフェクトを音にかける実装方法を提示しています。使用している新クラスは AVAudioEngine, AVAudioUnitDistortion, AVAudioUnitDelay, AVAudioPlayerNode, AVAudioFile 等々。


New Image Filters

Core Image の CIFilter に追加された新しいフィルタ集。iOS 8 の Built-in フィルタは127種類あるのですが、新たに追加されたのは13種類 *1 で、本サンプルでは以下の6種類が試せるようになっています。

  • CIGlassDistortion
  • CIDivideBlendMode
  • CILinearBurnBlendMode
  • CILinearDodgeBlendMode
  • CIPinLightBlendMode
  • CISubtractBlendMode


関連記事:


Custom Filters

iOS 8 では CIKernel というクラスが追加され、Core Image のフィルタ(CIFilter)を自作できるようになりました。


これを用いたシンプルなフィルタの作成手順を以前記事に書きましたが、


本サンプルでは、この CIKernel を用いたサンプルを4種類、実装してあります *2



Metal Basic

Metal を使ったシンプルな描画サンプルです。Apple公式サンプルの "MetalBasic3D" をベースに作成。



Metal Uniform Streaming

Metal のサンプルその2。同名のApple公式サンプルをベースに作成。



SceneKit

Mac には以前からあり、iOS には 8 で初めて追加された SceneKit のサンプル。Appleのサンプルがどれも最初の一歩目にはややこしいと感じたので、アイコン画像を3D空間に置いてライティングするだけのシンプルなサンプルです。



HealthKit

iOS 8 の注目の新機能の1つ、HealthKit のサンプル。HealthKitで利用可能なデータ全種類を読み出すことができます。



が、データがないと始まらないので、まずはオフィシャルの Health アプリをいろいろ使ってみてデータを作成してください。


あと、プロビジョニングプロファイルの件も忘れずに。。


TouchID

指紋認証のデモ。iPhone5sなど、対応デバイスでお試しください。 LocalAuthentication フレームワークを使用。



Visual Effects

UIView にブラーエフェクトをかけられる、すなわちあの「磨りガラス効果」を実現するための新クラス、UIBlurEffect と UIVibrancyEffect のサンプルです。



Ruby Annotation

Core Text に追加された CTRubyAnnotationRef を用いて、文字列にルビ(ふりがな)を付けて描画するサンプル。



クラスメソッドさんの記事を参考にさせていただきました!


WebKit

WKWebView のサンプル。ロード中のプログレスがとれるようになったので、それを SVProgressHUD に反映して表示しています。



UIAlertController

UIAlertController を用いた Alert と ActionSheet のサンプル。



User Notification

Schedule a local notification which has custom actions using UIUserNotificationSettings.



Pedometer

新たに追加された CMPedometer クラスを使って歩数情報を取得するサンプル。



AVKit

新たに追加された AVKit framework の AVPlayerViewController を使って動画をストリーミング再生するサンプル。


Histogram

Core Image の CIFilter に新たに追加された CIAreaHistogram と CIHistogramDisplayFilter を使用して画像のヒストグラムを計算、表示するサンプル。



Code Generator

2次元コード(AztecCode)と 128規格のバーコードを生成するサンプル。Core Image の CIFilter に新たに追加された CIAztecCodeGenerator と CICode128BarcodeGenerator を使用。



New Fonts

iOS 8 で追加された 7 種類のフォントのサンプル。

  • AppleSDGothicNeo-UltraLight
  • KohinoorDevanagari-Light
  • KohinoorDevanagari-Medium
  • KohinoorDevanagari-Book
  • DamascusLight
  • LaoSangamMN
  • KhmerSangamMN


ちなみに iOS 7 で追加されたフォント 37 種類のリストはこちら:


Popover

UIPopoverPresentationController のサンプル。



Accordion Fold Transition

CIFilter の CIAccordionFoldTransition を用いたアコーディオンのように折り畳まれるような遷移エフェクト・・・のはずなのですが現状そのように動作していません。GitHub や Google で検索してもまったく先行例がないので、どなたか成功した方、プルリクお待ちしております。。


おわりに

新機能の実装記事もこれからどんどん書いていきます!


以下これまでに書いたもの。


*1:調べたのベータ版の頃なので、ひょっとしたら増えてるかも。。

*2:WWDC2014のスライドを参考に実装


[iOS][Objective-C][Xcode]【Xcode 6】delegateをセットするところで「incompatible type ’id’」なるwarningが出る件

$
0
0

たとえば下記のように、delegate プロトコルと、それをプロパティに持つクラスを定義し、

@protocol HogeManagerDelegate <NSObject>
@end

@interface HogeManager : NSObject
@property (nonatomic, weak) id<HogeManagerDelegate> delegate;
@end

HogeViewController で下記のように `setDelegate:` するとします。

[[HogeManager sharedManager] setDelegate:self];

で、これを Xcode 6 でビルドすると、

warning: sending 'HogeViewController *const __strong' to parameter of incompatible type 'id<NSFileManagerDelegate>'
    [[HogeManager sharedManager] setDelegate:self];

こんな warning が出てきます。


全然 NSFileManagerDelegate とか関係ない(プロパティにも親クラスにもない、プロジェクトで全く明示的には使ってない)し、Xcode 5 では warning 出てなかったし・・・ということで、当初はスルーしてたのですが、やはり気になるので対処方法を検討してみました。


対処法

+ (id)sharedManager;

となっていたのを、


+ (instancetype)sharedManager;

とすればOKでした。


instancetypeについて

instancetype というのは、

instancetype型は、上で述べたような「レシーバのクラス==返り値オブジェクトのクラス」となることを明示的に示すための、メソッドの返り値にのみ使える型です。

Objective-Cにおけるinstancetype型について - Takebayashi.Asia


ということで、問題のwarningは、明示的に戻り値のオブジェクトのクラスが指定できてないよ、ということを知らせてくれていたわけです。


そういえば、今回の iOS 8 の API diff も、この戻り値 id > instancetypes への変更が盛りだくさんでしたね。。


[iOS][デバイス連携][Bluetooth]【勉強会資料】BLEとは何か/BLEの実例

$
0
0

昨日、都内のとある企業のクローズドな勉強会で、Bluetooth Low Energy (以降、BLE) 関連の話をしてきました。


僕に直接声がかかったわけではなく、知り合いのエンジニアが IoT について講義を任され、その方からBLEまわりについて話してくれないか、という間接的な依頼だったのと、僕自身あまり IoT というキーワードをそれほど意識していないこともあり、会の趣旨やニーズに合致していたのか謎ですが、とにかく自分のやってきた BLE 関連の実例紹介と、ざっくりBLEとは何か、というあたりについて話しました。


参加者の層としては管理職、プロデューサー、企画の方が多い印象だったので、GATT等の技術的に踏み込んだ話ではなく、BLEの特徴が把握できるようなポイントだけにとどめています。


会自体はクローズド(社内向け)だったのですが、僕が話した内容はとくに秘密とかはないので、以下に資料を公開します。(一部編集済み)


自己紹介

  • 堤 修一(つつみ しゅういち)
  • フリーランスiOSエンジニア

経歴

  • 京都大学 工学部 電気電子工学科 / 京都大学大学院 情報学研究科(1997〜2003)
  • NTTデータ 音声処理 の研究開発(2003〜2007)
  • キヤノン 複合機の 画像処理 開発(2007〜2009)
  • カヤック iOSアプリ プログラマ(2010〜2012)
  • シリコンバレーのスタートアップに参画(2013)
    • Y combinatorと並ぶシードアクセラレータの名門、500 startups に採択
  • 独立(2014)

実績(IoT関連以外)

iOSアプリ

開発実績30本以上

  • バウンドモンスターズ(200万ダウンロード、売り上げ 数億円)
  • タップ忍者(App Store Best of 2012)
  • Domino's App (Canne Lions 2011)
オープンソース活動

GitHubで世界ランキング1位*1になったリポジトリを3つ保有

  • iOS7-Sampler (2013)・・・iBeacon等
  • iOS8-Sampler (2014)・・・HealthKit, HomeKit等

https://github.com/shu223


執筆

f:id:shu223:20140930104433j:image

  • ブログ「Over&Out その後」
  • gihyo.jpでの連載「iOSアプリと連携させて使えるデバイスたち」
  • iBeaconの講演@ワイヤレスセミナー

IoT関連実績

  • 国内では(おそらく)初の、実店舗へのiBeacon導入
    • iBeaconで入店管理
    • アプリから注文、店員呼び出し
    • 客単価20%アップ
  • BLE(詳細後述)
    • 次世代パーソナルモビリティ「WHILL」
    • ウェアラブルおもちゃ「Moff」
    • 耳の聴こえないダンサーに音楽を感じて踊ってもらうプロジェクト「music for the deaf」

本日の内容

  • BLEとは
  • BLE事例1: Moff
  • BLE事例2: WHILL
  • BLE事例3: music for the deaf
  • BLEとiBeacon

BLEとは

「2.4GHz の無線を使った近距離無線通信規格」

ポイント
  • 無線
  • 超低消費電力
    • ボタン電池1個で数年動作可能
  • 従来のBluetooth(〜3.0)とは別モノ
    • 両対応した4.0は「デュアルモード」と呼ばれる
  • 通信距離はチップごとに違うが、だいたい5〜10mぐらい
  • 通信速度は低い
    • 通信していないときの消費電力を極力下げることで消費電力を抑えることに特化した規格
    • 心拍センサーのように、常時データをやり取りする必要がなく、1回のデータ量も少ない用途に向いている
    • 音楽を流しっぱなしにするような用途にはクラッシックBluetooth
iOS と BLE

フレームワークが開発者に解放 されているため、対応アプリを自由に開発できる。

  • 従来Bluetooth対応デバイス/アプリの開発にはMFi(Made for iPhone)というライセンスプログラムへの加入が必要だった
  • バックグラウンドでの接続も可能
  • iOS7以上をサポートする多くの iOS デバイスで利用可(iPhoneでいうと4s以降)

BLE事例1: ウェアラブルなおもちゃ『Moff』

腕に巻くバンド型ガジェット。腕の動きに合わせてアプリから音がでる



  • Amazonにて予約受付中。妖怪ウォッチに次ぐ2位

Moff Band (モフバンド) ウェアラブル おもちゃ / スマートトイ iPhone iPad 対応

*1:GitHub Trendingにて

[Xcode][iOS][Objective-C]Xcode 6 時代のマルチデバイス対応 〜Size Classとベクター画像〜

$
0
0

とあるお仕事で、iPad をサポート(= Universal 化)してほしいという要望があり、せっかくなので iPhone 6 / 6 Plus (4.7 / 5.5 inch スクリーン)もサポートしようってことで、新しい Xcode 6 の新しい仕組みである Size Class を使って複数画面対応を行ないました。あと、同じく Xcode 6 から Asset Catalog でベクター形式がサポートされるようになったので、こちらもトライしてみました。


で、そのときに学んだ諸々の断片的なメモです。勘違いもあるかもしれないのでその際は優しくご指摘いただけますと幸いです。


※ちなみに Size Class やベクター形式画像の使用は iOS 8 以上縛りではありません。単に Xcode 6 の新機能というだけなので。


Size Class の前提知識をつける

「Size Classsとは」ってところを学ぶには、クラスメソッドさんの下記記事が日本語、図解入りでとてもわかりやすいです。


Size Class 機能を使って複数画面サイズ対応する手順のチュートリアル動画。英語ですが、音声なしでもわかりやすいです。Xcodeのプレビュー機能を駆使するのめちゃめちゃ大事。


シーン別 Size Class の指定方法

AutoLayout を Size Class ごとに指定する

もっとも基本的な Size Class の用法。IB の Size Inspector で設定します。


f:id:shu223:20141002091213j:image:w200


UIコンポーネントを Size Class ごとに指定する

後述しますが、ある UIコンポーネントの一部プロパティだけ Size Class ごとに変えたい、UICollectionView のレイアウトだけ変えたい、ってなると、そのコンポーネントのオブジェクト自体を Size Class ごとに使い分けることになります。


で、こちらは IB の Attributes Inspector で設定します(わかりにくい!)


f:id:shu223:20141002091234j:image:w200


ちなみに、IBAction は困らないのですが、IBOutlet は IB 上の1つのオブジェクトとしか接続できないのでちょっと困りました。僕は結局コードから subviews をたどって取得するようにしましたが、もっといい方法があるかもしれないです。


UIコンポーネントのプロパティを Size Class ごとに指定する

たとえば AutoLayout で iPad 用のとある UIButton のサイズを大きめに設定したとすると、その titleLabel のフォントも大きくしたい ということになってきます。


で、これを IB 上でプレビューしながら設定したい、となると結局、上記の「UIコンポーネントを Size Class ごとに指定する」で対応するしかないかと。


UICollectionView のレイアウトを Size Class ごとに指定する

iPad、全然サイズ感違うので、UICollectionView の UICollectionViewFlowLayout (もしくは、UICollectionViewLayout を継承する何らかのレイアウト)を別々に指定したい、ってことになると思います。


で、結論から言うと、自分は UICollectionView を Size Class ごとにつくる ことで対応しました。上述の「UIコンポーネントを Size Class ごとに指定する」方法です。Storyboard の該当 CollectionView 上でカスタムセルを定義していた場合は、それも自ずと作り直すことになります。


UITableView のセルの高さを Size Class ごとに指定する

UITableViewのセルの高さも、それ自体を IB から Size Class ごとに指定することはできないので、IB上で Size Class ごとにオブジェクトをつくる・・・のは面倒なので、 UITraitCollection で Size Class を判定し、それに合わせたセルの高さを heightForRow のデリゲートメソッドで返すことにしました。


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    // iPadかどうかの判定
    BOOL isPad = NO;
    if ([self respondsToSelector:@selector(traitCollection)]) {
        
        isPad = self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular;
    }
    else {
        isPad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
    }
    
    return isPad ? 160.0 : 80.0;
}

なお、上記コードは、画面の向きが Portrait であることを前提としています。また、iOS 7 には `traitCollection` プロパティがないので、従来の方法(UI_USER_INTERFACE_IDIOM)で iPad スクリーンかどうかを判定しています。


xib と Size Class

xib は AutoLayout とかは普通に指定できますが、Size Class ごとの指定ができません(よね??Xcodeは操作方法知らないだけで実はできるとかがよくある。。)


自分は、スクロールビューに動的に貼るビューとか、再利用したいビューとかは xib でインターフェースをつくってそこから生成するということを結構よくやるのですが、Size Class の指定ができないってことで、それらを Storyboard に移し替えました。で、その関係で、あんまり使ってなかった `childViewController` とかも使うようになりました。


(2014.10.2追記)コメント欄より xib でも Size Class 使えますよという情報をいただいて改めて確認してみたところ、File Inspector で [Use Size Classes] にチェックを入れ忘れてただけで、普通に使えました。


Asset Catalog のベクター形式サポート

ここから Asset Catalog のベクター形式の話。いろいろとわかりやすい記事が出ています。


あと、WWDC の "What's new in Interface Builder" セッション動画も参考になります。


要点だけ書くと、

  • Xcode 6 の Asset Catalog ではベクター形式の画像をサポート
  • 2x, 3xとか複数リソースを登録する必要がなくなる(1ファイルだけでOK)
  • SVG ではなく PDF 形式

ベクター形式サポートに関するよくある誤解

よくあるというか、僕が誤解してただけなんですが、このベクター形式サポートは、


アプリ内で どんな大きさで使っても奇麗に描画されるものではない ということです。


どういうことかというと、プロジェクトに入れるのはベクタ形式でも、ビルドする際にラスタライズされる *1ので、アプリ実行時に使用されるのは結局ビットマップ形式 ということです。


なので、普通に拡大したらジャギります。ベクター的に使いたいときにはSVGとかを(Asset Catalog じゃないところで)プロジェクトに追加して、今まで通り UIBezierPath とか CGPath で描画しましょう。(このベクタ描画については、拙著にも書いてあります)


ベクター画像のサイズ

大きめに書き出すといい、という情報もありますが、1x サイズで書き出す (つまり所望のポイントサイズ)というのが正しいです。ビルド時にラスタライズ、つまり 2x, 3x サイズのビットマップ形式の画像を生成してくれます。


大きめに書き出すといい、というのは上述の、拡大して使用するとジャギる、ということに端を発する誤解かと思いますが、それは本来あるべきサイズより拡大して用いるからであって、そういう場合はその拡大した状態でのサイズを本来あるべきサイズ(1x サイズ)として指定すればいいのであって、大きめサイズを指定するということではないかと。(わかりにくい文章ですみません)


あと困ったのが、Illustrator で書き出したサイズと、Asset Catalog に入れたときのサイズが合わないという問題。こちらの解決方法は今のところ不明・・・


その他複数画面対応に関連するメモ

謎の「-16」

Xcode 6 で AutoLayout を設定しまくってると必ずぶちあたる、「両端にぴったり 0 でAutoLayout設定しようとすると現れる、謎の "-16"」問題。下記記事で、その正体、対処法が解説されています。


6/6 Plus に最適化される条件

ご存知の通り、既存アプリに何も修正をいれない状態で 6 / 6 Plus で実行すると単純に拡大されるだけです。では、何を条件としてそれが 4.7inch, 5.5inch 最適化モード(※単純拡大されなくなった状態)に切り替わるのか、のメモです。


  • Launch 画像を登録する

Asset Catalog で、4.7inch, 5.5inch 用の Launch 画像を入れると、それぞれに最適化されたものとして描画されるようになります。


  • Launch Screen Fileを指定する

起動画面を Storyboard でつくれるようになった、っていうアレです。そういう Storyboard をプロジェクトに含めるだけならセーフ、[General] > [App Icons and Launch Images] > [Launch Screen File] でその Storyboard を指定すると 4.7, 5.5 対応が必要になります。


  • Asset Catalog への 3x 画像の登録

は、トリガにはなりませんでした。


6 Plus で表示してみると、普通にその 3x 画像が適用されましたが、単純拡大のまま。




*1:WWDC のセッション "What's new in Interface Builder" 参照

[openFrameworks][Xcode][Mac]【oFセミナーメモ1】 boostライブラリの使い方

$
0
0

デジタルアートセミナー#3 openFrameworksで学ぶ、クリエイティブ・コーディング』という一泊二日のセミナーに参加しています。


最終的なまとめは最後に書くとして、とりいそぎ本日受けたセッションのメモを載せていきます。


セッション1 : C++テクニック

講師 : 堀口淳史、藤本直明

openFrameworksを本格的に使う上で避けて通れないC++のテクニックを学びます。

今回は、boostライブラリの使い方について学びます。


環境

  • MacOS X 10.9.5
  • Xcode 6.1 GMAIL.COM seed 2
  • oF osx 0.8.4
  • boost 1.56.0

boostとは

  • C++の高度で便利なライブラリ
    • STLを拡張
  • oFにpocoってのがもともと入っている
    • pocoとは設計思想が違う
    • boostはテンプレートを駆使
    • STLと違ってC++の開発環境に始めから入っていない
  • boostで書かれた過去の資産を利用できるようになる
  • ヘッダだけインクルードして使うライトな使い方もある
    • 正規表現とかはコンパイルしないと使えない
  • 自分でコンパイルしてMac環境で動かすのがなかなかハードルが高い

課題

  • oFは32ビットバイナリ、boostは普通にインストールすると64ビットバイナリ
  • oFとboostを同時に利用しようとすると、それぞれlibstdc++, libc++を使おうとしててこのあたりがリンクエラーとかの問題になる

「oFで動くMacのboostバイナリ」をどう作るか?


解決策

  • oFを64bitバイナリとしてコンパイルするのは簡単ではない

→ boost のコンパイル時に x86 を address-modelに `32_64` を指定する


  • oFはlibstdc++利用前提、libc++を利用するとコンパイルできない
  • boost はlibstdc++でもlibc++でもコンパイルできる

→ boost のコンパイル時に cxxflags と linflags に `-stdlib=libstdc++` を指定する


libstdc++とlibc++

  • libstdc++は GCCと共に開発される古くから使われている標準ライブラリ
    • GPLライセンス
  • libc++は LLVM/Clangと共に開発された新しい標準ライブラリ
    • MIT ライセンスと UIUC ライセンス

(2014.10.13追記)libstdc++のライセンスについては、コメント欄より下記のようにご指摘いただきました。

libstdc++のライセンスがGPLというのは少し誤解を招いてしまいかねないです。

というのも、libstdc++は特別な条項(GCC Runtime Library Exception)が追加されているからです。これにより、libstdc++を使用するアプリケーションを作成しても、それを公開する際にGPLを適用する必要がありません。その点で、通常のGPLとは大きく異なります。


oFで手っ取り早く使う

  • poco/include/ 配下に boost フォルダのヘッダを丸ごとつっこんじゃえば、パスが通ってるので、ヘッダだけならすぐに使えるようになる(行儀悪い)
  • shared pointer とかはそのまま使える

スマートポインタ

普通のポインタ
ofImage * mTestImage;
mTestImage = new ofImage( "test.jpg" );
delete mTestImage;

new したら delete が必要。


スマートポインタの場合(ofPtr は oF のスマートポインタ)

ofPtr < ofImage > mTestImageSP;
mTestImage = ofPtr< ofImage >( new ofImage( "test.jpg" ) );

delete不要。


boostだと、

boost::shared_ptr< ofImage >

って感じでスマートポインタを使える


スマートポインタに NULL 代入はできないので、

mTestImageSP.reset();

で内部でデストラクタが呼ばれて NULL と同じ状態になる。( `if (mTestImageSP)` でfalseになる)


boostインストール

https://github.com/toolbits/boost_1_56_0_xcode610_universal_binary

boost_libstdc++.dmgを解凍

  • ヘッダだけを使う場合は、includeのフォルダをパス通ってるとこにコピーする
  • libはコンパイル済みのバイナリ
    • Xcode6, MacOS X 10.9で動くようにコンパイルしたもの
  • 一番よく入れるのが、`/usr/local`
    • OS標準以外のあとから追加したライブラリとかを置く場所として(macでは)よく使われる
cd /user/local
open .

この配下にコピー


サンプルプロジェクト

サンプルを動かしつつ、boostの機能を紹介。

https://github.com/toolbits/of_plus_boost_2014seminar


サンプル1: boosted

両端のスペースをカットする文字列処理。ヘッダの機能だけ使用。

boost::algorithm::trim()
void ofApp::setup(){
    std::string str;
    
    str = " Hello boost ";
    std::cout << str << std::endl;
    
    boost::algorithm::trim(str);
    std::cout << str << std::endl;
}

サンプル2: boost_algorithm

文字列処理のサンプル。これらもヘッダだけで可能。


両端の空白を削除

boost::algorithm::trim(str);

カンマで文字列を分割

boost::algorithm::split(vec, str, boost::is_any_of(","));
for (it = vec.begin(); it != vec.end(); ++it) {
    std::cout << *it << std::endl;
}

分割した各文字列の両端の空白を削除

for (it = vec.begin(); it != vec.end(); ++it) {
    boost::algorithm::trim(*it);
}
for (it = vec.begin(); it != vec.end(); ++it) {
    std::cout << *it << std::endl;
}

各文字列を|を区切りにして連結

str = boost::algorithm::join(vec, "|");

文字列の置き換え

boost::algorithm::replace_all(str, "|", " / ");

文字列を置き換えた結果を返す

str = boost::algorithm::replace_first_copy(std::string("C++ source code"), "C++", "boooooooooooooooost");

サンプル3: boost_regex

正規表現のサンプル。これは要バイナリ。このサンプルが動けばboostの全機能が使えるということ。

※プロジェクトに libboost_regex.a が追加されている


boost::regex regex("[^/]+?\\.o$");
boost::match_results<std::string::const_iterator> result;

見つかった項目をすべて表示

std::string::const_iterator bit;
std::string::const_iterator eit;
bit = str.begin();
eit = str.end();
while (boost::regex_search(bit, eit, result, regex)) {
    std::cout << "match = " << result.str() << std::endl;
    bit = result[0].second;
}

見つかった項目をすべて置換

str = boost::regex_replace(str, regex, "********.o");

※ofUtilsに同様の文字列処理機能もあるので一度眺めておくと良い


サンプル4: boost_format_lexical_cast

数値を文字列にキャスト。ヘッダだけでOK。


番号で指定された通りに値を文字列化

str = (boost::format("%1% %2% %3%") % 1 % "abc" % 3.14).str();

printf のフォーマット文も利用可能

str = (boost::format("%06X (hex)") % 12648430).str();
str = (boost::format("%d (dec)") % 0xDEADBEEF).str();

lexical_cast を利用した整数から文字列への変換

str = boost::lexical_cast<std::string>(141421356);
std::cout << str << " (string)" << std::endl;
std::cout << "---- ---- ---- ----" << std::endl;

lexical_cast を利用した文字列から整数への変換

ival = boost::lexical_cast<int>(str);

lexical_cast を利用した文字列から実数への変換

str = "0.12345";
dval = boost::lexical_cast<double>(str);

lexical_cast を利用した不正な文字列から実数への変換

str = "0.12???";
try {
    dval = boost::lexical_cast<double>(str);
}
catch (boost::bad_lexical_cast& e) {
    dval = NAN;
}

サンプル5: boost_thread

スレッドをつくる

  • libboost_system.a
  • libboost_thread.a

サンプル6: boost_mutex

変数へのアクセスを排他にするためのmutex

  • libboost_system.a
  • libboost_thread.a
boost::mutex _mutex;
// カウント変数を増加
_mutex.lock();
++_count;
_mutex.unlock();
// カウント値を取得
_mutex.lock();
count = _count;
_mutex.unlock();
// lock() / unlock() の替わりに lock_guard を利用しても同じ
boost::lock_guard<boost::mutex> guard(_mutex);

// カウント変数を減少
--_count;

サンプル7: boost_lock

shared_mutex を使うと、マルチスレッド処理において、read/writeをいい感じにロックしてくれる。

boost::shared_lock<boost::shared_mutex> rlock(_mutex);

書き込みロック(unique_lock)は1つのスレッドからだけ取れる

// カウント変数を増加
{
    boost::unique_lock<boost::shared_mutex> wlock(_mutex);
    
    ++_count;
}

読みこみロック(shared_lock)は何スレッドからでもとれる

boost::shared_lock<boost::shared_mutex> rlock(_mutex);
ofColor color;

// カウント値を表示
color.setHsb(abs(_count) % 255, 255, 255);
ofBackground(color);
ofDrawBitmapString((boost::format("%1%") % _count).str(), 10, 50);

[openFrameworks][3D][OpenGL]【oFセミナーメモ2】 GLSL(Shader)テクニック

$
0
0

セッション1「C++テクニック」(boostライブラリの使い方)のメモ に続いて、セッション2 のメモです。


セッション2 : Shaderテクニック

講師 : 藤本直明、神田竜、他

GLSL(Shader)と呼ばれるOpenGLの機能を解説し、それを応用した映像表現を学びます。今回は、3Dを中心としたシェーディング手法を中心に解説していきます。


GLSLとは

  • OpenGLと一緒につかうシェーディング言語
  • シェーディング: 3DCGの見た目を決める
    • 光源の計算
    • 陰影の計算
    • ピクセルの計算
  • C言語っぽい見た目
  • グラボで並列処理
    • CPUで処理するよりも高速

ofShader

  • oFではofShaderを使う
  • 適用部分をbeginとendで挟む
  • oFからパラメータも渡せる
mShader.load("test.vert", "test.frag", "test.geom");
mShader.begin();

mShader.setUniform1f("rad", 10);

mVbo.draw(GL_POINTS, 0 , NUM);
mShader.end();

GLSLの種類

処理順に、

  • Vertex shader
  • Geometry shader
  • Fragment shader

Vertex Shader

頂点座標の変換

  • 頂点をうねうねさせる
  • ライティングのための準備

Geometry Shader

頂点の数の増減

  • 法線の方向にヒゲを生やす
  • ポリゴンを分割する
    • LOD (Level of Detail)・・・カメラの近くは繊細に、遠くは荒くても良い、みたいな動的に頂点数を増減する、みたいな使い方

省略可能


Fragment Shader

最終的な色を決める

  • ライティング
  • いらない部分を破棄する
  • ポストエフェクト

"tea pot discard glsl" で画像検索すると、ティーポットをFragment Shaderで処理した例が見れる


ピクセルシェーダとも呼ばれる


フラグメントシェーダを使ったポストエフェクト

講義資料:

ピクセルシェーダ on ofxPostGlitch|ひつじ|note


ofxPostGlitch

使用手順
  • addons フォルダに入れる
  • shader が入ってるフォルダ(shaders_pg)を、プロジェクトフォルダ配下の bin/data 直下に入れる
    • shaderは実行時に読み込まれるため、バイナリのデータフォルダに入れる必要がある

ofApp.h

#include "ofxPostGlitch.h"
ofxPostGlitch postGlitch;
ofFbo buffer;

ofApp.cpp

void ofApp::setup(){

    buffer.allocate(1024, 768);     // バッファ確保
    
    postGlitch.setup(&buffer);      // fboのポインタを渡す
}
void ofApp::draw(){
    
    // FBOに円を描画
    buffer.begin();
    ofClear(0, 0, 0);
    ofSetColor(255, 0, 0);
    ofCircle(100, 100, 100);
    buffer.end();

    // エフェクト選択
    postGlitch.setFx(OFXPOSTGLITCH_INVERT, ofGetKeyPressed());

    // エフェクトをかける
    postGlitch.generateFx();

    // FBOの内容を画面に描画
    buffer.draw(0,0);
}

setFxの引数を変えればエフェクトが変わる

postGlitch.setFx(OFXPOSTGLITCH_GLOW, ofGetKeyPressed());

ofxPostGlitchType一覧(ヘッダより)

enum ofxPostGlitchType{
OFXPOSTGLITCH_CONVERGENCE,
OFXPOSTGLITCH_GLOW,
OFXPOSTGLITCH_SHAKER,
OFXPOSTGLITCH_CUTSLIDER,
OFXPOSTGLITCH_TWIST,
OFXPOSTGLITCH_OUTLINE,
OFXPOSTGLITCH_NOISE,
OFXPOSTGLITCH_SLITSCAN,
OFXPOSTGLITCH_SWELL,
OFXPOSTGLITCH_INVERT,
OFXPOSTGLITCH_CR_HIGHCONTRAST,
OFXPOSTGLITCH_CR_BLUERAISE,
OFXPOSTGLITCH_CR_REDRAISE,
OFXPOSTGLITCH_CR_GREENRAISE,
OFXPOSTGLITCH_CR_REDINVERT,
OFXPOSTGLITCH_CR_BLUEINVERT,
OFXPOSTGLITCH_CR_GREENINVERT
};

円にかけてみた例:

f:id:shu223:20141011214001j:image:w500

(左がOFXPOSTGLITCH_TWIST、右がOFXPOSTGLITCH_SWELL)


フラグメントシェーダ

// 1ピクセルごとにこの処理が行なわれる
void main (void)
{
    // 自分の座標を取得
vec2 texCoord = vec2(pos.x , pos.y);
    
    // 画像内のその座標における色を取得
vec4 col = texture2DRect(image,texCoord);;
    
    // 反転させる
col.r = 1.0 - col.r;
col.g = 1.0 - col.g;
col.b = 1.0 - col.b;
    
    // 反転後の色を適用
gl_FragColor = col;
}

`gl_FragColor` に突っ込んだ色( vec4 構造体)が最終的な色になる。


GLSLのバージョンについて

  • oF上でさくっと動かせるバージョンは120と150
  • oFのサンプル、vboMeshDrawInstancedExample のシェーダを見ると、バージョン120と150の違いがわかる
#version 120
#version 150

  • 言語の仕様が全然違う
    • 最後 `gl_FragColor` につっこむのは120の仕様
    • ofxPostGlitch は120ベース

oFで150を使う場合は、

#define USE_PROGRAMMABLE_GL 1

をヘッダで定義する


(あとで追記)パーティクルにテクスチャを貼る

聞くだけで精一杯だったのであとで追記します。


oFでのシェーディング

固定機能シェーダ
  • OpenGLに元々入っている
  • フラットシェーディング
  • グローシェーディング
  • ライティング

- ofLightとofMaterial


プログラマブルシェーダ
  • 自分でプログラムでシェーディングを記述できる
  • 固定機能シェーダの内容をすべて実現できる(が、全部自分で書かなければならない。大変。)
  • vertex shader

ライトの種類

(配布pdfがすごく詳しいので、メモは省略)


f:id:shu223:20141011212906j:image:w400

(この画像はoFのサイトにあったもの)


サンプル:multiLightExample

examples/gl/multiLightExample


球の解像度

ofSetSphereResolution(128);

f:id:shu223:20141011212822j:image:w500


128だからツルツル、10とかにすると荒くなる


f:id:shu223:20141011213048j:image:w500


解像度落として、smoothlightingをオフにすると、

ofSetSmoothLighting(false);
ofSetSphereResolution(10);

-> フラットシェーディング


法線ベクトルの求め方

ポリゴンの2つの辺の外積を計算する

ofVec3f c = a.crossed(b);

// 単位ベクトルにする
c.normalize();

拡散光の求め方

物体の法線とライト方向の内積から、拡散光が計算できる

float c = a.dot(b);

※固定機能シェーダを使う場合にはOpenGLが計算してくれるので、自分で計算する必要はない


グローシェーディング

球のシェーディングとかのときに、 滑らかな曲面を表現するために、隣り合う平面の法線を平均したものをそれぞれの面の法線とする 方法


oF の `ofSetSmoothLighting` をオンにした状態


[openFrameworks][Mac]【oFセミナーメモ3】プロジェクションマッピング

$
0
0

デジタルアートセミナー#3 2日目の最初のセッションは、プロジェクションマッピングについて。


講師 : 藤本直明、他

openFrameworksでのプロジェクションマッピングの基礎を学び、実際に数名ずつのグループで簡単な制作を行います。 また、エッジブレンディングやメッシュワープなど、実践的なプロジェクションマッピングを行う上でのテクニックについても紹介します。


過去のセッションのレポートはこちら。


プロジェクションマッピングとは

プロジェクションマッピングじゃないもの・・・マッピングしてなくて、ただプロジェクションしてるだけのものとか

プロジェクションマッピング事例

3D Projection Mapping promoting The Tourist in Dallas - YouTube


マッピングソフト

ofxQuadWarp

シンプルなマッピングのアドオン。4つの頂点を動かすとその矩形に合わせて映像をwarp処理してくれる。


f:id:shu223:20141012125640j:image:w600

(頂点調整前)


f:id:shu223:20141012125651j:image:w600

(頂点調整後)


使い方
// 画像読み込み
img.loadImage("quad_warp_kittens.png");

// 位置とサイズを取得
int x = (ofGetWidth() - img.width) * 0.5;       // center on screen.
int y = (ofGetHeight() - img.height) * 0.5;     // center on screen.
int w = img.width;
int h = img.height;

// FBO確保
fbo.allocate(w, h);

// 画像のrectを ofxQuadWarp にセット
warper.setSourceRect(ofRectangle(0, 0, w, h));              // this is the source rectangle which is the size of the image and located at ( 0, 0 )

// 4つの頂点の初期座標を ofxQuadWarp にセット
warper.setTopLeftCornerPosition(ofPoint(x, y));             // this is position of the quad warp corners, centering the image on the screen.
warper.setTopRightCornerPosition(ofPoint(x + w, y));        // this is position of the quad warp corners, centering the image on the screen.
warper.setBottomLeftCornerPosition(ofPoint(x, y + h));      // this is position of the quad warp corners, centering the image on the screen.
warper.setBottomRightCornerPosition(ofPoint(x + w, y + h)); // this is position of the quad warp corners, centering the image on the screen.

// セットアップ&ロード
warper.setup();
warper.load(); // reload last saved changes.

Quad Warp事例

トラッキングしてプロジェクション

kz - Party in the Car - DRIVING KIDS with TOYOTA スペシャルムービー feat. ULTRA JAPAN 2014 - YouTube


講義資料: プロジェクションマッピング実例と応用|ひつじ|note

車に再帰性反射材のマーカーを付けて、車の位置をトラッキングしながらその周りで映像が展開するという演出です。車のトラッキングには、6台のoptiTrackを15mの高さから吊り下げてセンシングをしています。


optiTrackとは赤外線による光学式モーションキャプチャで、複数台を連携させて高い精度とfpsでマーカーの位置が取得できるデバイスです。


車にマッピングしたくないので、車には白い光をあてて、プロジェクションを逃がしてやる。

再帰性反射材のマーカーを3つ載せて、OptiTrack でトラッキング

  • ラジコンでテスト
  • マーカー付きステッキでテスト

OptiTrackの処理が速く、プロジェクターの処理が追いつかない ので、進行方向にちょっと進ませた場所に投影(講義資料の、『レイテンシ補完』参照)


ジオラマに投影

https://www.youtube.com/watch?v=SRCVKciy-zI


複数のプロジェクタで投影する

エッジブレンディング

プロジェクタ間のキャリブレーション

Mac の [設定] > [ディスプレイ] > [カラー] > [補正]

ディスプレイキャリブレータ・アシスタントが起動する

薄目で林檎マークが溶け込むポイントで、全プロジェクタを調整する


メッシュワープ

Quad Warp みたいに4点だけじゃなくて、もっと多くのポイントでwarpできる・・・曲面への投影


https://www.youtube.com/watch?v=xqrJrqcqFBQ


  • 使用したoFアドオンは非公開
  • OpenGL の命令を直叩きで実装してある

MappaMok

  • カメラで撮影した画像と3Dモデルを合わせる
    • さまざまなパターンをプロジェクタから投影 → カメラで撮影

参考リンク: Kyle McDonaldの「光の演習」ワークショップ@SUPER FLYING TOKYOに参加してきました - Over&Out その後


[openFrameworks][動画処理]【oFセミナーメモ4】openFrameworksと映像制作ソフトの連携

$
0
0

デジタルアートセミナー#3 openFrameworksで学ぶ、クリエイティブ・コーディング』のライゾマ比嘉さんのセッション『openFrameworksと映像制作ソフトの連携』のメモ。

講師 : 比嘉了

AfterEffectsやCinema4Dなどの映像ソフトとopenFrameworksを連携させる映像制作手法の紹介を行います。


講義資料はこちらで公開されています。markdown形式。


過去のセッションのレポートはこちら。


事例紹介

(ダンスのやつ。動画メモし忘れました)

  • 手と頭につけてるマーカーで軌跡を書く
  • 他の部分は動的生成ではなく、CINEMA 4Dであらかじめ用意していたもの

Illustratorとの連携:ofxPDF

ベクタデータのうち、SVGよりPDFの方がロードが10倍ぐらい速いことがあったので、それからはPDFを使っている。そのPDFをoFで取り扱うアドオン。


普通に描画
ofxPDF pdf;
pdf.loadPDF("tiger.pdf");
pdf.draw();

テキストアニメーション

f:id:shu223:20141013174237j:image:w400

(アニメーションの途中の様子です)


void draw()
{
    float app_time = ofGetElapsedTimef();
    float animation_time = fmodf(app_time, 2) / 2.;
    
    cout << "app_time: = " << app_time << ", animation_time: " << animation_time << endl;
    
    ofSetColor(0);
    
    // PDFのパスを順番に取り出して ofPolyline で描画する
    for (int i = 0; i < pdf.getNumPath(); i++)
    {
        ofPath& path = pdf.getPathAt(i);
        
        vector<ofPolyline>& polys = path.getOutline();
        for (int k = 0; k < polys.size(); k++)
        {
            ofPolyline poly = polys[k];
            
            poly = poly.getResampledByCount(100);
            
            int target_size = poly.size() * animation_time;
            poly.resize(target_size);
            
            poly.draw();
        }
    }
}

順番に見ていくと、


1. パスを取り出す

ofPath& path = pdf.getPathAt(i);

2. パスのアウトラインを取り出す

vector<ofPolyline>& polys = path.getOutline();

ofPolyline がベクタで得られる


3. ofPolylineをリサイズしながら描画する

for (int k = 0; k < polys.size(); k++)
{
    ofPolyline poly = polys[k];

    poly = poly.getResampledByCount(100);

    int target_size = poly.size() * animation_time;
    poly.resize(target_size);

    poly.draw();
}

各アウトラインが、長さ0から元の長さに戻っていく。


After Effects との連携:ofxAfterEffectsKeyframeParser

サッカーのボールの軌跡を追う

AEにはそういう機能が入っている: tracker

-> キーフレームとして入る

-> ofxAfterEffectsKeyframeParser で読む


f:id:shu223:20141013174310j:image:w600


画像解析不要!


Cinema 4Dとの連携:ofxAlembic

https://github.com/perfume-dev/ofxAlembic

  • メッシュアニメーション
  • パーティクル
  • polyline
  • カメラワーク

などが読み書きできる


f:id:shu223:20141013174340j:image:w600

f:id:shu223:20141013174400j:image:w600

(それぞれ ofxAlembic に付属のサンプルを実行したもの。アニメーションします)



[openFrameworks][画像処理][動画処理]【oFセミナーメモ5】映像解析

$
0
0

デジタルアートセミナー#3 openFrameworksで学ぶ、クリエイティブ・コーディング』の最終セッション『映像解析によるインタラクション』のメモです。

openFrameworksとOpenCV(ofxOpenCV、ofxCv)を組みあわせることで、映像を用いたインタラクティブな表現の可能性が大きく拡がります。このセッションでは、実例を紹介しながら映像とのリアルタイムなインタラクションの手法を探ります。


田所先生のイントロ、ひつじさんのオプティカルフロー+ドロネー変換、ライゾマ登本さんによるアドバンストな話、の3本立て構成でした。


過去のセッションのレポートはこちら。


田所先生のイントロ

講義資料: Session 6: 映像解析によるインタラクション


オプティカル・フロー

映像内の物体の動きを、ベクトル場で表したもの


f:id:shu223:20141013191045j:image:w500


2種類のアルゴリズム
  • Gunner Farneback

- 密なオプティカルフロー

- ofxCv::FlowFarneback

  • Pyramidal LK

- 疎な特徴集合に対するオプティカルフロー

- ofxCv::FlowPyrLK


ひつじさん

講義資料: オプティカルフローを使ったモーショングラフィックス生成|ひつじ|note



ダンサーさんの踊っている映像を使用して、それをリアルタイムにカットアップしながらオプティカルフローを使ったグラフィックを載せているというプログラムです。


  • YCAMのダンサーの映像にオプティカルフローをかける・・・特徴点を抽出
  • ofxDelaunay ドロネー変換

ドロネー図 - Wikipedia


f:id:shu223:20141013191122p:image


登本さん

Kinectで3Dモデリング

キャリブレーション

  • Kinect3台
  • それぞれのカメラの位置がわかってない
  • そのままだと 2.5d
  • 光る玉を3台のKinectから見える位置で振る
    • kinectのcolorの方で見ると、暗い部屋との対比で、簡単に中心位置を割り出せる
  • カメラ位置の推定に、OpenCV の estimateAffine3D を使用

ofxEvm

Eulerian Video Magnification

動画の中から、人間の目ではわからないような微細な変化を検出する


Eulerian Video Magnification - YouTube


EVMのアルゴリズム

f:id:shu223:20141013191301j:image:w600

(上記動画内の解説図)


論文と MATLAB
  • 論文のコードは MATLAB で公開されてることが多い
  • EVM も MATLAB でコードが公開されてる
  • MATLAB が使われるのは、その世界ではみんな使ってるので、referされやすいから。Pythonも増えてきた。
  • MatLabからのC++エクスポート機能はつかってない。自分でC++で書き直している。

SVGでAR
  • カメラを固定して、映っている対象物の頂点の位置を示したSVGファイル をつくる
  • → その位置に別の映像をオーバーレイするとAR的なことができる
  • CameraCalibrate3D を使用 する
  • 最終的なテクスチャをズームしたり変位させたり回転させたりすることでカメラが動いてるっぽくも見える

TLD Tracker

Tracking Learning Detection



ofxTldTracker

  • ライセンスはLGPL

OpenCV 3.0 にTLDアルゴリズムのとラッカーが追加される

Tracker Algorithms — OpenCV 3.0.0-dev documentation の TrackerTLD


[openFrameworks][動画処理][画像処理]一泊二日のopenFrameworksセミナーに参加してきました

$
0
0

先週末、『デジタルアートセミナー#3 openFrameworksで学ぶ、クリエイティブ・コーディング』という一泊二日のセミナーに参加してきました。(※参加者のTLでは「oFセミナー」という呼称の方が一般的でした)


自分にとっての openFrameworks (以下 oF)は、 去年真鍋さんと仕事したいがために少しかじってみた ものの、さらっと基礎をなでただけで結局一度も実案件で使うことも自分で何かつくってみることもなかった、という程度の縁しかありません。


それでも参加したのは、講師陣と内容がすごく興味深かったからです。


2014年の今に boost ライブラリについてがっつり2時間半教えてくれるセミナーはなかなかないだろうし、iOS 8 から CIKernel が追加されて GLSL で Core Image のカスタムフィルタをつくれるようになった ので、GLSL についてプロ中のプロから直接学べるなら是非ともという感じだし、プロジェクションマッピングは流行り始めてから数年経つけど自分ではやったことないので要素技術とかポイントは把握しておきたいし、映像制作ソフトの連携や映像解析の話も興味ある分野だったり。


つまるところ oF 抜きにしても今回のセミナー内容は自分にとって学びたい内容ばかりだったので、募集開始直後1分以内ぐらいに全力で応募した次第です。


で、実際に参加してみた結果、期待以上でした。「これが聞けただけでも参加した甲斐があった!」と思った話が何度あったことか。これで宿泊費込みで1.5万円は安すぎるので、次回あったら10万円でも参加したいというレベルです。(実際に講師/TAの方々に正規フィーを払ったらそれでも済まないだろうけど。。)


では以下、それぞれのセッションについて。


セッション1 : C++テクニック(boostライブラリの使い方)

講師 : 堀口淳史、藤本直明

openFrameworksを本格的に使う上で避けて通れないC++のテクニックを学びます。

今回は、boostライブラリの使い方について学びます。


oF も C++ も初心者レベルだったので参加前はついていけるか不安だったのですが、基礎の基礎からじっくり丁寧に解説してくれて、libstdc++ と libc++ の違い とか、「oFで動くMacのboostバイナリ」をコンパイルするためのビルドオプションがどういう理由で決まってくるのかとか、あとboostの使い方自体も、非常に勉強になりました。


詳細な講義メモはこちらにあります。


セッション2: Shaderテクニック(GLSL)

講師 : 藤本直明、神田竜、他

GLSL(Shader)と呼ばれるOpenGLの機能を解説し、それを応用した映像表現を学びます。今回は、3Dを中心としたシェーディング手法を中心に解説していきます。


冒頭に書きましたが、iOS 8 から CIKernel で自前フィルタを GLSL で書けるようになったし、GPUImage とかで自前フィルタ追加したい場合もシェーダを自分で書ける必要があるしで、わりと以前から自分の中でシェーダはちゃんと勉強したい項目のひとつでした。


で、やっぱりこのセッションも超勉強になりました。


自分が興味があったところはフラグメントシェーダ(ピクセルシェーダとも呼ばれる)のあたりで、よく分かってなかった Vertex Shader とかのあたりもすごく腹落ちしたし、ライティングについても ライトの種類から拡散光の求め方まで順序立てて教えてもらえて、これまた勉強したいと思っていた3Dプログラミングの勉強もできた感じです。


f:id:shu223:20141011213048j:image:w600


詳細な講義メモはこちらにあります。


セッション3: 自己紹介&ショートセッション

講師/TA陣が自分の案件とその中で使ってる技術Tipsを紹介してくれるセッション。流れ解散制で、自分は深夜2時に退室したのですが、実に深夜3時半までセッションは続いたそうです。


オフレコな話が多かったので詳細レポートはできませんが、「あの案件の裏側はこうなってたのか!!!」みたいな話が盛りだくさんでこれまた勉強になりすぎる内容でした。


あと、みなさん技術+デザインとか演出のセンス+アイデアがすごくて、iOSしかできない自分はより精進せねば・・・と改めて思ったのでした。


セッション4: プロジェクションマッピング

openFrameworksでのプロジェクションマッピングの基礎を学び、実際に数名ずつのグループで簡単な制作を行います。 また、エッジブレンディングやメッシュワープなど、実践的なプロジェクションマッピングを行う上でのテクニックについても紹介します。


個人的にはあまりプロジェクションマッピングにはそんなに興味がなくて、そしてやったこともなく、でもすごい流行ってるのでちょっと気になる、ちょっと自分で体験してみたりはしたい・・・みたいな存在だったので、まさにうってつけのセッションでした。


f:id:shu223:20141012125651j:image:w600


講義メモ:


このセミナー全体を通して感じたことですが、プロジェクションマッピング(とかAR)は、もはや興味があるとかないとかのレベルじゃなくて、リアルな場での表現手段としてもはや当たり前なものになってるんだなーと。「これはプロジェクションマッピングの作品です」みたいな感じじゃなくて、演劇の背景だったり、TVのスタジオで世界観をつくる使い方だったりで表現のいち手法になってる感じ。


セッション5: openFrameworksと映像制作ソフトの連携

ライゾマ比嘉さんのセッション。


AfterEffectsやCinema4Dなどの映像ソフトとopenFrameworksを連携させる映像制作手法の紹介を行います。 (AfterEffectsやCinema4D、Ableton Live、Adobe Premiereなどをお持ちの方は、持参して頂けると手元で試せるのでよいかもしれません)


受講前は、「AfterEffects持ってないなー」「Cinema4D??」ぐらいの感じだったのですが、動画内のサッカーボールのトラッキングを After Effects でやって、そのキーフレームを取り出すことでいかにも映像解析がすごい的に見せる みたいな方法は目からウロコで感動しました。


f:id:shu223:20141013174310j:image:w600


あと、ofxPDF というアドオンで、PDFベクタ形式のデータを読み取ってアウトラインを順番に取り出してアニメーション表示するやつは、すごくいい感じなので iOS ネイティブにも移植しようかと。Xcode 6 の Asset Catalog でも PDF ベクター形式をサポート したので、PDF 形式自体が iOS 界隈で一般的になってきそうだし。


f:id:shu223:20141013174237j:image:w400


講義メモ:


セッション6: 映像解析によるインタラクション

openFrameworksとOpenCV(ofxOpenCV、ofxCv)を組みあわせることで、映像を用いたインタラクティブな表現の可能性が大きく拡がります。このセッションでは、実例を紹介しながら映像とのリアルタイムなインタラクションの手法を探ります。

田所先生のイントロ、ひつじさんのオプティカルフロー+ドロネー変換、ライゾマ登本さんによるアドバンストな話、の豪華3本立て構成でした。


動画の中から、人間の目ではわからないような微細な変化を検出するアルゴリズム EVM(Eulerian Video Magnification)、トラッキングしながらリアルタイムに学習もしていく TLD(Tracking Learning Detection)アルゴリズム等々、非常に勉強になりました。


f:id:shu223:20141013191301j:image:w600

(EVMの処理フロー)


講義メモ:


あと、講義の後に、登本さんにとあるライゾマ案件のしくみについて直接聞いてみたところ、自分が用意してた答えとは全然違ってて、聞かないとわからなかったであろう方法だったので、それもほんと質問してよかったなと。


おわりに

最高でした!主催のみなさま、講師のみなさま、TAのみなさま、セミナーハウスのみなさまどうもありがとうございました!!


[制作実績][Bluetooth]MoffとWHILLのアプリがリリースされました!その開発裏話など。

$
0
0

iOSアプリ開発者を名乗る者として恥ずかしい話なのであまり自分から積極的に言って来なかったのですが、実はわたくし、2012年末以降、実に2年近く一本もアプリを出せてませんでした


いや、コードはたくさん書いてたんですが、2013年前半はひたすら 書籍執筆とそのサンプルコード作り だったし、後半は SDK をつくってたので、自分の書いたコードが人様のアプリには入ってはいたものの、やはり自分が開発したアプリが出ました!という感はなく。そして2014年になって独立してからも、諸事情でストアに出さないことになったり、プロトタイプやデモまでのお手伝いだったりということが多かったもので。。


で、そんな中、がっつりお手伝いさせていただいたアプリがこの10月に立て続けにリリースとなったのでご報告させていただきます!


裏話、とまでは言えないかもしれませんが、アプリの紹介以外に、開発の経緯とか、働き方とか、技術的なことについても(公開して問題ない範囲で)少し紹介したいと思います。


次世代パーソナルモビリティ『WHILL』

f:id:shu223:20141017084400j:image:w600


昨日ストアに出たばかりの、次世代パーソナルモビリティ WHILL と BLE により連携するアプリです。


f:id:shu223:20140930104709j:image:w500


アプリの機能

f:id:shu223:20141017083349p:image:w600


  • リモートコントロール

ベッドサイドにWHILLを呼び寄せる、介助者が操作する、といったユースケースを想定した機能です。BLEの用途として遠隔操作はベーシックなアイデアですが、WHILLのようにおもちゃサイズではないものがラジコンのように手元のスマホから動かせると、未来感あります。


  • シートのスライドをコントロール

WHILLは乗り降りしやすいようにシートを前後にスライドさせることができるのですが、その操作部はアームの下側にあるので、ベッドなどからWHILLに載る際にはスマホから操作できると便利だそうです。


  • 内部パラメータ設定

パワー、前進速度の最大値、最小値、前進加速度の最大値、最小値、前進減速度の最大値、最小値、後進速度の・・・等々々、19種類におよぶパラメータがあり、これらを自分好みのチューニングにしたいというニーズが非常に強いそうです。100人いれば本当に好みが100人違うそうで、サービスマンが全米を飛び回ってチューニングしてるとコストが莫大になってしまうので、BLE経由で自ら設定変更できるようになっています。


WHILL本体なしで試す

もちろんWHILL本体ありきのアプリなのですが、

  • 最初の "WHILL BLE KEY" の入力ダイアログをキャンセルして、
  • CONNECTボタンじゃなくその下の "START WITHOUT WHILL" を選択

することで一通り試してみることはできます。


https://itunes.apple.com/app/id926042487


開発体制

WHILL の CTO 福岡さんが WHILL 本体側(回路設計&ファーム実装)、アプリ側を堤が担当しました。


アプリのデザインはカヤック時代の同僚、おかず にお願いしました。


BLE112 Development Kit

WHILL は BLE チップとして Bluegiga 社の BLE112 を使っています。で、開発で大活躍したのが下記画像の Development Kit で、


f:id:shu223:20140930104801j:image:w400


これはディスプレイ・USBインターフェース・バッテリーボックス・デバッガ・確認用のセンサ等々、BLEモジュールの開発・検証に必要な諸々がボードにビルトインされているので、部品を集めて回路を組んだりしなくても、買ってすぐに BLE モジュールのファームウェア開発を始められるという代物です。


WHILL は物理的にもコスト的にも開発用に本体を何台も用意したりすることは難しいので、基本的にWHILL本体と繋げて動作させるのは実装完了してからの動作確認時ぐらいになってきます。


で、それまではiOSアプリ側は、この Development Kit を WHILL の代わりの接続先として使ってました。WHILL側の福岡さんと gatt.xml を共有しつつ。


参考記事: 【改訂版】BLE112 / 113 の開発環境を Mac に構築する - Over&Out その後


参加の経緯

WHILL を手伝い始めたのはけっこう前で、今年の3月に遡ります。CEO 杉江さんから Facebook Message をいただいたのがきっかけでした。


当時から iOS × デバイスの BLE 連携は一番やりたい分野だったし、WHILLは 500startupsにいたころから プロダクトもチームもリスペクトしてたので、ぜひともやりたいですとがっつり食いつかせていただきました。


で、CTO福岡さんと何回かスカイプミーティングをしたあと、町田の工房に行ってWHILLに乗せてもらい、まずは仕様やその後の開発方法について話し合いつつBLE接続なしのUI/UX共有用アプリをつくり、という感じでゆっくりと手伝い始めました。


(当時のブログ記事:独立して最初の3ヵ月間にやったお仕事のまとめ - Over&Out その後


で、その後も基本的に毎週土曜日、でも福岡さんが忙しかったり出張だったりすると中止になるので、だいたい月に3人日ぐらいのペースで開発を進めてきました。


TV出演

アプリだけWBSに出演したこともあります。



ウェアラブルなおもちゃ『Moff』

Moff は、Kickstarter 向け出荷が先月だったので実はそのときにはアプリはもう出ていたのですが、正式に 10/15 に発売になりました!



お子さんのいらっしゃる iOS な方々はぜひお買い求めいただけると嬉しいです。Amazon電子玩具部門で妖怪ウォッチに次ぐ2位の人気だそうです。(僕も甥っ子達へのプレゼント用に2つ買いました)


こういうおもちゃです↓↓↓↓


コンテンツについて

刀でキンキンやりあったりボクシングでボコボコするのも楽しいのですが、なんといっても Drum が楽しいです。



自分の中心軸から左の方に向いて腕を振る(ドラムスティックを振る感じで)とハイハットとスネアが、右に向いて振るとタムが鳴ります。で、上の方で振るとクラッシュシンバルが鳴ると。子供からも(その演奏姿を観る)親御さんからもすごく評判がいいそうです。


ちなみに、最初に入っているコンテンツは13個ですが、いま審査に出しているバージョンから、追加コンテンツの配信機能(一定の条件でダウンロードできるようになる)がつきます!


開発体制

iOSアプリのバージョン1.1.0(審査中)までに関しては、CTO米坂さんと僕とで実装しています。もちろん、ハード、サーバーサイド、デザイン、ジェスチャ認識アルゴリズム開発等々含めるともっと多くの人が関わっています。(が、どの辺りまで書いてよいか要確認なので控えておきます)


参加の経緯

とあるミートアップでCTO米坂さんが声をかけてくれたのがきっかけでした。ちょうどその数日前に「Kickstarterで2日間で目標調達額を達成!」というニュースをFacebookで見かけて興味を持っていたところだったので、こちらも全力で食いつき、GW明けから開発に参加させていただきました。


こちらは最初2週間ぐらい集中して入ってアプリの基本形をつくった後、その後は開発内容やフェーズに応じて週2〜3ペースでお手伝いさせていただいてます。


おわりに

書いてて気付いたのですが、どちらも「CTOとがっつり一緒に開発」というところが共通してるなーと。

  • 開発にまつわる諸々が技術的なことも含め共有できて、
  • プロダクトへの愛と責任があって、
  • その場で即断する裁量がある

方と一緒にやれる場合に自分はいい関係が築けることが多いのかなと。(もちろん今後これ以外にもいろんなパターンがあるとは思いますが)


そんなわけで、WHILL と Moff とそのアプリとフリーランスiOSエンジニアの堤を今後ともよろしくお願いします!


[iOS][Xcode]【UIScrollView × Autolayout 問題】Appleエンジニア直伝のファイナルアンサー

$
0
0

iPhone6,6Plus サポートとか LaunchScreen.xib とか Size Class とか考えると、もはや Autolayout は必須な感じになってきてます。



で、Autolayout ✕ UIScrollView の例の問題(UIScrollView のサイズを superview との制約で動的に変えるときにその中身も動的に変えたい、ってやつ。こんな雑な説明でもハマったことある人にはわかっていただけるかと・・・)、Apple 公式でこんなドキュメントが出てますが、



"Mixed Approach" とかなんか筋が悪い感じだし、"Pure Auto Layout Approach" とかサンプル見ると Constraint を例のビジュアルなんとかで書いてて正直どっちも真似したくない感。。Xcode 5 時代のドキュメントでちょっと古いし。。


StackOverflow でもあんまりピンとくる回答は見つからないし、UIScrollView はなるべく使わず、ページング的なやつは UIPageViewController とか UITableView とか UICollectionView でやろうみたいな話も見かけました。


もっとストンと腹落ちする解決法ないのかなーと思ってたところに、友人の開発者からこんな記事を教えてもらいました。



Apple エンジニア直伝のシンプルな解決法

WWDC で Apple のエンジニアにやらせてみたところ40分かかったそうです笑


で、その一番のポイントがこれ。


f:id:shu223:20141030074942p:image:w400


UIScrollView の中身のビューに対して、「幅 or 高さの基準にする view について "Equal Widths" or "Equal Heights" となる制約をセットする」というものです。


すごくシンプルな上に、納得感もあります。


やってみた

UIScrollView 直下のビューが

  • 複数ある
  • 幅ピッタリじゃない(space 0 じゃない)

場合も、以下のようにそれぞれ Equal Widths 設定すると、


f:id:shu223:20141030075117j:image:w600


バッチリ意図通りに、幅は縮小されて、高さ方向はスクロールするようになりました。


f:id:shu223:20141030075156g:image



[制作実績]独立してから第3四半期目の実績まとめ

$
0
0

3ヶ月ごとにフリーランスとしてやらせていただいたお仕事をまとめています。

とくに会計年度を定めてるわけじゃなくて、3ヶ月ごとに書いてて3回目なので「第3四半期目」と題しました。時期的には2014年8月〜10月です。


概要

ざっくり書いておくと、こんな感じです。


【新規】

  • SmartDrive
    • 車とスマートフォンをつなぐデバイスとアプリをつくっているスタートアップ
  • 書籍の執筆
    • iOS × BLE の技術書
    • konashiの開発者、松村礼央さんとの共著
  • 海外書籍のレビュー
    • とある海外出版社のiOS 8 技術書のレビュアー
  • 1〜数人日の作り切りアプリ開発数件
  • 講演、登壇いくつか
  • iOS8-Sampler
    • 個人でやってるOSSプロジェクト
    • GitHub Trendingでrepository/developer部門両方で1位に!

【継続】

  • WHILL
    • 10月、制作したiOSアプリがリリース!
  • Moff
    • 10月に一般販売開始!
  • 真鍋大度さんとのお仕事:music for the deaf
    • 8/13 横浜パラトリエンナーレの特別イベントとして、プレゼンテーション(ライブパフォーマンス)を実施

SmartDrive

9月ぐらいからiOSアプリを手伝い始めました。


会社やプロダクトの詳細はこちらを。


車の OBD2(On Board Diagnosis second generation)端子に挿せるデバイスから、BLEでスマホに走行データを送り、データ解析して付加価値を提供するプロダクト/サービスです。


f:id:shu223:20141104123751j:image:w600


僕が参加した時点である程度アプリもデバイスも実証実験ができるぐらいにはできあがってましたが、ソースコードがまだリーン的(←誤用)だったので、未実装機能を実装しつつ関連部分をリファクタリングしていくような感じで関わり始めました(たとえば、初日はissueに対応しつつ肥大化していたストーリーボードを切り分けるところから着手)。


継続的にお手伝いすることになったのは WHILL、Moff 以来なので、結構久しぶりの新規クライアント、という感があります。


書籍執筆

10月ぐらいから、iOS × BLE の技術書を書き始めました。konashi の開発者、松村礼央さんとの共著です。


実は3月ぐらいにはお話をいただいていたのですが、「(僕より詳しい人が山ほどいる中で、)なぜ自分が書くのか?」というところと、前著を書くのがめちゃめちゃ大変だった(他の仕事を全部断って5ヶ月間かかりっきり)というトラウマ(?)もあってなかなか乗りきれずにいました。


特に、なぜ書くのか?というところでは、

  • 上原さんが書けばそれでみんな幸せなのでは?
  • "Getting Started with Bluetooth Low Energy" の翻訳本が出ればそれで幸せなのでは?
  • そもそも既刊の『iOS 5 プログラミングブック』『iPhoneアプリ開発 エキスパートガイド iOS 6 対応』『上を目指すプログラマーのためのiPhoneアプリ開発テクニック iOS 7 編』で結構網羅されてるのでは?


上を目指すプログラマーのためのiPhoneアプリ開発テクニック iOS 7編
加藤 寛人 西方 夏子 藤川 宏之 鈴木 晃 高丘 知央
インプレスジャパン
売り上げランキング: 1,885

iPhoneアプリ開発エキスパートガイド iOS 6対応
加藤 寛人 藤川 宏之 高丘 知央 西方 夏子 吉田 悠一 関川 雄介
インプレスジャパン
売り上げランキング: 16,950

iOS5プログラミングブック
インプレスジャパン (2012-08-23)
売り上げランキング: 25,214

・・・というあたりで相当悶々としてました。いや何しろ自分のBLE関連知識の多くは 上原さんのブログ やFacebookグループで勉強させてもらったものだし。。


で、そんな煮え切らない気持ちのままあれよあれよと半年ほど経ってしまったころ、編集の方が共著者として松村さんにお話を通してきてくれて、ある日のミーティングで一気に自分の中でストンと「自分が書くべき理由」が腹落ちしました。


自分の1年ほど前を振り返ってみると、連載ドリブンで勉強しよう、と『iOSアプリと連携させて使えるデバイスたち:連載|gihyo.jp … 技術評論社』という連載をgihyoさんに企画提案し、BLEとか意識せずiOSと繋がるガジェットという理由だけで購入した konashi を第1回に取り上げたところから始まって、これまたBLEとか意識せず関わった iBeacon 案件があって、これまたBLEとか意識せず関わったとある新規ウェアラブルデバイス案件がありそこからBluetoothについて勉強し始め、・・・WHILLの話が来て、Moffの話が来て・・・


まぁなんというか、自分は BLE とか関係なく、ただただ「iOSと連携する外部デバイスの分野って何か楽しそう」ってところから始まって、つくりたい欲求ドリブンで調べているうちに必然的に BLE について知識がついてきたのであって、そういう切り口/順序で書くのであれば、他の関連書籍がありながらも僕が書く余地もありそうだなと。


あと、松村さんは konashi というハードをつくった人で、僕も WHILL, Moff, SmartDrive, 真鍋さんとのピリピリデバイス と多くハードウェアプロジェクトにiOSエンジニアとして実際に手を動かして関わっていて、そのあたりでも何か宿るものはあるんじゃないかと。


というわけで今は迷いなくバリバリ書いております。上原さんや小林先生やIRKitの大塚さんにも査読いただく予定です。電子版同時リリースはいろいろ大変そうですが編集の方を通してがんばって交渉していく所存です。無事出版されたらよろしくお願いいたします!


WHILL

今年の4月から週末を中心にじわじわとつくってきたアプリが、ついに10月にリリースされました!


f:id:shu223:20141017083349p:image:w600


WHILLなしでも試せます。詳細はこちら:


申請の日はWHILLの新オフィス@鶴見に泊まりこみで作業しました。


(WHILLの新オフィス@鶴見。どでかい倉庫的な建物の中にメンバーみんなで組み立てたプレハブ)


Moff

9月にKickstarter支援者向けリリース、10月一般リリース。最近はお仕事的に新展開になってきましたが書いていいか先方にまだ確認できてないのでそのお話はまた今度。


ちなみに WHILL も Moff も、トップのピコーンピコーンするアニメーションは拙作のオープンソースライブラリ "Pulsing Halo" を使用しております。


f:id:shu223:20141104132131g:image:left

f:id:shu223:20141104132209g:image:left




music for the deaf

横浜パラトリエンナーレでの、SOUL FAMILY × 真鍋大度 + 石橋素 + 照岡正樹 + 堤修一 名義での展示・ライブパフォーマンス。


f:id:shu223:20140814072957j:image:w500


経緯や当日の様子などの詳細はこちらに。


海外書籍のレビュー

iOS8-Samplerを出したおかげか、とある出版社から iOS 8 の技術書のレビュー依頼が届きました。


iOS 8 と題してるのにスクショが Xcode 5(iOS 8 は要Xcode 6)だったり、最初のサンプルが UIAlertView(iOS 8 では deprecated)だったりして前途多難な感じでしたが、ちゃんとフィードバックに書いたのできっとそのあたりは直されて良い本になっているのではないでしょうか。


そしてどうにかこうにか全7章のフィードバックを返し終えたタイミングで、出版社側の担当者より退職のお知らせ。自分がレビュアーとして記載されるかどうかは謎です。。とりあえず英語で書籍を読む練習にはなったので、良い経験にはなりました。


iOS8-Sampler

詳細はこちらに。


GitHub の Trending で 1 位になりました!


f:id:shu223:20141104141630j:image:w600


Trending の 1 位になるのは、iOS7-Sampler、AnimatedTransitionGalleryに続く3つ目です。スター数は11/4現在約2,100。


オープンソース活動で収益ゼロですが、このブログは海外にはリーチしないので、グローバルに自分のエンジニアとしてのポジションをつくっていくにはこういう投資は必要だなーと思ってある程度時間を割いてでも(=収益になる仕事を減らしてでも)やることにしています。


講演、登壇


(インタビュー)


仕事観・働き方についてとある媒体で連載する話もいただいたのですが、連載するほど体系化できてないし、そんなことよりもっと技術力を積み上げて、もっと手を動かしてプロダクトを世に出していかねば、ということで見送らせていただきました。


1〜数人日の作り切りアプリ開発数件

プロジェクト新規作成から納品まで1〜数人日ぐらいの短期案件をいくつかやらせていただきました。

  • RoadMovieみたいな、細かい動画を撮影してひとつの動画につなげて保存するアプリ、1人日
  • iBeacon で店内領域検出、Core Bluetooth で店員用アプリと通信するデモアプリ、1人日
  • 東京デザイナーズウィーク出展用のシンプルなアプリ、x人日

おわりに

正式に独立してから9ヶ月も経ち、紆余曲折・試行錯誤してきた中でフリーランスとしての働き方、今後の展望について思うところ/書きたいこともいろいろとあるのですがそのあたりも書いてると時間かかりそうなのでまたの機会に書こうと思います。


[雑記]TechCrunchハッカソン2014で入賞しました!

$
0
0

一昨日、昨日と2日間にわたって開催された『TechCrunch Tokyo Hackathon 2014』に参加し、賞をいただきました。


f:id:shu223:20141117095757j:image:w480


上位5チームが発表され、その中での順位は発表されなかったのですが、あとで聞いたところによると、上位5チーム中得票数1位(!)だったとのことです。


参加者120名(160?)の大規模ハッカソンでした。以下ざっくりレポート。


特別参加エンジニア

昨年の同ハッカソンでは"TechTalk"という枠組みで『スキルなし・実績なし 32歳窓際エンジニアがシリコンバレーで働くようになるまで』というタイトルで講演させていただいた縁もあり、TechCrunch Japan編集長の西村さんよりお声がけいただき、今回は「特別参加エンジニア」という枠で参加させていただきました。


f:id:shu223:20141117095826j:image


特別参加エンジニアといっても、あらかじめ参加表明するっていう以外に何ら特別なことはなく、普通にチームに入って最初から最後までいち参加者としてハックする、というものです。


そもそもハッカソンは大好物で、出るなら自分もガリガリ手を動かしたいので、大変ありがたいオファーでした。


ルール/審査基準

自分が参加したことのある中では珍しく、あらかじめルールや審査基準が明示されました。


(ルール)

  • 転換1分、発表時間3分
  • デモのみ
    • パワポやキーノートは使わない
    • コンセプトムービーはいらない

(審査基準)

  • イノベーション (革新性、新規性)
  • デザイン
  • 完成度

従来のハッカソンだと、しっかり動くところまでつくって、発表時のいろんなトラブルも想定して機能やバックアップ手段までつくりこんだ挙句、本番でちゃんと動いてなかったり、そもそもできてなかったりするチームが受賞したりしてモヤモヤしたこともあったので、「完成度を見ます」「デザインも見ます」「デモ中心で。かっこいいコンセプトムービーとかいりません」とかあらかじめ明言してくれるのはすごくいいなーと。


アイスブレイク

これもうまいなーと思いました。『自分が最も好きな(イノベーションの宝庫)ひみつ道具を書いてください』というテーマでスケッチブックに絵を描く、というものです。緊張をほぐすのと、なんとなく「イノベーション」というところで頭の体操をするのが狙い。


f:id:shu223:20141117095939j:image:w400


僕は「ネムケスイトール」(眠気を吸い取る銃)を書きました。おそらく30年近く前に見たっきりなので、見た目は完全にうろ覚えです。


アイデア出し/チーム決め

協賛企業のAPI説明のあと、アイデア出しタイム。使いたいAPIをひとつ選んで、アイデアを用意された紙に書きます。


で、それをテーブルの上に置いて、協賛企業の人たちも含め全員がテーブルを回り、いいなと思ったアイデアに星マークをつけていき、星マークの多いアイデアは「モテアイデア」(みんなからの評価が高くそのアイデアに人が集まりそうという意味)としてみんなの前で発表します。(チーム作成のきっかけになる&みんなのアイデアのヒントになる)


僕はエプソンの MOVERIO を使ったアイデアで星15個と21個をいただきモテアイデアとして発表させていただきましたが、


f:id:shu223:20141117100019j:image:w600


MOVERIO SDKはAndroid版のみ、ということで、サクッとそのアイデアは捨て、自分の得意技術(iOS)で役立てて、かつ自分もつくりたいアイデア、という観点でいろんな方々のアイデアを聞いてメンバー探しをしました。*1


ハックタイム

ここまでで初日のお昼ぐらいで、あとはチームでブレストしてやること決めて、翌日の発表タイムまでひたすらハック。会場は24時間開放されていて、うちのチームは翌日の朝方こんな感じになってました。



見づらいですが右端に転がってるのが僕(3人転がってます)です。結構な人数が徹夜してました。


できたもの

リコーの 360° 録画できるカメラ「THETA」をつかって議事録を自動作成するサービスをつくりました。


f:id:shu223:20141117100410j:image:w300



THETAを机の上に置いて会議をすると、あとは全自動で解析され、こんな感じでLINEのチャットを読むように議事録が閲覧できるようになります。


f:id:shu223:20141117100725g:image


THETAの全天球動画から参加者の発言を音声認識で自動抽出、同時に動画に顔認識/話者認識もかけて誰がしゃべっていてみんながどういう表情をしているかもわかる、というもの。上のgifアニメでも、実際にTHETAで撮った会議をヤラセなしで解析してるので、認識結果がそこそこ間違ってるところも逆にリアルかと。ちなみにTHETAはハッカソンとして用意されてたものではなく、チームメンバーの方が持ってきたものです。


僕はもちろん、iOSアプリを担当しました。


所感

最近は雨後の筍のように開催されているハッカソンですが、徹夜してフラフラになれる本来の語源に近いハッカソンは実はそう多くないんじゃないかと思います。「つくりたいもの考えて、つくって、発表して、リアクションをもらう」っていうものづくりの醍醐味を一晩に濃縮して体験できるハッカソンはやっぱり楽しいなーと。賞もいただけたし。発表会の雰囲気も謎の一体感があってすごくよかった。主催のみなさん、参加者のみなさん、ありがとうございました!


*1:ハッカソンをきっかけにやったことない技術に触れる、というもの意義深いと思うのですが、今回は自分が特別参加エンジニアというのもあってある程度結果を出すことを優先しました

[iOS]【WatchKit】Apple Watch アプリのつくり方 &全API解説

$
0
0

Apple Watch の SDK である『WatchKit』がリリースされてたので、さっそくさわってみました。


以下、サンプル実行方法AppleWatchアプリの実装方法(所要時間1分、プログラミング不要!全クラス解説の順に書いていきます。


f:id:shu223:20141119142039j:image:w314


※本記事は、Appleによる公開ドキュメント(ログイン不要領域にあるもの)の範囲で書いています。


サンプル実行方法

何はともあれまずはサンプル実行。


iPhone6 シミュレータとかの並びに Apple Watch とかが来るのかなと思ってたので、一瞬サンプルをどう実行してよいのか面食らいましたが、シミュレータメニューから


[Hardware] > [External Displays] 
> [Apple Watch - 38mm] または [Apple Watch - 42mm] を選択

で、Apple Watch サイズの外部ディスプレイシミュレータが起動するので、この状態で WatchKit Extension をアクティベートすると、外部ディスプレイの方にUIが表示されるようになります。


実装手順

テキストを表示するだけの超シンプルアプリを実装してみます。所要時間約1分、コード不要

1. Extensionターゲット作成

プロジェクトをつくって、 [File] > [New] > [Target] から、Apple Watch を選択(テンプレートは Watch App のみ)します。


2. UIをいじる

Interface.storyboard が生成されるので、Interface Controller Scene にとりあえずラベル(WKInterfaceLabel)でも置いてみます。


3. ビルドしてみる

サンプル実行方法と同じように、実行すると、置いたラベルが表示されます。(スクショ載せられないのがもどかしい)


全API解説

WatchKit Framework Reference を見てみるとクラスの数はなんとたったの15個。自分はもっと一大SDKが来ると思い「iOS8-Sampler」の流れで「WatchKit-Sampler」つくるつもりでいたので拍子抜けですが、せっかくなので全クラスをひと通り見てみます。


WKInterfaceObject とそのサブクラス

WKInterfaceObject というクラスが全インターフェース系クラスのベースとなっています。(ざっくりいうと UIKit でいうところの UIView みたいなものかと)


以下、そのサブクラスである UIコンポーネント系クラス全11種です。

  • WKInterfaceButton : ボタン
  • WKInterfaceDate : 日付 or 時間表示用ラベル
  • WKInterfaceGroup : 他のインターフェースオブジェクトのコンテナとなるクラス
  • WKInterfaceImage : 画像表示。アニメーションAPIも用意されている。
  • WKInterfaceLabel : ラベル
  • WKInterfaceMap : マップ
  • WKInterfaceSeparator: セパレータ
  • WKInterfaceSlider : スライダー
  • WKInterfaceSwitch : スイッチ
  • WKInterfaceTable : テーブル
  • WKInterfaceTimer : カウントダウンタイマー表示用ラベル

それぞれどんなインターフェースかは、上記の一言解説でだいたい想像つくと思いますが、ヘッダみると UIKit や MapKit の同じ位置づけのクラスとできることは結構違います(よりシンプル)。


WKInterfaceController

インターフェースのコントローラクラス、ざっくり言ってしまえば UIKit でいう UIViewController みたいな位置づけのクラス。


WKUserNotificationInterfaceController

WKInterfaceController のサブクラスで、追加されている API は以下の3つだけ。

- (instancetype)init;
- (void)didReceiveRemoteNotification:(NSDictionary *)remoteNotification withCompletion:(void(^)(WKUserNotificationInterfaceType interface)) completionHandler;
- (void)didReceiveLocalNotification:(UILocalNotification *)localNotification withCompletion:(void(^)(WKUserNotificationInterfaceType interface)) completionHandler;

リモート通知、ローカル通知を受け取ったときに呼ばれるメソッドが用意されているようです。


WKInterfaceDevice

ウォッチ側のデバイス情報を管理するクラス。APIを見ると、

+ (WKInterfaceDevice *)currentDevice;

- (void)addCachedImage:(UIImage *)image name:(NSString *)name;
- (void)addCachedImageWithData:(NSData *)imageData name:(NSString *)name;
- (void)removeCachedImageWithName:(NSString *)name;
- (void)removeAllCachedImages;

@property(nonatomic,readonly) CGRect    screenBounds;
@property(nonatomic,readonly) CGFloat   screenScale;
@property(nonatomic,readonly,strong) NSLocale *currentLocale;
@property(nonatomic,readonly,copy)  NSString *preferredContentSizeCategory;

キャッシュする画像をここから管理できたり、スクリーンサイズやスケール、言語設定の情報等を取得できるようです。


おわりに

ウォッチ側のセンサー値を取るAPIすらなく、実処理はiOSアプリ側に持たせて Watch側はシンプルに表示するだけっていう何ともシンプルなフレームワーク。。これでどんな新しい体験が生み出せるのか正直まだイメージできてませんが、、、WatchKit のお仕事お待ちしております!!!!




[雑記][音声処理][電子工作][iOS][IoT]新しい楽器をつくるハッカソン「Play-a-thon」に参加してきました

$
0
0

つい10日ほど前に TechCrunch ハッカソンに参加した件について書いたばかりですが、実は今月の6(木)、7(金)、21(金)、24(月)と何と4日間、しかも平日(!)*1 という日程で、「新しい楽器をつくる」というコンセプトのハッカソン、その名も「Play-a-thon」に参加してきました。


参加のいきさつ

10月のある日、珍しく IAMAS の小林先生から Facebook Message が届き「これは何か面白い仕事の予感・・・!」と思って読んでみるとこのPlay-a-thonへのお誘いでした。


すごーく興味をそそられたものの、

  • 日単位で時間(と技術)を切り売りしているフリーランスエンジニアという立場上、n日の予定を入れると n × {日単価} の出費と実質的に同等
  • 当時既に同じ11月に開催されるTechCrunchハッカソンへの特別参加エンジニアとしての参加も決定していた。1ヶ月に合計6日間ハッカソン。。
  • 執筆含め既に予定がいっぱいいっぱいだった

という事情があり一瞬お断りしようと思ったのですが、「平日4日間拘束」という妙に高い参加ハードルが逆にコアな人たちを集めそうでおもしろそうという期待と、小林先生直々の勧誘なのでできれば乗っかりたいという気持ちとで、気付くとPeatixでチケットお買い上げしていたのでした。


内容

Engadget さん主催ということで、詳しいことは近々アップされるであろうレポート記事をご覧いただくとして、ざっくり書くと

  • 11/6:工場見学・懇親
  • 11/7:アイデア出し、チーム作り、プロトタイピング(廃材で工作)
  • 11/21:制作
  • 11/24:Engadget Fesにて発表(つくった楽器でライブ演奏!)

こんな日程でした。


つくったもの

「食べられる楽器」というコンセプトで、日本全国どこでも10円で手に入る「うまい棒」を使った楽器をつくりました。


f:id:shu223:20141126093948j:image:w400


うまい棒+トロンボーンで『ウマイボーン』と呼びます。マウスピース部分とスライド部分がうまい棒になっていて、トロンボーンと同様スライドうまい棒を上下に動かすことで音程が変わります


Umaibone Demo1

(ライブ前のお披露目会にてチラッと音出し、の様子)


Umaibone LIVE 1

(ライブ冒頭の独演。実際にうまい棒を操作して生演奏してます)


しくみ

しくみを先に読んでしまうとあまり楽しくない(しくみ自体に発明感はない)ので、あえて控えておこうと思います。


が、ひとつだけ書いておきますと、ユカイ工学さんの「Konashi」を使用しております。


konashiはひさびさに触ったのでこちらの(以前自分が書いた)記事を参考に思い出しつつ実装しました。


ちなみに前回konashiを触ったのは8月ぐらいのこのお仕事でした。


余談ですが、ライブ演奏の前日ぐらいに Konashi 2 が発表され、通信機能が強化されつつ安くなった、ということで Maker Faire Tokyo に行った際にユカイさんのブースで直接買おうと思ったのですが発売は12月でした。。orz


(konashi 2 の変更点)

  • PIOのピン数の変更(8->6)
  • DAC(アナログ出力)未対応
  • UARTの対応baudrateを追加
  • UARTで複数バイトを一度に送受信を可能に
  • I2Cで一度に送受信できるバイト数を、20から16に変更
  • BLEのService,CharacteristicのUUIDを変更
  • PWMを出せるピンがPIO0-2の3本のみに変更
  • PWM波形の仕様変更
  • OTAファームウェアアップデートに対応

ちなみに宣伝的な余談が続いて恐縮ですが、初代konashi開発者の松村礼央さんとiOS×BLEな書籍を執筆中ですのでそちらも出たらよろしくお願いします。


変遷

Play-a-thon日程に沿って「ウマイボーン」の進化の過程を記しておきます。


11/7 廃材でのハードウェアスケッチ

f:id:shu223:20141126034502j:image:w360


発泡スチロールを円筒形に削り、ガムテープを巻きつけたもの(うまい棒のつもり*2)と、吹き口としての紙コップ、あとLEDがピカピカ光るみたいなイメージで正体不明の赤い半球をつけたもの。Arduinoはぶら下がってるだけ


11/21 プロトタイプ

f:id:shu223:20141126034557j:image:w600


謎のドアノブ(持ち手のつもり)、測距センサと反射板(紙に白いテープを貼ったもの)、相変わらず発泡スチロールの胴体。うまい棒が文字通り取ってつけてある


一応トロンボーン的にうまい棒スライドで音程を変えられる(こともある)。


11/24 初代完成

f:id:shu223:20141126094141j:image:w300


3Dプリンタで出力された筐体に(konashi以外の)回路が収まり、うまい棒を使った「食べられる楽器」としての体裁がだいぶ整った。

  • うまい棒スライドで音程が連続的に変化
  • 4オクターブの範囲で音域を切り替え可能
  • 楽器の音色切り替え可能(チューバ、トロンボーン、トランペット、オーボエ)
  • 加速度センサによるサンプラー機能(ライブ演出用)
  • マウスピースをかじると発動するスイッチ

といった機能を搭載。


ライブ当日

Umaibone LIVE2

(真ん中のメガネかけてる吉田氏のウマイボーンだけ本物で、実際に生演奏してます)


(フル動画は準備中です)


クレジット

  • デバイス&ウマイボーン演奏:Takatoshi Yoshida(量子物理学専攻の東大生)
  • 作曲&ライブ演出:川瀬浩介(プロの作曲家)
  • ロゴ、Tシャツ、アプリアイコンデザイン:Hisami Takezawa(デザイナー)
  • 筐体制作:Mitsuhiro Hirano(チームラボで日々デバイスつくってる方)
  • プログラム:堤

f:id:shu223:20141126040511j:image:w500

(左から、Yoshidaさん、堤、川瀬さん、Takezawaさん。Hiranoさんはこのときお仕事で欠席。。)


ウマイダーQ(Umaider Quintet)*3のFacebookページ:


主催のEngadgetさん、小林先生、YAMAHAのみなさま、参加者のみなさま、チームのみなさん、どうもありがとうございました!!!!


*1:ただし最終日だけ祝日

*2:会場が山奥だったので買えなかった

*3:当初の案はうまい棒+リコーダーだったので、チーム名に「ウマイダー」と付いています

[雑記]Yahoo! JAPAN インターネット クリエイティブアワード 2014で「しゃべる名刺」がグランプリをいただきました!!!!

$
0
0

昨日開催されたYahooさんのクリエイティブアワード贈賞式にて、なんと僕の個人名刺「しゃべる名刺」がグランプリをいただいてしまいました!


f:id:shu223:20141127080832j:image:w600


嬉しくてこんな記事書いてますが、僕は単に敬愛するねじさんに名刺制作を依頼した、というだけで、デザインはもちろんのこと、「しゃべる名刺」というアイデア、しゃべる内容とか含め、全部ねじさんの創造物です。アプリの実装は僕ですが、ねじさんに指示されるがままにつくっただけ。(というか、アプリ開発者の方々にはおわかりかと思いますが、「特定の箇所を押すと声を発する」というコードはHello World級の簡単さですらあります。)サイトはのびー(連名の藤澤 伸)作です。


発注の経緯は当時のブログにも書いてあります。


僕が何かクリエイティビティに貢献したとすると、僕がiOSに特化したエンジニアである、という点はあるかもしれません。器用でオールマイティーでフルスタックな方の名刺だと、「iPhoneに載せると声で自己紹介してくれるんですよー」といってもその表現の意味が半減したでしょうから。。


「しゃべる名刺」とは?

動画を見ていただくのがいちばんわかりやすいかと。



「しゃべる名刺」の効果

ねじさんに個人的に伝えたことはあるのですが、この名刺、僕の個人名刺としてまじで絶大な効果を発揮してくれています。あまり書く機会もないので、せっかくなのでここに書いておきたいと思います。


コミュニケーション下手をカバーしてくれる

まず、僕は日々黙々とプログラムを書くのが仕事なので、ご多分に漏れず、あんまり初対面の人とすぐに打ち解けたり、みたいなことは苦手です。で、そこでこの名刺がいい感じにアイスブレイクになります。


「このデジタルの時代に紙の名刺交換なんてナンセンスだ!」なんて声もありますが、僕はこの名刺でコミュニケーションの第一歩をだいぶ助けられてるので、名刺を家に忘れてしまったときなどは初対面の人と会うのが心もとないぐらいです。


あと、日本語しかしゃべりませんが、外国の方にもけっこうウケます。「名刺なんて出すの日本人だけだよねー」というムードがありますが、僕は海外にいったときもよくこの名刺にお世話になってます。「どんなセンサーが入ってるんだ?」みたいにまじまじと名刺を見られることもあります。


多くの名刺に埋もれてもOK

懇親会とかカンファレンスとかで多くの人に会って家に帰って名刺を整理してると、誰が誰だかわからなくなるのが常だと思いますが、僕の名刺はアイコンサイズの穴が開いてるので、多くの名刺に埋もれても、少なくとも「この人はiOSエンジニアだったな」ということぐらいは思い出してもらえるのかなと。


自分がリーチできない層にリーチする

僕のメディアたるこのブログは基本的にiOSエンジニアの方々にしかリーチしないのですが、この名刺のおかげで、デザイナーや企画の方々にも知っていただけたり、つながりができたりすることがよくあります。これは名刺にクリエイティブそのものによるメリットというより、ねじさんのデザイナー・企画者としての知名度によるところも大きいですが。。


フリーランスエンジニア堤について

アワード受賞経由で初めてこのブログに行き着いた方も多いと思うので、ちょっと宣伝的なことも書いておこうと思います。


直近のお仕事のまとめ。最近はWHILL, MoffなどBLEで外部デバイスと連携するiOSアプリを中心に手がけています。


GitHubにいろいろとソースコードを置いています。Trendingで1位、つまりオープンソース世界一になった(といっても過言ではない)リポジトリを3つ保有しています。


経歴等(LinkeInのプロフィール)



こんな素晴らしい賞をありがとうございました!!今後共フリーランスのiOSエンジニア堤をよろしくお願い致します!!!!


f:id:shu223:20141127081022j:image:w600

[BLE][iOS]Core Bluetooth トラブルシューティング

$
0
0

iOSでBLEを利用するアプリを開発していると、「スキャンで見つからない」「つながらない」といった場面はよく出てきますし、相手が新規開発デバイスだとそっちを疑いたくなることもあるわけですが、けっこうiOS側での「あるある」な実装ミスや勘違いというのが多くあります。


そんなよくあるトラブル、その解決のためのチェックポイント等をまとめました。


トラブル1: スキャンに失敗する

→ スキャンの直前に CBCentralManager を初期化していないか?

たとえば「1回目のスキャンに失敗するけど、2回目ではたいていうまく繋がる」という場合には、CBCentralManager の初期化タイミングが遅く、スキャンを開始するタイミングでまだ `CBCentralManagerStatePoweredOn` になってない、という可能性があります。


この実装ミスは、再試行ではうまくいくだけに、「何かハードか電波の調子悪いのかなー」ぐらいに思い過ごしがちなので要注意です。1発でバシッと繋がるようになるのはユーザー体験の改善効果としても大きいと思うし、修正も簡単なので、ぜひ今一度ご確認を。


→ サービスを指定している場合、そのサービスをペリフェラル側でアドバタイズしているか?

セントラル側で `scanForPeripheralsWithServices:options:` の第1引数にサービスのリストを渡している場合に、ペリフェラル側でそのサービスを提供はしていてもアドバタイズメントデータに入れていない と、スキャン時に発見できないことになります。


たとえばを `scanForPeripheralsWithServices:options:` の第1引数に `nil` を渡してみるとそのペリフェラルが見つかるようになる、といった場合はこのケースに当てはまっている可能性があります。


トラブル2: 接続に失敗する

→ 発見したCBPeripheral の参照を保持しているか?

Core Bluetooth に慣れていないと忘れがちなのが、スキャンにより発見した CBPeripheral オブジェクトを、strong のプロパティなり配列に格納するなりして参照を保持しないと解放されてしまう可能性がある、という点です。


`centralManager:didDisconnectPeripheral:error:` の引数に入ってくる CBPeripheral オブジェクトは、必要であれば(接続したりするのであれば)きちんとその参照を保持する必要があります。


これを怠ると、`connectPeripheral:options:` をコールしても失敗するとか、デリゲートメソッドが呼ばれない、といった事態を引き起こします。


トラブル3: サービスまたはキャラクタリスティックが見つからない

→ UUIDが間違っていないか?

`discoverServices:` , `discoverCharacteristics:forService:` で検索対象のサービス/キャラクタリスティックの CBUUID オブジェクト(の配列)を渡しているのであれば、いったん確認のため `nil` を渡してみます。


これで見つかるようなら、渡してるUUIDが間違っている、と考えられます。


→ ペリフェラル側でGATTを変更したのではないか?

iOSアプリと連携する新規ハードウェア開発をしているとものすごくあるあるで、ハマる人が多いのですが、開発途中でペリフェラル側(外部デバイス)で GATT の内容を変更すると、iPhone の Settings から Bluetooth を Off/On しないと変更が反映されない というのがあります。


このことを知らないと、たとえばキャラクタリスティックの `value` が取れず、

  • BLE の接続状態を疑う
  • Central / Peripheral 間での UUID の食い違いを疑う
  • etc...

と、無駄なデバッグ作業をしてしまいかねません。


で、とりいそぎ上にも書いた通り iPhone の off/on で GATT の変更を反映することはできるのですが、正しい解決方法をAppleの中の人に聞いてきたので、下記記事を併せてご参照ください。


トラブル4: Writeで失敗する

→ CBCharacteristicWriteType を間違って指定していないか?

`writeValue:forCharacteristic:type:` の第3引数に指定する CBCharacteristicWriteType (レスポンスありの場合は `CBCharacteristicWriteWithResponse`、なしの場合は `CBCharacteristicWriteWithoutResponse`) は、GATTの当該キャラクタリスティックのプロパティ設定と合ってないとエラーになります。


アプリ側では「確認のためレスポンス欲しいなー」ってな動機で WriteWithResponse を指定したくなる場合もあるかもしれませんが、GATT側では WriteWithoutResponse となっていると失敗します。


トラブル5: バックグラウンドでのスキャンが動作しない

→ サービスを指定しているか?

バックグラウンドでのスキャン時は、`scanForPeripheralsWithServices:options:` の第1引数にスキャン対象とするサービスを1つ以上渡す必要があります。

> they must explicitly scan for one or more services by specifying them in the serviceUUIDs parameter.


→ もう少し待ってみる

フォアグラウンドのときと比べ、バックグラウンドでのスキャンは間隔が長くなります。


Appleのドキュメントでは具体的な数値を発見できなかったのですが、わふうさんの記事によると12分に1回とか。


おわりに

以上、日々の開発の中で書きためていたトラブルシューティングでした。他にもあれば追記していきます。


[BLE][iOS]ANCSでiOSの電話着信やメール受信の通知を外部デバイスから取得する

$
0
0

ANCS は「Apple Notification Center Service」の略で、電話着信やメール受信等、iOSで発生するさまざまな種類の通知に、BLEで繋がっている外部デバイスからアクセスするためのサービスです。


iOSアプリに携わるエンジニアとしてはリモート通知(プッシュ通知)の APNS (Apple Push Notification Service) と混同しそうになる略称ですが、もちろん別モノです。


IoTとかウェアラブル的な文脈では大抵のケースでiOSデバイスがセントラルになり、外部デバイスがペリフェラルとなりますが、ANCSはiOSデバイスがサービス提供側となるため、その立場が逆転し、iOSデバイスがペリフェラル、外部デバイスがセントラルとなります。


f:id:shu223:20141205065442p:image:w300




※本記事はBLEアドベントカレンダー5日目の記事です。



用語について

Appleが提供しているドキュメント「Apple Notification Center Service (ANCS) Specification」では、サービス提供側(つまりiOSデバイス)を NP (Notification Provider)、サービスを受ける側(外部デバイス)を NC (Notification Consumer) と呼んでいるので、本記事でも以降そのように表現します。


また、同ドキュメントでは、iOSにおけるPush NotificationやLocal Notificationといった通知と、GATTにおけるNotificationを呼び分けるため、"iOS Notification", "GATT Notification" という表現が使用されています。本記事内でも、これらの区別のため「iOS通知」「GATT通知」という表現を使用します。


ANCS の GATT

ANCSサービスのUUIDは次のように定義されています。

7905F431-B5CE-4E99-A40F-4B1E122D00D0

そして、ANCSサービスは、以下のキャラクタリスティックを持っています。

Characteristic UUID Properties
Notification Source 9FBF120D-6301-42D9-8C58-25E699A21DBD notifiable
Control Point 69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9 writeable with response
Data Source 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB notifiable

Notification Source は、

  • NPでのiOS通知の到着
  • NPでのiOS通知の変更
  • NPでのiOS通知の削除

をNCに知らせるためのキャラクタリスティックです。

また Control Point は NC が NP に iOS通知のより詳細な情報を要求するための Write キャラクタリスティックで、Control Point への書き込みが成功すると、NP は Data Source キャラクタリスティックでのGATT通知によりリクエストに応答します。


これらのサービス/キャラクタリスティックでは、別のiOSデバイスからセントラルとして接続しても見つからないようになっています。ANCSが提供されるようになったiOS7より前のiOSデバイス、あるいはそれ以外のMac等のデバイスからは見つけることができます。



実装サンプル

以下、Notification Source キャラクタリスティックを介して、iOS通知の到着や変更をNC側で受け取る実装方法について説明します。


NPの実装

NC側からペリフェラル名で発見できるように、`CBAdvertisementDataLocalNameKey` に何らかのデバイス名を指定してアドバタイズ開始しておきます。(一般的なペリフェラルマネージャの実装なのでコードは省略)


NCの実装

上述した通りiOSデバイスはNCになれないため、ここでは Mac OS X のアプリとして実装します。

なお、スキャン、接続、サービス/キャラクタリスティックの探索まではセントラルとしては通例通りの処理なので説明を省略します。


Notification Source をサブスクライブする

Notification Source キャラクタリスティックの値の更新通知を有効にします。

- (void)                      peripheral:(CBPeripheral *)peripheral
    didDiscoverCharacteristicsForService:(CBService *)service
                                   error:(NSError *)error
{
    CBUUID *notificationSourceUuid = [CBUUID UUIDWithString:@"9FBF120D-6301-42D9-8C58-25E699A21DBD"];
    
    for (CBCharacteristic *aCharacteristic in service.characteristics) {
        
        if ([aCharacteristic.UUID isEqualTo:notificationSourceUuid]) {

            self.notificationSourceCharacteristic = aCharacteristic;
            
            // Notification Source の subscribeを開始する
            [peripheral setNotifyValue:YES
                     forCharacteristic:aCharacteristic];
        }
    }
}

Notification Source の値を読む

Notification Source キャラクタリスティックの値は、次のような8バイトで構成されています。


f:id:shu223:20141205065849p:image:w588


本サンプルでは、どのようなiOS通知があったのかを最低限判別できるよう、「EventID」「CategoryID」の2つを読み取ることにします。


EventIDはiOS通知が「新規」「変更」「削除」のどれなのかを示す値で、次のように定義されています。

EventIDNotificationAdded 0
EventIDNotificationModified 1
EventIDNotificationRemoved 2
Reserved EventID values 3-255

CategoryIDはiOS通知の種類を示す値で、次のように定義されています。

CategoryIDOther 0
CategoryIDIncomingCall 1
CategoryIDMissedCall 2
CategoryIDVoicemail 3
CategoryIDSocial 4
CategoryIDSchedule 5
CategoryIDEmail 6
CategoryIDNews 7
CategoryIDHealthAndFitness 8
CategoryIDBusinessAndFinance 9
CategoryIDLocation 10
CategoryIDEntertainment 11
Reserved CategoryID values 12–255

Notification Source キャラクタリスティックの値に変更があると、すなわちNP側で電話着信などのiOS通知が新規で発生した/変更された、等のイベントが発生すると、サブスクライブしているNCに対してGATT通知が送られます。


このタイミングでキャラクタリスティックからEventIDとCategoryIDを読み取り、ログ出力するコードは次のようになります。

- (void)                 peripheral:(CBPeripheral *)peripheral
    didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
                              error:(NSError *)error
{
    NSLog(@"%@", characteristic.value);

    // 8バイト取り出す
    unsigned char bytes[8];
    [characteristic.value getBytes:bytes length:8];    

    // Event ID
    unsigned char eventId = bytes[0];
    switch (eventId) {
        case 0:
            NSLog(@"Notification Added");
            break;
        case 1:
            NSLog(@"Notification Modified");
            break;
        case 2:
            NSLog(@"Notification Removed");
            break;
        default:
            // reserved
            break;
    }

    unsigned char categoryId = bytes[2];
    switch (categoryId) {
        case 0:
            // Other
            break;
        case 1:
            NSLog(@"Incoming Call");
            break;
        case 2:
            NSLog(@"Missed Call");
            break;
        case 3:
            NSLog(@"Voice Mail");
            break;
        case 4:
            NSLog(@"Social");
            break;
        case 5:
            NSLog(@"Schedule");
            break;
        case 6:
            NSLog(@"Email");
            break;
        case 7:
            NSLog(@"News");
            break;
        case 8:
            NSLog(@"Health and Fitness");
            break;
        case 9:
            NSLog(@"Business and Finance");
            break;
        case 10:
            NSLog(@"Location");
            break;
        case 11:
            NSLog(@"Entertainment");
            break;
        default:
            // Reserved
            break;
    }
}

実行結果

次のようにログ出力されました。(見やすいよう各通知のログを1行にまとめています)

<001d0201 00000000>, Notification Added, Missed Call
<001d0202 01000000>, Notification Added, Missed Call
<001d0203 02000000>, Notification Added, Missed Call
<00150601 03000000>, Notification Added, Email
<00150602 04000000>, Notification Added, Email
<00100603 05000000>, Notification Added, Email
<00100604 06000000>, Notification Added, Email
<00150605 07000000>, Notification Added, Email
<00150401 08000000>, Notification Added, Social
<00150b01 09000000>, Notification Added, Entertainment
<00150b02 0a000000>, Notification Added, Entertainment
<00150b03 0b000000>, Notification Added, Entertainment
<00150a01 0c000000>, Notification Added, Location
<00150801 0d000000>, Notification Added, Health and Fitness
<00150802 0e000000>, Notification Added, Health and Fitness
<00150901 0f000000>, Notification Added, Business and Finance
<00150001 10000000>, Notification Added
<00150002 11000000>, Notification Added
<00150003 12000000>, Notification Added
<00150402 13000000>, Notification Added, Social

電話着信やメール受信、SNSのiOS通知の発生や削除がNC側(ここではMacアプリ)で検知できていることがわかります。


iOSでの通知設定について

PebbleのSupport Centerのページによると、iOS側の通知をどこまで許可することでANCSによりNCに通知されるかがアプリによって違うようです。

The following apps need nothing more than "Allow Notifications" for their notifications to appear on Pebble.

  • iOS 7 email
  • SMS and iMessages
  • Calendar
  • CalenMob
  • BBM

At least one of the alert styles (banners, alerts, badge app icon, or alert sound) must be enabled for the following apps, in addition to having "Allow Notifications" on.

  • Gmail
  • Hangouts
  • WhatsApp
  • Facebook
  • Facebook Messenger
  • Snapchat

The following apps require that the banners alert style specifically be chosen in order to deliver notifications to Pebble:

  • Twitter

# 同ページでは "Here is what we have discovered so far:", "If you are aware of any other apps which require a special set up, please contact our Support Team" 等と表現されていることから、どういうルールでこれらが決まるのかははっきりしていないようです。


参考記事


[BLE][iOS][iBeacon][Android]iBeacon と BLE

$
0
0

昨年末〜今年初めにかけて一世を風靡した iBeacon ですが、なんというか、本来期待されるべき方向ではない方向で期待され、ガッカリされることが多いような印象を受けます。

  • 「コンテンツを内部に保持して直接配信することはできない」
  • 「双方向通信はできない」*1
  • 「距離はあてにならない」
  • 「検出できたりできなかったりする」
  • 「ビーコンのバッテリーが意外ともたない」

などなどなどなど。


で、個人的にはこういうガッカリは、「BLEをどのように利用することでiBeaconという領域観測サービスが実現されているか」を理解していれば、そもそもそういう期待は方向性違いであると気付けたり、何らかの改善指針を持てたりする部分があるなぁと感じてまして、本記事では「iBeacon と BLE」にフォーカスして書きたいと思います。


なお、本記事は 「Bluetooth Low Energy Advent Calendar 2014 - Qiita」の8日目の記事となります。


ビーコン=アドバタイズ専用デバイス

iBeaconにおける「ビーコン」というのは、BLEの観点から簡単にいうと、「アドバタイズに特化したペリフェラル」です。*2


通常のBLEペリフェラルデバイスの場合は、アドバタイズしてセントラルから見つけてもらい、そのあと接続し、データのやりとりを行うわけですが、ビーコンはそれらの機能をすっ飛ばして自分の存在を知らせる機能(アドバタイズ)だけに特化することで、シンプル、低コスト、低消費電力 に振り切っている、というのが最大のポイントです。*3


BLEガジェットは安いものでも5000円以上はする中で、ビーコンモジュールは安いものだと1台200円ほどだったり、寿命が数年間と謳われていたりするのは、このためです。


ちなみに、ビーコン界ではもっともよく知られている(と僕は思っている)、「Estimote」のビーコンはシリコンケースががっちり糊付けされていて、ケースをカッター等で切らないと(つまり破壊しないと)電池交換できないようになっていて、


f:id:shu223:20141209000558j:image

estimoteが届いたので分解してみた - yumulog | 社会人博士の日記 より)


もちろんスイッチ等でon/offできるわけでもないので、これが届いた当初は「まじで!?」「回路を見られたくないのかな?」とか思ったのですが、今思えば、

  • シリコンケース糊付け・・・安価な防水効果。設置して放置しておける
  • 電池交換ができない・・・ビーコンなので使い捨てでOK

と上述したiBeaconの思想から考えると、大いに納得がいきます。


アドバタイズ周期・電波強度とバッテリー消費

上述した通り、ビーコンはアドバタイズに(ほぼ)特化したデバイスであり、アドバタイズはざっくり言うと電波を発して自身の存在を知らせる機能なので、バッテリー寿命について「アドバタイズ周期」「電波強度」からシンプルに考えられることになります。*4


アドバタイズ周期を上げれば *5 電波を発する頻度が多くなるのでバッテリー消費は大きくなりますし、電波強度ももちろん強くすればより早くバッテリーを消費します。


逆に、アドバタイズ周期を下げればビーコンの発見されやすさが下がりますし *6、電波強度を下げれば領域観測の範囲が狭まります。


多くのビーコンモジュールはこれら「アドバタイズ周期」「電波強度」を変更できるようになっているので、適用しようとしているサービスに応じてバッテリー消費とのトレードオフを考慮しながら適切に設定することが肝要です。


またビーコンモジュールを販売している各社のページには、(バッテリーが)「約1年持ちます」「2年持ちます」等と書かれている場合がありますが、アドバタイズ周期や電波強度をどのように設定した上での話なのか、に注意する必要があります。


iBeaconのアドバタイズメントパケット

iBeaconのビーコン側の仕様は一般には公開されていない(要iBeaconライセンス取得)のですが、上述の通り要はBLEのペリフェラルなので、容易にそのアドバタイズメントパケットを観測できます。


そのフォーマットに沿ってパケットを構成してアドバタイズを行えば、MacでもAndroidでもBLE113等の開発キットでもiBeaconのビーコンモジュールとしてふるまえますし、そのルールに従ってビーコンのアドバタイズメントパケットを解析すれば、iOSデバイス以外からもそのビーコンのUUIDやmajor,minorを取得可能(すなわち、領域観測と同じような挙動を実現可能)です。


アドバタイズメントパケットのフォーマット

BLEのアドバタイズメントパケットの各バイトがどのように構成されているかは、Bluetooth SIG によるドキュメント「Bluetooth Specification」 にある下記の図がわかりやすいです。


f:id:shu223:20141209000805p:image:w582


ここでは詳細説明を省略しますが、AD Type が `FF` の場合、その AD Structure は "Manufactureer Specific Data" であることを意味し、Manufactureer が自由にその AD Structure の長さと内容を決めることができます


Apple はこの AD Type を利用し、Apple は iBeacon のアドバタイズメントパケットのフォーマットを定義しているわけです。


iBeaconのアドバタイズメントパケットの詳細

iBeacon のアドバタイズメントパケットのうち、iBeacon 特有の部分、すなわち AD Type が `FF` である AD Structure だけ抜き出すと、そのパケットフォーマットは次のようになっています。

1A # AD Structure の長さ(bytes)
FF # AD type
4C 00 # Company identifier code (0x004C は Apple を示す)
02 # Byte 0 of iBeacon advertisement indicator
15 # Byte 1 of iBeacon advertisement indicator
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX # iBeacon の proximity uuid
XX XX # major 
XX XX # minor 
XX # Tx Power

(参考:http://stackoverflow.com/questions/18906988/what-is-the-ibeacon-bluetooth-profile


`XX` とした部分以外のバイト値はiBeaconにおいて固定値です。


Bluetooth Explorer 等のアプリケーションで iBeacon のアドバタイズメントパケットを監視してみると、上記のフォーマットに則っていることが確認できます。


f:id:shu223:20141209002358j:image:w582


Core Bluetooth に対する iBeacon のアドバンテージ

ここまでで、iBeaconにおける「ビーコン」はBLEにおけるペリフェラルのサブセット仕様である、ということを書いてきました。BLEのペリフェラルになれるあらゆるBLEモジュールは、「ビーコン」になれます。


そして、ビーコン自体がただのアドバタイズだけを行うペリフェラルだとすると、セントラル側であるiOSデバイスからは当然 Core Location のビーコン領域観測の機能を使用しなくても、Core Bluetooth を使えば問題なく検出できる、ということになります。むしろ、Core Bluetooth を使用した方が、ペリフェラルのより詳細な情報を得られるというメリットさえあります。


しかし、Core Bluetooth での実装では実現できない、Core Location の領域観測サービスならではのアドバンテージ もあります。


ロック画面表示をトリガとするビーコン検出

ビーコン自体はただのペリフェラルなので、Core Bluetooth で検出できるわけですが、バックグラウンドモードにおける Core Bluetooth のスキャンにはいくつかの制限があり、その一つにスキャン間隔が長くなる、というものがあります。


これが、Core Location の領域観測サービスを使用してビーコン領域を検出する場合、ユーザーがiPhoneのロック画面を表示した瞬間にだけビーコン領域検出 を行ってくれるようになります。


ユーザビリティの観点からも、バッテリー消費の観点からも、非常にメリットの大きい機能です。


参考書籍:

iBeacon ハンドブック
iBeacon ハンドブック
posted with amazlet at 14.12.08
(2014-03-25)
売り上げランキング: 11,647

ロック画面へのアプリアイコン表示

iOS 8 より、あるアプリで観測している領域が検出された場合に、そのアプリのアイコンがロック画面の左下に表示されるようになりました。


f:id:shu223:20141209000735j:image


この状態でアイコンをドラッグして上方向にスライドすると、そのアプリが起動します。


Core Bluetooth を利用してバックグラウンドでペリフェラルを検出しても、iOSのロック画面に直接の動線を置く等ということはできないので、これもまたiBeaconならではの大きなアドバンテージといえます。


おわりに

iBeaconという領域観測サービスを実現するために、BLEがどのように用いられているのか、について書きました。


割り切った仕様なのでできないことも多いのは事実ですが、「安いので大量にバラまける」「低消費電力なので小型な電池で長持ちする+構造がシンプルなので簡単に防水にできる+安い = 放置して使い捨てにできる」などなど、iBeaconならではの特長も多くあります。


さらに、アドバタイズや電波のことを理解してサービス設計やチューニングを行えば、つながりやすさやバッテリーの持ちに関しても改善が見込めます。


これらiBeaconの方式や特性をうまく活かし、より有益なiBeaconサービスに繋げていきましょう!


関連記事:


*1:UUID・major・minor等のアドバタイズメントパケットの内容を動的に変更することでiBeaconと双方向通信的なものを実現することは可能ですが、やはり「そもそもBLEのサブセット仕様である」ということを考えるとそうした力技で双方向通信を行うことに意味はないかと。

*2:セントラルがスキャンで発見できるよう、ペリフェラルデバイスが「ここにいるよー」と電波を発することを「アドバタイズ」(日本語でいうと広告)と呼びます

*3:そもそもBLEにおけるセントラル・ペリフェラルという概念には、「高度な機能はセントラル側に持たせ、ペリフェラル側のデバイスはシンプル・低コスト・低消費電力に済むように」という思想が込められているのですが、さらにそれをシンプルにしたものがiBeaconです

*4:UUIDの更新やファーム更新等、ビーコンによってはアドバタイズ以外の要因でバッテリーを消費します

*5:BLEの規格ではアドバタイズ周期は最小 20[ms] 〜 最大 10.24[s]の範囲で 0.625[ms]の整数倍、と定められています

*6:たとえば、アドバタイズ周期を10.24sにして、アドバタイズが終わった直後に領域観測側がスキャンを行ったとすると、約10.24sビーコンの発見が遅れることになります

Viewing all 317 articles
Browse latest View live