roomba 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +21 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/ext/extconf.rb +7 -0
- data/ext/roomba.c +325 -0
- data/ext/roombalib.c +302 -0
- data/ext/roombalib.h +118 -0
- data/lib/roomba.rb +0 -0
- data/spec/roomba_spec.rb +7 -0
- data/spec/spec_helper.rb +9 -0
- metadata +94 -0
data/.document
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Doug P.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
= roomba
|
2
|
+
|
3
|
+
Library to control a Roomba.
|
4
|
+
|
5
|
+
This code wraps the library found here:
|
6
|
+
http://roombahacking.com/roombahacks/roombacmd/
|
7
|
+
|
8
|
+
== Note on Patches/Pull Requests
|
9
|
+
|
10
|
+
* Fork the project.
|
11
|
+
* Make your feature addition or bug fix.
|
12
|
+
* Add tests for it. This is important so I don't break it in a
|
13
|
+
future version unintentionally.
|
14
|
+
* Commit, do not mess with rakefile, version, or history.
|
15
|
+
(if you want to have your own version, that is fine but
|
16
|
+
bump version in a commit by itself I can ignore when I pull)
|
17
|
+
* Send me a pull request. Bonus points for topic branches.
|
18
|
+
|
19
|
+
== Copyright
|
20
|
+
|
21
|
+
Copyright (c) 2010 Doug P. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "roomba"
|
8
|
+
gem.summary = %Q{Library to control a Roomba}
|
9
|
+
gem.description = %Q{Library to control a Roomba}
|
10
|
+
gem.email = "dougtko@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/dougsko/roomba"
|
12
|
+
gem.authors = ["Doug P."]
|
13
|
+
gem.add_development_dependency "rspec"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'spec/rake/spectask'
|
21
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
22
|
+
spec.libs << 'lib' << 'spec'
|
23
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
24
|
+
end
|
25
|
+
|
26
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
27
|
+
spec.libs << 'lib' << 'spec'
|
28
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
29
|
+
spec.rcov = true
|
30
|
+
end
|
31
|
+
|
32
|
+
task :spec => :check_dependencies
|
33
|
+
|
34
|
+
task :default => :spec
|
35
|
+
|
36
|
+
require 'rake/rdoctask'
|
37
|
+
Rake::RDocTask.new do |rdoc|
|
38
|
+
if File.exist?('VERSION')
|
39
|
+
version = File.read('VERSION')
|
40
|
+
else
|
41
|
+
version = ""
|
42
|
+
end
|
43
|
+
|
44
|
+
rdoc.rdoc_dir = 'rdoc'
|
45
|
+
rdoc.title = "roomba #{version}"
|
46
|
+
rdoc.rdoc_files.include('README*')
|
47
|
+
rdoc.rdoc_files.include('lib/**/*.rb', 'ext/**/*.c')
|
48
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/ext/extconf.rb
ADDED
data/ext/roomba.c
ADDED
@@ -0,0 +1,325 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "roombalib.h"
|
3
|
+
|
4
|
+
static VALUE cRoomba;
|
5
|
+
|
6
|
+
static void
|
7
|
+
roomba_destroy(Roomba *roomba)
|
8
|
+
{
|
9
|
+
roomba_free(roomba);
|
10
|
+
}
|
11
|
+
|
12
|
+
static VALUE
|
13
|
+
roomba_new(VALUE klass, VALUE rb_portname)
|
14
|
+
{
|
15
|
+
const char *portname;
|
16
|
+
struct Roomba *roomba;
|
17
|
+
|
18
|
+
portname = STR2CSTR(rb_portname);
|
19
|
+
roomba = roomba_init(portname);
|
20
|
+
return Data_Wrap_Struct(klass, 0, roomba_destroy, roomba);
|
21
|
+
}
|
22
|
+
|
23
|
+
static VALUE
|
24
|
+
close(VALUE self)
|
25
|
+
{
|
26
|
+
struct Roomba *roomba;
|
27
|
+
|
28
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
29
|
+
roomba_close(roomba);
|
30
|
+
return Qnil;
|
31
|
+
}
|
32
|
+
|
33
|
+
static VALUE
|
34
|
+
valid(VALUE self)
|
35
|
+
{
|
36
|
+
struct Roomba *roomba;
|
37
|
+
|
38
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
39
|
+
return INT2NUM(roomba_valid(roomba));
|
40
|
+
}
|
41
|
+
|
42
|
+
static VALUE get_portpath(VALUE self){
|
43
|
+
struct Roomba *roomba;
|
44
|
+
|
45
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
46
|
+
return rb_str_new2(roomba_get_portpath(roomba));
|
47
|
+
}
|
48
|
+
|
49
|
+
static VALUE
|
50
|
+
send(VALUE self, VALUE rb_cmd, VALUE rb_len)
|
51
|
+
{
|
52
|
+
struct Roomba *roomba;
|
53
|
+
const uint8_t *cmd;
|
54
|
+
int len;
|
55
|
+
|
56
|
+
cmd = STR2CSTR(rb_cmd);
|
57
|
+
len = NUM2INT(rb_len);
|
58
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
59
|
+
|
60
|
+
return INT2NUM(roomba_send(roomba, cmd, len));
|
61
|
+
}
|
62
|
+
|
63
|
+
static VALUE
|
64
|
+
drive(VALUE self, VALUE rb_vel, VALUE rb_rad)
|
65
|
+
{
|
66
|
+
struct Roomba *roomba;
|
67
|
+
int vel, rad;
|
68
|
+
|
69
|
+
vel = NUM2INT(rb_vel);
|
70
|
+
rad = NUM2INT(rb_rad);
|
71
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
72
|
+
|
73
|
+
roomba_drive(roomba, vel, rad);
|
74
|
+
return Qnil;
|
75
|
+
}
|
76
|
+
|
77
|
+
static VALUE
|
78
|
+
stop(VALUE self)
|
79
|
+
{
|
80
|
+
struct Roomba *roomba;
|
81
|
+
|
82
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
83
|
+
roomba_stop(roomba);
|
84
|
+
return Qnil;
|
85
|
+
}
|
86
|
+
|
87
|
+
static VALUE
|
88
|
+
forward(VALUE self)
|
89
|
+
{
|
90
|
+
struct Roomba *roomba;
|
91
|
+
|
92
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
93
|
+
roomba_forward(roomba);
|
94
|
+
return Qnil;
|
95
|
+
}
|
96
|
+
|
97
|
+
static VALUE
|
98
|
+
forward_at(VALUE self, VALUE rb_vel)
|
99
|
+
{
|
100
|
+
struct Roomba *roomba;
|
101
|
+
int vel;
|
102
|
+
|
103
|
+
vel = NUM2INT(rb_vel);
|
104
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
105
|
+
roomba_forward_at(roomba, vel);
|
106
|
+
return Qnil;
|
107
|
+
}
|
108
|
+
|
109
|
+
static VALUE
|
110
|
+
backward(VALUE self)
|
111
|
+
{
|
112
|
+
struct Roomba *roomba;
|
113
|
+
|
114
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
115
|
+
roomba_backward(roomba);
|
116
|
+
return Qnil;
|
117
|
+
}
|
118
|
+
|
119
|
+
static VALUE
|
120
|
+
backward_at(VALUE self, VALUE rb_vel)
|
121
|
+
{
|
122
|
+
struct Roomba *roomba;
|
123
|
+
int vel;
|
124
|
+
|
125
|
+
vel = NUM2INT(rb_vel);
|
126
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
127
|
+
roomba_backward_at(roomba, vel);
|
128
|
+
return Qnil;
|
129
|
+
}
|
130
|
+
|
131
|
+
static VALUE
|
132
|
+
spinleft(VALUE self)
|
133
|
+
{
|
134
|
+
struct Roomba *roomba;
|
135
|
+
|
136
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
137
|
+
roomba_spinleft(roomba);
|
138
|
+
return Qnil;
|
139
|
+
}
|
140
|
+
|
141
|
+
static VALUE
|
142
|
+
spinleft_at(VALUE self, VALUE rb_vel)
|
143
|
+
{
|
144
|
+
struct Roomba *roomba;
|
145
|
+
int vel;
|
146
|
+
|
147
|
+
vel = NUM2INT(rb_vel);
|
148
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
149
|
+
roomba_spinleft_at(roomba, vel);
|
150
|
+
return Qnil;
|
151
|
+
}
|
152
|
+
|
153
|
+
static VALUE
|
154
|
+
spinright(VALUE self)
|
155
|
+
{
|
156
|
+
struct Roomba *roomba;
|
157
|
+
|
158
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
159
|
+
roomba_spinright(roomba);
|
160
|
+
return Qnil;
|
161
|
+
}
|
162
|
+
|
163
|
+
static VALUE
|
164
|
+
spinright_at(VALUE self, VALUE rb_vel)
|
165
|
+
{
|
166
|
+
struct Roomba *roomba;
|
167
|
+
int vel;
|
168
|
+
|
169
|
+
vel = NUM2INT(rb_vel);
|
170
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
171
|
+
roomba_spinright_at(roomba, vel);
|
172
|
+
return Qnil;
|
173
|
+
}
|
174
|
+
|
175
|
+
static VALUE
|
176
|
+
set_velocity(VALUE self, VALUE rb_vel)
|
177
|
+
{
|
178
|
+
struct Roomba *roomba;
|
179
|
+
int vel;
|
180
|
+
|
181
|
+
vel = NUM2INT(rb_vel);
|
182
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
183
|
+
roomba_set_velocity(roomba, vel);
|
184
|
+
return Qnil;
|
185
|
+
}
|
186
|
+
|
187
|
+
static VALUE
|
188
|
+
get_velocity(VALUE self)
|
189
|
+
{
|
190
|
+
struct Roomba *roomba;
|
191
|
+
|
192
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
193
|
+
return INT2NUM(roomba_get_velocity(roomba));
|
194
|
+
}
|
195
|
+
|
196
|
+
static VALUE
|
197
|
+
play_note(VALUE self, VALUE rb_note, VALUE rb_duration)
|
198
|
+
{
|
199
|
+
struct Roomba *roomba;
|
200
|
+
uint8_t note, duration;
|
201
|
+
|
202
|
+
note = NUM2INT(rb_note);
|
203
|
+
duration = NUM2INT(rb_duration);
|
204
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
205
|
+
roomba_play_note(roomba, note, duration);
|
206
|
+
return Qnil;
|
207
|
+
}
|
208
|
+
|
209
|
+
static VALUE
|
210
|
+
set_motors(VALUE self, VALUE rb_mainbrush, VALUE rb_vacuum,
|
211
|
+
VALUE rb_sidebrush)
|
212
|
+
{
|
213
|
+
struct Roomba *roomba;
|
214
|
+
uint8_t mainbrush, vacuum, sidebrush;
|
215
|
+
|
216
|
+
mainbrush = NUM2INT(rb_mainbrush);
|
217
|
+
vacuum = NUM2INT(rb_vacuum);
|
218
|
+
sidebrush = NUM2INT(rb_sidebrush);
|
219
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
220
|
+
roomba_set_motors(roomba, mainbrush, vacuum, sidebrush);
|
221
|
+
return Qnil;
|
222
|
+
}
|
223
|
+
|
224
|
+
static VALUE
|
225
|
+
set_leds(VALUE self, VALUE rb_status_green, VALUE rb_status_red,
|
226
|
+
VALUE rb_spot, VALUE rb_clean, VALUE rb_max, VALUE rb_dirt,
|
227
|
+
VALUE rb_power_color, VALUE rb_power_intensity)
|
228
|
+
{
|
229
|
+
struct Roomba *roomba;
|
230
|
+
uint8_t status_green, status_red, spot, clean, max, dirt;
|
231
|
+
uint8_t power_color, power_intensity;
|
232
|
+
|
233
|
+
status_green = NUM2INT(rb_status_green);
|
234
|
+
status_red = NUM2INT(rb_status_red);
|
235
|
+
spot = NUM2INT(rb_spot);
|
236
|
+
clean = NUM2INT(rb_clean);
|
237
|
+
max = NUM2INT(rb_max);
|
238
|
+
dirt = NUM2INT(rb_dirt);
|
239
|
+
power_color = NUM2INT(rb_power_color);
|
240
|
+
power_intensity = NUM2INT(rb_power_intensity);
|
241
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
242
|
+
roomba_set_leds(roomba, status_green, status_red, spot, clean,
|
243
|
+
max, dirt, power_color, power_intensity);
|
244
|
+
return Qnil;
|
245
|
+
}
|
246
|
+
|
247
|
+
static VALUE
|
248
|
+
vacuum(VALUE self, VALUE rb_state)
|
249
|
+
{
|
250
|
+
struct Roomba *roomba;
|
251
|
+
uint8_t state;
|
252
|
+
|
253
|
+
state = NUM2INT(rb_state);
|
254
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
255
|
+
roomba_vacuum(roomba, state);
|
256
|
+
return Qnil;
|
257
|
+
}
|
258
|
+
|
259
|
+
static VALUE
|
260
|
+
read_sensors(VALUE self)
|
261
|
+
{
|
262
|
+
struct Roomba *roomba;
|
263
|
+
|
264
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
265
|
+
return INT2NUM(roomba_read_sensors(roomba));
|
266
|
+
}
|
267
|
+
|
268
|
+
static VALUE
|
269
|
+
print_sensors(VALUE self)
|
270
|
+
{
|
271
|
+
struct Roomba *roomba;
|
272
|
+
|
273
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
274
|
+
roomba_print_sensors(roomba);
|
275
|
+
return Qnil;
|
276
|
+
}
|
277
|
+
|
278
|
+
static VALUE
|
279
|
+
print_raw_sensors(VALUE self)
|
280
|
+
{
|
281
|
+
struct Roomba *roomba;
|
282
|
+
|
283
|
+
Data_Get_Struct(self, struct Roomba, roomba);
|
284
|
+
roomba_print_raw_sensors(roomba);
|
285
|
+
return Qnil;
|
286
|
+
}
|
287
|
+
|
288
|
+
static VALUE
|
289
|
+
delay(VALUE self, VALUE rb_millisecs)
|
290
|
+
{
|
291
|
+
int millisecs;
|
292
|
+
|
293
|
+
millisecs = NUM2INT(rb_millisecs);
|
294
|
+
roomba_delay(millisecs);
|
295
|
+
return Qnil;
|
296
|
+
}
|
297
|
+
|
298
|
+
void Init_roomba(){
|
299
|
+
cRoomba = rb_define_class("Roomba", rb_cObject);
|
300
|
+
rb_define_singleton_method(cRoomba, "new", roomba_new, 1);
|
301
|
+
rb_define_method(cRoomba, "close", close, 0);
|
302
|
+
rb_define_method(cRoomba, "valid", valid, 0);
|
303
|
+
rb_define_method(cRoomba, "get_portpath", get_portpath, 0);
|
304
|
+
rb_define_method(cRoomba, "send", send, 2);
|
305
|
+
rb_define_method(cRoomba, "drive", drive, 2);
|
306
|
+
rb_define_method(cRoomba, "stop", stop, 0);
|
307
|
+
rb_define_method(cRoomba, "forward", forward, 0);
|
308
|
+
rb_define_method(cRoomba, "forward_at", forward_at, 1);
|
309
|
+
rb_define_method(cRoomba, "backward", backward, 0);
|
310
|
+
rb_define_method(cRoomba, "backward_at", backward_at, 1);
|
311
|
+
rb_define_method(cRoomba, "spinleft", spinleft, 0);
|
312
|
+
rb_define_method(cRoomba, "spinleft_at", spinleft_at, 1);
|
313
|
+
rb_define_method(cRoomba, "spinright", spinright, 0);
|
314
|
+
rb_define_method(cRoomba, "spinright_at", spinright_at, 1);
|
315
|
+
rb_define_method(cRoomba, "set_velocity", set_velocity, 1);
|
316
|
+
rb_define_method(cRoomba, "get_velocity", get_velocity, 0);
|
317
|
+
rb_define_method(cRoomba, "play_note", play_note, 2);
|
318
|
+
rb_define_method(cRoomba, "set_motors", set_motors, 3);
|
319
|
+
rb_define_method(cRoomba, "set_leds", set_leds, 8);
|
320
|
+
rb_define_method(cRoomba, "vacuum", vacuum, 1);
|
321
|
+
rb_define_method(cRoomba, "read_sensors", read_sensors, 0);
|
322
|
+
rb_define_method(cRoomba, "print_sensors", print_sensors, 0);
|
323
|
+
rb_define_method(cRoomba, "print_raw_sensors", print_raw_sensors, 0);
|
324
|
+
rb_define_method(cRoomba, "delay", delay, 0);
|
325
|
+
}
|
data/ext/roombalib.c
ADDED
@@ -0,0 +1,302 @@
|
|
1
|
+
/*
|
2
|
+
* roombalib -- Roomba C API
|
3
|
+
*
|
4
|
+
* http://hackingroomba.com/
|
5
|
+
*
|
6
|
+
* Copyright (C) 2006, Tod E. Kurt, tod@todbot.com
|
7
|
+
*
|
8
|
+
* Updates:
|
9
|
+
* 14 Dec 2006 - added more functions to roombalib
|
10
|
+
*/
|
11
|
+
|
12
|
+
|
13
|
+
#include <stdio.h> /* Standard input/output definitions */
|
14
|
+
#include <stdint.h> /* Standard types */
|
15
|
+
#include <stdlib.h> /* calloc, strtol */
|
16
|
+
#include <string.h> /* strcpy */
|
17
|
+
#include <unistd.h> /* UNIX standard function definitions */
|
18
|
+
#include <fcntl.h> /* File control definitions */
|
19
|
+
#include <errno.h> /* Error number definitions */
|
20
|
+
#include <termios.h> /* POSIX terminal control definitions */
|
21
|
+
#include <sys/ioctl.h>
|
22
|
+
|
23
|
+
#include "roombalib.h"
|
24
|
+
|
25
|
+
int roombadebug = 0;
|
26
|
+
|
27
|
+
// internal use only
|
28
|
+
int roomba_init_serialport( const char* serialport, speed_t baud );
|
29
|
+
|
30
|
+
Roomba* roomba_init( const char* portpath )
|
31
|
+
{
|
32
|
+
int fd = roomba_init_serialport( portpath, B57600 );
|
33
|
+
if( fd == -1 ) return NULL;
|
34
|
+
uint8_t cmd[1];
|
35
|
+
|
36
|
+
cmd[0] = 128; // START
|
37
|
+
int n = write(fd, cmd, 1);
|
38
|
+
if( n!=1 ) {
|
39
|
+
perror("open_port: Unable to write to port ");
|
40
|
+
return NULL;
|
41
|
+
}
|
42
|
+
roomba_delay(COMMANDPAUSE_MILLIS);
|
43
|
+
|
44
|
+
cmd[0] = 130; // CONTROL
|
45
|
+
n = write(fd, cmd, 1);
|
46
|
+
if( n!=1 ) {
|
47
|
+
perror("open_port: Unable to write to port ");
|
48
|
+
return NULL;
|
49
|
+
}
|
50
|
+
roomba_delay(COMMANDPAUSE_MILLIS);
|
51
|
+
|
52
|
+
Roomba* roomba = calloc( 1, sizeof(Roomba) );
|
53
|
+
roomba->fd = fd;
|
54
|
+
strcpy(roomba->portpath, portpath);
|
55
|
+
roomba->velocity = DEFAULT_VELOCITY;
|
56
|
+
|
57
|
+
return roomba;
|
58
|
+
}
|
59
|
+
|
60
|
+
void roomba_free( Roomba* roomba )
|
61
|
+
{
|
62
|
+
if( roomba!= NULL ) {
|
63
|
+
if( roomba->fd ) roomba_close( roomba );
|
64
|
+
free( roomba );
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
const char* roomba_get_portpath( Roomba* roomba )
|
69
|
+
{
|
70
|
+
return roomba->portpath;
|
71
|
+
}
|
72
|
+
|
73
|
+
void roomba_close( Roomba* roomba )
|
74
|
+
{
|
75
|
+
close( roomba->fd );
|
76
|
+
roomba->fd = 0;
|
77
|
+
}
|
78
|
+
|
79
|
+
// is this Roomba pointer valid (but not necc connected)
|
80
|
+
int roomba_valid( Roomba* roomba )
|
81
|
+
{
|
82
|
+
return (roomba!=NULL && roomba->fd != 0);
|
83
|
+
}
|
84
|
+
|
85
|
+
void roomba_set_velocity( Roomba* roomba, int vel )
|
86
|
+
{
|
87
|
+
roomba->velocity = vel;
|
88
|
+
}
|
89
|
+
|
90
|
+
int roomba_get_velocity( Roomba* roomba )
|
91
|
+
{
|
92
|
+
return roomba->velocity;
|
93
|
+
}
|
94
|
+
|
95
|
+
// send an arbitrary length roomba command
|
96
|
+
int roomba_send( Roomba* roomba, const uint8_t* cmd, int len )
|
97
|
+
{
|
98
|
+
int n = write( roomba->fd, cmd, len);
|
99
|
+
if( n!=len )
|
100
|
+
perror("roomba_send: couldn't write to roomba");
|
101
|
+
return (n!=len); // indicate error, can usually ignore
|
102
|
+
}
|
103
|
+
|
104
|
+
// Move Roomba with low-level DRIVE command
|
105
|
+
void roomba_drive( Roomba* roomba, int velocity, int radius )
|
106
|
+
{
|
107
|
+
uint8_t vhi = velocity >> 8;
|
108
|
+
uint8_t vlo = velocity & 0xff;
|
109
|
+
uint8_t rhi = radius >> 8;
|
110
|
+
uint8_t rlo = radius & 0xff;
|
111
|
+
if(roombadebug)
|
112
|
+
fprintf(stderr,"roomba_drive: %.2hhx %.2hhx %.2hhx %.2hhx\n",
|
113
|
+
vhi,vlo,rhi,rlo);
|
114
|
+
uint8_t cmd[] = { 137, vhi,vlo, rhi,rlo }; // DRIVE
|
115
|
+
int n = write(roomba->fd, cmd, 5);
|
116
|
+
if( n!=5 )
|
117
|
+
perror("roomba_drive: couldn't write to roomba");
|
118
|
+
}
|
119
|
+
|
120
|
+
void roomba_stop( Roomba* roomba )
|
121
|
+
{
|
122
|
+
roomba_drive( roomba, 0, 0 );
|
123
|
+
}
|
124
|
+
|
125
|
+
void roomba_forward( Roomba* roomba )
|
126
|
+
{
|
127
|
+
roomba_drive( roomba, roomba->velocity, 0x8000 ); // 0x8000 = straight
|
128
|
+
}
|
129
|
+
void roomba_forward_at( Roomba* roomba, int velocity )
|
130
|
+
{
|
131
|
+
roomba_drive( roomba, velocity, 0x8000 );
|
132
|
+
}
|
133
|
+
|
134
|
+
void roomba_backward( Roomba* roomba )
|
135
|
+
{
|
136
|
+
roomba_drive( roomba, -roomba->velocity, 0x8000 );
|
137
|
+
}
|
138
|
+
void roomba_backward_at( Roomba* roomba, int velocity )
|
139
|
+
{
|
140
|
+
roomba_drive( roomba, -velocity, 0x8000 );
|
141
|
+
}
|
142
|
+
|
143
|
+
void roomba_spinleft( Roomba* roomba )
|
144
|
+
{
|
145
|
+
roomba_drive( roomba, roomba->velocity, 1 );
|
146
|
+
}
|
147
|
+
void roomba_spinleft_at( Roomba* roomba, int velocity )
|
148
|
+
{
|
149
|
+
roomba_drive( roomba, velocity, 1 );
|
150
|
+
}
|
151
|
+
|
152
|
+
void roomba_spinright( Roomba* roomba )
|
153
|
+
{
|
154
|
+
roomba_drive( roomba, roomba->velocity, -1 );
|
155
|
+
}
|
156
|
+
void roomba_spinright_at( Roomba* roomba, int velocity )
|
157
|
+
{
|
158
|
+
roomba_drive( roomba, velocity, -1 );
|
159
|
+
}
|
160
|
+
|
161
|
+
void roomba_play_note( Roomba* roomba, uint8_t note, uint8_t duration )
|
162
|
+
{
|
163
|
+
uint8_t cmd[] = { 140, 15, 1, note, duration, // SONG, then
|
164
|
+
141, 15 }; // PLAY
|
165
|
+
int n = write( roomba->fd, cmd, 7);
|
166
|
+
if( n!=7 )
|
167
|
+
perror("roomba_play_note: couldn't write to roomba");
|
168
|
+
}
|
169
|
+
|
170
|
+
// Turns on/off the non-drive motors (main brush, vacuum, sidebrush).
|
171
|
+
void roomba_set_motors( Roomba* roomba, uint8_t mainbrush, uint8_t vacuum, uint8_t sidebrush)
|
172
|
+
{
|
173
|
+
uint8_t cmd[] = { 138, // MOTORS
|
174
|
+
((mainbrush?0x04:0)|(vacuum?0x02:0)|(sidebrush?0x01:0))};
|
175
|
+
int n = write( roomba->fd, cmd, 2);
|
176
|
+
if( n!=2 )
|
177
|
+
perror("roomba_set_motors: couldn't write to roomba");
|
178
|
+
}
|
179
|
+
|
180
|
+
// Turns on/off the various LEDs.
|
181
|
+
void roomba_set_leds( Roomba* roomba, uint8_t status_green, uint8_t status_red,
|
182
|
+
uint8_t spot, uint8_t clean, uint8_t max, uint8_t dirt,
|
183
|
+
uint8_t power_color, uint8_t power_intensity )
|
184
|
+
{
|
185
|
+
uint8_t v = (status_green?0x20:0) | (status_red?0x10:0) |
|
186
|
+
(spot?0x08:0) | (clean?0x04:0) | (max?0x02:0) | (dirt?0x01:0);
|
187
|
+
uint8_t cmd[] = { 139, v, power_color, power_intensity }; // LEDS
|
188
|
+
int n = write( roomba->fd, cmd, 4);
|
189
|
+
if( n!=4 )
|
190
|
+
perror("roomba_set_leds: couldn't write to roomba");
|
191
|
+
}
|
192
|
+
|
193
|
+
// Turn all vacuum motors on or off according to state
|
194
|
+
void roomba_vacuum( Roomba* roomba, uint8_t state ) {
|
195
|
+
roomba_set_motors( roomba, state,state,state);
|
196
|
+
}
|
197
|
+
|
198
|
+
int roomba_read_sensors( Roomba* roomba )
|
199
|
+
{
|
200
|
+
uint8_t cmd[] = { 142, 0 }; // SENSOR, get all sensor data
|
201
|
+
int n = write( roomba->fd, cmd, 2);
|
202
|
+
roomba_delay(COMMANDPAUSE_MILLIS); //hmm, why isn't VMIN & VTIME working?
|
203
|
+
n = read( roomba->fd, roomba->sensor_bytes, 26);
|
204
|
+
if( n!=26 ) {
|
205
|
+
if(roombadebug)
|
206
|
+
fprintf(stderr,"roomba_read_sensors: not enough read (n=%d)\n",n);
|
207
|
+
return -1;
|
208
|
+
}
|
209
|
+
return 0;
|
210
|
+
}
|
211
|
+
|
212
|
+
void roomba_print_raw_sensors( Roomba* roomba )
|
213
|
+
{
|
214
|
+
uint8_t* sb = roomba->sensor_bytes;
|
215
|
+
int i;
|
216
|
+
for(i=0;i<26;i++) {
|
217
|
+
printf("%.2hhx ",sb[i]);
|
218
|
+
}
|
219
|
+
printf("\n");
|
220
|
+
}
|
221
|
+
|
222
|
+
void roomba_print_sensors( Roomba* roomba )
|
223
|
+
{
|
224
|
+
uint8_t* sb = roomba->sensor_bytes;
|
225
|
+
printf("bump: %x %x\n", bump_left(sb[0]), bump_right(sb[0]));
|
226
|
+
printf("wheeldrop: %x %x %x\n", wheeldrop_left(sb[0]),
|
227
|
+
wheeldrop_caster(sb[0]), wheeldrop_right(sb[0]));
|
228
|
+
printf("wall: %x\n", sb[1]);
|
229
|
+
printf("cliff: %x %x %x %x\n", sb[2],sb[3],sb[4],sb[5] );
|
230
|
+
printf("virtual_wall: %x\n", sb[6]);
|
231
|
+
printf("motor_overcurrents: %x %x %x %x %x\n", motorover_driveleft(sb[7]),
|
232
|
+
motorover_driveright(sb[7]), motorover_mainbrush(sb[7]),
|
233
|
+
motorover_sidebrush(sb[7]), motorover_vacuum(sb[7]));
|
234
|
+
printf("dirt: %x %x\n", sb[8],sb[9]);
|
235
|
+
printf("remote_opcode: %.2hhx\n", sb[10]);
|
236
|
+
printf("buttons: %.2hhx\n", sb[11]);
|
237
|
+
printf("distance: %.4x\n", (sb[12]<<8) | sb[13] );
|
238
|
+
printf("angle: %.4x\n", (sb[14]<<8) | sb[15] );
|
239
|
+
printf("charging_state: %.2hhx\n", sb[16]);
|
240
|
+
printf("voltage: %d\n", (sb[17]<<8) | sb[18] );
|
241
|
+
printf("current: %d\n", ((int8_t)sb[19]<<8) | sb[20] );
|
242
|
+
printf("temperature: %d\n", sb[21]);
|
243
|
+
printf("charge: %d\n", (sb[22]<<8) | sb[23] );
|
244
|
+
printf("capacity: %d\n", (sb[24]<<8) | sb[25] );
|
245
|
+
}
|
246
|
+
|
247
|
+
// 100,000 us == 100 ms == 0.1s
|
248
|
+
void roomba_delay( int millisecs )
|
249
|
+
{
|
250
|
+
usleep( millisecs * 1000 );
|
251
|
+
}
|
252
|
+
|
253
|
+
|
254
|
+
|
255
|
+
// private
|
256
|
+
// returns valid fd, or -1 on error
|
257
|
+
int roomba_init_serialport( const char* serialport, speed_t baud )
|
258
|
+
{
|
259
|
+
struct termios toptions;
|
260
|
+
int fd;
|
261
|
+
|
262
|
+
if(roombadebug)
|
263
|
+
fprintf(stderr,"roomba_init_serialport: opening port %s\n",serialport);
|
264
|
+
|
265
|
+
fd = open( serialport, O_RDWR | O_NOCTTY | O_NDELAY );
|
266
|
+
if (fd == -1) { // Could not open the port.
|
267
|
+
perror("roomba_init_serialport: Unable to open port ");
|
268
|
+
return -1;
|
269
|
+
}
|
270
|
+
|
271
|
+
if (tcgetattr(fd, &toptions) < 0) {
|
272
|
+
perror("roomba_init_serialport: Couldn't get term attributes");
|
273
|
+
return -1;
|
274
|
+
}
|
275
|
+
|
276
|
+
cfsetispeed(&toptions, baud);
|
277
|
+
cfsetospeed(&toptions, baud);
|
278
|
+
|
279
|
+
// 8N1
|
280
|
+
toptions.c_cflag &= ~PARENB;
|
281
|
+
toptions.c_cflag &= ~CSTOPB;
|
282
|
+
toptions.c_cflag &= ~CSIZE;
|
283
|
+
toptions.c_cflag |= CS8;
|
284
|
+
// no flow control
|
285
|
+
toptions.c_cflag &= ~CRTSCTS;
|
286
|
+
|
287
|
+
toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
|
288
|
+
toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
|
289
|
+
|
290
|
+
toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
|
291
|
+
toptions.c_oflag &= ~OPOST; // make raw
|
292
|
+
|
293
|
+
toptions.c_cc[VMIN] = 26;
|
294
|
+
toptions.c_cc[VTIME] = 2; // FIXME: not sure about this
|
295
|
+
|
296
|
+
if( tcsetattr(fd, TCSANOW, &toptions) < 0) {
|
297
|
+
perror("roomba_init_serialport: Couldn't set term attributes");
|
298
|
+
return -1;
|
299
|
+
}
|
300
|
+
|
301
|
+
return fd;
|
302
|
+
}
|
data/ext/roombalib.h
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
/*
|
2
|
+
* roombalib -- Roomba C API
|
3
|
+
*
|
4
|
+
* http://hackingroomba.com/
|
5
|
+
*
|
6
|
+
* Copyright (C) 2006, Tod E. Kurt, tod@todbot.com
|
7
|
+
*
|
8
|
+
* Updates:
|
9
|
+
* 14 Dec 2006 - added more functions to roombalib
|
10
|
+
*/
|
11
|
+
|
12
|
+
|
13
|
+
#include <stdint.h> /* Standard types */
|
14
|
+
|
15
|
+
#define DEFAULT_VELOCITY 200
|
16
|
+
#define COMMANDPAUSE_MILLIS 100
|
17
|
+
|
18
|
+
// holds all the per-roomba info
|
19
|
+
// consider it an opaque blob, please
|
20
|
+
typedef struct Roomba_struct {
|
21
|
+
int fd;
|
22
|
+
char portpath[80];
|
23
|
+
uint8_t sensor_bytes[26];
|
24
|
+
int velocity;
|
25
|
+
} Roomba;
|
26
|
+
|
27
|
+
// set to non-zero to see debugging output
|
28
|
+
extern int roombadebug;
|
29
|
+
|
30
|
+
// given a serial port name, create a Roomba object and return it
|
31
|
+
// or return NULL on error
|
32
|
+
Roomba* roomba_init( const char* portname );
|
33
|
+
|
34
|
+
// frees the memory of the Roomba object created with roomba_init
|
35
|
+
// will close the serial port if it's open
|
36
|
+
void roomba_free( Roomba* roomba );
|
37
|
+
|
38
|
+
// close the serial port connected to the Roomba
|
39
|
+
void roomba_close( Roomba* roomba );
|
40
|
+
|
41
|
+
// is this Roomba pointer valid (but not necc connected)
|
42
|
+
int roomba_valid( Roomba* roomba );
|
43
|
+
|
44
|
+
// return the serial port path for the given roomba
|
45
|
+
const char* roomba_get_portpath( Roomba* roomba );
|
46
|
+
|
47
|
+
// send an arbitrary length roomba command
|
48
|
+
int roomba_send( Roomba* roomba, const uint8_t* cmd, int len );
|
49
|
+
|
50
|
+
// Move Roomba with low-level DRIVE command
|
51
|
+
void roomba_drive( Roomba* roomba, int velocity, int radius );
|
52
|
+
|
53
|
+
// stop the Roomba
|
54
|
+
void roomba_stop( Roomba* roomba );
|
55
|
+
|
56
|
+
// Move Roomba forward at current velocity
|
57
|
+
void roomba_forward( Roomba* roomba );
|
58
|
+
void roomba_forward_at( Roomba* roomba, int velocity );
|
59
|
+
|
60
|
+
// Move Roomba backward at current velocity
|
61
|
+
void roomba_backward( Roomba* roomba );
|
62
|
+
void roomba_backward_at( Roomba* roomba, int velocity );
|
63
|
+
|
64
|
+
// Spin Roomba left at current velocity
|
65
|
+
void roomba_spinleft( Roomba* roomba );
|
66
|
+
void roomba_spinleft_at( Roomba* roomba, int velocity );
|
67
|
+
|
68
|
+
// Spin Roomba right at current velocity
|
69
|
+
void roomba_spinright( Roomba* roomba );
|
70
|
+
void roomba_spinright_at( Roomba* roomba, int velocity );
|
71
|
+
|
72
|
+
// Set current velocity for higher-level movement commands
|
73
|
+
void roomba_set_velocity( Roomba* roomba, int velocity );
|
74
|
+
|
75
|
+
// Get current velocity for higher-level movement commands
|
76
|
+
int roomba_get_velocity( Roomba* roomba );
|
77
|
+
|
78
|
+
// play a musical note
|
79
|
+
void roomba_play_note( Roomba* roomba, uint8_t note, uint8_t duration );
|
80
|
+
|
81
|
+
// Turns on/off the non-drive motors (main brush, vacuum, sidebrush).
|
82
|
+
void roomba_set_motors( Roomba* roomba, uint8_t mainbrush, uint8_t vacuum, uint8_t sidebrush);
|
83
|
+
|
84
|
+
// Turns on/off the various LEDs.
|
85
|
+
void roomba_set_leds( Roomba* roomba, uint8_t status_green, uint8_t status_red,
|
86
|
+
uint8_t spot, uint8_t clean, uint8_t max, uint8_t dirt,
|
87
|
+
uint8_t power_color, uint8_t power_intensity );
|
88
|
+
|
89
|
+
// Turn all vacuum motors on or off according to state
|
90
|
+
void roomba_vacuum( Roomba* roomba, uint8_t state );
|
91
|
+
|
92
|
+
// Get the sensor data from the Roomba
|
93
|
+
// returns -1 on failure
|
94
|
+
int roomba_read_sensors( Roomba* roomba );
|
95
|
+
|
96
|
+
// print existing sensor data nicely
|
97
|
+
void roomba_print_sensors( Roomba* roomba );
|
98
|
+
|
99
|
+
// print existing sensor data as string of hex chars
|
100
|
+
void roomba_print_raw_sensors( Roomba* roomba );
|
101
|
+
|
102
|
+
// utility function
|
103
|
+
void roomba_delay( int millisecs );
|
104
|
+
#define roomba_wait roomba_delay
|
105
|
+
|
106
|
+
// some simple macros of bit manipulations
|
107
|
+
#define bump_right(b) ((b & 0x01)!=0)
|
108
|
+
#define bump_left(b) ((b & 0x02)!=0)
|
109
|
+
#define wheeldrop_right(b) ((b & 0x04)!=0)
|
110
|
+
#define wheeldrop_left(b) ((b & 0x08)!=0)
|
111
|
+
#define wheeldrop_caster(b) ((b & 0x10)!=0)
|
112
|
+
|
113
|
+
#define motorover_sidebrush(b) ((b & 0x01)!=0)
|
114
|
+
#define motorover_vacuum(b) ((b & 0x02)!=0)
|
115
|
+
#define motorover_mainbrush(b) ((b & 0x04)!=0)
|
116
|
+
#define motorover_driveright(b) ((b & 0x08)!=0)
|
117
|
+
#define motorover_driveleft(b) ((b & 0x10)!=0)
|
118
|
+
|
data/lib/roomba.rb
ADDED
File without changes
|
data/spec/roomba_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: roomba
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Doug P.
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-08-28 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
description: Library to control a Roomba
|
36
|
+
email: dougtko@gmail.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions:
|
40
|
+
- ext/extconf.rb
|
41
|
+
extra_rdoc_files:
|
42
|
+
- LICENSE
|
43
|
+
- README.rdoc
|
44
|
+
files:
|
45
|
+
- .document
|
46
|
+
- .gitignore
|
47
|
+
- LICENSE
|
48
|
+
- README.rdoc
|
49
|
+
- Rakefile
|
50
|
+
- VERSION
|
51
|
+
- ext/extconf.rb
|
52
|
+
- ext/roomba.c
|
53
|
+
- ext/roombalib.c
|
54
|
+
- ext/roombalib.h
|
55
|
+
- lib/roomba.rb
|
56
|
+
- spec/roomba_spec.rb
|
57
|
+
- spec/spec_helper.rb
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: http://github.com/dougsko/roomba
|
60
|
+
licenses: []
|
61
|
+
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options:
|
64
|
+
- --charset=UTF-8
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
hash: 3
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.3.7
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: Library to control a Roomba
|
92
|
+
test_files:
|
93
|
+
- spec/roomba_spec.rb
|
94
|
+
- spec/spec_helper.rb
|