-
Notifications
You must be signed in to change notification settings - Fork 3
/
hls_lfcd2.py
147 lines (122 loc) · 3.76 KB
/
hls_lfcd2.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"""
This is code to interact lidar: HLS-LFCD2 with python3.
:author: Wahaj Murtaza
:github: https://github.com/wahajmurtaza
:email: wahajmurtaza@gmail.com
"""
import serial
from time import sleep
import threading
# LIDAR DATASHEET: https://emanual.robotis.com/assets/docs/LDS_Basic_Specification.pdf
# RED 5V
# BROWN TX
# ORANGE PWM (connect with pwm) # ground internally
# BLACK GND
# GREEN RX
# BLUE BOT (not used)
# BLACK PWM (connect with pwm)
# RED 5V
class Lidar:
distance = [0] * 360
intensity = [0] * 360
rpm = 0
keep_loop = True
def __init__(self, port, angle_offset=0):
"""
Initiate Lidar object, aquire serial port, set parameters and start a lidar thread
:param port: Serial Port at which lidar is connected
:param angle_offset: Angle Offset (to adjust the front at zero) { 0 > angle_offset < 360 }
"""
self.ser = serial.Serial(port=port, baudrate=230400)
self.angle_offset = angle_offset
self.thread = threading.Thread(target=self._start_loop)
self.thread.start()
def _read_serial(self):
"""
read serial data (42 bytes)
:return: serial data
"""
data = self.ser.read(42)
return data
def _read_range(self, data):
"""
read parameters from data
:param data: serial data
:return: None
"""
bytes_data = list(data)
degree = (bytes_data[1] - 0xA0) * 6
self.rpm = (bytes_data[3] << 8) | bytes_data[2]
if bytes_data[41] != bytes_data[40] or bytes_data[40] == 0:
print(f'invalid data: {degree}')
return
for i in range(6):
distance = (bytes_data[2 + (i*4)+3] << 8) | (bytes_data[2 + (i*4)+2])
intensity = (bytes_data[2 + (i*4)+1] << 8) | (bytes_data[2 + (i*4)+0])
angle = degree + i
angle_offsetted = angle + self.angle_offset if angle + self.angle_offset < 360 else angle + self.angle_offset - 360
self.distance[angle_offsetted] = distance
self.intensity[angle_offsetted] = intensity
def start(self):
"""
start the lidar
:return: None
"""
self.ser.write(b'b')
def stop(self):
"""
stop the lidar, can be started again
:return: None
"""
self.ser.write(b'e')
def _start_loop(self):
"""
Start the lidar loop (must be called in a separate thread)
:return: None
"""
while self.keep_loop:
data = self._read_serial()
if data[0] != 250:
self.ser.write(b'e')
self.ser.close()
sleep(0.1)
self.ser.open()
self.ser.write(b'b')
continue
self._read_range(data)
def terminate(self):
"""
stop the leader, close serial port, and terminate thread
:return: None
"""
self.stop()
self.keep_loop = False
self.ser.close()
self.thread.join()
def get_distance(self):
"""
get lidar distace
:return: return distance array 1x360
"""
return self.distance
def get_intensity(self):
"""
get lidar intensity
:return: return intensity array 1x360
"""
return self.intensity
def get_rpm(self):
"""
get lidar RPM
:return: int
"""
return self.rpm
if __name__ == '__main__':
lidar = Lidar("COM6", angle_offset=0)
lidar.start()
sleep(2)
print(f'rpm = {lidar.get_rpm()}')
print(f'distance = {lidar.get_distance()}')
print(f'intensity = {lidar.get_intensity()}')
lidar.stop()
lidar.terminate()