はい、ダメだったはなしです。
皆さんご存知の通り、HoloLensはGPSのってないので迷子に優しくないデバイスです。
ナビゲーションだけじゃなくて、GPSが使えると何が嬉しいかというと、開発でいつも頭を悩ませる位置合わせがオブジェクトそのものにリアル座標を設定してあげることで楽になる・・・かもしれない。
(この記事とか面白いですよ)
www.moguravr.com
今回挑戦したのは、Google Maps Geolocation APIを使ってHoloLensの位置情報をとってみるという試み。
developers.google.com
Geolocation APIではWifiのAccessPointを2点以上与えてあげると、現在地を返してくれるそうです。
最新のアプリ - UWP での Wi-Fi スキャナーのビルドでは、APIに必要なアクセスポイントの情報を取得する方法について書かれています。
まずはサンプルを実行してみましょう。以下からクローンして実行してみます。
github.com
(写真には出さないけど、Macアドレス、SSID、信号強度などがずらっと表示されます)
では、次にUnity側へ実装してみます。
今回の開発環境は、
- Unity2017.1.2
- VS2017
になります。
レポジトリから、
- WiFiPointData.cs
- WiFiScanner.cs
- WiFiSignal.cs
をUnityProjectに引っ張ってきます。そのままだとwifi-scannerはビルドに引っかかるので#if UNITY_UWP ~ #endifで囲ってあげてください。
using System; using System.Threading.Tasks; #if UNITY_UWP using Windows.Devices.Enumeration; using Windows.Devices.WiFi; #endif namespace WiFiScannerUWP { public class WiFiScanner { #if UNITY_UWP ~~~~~~ #endif } }
それでは、MainPage.xaml.csを元にAPIを呼んでみます。
using System; using System.Text; using System.Collections.Generic; using Newtonsoft.Json; using UnityEngine; #if UNITY_UWP using System.Threading.Tasks; using WiFiScannerUWP; using System.Net.Http; using Windows.Devices.WiFi; using Windows.Devices.Geolocation; #endif public class Rootobject { public WifiAccessPoints[] wifiAccessPoints { get; set; } } public class WifiAccessPoints { public string macAddress { get; set; } } public class Response { public Location location { get; set; } public float accuracy { get; set; } } public class Location { public float lat { get; set; } public float lng { get; set; } } public class WiFiScanViewer : MonoBehaviour { #if UNITY_UWP private WiFiScanner wifiScanner; private HttpClient httpClient = new HttpClient(); List<WifiAccessPoints> wifiPoints; #endif string msg; private readonly string url = "https://www.googleapis.com/geolocation/v1/geolocate?key="; public string apiKey = "********"; #if UNITY_UWP void Start() { wifiScanner = new WiFiScanner(); InitializeScanner(); //3秒後から5秒おきにスキャン InvokeRepeating("GetPositionInformation", 3f, 5f); } /// <summary> /// Scan及び位置情報の取得 /// </summary> private async void GetPositionInformation() { try { string info = await RunWifiScan(); var jsonString = JsonConvert.DeserializeObject<Response>(info); msg = "LAT: " + jsonString.location.lat + "\r\n" + "LNG: " + jsonString.location.lng + "\r\n" + "Accuracy: " + jsonString.accuracy; } catch (Exception e) { msg = e.ToString(); } } /// <summary> /// Scannerの初期化 /// </summary> private async void InitializeScanner() { await this.wifiScanner.InitializeScanner(); } /// <summary> /// Scanの実行 /// </summary> /// <returns></returns> private async Task<String> RunWifiScan() { await this.wifiScanner.ScanForNetworks(); Geolocator geolocator = new Geolocator(); Geoposition position = await geolocator.GetGeopositionAsync(); WiFiNetworkReport report = this.wifiScanner.WiFiAdapter.NetworkReport; wifiPoints = new List<WifiAccessPoints>(); //アクセスポイントの情報取得 foreach (var availableNetwork in report.AvailableNetworks) { var wifiaccessPoint = new WifiAccessPoints(); wifiaccessPoint.macAddress = availableNetwork.Bssid; wifiPoints.Add(wifiaccessPoint); } //送信データのシリアライズ var postData = JsonConvert.SerializeObject(wifiPoints.ToArray()); var resMsg = ""; //Geolocation apiの呼び出し using (var client = new HttpClient()) { var content = new StringContent(postData, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url + apiKey, content); resMsg = await response.Content.ReadAsStringAsync(); } return resMsg; } #endif }
wifiAccessPoints では複数のパラメータを指定できるのですが、使用したパラメータはMACアドレスのみです。
信号強度のパラメータが有用という情報は見かけたのですが、残念ながらUWPで使用できるのは0-5の値のみで必要なデシベル値がとれないようです。
信号強度のパラメータはavailableNetwork.NetworkRssiInDecibelMilliwattsで取得できます。
データはJSON.Netを使ってシリアライズ/デシリアライズしています。
CapabilityからInternet Clientを有効にし、ビルド後にPackage.appxmanager から画像にある2つのCapabilityを有効にします。
配置後、うまく位置データが表示されない場合はHoloLensのSettings->Privacy->Locationから対象のアプリの位置情報をONにしてください。
ご存知の結果になります。
外部デバイスを使わずHoloLensで位置情報をとってみた。
— デコ・シ (@Ash_Yin) 2017年12月17日
Google GeoLocation APIとUWPのWifi-Scannerサンプルを使ってさっくりと実装してみました。精度があれっていうか全然違うところなんですが、ホットスポットと繋ぐととれるらしいのでまた試してみます #HoloLensJP pic.twitter.com/OdI03d9aIb