Livox Mid-70 + Python

TL;DR

  1. Livox Mid-70 を購入したので確認
  2. 公式 SDK は C++ のみだが、plot とかもやりたかったので Python で try
  3. CRC32 + Handshake の cmd_type でハマったのでそちらも絡めて

背景

Livox Mid-70 の公式 SDK(Livox-SDK)は C/C++ のみ。購入後の動作確認を Python でサクッとやりたかったので、Wiki の Communication Protocol を見ながら UDP 通信を書いてみた。


はまりどころ 1: CRC32

Wiki にはこう書いてある:

crc32 initial value: 0x564F580A

素直にビットシフトで実装すると SDK と異なる値が出る。実際の SDK は CRC-32/ADCCP(標準 CRC32)を使っていて、内部で init ^ 0xFFFFFFFFresult ^ 0xFFFFFFFF が入る。

# NG
def calc_crc32(data: bytes) -> int:
    crc = 0x564F580A
    for b in data:
        crc ^= b
        for _ in range(8):
            crc = (crc >> 1) ^ 0xEDB88320 if (crc & 1) else (crc >> 1)
    return crc & 0xFFFFFFFF

# OK: binascii.crc32 が XOR を自動でやってくれる
import binascii

def calc_crc32(data: bytes) -> int:
    return binascii.crc32(data, 0x564F580A) & 0xFFFFFFFF

CRC16 は Wiki 通りで問題ない。CRC32 だけ罠。


はまりどころ 2: Handshake の cmd_type

通常コマンドは cmd_type=0x00(Request)だが、Handshake だけは cmd_type=0x01(ACK)で送る。Broadcast への応答という扱いらしい。SDK の実パケットを見て気づいた。

def make_handshake() -> bytes:
    ip = bytes(int(x) for x in PC_IP.split("."))
    payload = ip + struct.pack("<HHH", DATA_PORT, PC_CMD_PORT, DATA_PORT)
    return build_frame(0x00, 0x01, payload, cmd_type=0x01)  # ACK

動作した接続シーケンス

  1. Broadcast 受信 — port 55000
  2. Handshake — cmd_type=0x01, cmd_id=0x01, payload に IP + ポート。ret_code=0x00 を確認
  3. Heartbeat — cmd_id=0x03 で working_state=1 になるまでポーリング
  4. Start Sampling — cmd_id=0x04, payload=0x01
  5. 点群受信 — data_type=2 (Cartesian int32), 14bytes/point
  6. Heartbeat 維持 — 約 1 秒間隔(止めると LiDAR が再 Broadcast に戻る)

まとめ

Wiki だけだと少し足りないところがあり、特に CRC32 は SDK のソースを見ないと気づきにくい。同じことをやる人の参考になれば。

参考リンク

公式情報

あわせて読むと理解しやすい項目

この記事をシェア

2020-2026
弊社では、一緒に会社を面白くしてくれる仲間を募集しています。
お気軽にお問い合わせください!
P.S. よろしければこちらもどうぞ
新明工業クラシックカーレストア blog — クラシックカーのレストアのお仕事の一部を公開しています。
新明工業コンベア blog — コンベアに関する技術情報を発信しています。