** pyqtgraph.plot( ) 

   --> 소스코드 보면, PlotWindow 객체 생성하여, plot( ) 실행함.

   --> PlotWindow ; graphicsWindows.py 내부에 정의됨.

          --> 소스코드보면, 내부적으로 QMainWindow 에 PlotWidget 을 사용하여 만들었다.

 

  ==> 결론적으로,  pyqtgraph.plot( ) 은 내부적으로 PlotWidget.plot( ) 을 실행하고,

                      GUI window는 pyqt의 QMainWindow 사용함.

 

 

 

 

** pyqt5 내에 pyqtgraph를 통합할때.  PlotWidget() 을 사용하자.

      -- PlotWidget() 은 내부적으로 GraphicWidget 을 상속받고, PlotItem() 의 메소드를 사용한다. 

 

      -- 즉,  PlotWidget() 초기화시에, parent 와 background 매개변수는 GraphicWidget 에서 사욯하고, 

             나머지 매개변수는 PlotItem() 으로 넘겨 사용됨. 

 

 

 

 

** pyqtgraph 에서 global configuration options 사용 예.   http://www.pyqtgraph.org/documentation/config_options.html

 

        ex1)  pg.setConfigOption('background', 'y')  # global configuration options

 

        ex2)  pg.setConfigOptions(background='w', foreground='b')  # key-value 형태로 여러개 인자 사용 가능. 

 

 

 

** numpy 를 사용하지 않아도, 간단한 그래프를 그릴수 있다.

 

 

 

** plot( ) 에 관하여...

    -- PlotWidget.plot( ) 사용시...

        --> 내부적으로 PlotItem.plot( ) 메소드를 사용함.

        ---> PlotItem.plot( ) 는 PlotDataItem 객체를 반환한다.

 

     ; plot( data ) 에서 사용하는 data 값은 list 혹은 numpy array 를 사용한다.

 

 

 

 

** 실제 차트 그리는 명령어는 아래 2가지 중 하나 사용하면됨.

 

pw.plot(x, y, pen='r') 

 

또는 

 

pdi = pw.plot()  # PlotDataItem obj 반환

pdi.setData(x, y, pen='g')

 

  ---> plot( ) 으로 차트그릴때, 내부적으로 setData( ) 를 사용하므로, 그냥 setData( ) 사용하는 습관이 좋을듯..... 

 

 



출처: https://freeprog.tistory.com/366?category=716617 [취미로 하는 프로그래밍 !!!]

 

 

 

# https://freeprog.tistory.com/366?category=716617

import pyqtgraph as pg
# import pyqtgraph.exporters
# import numpy as np

from PyQt5.QtWidgets import *


class MyMainWindow(QMainWindow):
    """
    QMainWindow 의 central widget 으로 pyqtgraph의 PlotWidget() 사용함.
    """
    def __init__(self):
        super().__init__()
        # pg.setConfigOption('background', 'y')  # global configuration options
        # pg.setConfigOptions(background='w')  # global configuration options
        # pg.setConfigOptions(background='w', foreground='b')  # key-value 형태로 여러개 인자 사용 가능.

        y = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
        x = range(0, 10)

        # pw = pg.PlotWidget(background='w', title="aaaa")
        pw = pg.PlotWidget(title="기본예제")  # title 매개변수는 내부적으로 PlotItem() 에서 사용됨.
        # pw = pg.PlotWidget()

        """
        ** 실제 차트 그리는 명령어는 아래 2가지 중 하나 사용하면됨.
        
        pw.plot(x, y, pen='r') 
        
        또는 
        
        pdi = pw.plot()  # PlotDataItem obj 반환
        pdi.setData(x, y, pen='g')
        """
        # pw.plot(x, y)
        # pw.plot(x, y, pen='r')  # plot() 메소드는 내부적으로 PlotItem 의 plot() 을 사용함.
        
        pdi = pw.plot()  # PlotDataItem obj 반환
        pdi.setData(x, y, pen='g')

        self.setCentralWidget(pw)  # pyqt5 와 pyqtgraph 연결.

        # self.setGeometry(300, 700, 350, 500)
        self.show()


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)

    mywin = MyMainWindow()

    sys.exit(app.exec_())

제 구매처 : https://www.aliexpress.com/item/4001253880158.html?spm=a2g0s.9042311.0.0.51cd4c4dFsfQSj&fbclid=IwAR1rvYLt_6CMDVgvjOSD-1njVUQhOB2RBI6-sXNhqkfqUt-XzrxOjSF72IM 

 

13.55US $ |laser radar 360 degree laser radar scanning distance measuring sensor diy wireless transmission infrared data transmi

Smarter Shopping, Better Living! Aliexpress.com

www.aliexpress.com

윗 제품을 한 번 사서 살려봤는데, 제 능력보다는 어떤 이가 어제 딱 성공을 해서 웹에 올려놓은 덕에 저도 따라서 베껴서 성공했습니다.

 

동영상 페북 링크 : https://www.facebook.com/permalink.php?story_fbid=4071094949677690&id=100003316754962&notif_id=1626497694343936&notif_t=feedback_reaction_generic&ref=notif 

 

로그인 또는 가입하여 보기

Facebook에서 게시물, 사진 등을 확인하세요.

www.facebook.com

 

 

 

중요한 내용 : 

     제품 마크 : Radar_MB_1R2T_V1.5.8  or V.1.5.9 <==  제품 밑에 반드시 이 마크가 있는 제품에 국한된 내용입니다.

     헤더 : AA 55 28 28

     시리얼 속도 : 153600

     처음 테스트용 라이다와 PC의 연결은 흔한 $2짜리 USB<=>UART 모듈을 사용하시면 됩니다.

     핀 연결 : 저기 속도 조정 핀은 연결 안해도 됩니다.   

     Serial은 3.3V

     전원은 5V

중요한 화일들 :  화일 이름은 편하게 각자 정하면 됩니다.  저는 my_lidar.py라고 부릅니다.

   이게 메인 Working Code입니다. 

 

   Credit : Vidicon from Discord, Subject : zRGJcqa, #radar_mb_1r2t

 

아래 코드는 matplotlib를 사용해서 너무 느려서, 아래 코드를 사용하지 말고  PyQtGraph 라이브러리를 사용해서 완전히 다시 만든 코드를 사용하십시요.   속도가 100배는 차이가 나는 것 같습니다. 제가 직접 PyQtGraph를 배워가며 만들었습니다.

엄청 빠른 새 코드는 다음 링크에 있습니다. https://wise-self.tistory.com/78?category=1044077

 

아래 코드는 그냥 구조를 보기 좋으니 데이타 구조가 어떤가를 보기용으로만 쓸만합니다.

주의사항은 serial 라이브러리 설치시 pip3 install pyserial 을 해야지, pip3 install serial을 하시면 안됩니다.  (중요)

#!/usr/bin/env python3
import matplotlib.pyplot as plt
import sys
import serial
import time
from enum import Enum
import math

SERIAL_PORT = "/dev/ttyUSB0"

class State(Enum):
	START1 = 0
	START2 = 1
	HEADER = 2
	DATA = 3


def readbytes(file, count):
	data = ser.read(count)
	if len(data) != count:
		print("End of file")
		return False
	return data


if __name__ == "__main__":
		
	try:
		ser = serial.Serial(SERIAL_PORT, 153600, timeout=0.1) 
	except:
		print("could not connect to device")
		exit()
	counter = 0
	rmax = 10.0
	
	dist = plt.subplot(111, polar = True)
	
	data_lenght = 0
	start_angle = 0
	stop_angle = 0


	run = True
	step = (-math.pi*2) 
	try:
		state = State.START1
		while run:

			if state == State.START1:
				data = ser.read(1)
				#if data == False:
				#	break
				if data[0] == 0xAA:
					state = State.START2
				# else:
					# print("sync")
				continue
			elif state == State.START2:
				data = ser.read(1)
				#if data == False:
				#	break
				if data[0] == 0x55:
					state = State.HEADER
				else:
					state = State.START1
					# print("sync2")
				continue
			elif state == State.HEADER:
				data = ser.read(8)
				pack_type = data[0]
				data_lenght = int(data[1])
				start_angle = int(data[3] << 8) + int(data[2])
				stop_angle = int(data[5] << 8) + int(data[4])
				#unknown = int(data[7] << 8) + int(data[6])

				diff = stop_angle - start_angle
				if stop_angle < start_angle:
					diff =  0xB400 - start_angle + stop_angle

				angle_per_sample = 0
				if diff > 1 and (data_lenght-1) > 0:
					angle_per_sample = diff / (data_lenght-1)
				
				# print("[{}]\ttype:{},\tlenght {},\tstart: {},\tstop: {}, \tdiff: {} \tdiff: {}".format(counter, pack_type, data_lenght, start_angle, stop_angle, diff, angle_per_sample), end="\n")
				
				counter += 1
				if pack_type != 40:
					counter = 0

				state = State.DATA
				continue
				
			elif state == State.DATA:
				state = State.START1
				#read data
				data = ser.read(data_lenght * 3)
				#data = readbytes(f, data_lenght * 3) 
				if data == False:
					break
		
				angle_list = []
				distance_list = []
				quality_list = []
		
				for i in range(0, data_lenght):
					
					data0 = int(data[i*3 + 0])
					data1 = int(data[i*3 + 1])
					data2 = int(data[i*3 + 2]) 
					distance = (data2  << 8) + data1

					angle = (start_angle + angle_per_sample * i)
					anglef = step * (angle / 0xB400) 
					angle_list.append(anglef)

					distance_list.append(distance / 1000) # div to convert mm to meter
					quality_list.append(data0) 

				
				if pack_type != 40:
					plt.cla()
					continue # package contance no data skip plot

				dist.scatter(angle_list, distance_list, c = "purple", s = 3) # dot
				# dist.plot(angle_list, distance_list, c = "purple") # line 
				dist.scatter(angle_list, quality_list, c = "red", s = 1)

				dist.set_theta_offset(math.pi / 2)
				dist.set_rmax(rmax)
				dist.set_rmin(0.0)
				plt.pause(0.01)
				rmax = dist.get_rmax()
				
			else:
				print("error")
	

	except KeyboardInterrupt:
		run = False
		exit()

최근에 물건을 3개를 더 받았는데 그 중 2개가 Radar_MB_1R2T_V1.5.8  이 아니고 Radar_MB_1R2T_V1.5.9 이었습니다.

그리고 그 중 1개는 윗 코드로는 작동을 안해서 원인을 찾아보니, 오는 신호에서 type 이 다른 제품들은 40이었는데 이 한개만 60번으로 나오더군요.   찾아낸 방법은 코드의 라인 84번의 #를 풀면 라이다에서 나오는 신호를 분석해서 스크린에 뿌려줍니다.

그래서 그 제품 하나는 따로 코드를 만들었습니다.  라인 87과 120에 type의 값을 40에서 60으로 바꿨더니 작동하더군요.

======================================================================

저번에 이 라이다의 문제를 해결한 이가 이 라이다의 ROS v.1용 드라이버도 완성했습니다. 현재는 초벌입니다.

 https://github.com/Vidicon/mb_1r2t_ros

 

GitHub - Vidicon/mb_1r2t_ros: ROS1 driver for the mb_1r2t lidar

ROS1 driver for the mb_1r2t lidar. Contribute to Vidicon/mb_1r2t_ros development by creating an account on GitHub.

github.com

 

+ Recent posts