はじめに
最近本業でROS2を使ったロボットの開発を始めたので、夏休みの間に自分でもLiDARやROS2の扱いに慣れようと思ってUnitree LiDAR L2を買いました。
Aliexpressで買ったのですが、日本円で5万円台の激安3D LiDARです。
(安くてそこそこ高精度と評価の高いLivox Mid-360は安いとは言っても10万円ほどするので、個人が趣味で買うにはちょっと躊躇します。)
セットアップ方法は公式のUnilidar SKD2で説明されているのですが、細部まで記載されておらずちょっとハマったので自分がRviz2で点群データを確認できるところまでセットアップした流れを紹介します。
今回もいつものごとく、ハマったらClaude Codeに助けてもらっています。![]()
前提条件
- Ubuntu 20.04/22.04
- ROS2 Humble
- PCL-1.10
- LiDAR IP: 192.168.1.62 <-出荷時の初期IPのようです。
- ユーザーが
dialoutグループに所属していること
# dialoutグループの確認
groups
# 必要に応じて追加
sudo usermod -a -G dialout $USER
1. Unilidar SDK2の入手
cd ~
git clone https://github.com/unitreerobotics/unilidar_sdk2.git
cd unilidar_sdk2
2. UDP(イーサネット)接続での設定
2.1 ネットワーク設定の確認
LiDARのデフォルトIP(192.168.1.62)に接続できるよう、ローカルIPを設定します。
# 現在のIP設定確認
ip addr show
# LiDARとの接続確認
ping -c 3 192.168.1.62
2.2 UDP接続用ファイル修正
// 修正前
std::string local_ip = "192.168.1.2";
unsigned short local_port = 6201;
// 修正後(環境に合わせて調整)
std::string local_ip = "192.168.1.3"; // 実際のローカルIPに変更
unsigned short local_port = 6202; // ポート競合を回避
# UDP接続用設定
def generate_launch_description():
node1 = Node(
parameters= [
{'initialize_type': 2}, # UDP通信
{'local_ip': '192.168.1.3'}, # 実際のローカルIPに変更
{'local_port': 6203}, # ポート競合を回避
]
)
2.3 UDP接続でのビルドと実行
# C++ SDKのテスト
cd unilidar_sdk2/unitree_lidar_sdk/build
cmake .. && make -j2
cd ..
./bin/example_lidar_udp
# ROS2パッケージでの実行
cd unilidar_sdk2/unitree_lidar_ros2
colcon build
source /opt/ros/humble/setup.bash
source install/setup.bash
ros2 launch unitree_lidar_ros2 launch.py # unitree lidarのROS2パッケージとRviz2が同時に起動します。
source /opt/ros/humble/setup.bash と source install/setup.bash は ~/.bashrcに追記しておくと毎回ターミナルを立ち上げるたびに実行しなくて済みます。
3. (必要に応じて)シリアルポート接続での設定
3.1 LiDARをシリアルモードに切り替え
重要: LiDARは工場出荷時にEthernetケーブルを使用するUDPモードで設定されているため、付属のUSB-Cケーブルで接続できるようにするにはまずUDP接続でシリアルモードに変更する必要があります。
cd unilidar_sdk2/unitree_lidar_sdk
./bin/set_to_serial_mode
3.2 シリアルポート用ファイル修正
# シリアル接続用設定
def generate_launch_description():
node1 = Node(
parameters= [
{'initialize_type': 1}, # シリアル通信
{'serial_port': '/dev/ttyACM0'}, # シリアルポートデバイス
{'baudrate': 4000000}, # ボーレート設定
]
)
3.3 シリアルポートデバイスの確認
# シリアルポートデバイスの確認
ls -la /dev/ttyACM*
ls -la /dev/ttyUSB*
# 権限確認(dialoutグループに所属していることを確認)
groups
3.4 シリアル接続でのテストと実行
重要: シリアル通信では、LiDAR電源投入後に毎回C++ SDKでのテストが必要です。
# 1. C++ SDKでのシリアル接続テスト(L2の電源投入後には必須)
cd unitree_lidar_sdk
./bin/example_lidar_serial
# 2. ROS2パッケージでの実行(シリアルテスト成功後)
cd unitree_lidar_ros2
colcon build
source /opt/ros/humble/setup.bash
source install/setup.bash
ros2 launch unitree_lidar_ros2 launch.py
3.5 シリアル通信でのC++ SDKテスト不要化
電源投入毎にC++ SDKテストが必要な原因は、ROS2ノードの初期化処理に重要なステップが不足しているためです。
ROS2ノードで不足している処理:
-
startLidarRotation()- LiDARモーター回転開始 -
resetLidar()- デバイスリセット - コマンド間の適切な待機時間(1秒)
以下の修正を実施することで、C++ SDKテストの実行コマンドを省略(厳密にはunitree lidarのROS2パッケージとRviz2の起動と同時に上記の処理を実行する)できます。
3.5.1. unilidar_sdk2/unitree_lidar_ros2/src/unitree_lidar_ros2/launch/launch.pyの修正
# 動作モード修正前
def generate_launch_description():
node1 = Node(
parameters= [
{'work_mode': 0},
]
# 動作モード修正後
def generate_launch_description():
node1 = Node(
parameters= [
{'work_mode': 8},
]
3.5.2. unilidar_sdk2/unitree_lidar_ros2/src/unitree_lidar_ros2/include/unitree_lidar_ros2.hの149行目付近に追記:
lsdk_->setLidarWorkMode(work_mode_);
// シリアル通信用の追加初期化処理
if (initialize_type_ == 1) { // シリアルモードのみ
lsdk_->startLidarRotation();
std::this_thread::sleep_for(std::chrono::seconds(1));
lsdk_->resetLidar();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
修正後に下記を実行
cd unitree_lidar_ros2
colcon build
source /opt/ros/humble/setup.bash
source install/setup.bash
ros2 launch unitree_lidar_ros2 launch.py
4. Rviz2での可視化
4.1 Rviz2の起動
# 自動でRviz2も起動される(launch.pyに含まれている)
ros2 launch unitree_lidar_ros2 launch.py
# または個別で起動
source /opt/ros/humble/setup.bash
rviz2 -d install/unitree_lidar_ros2/share/unitree_lidar_ros2/view.rviz
4.2 トピック確認
# 利用可能なトピックの確認
ros2 topic list
# 期待されるトピック
# /unilidar/cloud (sensor_msgs/msg/PointCloud2)
# /unilidar/imu (sensor_msgs/msg/Imu)
# トピック情報の確認
ros2 topic info /unilidar/cloud
ros2 topic info /unilidar/imu
# データ頻度の確認
ros2 topic hz /unilidar/cloud
ros2 topic hz /unilidar/imu
5. 動作モードの設定
LiDARの動作モードはuint32_tの各ビットで制御されます:
| ビット位置 | 機能 | 値0 | 値1 |
|---|---|---|---|
| 0 | FOV切り替え | 標準FOV (180°) | 広角FOV (192°) |
| 1 | 測定モード | 3D測定モード | 2D測定モード |
| 2 | IMU有効化 | IMU有効 | IMU無効 |
| 3 | 通信モード | イーサネットモード | シリアルモード |
| 4 | 起動モード | 電源投入時自動開始 | 電源投入時待機 |
// 例:シリアル通信 + 3D + IMU有効 + 自動開始
uint32_t workMode = 8; // ビット3のみ1(シリアルモード)
// 例:UDP通信 + 3D + IMU有効 + 自動開始
uint32_t workMode = 0; // すべて0(デフォルト)
5.1 ROS2での動作モード設定
# work_modeパラメータで設定(デフォルト値:0)
{'work_mode': 0}, # UDP通信 + 3D + IMU有効 + 自動開始
# 例:シリアル通信 + 2D測定モード + IMU無効
{'work_mode': 14}, # ビット1,2,3 = 1 (2D + IMU無効 + シリアル)
# 例:UDP通信 + 広角FOV + 3D測定
{'work_mode': 1}, # ビット0 = 1 (広角FOV)
5.2 C++ SDKでの動作モード設定
// setWorkModeメソッドで設定
unitree_lidar_sdk::UnitreeLidarReader lidar_reader;
uint32_t work_mode = 0; // 設定したいモード値
// 接続後にモード設定を実行
lidar_reader.setWorkMode(work_mode);
5.3 動作モード設定の適用方法
# 1. ROS2での設定変更
# launch.pyのwork_modeパラメータを編集後、再起動
cd unilidar_sdk2/unitree_lidar_ros2
colcon build
source install/setup.bash
ros2 launch unitree_lidar_ros2 launch.py
# 2. C++ SDKでの設定変更
# ソースコード編集後、リビルドして実行
cd unilidar_sdk2/unitree_lidar_sdk/build
cmake .. && make -j2
cd ..
./bin/example_lidar_udp
6. トラブルシューティング
6.1 UDP接続の問題
# ポート使用状況の確認
sudo netstat -tuln | grep 6201
# ファイアウォール設定の確認
sudo ufw status
# LiDAR接続確認
ping -c 3 192.168.1.62
6.2 シリアル接続の問題
# シリアルデバイスの確認
dmesg | grep ttyACM
ls -la /dev/ttyACM*
# 権限の確認
groups
ls -la /dev/ttyACM0
# 必要に応じて権限追加
sudo chmod 666 /dev/ttyACM0
6.3 ROS2の問題
# ROS2デーモンのリスタート
ros2 daemon stop
ros2 daemon start
# ノードの確認
ros2 node list
# パッケージの再ビルド
colcon build --packages-select unitree_lidar_ros2
7. 座標系とデータフォーマット
7.1 座標系定義
- LiDAR座標系: 右手座標系、原点は底面マウント部中央
- IMU座標系: LiDAR座標系に対して平行移動のみ
-
変換行列: LiDARからIMUへの変換は
[-0.007698, -0.014655, 0.00667]の平行移動
↓はUnitree 4D LiDAR L2 User Manualからの引用です。

7.2 データ仕様
- 点群データ: 18リング構成、最大100m測定範囲
- IMUデータ: 6軸(加速度・角速度)+ クォータニオン
-
フレーム名:
unilidar_lidar(点群),unilidar_imu(IMU)
8. 設定ファイルの保存場所
修正が必要な主要ファイル:
-
unilidar_sdk2/unitree_lidar_sdk/examples/example_lidar_udp.cpp- UDP接続設定 -
unilidar_sdk2/unitree_lidar_ros2/src/unitree_lidar_ros2/launch/launch.py- ROS2起動設定 -
unilidar_sdk2/unitree_lidar_ros2/src/unitree_lidar_ros2/rviz/view.rviz- Rviz2設定
9.Docker化+ROS Bridge/Foxglove Bridge対応
ここまでの設定をローカル環境内で実施してもよいのですが、LiDARを持ち運び用のPCに接続して点群MAPを作成したりSLAMの実験を行うときには面倒な作業ですし、他のプログラムの環境に干渉する恐れもあります。
なので、Dockerコンテナ内でUnitree LiDAR L2を使えるようにしました。
ローカルネットワーク内の他のPCからもTOPICをPub/Subできるよう、ROS BridgeとFoxglove Bridgeも組み込んでいます。
必要なファイル類は公式からフォークした https://github.com/todateman/unilidar_sdk2 に反映しているので、もし必要なら利用してみてください。
9.1. Dockerコンテナを利用してUnitree L2 LiDARをWSL2のUbuntuで使用できるようにする
もし持ち運び可能なUbuntuマシンがなくWindowsマシンしかない場合は、WSL2でUbuntu22.04の環境を構築し、この環境でL2 LiDARを使用することができます。
WSL2でUbuntu22.04、git、Docker、Docker composeがセットアップできている前提です。
まずはWSL2からホストマシンのUSBデバイスを使えるようにするを参考に、ホストPC(WindowsPC)で接続したUnitree L2 LiDARをWSL2側にマウントさせます。
# まずはWindows側で認識しているUSBデバイスを確認
> usbipd list
Connected:
BUSID VID:PID DEVICE STATE
1-3 04f2:b760 HP Wide Vision HD Camera, Camera DFU Device Not shared
1-4 04f3:0c00 ELAN WBF Fingerprint Sensor Not shared
2-1 1a86:55d3 USB-Enhanced-SERIAL CH343 (COM4) Not shared
2-3 0489:e0f2 MediaTek Bluetooth Adapter Not shared
usbipd: warning: USB filter 'USBPcap' is known to be incompatible with this software; 'bind --force' will be required.
# L2 LiDAR のBUS ID(2-1)をWSL2とシェアする
> usbipd bind --busid 2-1
usbipd: warning: USB filter 'USBPcap' is known to be incompatible with this software; 'bind --force' will be required.
> usbipd list
Connected:
BUSID VID:PID DEVICE STATE
1-3 04f2:b760 HP Wide Vision HD Camera, Camera DFU Device Not shared
1-4 04f3:0c00 ELAN WBF Fingerprint Sensor Not shared
2-1 1a86:55d3 USB-Enhanced-SERIAL CH343 (COM4) Shared
2-3 0489:e0f2 MediaTek Bluetooth Adapter Not shared
usbipd: warning: USB filter 'USBPcap' is known to be incompatible with this software; 'bind --force' will be required.
# L2 LiDAR のBUS ID(2-1)をWSL2にアタッチする
> usbipd attach --wsl --busid 2-1
usbipd: info: Using WSL distribution 'Ubuntu-22.04' to attach; the device will be available in all WSL 2 distributions.
usbipd: info: Detected networking mode 'nat'.
usbipd: info: Using IP address 172.31.128.1 to reach the host.
> usbipd list
Connected:
BUSID VID:PID DEVICE STATE
1-3 04f2:b760 HP Wide Vision HD Camera, Camera DFU Device Not shared
1-4 04f3:0c00 ELAN WBF Fingerprint Sensor Not shared
2-1 1a86:55d3 USB-Enhanced-SERIAL CH343 (COM4) Attached
2-3 0489:e0f2 MediaTek Bluetooth Adapter Not shared
usbipd: warning: USB filter 'USBPcap' is known to be incompatible with this software; 'bind --force' will be required.
WSL2(Ubuntu)側で確認
# アタッチ前
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
# アタッチ後
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 1a86:55d3 QinHeng Electronics USB Single Serial
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
# 下記のコマンドでWSL2側で認識しているポート名が分かる
$ ls /dev/ttyACM*
/dev/ttyACM0
あとは https://github.com/todateman/unilidar_sdk2/ のリポジトリを
git clone https://github.com/todateman/unilidar_sdk2.git
でクローンして、README_DOCKER_JP.mdの内容に沿ってDockerコンテナを立ち上げれば、あっけなくWindowsPCのWSL2で実行しているUbuntuで実行したDockerコンテナでUnitree L2 LiDARから取得した点群データが確認できるはず。
![PXL_20250809_135931181[1].jpg](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F360166%2F228880b0-7d22-4483-9294-0ca6e2a236ff.jpeg?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=407b1327a5dbc09c25df88382f94d5d5)
