Genesisで東京タワーの点群データを表示させてみた！！！

# はじめに
こんにちは、しゅんです。

「転スラ」のリムル様の移動シミュレーションに苦戦している中で、「点群データを表示できたら面白いかも！」と思い立ち、東京タワーの点群データをGenesisで可視化してみることにしました。

「転スラ」のリムル様の移動については前回の記事へ

https://qiita.com/syun88/items/906f80fe9d27530ffa6d


今回はその経緯と、実際に表示させるまでの手順をご紹介します！

## 使用したオープンデータ
この記事では、**東京都デジタルツイン実現プロジェクト 区部点群データ**を使用しています。このデータはオープンソースとして提供されており、以下のリンクからダウンロードできます：

[東京都デジタルツイン実現プロジェクト - 区部点群データ](https://www.geospatial.jp/ckan/dataset/tokyopc-23ku-2024/resource/7807d6d1-29f3-4b36-b0c8-f7aa0ea2cff3)

※ データは `.las` ファイル形式で提供されており、東京都区部全域の詳細な点群データが含まれています。


## 必要な準備
この記事の内容を実行するには以下の環境はもう詳しく説明しません

- [laspy](https://laspy.readthedocs.io/)（点群データを扱うライブラリ）

まず、`laspy` をインストールしましょう：

```bash
pip install laspy
```


## 実現したいこと
点群データ（`.las` ファイル）を読み込み、Genesisの仮想シミュレーション環境に表示します。  
データの例として東京タワー周辺の点群データを使用し、以下のようなステップで進めます：

1. 点群データの読み込みと簡単な可視化（2D/3Dプロット）
2. データをGenesisのPlane上に整列
3. 仮想空間でリアルタイム描画


## 最初の確認：点群データの読み込みと概要表示

点群データ（`.las` ファイル）を読み込み、その基本的な情報を確認します。

以下のコードでは、データの総数や座標範囲を表示します：

```python
import laspy

# サンプルファイルのパスを指定
file_path = "/path/to/your/las/file.las"

# LASファイルを読み込む
las = laspy.read(file_path)

# 点群データの概要を表示
print(f"点群の総数: {len(las.x)}")
print(f"X座標範囲: {las.x.min()} - {las.x.max()}")
print(f"Y座標範囲: {las.y.min()} - {las.y.max()}")
print(f"Z座標範囲: {las.z.min()} - {las.z.max()}")
```

---

## 2D/3Dプロットで点群データを確認

次に、Matplotlibを使って点群データを2Dおよび3Dでプロットしてみます。

### 2Dプロット
```python
import matplotlib.pyplot as plt

# サンプリング（データ量が多い場合に適用）
sample_rate = 100  # 100分の1をプロット
x_sampled = las.x[::sample_rate]
y_sampled = las.y[::sample_rate]
z_sampled = las.z[::sample_rate]

plt.figure(figsize=(10, 8))
plt.scatter(x_sampled, y_sampled, c=z_sampled, cmap="viridis", s=0.1)
plt.colorbar(label="Height (Z)")
plt.xlabel("X Coordinate")
plt.ylabel("Y Coordinate")
plt.title("2D Projection of Point Cloud")
plt.show()
```

### 3Dプロット
```python
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(12, 10))
ax = fig.add_subplot(111, projection='3d')

ax.scatter(x_sampled, y_sampled, z_sampled, c=z_sampled, cmap="viridis", s=0.1)
ax.set_xlabel("X Coordinate")
ax.set_ylabel("Y Coordinate")
ax.set_zlabel("Z Coordinate")
ax.set_title("3D Visualization of Point Cloud")
plt.show()
```

---

## 最終目標：Genesisでのリアルタイム描画

次に、点群データをGenesisのPlane上に整列し、リアルタイムで描画します。

### 最終版コード
以下が完成版コードです：

```python

import os
import numpy as np
import laspy
import genesis as gs

# 初期化
gs.init(seed=0, precision='32', logging_level='debug', backend=gs.cpu)

# シーンの作成
scene = gs.Scene(show_viewer=True)

# 地面を追加（無限 Plane）
plane = scene.add_entity(
    gs.morphs.Plane(
        pos=(0.0, 0.0, 0.0),  # 原点に配置
    ),
    material=gs.materials.Rigid(
        rho=1000,
        friction=0.5
    )
)

# LASファイルを読み込むフォルダ
folder_path = "/media/syun/ssd02/python_learning/Genesis/tokyo_project/data"

# 全点群データを格納するリスト
all_points = []

# フォルダ内の全ての`.las`ファイルを処理
for root, dirs, files in os.walk(folder_path):
    for file in files:
        if file.endswith(".las"):
            file_path = os.path.join(root, file)
            print(f"Loading {file_path}...")
            las = laspy.read(file_path)
            
            # 点群データをサンプリングしてリストに追加
            sample_rate = 1  # 必要に応じて調整 1 すべての点を取得できます。
            x_sampled = las.x[::sample_rate]
            y_sampled = las.y[::sample_rate]
            z_sampled = las.z[::sample_rate]
            
            points = np.column_stack((x_sampled, y_sampled, z_sampled))
            all_points.append(points)

# 全ての点群を一つの配列に統合
all_points = np.vstack(all_points)
print(f"Total points: {len(all_points)}")

# 点群の範囲を取得
min_coords = np.min(all_points, axis=0)  # x, y, z の最小値
max_coords = np.max(all_points, axis=0)  # x, y, z の最大値
print(f"Point cloud bounds: min={min_coords}, max={max_coords}")

# 点群を原点に合わせる（Plane 上に配置）
all_points[:, :2] -= (min_coords[:2] + max_coords[:2]) / 2  # x, y を中心に移動
all_points[:, 2] -= min_coords[2]  # z を地面に揃える

# シーンを構築
scene.build()

# 点群を描画
scene.draw_debug_points(
    poss=all_points,
    # colors=(0.5, 0.5, 1.0, 0.8)  # RGBAカラー指定　でデフォルト設定は赤
)

# シミュレーションを実行
scene.reset()
while True:
    scene.step()

```


## 結果
上記コードを実行すると、点群データがGenesisのPlane上に正しく表示されます。赤い点群が、東京タワーの形状をリアルタイムで描画していることが確認できます。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Genesisで東京タワーの点群データを表示させてみた！！！ <a href="https://t.co/ObuzvbIuHz">pic.twitter.com/ObuzvbIuHz</a></p>&mdash; SYUN (@syun88AI) <a href="https://twitter.com/syun88AI/status/1875885753718477032?ref_src=twsrc%5Etfw">January 5, 2025</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 


## おわりに
今回は、Genesisを使って点群データを表示させる手法を紹介しました。このように、意外と簡単にできます。 LiDARも応用できるのでは？？？では最後まで見てくれてありがとうございます。