rplidar 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +11 -1
- data/.rubocop.yml +7 -5
- data/Gemfile.lock +15 -15
- data/README.md +2 -2
- data/lib/rplidar.rb +13 -0
- data/lib/rplidar/current_state_data_response.rb +16 -0
- data/lib/rplidar/device_info_data_response.rb +40 -0
- data/lib/rplidar/driver.rb +20 -77
- data/lib/rplidar/response.rb +22 -0
- data/lib/rplidar/response_descriptor.rb +94 -0
- data/lib/rplidar/scan_data_response.rb +52 -0
- data/lib/rplidar/version.rb +1 -1
- data/spec/rplidar/current_state_data_response_spec.rb +27 -0
- data/spec/rplidar/device_info_data_response_spec.rb +65 -0
- data/spec/rplidar/driver_spec.rb +25 -98
- data/spec/rplidar/response_descriptor_spec.rb +88 -0
- data/spec/rplidar/response_spec.rb +38 -0
- data/spec/rplidar/scan_data_response_spec.rb +111 -0
- data/spec/rplidar_spec.rb +5 -0
- metadata +13 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9e897b58884e73242ae2efa07042f6c5c2d2ff59bf493903690974053d102cfc
|
|
4
|
+
data.tar.gz: ade82a5c1ffefa00b96eadafa5fbf8ca2c9ab708db71619823d8f7479b93fd07
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f77cb72a0a2d985fcf649d2ec2547ffe8b7220a0b3638a55531629a9f9f3ef0ddb30fbf4cfade728a168056ce878837731d4e982481dd7df2537a7767900f0fa
|
|
7
|
+
data.tar.gz: 9495f13a140c70827670fe1b2dce6e15eee523e8f887c76382800fd1df75b278b7e0d34c45a921a6e3bc9e93f4468e2ebb7bba980b21e4a165e2617df3d407c4
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
rplidar (0.1.
|
|
4
|
+
rplidar (0.1.3)
|
|
5
5
|
rubyserial (~> 0.6)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
@@ -13,7 +13,7 @@ GEM
|
|
|
13
13
|
simplecov
|
|
14
14
|
url
|
|
15
15
|
diff-lcs (1.3)
|
|
16
|
-
docile (1.3.
|
|
16
|
+
docile (1.3.1)
|
|
17
17
|
ffi (1.9.25)
|
|
18
18
|
jaro_winkler (1.5.1)
|
|
19
19
|
json (2.1.0)
|
|
@@ -23,20 +23,20 @@ GEM
|
|
|
23
23
|
powerpack (0.1.2)
|
|
24
24
|
rainbow (3.0.0)
|
|
25
25
|
rake (10.5.0)
|
|
26
|
-
rspec (3.
|
|
27
|
-
rspec-core (~> 3.
|
|
28
|
-
rspec-expectations (~> 3.
|
|
29
|
-
rspec-mocks (~> 3.
|
|
30
|
-
rspec-core (3.
|
|
31
|
-
rspec-support (~> 3.
|
|
32
|
-
rspec-expectations (3.
|
|
26
|
+
rspec (3.8.0)
|
|
27
|
+
rspec-core (~> 3.8.0)
|
|
28
|
+
rspec-expectations (~> 3.8.0)
|
|
29
|
+
rspec-mocks (~> 3.8.0)
|
|
30
|
+
rspec-core (3.8.0)
|
|
31
|
+
rspec-support (~> 3.8.0)
|
|
32
|
+
rspec-expectations (3.8.1)
|
|
33
33
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
34
|
-
rspec-support (~> 3.
|
|
35
|
-
rspec-mocks (3.
|
|
34
|
+
rspec-support (~> 3.8.0)
|
|
35
|
+
rspec-mocks (3.8.0)
|
|
36
36
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
37
|
-
rspec-support (~> 3.
|
|
38
|
-
rspec-support (3.
|
|
39
|
-
rubocop (0.
|
|
37
|
+
rspec-support (~> 3.8.0)
|
|
38
|
+
rspec-support (3.8.0)
|
|
39
|
+
rubocop (0.59.1)
|
|
40
40
|
jaro_winkler (~> 1.5.1)
|
|
41
41
|
parallel (~> 1.10)
|
|
42
42
|
parser (>= 2.5, != 2.5.1.1)
|
|
@@ -44,7 +44,7 @@ GEM
|
|
|
44
44
|
rainbow (>= 2.2.2, < 4.0)
|
|
45
45
|
ruby-progressbar (~> 1.7)
|
|
46
46
|
unicode-display_width (~> 1.0, >= 1.0.1)
|
|
47
|
-
rubocop-rspec (1.29.
|
|
47
|
+
rubocop-rspec (1.29.1)
|
|
48
48
|
rubocop (>= 0.58.0)
|
|
49
49
|
ruby-progressbar (1.10.0)
|
|
50
50
|
rubyserial (0.6.0)
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Rplidar
|
|
2
2
|
|
|
3
|
-
[](https://semaphoreci.com/yurykotlyarov/rplidar) [](https://codecov.io/gh/yura/rplidar) [](https://codeclimate.com/github/yura/rplidar/maintainability) [](https://hakiri.io/github/yura/rplidar/master)
|
|
3
|
+
[](https://semaphoreci.com/yurykotlyarov/rplidar) [](https://codecov.io/gh/yura/rplidar) [](https://codeclimate.com/github/yura/rplidar/maintainability) [](https://hakiri.io/github/yura/rplidar/master) [](https://badge.fury.io/rb/rplidar)
|
|
4
4
|
|
|
5
5
|
Ruby implementation of SLAMTEK RPLIDAR A2M8 lidar.
|
|
6
6
|
|
|
@@ -25,7 +25,7 @@ Or install it yourself as:
|
|
|
25
25
|
Run `bundle exec irb`
|
|
26
26
|
|
|
27
27
|
```ruby
|
|
28
|
-
require '
|
|
28
|
+
require 'rplidar'
|
|
29
29
|
|
|
30
30
|
# for Mac OS
|
|
31
31
|
lidar = Rplidar::Driver.new('/dev/tty.SLAB_USBtoUART')
|
data/lib/rplidar.rb
CHANGED
|
@@ -1,2 +1,15 @@
|
|
|
1
1
|
require 'rplidar/driver'
|
|
2
|
+
require 'rplidar/response'
|
|
3
|
+
require 'rplidar/response_descriptor'
|
|
4
|
+
require 'rplidar/scan_data_response'
|
|
5
|
+
require 'rplidar/current_state_data_response'
|
|
6
|
+
require 'rplidar/device_info_data_response'
|
|
2
7
|
require 'rplidar/version'
|
|
8
|
+
|
|
9
|
+
module Rplidar
|
|
10
|
+
# Lidar states
|
|
11
|
+
STATE_GOOD = 0
|
|
12
|
+
STATE_WARNING = 1
|
|
13
|
+
STATE_ERROR = 2
|
|
14
|
+
|
|
15
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Rplidar
|
|
2
|
+
# Implementation of response to the GET_HEALTH request.
|
|
3
|
+
class CurrentStateDataResponse < Response
|
|
4
|
+
def response
|
|
5
|
+
case raw_response[0]
|
|
6
|
+
when STATE_GOOD then { state: :good, error_code: error_code }
|
|
7
|
+
when STATE_WARNING then { state: :warning, error_code: error_code }
|
|
8
|
+
when STATE_ERROR then { state: :error, error_code: error_code }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def error_code
|
|
13
|
+
(raw_response[2] << 8) + raw_response[1]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Rplidar
|
|
2
|
+
class DeviceInfoDataResponse < Response
|
|
3
|
+
# RPLIDAR model ID.
|
|
4
|
+
def model
|
|
5
|
+
raw_response[0]
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Firmware version number, the minor value part.
|
|
9
|
+
def firmware_minor
|
|
10
|
+
raw_response[1]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Firmware version number, the major value part.
|
|
14
|
+
def firmware_major
|
|
15
|
+
raw_response[2]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def firmware
|
|
19
|
+
"#{firmware_major}.#{firmware_minor}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Hardware version number.
|
|
23
|
+
def hardware
|
|
24
|
+
raw_response[3]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# 128bit unique serial number. When converting to text in hex,
|
|
28
|
+
# the Least Significant Byte prints first.
|
|
29
|
+
def serial_number
|
|
30
|
+
raw_response[4..-1].pack('c*').unpack('H*').first.upcase
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def response
|
|
34
|
+
{
|
|
35
|
+
model: model, firmware: firmware,
|
|
36
|
+
hardware: hardware, serial_number: serial_number
|
|
37
|
+
}
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/rplidar/driver.rb
CHANGED
|
@@ -3,13 +3,9 @@ require 'rubyserial'
|
|
|
3
3
|
module Rplidar
|
|
4
4
|
# Ruby implementation of driver of the SLAMTEC RPLIDAR A2.
|
|
5
5
|
class Driver
|
|
6
|
-
# Lidar states
|
|
7
|
-
STATE_GOOD = 0
|
|
8
|
-
STATE_WARNING = 1
|
|
9
|
-
STATE_ERROR = 2
|
|
10
|
-
|
|
11
6
|
# Commands
|
|
12
7
|
COMMAND_GET_HEALTH = 0x52
|
|
8
|
+
COMMAND_GET_INFO = 0x50
|
|
13
9
|
COMMAND_MOTOR_PWM = 0xF0
|
|
14
10
|
COMMAND_SCAN = 0x20
|
|
15
11
|
COMMAND_STOP = 0x25
|
|
@@ -17,11 +13,13 @@ module Rplidar
|
|
|
17
13
|
|
|
18
14
|
COMMANDS_WITH_RESPONSE = [
|
|
19
15
|
COMMAND_GET_HEALTH,
|
|
16
|
+
COMMAND_GET_INFO,
|
|
20
17
|
COMMAND_SCAN
|
|
21
18
|
].freeze
|
|
22
19
|
|
|
23
20
|
# Default length of responses
|
|
24
21
|
RESPONSE_DESCRIPTOR_LENGTH = 7
|
|
22
|
+
GET_INFO_RESPONSE_LENGTH = 20
|
|
25
23
|
SCAN_DATA_RESPONSE_LENGTH = 5
|
|
26
24
|
|
|
27
25
|
UART_BAUD_RATE = 115_200
|
|
@@ -32,12 +30,14 @@ module Rplidar
|
|
|
32
30
|
|
|
33
31
|
def current_state
|
|
34
32
|
descriptor = command(COMMAND_GET_HEALTH)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
raw_response = read_response(descriptor[:data_response_length])
|
|
34
|
+
Rplidar::CurrentStateDataResponse.new(raw_response).response
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def device_info
|
|
38
|
+
descriptor = command(COMMAND_GET_INFO)
|
|
39
|
+
raw_response = read_response(descriptor[:data_response_length])
|
|
40
|
+
Rplidar::DeviceInfoDataResponse.new(raw_response).response
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def start_motor(pwm = 660)
|
|
@@ -121,84 +121,27 @@ module Rplidar
|
|
|
121
121
|
binary_to_ints(string).reduce(:^)
|
|
122
122
|
end
|
|
123
123
|
|
|
124
|
-
# Format of Response Descriptor:
|
|
125
|
-
#
|
|
126
|
-
# Start Flag 1 Start Flag 2 Data Response Length Send Mode Data Type
|
|
127
|
-
#
|
|
128
|
-
# 1 byte (0xA5) 1 bytes (0x5A) 30 bits 2 bits 1 byte
|
|
129
124
|
def response_descriptor
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
125
|
+
raw_response = read_response(RESPONSE_DESCRIPTOR_LENGTH)
|
|
126
|
+
Rplidar::ResponseDescriptor.new(raw_response).response
|
|
127
|
+
end
|
|
133
128
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
send_mode: response[5] >> 6,
|
|
138
|
-
data_type: response[6]
|
|
139
|
-
}
|
|
129
|
+
def scan_data_response
|
|
130
|
+
raw_response = read_response(SCAN_DATA_RESPONSE_LENGTH)
|
|
131
|
+
Rplidar::ScanDataResponse.new(raw_response).response
|
|
140
132
|
end
|
|
141
133
|
|
|
142
|
-
def
|
|
143
|
-
|
|
134
|
+
def read_response(length)
|
|
135
|
+
t = Time.now
|
|
144
136
|
response = []
|
|
145
137
|
while response.size < length
|
|
146
138
|
byte = port.getbyte
|
|
147
139
|
response << byte if byte
|
|
148
|
-
raise 'Timeout while
|
|
140
|
+
raise 'Timeout while reading a byte from the port' if Time.now - t > 2
|
|
149
141
|
end
|
|
150
142
|
response
|
|
151
143
|
end
|
|
152
144
|
|
|
153
|
-
def scan_data_response
|
|
154
|
-
response = data_response(SCAN_DATA_RESPONSE_LENGTH)
|
|
155
|
-
check_data_response_header(response)
|
|
156
|
-
|
|
157
|
-
{
|
|
158
|
-
start: response[0][0] == 1,
|
|
159
|
-
quality: quality(response),
|
|
160
|
-
angle: angle(response),
|
|
161
|
-
distance: distance(response)
|
|
162
|
-
}
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def check_data_response_header(response)
|
|
166
|
-
unless correct_start_bit?(response)
|
|
167
|
-
raise 'Inversed start bit of the data response ' \
|
|
168
|
-
'is not inverse of the start bit'
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
unless correct_check_bit?(response)
|
|
172
|
-
raise 'Check bit of the data response is not equal ' \
|
|
173
|
-
'to 1'
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
def correct_start_bit?(response)
|
|
178
|
-
# start bit
|
|
179
|
-
start = response[0][0]
|
|
180
|
-
# inversed start bit
|
|
181
|
-
inversed = response[0][1]
|
|
182
|
-
|
|
183
|
-
(start == 1 && inversed.zero?) || (start.zero? && inversed == 1)
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
def correct_check_bit?(response)
|
|
187
|
-
response[1][0] == 1
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
def quality(response)
|
|
191
|
-
response[0] >> 2
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
def angle(response)
|
|
195
|
-
((response[2] << 7) + (response[1] >> 1)) / 64.0
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
def distance(response)
|
|
199
|
-
((response[4] << 8) + response[3]) / 4.0
|
|
200
|
-
end
|
|
201
|
-
|
|
202
145
|
def clear_port
|
|
203
146
|
while port.getbyte
|
|
204
147
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Rplidar
|
|
2
|
+
# Generic lidar response class
|
|
3
|
+
class Response
|
|
4
|
+
attr_reader :raw_response
|
|
5
|
+
|
|
6
|
+
def initialize(raw_response)
|
|
7
|
+
@raw_response = raw_response
|
|
8
|
+
check_response
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def check_response
|
|
12
|
+
check_header
|
|
13
|
+
check_payload
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def check_header; end
|
|
17
|
+
|
|
18
|
+
def check_payload; end
|
|
19
|
+
|
|
20
|
+
def response; end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
module Rplidar
|
|
2
|
+
DATA_TYPE_DEVICE_INFO = 0x4
|
|
3
|
+
|
|
4
|
+
# Incapsulates Response Descriptor processing. Format of Response Descriptor:
|
|
5
|
+
#
|
|
6
|
+
# Start Flag 1 Start Flag 2 Data Response Length Send Mode Data Type
|
|
7
|
+
# 1 byte (0xA5) 1 bytes (0x5A) 30 bits 2 bits 1 byte
|
|
8
|
+
class ResponseDescriptor < Response
|
|
9
|
+
def check_response
|
|
10
|
+
check_header
|
|
11
|
+
check_payload
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def check_header
|
|
15
|
+
unless correct_first_byte?
|
|
16
|
+
raise 'Wrong first byte of the response descriptor: ' \
|
|
17
|
+
"'#{int_to_hex(raw_response[0])}'"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
unless correct_second_byte?
|
|
21
|
+
raise 'Wrong second byte of the response descriptor: ' \
|
|
22
|
+
"'#{int_to_hex(raw_response[1])}'"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def check_payload
|
|
27
|
+
unless correct_send_mode?
|
|
28
|
+
raise 'Wrong send mode value of the response descriptor: ' \
|
|
29
|
+
"'#{int_to_hex(send_mode)}'"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
unless correct_data_type?
|
|
33
|
+
raise 'Wrong data type value of the response descriptor: ' \
|
|
34
|
+
"'#{int_to_hex(data_type)}'"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def correct_first_byte?
|
|
39
|
+
raw_response[0] == 0xA5
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def correct_second_byte?
|
|
43
|
+
raw_response[1] == 0x5A
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def correct_send_mode?
|
|
47
|
+
[0x0, 0x1].include?(send_mode)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def correct_data_type?
|
|
51
|
+
[0x6, 0x81, DATA_TYPE_DEVICE_INFO].include?(data_type)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def data_response_length
|
|
55
|
+
(raw_response[4] << 16) + (raw_response[3] << 8) + raw_response[2]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# The 2 bits Send Mode field describes the request/response mode
|
|
59
|
+
# of the current session. Values:
|
|
60
|
+
# * 0x0 - Single Request - Single Response mode, RPLIDAR will send
|
|
61
|
+
# only one data response packet in the current session.
|
|
62
|
+
# * 0x1 - Single Request - Multiple Response mode, RPLIDAR will
|
|
63
|
+
# continuously send out data response packets with the same format
|
|
64
|
+
# in the current session.
|
|
65
|
+
# * 0x2 and 0x3 are reserved for future use
|
|
66
|
+
def send_mode
|
|
67
|
+
raw_response[5] >> 6
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# The 1byte Data Type describes the type of the incoming
|
|
71
|
+
# data response packets.
|
|
72
|
+
def data_type
|
|
73
|
+
raw_response[6]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def response
|
|
77
|
+
{
|
|
78
|
+
data_response_length: data_response_length,
|
|
79
|
+
send_mode: send_mode,
|
|
80
|
+
data_type: data_type
|
|
81
|
+
}
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def int_to_hex(value)
|
|
87
|
+
if value
|
|
88
|
+
"0x#{value.to_s(16).upcase}"
|
|
89
|
+
else
|
|
90
|
+
value.inspect
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Rplidar
|
|
2
|
+
# Data response for one scan measurement
|
|
3
|
+
class ScanDataResponse < Response
|
|
4
|
+
def check_header
|
|
5
|
+
unless correct_start_bit?
|
|
6
|
+
raise 'Inversed start bit of the data response ' \
|
|
7
|
+
'is not inverse of the start bit'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
raise 'Check bit of the data response is not equal to 1' \
|
|
11
|
+
unless correct_check_bit?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def correct_start_bit?
|
|
15
|
+
# start bit
|
|
16
|
+
start = raw_response[0][0]
|
|
17
|
+
# inversed start bit
|
|
18
|
+
inversed = raw_response[0][1]
|
|
19
|
+
|
|
20
|
+
(start == 1 && inversed.zero?) || (start.zero? && inversed == 1)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def correct_check_bit?
|
|
24
|
+
raw_response[1][0] == 1
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def start?
|
|
28
|
+
raw_response[0][0] == 1
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def quality
|
|
32
|
+
raw_response[0] >> 2
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def angle
|
|
36
|
+
((raw_response[2] << 7) + (raw_response[1] >> 1)) / 64.0
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def distance
|
|
40
|
+
((raw_response[4] << 8) + raw_response[3]) / 4.0
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def response
|
|
44
|
+
{
|
|
45
|
+
start: start?,
|
|
46
|
+
quality: quality,
|
|
47
|
+
angle: angle,
|
|
48
|
+
distance: distance
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
data/lib/rplidar/version.rb
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Data Responses
|
|
2
|
+
DR_HEALTH_GOOD = [0, 0, 0].freeze
|
|
3
|
+
DR_HEALTH_WARN = [1, 0, 0].freeze
|
|
4
|
+
DR_HEALTH_ERR = [2, 3, 5].freeze
|
|
5
|
+
|
|
6
|
+
RSpec.describe Rplidar::CurrentStateDataResponse do
|
|
7
|
+
let(:data_response) { described_class.new([0, 0, 0]) }
|
|
8
|
+
|
|
9
|
+
describe '#response' do
|
|
10
|
+
subject(:response) { data_response.response }
|
|
11
|
+
|
|
12
|
+
it 'returns :good if lidar is in Good (0) state' do
|
|
13
|
+
allow(data_response).to receive(:raw_response).and_return(DR_HEALTH_GOOD)
|
|
14
|
+
expect(response).to eq(state: :good, error_code: 0)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'returns :warning if lidar is in Warning (1) state' do
|
|
18
|
+
allow(data_response).to receive(:raw_response).and_return(DR_HEALTH_WARN)
|
|
19
|
+
expect(response).to eq(state: :warning, error_code: 0)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'returns :error if lidar is in Error (2) state' do
|
|
23
|
+
allow(data_response).to receive(:raw_response).and_return(DR_HEALTH_ERR)
|
|
24
|
+
expect(response).to eq(state: :error, error_code: 1283)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
DR_GET_INFO = [
|
|
2
|
+
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
|
|
3
|
+
].freeze
|
|
4
|
+
|
|
5
|
+
DR_GET_INFO_REAL = [
|
|
6
|
+
40, 24, 1, 4, 168, 226, 154, 240, 197, 226,
|
|
7
|
+
157, 210, 182, 227, 157, 245, 43, 49, 49, 22
|
|
8
|
+
].freeze
|
|
9
|
+
|
|
10
|
+
RSpec.describe Rplidar::DeviceInfoDataResponse do
|
|
11
|
+
let(:response) { described_class.new(DR_GET_INFO) }
|
|
12
|
+
|
|
13
|
+
describe '#model' do
|
|
14
|
+
it 'returns model' do
|
|
15
|
+
expect(response.model).to eq(1)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe '#firmware_minor' do
|
|
20
|
+
it 'returns firmware minor' do
|
|
21
|
+
expect(response.firmware_minor).to eq(2)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe '#firmware_major' do
|
|
26
|
+
it 'returns firmware major' do
|
|
27
|
+
expect(response.firmware_major).to eq(3)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe '#firmware' do
|
|
32
|
+
it 'returns firmware version' do
|
|
33
|
+
expect(response.firmware).to eq('3.2')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe '#hardware' do
|
|
38
|
+
it 'returns hardware' do
|
|
39
|
+
expect(response.hardware).to eq(4)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe '#serial_number' do
|
|
44
|
+
it 'returns serial_number' do
|
|
45
|
+
expect(response.serial_number).to eq('05060708090A0B0C0D0E0F1011121314')
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe '#response' do
|
|
50
|
+
it 'returns device info' do
|
|
51
|
+
expect(response.response).to eq(
|
|
52
|
+
model: 1, firmware: '3.2',
|
|
53
|
+
hardware: 4, serial_number: '05060708090A0B0C0D0E0F1011121314'
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'returns real device info' do
|
|
58
|
+
allow(response).to receive(:raw_response).and_return(DR_GET_INFO_REAL)
|
|
59
|
+
expect(response.response).to eq(
|
|
60
|
+
model: 40, firmware: '1.24',
|
|
61
|
+
hardware: 4, serial_number: 'A8E29AF0C5E29DD2B6E39DF52B313116'
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
data/spec/rplidar/driver_spec.rb
CHANGED
|
@@ -10,11 +10,6 @@ RAW_RD_SCAN = ascii("\xA5Z\x05\x00\x00@\x81")
|
|
|
10
10
|
RD_GET_HEALTH = [165, 90, 3, 0, 0, 0, 6].freeze
|
|
11
11
|
RD_SCAN = [165, 90, 5, 0, 0, 64, 129].freeze
|
|
12
12
|
|
|
13
|
-
# Data Responses
|
|
14
|
-
DR_HEALTH_GOOD = [0, 0, 0].freeze
|
|
15
|
-
DR_HEALTH_WARNING = [1, 0, 0].freeze
|
|
16
|
-
DR_HEALTH_ERROR = [2, 3, 5].freeze
|
|
17
|
-
|
|
18
13
|
DR_SCAN = [62, 63, 3, 117, 4].freeze
|
|
19
14
|
|
|
20
15
|
RSpec.describe Rplidar::Driver do
|
|
@@ -34,7 +29,7 @@ RSpec.describe Rplidar::Driver do
|
|
|
34
29
|
allow(lidar).to receive(:command)
|
|
35
30
|
.with(0x52)
|
|
36
31
|
.and_return(data_response_length: 3)
|
|
37
|
-
allow(lidar).to receive(:
|
|
32
|
+
allow(lidar).to receive(:read_response)
|
|
38
33
|
.with(3)
|
|
39
34
|
.and_return([0, 0, 0])
|
|
40
35
|
end
|
|
@@ -46,31 +41,29 @@ RSpec.describe Rplidar::Driver do
|
|
|
46
41
|
|
|
47
42
|
it 'reads data_response' do
|
|
48
43
|
current_state
|
|
49
|
-
expect(lidar).to have_received(:
|
|
44
|
+
expect(lidar).to have_received(:read_response).with(3)
|
|
50
45
|
end
|
|
51
46
|
|
|
52
47
|
it 'returns :good if lidar is in Good (0) state' do
|
|
53
|
-
allow(lidar).to receive(:
|
|
48
|
+
allow(lidar).to receive(:read_response)
|
|
54
49
|
.with(3)
|
|
55
|
-
.and_return(
|
|
56
|
-
expect(current_state).to eq(
|
|
50
|
+
.and_return([0, 0, 0])
|
|
51
|
+
expect(current_state).to eq(state: :good, error_code: 0)
|
|
57
52
|
end
|
|
58
53
|
|
|
59
54
|
it 'returns :warning if lidar is in Warning (1) state' do
|
|
60
|
-
allow(lidar).to receive(:
|
|
55
|
+
allow(lidar).to receive(:read_response)
|
|
61
56
|
.with(3)
|
|
62
|
-
.and_return(
|
|
63
|
-
expect(current_state).to eq(
|
|
57
|
+
.and_return([1, 0, 0])
|
|
58
|
+
expect(current_state).to eq(state: :warning, error_code: 0)
|
|
64
59
|
end
|
|
65
60
|
|
|
66
61
|
it 'returns :error if lidar is in Error (2) state' do
|
|
67
|
-
allow(lidar).to receive(:
|
|
62
|
+
allow(lidar).to receive(:read_response)
|
|
68
63
|
.with(3)
|
|
69
|
-
.and_return(
|
|
70
|
-
expect(current_state).to eq(
|
|
64
|
+
.and_return([2, 3, 5])
|
|
65
|
+
expect(current_state).to eq(state: :error, error_code: 1283)
|
|
71
66
|
end
|
|
72
|
-
|
|
73
|
-
it 'concatenates error code bytes'
|
|
74
67
|
end
|
|
75
68
|
|
|
76
69
|
describe '#start_motor' do
|
|
@@ -209,25 +202,25 @@ RSpec.describe Rplidar::Driver do
|
|
|
209
202
|
|
|
210
203
|
describe '#response_descriptor' do
|
|
211
204
|
before do
|
|
212
|
-
allow(lidar).to receive(:
|
|
205
|
+
allow(lidar).to receive(:read_response)
|
|
213
206
|
.with(7)
|
|
214
207
|
.and_return(RD_GET_HEALTH)
|
|
215
208
|
end
|
|
216
209
|
|
|
217
210
|
it 'reads 7 bytes from the port' do
|
|
218
211
|
lidar.response_descriptor
|
|
219
|
-
expect(lidar).to have_received(:
|
|
212
|
+
expect(lidar).to have_received(:read_response).with(7)
|
|
220
213
|
end
|
|
221
214
|
|
|
222
215
|
it 'processes GET_HEALTH response descriptor correctly' do
|
|
223
|
-
allow(lidar).to receive(:
|
|
216
|
+
allow(lidar).to receive(:read_response)
|
|
224
217
|
.with(7).and_return(RD_GET_HEALTH)
|
|
225
218
|
expect(lidar.response_descriptor).to \
|
|
226
219
|
eq(data_response_length: 3, send_mode: 0, data_type: 6)
|
|
227
220
|
end
|
|
228
221
|
|
|
229
222
|
it 'processes scan response descriptor correctly' do
|
|
230
|
-
allow(lidar).to receive(:
|
|
223
|
+
allow(lidar).to receive(:read_response)
|
|
231
224
|
.with(7).and_return(RD_SCAN)
|
|
232
225
|
expect(lidar.response_descriptor).to \
|
|
233
226
|
eq(data_response_length: 5, send_mode: 1, data_type: 129)
|
|
@@ -258,27 +251,27 @@ RSpec.describe Rplidar::Driver do
|
|
|
258
251
|
end
|
|
259
252
|
end
|
|
260
253
|
|
|
261
|
-
describe '#
|
|
262
|
-
subject(:
|
|
254
|
+
describe '#read_response' do
|
|
255
|
+
subject(:read_response) { lidar.read_response(5) }
|
|
263
256
|
|
|
264
257
|
before do
|
|
265
258
|
allow(port).to receive(:getbyte).and_return(1, 55, 88, 111, 222, 111)
|
|
266
259
|
end
|
|
267
260
|
|
|
268
261
|
it 'reads bytes from the port' do
|
|
269
|
-
|
|
262
|
+
read_response
|
|
270
263
|
expect(port).to have_received(:getbyte).exactly(5).times
|
|
271
264
|
end
|
|
272
265
|
|
|
273
266
|
it 'returns all read bytes' do
|
|
274
|
-
expect(
|
|
267
|
+
expect(read_response).to eq([1, 55, 88, 111, 222])
|
|
275
268
|
end
|
|
276
269
|
|
|
277
270
|
it 'raises timeout exception if read takes more than 2 seconds' do
|
|
278
271
|
allow(port).to receive(:getbyte).and_return(1, 2, 3, nil)
|
|
279
272
|
expect do
|
|
280
|
-
|
|
281
|
-
end.to raise_error('Timeout while
|
|
273
|
+
read_response
|
|
274
|
+
end.to raise_error('Timeout while reading a byte from the port')
|
|
282
275
|
end
|
|
283
276
|
end
|
|
284
277
|
|
|
@@ -286,47 +279,21 @@ RSpec.describe Rplidar::Driver do
|
|
|
286
279
|
subject(:scan_data_response) { lidar.scan_data_response }
|
|
287
280
|
|
|
288
281
|
before do
|
|
289
|
-
allow(lidar).to receive(:
|
|
290
|
-
allow(lidar).to receive(:check_data_response_header).with(DR_SCAN)
|
|
291
|
-
allow(lidar).to receive(:angle).with(DR_SCAN).and_return(111)
|
|
292
|
-
allow(lidar).to receive(:distance).with(DR_SCAN).and_return(222)
|
|
293
|
-
allow(lidar).to receive(:quality).with(DR_SCAN).and_return(333)
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
it 'reads data_response' do
|
|
297
|
-
scan_data_response
|
|
298
|
-
expect(lidar).to have_received(:data_response).with(5)
|
|
282
|
+
allow(lidar).to receive(:read_response).with(5).and_return(DR_SCAN)
|
|
299
283
|
end
|
|
300
284
|
|
|
301
|
-
it '
|
|
285
|
+
it 'reads response' do
|
|
302
286
|
scan_data_response
|
|
303
|
-
expect(lidar).to have_received(:
|
|
287
|
+
expect(lidar).to have_received(:read_response).with(5)
|
|
304
288
|
end
|
|
305
289
|
|
|
306
290
|
it 'returns hash with processed values' do
|
|
307
291
|
expect(scan_data_response).to eq(
|
|
308
|
-
start: false, angle:
|
|
292
|
+
start: false, angle: 6.484375, distance: 285.25, quality: 15
|
|
309
293
|
)
|
|
310
294
|
end
|
|
311
295
|
end
|
|
312
296
|
|
|
313
|
-
describe '#check_data_response_header' do
|
|
314
|
-
it 'raises inversed start flag bit is not inverse of the start flag bit' do
|
|
315
|
-
[[[1, 1]], [[0, 0]], [[1, -2]], [[0, -1]]].each do |wrong_response|
|
|
316
|
-
expect { lidar.check_data_response_header(wrong_response) }.to \
|
|
317
|
-
raise_error('Inversed start bit of the data response ' \
|
|
318
|
-
'is not inverse of the start bit')
|
|
319
|
-
end
|
|
320
|
-
end
|
|
321
|
-
|
|
322
|
-
it 'raises an exception if 3rd bit is not equal to 1' do
|
|
323
|
-
[[[1, 0], [0]], [[0, 1], [2]]].each do |wrong_response|
|
|
324
|
-
expect { lidar.check_data_response_header(wrong_response) }.to \
|
|
325
|
-
raise_error('Check bit of the data response is not equal to 1')
|
|
326
|
-
end
|
|
327
|
-
end
|
|
328
|
-
end
|
|
329
|
-
|
|
330
297
|
describe '#close' do
|
|
331
298
|
subject(:close) { lidar.close }
|
|
332
299
|
|
|
@@ -365,46 +332,6 @@ RSpec.describe Rplidar::Driver do
|
|
|
365
332
|
end
|
|
366
333
|
end
|
|
367
334
|
|
|
368
|
-
describe '#correct_start_bit?' do
|
|
369
|
-
it 'raises inversed start flag bit is not inverse of the start flag bit' do
|
|
370
|
-
[[[1, 1]], [[0, 0]], [[1, -2]], [[0, -1]]].each do |response|
|
|
371
|
-
expect(lidar.correct_start_bit?(response)).to be_falsy
|
|
372
|
-
end
|
|
373
|
-
end
|
|
374
|
-
end
|
|
375
|
-
|
|
376
|
-
describe '#correct_check_bit?' do
|
|
377
|
-
it 'returns true if first bit of the second byte is equal to 1' do
|
|
378
|
-
[[0, 1], [0, 3], [0, 5], [0, 255]].each do |response|
|
|
379
|
-
expect(lidar.correct_check_bit?(response)).to be_truthy
|
|
380
|
-
end
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
it 'returns false if 1st bit of the 2nd byte is not equal to 1' do
|
|
384
|
-
[[0, 0], [0, 2], [0, 254]].each do |response|
|
|
385
|
-
expect(lidar.correct_check_bit?(response)).to be_falsy
|
|
386
|
-
end
|
|
387
|
-
end
|
|
388
|
-
end
|
|
389
|
-
|
|
390
|
-
describe '#angle' do
|
|
391
|
-
it 'processes angle from the 2nd and 3rd bytes' do
|
|
392
|
-
expect(lidar.angle([62, 155, 2, 112, 4])).to eq(5.203125)
|
|
393
|
-
end
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
describe '#distance' do
|
|
397
|
-
it 'processes angle from the 4th and 5th bytes' do
|
|
398
|
-
expect(lidar.distance([62, 155, 2, 112, 4])).to eq(284)
|
|
399
|
-
end
|
|
400
|
-
end
|
|
401
|
-
|
|
402
|
-
describe '#quality' do
|
|
403
|
-
it 'processes quantity from the 1st bit' do
|
|
404
|
-
expect(lidar.quality([62, 155, 2, 112, 4])).to eq(15)
|
|
405
|
-
end
|
|
406
|
-
end
|
|
407
|
-
|
|
408
335
|
describe '#clear_port' do
|
|
409
336
|
subject(:clear_port) { lidar.clear_port }
|
|
410
337
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
RD_GET_HEALTH = [165, 90, 3, 0, 0, 0, 6].freeze
|
|
2
|
+
RD_SCAN = [165, 90, 5, 0, 0, 64, 129].freeze
|
|
3
|
+
|
|
4
|
+
RSpec.describe Rplidar::ResponseDescriptor do
|
|
5
|
+
let(:descriptor) { described_class.new(RD_SCAN) }
|
|
6
|
+
|
|
7
|
+
describe '#check_header' do
|
|
8
|
+
subject(:check_header) { descriptor.check_header }
|
|
9
|
+
|
|
10
|
+
it 'raises "Wrong first byte of the response descriptor" exception' do
|
|
11
|
+
allow(descriptor).to receive(:raw_response).and_return([90, 0, 0, 0, 0])
|
|
12
|
+
expect { check_header }.to \
|
|
13
|
+
raise_error("Wrong first byte of the response descriptor: '0x5A'")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'raises exception for nils' do
|
|
17
|
+
allow(descriptor).to receive(:raw_response).and_return([nil, nil, nil])
|
|
18
|
+
expect { check_header }.to \
|
|
19
|
+
raise_error("Wrong first byte of the response descriptor: 'nil'")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'raises "Wrong second byte of the response descriptor" exception' do
|
|
23
|
+
allow(descriptor).to receive(:raw_response).and_return([165, 165, 0, 0])
|
|
24
|
+
expect { check_header }.to \
|
|
25
|
+
raise_error("Wrong second byte of the response descriptor: '0xA5'")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe '#check_payload' do
|
|
30
|
+
subject(:check_payload) { descriptor.check_payload }
|
|
31
|
+
|
|
32
|
+
it 'raises "Wrong send mode value of the response descriptor" exception' do
|
|
33
|
+
allow(descriptor).to \
|
|
34
|
+
receive(:raw_response).and_return([165, 90, 3, 0, 0, 128])
|
|
35
|
+
expect { check_payload }.to \
|
|
36
|
+
raise_error("Wrong send mode value of the response descriptor: '0x2'")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'raises "Wrong data type value of the response descriptor" exception' do
|
|
40
|
+
allow(descriptor).to \
|
|
41
|
+
receive(:raw_response).and_return([165, 90, 3, 0, 0, 64, 1])
|
|
42
|
+
expect { check_payload }.to \
|
|
43
|
+
raise_error("Wrong data type value of the response descriptor: '0x1'")
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe '#data_response_length' do
|
|
48
|
+
subject(:data_response_length) { descriptor.data_response_length }
|
|
49
|
+
|
|
50
|
+
it 'returns data response length for GET_HEALTH request' do
|
|
51
|
+
allow(descriptor).to \
|
|
52
|
+
receive(:raw_response).and_return(RD_GET_HEALTH)
|
|
53
|
+
expect(data_response_length).to eq(3)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'returns data response length for SCAN request' do
|
|
57
|
+
allow(descriptor).to \
|
|
58
|
+
receive(:raw_response).and_return(RD_SCAN)
|
|
59
|
+
expect(data_response_length).to eq(5)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe '#send_mode' do
|
|
64
|
+
subject(:send_mode) { descriptor.send_mode }
|
|
65
|
+
|
|
66
|
+
it 'returns Single Request - Single Response for GET_HEALTH request' do
|
|
67
|
+
allow(descriptor).to receive(:raw_response).and_return(RD_GET_HEALTH)
|
|
68
|
+
expect(send_mode).to eq(0x0)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'returns Single Request - Multiple Response for SCAN request' do
|
|
72
|
+
allow(descriptor).to receive(:raw_response).and_return(RD_SCAN)
|
|
73
|
+
expect(send_mode).to eq(0x1)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe '#response' do
|
|
78
|
+
subject(:response) { descriptor.response }
|
|
79
|
+
|
|
80
|
+
it 'returns processed values for SCAN request' do
|
|
81
|
+
expect(response).to eq(
|
|
82
|
+
data_response_length: 5,
|
|
83
|
+
send_mode: 1,
|
|
84
|
+
data_type: 0x81
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Rplidar::Response do
|
|
4
|
+
let(:response) { described_class.new([1, 2, 3, 4, 5]) }
|
|
5
|
+
|
|
6
|
+
describe '.new' do
|
|
7
|
+
before do
|
|
8
|
+
allow_any_instance_of(described_class).to receive(:check_response)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'creates new instance of Rplidar::Response' do
|
|
12
|
+
expect(response.raw_response).to eq([1, 2, 3, 4, 5])
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'checks response' do
|
|
16
|
+
expect(response).to have_received(:check_response)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe '#check_response' do
|
|
21
|
+
subject(:check_response) { response.check_response }
|
|
22
|
+
|
|
23
|
+
before do
|
|
24
|
+
allow(response).to receive(:check_header)
|
|
25
|
+
allow(response).to receive(:check_payload)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'calls #check_header' do
|
|
29
|
+
check_response
|
|
30
|
+
expect(response).to have_received(:check_header)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'calls #check_payload' do
|
|
34
|
+
check_response
|
|
35
|
+
expect(response).to have_received(:check_payload)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
RSpec.describe Rplidar::ScanDataResponse do
|
|
2
|
+
let(:raw_response) { [62, 155, 2, 112, 4] }
|
|
3
|
+
let(:response) { described_class.new(raw_response) }
|
|
4
|
+
|
|
5
|
+
describe '.new' do
|
|
6
|
+
it 'checks header' do
|
|
7
|
+
allow_any_instance_of(described_class).to receive(:check_header)
|
|
8
|
+
response
|
|
9
|
+
expect(response).to have_received(:check_header)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe '#check_header' do
|
|
14
|
+
subject(:check_header) { response.check_header }
|
|
15
|
+
|
|
16
|
+
before do
|
|
17
|
+
allow(response).to receive(:correct_start_bit?).and_return(true)
|
|
18
|
+
allow(response).to receive(:correct_check_bit?).and_return(true)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'does not raise any exception if header bits are correct' do
|
|
22
|
+
expect { check_header }.not_to raise_error
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'raises inversed start flag bit is not inverse of the start flag bit' do
|
|
26
|
+
allow(response).to receive(:correct_start_bit?).and_return(false)
|
|
27
|
+
|
|
28
|
+
expect { check_header }.to \
|
|
29
|
+
raise_error('Inversed start bit of the data response ' \
|
|
30
|
+
'is not inverse of the start bit')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'raises an exception if 3rd bit is not equal to 1' do
|
|
34
|
+
allow(response).to receive(:correct_check_bit?).and_return(false)
|
|
35
|
+
|
|
36
|
+
expect { response.check_header }.to \
|
|
37
|
+
raise_error('Check bit of the data response is not equal to 1')
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe '#correct_start_bit?' do
|
|
42
|
+
it 'returns true if 1st bit of 1st byte is 1 and 2nd bit is 0' do
|
|
43
|
+
allow(response).to receive(:raw_response).and_return([0b01])
|
|
44
|
+
expect(response).to be_correct_start_bit
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'returns true if 1st bit of 1st byte is 0 and 2nd bit is 1' do
|
|
48
|
+
allow(response).to receive(:raw_response).and_return([0b110])
|
|
49
|
+
expect(response).to be_correct_start_bit
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'returns false if both 1st bit and 2nd one of the 1st byte are 1s' do
|
|
53
|
+
allow(response).to receive(:raw_response).and_return([0b1011])
|
|
54
|
+
expect(response).not_to be_correct_start_bit
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'returns false if both 1st bit and 2nd one of the 1st byte are 0s' do
|
|
58
|
+
allow(response).to receive(:raw_response).and_return([0b10100])
|
|
59
|
+
expect(response).not_to be_correct_start_bit
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe '#correct_check_bit?' do
|
|
64
|
+
it 'returns true if 1st bit of the 2nd byte is equal to 1' do
|
|
65
|
+
allow(response).to receive(:raw_response).and_return([0b10101, 0b101])
|
|
66
|
+
expect(response).to be_correct_check_bit
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'returns false if 1st bit of the 2nd byte is not equal to 1' do
|
|
70
|
+
allow(response).to receive(:raw_response).and_return([0b10101, 0b10])
|
|
71
|
+
expect(response).not_to be_correct_check_bit
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
describe '#start?' do
|
|
76
|
+
it 'returns false if 1st bit of the 1st byte is equal to 0' do
|
|
77
|
+
expect(response).not_to be_start
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'returns true if 1st bit of the 1st byte is equal to 1' do
|
|
81
|
+
allow(response).to receive(:raw_response).and_return([0b1011])
|
|
82
|
+
expect(response).to be_start
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
describe '#angle' do
|
|
87
|
+
it 'processes angle from the 2nd and 3rd bytes' do
|
|
88
|
+
expect(response.angle).to eq(5.203125)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe '#distance' do
|
|
93
|
+
it 'processes angle from the 4th and 5th bytes' do
|
|
94
|
+
expect(response.distance).to eq(284)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
describe '#quality' do
|
|
99
|
+
it 'processes quantity from the 1st bit' do
|
|
100
|
+
expect(response.quality).to eq(15)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe '#response' do
|
|
105
|
+
it 'returns a hash with response' do
|
|
106
|
+
expect(response.response).to eq(
|
|
107
|
+
start: false, angle: 5.203125, distance: 284, quality: 15
|
|
108
|
+
)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rplidar
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yury Kotlyarov
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2018-09-
|
|
11
|
+
date: 2018-09-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rubyserial
|
|
@@ -112,10 +112,21 @@ files:
|
|
|
112
112
|
- bin/console
|
|
113
113
|
- bin/setup
|
|
114
114
|
- lib/rplidar.rb
|
|
115
|
+
- lib/rplidar/current_state_data_response.rb
|
|
116
|
+
- lib/rplidar/device_info_data_response.rb
|
|
115
117
|
- lib/rplidar/driver.rb
|
|
118
|
+
- lib/rplidar/response.rb
|
|
119
|
+
- lib/rplidar/response_descriptor.rb
|
|
120
|
+
- lib/rplidar/scan_data_response.rb
|
|
116
121
|
- lib/rplidar/version.rb
|
|
117
122
|
- rplidar.gemspec
|
|
123
|
+
- spec/rplidar/current_state_data_response_spec.rb
|
|
124
|
+
- spec/rplidar/device_info_data_response_spec.rb
|
|
118
125
|
- spec/rplidar/driver_spec.rb
|
|
126
|
+
- spec/rplidar/response_descriptor_spec.rb
|
|
127
|
+
- spec/rplidar/response_spec.rb
|
|
128
|
+
- spec/rplidar/scan_data_response_spec.rb
|
|
129
|
+
- spec/rplidar_spec.rb
|
|
119
130
|
- spec/spec_helper.rb
|
|
120
131
|
homepage: http://github.com/yura/rplidar
|
|
121
132
|
licenses:
|