roomba: iRobot Roomba/Create Interface in Racket
(require (planet neil/roomba:1:0)) |
1 Introduction
2 Logging
This package sends logging messages to the Racket logger, naming the messages as “roomba”. This includes debug level messages for each use of most of this package’s API. You can see these messages in the usual Racket ways, such as by using the PLTSTDERR environment variable, or via the DrRacket Log window.
3 Exceptions
struct
(struct exn:fail:roomba exn:fail (roomba))
roomba : roomba?
struct
(struct exn:fail:roomba:io exn:fail:roomba ())
struct
(struct exn:fail:roomba:mode exn:fail:roomba (expected actual))
expected : (listof symbol?) actual : symbol?
4 Protocols
5 Models
> (decode-roomba-manufacturing-code "JEN041100610060012345")
'((manufacturer . jetta) |
(status . new) |
(model . 4110) |
(date . #(2006 10 6)) |
(rev . 0) |
(serial . 12345)) |
parameter
→
(hash/c (or/c exact-nonnegative-integer? symbol?) roomba-model?) (current-number-to-roomba-model-hash hasheqv) → void?
hasheqv :
(hash/c (or/c exact-nonnegative-integer? symbol?) roomba-model?)
Second Generation —
'second-generation 1100 'series-4000 'series-400 4000 400 4100 410 4105 416 4110 'sagelike-4130 'discolike-4130 4150 4170 4188 4210 4220 4225 4230 4260 500 Series —
'series-500 510 530 532 535 550 560 562 564 570 571 572 580 581 600 Series —
'series-600 610 620 630 650 660 Create —
'create 4400 4418
parameter
→ (or/c roomba-model? exact-nonnegative-integer? symbol?) (current-default-roomba-model model) → void? model : (or/c roomba-model? exact-nonnegative-integer? symbol?)
6 Roomba Object
parameter
(current-roomba roomba) → void? roomba : roomba?
7 Opening and Closing
parameter
(current-default-roomba-device path) → void? path : path-string?
procedure
(open-roomba [ #:name name #:model model #:device device #:set-current? set-current?]) → roomba name : (or/c #f string?) = #f
model : (or/c roomba-model? exact-nonnegative-integer? symbol?) = (current-roomba-default-model) device : path-string? = (current-default-roomba-device) set-current? : boolean? = #true
syntax
(with-roomba maybe-name maybe-model maybe-device body ...+)
maybe-name =
| #:name string? maybe-model =
|
#:model (or/c roomba-model? exact-nonnegative-integer? symbol?) maybe-device =
| #:device string?
8 Modes
'off —
Powered off or sleeping, and you probably need to manually press a button to wake it up. 'passive —
Sensors can be read, but cannot be controlled in this mode. 'safe —
Can be controlled. Lift and cliff sensors, or plugging into charger, do trigger switch to 'passive mode. 'safe is the usual mode for most purposes. 'full —
Can be controlled. Lift and cliff sensors, and charger plugging do not switch Roomba to 'passive mode. Switching to 'full mode also stops any battery charging. Don’t use 'full mode unless you’re sure you need to, and you can cover the safety risks other ways. 'closed —
This connection with the Roomba is closed, so this connection does not know the mode. The mode is changed to this when close-roomba is called, when with-roomba exits, or when an I/O error occurs when attempting to talk with the Roomba.
procedure
(set-roomba-mode [ #:roomba roomba] #:mode mode) → void? roomba : roomba? = (current-roomba) mode : (or/c 'safe 'full 'off)
9 Stock Behaviors
9.1 Cleaning
9.2 Docking
10 Driving
procedure
(set-roomba-drive [ #:roomba roomba] #:velocity-mm/s velocity-mm/s #:radius-mm radius-mm) → void? roomba : roomba? = (current-roomba) velocity-mm/s : integer? radius-mm : ((or/c #f integer?) #f)
11 Motors
procedure
(set-roomba-motors [ #:roomba roomba #:side-brush? side-brush? #:vacuum? vacuum? #:main-brush? main-brush?]) → void? roomba : roomba? = (current-roomba) side-brush? : boolean? = #false vacuum? : boolean? = #false main-brush? : boolean? = #false
12 Lights
procedure
(set-roomba-leds [ #:roomba roomba #:debris? debris? #:max? max? #:clean? clean? #:spot? spot? #:dock? dock? #:check? check? #:play? play? #:advance? advance? #:status status #:power-color power-color #:power-intensity power-intensity]) → void? roomba : roomba? = (current-roomba) debris? : boolean? = #false max? : boolean? = #false clean? : boolean? = #false spot? : boolean? = #false dock? : boolean? = #false check? : boolean? = #false play? : boolean? = #false advance? : boolean? = #false status : (or/c #f 'red 'green 'amber) = #false power-color : byte? = 0 power-intensity : byte? = 0
Variable
Labels
Series
debris?
Dirt Detect, Dirt Alert, Debris
2nd, 500, 600
max?
Max
2nd
clean?
Clean
2nd
spot?
Spot
2nd, 500, 600
dock?
Dock
500, 600
check?
Check Robot
500, 600
play?
Play
Create
advance?
Advance
Create
status
Status
2nd
power-color,
power-intensity
Power (Clean)
2nd, 500, Create
13 Sound
| ‹song-language› | ::= | ( ‹note›+ ) |
| ‹note› | ::= | ‹frequency› |
|
| | | ( ‹frequency› ‹duration› ) |
| ‹frequency› | ::= | symbol? |
|
| | | number? |
| ‹duration› | ::= | whole |
|
| | | w |
|
| | | half |
|
| | | h |
|
| | | quarter |
|
| | | q |
|
| | | number? |
'(b a g a b b (b h) a a (a h) b d (d h))
procedure
(compile-roomba-song [ #:roomba roomba #:song-number song-number] #:song-language song-language) → roomba-song? roomba : roomba? = (current-roomba) song-number : roomba-song-number? = 0 song-language : roomba-song-language?
procedure
(store-song-on-roomba [ #:roomba roomba #:song-number song-number] #:song song) → void? roomba : roomba? = (current-roomba) song-number : roomba-song-number? = 0 song : (or/c roomba-song-language? compiled-roomba-song?)
procedure
(play-song-on-roomba [ #:roomba roomba #:song-number number]) → void? roomba : roomba? = (current-roomba) number : roomba-song-number? = 0
14 Sensors
procedure
(read-roomba-sensors [ #:roomba roomba #:packet-code packet-code]) → (listof (cons/c symbol? any/c)) roomba : roomba? = (current-roomba) packet-code : (or/c 0 1 2 3) = 0
> (read-roomba-sensors #:packet-code 1)
((dirt-detect-right . 0) |
(dirt-detect-left . 0) |
(side-brush-overcurrent? . #f) |
(vacuum-overcurrent? . #f) |
(main-brush-overcurrent? . #f) |
(drive-right-overcurrent? . #f) |
(drive-left-overcurrent? . #f) |
(virtual-wall? . #f) |
(cliff-right? . #f) |
(cliff-front-right? . #f) |
(cliff-front-left? . #f) |
(cliff-left? . #f) |
(wall? . #f) |
(bump-right? . #f) |
(bump-left? . #f) |
(wheeldrop-right? . #f) |
(wheeldrop-left? . #f) |
(wheeldrop-caster? . #f)) |
> (read-roomba-sensors #:packet-code 2)
((angle . 0) |
(distance . 0) |
(max-button? . #f) |
(clean-button? . #f) |
(spot-button? . #f) |
(power-button? . #f) |
(remote-control-command . 255)) |
> (read-roomba-sensors #:packet-code 3)
((battery-capacity . 973) |
(battery-charge . 889) |
(battery-temperature . 30) |
(battery-current . -176) |
(battery-voltage . 13888) |
(battery-charging-state . not-charging)) |
15 Troubleshooting
Ensure that the serial cable or other interface is firmly attached in all places it could become loose.
If you built a serial interface using instructions found on the Web, be aware that some pinout diagrams for the mini-DIN were published with pins reversed. Double-check against different pinouts.
If you’re connecting to an iRobot Create using the Command Module, make sure that you follow the boot-time procedures documentd in the iRobot Command Module Owners Manual. Also note that the developers of this package have not yet tested use through the Command Module.
Consider whether you have the right device file for your #:device argument. For example, if you’re using "/dev/ttyS0", maybe the correct device is "/dev/ttyS1", "/dev/ttyUSB0", or something else.
If you’re using a USB interface on the PC side, perhaps using a USB-to-RS232 adapter with an iRobot RS232-to-Roomba cable, check whether the USB device is actually recognized by the PC. On GNU/Linux, you can use the lsusb shell command to list recognized USB devices, and you can also check the syslog log files for the time that you plugged in the device.
If the PC’s serial port is an RS232 port on a laptop dock, consider that a hardware or operating system bug might be causing the serial port to “disappeared”. This has been known to happen with a ThinkPad T60 plugged into a dock, for example, and the solution in that case is to reboot the laptop while plugged into the dock.
On at least some Roomba models (including the 400), the Clean or Power button should be solid green before the Roomba can be accessed via this package. If button is not solid green, try pressing it, in hopes of it turning solid green. Be prepared to lift up the Roomba if pressing the button starts a clean cycle.
If the Roomba’s Clean or Power button is not solid green and pressing does not correct that, try removing and reattaching the cable from the Roomba’s serial port.
If all else fails, try removing the cable from the Roomba’s mini-DIN, removing the Roomba’s battery, waiting a few seconds, reattaching the Roomba’s battery, and finally reattaching the cable to the Roomba’s mini-DIN.
Consider that the Roomba is refusing to communicate because its battery desperately needs charging, even if it appears to have some charge left.
16 Known Issues
Needs initial testing, with different models.
Figure out why DrRacket is prompting for input in the Interactions pane under some unclear circumstances.
Continue working on the ROI and COI protocols, once appropriate test hardware is available.
In process of adding ROI and COI extensions for sensors, document it. Currently our sensors documentation is almost nonexistent.
Test use of USB interface of Create Command Module, once we have a working one.
Improve how stdio error messages are handled when calling /bin/stty.
We might be able to do better waking of the Roomba, using RTS. However, we cannot test this at this time, since, on our test setup at the moment (Roomba 400, plugged into iRobot brand cable, plugged into RS232 port of ThinkPad dock), even example code does not wake the Roomba.
Any any special support needed for other off-the-shelf Roomba hardware interfaces, such as those by RoboDynamics. We are aware that some of them are reported to need special handling, but we do not presently have use of them for testing.
- A let-roomba-sensors would be nice, so you could do things like this efficiently on SCI (OI makes it easier):
(let-roomba-sensors (wall battery-charge distance angle) ...) We have an example but have not coded it yet, til we look more closely at the different OI specs. Until then, we expect that the form would expand to code that looked at the protocol at runtime, and did different optimizations for SCI, OI-500 and OI-Create. Support a little bit more of Common Music Notation, especially for meter.
Add convenience for compiling and playing songs longer than 16 notes.
Test on Mac OS X.
Possibly add support for Microsoft Windows. Especially if Windows 7 and later have filesystem path devices for serial ports.
Get rid of LED control overlap in set-roomba-leds.
Put Raspberry Pi with WiFi onboard an iRobot Create. Hook up development tools so that Roomba programs can run onboard, on the Pi, as well as offboard on PC (say, in DrRacket for debugging), with the Pi gatewaying the OI protocol received over SSH WiFi.
17 History
- PLaneT 1:0 —
2013-08-18 Initial release. Still needs some initial testing with various different Roombas, and we are releasing now for that purposes.
18 Legal
Copyright 2013 Neil Van Dyke. This program is Free Software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. See http://www.gnu.org/licenses/ for details. For other licenses and consulting, please contact the author.