*Node-RED プログラム「飛行機がもうすぐ来るよ」 に、飛行機が見える方角を追加してみた。

## 1.はじめに
Node-REDプログラムで、設定した範囲内に飛行機が入ると、「飛行機がもうすぐ来るよ」と音声で知らせてくれる面白いものがあります。飛行機が来ることだけでなく、どの方角に飛んでいるのか？ そして飛行機が範囲内に来る予測を、心の欲するままにプログラムを考えて追加してみました。

## 2．追加したプログラム
(1)飛行機が飛んでいる方角：逆三角関数アークタンジェント(arctangent)で角度を算出。
(2)飛行機が来る予測：約10km(約1分) 飛行後、設定位置から半径10㎞範囲内に入るか判定。

### (1)飛行機が飛んでいる方角(詳細)
設定位置からの飛行機の方角、角度(北から右回り)を計算して音声で知らせる。 

プログラム内容
　　　　①　　　　　②　　　　　　　③　　　　　　④　　　　　⑤　　　　　⑥
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801125/25d2afb3-0bd8-b1b6-cc1a-dfae17437888.png)


#### ①設定位置から飛行機位置までの距離、X（経度）とY（緯度）を引き算にて求める。
```JavaScript:
x= Number(msg.payload.lon);   //飛行機位置（経度）を変数ｘに代入
msg.x=x-135.0162              //飛行機位置（経度) から設定位置（135.0162）を引く。
y= Number(msg.payload.lat);   //飛行機位置（緯度）を変数yに代入
msg.y=y-34.7167               //飛行機位置（緯度）から設定位置(34.7167)を引く。
return msg;
```

#### ②③飛行機位置の象限により、Switchノードにて、分岐させる。
- 各象限によって、角度計算のプログラムが異なるため、分岐させる。
- 設定位置は、中心(x=0,y=0)である。飛行機位置が、0°~90°の範囲内の場合、第一象限。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801125/b484b9e6-e7c2-1ec3-9abb-8780cb345946.png)

#### ④各象限ごとに角度計算をする。
下記は、1象限のプログラムを示し、詳細は後述で説明する。
なお、角度計算は、各象限ごとで、4パターンだと考えたが、結果は2パターンであった。
内容を分かりやすくするために、本プログラムは4パターンのままにしている。
```JavaScript:
msg.deg=90-(Math.atan(msg.y/msg.x)*180/Math.PI)
return msg;
```
#### ⑤角度の小数点以下を切り捨て、文章にする。
```JavaScript:
msg.payload="飛行機が上空に飛んでいるよ"+String(Math.floor(msg.deg))+"度に"
return msg;
```
#### ⑥音声出力する。

 
#### 上記④の各ファンクションのプログラム(計算式)
第一象限と第四象限においては、90°を基準として、
第一象限では、90°からの引き算、第四象限では足し算で、飛行機の位置角度を求める。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801125/973f40a3-973d-631a-e934-fa6a90cbeaab.png)

第二象限と第三象限においては、270°を基準として、
第三象限では、270°からの引き算、第二象限では、足し算で、飛行機の位置角度を求める。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801125/110f0c52-b26c-4c10-93b7-20f6e77198d3.png)


各象限のプログラム内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801125/1a1e6e04-e680-b2f1-9e4c-c14d544d813b.png)

第二象限は、2つ上の図で示す通り【加算】であるが、
プログラム「msg.deg=270 <font color="Red">－</font> (Math.atan(msg.y/msg.x)*180/Math.PI)」は【マイナス符号】。
間違い?　と思うが、ｘの値がマイナス、yの値がプラスであるため、「Math.atan(msg.y/msg.x)」の計算結果がマイナスとなり、
マイナス(計算結果)×マイナス(符号)は、プラス(加算)となり、正しい。
※第四象限の説明は、同じであるため省略する。


### (2)飛行機が来る予測(詳細)
プログラム内容
　　　　　　　①　　　　　　　　　　　　　②　　　　　　　　　　　　③
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801125/e329609f-c973-53dd-ebd9-e2cbc79f6ba4.png)

#### ①約10km飛行後の設定位置との距離

```JavaScript:
xa= Number(msg.payload.lon);			//<font color="Red">飛行機の位置（経度）をxaに代入
xa=xa+0.1*Math.sin(msg.payload.heading) // ※1
xa=xa-135.0162                          //飛行機10km進行後と設定位置の差
xa=Math.pow(xa,2)                       //xaを2乗する。【三平方の定理 x方向の辺】
ya= Number(msg.payload.lat);            //飛行機の位置（緯度）をyaに代入
ya=ya+0.1*Math.cos(msg.payload.heading) // ※1
ya=ya-34.7167					        //飛行機10km進行後と接近を確認したい位置の差
ya=Math.pow(ya,2)                       //yaを2乗する。【三平方の定理 y方向の辺】
msg.z=Math.sqrt(xa+ya)                  //ｚの距離を求める。三平方の定理 斜辺】
return msg;
```

※1：飛行機が約10km進んだ先の位置（経緯度）を計算
　約10kmは約0.1°である。この約0.1°に、三角関数にて、約10km進んだ先を算出する。
・約0.1°の求め方：360°×10㎞÷4万km(地球赤道1周)＝0.09≒0.1°
 　 (赤道＝緯度0°なので、厳密な計算ではない。そもそも約10kｍと適当なので気にしない)
・三角関数：経度方向は sin、緯度方向は cosである。
・msg.payload.headingは、飛行機の進行角度、北から時計回りにラジアン表示。

#### ②半径10km以内?
msg.zの値が0.1(約10km)以内であるかを、Switchノードにて、判別する。

#### ③音声出力する。

### ＜補足情報＞
- 飛行機が来る予測は、飛行機の進路変更があった場合、当然外れます。
- 飛行機の位置角度を、音声ではなく、物理的な回転体(サーボモータ)にて指し示すこともできます。実際に行ってみました。一般的なサーボモータの回転角度は180°なので、サーボモータを2個連結して360°示せるようにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801125/bb930e55-2a09-06fd-29bd-46f3dfd3d37b.png)
以上となります。