# X plane 模擬環境
###### tags: `飛控`
| 月份 | 週次(日期) | 內容 |
| ---- | --------------------- | ------------------------------------------------------ |
| Oct | I (Oct.10~OctOct.16) | 建立Xplane的環境 |
| | II (Oct.17~Oct.23) | 使用UDP連結Xplane,傳輸數據至matlab|
| | III (Oct.24~Oct.30) | 連結外部搖桿數據至matlab |
| Nov | IV (Oct.31~Nov.6) |建立PID控制器控制姿態 |
| | V (Nov.7~Nov.13) |debug |
| | VI (Nov.14~Nov.20) |debug |
| | VII (Nov.21~Nov.27) |先基於Cessna172調整PID參數使姿態 |
| Dec | VIII (Nov.28~Dec.4) |定義新飛機氣動外型(TUNA T) |
| | IX (Dec.5~Dec.11) |對自訂飛機調整PID控制器 |
| | X (Dec.12~Dec.18) |收集飛行動態資料 |
| | XI (Dec.19~Dec.26) |debug |
| | XII (Dec.26~Jan.1) |debug |
>[name=紀中威]
>[name=蕭凡棋]
## 安裝Xplane
去到UAV雲端中-工具程式-Xplane10將所有相關東西下載並依序1~9執行一遍
### 使用軟體
#### Xplane 10
#### Matlab 2022b
## 使用UDP連結Matlab

我們將使用 MATLAB 中 Simullink 透過UDP發送及接收Xplane模擬出來的飛行數據,也可以使用外接控制器去發送控制訊號
本次模擬皆是模擬定翼機,如果要試其他類型可以去
http://www.nuclearprojects.com/xplane/info.shtml
## Sending UDP datagrams

---
### Input

輸入訊號可以使用各種的RC控制器,我是使用Logitech 3D extreme pro
透過UDP訊號輸入直接覆蓋在Xplane10中的操縱輸入
如果要使用Logitech 3D extreme pro 去以下網址下載驅動程式
https://support.logi.com/hc/zh-tw/articles/360024843033--%E4%B8%8B%E8%BC%89-Extreme-3D-Pro

可以創建一個scope來監測操縱桿的訊號輸入是否正確
使用過程中怕訊號有出錯,所以我們需要創建一個calibrate block 來設定上下限
roll, pitch, yaw : -1 ~ 1
thrust : 0 ~ 1
---
### Encoding and sending

再來我們需要將訊號打包成Xplane 看得懂的訊號,來自控制桿的訊號為 double ,需要先使用Data Type Conversion 轉換成 single 在 轉成 8位無符號整數(uint8)。

將Data Type Conversion block 中的
Output data type : [Inherit: Inherit via back propagation] 改成 Output data type : [single]
使用Byte pack 將單精度訊號打包成unit8

---
#### UDP_encode


可以勾選不同的頻道數量來決定我們需要進行人為控制的參數選項,調整右下的UDP rate 越大發送訊號的頻率會越高,下面11 25的部分就是我們介入pitch, roll, yaw, throttle的部分。Xplane10_Settings_Data inputs and outputs 中可以查看對應數字的控制參數頻道,但隨著版本不一樣可能有所不同
```
function UDP = UDP_encode(roll_single, pitch_single, yaw_single, throttle_single)
DATA = [68 65 84 65 48];
NULL = [0 192 121 196];
UDP_flightcon = [11 0 0 0 pitch_single' roll_single' yaw_single' NULL NULL NULL NULL NULL];
UDP_throttle = [25 0 0 0 throttle_single' NULL NULL NULL NULL NULL NULL NULL];
UDP = [DATA UDP_flightcon UDP_throttle]';
end
```
傳送信號的最後一步,就是將訊號傳到Xplane10裡面,我們需要設定相同的IP address 和對應的port 確保有正確接收,在UDP Send Block 設定address & port ,如果是在同一台電腦上使用的話,可以打127.0.0.1就好,意思就是本台主機,X-Plane 默認接收端口是 49000 ,可以去Xplane 10_Net Connection_Data 中下面查看使用的UDP ports
如果使用不同台電腦,可以去cmd 中打ipconfig 中的IPV4 address 即是電腦IP位址


發送成功的話會顯示,表示Xplane 10 成功接收來自simulink 中UDP 發送的訊號

---
## Receiving UDP datagrams

由於Xplane10 中49000 49001 49002 已經被定義使用我們可以將發送端口設置成 49003,
---
### UDP recieve


將UDP Recieve Block 接收IP和address 改成 在Xplane10上面設定的一樣(0.0001改成0.1)
#### **發現**
可以更改UDP recieve block 中的maximum length for message 來更改輸出數據的多寡,
heading data = 5 bytes
資料長度所選
group of 4 bytes each
8 fields

已這張圖為例
maximum length for message = 8 * 9 * 4 + 5 = 293
---
### UDP decode
UDP decode 接收來自Recieve 的資料加以整理,輸出我們想要觀測的數據
每個頻道有 36bytes ,每個頻道編號分配 4bytes
```
% X-Plane: Channels 11, 17, 20
%--------------------------------------------------------------------------
% flight_con = [elev ailrn ruddr];
% flight controls
% attitude = [pitch roll hding_true hding_mag];
% pitch, roll, yaw
% location = [lat lon alt_msl alt_agl];
% latitude, longitude, altitude [deg],[ftmsl],[ftagl] (mean sea level, actual ground level)
%--------------------------------------------------------------------------
function [elev, ailrn, ruddr, pitch, roll, hding_true, hding_mag, lat, lon, alt_msl, alt_agl] = UDP_decode(UDP)
% We don't need the DATA header, which are the first 5 bytes
UDP = UDP(6:end);
% We cut the datagram in channels, each containing 36 bytes, 4 for the channel number, and 4 for each of the 8 entries.
CH11 = UDP(1:36);
CH17 = UDP(37:72);
CH20 = UDP(73:108);
%-------------------------
% At last we extract each entry from their channel and output them.
elev = Channel_to_single(CH11,1);
ailrn = Channel_to_single(CH11,2);
ruddr = Channel_to_single(CH11,3);
pitch = Channel_to_single(CH17,1);
roll = Channel_to_single(CH17,2);
hding_true = Channel_to_single(CH17,3);
hding_mag = Channel_to_single(CH17,4);
lat = Channel_to_single(CH20,1);
lon = Channel_to_single(CH20,2);
alt_msl = Channel_to_single(CH20,3);
alt_agl = Channel_to_single(CH20,4);
%---------------------------------
end
function [single] = Channel_to_single(CH, data_pos)
start_byte = 1 + 4*data_pos;
stop_byte = start_byte + 3;
single = CH(start_byte:stop_byte);
end
```
傳出的訊號需要拆封成simulink可以讀取的訊號,加上Byte Unpack 並根據UDP decode 訊號輸出訊號調整數量及訊號型態,輸出的訊號可以用scope 來隨時監測


---
### 將機型換成Cessna 172P 並對輸出數值做調整
**輸出訊號名稱**
1. speed
2. elevator
3. aileron
4. rudder
5. latitude
6. longitude
7. altitude
{%youtube 6dRcyO_HCW4 %}