def run_lidar():
	try:
		lidar = RPLidar(None,'/dev/ttyUSB0') #check usb port with dmesg
		while True:
			for scan in lidar.iter_scans():
				for(quality, angle, distance) in scan:
					if( angle >= 240 and angle <=300):	#center on 267.3, corrected on filter end
						print(",,,,,{:7.2f}, {:7.2f}".format(angle, distance))

	except KeyboardInterrupt:
		lidar.stop()
		lidar.clear_input()
		lidar.disconnect()
	finally:
		lidar.stop()
		lidar.disconnect()
Exemplo n.º 2
0
class RPLidar(object):
    '''
    https://github.com/adafruit/Adafruit_CircuitPython_RPLIDAR
    '''
    def __init__(self, lower_limit = 0, upper_limit = 360, debug=False):
        from adafruit_rplidar import RPLidar

        # Setup the RPLidar
        PORT_NAME = "/dev/ttyUSB0"

        import glob
        port_found = False
        self.lower_limit = lower_limit
        self.upper_limit = upper_limit
        temp_list = glob.glob ('/dev/ttyUSB*')
        result = []
        for a_port in temp_list:
            try:
                s = serial.Serial(a_port)
                s.close()
                result.append(a_port)
                port_found = True
            except serial.SerialException:
                pass
        if port_found:
            self.port = result[0]
            self.distances = [] #a list of distance measurements
            self.angles = [] # a list of angles corresponding to dist meas above
            self.lidar = RPLidar(None, self.port, timeout=3)
            self.lidar.clear_input()
            time.sleep(1)
            self.on = True
            #print(self.lidar.get_info())
            #print(self.lidar.get_health())
        else:
            print("No Lidar found")



    def update(self):
        scans = self.lidar.iter_scans(550)
        while self.on:
            try:
                for scan in scans:
                    self.distances = [item[2] for item in scan]
                    self.angles = [item[1] for item in scan]
            except serial.serialutil.SerialException:
                print('serial.serialutil.SerialException from Lidar. common when shutting down.')

    def run_threaded(self):
        sorted_distances = []
        if (self.angles != []) and (self.distances != []):
            angs = np.copy(self.angles)
            dists = np.copy(self.distances)

            filter_angs = angs[(angs > self.lower_limit) & (angs < self.upper_limit)]
            filter_dist = dists[(angs > self.lower_limit) & (angs < self.upper_limit)] #sorts distances based on angle values

            angles_ind = np.argsort(filter_angs)         # returns the indexes that sorts filter_angs
            if angles_ind != []:
                sorted_distances = np.argsort(filter_dist) # sorts distances based on angle indexes
        return sorted_distances


    def shutdown(self):
        self.on = False
        time.sleep(2)
        self.lidar.stop()
        self.lidar.stop_motor()
        self.lidar.disconnect()
Exemplo n.º 3
0
class proc_lidar():
    def __init__(self):
        # Setup the RPLidar, 라이다 센서 셋업
        PORT_NAME = '/dev/ttyUSB0'  # 포트네임 설정
        self.lidar = RPLidar(
            None,
            PORT_NAME)  # 해당 포트 네임으로 라이다 객체 생성, None -> motor pin, 모터 작동 시작
        time.sleep(2)

    def get_data(self):
        self.scan_data = [0] * 360  # 360개의 버퍼 생성
        scan = next(self.lidar.iter_scans())
        for (_, angle, distance) in scan:  # 레이저 강도, 각도, 거리 순
            self.scan_data[min(
                [359, floor(angle)]
            )] = distance  # floor->내림값 구하는 함수, 내림값 구한후 359보다 작은 값인지 검사후 저장, 각도가 인덱스값이 됨
        return self.scan_data

    def process_data(self):  # 데이터 처리함수 정의(FOV내 데이터 좌표로 변환)
        global max_distance
        self.data = []
        self.coords = []
        angle = int(sta_ang)  # 처음 인덱스 시야각의 시작 각도로 설정
        while (angle != int(end_ang)):  # 인덱스 값이 종료 각 도달하기 전까지 실행
            if angle == 360:  # 인덱스 각도가 360도가 되면 다시 0부터 시작하기 위한 설정
                angle = 0
            distance = self.scan_data[angle]  # 해당 각도에 대한 거리값 가져오기

            if distance > 0 and distance < max_distance:  # 측정되지 않은 거리값은 버림
                print("{0}도 에서 {1} cm: ".format(angle, distance * 0.1))
                # max_distance = max([min([5000, distance]), max_distance]) # 최대 5000으로 거리값 제한,
                # radians = (angle-90) * pi / 180.0 # 각도의 라디안값 구하기, mask
                radians = (angle) * pi / 180.0  # 각도의 라디안값 구하기, view
                x = distance * cos(radians)  # x축 좌표 계산
                y = distance * sin(radians)  # y축 좌표 계산
                self.coords.append([
                    int(distance * 0.1 * sin((angle) * pi / 180.0)),
                    int(distance * 0.1 * cos((angle) * pi / 180.0))
                ])
            self.data.append([
                int(640 + x / max_distance * 639),
                int(720 + y / max_distance * 639)
            ])  # 640*640에 맞게 좌표 계산
            angle = angle + 1
        return self.data, self.coords

    def proc_coords(self):  # 좌표 리스트에서 물체 탐지
        self.obj_coords = []
        sta_x = 0
        sta_y = 0
        max_dist = 10  #  두 점 사이 최대 거리

        i = 0
        while (i < len(self.coords)):  # 좌표 리스트 길이만큼 반복
            x, y = self.coords[i]  # 좌표 불러와 저장

            if sta_x == 0 and sta_y == 0:  # 처음일 경우
                sta_x = x
                sta_y = y
                i = i + 1
                continue

            pre_x, pre_y = coords[i - 1]  # 이전 좌표 저장
            dist = sqrt((x - pre_x)**2 + (y - pre_y)**2)  # 이전 좌표와 현재 좌표 거리 저장

            if dist > max_dist:  # 거리가 최대 길이보다 클 경우(다른 객체)
                tmp_list = []  # 임시 리스트 생성
                tmp_list += (sta_x, sta_y, pre_x, pre_y)  # 시작점 끝점 저장
                sta_x = x  # 현재 x좌표를 새로운 객체 시작점으로 저장
                sta_y = y  # 현재 y좌표를 새로운 객체 시작점으로 저장
                self.obj_coords.append(tmp_list)  # 객체 리스트에 탐지한 객체 저장
                i = i + 1
                continue

            if (i == len(coords) - 1) and (
                    dist < max_dist):  # 리스트의 마지막 요소 이고, 이전 점과 연결된 객체인 경우
                tmp_list = []  # 임시 리스트 생성
                tmp_list += (sta_x, sta_y, x, y)  # 객체 좌표 저장
                self.obj_coords.append(tmp_list)  # 객체 리스트에 정보 저장
            i = i + 1
        return self.obj_coords  # 최종 결과 리턴

    def get_view_coords(self):  # 좌표 영상좌표로 변환
        self.view_coords = []  # 변환된 좌표 저장할 리스트 초기화

        for x1, y1, x2, y2 in self.obj_coords:  # 물체 좌표 불러오기
            if y1 > 50 or y2 > 50:  # 거리 이용하여 물체 제한(y 좌표)
                continue

            print("물체 좌표(탑-뷰 좌표): {0}, {1}, {2}, {3}".format(x1, y1, x2, y2))
            ang1 = atan(x1 / y1) * (180 / pi)  # 시작점 각도 추출
            ang2 = atan(x2 / y2) * (180 / pi)  # 끝점 각도 추출

            dist1 = sqrt(x1**2 + y1**2)  # 시작점 거리 추출
            dist2 = sqrt(x2**2 + y2**2)  # 끝점 거리 추출

            print("ang1: " + str(ang1))
            print("ang2: " + str(ang2))
            print("dist1: " + str(dist1))
            print("dist2: " + str(dist2))

            x1 = int(ang1 / 31 * 640) + 640  # 시작점 영상 가로 좌표 계산
            x2 = int(ang2 / 31 * 640) + 640  # 끝점 영상 가로 좌표 계산

            if dist1 < 130:  # 시작점 거리가
                if dist1 <= 20:
                    y1 = 719
                y1 = 720 - int(-0.0348 * (dist1 - 130)**2 + 385)
            elif (dist1 <= 250):
                y1 = 720 - int(-0.007 * (dist1 - 250) + 471)
            else:
                y1 = 720 - 471

            if dist2 < 130:
                if dist2 <= 20:
                    y2 = 719
                y2 = 720 - int(-0.0348 * (dist2 - 130)**2 + 385)
            elif (dist2 <= 250):
                y2 = 720 - int(-0.007 * (dist2 - 250) + 471)
            else:
                y2 = 720 - 471

            self.view_coords.append([x1, y1, x2, y2])
        print("물체의 좌표(영상): " + str(self.view_coords))
        return self.view_coords

    def disconnect_lidar(self):
        self.lidar.clear_input()
        self.lidar.stop_motor()
        self.lidar.stop()
        self.lidar.disconnect()