PowerAppsのLocation関数を使ってノンコーディングでスピードメーターっぽいものを作ってみた

# 今回の投稿背景
PowerAppsの関数の一つに"Location"関数というものがあり
これを使用することで、緯度と経度、あと高度が取れるのです。
簡単な使用方法は[こちら（PowerApps の Acceleration、App、Compass、Connection、Location の各シグナル）](https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/functions/signals)

お！ということはですよ？緯度と経度が取れるなら、スピードメーター作れるんじゃね？！
ってことで、Arduinoで作ったことがある経験から、PowerAppsでも
**ノンコーディング** でスピードメーターを作ってみることにしました。

あとは、Twitterにあげたら
@taiki_yoshida にこんなリツイートを頂いたからというのもあります:flushed:
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/PowerApps?src=hash&amp;ref_src=twsrc%5Etfw">#PowerApps</a> でスピードメーターの発想はなかった！ ブログ記事出ないかな… <a href="https://t.co/KNryfUZyAM">https://t.co/KNryfUZyAM</a></p>&mdash; Taiki Yoshida (@TaikiYoshidaJP) <a href="https://twitter.com/TaikiYoshidaJP/status/1036125670391201793?ref_src=twsrc%5Etfw">2018年9月2日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>



# というわけで作ったものがこちら（Twitter）
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">先日失敗した<a href="https://twitter.com/hashtag/PowerApps?src=hash&amp;ref_src=twsrc%5Etfw">#PowerApps</a> で スピードメーターですが、いろいろ確認したところ、計算式が、ミスっていたようです(´°̥̥̥̥̥̥̥̥ω°̥̥̥̥̥̥̥̥｀)<br>修正しましたのでご査収下さい。<br>ついでに <a href="https://twitter.com/hashtag/%E3%83%A2%E3%83%88%E3%83%96%E3%83%AD%E3%82%AC%E3%83%BC?src=hash&amp;ref_src=twsrc%5Etfw">#モトブロガー</a> の皆さんにも喜んで頂けるよう、速度の倍率設定を機能に追加しました。 <a href="https://t.co/I5out8RFOn">pic.twitter.com/I5out8RFOn</a></p>&mdash; りなたむ@steed400 (@R_t_A_n_M) <a href="https://twitter.com/R_t_A_n_M/status/1035841927009058817?ref_src=twsrc%5Etfw">2018年9月1日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# 速度の出し方って・・・
小学校の時習いませんでした？
**速度＝距離÷時間**

## 時間は・・・
GPS情報はその時その時の緯度と経度なので、信号補足ポイント間の時間を代入してあげればいいですね

## じゃあ距離は・・・
緯度と経度から距離を算出するためにはヒュベニの公式を使用します。

```math
距離d=\sqrt{(d_y M)^2+(d_x N \cos \mu_y)^2}
```
```math
緯度差d_y=y_1-y_2
```
```math
経度差d_x=x_1-x_2
```
```math
緯度平均値\mu_y=\frac{y_1+y_2}{2}
```
```math
子午線曲率半径M=\frac{a(1-e^2)}{W^3}
```
```math
卯酉線曲率半径N=\frac{a}{W}
```
```math
W=\sqrt{1-e^2 \sin^2 \mu_y}
```
```math
e=\sqrt{\frac{a^2-b^2}{a^2}}
```

これ書くのしんどいｗｗｗ
参考サイト：[日本は山だらけ：二地点の緯度・経度からその距離を計算する](http://yamadarake.jp/trdi/report000001.html)


###なんちゃら線の半径MとNはどうやって出すんじゃい！！
aとかbとかeは定数値なので、以下の数式をそのまま使用できます。

```math
M=\frac{6334834}{\sqrt{(1-0.006674 \times \sin \mu_y \times \sin \mu_y)^3}}
```
```math
N=\frac{6377397}{\sqrt{(1-0.006674 \times \sin \mu_y \times \sin \mu_y)}}
```
参考サイト：[端子録：GPS データ (GPX) から移動距離を求める](http://dtan4.hatenablog.com/entry/2013/06/10/013724)

# ということで・・・
時間と距離が分かれば速度が出ます。
時間はさておき、距離を算出してみましょう。

# 距離を生成する
都度データが変わりますので、タイマーコントロールを使用します。

## 緯度経度格納用タイマーコントロール
まずは、現在の緯度と経度を格納するためのタイマーコントロールを作成します。
OnTimerStartプロパティに以下の関数を入力します。

```php:OnTimerStart
Set(Var_Latitude_now,Location.Latitude)&
Set(Var_Longitude_now,Location.Longitude)
```
期間はとりあえず1秒（1000msec）としましょう。
繰り返しと自動開始にチェックを入れます。

## 距離計算用各種変数格納タイマーコントロール
続いて距離計算用の各種変数を格納するタイマーコントロールを作成します。
OnTimerStartプロパティに以下の関数を入力します。

```php:OnTimerStart
If(Var_Latitude_before <> Var_Latitude_now,
	Set(Var_Latitude_Ave,Average(Radians(Var_Latitude_before),Radians(Var_Latitude_now)))&
	Set(Var_Latitude_diff,(Var_Latitude_before - Var_Latitude_now))&
	Set(Var_Longtitude_diff,(Var_Longtitude_before - Var_Longitude_now))&
	Set(Var_Meridian_Radius,(6334834/Sqrt(((1-0.006674*Sin(Var_Latitude_Ave)*Sin(Var_Latitude_Ave))^3))))&
	Set(Var_Rabbit_Radius,(6334834/Sqrt(((1-0.006674*Sin(Var_Latitude_Ave)*Sin(Var_Latitude_Ave))))))&
	Set(Var_Latitude_before,Var_Latitude_now)&
	Set(Var_Longtitude_before,Var_Longitude_now)
,"")
```
こちらも期間はとりあえず1秒（1000msec）としましょう。
繰り返しと自動開始にチェックを入れます。

## 距離計算用タイマーコントロール
あらかたの変数が取れたので、距離の公式に合わせて代入していきます。
複雑なので、平方根する前の数値の計算をそれぞれグローバル変数に作成していきます。
※まとめることもできますが、計算式間違いするのを極力減らすため、いったんは分けておいたほうがいいです＾＾；

```math
(d_y M)^2+(d_x N \cos \mu_y)^2
```

```php:OnTimerStart
Set(Calc01,(Var_Meridian_Radius*Radians(Abs(Var_Latitude_diff)))^2)&
Set(Calc02,(Var_Rabbit_Radius*Cos(Var_Latitude_Ave)*Radians(Abs(Var_Longtitude_diff)))^2)
```

では実際の距離計算コントロールも作成します。

```php:OnTimerStart
Set(Var_Distance,Sqrt(Calc01+Calc02))
```
これで距離を算出することができました。
なお、単位はメートルです。

# では実際に速度を求めてみましょう。
こちらもタイマーコントロールを使用します。

```php:OnTimerStart
Set(Var_Speed,(Var_Distance/1000)/3600)
```
上記は時速で算出しています。
緯度経度情報を1秒間隔で取得しているので
メートルをkmに変換し、3600秒で割れば求めることができます。

表示はラベルを使用します。
TEXTプロパティに以下の関数を入力しましょう。

```php:TEXT
Round(Var_Speed,3)&"km/h"
```

# というわけでスピードメーターが完成・・・？
と言いたいところですが、かなりばらつきがあり
走行中は比較的安定しているのですが、低速度時は精度が低くかなりよろしくないです。
加速度などもとることができますので
こちらも有効活用するなどして、より精度を高める工夫が
必要になるので注意しましょう。

# まとめ
Location関数だけで作るにはかなり限度があるが、できないことはない。
あとは加速度データも含めて計算するようにするかとか
取得判定時の時間差を計算式に盛り込むなどすると精度が上がると思う。

# Microsoftさんへのお願い
Location関数のGPS取得するタイミングをこちらで制御できるような仕組みがあると非常にありがたいです。