lignite 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bf1b7c4214285394b080eee7ac292b74a02583ec
4
- data.tar.gz: 2e8eceb5bb0058722da49642ac252c9054f3582b
3
+ metadata.gz: ce4cca8022a372bfd1ee229725d3a538376c6d54
4
+ data.tar.gz: 7957e5d6aa35cf8551752d3a324f2cef141bd466
5
5
  SHA512:
6
- metadata.gz: 7dba38b35d34ffbafce9c5788c792f12d598623d4862dbfa0f3a3ed99c1c31c490495619cef96970047e9622832d0c92ae97cbfc9282a5e3c52a0f2e06992114
7
- data.tar.gz: dddf6c17fd11bd751b111d6c03e70c6114a5333a3acd61ee7fe4dd8958195ab7c3b5c44260144b5e2bea2d3945a8b2621b36d278fc55a5b08d969766a81e417a
6
+ metadata.gz: fdf692daad988853107d65e5ebf31da38e0c6bd5d4bf6819e9b0e8e8ca5a140fe95bdf51d32db8c556f1e07298f3671aa389e8c994ff2293f087ae1c237cf1a7
7
+ data.tar.gz: c5a98aedfde6259e69cdadbed737ee7fa1eed93d505a42489ee99a2a64ff8dcadabbdd8c1f4d7bca0a7cb004fc18caaa4cc33f61275153789a63386404896d18
@@ -2,11 +2,39 @@ inherit_from: rubocop-suse.yml
2
2
 
3
3
  AllCops:
4
4
  TargetRubyVersion: 2.1
5
+ Exclude:
6
+ - 'vendor/**/*'
7
+ - '.git/**/*'
8
+ - lib/lignite/ev3_ops.rb
5
9
 
6
10
  Naming/FileName:
7
11
  Exclude:
8
12
  - spec/data/*.rb
9
13
 
10
14
  Layout/IndentHeredoc:
15
+ Enabled: false
16
+
17
+ Performance/RedundantBlockCall:
18
+ Enabled: false
19
+
20
+ Style/SymbolArray:
21
+ Enabled: false
22
+
23
+ Metrics/BlockLength:
11
24
  Exclude:
12
25
  - lignite.gemspec
26
+ - lib/lignite/ev3_tool.rb
27
+ - spec/**/*.rb
28
+
29
+ Metrics/ClassLength:
30
+ Exclude:
31
+ - lib/lignite/ev3_tool.rb
32
+ - lib/lignite/motors.rb
33
+
34
+ Metrics/MethodLength:
35
+ Max: 25
36
+
37
+ Metrics/ModuleLength:
38
+ Exclude:
39
+ # generated
40
+ - lib/lignite/enums.rb
data/NEWS.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## unreleased
4
4
 
5
+ ## 0.4.0, 2018-03-04
6
+
7
+ - Generate Ev3Ops ahead of time, enabling YARD docs for them,
8
+ reducing startup time
9
+ - Fixed `ev3tool ls`, `ls-l`, `start`, all broken in 0.3.0
10
+
5
11
  ## 0.3.0, 2018-03-02
6
12
 
7
13
  - Added Tap and Replay to simulate a real robot with YAML files for tests
data/Rakefile CHANGED
@@ -1,6 +1,27 @@
1
- task default: :test
1
+ task default: [:test, :rubocop, :yard]
2
2
 
3
3
  desc "Run tests"
4
4
  task :test do
5
5
  system "rspec"
6
6
  end
7
+
8
+ desc "Run RuboCop"
9
+ task :rubocop do
10
+ system "rubocop --display-cop-names"
11
+ end
12
+
13
+ desc "Generate YARD documentation"
14
+ task :yard do
15
+ system "yardoc --use-cache"
16
+ end
17
+
18
+ EV3_YML = "data/ev3.yml".freeze
19
+ GENERATOR = "tools/ops_from_yml".freeze
20
+ OPS = "lib/lignite/ev3_ops.rb".freeze
21
+
22
+ desc "Regenerate the EV3 assembler operations"
23
+ task ops: OPS
24
+
25
+ file OPS => [EV3_YML, GENERATOR] do |t|
26
+ sh GENERATOR, t.prerequisites.first, t.name
27
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -1,151 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
- require "lignite"
3
- require "thor"
4
- require "fileutils"
5
- include Lignite::Bytes
2
+ require "lignite/ev3_tool"
6
3
 
7
- # The VM current working directory is /home/root/lms2012/sys
8
- # which is not very useful. A better default is /home/root/lms2012/prjs
9
- # which is displayed on the 2nd tab of the brick UI.
10
- EV3TOOL_HOME = "../prjs".freeze
11
-
12
- def phandles
13
- handles = sc.list_open_handles
14
- puts "OPEN HANDLES: ", hexdump(handles)
15
- end
16
-
17
- class Ev3Tool < Thor
18
- desc "upload LOCAL_FILENAME [BRICK_FILENAME]", "upload a program or a file"
19
- map "ul" => "upload"
20
- def upload(local_filename, brick_filename = nil)
21
- data = File.read(local_filename, encoding: Encoding::BINARY)
22
- unless brick_filename
23
- prj = File.basename(local_filename, ".rbf")
24
- brick_filename = "#{EV3TOOL_HOME}/#{prj}/#{prj}.rbf"
25
- end
26
- handle = sc.begin_download(data.bytesize, brick_filename)
27
- sc.continue_download(handle, data)
28
- end
29
-
30
- desc "download BRICK_FILENAME [LOCAL_FILENAME]", "download a file"
31
- map "dl" => "download"
32
- def download(brick_filename, local_filename = nil)
33
- local_filename ||= File.basename(brick_filename)
34
- fsize, handle, data = sc.begin_upload(4096, brick_filename)
35
- File.open(local_filename, "w") do |f|
36
- loop do
37
- f.write(data)
38
- fsize -= data.bytesize
39
- break if fsize.zero?
40
- handle, data = sc.continue_upload(handle, 4096)
41
- end
42
- end
43
- end
44
-
45
- desc "list-files DIRNAME", "list DIRNAME in a long format"
46
- map "ls-l" => "list-files"
47
- def list_files(name)
48
- name ||= EV3TOOL_HOME
49
- name = "#{EV3TOOL_HOME}/#{name}" unless name.start_with?("/")
50
-
51
- result = ""
52
- fsize, handle, data = sc.list_files(4096, name)
53
- loop do
54
- result += data
55
- fsize -= data.bytesize
56
- break if fsize.zero?
57
- handle, data = sc.continue_list_files(handle, 4096)
58
- end
59
- result
60
- rescue Lignite::VMError
61
- nil
62
- end
63
-
64
- desc "ls DIRNAME", "list DIRNAME in a short format"
65
- def ls(name)
66
- raw = list_files(name)
67
- return nil if raw.nil?
68
-
69
- raw.lines.map do |l|
70
- l = l.chomp
71
- next nil if ["./", "../"].include?(l)
72
- next l if l.end_with?("/")
73
- # skip checksum + space + size + space
74
- l[32 + 1 + 8 + 1..-1]
75
- end.compact
76
- end
77
-
78
- desc "start NAME", "start a program"
79
- def start(name)
80
- if name.include?("/")
81
- name = "#{EV3TOOL_HOME}/#{name}" unless name.start_with?("/")
82
- else
83
- name = "#{EV3TOOL_HOME}/#{name}/#{name}.rbf"
84
- end
85
-
86
- unless file_exist?(name)
87
- $stderr.puts "File #{name.inspect} not found"
88
- exit 1
89
- end
90
-
91
- slot = Lignite::USER_SLOT
92
- no_debug = 0
93
- dc.block do
94
- # these are local variables
95
- data32 :size
96
- data32 :ip
97
- file_load_image(slot, name, :size, :ip)
98
- program_start(slot, :size, :ip, no_debug)
99
- end
100
- end
101
-
102
- desc "stop", "stop a running program"
103
- def stop
104
- dc.program_stop(Lignite::USER_SLOT)
105
- end
106
-
107
- no_commands do
108
- def file_exist?(name)
109
- dirname = File.dirname(name)
110
- filename = File.basename(name)
111
- files = ls(dirname) || []
112
- files.include?(filename)
113
- end
114
-
115
- def assisted_connection
116
- Lignite::Connection.create
117
- rescue => e
118
- fn = Lignite::Connection::Bluetooth.config_filename
119
- $stderr.puts <<MSG
120
- Could not connect to EV3.
121
- Use a USB cable or configure a Bluetooth address in #{fn.inspect}.
122
- Details:
123
- #{e.message}
124
- MSG
125
-
126
- template = Lignite::Connection::Bluetooth.template_config_filename
127
- if !File.exist?(fn) && File.exist?(template)
128
- FileUtils.mkdir_p(File.dirname(fn))
129
- FileUtils.install(template, fn)
130
- $stderr.puts "(A template config file has been copied for your convenience)"
131
- end
132
- exit 1
133
- end
134
-
135
- def sc
136
- return @sc if @sc
137
- @sc = Lignite::SystemCommands.new(conn)
138
- end
139
-
140
- def dc
141
- return @dc if @dc
142
- @dc = Lignite::DirectCommands.new(conn)
143
- end
144
-
145
- def conn
146
- @conn ||= assisted_connection
147
- end
148
- end
149
- end
150
-
151
- Ev3Tool.start(ARGV)
4
+ Lignite::Ev3Tool.start(ARGV)
@@ -1,15 +1,17 @@
1
1
  #!/usr/bin/ruby
2
-
3
- # https://www.lego.com/mindstorms/build-a-robot/bobb3e
4
- # A Bobcat® like two-tracked forklift
5
-
6
2
  require "lignite"
7
3
 
4
+ # A Bobcat like two-tracked forklift.
5
+ # https://www.lego.com/mindstorms/build-a-robot/bobb3e
8
6
  class Bobbee
7
+ # The pair of motors driving the tracks
9
8
  # @return [Lignite::Motors]
10
9
  attr_reader :drive
10
+ # The motor lifting the fork
11
11
  # @return [Lignite::Motors]
12
12
  attr_reader :lift
13
+ # Interface to all other commands
14
+ # @return [Lignite::DirectCommands]
13
15
  attr_reader :dc
14
16
 
15
17
  def initialize(drive: Lignite::PORT_B | Lignite::PORT_C,
@@ -21,33 +23,34 @@ class Bobbee
21
23
  @dc = dc
22
24
  end
23
25
 
26
+ # @param speed [Integer] -100..100
24
27
  # @param turn [Integer] -200..200
25
- def time_sync(speed, turn, ms, brake = Lignite::BRAKE, wait: true)
26
- # 1500 ms is about 1 boost square at speed 100
27
- drive.time_sync(-speed, turn, ms, brake)
28
- end
29
-
30
- # @param turn [Integer] -200..200
28
+ # turn 0 (straight)
29
+ # - 900 (2.5 * 360) degrees is about 1 boost square
30
+ # turn 200 (full right)
31
+ # - 2400 degrees is a full turn, 600 deg is an about-right turn
32
+ # where the center of rotation is the battery-cover of the brick,
33
+ # or between the rear axles.
34
+ # turn 100 (semi right)
35
+ # - 4800 degrees is a full turn, about one of the rear axles
36
+ # @param degrees [Integer] degrees to turn the motors
37
+ # (complicated by gears and *turn*, which see)
38
+ # @param brake [BRAKE,COAST]
39
+ # @param wait [Boolean] work around my ignorance of motor readiness
31
40
  def step_sync(speed, turn, degrees, brake = Lignite::BRAKE, wait: true)
32
- # turn 0 (straight)
33
- # - 900 (2.5 * 360) degrees is about 1 boost square
34
- # turn 200 (full right)
35
- # - 2400 degrees is a full turn, 600 deg is an about-right turn
36
- # where the center of rotation is the battery-cover of the brick,
37
- # or between the rear axles.
38
- # turn 100 (semi right)
39
- # - 4800 degrees is a full turn, about one of the rear axles
40
41
  drive.step_sync(-speed, turn, degrees, brake)
41
42
  drive.ready if wait
42
43
  end
43
44
 
44
45
  LIFT_FULL = 220
45
46
 
47
+ # Raise the fork from the ground up
46
48
  def raise(wait: true)
47
49
  lift.step_power(30, 10, LIFT_FULL - 20, 10)
48
50
  lift.ready if wait
49
51
  end
50
52
 
53
+ # Raise the fork one third of the way from the ground up
51
54
  def third_raise(wait: true)
52
55
  lift.step_power(30, 10, LIFT_FULL / 3 - 20, 10)
53
56
  lift.ready if wait
@@ -56,6 +59,7 @@ class Bobbee
56
59
  sleep 3
57
60
  end
58
61
 
62
+ # Lower the fork from above to the ground
59
63
  def lower(wait: true)
60
64
  lift.step_power(-1, 10, LIFT_FULL - 20, 10) # , Lignite::COAST)
61
65
  lift.ready if wait
@@ -64,107 +68,125 @@ class Bobbee
64
68
  sleep 3
65
69
  end
66
70
 
71
+ # Lower the fork one third of the way from above to the ground
67
72
  def third_lower(wait: true)
68
73
  lift.step_power(-1, 10, LIFT_FULL / 3 - 20, 10)
69
74
  lift.ready if wait
70
75
  end
71
76
 
77
+ # Beep
72
78
  def beep(ms = 300)
73
79
  dc.sound_tone(20, 1760, ms)
74
80
  dc.sound_ready
75
81
  end
76
82
 
83
+ # steps to move 1 square on the Boost mat
77
84
  SQUARE_STEPS = 920
78
- def f(steps = SQUARE_STEPS)
85
+
86
+ # Drive forward 1 square on the Boost mat
87
+ def forward(steps = SQUARE_STEPS)
79
88
  step_sync(50, 0, steps)
80
89
  beep
81
90
  sleep 3
82
91
  end
83
92
 
84
- def b(steps = SQUARE_STEPS)
93
+ # Drive backward 1 square on the Boost mat
94
+ def back(steps = SQUARE_STEPS)
85
95
  step_sync(-50, 0, back_factor(steps))
86
96
  beep
87
97
  sleep 3
88
98
  end
89
99
 
90
- # it moves faster when going backwards!?
100
+ # Compensation factor when moving backward
91
101
  def back_factor(n)
102
+ # why? maybe the center of mass affects it
92
103
  (n * 0.95).to_i
93
104
  end
94
105
 
106
+ # If we want to turn inside a Boost mat square,
107
+ # we cannot simply make a turn since the center of rotation of the robot
108
+ # is between the rear axles which is not in the center of the square.
109
+ # So we need to move forward a bit, turn, and move back the same amount.
95
110
  ROTATION_OFFSET = 350
96
- def f1
97
- f(ROTATION_OFFSET)
111
+
112
+ def align_centers_for_turning(&turn_block)
113
+ forward(ROTATION_OFFSET)
114
+ beep(100)
115
+
116
+ turn_block.call
117
+
118
+ back(ROTATION_OFFSET)
98
119
  beep(100)
99
120
  end
100
121
 
122
+ # Motor degrees needed to turn the robot 90 degrees when using turn=200
101
123
  TURN_90_AT_200_STEPS = 600
102
- def l2
124
+
125
+ # Turn 90 degrees left, simply by moving tracks in opposite directions
126
+ def left_immediate
103
127
  step_sync(50, -200, TURN_90_AT_200_STEPS)
104
128
  beep(100)
105
129
  sleep 3
106
130
  end
107
131
 
108
- def r2
132
+ # Turn 90 degrees right, simply by moving tracks in opposite directions
133
+ def right_immediate
109
134
  step_sync(50, 200, TURN_90_AT_200_STEPS)
110
135
  beep(100)
111
136
  sleep 3
112
137
  end
113
138
 
114
- def f3
115
- b(ROTATION_OFFSET)
116
- beep(100)
117
- end
118
-
119
- def l
120
- # a 3 part maneuver: forward, left, and back-a-little
121
- # to turn 1 BS left
122
- f1
123
- l2
124
- f3
139
+ # Turn 90 degrees left, starting and ending inside a Boost mat square
140
+ def left
141
+ align_centers_for_turning do
142
+ left_immediate
143
+ end
125
144
  end
126
145
 
127
- def r
128
- # a 3 part maneuver: forward, right, and back-a-little
129
- # to turn 1 BS right
130
- f1
131
- r2
132
- f3
146
+ # Turn 90 degrees right, starting and ending inside a Boost mat square
147
+ def right
148
+ align_centers_for_turning do
149
+ right_immediate
150
+ end
133
151
  end
134
152
  end
135
153
 
136
154
  bb = Bobbee.new
137
- # 1 BS
138
- # bb.time_sync(100, 0, 1500)
139
155
 
140
- # Put Bobb3e on the blue arrow. Move it one square left, and forward.
141
- # Put the container on a raised platform on the "twins" square.
142
- # Put a raised platform on the "fire" square
156
+ # Put Bobb3e (B) on the blue arrow (^). Move it one square left, and forward.
157
+ # Put the container on a raised platform on the "twins" square (T).
158
+ # Put a raised platform on the "fire" square (F).
159
+ #
160
+ # ..F
161
+ # ...
162
+ # B.T
163
+ # .^.
143
164
  def from_twins_to_fire(bb)
144
165
  bb.instance_exec do
145
166
  beep
146
167
 
168
+ 2.times { third_raise }
169
+
170
+ right
171
+ forward
147
172
  third_raise
148
- third_raise
149
- r
150
- f
151
- third_raise
152
- b
153
- l
173
+ back
174
+ left
154
175
  # we're at the starting position, but carrying the load
155
176
 
156
177
  # move towards the recipient
157
- f; f; r
178
+ 2.times { forward }
179
+ right
158
180
 
159
181
  # deliver and unload
160
- f
182
+ forward
161
183
  third_lower
162
- b
184
+ back
163
185
 
164
186
  # resting position
165
- l; b; b
166
- third_lower
167
- third_lower
187
+ left
188
+ 2.times { back }
189
+ 2.times { third_lower }
168
190
  end
169
191
  end
170
192
 
@@ -172,37 +194,37 @@ def from_fire_to_twins(bb)
172
194
  bb.instance_exec do
173
195
  beep
174
196
 
175
- third_raise
176
- third_raise
197
+ 2.times { third_raise }
177
198
 
178
199
  # move towards the load
179
- f; f; r
200
+ 2.times { forward }
201
+ right
180
202
 
181
203
  # load
182
- f
204
+ forward
183
205
  third_raise
184
- b
206
+ back
185
207
 
186
208
  # starting position
187
- l; b; b
209
+ left
210
+ 2.times { back }
188
211
 
189
212
  # deliver
190
- r
191
- f
213
+ right
214
+ forward
192
215
  third_lower
193
- b
194
- l
216
+ back
217
+ left
195
218
 
196
219
  # resting position
197
- third_lower
198
- third_lower
220
+ 2.times { third_lower }
199
221
  end
200
222
  end
201
223
 
202
224
  def calibrate_forward_and_back(bb)
203
225
  bb.instance_exec do
204
- f; f; f; f
205
- b; b; b; b
226
+ 4.times { forward }
227
+ 4.times { back }
206
228
  end
207
229
  end
208
230