ZED SDK でspatial-mappingを使う

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

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

https://www.stereolabs.com/docs/spatial-mapping/using-mapping

## 使い方
```
python3 spatial_mapping.py -h
usage: spatial_mapping.py [-h] [--input_svo_file INPUT_SVO_FILE] [--ip_address IP_ADDRESS] [--resolution RESOLUTION] [--build_mesh]

optional arguments:
  -h, --help            show this help message and exit
  --input_svo_file INPUT_SVO_FILE
                        Path to an .svo file, if you want to replay it
  --ip_address IP_ADDRESS
                        IP Adress, in format a.b.c.d:port or a.b.c.d, if you have a streaming setup
  --resolution RESOLUTION
                        Resolution, can be either HD2K, HD1200, HD1080, HD720, SVGA or VGA
  --build_mesh          Either the script should plot a mesh or point clouds of surroundings
```

## spatial_mapping.py を実行する。

```
cd zed-sdk/spatial mapping/spatial mapping/python

python3 spatial_mapping.py
Press on 'Space' to enable / disable spatial mapping
Disable the spatial mapping after enabling it will output a .obj mesh file
[2024-06-19 02:28:03 UTC][ZED][INFO] init
Mesh saved under mesh_gen.obj

meshlab mesh_gen.obj
```

## 出力ファイル

--build_mesh を指定したときに得られるファイル。
```commandline
mesh_gen.obj
mesh_gen_material0000_map_Kd.png
mesh_gen.mtl
```

mtl: マテリアル テンプレート ライブラリ
mesh_gen_material0000_map_Kd.png: メッシュと対応付けられた範囲のRGBデータ。（３チャネル）

--build_mesh を指定しないときに得られるファイル。

mesh_gen.obj
点群だけが得られる
## なぜspatial mappingを使うのか
- 単一のフレームでの点群の精度は高くない。
- 

## SPATIAL_MAP_TYPE 型
<enum 'SPATIAL_MAP_TYPE'>
`FUSED_POINT_CLOUD: SPATIAL_MAP_TYPE.FUSED_POINT_CLOUD`
　 pymesh = sl.FusedPointCloud()　を用意する。
  点群なので、surfaceデータを持たない。
`MESH: SPATIAL_MAP_TYPE.MESH`
　pymesh = sl.Mesh()　を用意する。
 メッシュなので、三角形が基本でsurfaceデータを持つ。

## MAPPING_RESOLUTION　型
<enum 'MAPPING_RESOLUTION'> 
HIGH: MAPPING_RESOLUTION.HIGH
LOW: MAPPING_RESOLUTION.LOW
MEDIUM: MAPPING_RESOLUTION.MEDIUM

## MAPPING_RANGE 型
<enum 'MAPPING_RANGE'>
AUTO: MAPPING_RANGE.AUTO
LONG: MAPPING_RANGE.LONG
MEDIUM: MAPPING_RANGE.MEDIUM
SHORT: MAPPING_RANGE.SHORT

> MAPPING_RANGE::NEAR: integrates depth up to 3.5 meters.
MAPPING_RANGE::MEDIUM: integrates depth up to 5 meters.
MAPPING_RANGE::FAR: integrates depth up to 10 meters.

https://www.stereolabs.com/docs/spatial-mapping/using-mapping#adjusting-range
ドキュメントの乖離が生じている。

## SpatialMappingParameters クラス
メソッド
get_range_preset()
get_recommended_range()
get_resolution_preset()
load()
save()
set_range()
set_resolution()

データメンバー
allowed_range: [ 2. 20.]
allowed_resolution: [0.01 0.2 ]
map_type: SPATIAL_MAP_TYPE.FUSED_POINT_CLOUD
max_memory_usage: 2048
range_meter: 0.0
resolution_meter: 0.019999999552965164
reverse_vertex_order: False
save_texture: False
stability_counter: 0.0
use_chunk_only: True

```
import pysed.sl as sl
help(sl.SpatialMappingParameters)
```
と入力することで、このクラスのドキュメントを読むことができる。

```
class SpatialMappingParameters(builtins.object)
 |  Methods defined here:
 |  
 |  __reduce__ = __reduce_cython__(...)
 |      SpatialMappingParameters.__reduce_cython__(self)
 |  
 |  __setstate__ = __setstate_cython__(...)
 |      SpatialMappingParameters.__setstate_cython__(self, __pyx_state)
 |  
 |  get_range_preset(self, mapping_range=<MAPPING_RANGE.AUTO: 3>) -> 'float'
 |      SpatialMappingParameters.get_range_preset(self, mapping_range=MAPPING_RANGE.AUTO) -> float
 |  
 |  get_recommended_range(self, resolution, py_cam: 'Camera') -> 'float'
 |      SpatialMappingParameters.get_recommended_range(self, resolution, Camera py_cam: Camera) -> float
 |  
 |  get_resolution_preset(self, resolution=<MAPPING_RESOLUTION.HIGH: 0>) -> 'float'
 |      SpatialMappingParameters.get_resolution_preset(self, resolution=MAPPING_RESOLUTION.HIGH) -> float
 |  
 |  load(self, filename: 'str') -> 'bool'
 |      SpatialMappingParameters.load(self, str filename: str) -> bool
 |  
 |  save(self, filename: 'str') -> 'bool'
 |      SpatialMappingParameters.save(self, str filename: str) -> bool
 |  
 |  set_range(self, mapping_range=<MAPPING_RANGE.AUTO: 3>) -> 'None'
 |      SpatialMappingParameters.set_range(self, mapping_range=MAPPING_RANGE.AUTO) -> None
 |  
 |  set_resolution(self, resolution=<MAPPING_RESOLUTION.HIGH: 0>) -> 'None'
 |      SpatialMappingParameters.set_resolution(self, resolution=MAPPING_RESOLUTION.HIGH) -> None
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  allowed_range
 |      SpatialMappingParameters.allowed_range: np.array[float]
 |  
 |  allowed_resolution
 |      SpatialMappingParameters.allowed_resolution: np.array[float]
 |  
 |  map_type
 |      SpatialMappingParameters.map_type: SPATIAL_MAP_TYPE
 |  
 |  max_memory_usage
 |      SpatialMappingParameters.max_memory_usage: int
 |  
 |  range_meter
 |      SpatialMappingParameters.range_meter: float
 |  
 |  resolution_meter
 |      SpatialMappingParameters.resolution_meter: float
 |  
 |  reverse_vertex_order
 |      SpatialMappingParameters.reverse_vertex_order: bool
 |  
 |  save_texture
 |      SpatialMappingParameters.save_texture: bool
 |  
 |  stability_counter
 |      SpatialMappingParameters.stability_counter: int
 |  
 |  use_chunk_only
 |      SpatialMappingParameters.use_chunk_only: bool
```


## まだ十分には理解できていないこと
- 着目領域を絞り込んで点群・メッシュを得る方法
- カメラを移動させて、物体をいろんな側面から見てモデルを作る方法