2016年5月23日月曜日

Project Tango - Google I/O 2016

What's New with Project Tango

デモとビデオがたくさんあり、Tango の Keynote っぽいセッション。恐竜のアプリ楽しそう。
  • Standard Android development and publishing
  • C/C++, Java, Unity, Unreal
  • Detect if Tango features are available on device
Googel Store で $512.00 で新しい Project Tango タブレット開発キットが買えるようになった
https://store.google.com/product/project_tango_tablet_development_kit
(*日本では買えません)

追記:わざわざセッションで言及してたので new かと勘違いしてしまいました。new じゃなかった。残念...

Consumer 向けの Tango Phone を Lenovo と開発中。2016年の後半に出る予定。詳しくは 2016年6月9日の Lenovo Tech World で発表される。
http://www.lenovo.com/registerfortechworld/
http://www.lenovo.com/projecttango/


Introducing Project Tango Area Learning



Project Tango の主な3技術として Motion Tracking と Depth Perception と Area Learning がある。 Motion Tracking によってデバイスが最初のいちからどれだけ動いたかがわかる。 Tango 用の Tablet と Phone には特別な3Dカメラがついており、Tango はこのカメラを使って実世界の 3D geometry を検出できる。

Area Learning は Tango デバイスに記憶を与える。 Tango には広域カメラが付いていて、実世界の特徴のあるものをランドマークとして覚える。ランドマークの位置がカメラ内で移動したらデバイスが移動したとして Motion Tracking している。 目を閉じて見た目の全然異なる所に移動すると前にいた場所がわからなくなるのと同じように、これまで Tango には記憶がなかったので Motion Tracking を開始するたびに同じ状況になっていた。 Area Learning ではランドマークがどこに見えたかと、ランドマークの見た目についての mathmatical description の2つを記憶する。

AR でバーチャル椅子をダイニングに配置するとする。Motion Tracking だけだと、椅子の位置が徐々にずれてきてしまう。Area Learning を使うとこの drift がなくなる。椅子の位置を記憶するので Motion Tracking の drift を補正して正しい場所に表示できる。

複数人VRゲームでは、ゲームしている場所を記憶してその記憶をすべてのデバイスで共有することで、それぞれの位置が正しく補正されゲーム体験を改善できる。

Tango は
- 片付いているときと散らかっているときの部屋
- 異なる時間帯(朝・夜)の部屋
- 異なるライティング
- 観客がいるときといないときのスタジアム
- ランドマークの少ない部屋(全部白くてものが何もない部屋とか)
- 異なる季節(木に葉がある/ないなど)
などで同じ場所だと認識するのが難しい。

解決するキーは時間。 実世界には時間をかけてゆっくり変わるものと、短い時間で変わるものがある。地下鉄の駅では人や広告が入れ替わるので、記憶したものは短い間だけ正しくなる。 そこで、短い期間の記憶に頼るようにアプリをつくるのが良い戦略になる。

AR drift correction
  1. // Configure drift-free motion tracking  
  2. mConfig = new TangoConfig();  
  3. mConfig = mTango.getConfig(TangoConfig.CONFIG_TYPE_CURRENT);  
  4. mConfig.putBoolean(TangoConfig.KEY_BOOLEAN_ENABLE_DRIFT_CORRECTION, true); // ←  
  1. // Query drift-free motion tracking  
  2. TangoCoordinateFramePair frame_pair;  
  3. frame_pair.base = TANGO_COORDINATE_FRAME_AREA_DESCRIPTION; // ←  
  4. frame_pair.target = TANGO_COORDINATE_FRAME_DEVICE;  
  5. TangoService_getPoseAtTime(timestamp, frame_pair, &area_description_T_device);  
Multiplayer game

Create Memory → Share Memory → Multi Player

Create Memory
  1. // Learning an area description  
  2. mConfig = new TangoConfig();  
  3. mConfig = mTango.getConfig(TangoConfig.CONFIG_TYPE_CURRENT);  
  4. mConfig.putBoolean(TangoConfig.KEY_BOOLEAN_LEARNINGMODE, true); // ←  
  5.   
  6. // Saving an area description  
  7. mMemory = new String();  
  8. mMemory = mTango.saveAreaDescription(); // ←  
Share Memory between devices
  1. // Export an area description  
  2. Intent mExportIntent = new Intent();  
  3. mExportIntent.setClassName("com.projecttango.tango"  
  4.         "com.google.atap.tango.RequestImportExportActivity");  
  5. mExportIntent.putExtra(EXTRA_KEY_SOURCEUUID, mMemory);  
  6. mExportIntent.putExtra(EXTRA_KEY_DESTINATIONFILE, "/sdcard/area_description");  
  7.   
  8. mActivity.startActivityForResult(mExportIntent, Tango.TANGO_INTENT_ACTIVITYCODE);  
Multi Player
  1. // Loading an area description  
  2. mConfig = new TangoConfig();  
  3. mConfig = mTango.getConfig(TangoConfig.CONFIG_TYPE_CURRENT);  
  4. mConfig.putBoolean(TangoConfig.KEY_STRING_AREADESCRIPTION, mMemory);  // ←  
  1. // Query device pose in are description  
  2. TangoCoordinateFramePair frame_pair;  
  3. frame_pair.base = TANGO_COORDINATE_FRAME_AREA_DESCRIPTION; // ←  
  4. frame_pair.target = TANGO_COORDINATE_FRAME_DEVICE;  
  5. TangoService_getPoseAtTime(timestamp, frame_pair, &area_description_T_device);  



6 Degrees of Freedom Gaming in Android with Project Tango

Tango の3つの technology (Motion Tracking と Depth Perception と Area Learning)を一通り解説。

ARで何ができるか何ができないのかを見せるために猫のアプリを作ることにしたそうだ。virtual cat を実世界に。
このページをチェックすると楽しいらしい。
https://en.wikipedia.org/wiki/Cats_and_the_Internet

フレーム変換
  1. TangoErrorType TangoService_getPoseAtTime(  
  2.     double timestamp,  
  3.     TangoCoordinateFramePair frame,  
  4.     TangoPoseData* pose);  
  1. TangoCoordinateFramePair frame_pair;  
  2. frame_pair.base = TANGO_COORDINATE_FRAME_START_OF_SERVICE;  
  3. frame_pair.target = TANGO_COORDINATE_FRAME_DEVICE;  
  4.   
  5. TangoPoseData start_device_T_device;  
  6. TangoService_getPoseAtTime(timestamp, frame_pair, &start_service_T_device);  
猫を実世界の geometry に合わせないと、猫が宙に浮いたりしてしまう。 Tango ならこれを解決できる。
  1. TangoPoseData pose_color_camera_t0_T_depth_camera_t1;  
  2. TangoSupport_calculateRelativePose(  
  3.     last_color_time_, TANGO_COORDINATE_FRAME_CAMERA_COLOR,  
  4.     last_cloud_->timestamp, TANGO_COORDINATE_FRAME_CAMERA_DEPTH,  
  5.     &pose_color_camera_t0_T_depth_camera_t1);  
  6.   
  7. TangoSupport_fitPlaneModelNearClick(  
  8.     last_cloud_, &color_camera_intrinsics_,  
  9.     &pose_color_camera_t0_T_depth_camera_t1, glm::value_ptr(uv),  
  10.     glm::value_ptr(double_depth_position);  
  11.     glm::value_ptr(double_depth_plane_equation));  
猫アプリのデモ必見。

猫が家具の後ろにいったときに透けて見えてしまうのは現実っぽくない。 Tango は実世界の 3D データを作ることができる。ここからメッシュを作ると、実世界の家具の向こうにいった virtual の猫を非表示にしたり半透明にできる。 これのための処理はSDKで抽象化されていて、利用できる messing library もある。

あれこれやってデバイスのパワーを使いすぎると、デバイスがすごく熱くなったりする。Tango チームは速く効率的になるようにコードを最適化している。


Project Tango Developer Panel

3rd party の Tango アプリ開発者による Panel Session


2016年5月22日日曜日

Image compression for Android developers - Google I/O 2016

(テンション高いし、聞き取りやすい英語なのでオススメです)

Before we start

その他便利ツールなど

Four formats you care about

  • PNG
  • VectorDrawable
  • JPG
  • WebP

PNG

144x144 の単色の I/O アイコンが github では 6k だがストアの apk では 2k。でもまだ 144x144 にしてはでかい。8 color indexed image にすれば 932bytes になる。
  • palette や indexed にできるように調整する
  • 透明なピクセルのRGBチャネルを処理する
  • preprocess するなら gradle で cruncherEnabled = false
詳しくは Smaller PNGs : goo.gl/1yp3Bj

VectorDrawable

  • VectorDrawable使おう
  • 特に単色のピクトグラムに最適
  • POTrace (goo.gl/TG5z) は画像から vector に変換するツール

JPEG

  • qualityには何を指定すればいいの?
  • ImgMin project (goo.gl/OSvkMS) が参考になる
  • Butteraugli (goo.gl/1ehQOi) も参考になる

JPG Optimizer

  • JPEGMini (Lossy)
  • MozJPEG (Lossy)
  • cJPEG (Lossless)
  • packJPG (Lossless, Custom format)
  • Web solutions
どれ使ってもいいからやろう

image format 選択フロー

VectorDrawable にできる - yes -> VectorDrawable
 |
 no
↓
WebP をサポートしてる? - yes -> WebP
 |
 no
↓
透明が必要? - yes -> PNG
 |
 no
↓
simple or complex ? - simple -> PNG
 |
 complex
↓
JPG

PNG -> Use a tool, Resuce Colors, Hand Optimize
JPG -> Use a tool, Correct Quality, Hand Optimize


PROFILE YOUR CODE!!

Introducing the Awareness API, an easy way to make your apps context aware - Google I/O 2016

いままで

Where you are
  • Fused Location
  • Places API
  • Geofencing
What you're doing
  • Activity Recognition
  • Google Fit Platform
  • Sensors Platform
What's around you
  • Nearby Messages
  • Nearby Connections
  • Nearby Notifications
それぞれの API を組み合わせて使うのが大変だった。 例えば、複数の条件(Geofencingの中にいて、かつ車に乗っているなど)の組み合わせで処理のトリガーとするのが大変だった。電池への影響も考えないといけない。 そこで、組み合わせて使うのが簡単になる Awareness API をリリースした。

Awareness API

unified sensing platform

7 context types natively supported

  • Location (Latitude and longitude)
  • Places ("Starbucks", Coffee shop)
  • Beacons (What beacons or devices are nearby?)
  • Time (Local time)
  • Activity (Walking, running, biking, or driving)
  • Headphones (Headphones plugged or not?)
  • Weather (Current temperature and conditions)

Fance API

Callback style
  1. AreanessFence startDriving = DetectedActivityFence.staring(  
  2.  DetectedActivityFence.IN_VEHICLE);  
  3.   
  4. AwarenessFence areaAroundStore = LocationFence.in(  
  5.  STORE_LATITUDE, STORE_LONGITUDE,  
  6.  1000 /* radius in meters */, 0L /* dwell time */);  
  7.   
  8. AwarenessFence duringDriving = DetectedActivityFence.during(  
  9.  DetectedActivityFence.IN_VEHICLE);  
  10.   
  11. AwarenessFence openHours = TimeFence.inDailyInterval(  
  12.  TimeZone.getDefault(),  
  13.  10 * HOURS_IN_MILLIS,  
  14.  18 * HOURS_IN_MILLIS);  
  15.   
  16. AwarenessFence drivingNearStore = AwarenessFence.and(  
  17.     areaAroundStore,  
  18.     duringDriving,  
  19.     openHours);  
  20.   
  21. // Create FenceUpdateRequest and register.  
  22. FenceUdateRequest fenceUpdateRequest = new FenceUpdateRequest.Builder()  
  23.  .addFence("startDriving", startDriving, pendingIntent)  
  24.  .addFence("drivingNearStore", drivingNearStore, pendingIntent)  
  25.  .build();  
  26.   
  27. Awareness.FenceApi.updateFences(googleApiClient, fenceUpdateRequest);  
  1. void onReceive(Context context, Intent intent) {  
  2.  FenceState fenceState = FenceState.extract(intent);  
  3.  if (fenceState.getFenceKey().equals("startDriving")) {  
  4.    if (fenceSate.getCurrentState() == FenceState.TRUE) {  
  5.        // show map apps  
  6.    }  
  7.  } else if (fenceState.getFenceKey().equals("drivingNearStore")) {  
  8.    if (fenceSate.getCurrentState() == FenceState.TRUE) {  
  9.        // show reminder  
  10.    }  
  11.  }  
  12. }  

Snapshot API

  1. PlacesResult placesResult = Awareness.SnapshotApi.getPlaces(googleApiClient).await();  
  2.   
  3. WeatherResult weatherResult = Awareness.SnapshotApi.getWeather(googleApiClient).await();  

Permission

  • Location, Place, Beacon, Weather -> ACCESS_FINE_LOCATION
  • Activity -> ACTIVITY_RECOGNITION
  • Headphones -> no permission