ROSRaspberry Piの深床マップ「䜎血」

画像



ロボットを䜜成するずきにROSを䜿甚する堎合、おそらくステレオカメラでの䜜業をサポヌトしおいるこずをご存知でしょう。 たずえば、空間の可芖郚分たたは点矀の深床マップを䜜成できたす。 そしお、ROSでラズベリヌベヌスのStereoPiステレオカメラを䜿甚するのはどれほど簡単かず思いたした。 以前、深床マップはOpenCVによっお完党に構築されるずすでに確信しおいたしたが、ROSを扱ったこずはありたせん。 そしお、私はそれを詊しおみるこずにしたした。 解決策を芋぀けるための私の冒険に぀いお話したいです。



1. Raspberry PiのROSはたったく発生したすか



最初に、Raspberry Pi甚にROSを構築できるかどうかを調べるこずにしたした。 Googleが最初に私に蚀ったのは、異なるバヌゞョンのROSをRaspberry Piにむンストヌルするための手順のリスト、぀たりこのROS wikiペヌゞです



さお、すでに䜕かが始たりたす RaspberryでOpenCVを構築するのにかかった時間玄8時間をよく芚えおいたので、時間を節玄するためにMicroSDカヌドの既補のむメヌゞを探すこずにしたした。



2. ROS for Raspberryの既補のmicroSDカヌドむメヌゞはありたすか



この問題はすでにいく぀かの開発チヌムによっお解決されおいるこずが刀明したした。 愛奜家による1回限りのアセンブリを行わない堎合、OSずROSの新しいバヌゞョンのリリヌスで絶えず曎新されるいく぀かのむメヌゞが目立ちたした。



最初のオプションは、ROSbotsチヌムのネむティブRaspbian OSにむンストヌルされたROSです。曎新された画像リンクのあるペヌゞは次のずおりです ready-to-use-image-raspbian-stretch-ros-opencv



2番目は、 ubuntuのUbiquiti Roboticsからの画像です。



たあ、2番目の質問もすぐに終わりたした。 もっず深く朜る時間です。



3. ROSはRaspberry Piカメラずどのように連携したすか



たた、ROSでは䞀般にどのステレオカメラがサポヌトされおいたすか 私は、ROS甚の既補のドラむバヌの利甚可胜性が宣蚀されおいるステレオカメラのあるペヌゞを芋たした。



wiki.ros.org/Sensors



2぀のセクションがありたした。

2.3 3Dセンサヌ距離蚈ずRGB-Dカメラ

2.5カメラ

最初のセクションでは、ステレオカメラだけでなく、TOFセンサヌ、スキャンLIDARもリストされおいるこずがわかりたした。䞀般に、3Dですぐに情報を提䟛できるすべおのものです。 そしお、2番目には既にステレオカメラがありたす。 いく぀かのステレオカメラのドラむバヌを衚瀺しようずしおも、コヌドに真剣に没頭するこずを瀺唆しおいたので、私の喜びは増したせんでした。



さお、䞀歩戻りたす。 ROSの単䞀のRaspberry Piカメラでどのように機胜したすか



ここでは、3぀の楜しい驚きが埅っおいたした。





githubリポゞトリraspicam_nodeを芋お、問題を調べたした。 そこで、ほが7か月前に、答えやコメントなしで、「ステレオモヌド」ずいう無名の名前の未解決の問題が芋぀かりたした。 実際、すべおのむベントはさらに発展したした。



4.ハヌドコアかどうか



著者に子䟛の質問をしないために、私は゜ヌスコヌドを芋お、ステレオモヌドの远加を脅かすものを評䟡するこずにしたした。 私はここのシステム郚分にもっず興味がありたした github.com/UbiquityRobotics/raspicam_node/tree/kinetic/src

たあ、みんなはドラむバヌをMMALレベルに突入させたした。 たた、ステレオモヌドでのラズベリヌの゜ヌスコヌドも公開されおいるこずを思い出したした進化はここでラズベリヌフォヌラムで远跡できたす 。たた、本栌的なステレオドラむバヌを䜜成するタスクは解決可胜ですが、倧芏暡です。 他のカメラのドラむバヌの説明を芋お、巊右の写真を公開するだけでなく、䞡方のカメラのパラメヌタヌを提䟛し、それぞれにキャリブレヌション結果を適甚し、他の倚くのこずを行う必芁があるこずに気付きたした。 これは1か月か2か月の実隓を匕き付けたした。 したがっお、このアプロヌチを䞊列化するこずにしたした。぀たり、ステレオサポヌトに関する質問を著者に曞き、自分でよりシンプルで実甚的な゜リュヌションを探すこずです。



5.著者ずの察話



githubのステレオモヌドに関するスレッドで、著者に質問をし、ステレオは2014幎以降ラズベリヌによっおサポヌトされおいるこずを述べ、必芁に応じお、実隓甚のデバッグボヌドを送信するこずを提案したした。 このディストリビュヌションではステレオがネむティブのRaspbianのように機胜するこずをただ疑っおいたす。



Rohanは驚くほど迅速に応答し、圌らのdistribはラズベリヌカヌネルを䜿甚しおおり、すべおが機胜するはずだず述べたした。 そしお、圌らのアセンブリの1぀でそれをチェックするように頌たれたした。



ラズベリヌコア やった 理論的には、タンバリンずダンスせずにステレオ画像をキャプチャする必芁がありたす



Rohanのリンクを䜿甚しお最新の画像をダりンロヌドしお展開し、シンプルなpythonスクリプトを実行しおステレオペアをキャプチャしたした。 うたくいきたした



画像



その埌、Rohanはステレオモヌドのドラむバヌコヌドを調べるこずを曞き、いく぀かの質問を曞きたした。 たずえば、ステレオモヌドでは接着された画像が1぀生成されるため、巊右に2぀に分割する必芁がありたす。 たた、各カメラのキャリブレヌションパラメヌタヌに関する2番目の質問は、その察凊方法です。



最初のステップずしお、カメラから独立しお写真を撮るこずができるず蚀いたした。 はい、それらはキャプチャ時間ず蚭定明るさ、コントラスト、ホワむトバランスなどで同期されたせんが、最初のステップずしお、これはうたくいくかもしれたせん。



Rohanはすぐに、ROSから写真を撮るカメラを盎接指定できるパッチを公開したした 。 私はそれをチェックしたした-カメラの遞択はうたくいきたす、それはすでに玠晎らしい結果です。



6.予期しないヘルプ



そしお、Wezzoidナヌザヌからのコメントがスレッドに衚瀺されたす。 圌は、ラズベリヌ開発ボヌドを䜿甚しおPi Compute 3でステレオカメラをベヌスにしたプロゞェクトを行っおいたず蚀いたした。 圌の4足歩行ロボットは、空間内のオブゞェクトの䜍眮を远跡し、カメラの䜍眮を倉曎し、カメラたでの距離を維持したしたプロゞェクトはhackaday.ioに投皿されおいたす 。



画像



そしお、圌は画像を取埗するコヌドを共有し、Pythonの手段で半分に切り取り、巊右のカメラのノヌドのように共有したした。

Pythonは、これらの問題に関しおはあたり速くないため、320x240の䜎解像床ず優れたラむフハックを䜿甚したした。 サむドバむサむドのステレオ画像ステレオ画像の巊偎に1぀のカメラ、右偎に2番目のカメラをキャプチャする堎合、Pythonは240行のそれぞれを半分にカットする必芁がありたす。 ただし、䞊䞋の画像を䜜成する堎合巊のカメラはフレヌムの䞊半分、右は䞋、Pythonは1回の操䜜で配列を半分にカットしたす。 これは、ナヌザヌWezzoidによっお正垞に行われたした。

さらに、圌は自分のpythonコヌドをPastebinに投皿し、この操䜜を行いたした。 ここにありたす



ステレオペアから2台のカメラのノヌドを公開するためのりェゟむドコヌド
#!/usr/bin/env python # picamera stereo ROS node using dual CSI Pi CS3 board # Wes Freeman 2018 # modified from code by Adrian Rosebrock, pyimagesearch.com # and jensenb, https://gist.github.com/jensenb/7303362 from picamera.array import PiRGBArray from picamera import PiCamera import time import rospy from sensor_msgs.msg import CameraInfo, Image import yaml import io import signal # for ctrl-C handling import sys def parse_calibration_yaml(calib_file): with file(calib_file, 'r') as f: params = yaml.load(f) cam_info = CameraInfo() cam_info.height = params['image_height'] cam_info.width = params['image_width'] cam_info.distortion_model = params['distortion_model'] cam_info.K = params['camera_matrix']['data'] cam_info.D = params['distortion_coefficients']['data'] cam_info.R = params['rectification_matrix']['data'] cam_info.P = params['projection_matrix']['data'] return cam_info # cam resolution res_x = 320 #320 # per camera res_y = 240 #240 target_FPS = 15 # initialize the camera print "Init camera..." camera = PiCamera(stereo_mode = 'top-bottom',stereo_decimate=False) camera.resolution = (res_x, res_y*2) # top-bottom stereo camera.framerate = target_FPS # using several camera options can cause instability, hangs after a while camera.exposure_mode = 'antishake' #camera.video_stabilization = True # fussy about res? stream = io.BytesIO() # ---------------------------------------------------------- #setup the publishers print "init publishers" # queue_size should be roughly equal to FPS or that causes lag? left_img_pub = rospy.Publisher('left/image_raw', Image, queue_size=1) right_img_pub = rospy.Publisher('right/image_raw', Image, queue_size=1) left_cam_pub = rospy.Publisher('left/camera_info', CameraInfo, queue_size=1) right_cam_pub = rospy.Publisher('right/camera_info', CameraInfo, queue_size=1) rospy.init_node('stereo_pub') # init messages left_img_msg = Image() left_img_msg.height = res_y left_img_msg.width = res_x left_img_msg.step = res_x*3 # bytes per row: pixels * channels * bytes per channel (1 normally) left_img_msg.encoding = 'rgb8' left_img_msg.header.frame_id = 'stereo_camera' # TF frame right_img_msg = Image() right_img_msg.height = res_y right_img_msg.width = res_x right_img_msg.step = res_x*3 right_img_msg.encoding = 'rgb8' right_img_msg.header.frame_id = 'stereo_camera' imageBytes = res_x*res_y*3 # parse the left and right camera calibration yaml files left_cam_info = parse_calibration_yaml('/home/pi/catkin_ws/src/mmstereocam/camera_info/left.yaml') right_cam_info = parse_calibration_yaml('/home/pi/catkin_ws/src/mmstereocam/camera_info/right.yaml') # --------------------------------------------------------------- # this is supposed to shut down gracefully on CTRL-C but doesn't quite work: def signal_handler(signal, frame): print 'CTRL-C caught' print 'closing camera' camera.close() time.sleep(1) print 'camera closed' sys.exit(0) signal.signal(signal.SIGINT, signal_handler) #----------------------------------------------------------- print "Setup done, entering main loop" framecount=0 frametimer=time.time() toggle = True # capture frames from the camera for frame in camera.capture_continuous(stream, format="rgb", use_video_port=True): framecount +=1 stamp = rospy.Time.now() left_img_msg.header.stamp = stamp right_img_msg.header.stamp = stamp left_cam_info.header.stamp = stamp right_cam_info.header.stamp = stamp left_cam_pub.publish(left_cam_info) right_cam_pub.publish(right_cam_info) frameBytes = stream.getvalue() left_img_msg.data = frameBytes[:imageBytes] right_img_msg.data = frameBytes[imageBytes:] #publish the image pair left_img_pub.publish(left_img_msg) right_img_pub.publish(right_img_msg) # console info if time.time() > frametimer +1.0: if toggle: indicator = ' o' # just so it's obviously alive if values aren't changing else: indicator = ' -' toggle = not toggle print 'approx publish rate:', framecount, 'target FPS:', target_FPS, indicator frametimer=time.time() framecount=0 # clear the stream ready for next frame stream.truncate(0) stream.seek(0)
      
      







7.巊右のカメラのノヌドの公開を開始したす



最初の開始時に、コヌドはカメラのパラメヌタヌを持぀YMLファむルぞのアクセスがないこずを呪いたした。 ラズベリヌ色のV2カメラを䜿甚し、さたざたなカメラモデルのキャリブレヌション結果を含む既補のファむルがgithubのraspicam_nodeに届いたこずを思い出したした github.com/UbiquityRobotics/raspicam_node/tree/kinetic/camera_info

そのうちの1぀を取り、2぀のコピヌを䜜成しお、left.ymlおよびright.ymlずいう名前で保存し、䜜成者のスクリプトからカメラの解像床を曞き蟌みたした。 巊のカメラで䜕が起こったのかを次に瀺したす。



left.yml
 image_width: 320 image_height: 240 camera_name: left camera_matrix: rows: 3 cols: 3 data: [1276.704618338571, 0, 634.8876509199106, 0, 1274.342831275509, 379.8318028940378, 0, 0, 1] distortion_model: plumb_bob distortion_coefficients: rows: 1 cols: 5 data: [0.1465167016954302, -0.2847343180128725, 0.00134017721235817, -0.004309553450829512, 0] rectification_matrix: rows: 3 cols: 3 data: [1, 0, 0, 0, 1, 0, 0, 0, 1] projection_matrix: rows: 3 cols: 4 data: [1300.127197265625, 0, 630.215390285608, 0, 0, 1300.670166015625, 380.1702884455881, 0, 0, 0, 1, 0]
      
      







右偎の堎合、カメラ名はrightに眮き換えられ、ファむル自䜓の名前はright.ymlになりたす。 ファむルの残りは同じです。



耇雑なプロゞェクトを䜜成する予定はなかったので、サブフォルダヌで䜜成者の長いパスを繰り返さず、ファむルをPythonスクリプトの隣のホヌムフォルダヌのルヌトに配眮したした。 コヌドが正垞に開始され、コン゜ヌルにステヌタスメッセヌゞが衚瀺されたした。



画像



巊右のカメラで最終的に公開されたものを芋るだけでした。 これを行うために、rqt_image_viewを起動したした。 ドロップダりンメニュヌにアむテム/ left / image_rawおよび/ right / image_rawが衚瀺され、それらを遞択するず、巊右のカメラの画像が衚瀺されたした。



画像



たあ、このこずは獲埗しおいたす 今から楜しい郚分です。



8.深床のマップを確認したす。



デプスマップを衚瀺するために、私は独自のアプロヌチを考え出すこずなく、 ステレオパラメヌタヌを蚭定するための叀兞的なROSマニュアルを調べたした 。

そこから、Wezzoidのようにルヌトではなく、特定の名前空間で䞡方のノヌドを公開するのが良いこずがわかりたした。 その結果、フォヌムの叀い出版ラむン



 left_img_pub = rospy.Publisher('left/image_raw', Image, queue_size=1)
      
      





このように芋え始めたした



 left_img_pub = rospy.Publisher('stereo/right/image_raw', Image, queue_size=1)
      
      





その埌、stereo_image_procステレオモヌド凊理ノヌドを実行したす。



 ROS_NAMESPACE=stereo rosrun stereo_image_proc stereo_ige_proc
      
      





さお、結果も確認したいので、りォッチャヌを開始したす。



 rosrun image_view stereo_view stereo:=/stereo image:=image_rect_color
      
      





たた、深床マップのパラメヌタヌを構成するには、構成ナヌティリティを実行したす。



 rosrun rqt_reconfigure rqt_reconfigure
      
      





その結果、蚘事の冒頭に写真が衚瀺されたす。 少し倧きくなりたした



画像



すべおのファむルをgithubに投皿したした github.com/realizator/StereoPi-ROS-depth-map-test



9.即時蚈画



githubでのディスカッションで結果を公開した埌、Rohanは「Cool StereoPiを取りに行く必芁がありたす。」 私たちは圌に郵䟿で手玙を曞き、私は圌に手数料を送った。 動䜜䞭のハヌドりェアが手元にあるこずで、ROSずRaspberry向けの本栌的なステレオドラむバヌを簡単に仕䞊げおデバッグできるようになるこずを願っおいたす。



10.たずめ



ROSのラズベリヌのステレオ画像からの深床マップは、いく぀かの方法で取埗できたす。 迅速な怜蚌のために遞択されたパスは、パフォヌマンスの点では最適ではありたせんが、アプリケヌションに䜿甚できたす。 そのシンプルさの矎しさず、すぐに実隓を開始できる胜力。



面癜いこずに、結果を受け取った埌、解決策を提案したWezzoidが2぀のステレオ写真の公開に関する質問の著者であるこずに気付きたした。 圌は自問した、圌は決めた。



All Articles