ZED SDK のセンサーデータ

## 想定する読者
stereolabsのzed2, zed mini, zed x などのステレオカメラの利用者
いまどきのステレオカメラは何ができるのかを知りたい人

## 前提
ZED SDK 4.0
Ubuntu 20.04
ZED2i
Python 版のAPI

## ZED カメラのセンサーデータ
ZED SDK にはさまざまなアプリケーションが予め用意されています。
カメラの向きを水平でなく傾いた状態でも、床面を正しく判断して、bird view を描画してくれます。
磁気センサもあるので、方位を知ることができます。
気圧計もあるので、気圧が分かるだけではなく、基準位置からの高低差を知ることができます。

### IMUのないステレオカメラでは：
- カメラの姿勢情報がわからないので、このようなアプリケーションを即座に動作させることができません。
- 別途IMUを機構的に精度よく取り付けて、カメラと同期のとれたタイミングでIMUデータを取得するように改造することになります。
- それは、よほどの理由がない限り、無駄な作業です。（もう既にあるのですから）

# ZED SDK 
以下はコードの断片です。
そのため、事前に必要なimport や変数の事前の初期化が不足している場合があります。
適宜補ってください。
例
```.py:
import pyzed.sl as sl
```

### 注意点
- 物理量には単位があります。
- どのような単位を使っているのか確認して使いましょう。
- ベクトルには、座標系の定義があります。
- どのようにXYZの座標系を定義しているのかに注意しましょう。
- ZED SDKの設定の中には、XYZの座標系の定義に関する設定・長さの単位を何にするのかという設定があります。
- それらの設定が意図したものになっているのかを明示的に確認しましょう。

### データ構造の探り方
- `inspect` モジュールを使う。[ZED SDK を使いこなす inspectでデータ構造を理解する](https://qiita.com/nonbiri15/items/72d95f4cd3218925b27d)
- help(インスタンス.メソッド名)を実行することで、メソッドの使い方を調べます。
- 戻り値があればそれをprint してみます。 

## Sensor data へのアクセス
```.py:
zed = sl.Camera()
sensors_data = sl.SensorsData()
zed.get_sensors_data(sensors_data, sl.TIME_REFERENCE.IMAGE)
```

### pyzed.sl.SensorsData 型
データメンバー
- camera_moving_state
- image_sync_trigger
メソッド
- get_barometer_data()
- get_imu_data()
- get_magnetometer_data()
- get_temperature_data()
- init_sensorsData()


### pyzed.sl.IMUData　型
データメンバー
- effective_rate
- is_available
- timestamp

メソッド
- get_angular_velocity() 
単位は [deg/s]
- get_angular_velocity_covariance()
- get_angular_velocity_uncalibrated()
- get_linear_acceleration()
linear_accelerationの出力例
[-0.12917175889015198, 9.600632667541504, -1.964520812034607]
y軸方向が 9.8 [m/s**2] の重力加速度に対応している。 
- get_linear_acceleration_covariance()
- get_linear_acceleration_uncalibrated()
- get_pose()
    - 4x4の射影行列が得られます。
    - これを使って、カメラ座標系から重力加速度を基準にした座標系に変換することができます。
- get_pose_covariance()

公式ドキュメント [IMU](https://www.stereolabs.com/docs/sensors/imu)

### pyzed.sl.MagnetometerData 型
データメンバー
- effective_rate
- is_available
- magnetic_heading
- magnetic_heading_accuracy
- magnetic_heading_state
- timestamp
メソッド

- get_magnetic_field_calibrated()
- get_magnetic_field_uncalibrated()

公式ドキュメント [magnetometer](https://www.stereolabs.com/docs/sensors/magnetometer)

### Pose
4x4の射影行列が得られます。

0.999868 0.016161 0.001609 -0.000000
-0.015502 0.979199 -0.202310 -0.000000
-0.004845 0.202259 0.979320 0.000000
0.000000 0.000000 0.000000 1.000000

### pyzed.sl.BarometerData 型
データメンバー
- effective_rate
- is_available
- pressure
- relative_altitude
- timestamp

公式ドキュメント [barometer](https://www.stereolabs.com/docs/sensors/barometer)


## pyzed.sl.Timestamp 型
以下の場所に記載済みです。
[ZED SDK のtimestampを取得するには](https://qiita.com/nonbiri15/items/f2d26b70620d2f4c2962)



## センサーデータを使う例題のスクリプト
[recording/export/sensors/python/export_sensors.py](https://github.com/stereolabs/zed-sdk/blob/master/recording/export/sensors/python/export_sensors.py)
センサーデータをJson形式に変換するコードが書かれています。
そのため、センサーデータのインスタンスに対するメソッドの使い方が多く含まれています。

これらのセンサーデータはどう使われるのかを探るには
pycharm などの統合環境で、get_pose() メソッドなどの知りたい対象を検索します。
そうすると、どのサンプルアプリケーションの中でどのように使われているのかがわかります。
たとえば、get_pose()はこのように使われています。

`positional tracking/positional tracking/python/positional_tracking.py`

```.py:
if zed.get_sensors_data(sensors_data, sl.TIME_REFERENCE.IMAGE) == sl.ERROR_CODE.SUCCESS:
    rotation = sensors_data.get_imu_data().get_pose().get_euler_angles()
    text_rotation = str((round(rotation[0], 2), round(rotation[1], 2), round(rotation[2], 2)))
    viewer.updateData(sensors_data.get_imu_data().get_pose(), text_translation, text_rotation, tracking_state)
```

## 公式のドキュメント
https://www.stereolabs.com/docs/sensors

[Tutorial 7: Getting sensor data from ZED Mini and ZED2](https://github.com/stereolabs/zed-sdk/tree/master/tutorials/tutorial%207%20-%20sensor%20data)