YDLIDARの環境構築および動作
https://gyazo.com/61ec15d317f30a0f80bc0dde3af5c476
概要
Ubuntu Server 22.04.4 LTSでYDLIDARの環境を構築しYDLIDAR T-MINI PROを動作させて値を取得することが目的の記事です。 当記事ではRaspberryPi4の中にUbuntu Serverを導入し構築しています。
使用する言語はPythonでAnaconda(miniforge3)での環境を構築します。 開発端末としてMacBook Air M1(2020)を使用しているためRaspberryPi <---> Macでの接続例になります。
作業時間の目安はインストール時間含め4時間くらいが目安です。
準備環境
当記事で使用する物
RaspberryPi4
RaspberryPi3でも動作しますが性能による差が出るかもしれません
映像出力するためのmicroHDMI-HDMIケーブル
MicroSD 16GB
できれば32GB 記事を書いている時になかったので16GBで代用しています
RaspberryPi4に繋げる電源ケーブルと充電器 20Wあれば良い
充電器の容量が20wよりも少ないと落ちてしまいます。 YDLIDARの電力供給分もあるので
映像出力先モニター
キーボードUSB接続のもの レシーバーがついてる無線式だとコードが邪魔にならず楽です
YDLIDAR本体
YDLIDAR通信用 Type-Cケーブル
YDLIDAR電源用 Micro USB Type-B
開発端末 MacBook
SDカードとLANケーブルが刺すことができるHUB
SSH、ソケット通信とOS書き込みのために使います
作業目次
Raspberry Pi4にUbuntuServerを導入
UbuntuをSDカードに書き込む
インターネット共有設定
ケーブルの接続
SSH
ローカルIPアドレスの固定
Ubuntu-Python環境構築
UbuntuServerに必要なライブラリを構築する
基本ライブラリのインストール
Cmakeの構築
YDLIDAR-SDKの構築
YDLIDARの動作
MacからPythonスクリプトを配置
実際に動かして値を確認する
Mac-Python環境構築
Macにソケット通信で値を取得
Mac,Ubuntu双方にサーバープログラムを配置
必要なライブラリを追加でインストール
取得した値をビジュアライズする
まとめ
活用について
感想
参考資料
hr.icon
Raspberry PI4にUbuntuServerを導入
Raspbarry Piを動かすためにOSを入れていきます。
UbuntuをSDカードに書き込む
簡単に書き込めるRaspberry Pi Imager
以下のリンクからImagerをインストール
MacOSになりますのでDownload for macOSを押してください
https://gyazo.com/5c3e654bea52eb0af4a7121614b7b737
右のdmgがダウンロードされるので、開いてRaspberyy Pi Imager.appをApplicationsフォルダに入れてください
https://gyazo.com/72ad9d6c83a9d87a12b48597eb722c4a
起動したら以下のような画面が開きます
Raspberry Piデバイスの部分は使用しているRaspberry Piに対応させたものを選択してください
https://gyazo.com/c165076418f841b5b98099051040d412https://gyazo.com/bb5a9fb2158d26d793c72cfb84f653b9
OSの選択では少し下に行くとOther general-purpose OSというところからUbuntuを選択する
選択したUbuntu Server 24.04 LTS (64-bit) を選択する
https://gyazo.com/4493f00ea1f3aefd3f0e3222e62e4867https://gyazo.com/6f9f2308a38ee2880b15612107c1b467https://gyazo.com/dc3190b43d947acd0a6e08c60279580d
ストレージの選択では挿しているSDカードが出ていると思うので選択します
https://gyazo.com/48a8effb9293fce237bbf580e90a716f
選択完了後インストール時の事前設定ができるので設定していく
次にを押して、設定を編集してください
https://gyazo.com/bbd419ecdfead503e5b2be866ac89971https://gyazo.com/3e151b2d2556ec92b2a35efafa84a48a
設定タブごとに説明します
一般
ホスト名、ユーザー名、ロケールを設定します
Wi-Fiは使用しないのでチェックボックスをはずしてOKです
それぞれパスワード等長すぎるとsudoコマンドを使う時とかSSH、rsnyc等を使用する時にめんどくさくなります
のであんまり気にしないのであれば短いく設定することをお勧めします
サービス
タブを一般からサービスに切り替えてSSHに関する設定をします
ここでは公開暗号鍵による設定はせずにパスワード認証をONにします
オプション
特に変えなくて良い
https://gyazo.com/fb09c926a17523b908ab5c4353af268dhttps://gyazo.com/fbb569d4f9b01b162b5d2e472de29e3ahttps://gyazo.com/769e3996a8b232c15e0f9b30330f3828
設定が終わったら保存を押してはいを押してください データがある場合は削除の問いがあるのではいを押してください
https://gyazo.com/614f5b12116b07b662c7c4c5b54590edhttps://gyazo.com/4d1098468845644a84b729ca8a06f017
パスワード求められたらそのまま入力して書き込みを始めてください
https://gyazo.com/4eb8e6e54821fc5d938eb44a69df20e4https://gyazo.com/1f561da3f26dda504b1881449d586d66
書き込みが終了したらRaspberry Piに挿します
インターネット共有設定
ここではRaspberry Piがネットワークに接続できるように設定していきます。
Wi-Fiを直接Raspberry Piに接続してもいいのですが、結局ソケット通信をLANケーブル経由で実現させるので同じ線でインターネットに接続できたら楽ですのでこの方法で行なっています。
仮にYDLIDARの値をLANケーブルではなくWi-Fi経由で送信する場合はローカルIPを固定すれば実現できます。
しかし、この有線LANの方法は出展する時や別の場所で検証する時、Wi-Fi環境がなかったりWi-Fi環境が変わったりする時、設定を変えなければならないということがほぼ起きないので、便利です。
Mac側設定
IP設定 設定→ネットワーク→Raspberry Piと接続しているLANデバイスを選択→右上の詳細ボタン→TCP/IP→IPv4の構成→手動に切り替える→IPアドレスを(192.168.2.1)に設定する→OKで確定させる
これでローカルIPのMac側の固定と構成が完了
https://gyazo.com/db6c76b0333ae11aecf875cc0277c980https://gyazo.com/ff394ceb98c177bd455636a4e450a6bc
インターネット共有設定 構成したネットワークをWi-Fi→Mac→Raspberry Piのような経路でネットワークを接続する。
いわゆるMacはWi-Fiのブリッジをしているイメージ
設定→一般→共有→インターネット共有→iボタン→
共有する接続経路→Macがネット接続してる端末 EthernetかWi-Fiだと思う
共有先のデバイスはRaspberryPi on Ubuntuと繋がってるLANのデバイスの事
https://gyazo.com/62025def7c9cf7a410a92fe7bcd50a79https://gyazo.com/96715ea75697c498922e1ad0828224aehttps://gyazo.com/f9fda887410ee82730804376963eb48a
これで完了
ケーブルの接続
https://gyazo.com/2b930e57de5a5a0999750c9b36bbd04d
これでちゃんとSDカードが刺さっているか確認 キーボードを使うのならそのレシーバーやUSBを挿してください
最後に電源ケーブルを挿す!自動で電源が入ります。
スイッチとかはなく電源接続=電源スイッチを押すようなものなので、安易に挿したら挿し直しとか抜かないように気をつけてください。最悪の場合壊れるので。
https://gyazo.com/1437c639a389b0f11e9a3fc0c7fff3cf
起動に少々時間かかります
注意
なかなか、起動しなくて電源ケーブルを途中で抜いちゃうとリカバリーモードで起動しにくくなったりOS破壊につながるのでフリーズとかどうしようもなくなった最終手段以外ではしっかりシャットダウンして停止してから電源ケーブルを抜くことをお勧めします。
userの入力が求められると起動完了です。
いっぱい文字列がありますが dclab login:のように出てきたら起動完了です 画像では左下に出てきています。
注意
起動が終わっても loginが出てこない場合があります。その時は接続しているキーボードのEnterとか押したら出てきます。何も出てこなかったらおそらく起動途中です。
https://gyazo.com/39ebaac22f5f45c2fcc79bd5658279d1
こちらを設定したuserとpasswordでログインしてください
ログインができたら次に進みます
下の画像のようになればログインできています
https://gyazo.com/79e8dbd965db475f43c6938d6b7beb9a
起動途中でインターネット共有の設定をONにした場合などはネットワークが繋がらない場合がありますのでpingコマンドで導通してるかチェックします
$ ping 8.8.8.8
https://gyazo.com/f29ea9db89a4766b87c074f0485321fd
このように応答が帰ってくれば繋がっているのでOKです
停止方法はcontrol + Cで強制停止できます
もし応答が正常に帰ってこなければ
$ sudo shutdown -r now
で再起動してみてください。
どうしてもうまくいかない場合はRaspberry PiにWi-Fiを直接設定してあげるといいかもしれません。
SSHの設定
SSH、NETWORKの設定前に初回起動時のupdateおよびupgradeを行います
$ sudo apt update
$ sudo apt full-upgrade -y
フルでやっているので結構時間かかります。 -yのオプションは Y/nの入力を省くためで、手間が省けるので楽です
最後らへんに画面が紫色になって入力を求められますが求められたらEnter押せば良いです
$ sudo shutdown -r now
一旦再起動します
よくsudoコマンドを使うとpasswordを求められるのでその度に設定したパスワードを入力してください
https://gyazo.com/e133bedce61fbf3588a3c25436b63b52
また起動したら今度はこのままログインせず
https://gyazo.com/82030b1c251275d7129a1f749ffc4d4a
Macから接続します
$ ssh ユーザ名@ホスト名.local
参考例:
$ ssh dclab@dclab.local
でMacからRaspberryPiのUbuntuへリモート接続します。ここから先は基本的にMacから作業を行います。
https://gyazo.com/1445db0f077b3777a7212ba68644c6e1
yesで開始してください。
パスワードの入力が求められるので Raspberry Pi側のパスワードを入力してください
https://gyazo.com/a56ebe4ffd1b744be82896de87dcb18a
Mac側でこのターミナルの画面になれば接続完了です。
https://gyazo.com/1ae3ab5d47c79f1cc317446ceedb2dde
もしssh接続で以下のようなエラーが出た場合の対策を記します。
code:error
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
このエラーは前に同じユーザ名@ホスト名にアクセスしたことがあるが、リモート先コンピュータが初期化されたりして前のコンピュータとは異なる場合に出るものです。
$ ssh-keygen -R ホスト名
例:今回の場合は
$ ssh-keygen -R dclab.local
でリセットをかけてもう一度sshコマンドをやってみてください。
ローカルIPアドレスの固定
Mac端末からリモート接続ができたら、ソケット通信を行うためにローカルIPアドレスを固定していきます。
Ubuntuのネットワーク設定のファイルがある場所は
~/etc/netplan/にあります。
その中にネットワークの設定をyaml形式で記述することで固定ができます。
defaultにあるファイルは触らずに新規で設定ファイルを記述していきます。※以下に注意あり
$ sudo nano /etc/netplan/lan-connect.yaml
で開きましょう
code:lan-connect.yaml
network:
version: 2
renderer: networkd
ethernets:
eth0:
dhcp4: no
addresses:
- 192.168.2.2/24
nameservers:
addresses:
- 8.8.8.8
- 8.8.4.4
routes:
- to: default
via: 192.168.2.1
書き込めたら、
saveしたいときはcontrol+x→y→return →return
saveしないときは、上の手順のyをnでキャンセル
ネットワーク設定の適用は
$ sudo netplan apply
パーミッションのWARNINGが出たらchmodで設定
$ sudo chmod 600 /etc/netplan/lan-connect.yaml
もしWARNING:root:Cannot call Open vSwitch: ovsdb-server.service is not running.が出たら
$ sudo apt install openvswitch-switch
でインストールしてください。
それ以外のWARNINGが出たらその都度設定ファイルを見直してみてください。
エラー文を見ればおおよそ分かりますが、インデントとか重要なので手書きするとよく引っかかります。
もし
設定してあげると
$ ssh ユーザ名@192.168.2.2
例:
$ ssh dclab@192.168.2.2
でも接続できるよ!
導通確認
$ ping 192.168.2.1
192.168.2.1これはMacに設定しているローカルIPアドレス
$ ping 8.8.8.8
とかで正常に通信できることが確認できたらOK
もし正常にうまくいかない場合は、
$ sudo shutdown -r now
で再起動してください
もう一度確認してください
eth0はRaspberry Piのイーサネットの物理デバイス名なので、もし異なる場合は
$ ip addr
で名前を確認すればいいと思います。
https://gyazo.com/be7ae8a1c4e829a436831474faee64c7
注意
Defaultの場合50-cloud-init.yaml(場合によっては変化する)というファイルがありますが、OS自体がネットワークに合わせて書き込んで一時的に設定できても、環境が変わると変化し固定設定がなくなるという理由で、新規で別ファイルに記述します。
netplanの仕様として設定ファイルが複数あったとしてもアルファベット順に管理されており、読み込みがあとの方が適用されるようです。また、複数の設定内容があっても重複しなければ両方適用されるみたいです。今回の場合lan-connect.yamlの名前はちゃんと認識されるようです。任意の名前をつけたい場合はアルファベット順さえ気をつければ大丈夫です。
hr.icon
Ubuntu-Python環境構築
Anacondaの縮小版を導入します。あとに出てくるMac端末の環境構築もおんなじです。おんなじUNIX系なので基本的にコマンドは似ています。全部おんなじではありませんが、今回は人によって環境が違うだけで、使うコマンドは同じです。
miniforge(conda, python環境導入)
$ echo $SHELL
これで出てきたSHELLに対応させてください
/bin/bash
$ bash Miniforge3-$(uname)-$(uname -m).sh
/bin/zsh
$ zsh Miniforge3-$(uname)-$(uname -m).sh
基本returnを連続で押してyes|noでyesでやってください
またreturn押したらインストールできると思います
https://gyazo.com/bc882a3bf74dd9acc9a5ab6add8da9f0
もししたの画像のようなメッセージが出たらyesで実行してください
https://gyazo.com/bad65c9463461ddc0771860f69e1fb4e
インストールがおわったら
bash
$ source ~/.bashrc
zsh
$ source ~/.zshrc
で読み込むと(base) dclab@dclab:のようにbaseが出てくると思いますこれで完了です
出てこなければ下のコマンドから起動してみてください
$ source ~/miniforge3/bin/activate
完了したら一応アップデートしてみてください
$ conda update -n base -c defaults conda
yesが求められたら yを入力して進んでください。
次に仮想環境を立てていきます
$ conda create -n py39 python=3.9
yesが求められたら yを入力して進んでください。
これでPython3.9で動作させることのできるpy39という名前の環境ができた
$ conda activate py39
で起動できます
Ubuntuの中ではこの環境をずっと使い続けるので
bashrcを編集し起動時に自動的に環境をアクティベートするようにする。
最初に使っているSHELLの設定ファイルを開く
bash
$ sudo nano ~/.bashrc
zsh
$ sudo nano ~/.zshrc
開いたら一番下に先ほどの起動コマンドを書き込む
https://gyazo.com/5413863b0a1a59ca57402c86f055935d
書き込めたら、
saveしたいときはcontrol+x→y→return →return
saveしないときは、上の手順のyをnでキャンセル
これで保存したら
bash
$ source ~/.bashrc
zsh
$ source ~/.zshrc
で読み込むと
(base)が環境名である(py39)に変わると思います
これで環境構築が終わりました続いていよいよ
YDLIDARを使うための構築をします
hr.icon
UbuntuServerに必要なライブラリを構築する
Mac端末からリモート接続ができたら、必要なライブラリのインストールおよび構築をしていきます。
CmakeとYDLIDAR-SDKの構築に非常に時間かかります。
ディレクトリ移動も含めて書いているので順に行えばそこまで難しいわけではないと思います。
sudoコマンドを使っているのでパスワードが求められたらその都度入力してあげてください。
基本ライブラリのインストール
$ cd ~/
$ sudo apt install -y git cmake pkg-config swig python3 python3-pip python3-setuptools build-essential libssl-dev
Cmakeの構築
$ tar xvfz cmake-3.29.3.tar.gz
$ cd cmake-3.29.3
$ ./bootstrap
$ make
$ cd ..
YDLIDAR-SDKの構築
$ conda install cmake setuptools
$ mkdir -p ~/YDLidar-SDK/build
$ cd ~/YDLidar-SDK/build
$ cmake .. -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX -DPYTHON_EXECUTABLE=$(which python)
$ make
$ make install
$ cd ../
$ pip3 install .
$ python3 setup.py build
$ python3 setup.py install
$ cd ~/
プログラムを配置する場所を作る
~/src
YDLIDAR_TEST
YDLIDAR_SOCKET
srcを作りその中に二つのディレクトリを作る
$ mkdir src src/YDLIDAR_TEST src/YDLIDAR_SOCKET
$
hr.icon
YDLIDARの動作
構築が完了したら値を取得してみます
私の環境ではMacの中~/src/YDLIDAR/YDLIDAR_TESTにプログラムを置いて VSCodeで書いています。
https://gyazo.com/9b4640d8d5563af5d89fa10977bcdbde
MacからPythonスクリプトを配置
実際に動作させるプログラムをMac端末からUbuntu端末へ送り配置させる。
Mac側のターミナル
$ rsync -avz -e ssh Mac側に置いてるプログラムのパス ユーザ名@固定してるローカルIP(ホスト名):Ubuntu内のプログラムを配置したい場所
例:
$ rsync -avz -e ssh ~/src/YDLIDAR/YDLIDAR_TEST/main.py dclab@192.168.2.2:~/src/YDLIDAR_TEST/
YDLIDAR_sample
Ubuntu側のコマンド
$ cd ~/src/YDLIDAR_TEST/
$ ls
で配置されたか確認できます。
code:main.py
import os
import math
import threading
import ydlidar
ydlidar.os_init()
ports = ydlidar.lidarPortList()
port = "/dev/ydlidar"
for key, value in ports.items():
port = value
laser = ydlidar.CYdLidar()
# T-mini-pro センサー定義
laser.setlidaropt(ydlidar.LidarPropSerialPort, port)
laser.setlidaropt(ydlidar.LidarPropSerialBaudrate, 230400)
laser.setlidaropt(ydlidar.LidarPropLidarType, ydlidar.TYPE_TRIANGLE)
laser.setlidaropt(ydlidar.LidarPropDeviceType, ydlidar.YDLIDAR_TYPE_SERIAL)
laser.setlidaropt(ydlidar.LidarPropSingleChannel, False)
# T-mini-proこのIntenstiyが無いとチェックサムに引っ掛かります
laser.setlidaropt(ydlidar.LidarPropIntenstiy, True)
# T-mini-pro センサー数値
laser.setlidaropt(ydlidar.LidarPropScanFrequency, 12.0) #6Hz~12Hz laser.setlidaropt(ydlidar.LidarPropSampleRate, 4) #不明 laser.setlidaropt(ydlidar.LidarPropMaxAngle, 180.0) #電源ランプ正面→左側 laser.setlidaropt(ydlidar.LidarPropMinAngle, -180.0) #電源ランプ正面→右側 laser.setlidaropt(ydlidar.LidarPropMaxRange, 12.0) #12.0m laser.setlidaropt(ydlidar.LidarPropMinRange, 0.02) #0.02m # 角度表記変換
def getdegree(angle):
degree = math.degrees(angle)
if degree < 0:
degree = 360 + degree
degree = int(degree)
return degree
# YDLidar稼働
def RunYDLidar():
ret = laser.initialize()
if ret:
ret = laser.turnOn()
scan = ydlidar.LaserScan()
while ret and ydlidar.os_isOk() :
r = laser.doProcessSimple(scan)
if r:
if scan.config.scan_time != 0.0:
for point in scan.points:
degree = getdegree(point.angle)
print("angle:", int(degree), " range: ", str(round(point.range, 5)), " Intensity: ", str(point.intensity))
else :
print("Failed to get Lidar Data")
laser.turnOff()
laser.disconnecting()
if __name__ == "__main__":
thread = threading.Thread(target=RunYDLidar, args=())
thread.start()
thread.join()
# RunYDLidar()
実際に動かして値を確認する
Pythonのプログラムを動かすには
Ubuntu側
$ cd ~/src/YDLIDAR_TEST/
$ python3 main.py
でできます。main.pyは適宜自分でつけたファイル名に書き換えてください
https://gyazo.com/195efa37cbb6f75299ad1ec173abc14a
このように値が取れたらOKです
hr.icon
Mac-Python環境構築
Anacondaの縮小版を導入します 先ほどのUbuntuの導入方法のMac版に書き換えたものになります。といってもおんなじです。おんなじUNIX系なんで基本的にコマンドは似ています。全部おんなじではありませんが、今回は人によって環境が違うだけで、使うコマンドは同じです。
miniforge(conda, python環境導入)
$ echo $SHELL
これで出てきたSHELLに対応させてください
/bin/bash
$ bash Miniforge3-$(uname)-$(uname -m).sh
/bin/zsh
$ zsh Miniforge3-$(uname)-$(uname -m).sh
基本returnを連続で押してyes|noでyesでやってください
またreturn押したらインストールできると思います
https://gyazo.com/bc882a3bf74dd9acc9a5ab6add8da9f0
もししたの画像のようなメッセージが出たらyesで実行してください
https://gyazo.com/bad65c9463461ddc0771860f69e1fb4e
インストールがおわったら
bash
$ source ~/.bashrc
zsh
$ source ~/.zshrc
で読み込むと(base) dclab@dclab:のようにbaseが出てくると思いますこれで完了です
出てこなければ下のコマンドから起動してみてください
$ source ~/miniforge3/bin/activate
完了したら一応アップデートしてみてください
$ conda update -n base -c defaults conda
yesが求められたら yを入力して進んでください。
次に仮想環境を立てていきます
$ conda create -n py39 python=3.9
yesが求められたら yを入力して進んでください。
これでPython3.9で動作させることのできるpy39という名前の環境ができた
$ conda activate py39
で起動できます
この先の設定はUbuntuでは行なったがMac側で別の開発してる時とか不便かもしれないのでUbuntu(Raspberry Pi)だけ設定するのをお勧めします
できるが 基本的にこの環境はずっと使い続けるので
bashrcを編集し起動時に自動的に環境をアクティベートするようにする。
最初に使っているSHELLの設定ファイルを開く
bash
$ sudo nano ~/.bashrc
zsh
$ sudo nano ~/.zshrc
開いたら一番下に先ほどの起動コマンドを書き込む
https://gyazo.com/5413863b0a1a59ca57402c86f055935d
書き込めたら、
saveしたいときはcontrol+x→y→return →return
saveしないときは、上の手順のyをnでキャンセル
これで保存したら
bash
$ source ~/.bashrc
zsh
$ source ~/.zshrc
で読み込むと
(base)が環境名である(py39)に変わると思います
これで環境構築が終わりました
hr.icon
Macにソケット通信で値を取得
Mac,Ubuntu双方にサーバープログラムを配置
配置するものを
プログラムで取得できているYDLIDARの値をSocket通信で送ってみます。
Mac側のターミナル
$ rsync -avz -e ssh Mac側に置いてるプログラムのパス ユーザ名@固定してるローカルIP(ホスト名):Ubuntu内のプログラムを配置したい場所
例:
$ rsync -avz -e ssh ~/src/YDLIDAR/YDLIDAR_SOCKET/main.py dclab@192.168.2.2:~/src/YDLIDAR_SOCKET/
Ubuntu側のコマンド
$ cd ~/src/YDLIDAR_SOCKET/
$ ls
で配置できたか確認できます
YDLIDAR_SOCKET.py
code:main.py
import os
import math
import socket
import threading
import csv
import time
import numpy as np
import ydlidar
# 環境変数
IP_ADDRESS = "192.168.2.2"
PORT = 12345
AVE_DATA = "averages.csv"
# 定数
CALIBRATION_DURATION = 10
ydlidar.os_init()
ports = ydlidar.lidarPortList()
port = "/dev/ydlidar"
for key, value in ports.items():
port = value
laser = ydlidar.CYdLidar()
# T-mini-pro センサー定義
laser.setlidaropt(ydlidar.LidarPropSerialPort, port)
laser.setlidaropt(ydlidar.LidarPropSerialBaudrate, 230400)
laser.setlidaropt(ydlidar.LidarPropLidarType, ydlidar.TYPE_TRIANGLE)
laser.setlidaropt(ydlidar.LidarPropDeviceType, ydlidar.YDLIDAR_TYPE_SERIAL)
laser.setlidaropt(ydlidar.LidarPropSingleChannel, False)
laser.setlidaropt(ydlidar.LidarPropIntenstiy, True)
laser.setlidaropt(ydlidar.LidarPropScanFrequency, 6.0) # 6Hz~12Hz
laser.setlidaropt(ydlidar.LidarPropSampleRate, 4) # 不明
laser.setlidaropt(ydlidar.LidarPropMaxAngle, 180.0) #電源ランプ正面→左側 laser.setlidaropt(ydlidar.LidarPropMinAngle, -180.0) # 電源ランプ正面→右側
laser.setlidaropt(ydlidar.LidarPropMaxRange, 12.0) # 12.0m
laser.setlidaropt(ydlidar.LidarPropMinRange, 0.02) # 0.02m
# 角度表記変換
def getdegree(angle):
degree = math.degrees(angle)
if degree < 0:
degree = 360 + degree
degree = int(degree)
return degree
# キャリブレーション
def YDLidar_Calibration():
ret = laser.initialize()
if ret:
ret = laser.turnOn()
scan = ydlidar.LaserScan()
# 360度の角度と距離を格納する配列
angle_distance_data = np.zeros((360, 2)) # 初期化
start_time = time.time()
print("10秒間スキャンを行います")
while ret and ydlidar.os_isOk() and (time.time() - start_time) < CALIBRATION_DURATION:
r = laser.doProcessSimple(scan)
if r:
for point in scan.points:
degree = getdegree(point.angle)
# print("angle:", int(degree), " range: ", str(round(point.range, 5)), " Intensity: ", str(point.intensity))
tmp_degree = degree
tmp_distance = round(point.range, 5)
else:
print("Failed to get Lidar Data")
laser.turnOff()
laser.disconnecting()
# 平均を計算
averages = np.zeros((360, 1))
for i in range(360):
if angle_distance_datai, 1 != 0: # ゼロ除算を防ぐ averagesi = angle_distance_datai, 0 / angle_distance_datai, 1 # 平均のCSVファイルに書き出し
output_filename = 'averages.csv'
with open(output_filename, 'w', newline='') as file:
writer = csv.writer(file)
for i in range(360):
writer.writerow([i, "{:.2f}".format(averagesi0)]) # 小数点以下2桁までの値を書き込む print(f"Averages saved to {output_filename}")
print("キャリブレーションが完了しました")
def run_lidar(connection):
std_data = {}
with open(AVE_DATA, 'r') as file:
reader = csv.DictReader(file)
count = 0
try:
ret = laser.initialize()
if ret:
ret = laser.turnOn()
scan = ydlidar.LaserScan()
while ret and ydlidar.os_isOk():
r = laser.doProcessSimple(scan)
if r:
# バッファリングするためのリスト
buffered_data = []
for point in scan.points:
degree = getdegree(point.angle)
distance = round(point.range, 5)
reference_distance = std_data.get(degree, 0)
if reference_distance and CENTER_DISTANCE <= distance < reference_distance - WALL_DISTANCE and 90 <= degree <= 270:
message = f"{int(count)}, {int(degree)}, {float(distance)}"
# print(message)
buffered_data.append(message)
count += 1
# バッファリングしたデータを一括で送信
try:
connection.sendall(('\n'.join(buffered_data) + '\n').encode())
except BrokenPipeError:
# クライアントが接続を切断した場合、ループを抜ける
print("クライアントが接続を切断しました。")
break
finally:
laser.turnOff()
laser.disconnecting()
connection.close()
# SocketServerSt.
def start_server():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((IP_ADDRESS, PORT))
server_socket.listen(1)
while True:
print("サーバーは接続を待っています...")
connection, client_address = server_socket.accept()
print(f"接続元: {client_address}")
lidar_thread = threading.Thread(target=run_lidar, args=(connection,))
lidar_thread.start()
lidar_thread.join()
if __name__ == "__main__":
user_input = input("キャリブレーションを行いますか? (y/n): ")
if user_input.lower() == 'y':
YDLidar_Calibration()
while user_input.lower() == 'y':
print("正常に成功しましたか?失敗した場合は再実行してください")
user_input = input("再実行しますか? (y/n): ")
if user_input.lower() == 'y':
YDLidar_Calibration()
print("サーバーを開始します")
start_server()
このプログラムはあくまで調整し壁位置をキャリブレーションしてから扱うようにしています。
壁位置の値を除外しできる限り人および物体の点群のみを送信するようにしています。
よりよう方法があればその方がいいですが時間が足りずこのようになっております。
また、このプログラムの通信方式はTCP通信であり、データの欠落を無くしてスムーズに動くようにしようと考えましたが、点群が多い(送信するデータ量が多い)と遅延してしまうためUDP通信の方が良いかもしれません。
プロジェクトの終了により未検証なのでどちらが良いかは分かりません。
Mac側でも準備します。
Mac側のYDLIDAR_SOCKETの同じ階層でいいので
dataplot.pyのファイルを作りましょう
code:dataplot.py
import numpy as np
import matplotlib.pyplot as plt
import socket
import threading
import time
from collections import deque
# プロットを更新する間隔(秒)
plot_interval = 0.1
# データの最大保持サイズ
max_data_size = 50
def plot_data():
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'})
while not exit_event.is_set(): # スレッド停止条件の設定
if len(degrees) >= 2:
ax.clear()
ax.scatter(np.radians(degrees), distances, c=colors, edgecolors='blue')
ax.set_theta_direction(-1) # 左回りに反転する
ax.set_rmax(5) # 中心からの最大距離を5mに設定
ax.set_rlabel_position(-22.5) # ラベルの位置を調整
plt.draw()
plt.pause(0.01)
time.sleep(plot_interval)
def start_client():
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('192.168.2.2', 12345))
try:
buffer = ""
while not exit_event.is_set(): # スレッド停止条件の設定
data = client_socket.recv(1024)
if not data:
break
buffer += data.decode()
while '\n' in buffer:
line, buffer = buffer.split('\n', 1)
if line:
parts = line.split(',')
if len(parts) == 3:
print("angle:", int(degree), " range: ", str(round(distance, 5)))
# データの追加
degrees.append(degree)
distances.append(distance)
# データのサイズが上限に達したら古いデータを削除
if len(degrees) > max_data_size:
degrees.popleft()
distances.popleft()
finally:
client_socket.close()
if __name__ == '__main__':
# データの格納用リスト
degrees = deque()
distances = deque()
exit_event = threading.Event() # スレッド停止条件を管理するイベント
# クライアントを開始
client_thread = threading.Thread(target=start_client)
client_thread.start()
# プロットを開始
plot_data()
# クライアントスレッドが終了するまで待機
client_thread.join()
必要なライブラリを追加でインストール
numpyが入っていないので
Ubuntu側で(py39)で環境に入っていることを確認し
環境に入れていなければ
$ conda activate py39
$ pip3 install numpy
Mac側では
$ conda activate py39
$ pip3 install numpy
$ pip3 install matplotlib
取得した値をビジュアライズする
Ubuntu側
$ cd ~/src/YDLIDAR_SOCKET/
$ python3 main.py
でできます。main.pyは適宜自分でつけたファイル名に書き換えてください
初回起動ではキャリブレーションが必要なようにしています。
動くものや人をできるだけ取り除いて壁の位置を取得します。
「サーバーを開始します」で待機状態に入ったら
Mac側
例:
$ cd ~/src/YDLIDAR/YDLIDAR_SOCKET/
$ python3 dataplot.py
これでビジュアライズされた人の位置が取れるはずです。
https://gyazo.com/e7a674827e7eb2f7e5eb1da46a510b7e
hr.icon
まとめ
活用について
今回の構築ではLANケーブルでの有線接続で成立させていますが、他にも方法があり
動作環境が変化しないのであれば部屋に通っているWi-FiでローカルIPを固定すれば実現可能です。
また環境が変化するが無線化を実現させたい場合はBluetooth用いて値を送信すれば実現できます。
がしかし、情報量の多さや遅延の関係上実現させるのに時間がかかるため、筆者は断念しました。
Socket通信で記述している方法は筆者が考えたものなので、値を送るだけならばSocet通信のクライアント側(Macのプログラム)をもっと完結しにて取り出してみるといいかもしれません。
そもそもRaspberry PiにUbuntuを入れてやるのではなくMacの中にUbuntuを導入できたらもっといいかもしれません。
感想
T-mini-proに関する情報があまりありませんでしたので、色々引っかかりエラーが出ました。結構つまづいたので誰かの役に立てたらいいなと思っています。
これでRaspberry PiのUbuntu運用の方法やコマンドラインの扱い方、Python環境構築、SSHなどなど学べることはたくさんありました。よく最初からやり直しで、構築から何度もやったので筆者は慣れてしまいましたが初めて触る人はなかなか苦戦するのではないかなと思います。
経験としてやっぱり最初は有線から作るべきだと思ったのと、SDカードの寿命でOSが飛びまくったのでちゃんと開発上気をつけるべき点は多かったかな。
本当はgitで色々作ったサンプルとか公開できるとよかったのですが、全然慣れていないので今回は記事からコピーする形式で公開しています。
なんだかんだ楽しかったので、これを見ている人がRaspberryPiとかPythonを好きになってくれると嬉しいです!
不明点があれば、どうぞ一番下にあるメールアドレスからご連絡ください。初心者なのでわからないこともありますが、できる限りはお答えします。
hr.icon
参考資料
Raspberry Piのセッティング
YDLIDAR関連
SSHやネットワーク関連
miniforgeの導入
hr.icon
筆者:的場 漱誠 (X21086)
メールアドレス:suinfo.dev@suinfocus.com