The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Robotics::IRobot - provides interface to iRobot Roomba and Create robots

SYNOPSIS

        use Robotics::IRobot;
        
        my $robot=Robotics::IRobot->new('/dev/rfcomm0');
        #could be /dev/ttyUSB0, /dev/ttyS0, etc.
        
        #Initializes port and sends OI Init command
        $robot->init();
        
        #Takes robot out of passive mode and enables
        #hardware based safeties
        $robot->startSafeMode();
        
        #Move robot forward at 100mm/s
        $robot->forward(100);
        
        #Get sensor state hash ref
        $robot->refreshSensors();
        my $sensorState=$robot->getSensorState();
        
        #Wait until we have moved 500mm
        while($sensorState->{totalDistance}<500) {
                sleep 1;
                $robot->refreshSensors();
        }
        
        $robot->stop();
        
        $robot->close();

VERSION

Version 0.14

REFERENCES

IRobot Open Interface specification -- http://www.irobot.com/filelibrary/pdfs/hrd/create/Create%20Open%20Interface_v2.pdf

REQUIRES

Time::HiRes, Device::SerialPort, YAML::Tiny, POSIX, Math::Trig

EXPORTS

Nothing

DESCRIPTION

Robotics::IRobot provides an interface for controlling and accessing sensor data from iRobot robots that support the OI Interface.

This module provides on object oriented interface to the robot and allows for both event-driven and polling-based reading of sensor data. It provides all functionality defined in the OI Interface for Roomba 400 series and Create robots. Also provided is some additional functionality such as primative dead reckoning and enhanced use of the Create's song functionality.

NOTE: This module is designed for controlling Create but will work with Roomba where applicable.

NOTICE

I make no warranty as to the correct functioning of this module. Use may cause your robot to fall down your basement stairs, catch fire, and burn your house down. Be prepared to take physical control of robot at all times.

I assume no responsibility or liability for damage to robot or its surroundings. If you do not agree to this, do not use this module.

DEVELOPMENT STATUS

This software is currently in alpha status. Telemetry is still a work in progress.

METHODS

Creation and Initialization

Robotics::IRobot->new($port,$indirectSensorsOn)

Creates a new IRobot object using the given communications port (defaults to /dev/iRobot) and enables indirect sensors if $indirectSensorsOn is true (this is the default).

$robot->init()

Initializes the port, connects to the robot, and initiates the OI Interface.

You must call one of startSafeMode or startFullMode before calling actuator commands.

$robot->initForReplay($telemetryFile)

Replays saved telemetry data, can be used for testing or analysis.

See section TELEMETRY

Actuators

$robot->reset()

Does a soft-reset of robot. Needed to begin charging or recover after triggering hardware based safeties.

$robot->startPassiveMode()

Puts robot into passive mode.

$robot->startSafeMode()

Puts robot into safe mode. (Turns on hardware based safeties.)

You must call one of startSafeMode or startFullMode before calling other actuator commands.

$robot->startFullMode()

Puts robot into full mode. (Turns off hardware based safeties.)

You must call one of startSafeMode or startFullMode before calling other actuator commands.

$robot->startDemo($demoId)

Puts robot in passive mode and starts built in demo. Consult OI Interface doc for available demos.

$robot->stopDemo()

Stops currently running demo.

$robot->drive($velocity, $radius)

Sends robot command to make a turn with speed $velocity (in mm/s), negative values are reverse; and turning radius $radius (in mm), positive values turn counter-clockwise, negative turn clockwise.

$robot->driveDirect($rightVelocity,$leftVelocity)

Sends robot command to drive right wheel at $rightVelocity (mm) and left wheel at $leftVelocity (mm). Positive values are forward, negative values are reverse.

$robot->stop()

Stops robot.

$robot->forward($velocity)

Moves robot forward at $velocity in (mm/s).

NOTE: This does not actually drive robot in a straight line, it actually performs right turn with a radius of 32768mm.

$robot->reverse($velocity)

Moves robot in reverse at $velocity in (mm/s).

$robot->rotateRight($velocity)

Rotates robot in place right (clockwise) at $velocity (in mm/s).

$robot->rotateLeft($velocity)

Rotates robot in place left (counter-clockwise) at $velocity (in mm/s).

$robot->setLEDs($powerColor, $powerIntensity, $playOn, $advanceOn)

Sets robot LEDs

        $powerColor should be >=0 and <=255.  0 is green, 255 is red.
        $powerIntensity should be >=0 and <=255
        $playOn and $advanceOn are boolean
$robot->setPlayLED($playOn)

Sets "Play" LED on or off.

$robot->togglePlayLED()

Toggles "Play" LED.

$robot->setAdvanceLED($advanceOn)

Sets "Advance" LED on or off.

$robot->toggleAdvanceLED()

Toggles "Advance" LED.

$robot->setPowerLED($powerColor,$powerIntensity)

Sets "Power" LED

        $powerColor should be >=0 and <=255.  0 is green, 255 is red.
        $powerIntensity should be >=0 and <=255
$robot->getLEDState()

Returns a hash reference with keys advance, play, powerColor, and powerIntensity that give current LED state. If modified, calls to updateLEDs will send modifications to robot.

NOTE: Values in hash reflect history of commands sent through interface. Actual LED state on robot may be different.

$robot->updateLEDs()

Writes current values in hash reference returned by getLEDState to robot.

$robot->setDigitalOutputs($output0,$output1,$output2)

Sets state of robot's digital outputs. Values are boolean.

$robot->setDigitalOutput($output,$state)

Sets state of output $output to $state.

        $output is >=0 and <=2. 
        $state is boolean.
$robot->toggleDigitalOutput($output)

Toggles state of digital output $output

$robot->getDigitalOutputs()

Returns an array ref containing state of robots digital outputs. If modified, calls to updateDigitalOutputs will send modifications to robot.

NOTE: Values in array reflect history of commands sent through interface. Actual output state on robot may be different.

$robot->updateDigitalOutputs()

Writes current values in array reference returned by getDigitalOutputs to robot.

$robot->setPWMLoads($lsd0, $lsd1, $lsd2)

Sets pwm duty cycle on low side drivers. Load values should be between 0 and 1 inclusive.

        0 is off, 1 is on, .5 is pulsed on 50% of the time, etc.
$robot->setPWMLoad($lsd, $load)

Sets pwm duty cycle on low side driver $lsd to $load. Load values should be between 0 and 1 inclusive.

        0 is off, 1 is on, .5 is pulsed on 50% of the time, etc.
$robot->changePWMLoad($lsd, $loadDelta)

Changes pwm duty cycle on low side driver $lsd by $loadDelta. Load Delta should be between 0 and 1 inclusive.

$robot->getPWMLoads()

Returns an array reference that contains current duty cycles of low side drivers. If modified, calls to updatePWMLoads will send modifications to robot.

NOTE: Values returned in this array are in the range 0-128, not 0-1 like the other methods. Also, values in array reflect history of commands sent through interface. Actual output state on robot may be different.

$robot->updatePWMLoads()

Writes current values in array reference returned by getPWMLoads to robot.

$robot->setPWMOnOff($lsd0, $lsd1, $lsd2)

Turns on and off low side drivers. Values are boolean.

$robot->sendIR($byte)

Sends IR byte through LED hooked up to LSD1.

See Open Interface doc for details.

$robot->setSongRaw($songId, @songBytes)

Sets song $songId in robot's memory to @songBytes. @songBytes can contain up to 16 notes.

See Open Interface doc for details.

$robot->playABCNotation($file, $callback)

Loads song in ABC format (see abcnotation.com) from $file and begins playing on Create. If passed, calls &$callback($robot) when done.

NOTE: You must either poll sensor values frequently or use the sensor data streaming methods for this method to work properly. Calling this method will overwrite any data contained in song banks 14 and 15

$robot->playLongSongRaw($callback, @songBytes)

Plays song contained in @songBytes (may be longer than 16 notes). If passed, calls &$callback($robot) when done.

NOTE: You must either poll sensor values frequently or use the sensor data streaming methods for this method to work properly. Calling this method will overwrite any data contained in song banks 14 and 15

IRobot::loadABCNotation($file)

Loads song in ABCNotation format from $file (see abcnotation.com). Returns song in format defined in OI Interface. If smaller than 16 notes (32 bytes) can be passed to setSongRaw. Otherwise resulting bytes can be passed to playLongSongRaw.

$robot->setSong($songId,$song)

Sets song bank $songId to the song specified in $song.

$song is expected to be a whitespace seperated list of notes. Each note is made up of an optional octave number, a note letter (a-g) or r for a rest, an optional sharp designator (#), and a duration in 64ths of a second. If no octave is given the last octave specified is used. If no octave has yet been specified octave 4 is used. Example:

        d16 a16 r32 3a16 a#32 b16 2b8 c#16

The example above will play a d in the 4th octave for 1/4 second, an a in the 4th octave for 1/4 second, rest for 1/2 second, an a in the 3rd octave for 1/4 second, and a sharp in the 3rd octage for 1/2 second, a b in the 3rd octave for 1/4 second, a b in the 2nd octave for 1/8 second, and a c sharp in the 2nd octave for 1/4 second.

The method will return the estimated duration in seconds the song will play. Using the example above the method would return 2.375

$robot->playSong($songId)

Plays song from bank $songId.

$robot->turnTo($direction, $speed, $callback)

Attempts to turn the robot to face $direction relative to the direction it was facing when $robot->init() was called or last $robot->markOrigin call. Robot will make the turn at $speed. Robot will stop once complete and call &$callback($robot) if $callback is passed.

See section DEAD RECKONING for more information.

NOTE: You must either poll sensor values frequently or use the sensor data streaming methods for this method to work properly.

$robot->goTo($x, $y, $speed, $callback)

Attempts to drive the robot to position ($x,$y) relative to its location when $robot->init() was called or last $robot->markOrigin call. Robot will make the proceed at $speed. Robot will stop once complete and call &$callback($robot) if $callback is passed.

See section DEAD RECKONING for more information.

NOTE: You must either poll sensor values frequently or use the sensor data streaming methods for this method to work properly.

Sensors

The robot's sensor data can be retrieved in several different ways. The easiest is to simply call $robot->refreshSensors on a regular basis. This will retrieve all sensor data from the robot, which can then be accessed from the hash returned by $robot->getSensorState(). If you do not want all sensor data to be retrieved, then you can use the $robot->getSensor($id) method. This will only retrieve data for one sensor (or sensor set) but, it is not recommended.

Consult the OI Interface document for more details on sensor ids.

Another method is to use the iRobot's sensor streaming functionality. When the robot is put in streaming mode it will send back sensor data once every 15ms. Use the $robot->startSteam, $robot->pauseStream. $robot->resumeStream method to start and stop the stream. The $robot->getStreamFrame method should be called at least every 15ms to read in the sensor data and update the sensor state hash. As with the polling method, you can pass a sensor ids to $robot->startStream to have the robot stream data for only particular sensors, but again, this is not recommeded.

The third method is to use the event-driven approach. Your program can register sensor listeners or events to listen for using the $robot->addSensorListener, $robot->addSensorEvent, $robot->runEvery, $robot->waitTime, $robot->waitDistance, and $robot->waitAngle methods. Once these have been registered the $robot->runSensorLoop and $robot->exitSensorLoop methods will put the robot in streaming mode then read sensor data as it comes in while updating the sensor state hash and calling any sensor listeners or events.

$robot->getSensorState()

Returns a hash reference containing last read values from robot sensors.

$robot->getDockSignal()

Returns an array indicating the presense of a "home base" docking station and any docking beacons seen.

Example:

        my ($dockPresent,$greenBeacon,$forceField,$redBeacon)=$robot->getDockSignal();
$robot->getSensorLocation($sensor)

Gets the current location of a sensor relative to the origin. Possible sensors:

cliffLeft
cliffFrontLeft
cliffFrontRight
cliffRight
bumpLeft
bumpCenter
bumpRight
caster
irSensor
wheelLeft
wheelRight
$robot->refreshSensors()

Retrieves all sensor data, refreshes sensor state hash, and triggers any sensor listeners or events. This method will block for up to 15ms if called more than once every 15ms.

If you are not calling this method more than once every few seconds. You may wish to switch the movement correction mode to 'robot' or 'raw', as these may be more accurate in this situation. See setMovementCorrectionMode method.

$robot->getSensor($sensorId)

Retreives data from a single sensor, refreshes sensor state hash, and triggers any sensor listeners or events. This method is generally not recommedended. $robot->refreshSensors() should be used instead.

If you are not polling the distance and angle sensors more than once every few seconds. You may wish to switch the dead reckoning mode to 'robot' or 'raw', as these may be more accurate in this situation. See setMovementCorrectionMode method.

See OI Documentation for sensor ids.

$robot->getSensors($sensorId1, $sensorId2, ... )

Retrieves data for a particular sensor, refreshes sensor state hash, and triggers any sensor listeners or events. This method is generally not recommended. $robot->refreshSensors() should be used instead.

If you are not polling the distance and angle sensors more than once every few seconds. You may wish to switch the dead reckoning mode to 'robot' or 'raw', as these may be more accurate in this situation. See setMovementCorrectionMode method.

See OI Documentation for sensor ids.

$robot->runSensorLoop()

Begins streaming sensor data from the robot. Updates sensor state hash every 15ms and triggers any sensor listeners or events. This method will block until $robot->exitSensorLoop() is called.

$robot->exitSensorLoop()

Stops streaming data from robot. Causes any previous call to runSensorLoop to return.

$robot->startStream()
$robot->startStream($sensorId)

Puts robot into streaming mode. If a $sensorId is passed only streams that sensor (not recommended). Otherwises streams data from all sensors.

See OI Documentation for more details

$robot->pauseStream()

Pauses the sensor data stream.

$robot->resumeStream()

Resumes a previously paused sensor stream.

$robot->getStreamFrame()

Gets one frame of sensor data, updates sensor data hash, and triggers any sensor listeners or events. Should be called at least once every 15ms. Method will block until one frame of sensor data has been read.

See OI Documentation for more details.

$robot->addSensorListener($priority,$action,$param)

Adds a sensor listener. This listener will be called whenever sensor data is retrieved, either as a group such as when $robot->refreshSensors or $robot->getStreamFrame is called or when individual sensors are retrieved using $robot->getSensors.

The priority parameter is used to determine the order in which listeners are called. Lower priorities are called first. Any listeners with a negative priority will be called before indirect sensors (dead reckoning) is calculated. Listeners with a priority less than 200 will be called before triggers for waitDistance, waitAngle, etc. events are called.

On each sensor data retrieval &$action($robot,$listener,$sensorIds) will be called. $sensorIds is a array ref containing the read sfensorIds. $listener is a hash containing the following keys:

id: listener id -- used to remove listener
priority: listener priority -- do not changed this value
action: the function being called
param: the value of $param passed to addSensorListener

The same hash ref is returned with each call, so this can be used by the action callback to store values.

Additionally, setting $listener->{stop} to true will prevent listeners with a higher priority value from executing. This is useful for listeners which implement safeties.

$robot->addSensorListener returns the listener id. This can be used to remove the listener later.

$robot->removeSensorListener($id)

Remove listener or event with $id.

$robot->addSensorEvent($priority,$test,$action,$param,$oneTime)

Executes &$test($robot,$listener,$sensorIds) each time sensor data is retrieved. $listener is a hash reference (see addSensorListener). $sensorIds is the array ref containing ids of the sensors read. &$action($robot,$listener,$sensorIds) is called if $test returns true. $param is included in the $listener hash ref. If $oneTime is true, the created listener is automatically removed the first time $test returns true.

As with addSensorListener, setting $listener->{stop} to true will stop further listeners and events from processing.

This method returns an id which can be passed to removeSensorListener to remove the event.

$robot->runEvery($priority,$time,$callback)

Creates a sensor event with $priority that calls &$callback($robot) every $time seconds. Returns an id that can be passed to removeSensorListener.

$robot->waitDistance($priority,$distance,$callback)

Creates a one time sensor event with $priority that calls &$callback($robot) once the robot has traveled $distance mm. Distance must be positive. Distances traveled in reverse will be used in determining total distance traveled. Returns an id that can be passed to removeSensorListener.

NOTE: if this method is called while in scripting mode, $priority and $callback are ignored and the scriptWaitDistance will be executed instead. (See scripting section below.)

$robot->waitAngle($priority,$angle,$callback)

Creates a one time sensor event with $priority that will call &$callback($robot) after robot has turned $angle radians in either direction. $angle must be positive. Turns in either direction will be used to determine total angle turned. Returns an id that can be passed to removeSensorListener.

NOTE: if this method is called while in scripting mode, $priority and $callback are ignored and the scriptWaitAngle will be executed instead. (See scripting section below.)

$robot->waitTillFacing($priority,$direction,$maxDelta,$callback)

Creates a one-time sensor event with priority $priority that will call &$callback($robot) when robot is within $maxDelta of absolute direction $direction (in radians). 0 radians is the direction the robot was facing when last $robot->init or $robot->markOrigin was called. $direction should be between -PI and PI. Returns an id that can be passed to removeSensorListener.

$robot->waitTime($priority,$time,$callback)

Creates a one-time sensor event with priority $priority that will call &$callback($robot) after $time seconds. Returns an id that can be passed to removeSensorListener.

NOTE: if this method is called while in scripting mode, $priority and $callback are ignored and the scriptWaitTime will be executed instead. (See scripting section below.)

$robot->markOrigin()

Sets the robot's current position as (0,0) and the direction the robot is currently facing as 0.

$robot->setPosition($x,$y,$direction)

Sets the robots current position as ($x,$y) and the direction $direction (in radians). 0 is along the +y axis.

Display

$robot->getSensorString()

Returns a string listing each sensor value from the sensor state hash.

$robot->getCondensedString()
$robot->getCondensedString($lineEnding)

Returns a string condensed version of the current state of the robots sensors. Suitable for output in a command line program.

Example:

        Bu Bp Cliff  DIn  AIn  Chrg Wl Whl   Oc  Sng Md
        AP LR LFlFrR 0123 0704 HbIn AV LCR 012LR P00 1
        Batt: 2606/2702 +1087@17200 (32) C Ir: 254
        (+00003,+00052) -002  DGFR      
        Cliff: 0000 0000 00000 00000 Wall: 00000

In the first 2 lines, Bu shows the status of the buttons on the robot. In the example above both the Advance and Play Buttons are pressed. Bp shows the status of the left (L) and right (R) bump sensors. Cliff shows the status of left (L), front-left (Fl), front-right (Fr), and right (R) sensors. DIn shows the state of the 4 digital inputs, AIn shows the value of the analog input. Chrg shows if charging is available from the home base (Hb) or internal (In) chargers. Wl shows the state of the actual (A) and virtual (V) wall sensors. Whl shows the state of the left (L), caster (C), and right (R) wheeldrop sensors. Oc shows the state of the overcurrent sensors for the 3 low side drivers, (0-2) and the left (L) and right (R) wheels. Sng indicates is a song is playing (P) and the currently selected song bank. Md shows the current mode number.

The battery line shows the battery charge and maxium capacity, the current and voltage flowing from the battery, the battry temperature, the charging state. Also, the byte recieved by the IR sensor is shown on this line. In the example above, the battery has charge of 2606 mAh out of a maximum capacity of 2702 mAh. The battery is charging at 1087 mA and 17200 mV. Positive current values indicate charging, negative ones indicate discharge. The battery temperature is 32 degrees C. The C indicates the battery is charging. The IR sensor is receiving byte 254.

The fourth line shows the estimated x and y position in mm, and the current direction in degrees. Also shown is any docking indicators: dock present (D), green beacon (G), force field (F), red beacon (R).

The last line indicates the raw signal values of the four cliff sensors (left, front-left, front-right, and right) and the wall sensor.

Scripting

These commands make use of the builtin scripting functionality of the iRobot create.

See OI Documentation for more details.

$robot->startScript()

Puts robot in scripting mode. Subsequent commands will not be sent to robot, but instead be saved to robots script memory. Create can store a maximum of 100 bytes of scripting commands.

$robot->runScript()

Runs the script currently stored in robot. This will cause the robot to go into passive mode and not respond to commands until script is complete.

$robot->repeatScript()

If called while in scripting mode, causes script to repeat from begining.

$robot->scriptMode()

Returns true if currently in scripting mode, false otherwise.

$robot->cancelScript()

Leaves scripting mode without writing script to robot.

$robot->endScript()

Leaves scripting mode and writes script to robot.

$robot->scriptWaitTime($time)

Waits $time seconds (rounded to nearest tenth). Robot will not respond to commands during this time. Not recommended to be used outside of scripting mode.

$robot->scriptWaitDistance($distance)

Waits until robot travels $distance mm. Robot will not respond to commands during this time. Not recommended to be used outside of scripting mode.

$robot->scriptWaitAngle($angle)

Waits until robot turns through $angle degrees. Robot will not respond to commands during this time. Not recommended to be used outside of scripting mode.

$robot->waitEvent($eventId) =item $robot->scriptWaitEvent($eventId)

Waits until event with id $eventId occurs. Robot will not respond to commands during this time. Not recommended to be used outside of scripting mode.

See OI Documentation for list of event ids.

Telemetry

This module has the ability to record telemetry data containing bytes sent to and from robot. And any debuging data that can be provided by client programs.

$robot->startTelemetry($file,$overwrite)

Begins writing telemetry data to $file. Appends data unless $overwrite is true.

$robot->stopTelemetry()

Stops recording telemetry data.

$robot->logTelemetry($type,$data)

Write client application provided data to telemetry file. The $type value should use the following specification for maxium compatibility with other applications. $data can be any binary value.

        Types:
                0- indirect sensor field
                16 - stream sync indicator
                32 - 63 -- reserved for client UI
                        32 - key press
                64-127 -- Debug info
                        64 - general debug
                255 - String message

Sensor Calibration

Sensor calibration can be used to correct for some inconsistancies and inaccuracies of the robot. 2 sets of sensors can be calibrated.

The first is the angle sensor. This sensor is supposed to return the angle turned in degrees since the last sensor reading. In practice it is extremely inaccurate. The accuracy can be some what improved by calculating the ratio between actual angle turned and angle reported at different velocities and then applying this ratio to read sensor values. This corrected value can be seen in the actualAngle and totalActualAngle indirect sensors.

The second set are the cliff signal sensors. These sensors report the IR reflectivity of 4 sections of floor near the front of the robot. These values could be used for example, to follow a dark line drawn on the ground. The sensors tend to be accurate individually, but each sensor will have a slightly different bias-- meaning each sensor will read the same section of floor differently. To correct for this we can generate statistics describing the range of values seen by each sensor over the same section of floor. We can then use this to determine the distance from the mean in standard deviations for a value read by a particular sensor based on the previous values read for that sensor. This value should be the same for each sensor when reading the same section of floor. These values are seen in the cliff...SignalDev indirect sensors.

Once these calibration data are created. They can be saved and retrieved using the saveCalibrationData and loadCalibrationData methods.

Note: default calibration values are provided, these were generated from calibration of my robot on my carpet. However, it is strongly recommended to calibrate your own robot and create a calibration file for each type of flooring on which you plan to operate the robot. The type of flooring will change both the wheel slipage and IR reflectivity, so both the angle and cliff signal sensors will need to be recalibrated.

See section Indirect sensors for more information.

$robot->loadCalibrationData($file)

Loads saved calibration file from $file or calibration.yaml if no file is given. This is called automatically on initialization. So, it is only necessary if you wish to load calibration data from another file.

$robot->saveCalibrationData($file)

Saves calibration data to $file or calibration.yaml if no file is given.

$robot->calibrate($sensor)

Calibrates indirect sensors. Method will block until calibration is complete. Robot will go though several complete rotations. Be sure to follow any instructions in calicration proceedure below. Returns true on calibration success, false otherwise. $sensor can be one of the following:

actualAngle: Calibrates actualAngle correction factors for dead reckoning
cliffDev: Calibrates cliffSignalDev sensors
all: Calibrates all sensors.

Calibration procedure: For cliffDev, the robot needs only to be on the type of surface it will be used on most often. For actualAngle, the procedure is more complicated. A "Home Base" docking station and a way to block of part of the robots IR sensor is required. Block all but a small section in the front of the IR Sensor. I usually do this with a strip of aluminum foil. Then place the robot a few feet away from the docking station and in a position so that the docking station can only be seen though the small gap you left in the IR sensor.

Note: You will need to call $robot->saveCalibrationData afterwards to save calibration to file.

$robot->setMovementCorrectionMode($mode)

Sets the movementCorrection method used by the module. Can be one of the following:

calibration: (default) Uses result of calibration to correct reported sensor values. This works best when robot is limited to straight movement and rotation in place. See Sensor Calibration.
time: Ignores angle sensor values and relies solely on requested movement and time.
robot: Trusts value reported by robot angle sensor is accurate. Assumes sensor value is difference between distance traveled by left wheel and distance travel by right wheel. (This seems to actually be the case.)
raw: Trusts value reported by robot angle sensor is accurate. Assumes sensor value is degrees rotated. (This is the value reported by the OI doc, but does not actually seem to be the case.)

<Or> you can pass your own sub to perform movement correction. When called it will be passed $robot, $listener, and $sensorIds. $sensorIds is a array ref containing the read sensorIds. $listener is a hash containing the details of the sensor listener used to calculate indirect sensor values. See addSensorListener for more details. The sub must return a list containing actual distance traveled in mm followed by actual angle rotated in radians.

Closing Connection

$robot->close()

Stops the robot motion and sensor streaming and closes communication port.

SENSORS

The sensor state hash can be retrieved from the $robot->getSensorState() method. This only need be retrieved once as subsequent updates will be made to the same hash. Each direct and indirect sensor reading can be retrieved from this hash using the keys below.

Direct Sensors

These are sensor values that are read directly from the robot.

Keys

wheeldropCaster -- wheeldrop sensor on front caster (boolean)
wheeldropLeft -- wheeldrop sensor on left wheel (boolean)
wheeldropRight -- wheeldrop sensor on right wheel (boolean)
bumpLeft -- left bump sensor (boolean)
bumpRight -- right bump sensor (boolean)
wall -- physical wall sensor (boolean)
cliffLeft -- left cliff sensor (boolean)
cliffFrontLeft -- front-left cliff sensor (boolean)
cliffFrontRight -- front-right cliff sensor (boolean)
virtualWall -- virtual wall sensor (boolean)
ocLeftWheel -- overcurrent on left wheel (boolean)
ocRightWheel -- overcurrent on right wheel (boolean)
ocLD0 -- overcurrent on low side driver 0 (boolean)
ocLD1 -- overcurrent on low side driver 1 (boolean)
ocLD2 -- overcurrent on low side driver 2 (boolean)
irByte -- byte received by IR sensor (unsigned byte)
advanceButton -- advance button state (boolean)
playButton -- play button state (boolean)
distance -- distance travelled in mm since last sensor refresh (signed short)
angle -- angle turned in degrees since last sensor refresh (signed short)
        positive angles are counter-clockwise
        negative are clockwise
        NOTE: This sensor is extremely inaccurate (see actualAngle)
chargingState -- indicates if robot is charging (boolean)
voltage -- voltage of battery (unsigned short)
current -- current of battery charge/discharged (signed short)
        positive values indicate charging
        negative indicate discharging
batteryTemp -- temperature of battery in degrees C (unsigned byte)
batteryCharge -- current battery charge in mAh (unsigned short)
batteryCapacity -- maximum battery capacity in mAh (unsigned short)
wallSignal -- raw signal value of wall sensor (unsigned short)
cliffLeftSignal -- raw signal value of left cliff sensor (unsigned short)
cliffFrontLeftSignal -- raw signal value of front-left sensor (unsigned short)
cliffFrontRightSignal -- raw signal value of front-right cliff sensor (unsigned short)
cliffRightSignal -- raw signal value of right cliff sensor (unsigned short)
deviceDetect -- state of robot's device detect pin (boolean)
digitalInput0 -- state of digital input 0 (boolean)
digitalInput1 -- state of digital input 1 (boolean)
digitalInput2 -- state of digital input 2 (boolean)
digitalInput3 -- state of digital input 3 (boolean)
analogIn -- value of analog input (unsigned short)
homeBaseAvailable -- true if robot is connected to home base (boolean)
internalCharger -- true if robot can charge battery using internal charger (boolean)
oiMode -- OI Interface mode (unsigned byte)
songNumber -- last selected song bank (unsigned byte)
songPlaying -- true if song is playing (boolean)
numPackets -- number of packets sent in last stream (byte)
requestedVelocity -- last requested velocity (signed short)
requestedRadius -- last requested turning radius (signed short)
requestedRightVelocity -- last requested right wheel velocity (signed short)
requestedLeftVelocity -- last requested left wheel velocity (signed short)

Indirect Sensors

These are sensor values that are derived from direct sensors.

Keys

totalAngle -- sum of all previous angle readings
totalDistance -- sum of all previous distance readings
lastSensorReading -- Timestamp in seconds of last reading
deltaT -- time in seconds since last reading
deltaX -- change in x coordinate since last reading
deltaY -- change in y coordinate since last reading
x -- x coordinate of current position
y -- y coordinate of current position
direction -- direction robot is currently facing in radians (between -PI and PI)
actualAngle -- an attempt to correct angle sensor; the actual angle turned in radians
totalActualAngle -- sum of all previous actual angle readings
actualDistance -- an attempt to correct distance sensor; the distance traveled in mm
totalActualDistance -- an attempt to correct distance sensor; the distance traveled in mm
turningRadius -- estimated actual turning radius
cliffFrontSignalDelta, cliffFrontRightSignalDelta, cliffLeftSignalDelta, cliffFrontLeftSignalDelta -- change in cliff sensors since last reading
cliffFrontSignalDev, cliffFrontRightSignalDev, cliffLeftSignalDev, cliffFrontLeftSignalDev -- difference from mean of current cliff sensor value in standard deviations

DEAD RECKONING

This module attempts to do some sensor correction and dead reckoning using sensor readings.

Coordinate System

When the $robot->new or $robot->markOrigin is called. The x,y, and direction values of the robot are set to 0. The robot is then assumed to be facing along the positive y-axis (direction 0). The positive x-axis is 90 clockwise. Positive directions are counter-clockwise, negative directions are clockwise.

Sensor Correction

An attempt is made to correct inaccurate angle readings. The correction is done using error factors determined experimentally on a Create. Your mileage may vary.

It is recommended that you calibrate your robot using the calibrate method before relying on dead reckoning.

RAW COMMUNICATION

The below methods can be used to for raw communication with the robot. Use of these within the same application as the rest of the methods in this module is strongly discouraged.

$robot->initPort()

Initializes the communications port. Returns true on success, false otherwise.

$robot->writeBytes(@bytes)

Writes bytes in @bytes to robot.

$robot->readData($length)

Reads $length bytes from robot. Blocks until bytes are read. Returns bytes read as string.

Data returned by this method will probably need to be passed to unpack. For example, to get an array of 4 bytes from robot use:

        unpack('C*',$robot->readData(4))

EXAMPLES

Wall bouncing

Moves robot foward until a bump sensor is triggered, then backs up and turns a random angle before continuing forward. Runs unil user hits the 'c' (close) or 's' (stop) keys.

        #!/usr/bin/perl
        
        use Robotics::IRobot;
        use Term::ReadKey;
        use Math::Trig; #for deg2rad
        
        print "Connecting...\n";
        my $iRobot=Robotics::IRobot->new('/dev/rfcomm0');
        
        #init robot and turn on hardware safeties
        $iRobot->init();
        print "Connected\n";
        $iRobot->startSafeMode();
        
        ReadMode 4,STDIN;
        
        my $sensorState=$iRobot->{sensorState};
        
        #check for a key press and display sensor output with every sensor read
        $iRobot->addSensorListener(300,sub {
                        my $c=ReadKey -1, STDIN;
        
                        if ($c) {
                                if ($c eq  's') {
                                        #stop robot on s
                                        $iRobot->stop();
                                } elsif ($c eq 'c') {
                                        #stop loop and exit program on c
                                        $iRobot->exitSensorLoop();
                                }
                        }
                        
                        #display sensor output
                        print $iRobot->getCondensedString("\n") . "\n";
                        
                },0);
        
        #action=0 moving foward
        #action=1 turning left
        #action=2 turning right
        #used to track whether we are responding to a bump event
        my $action=0;
        
        #trigger event when we are not responding to a bump event and one of
        #the bump sensors activates.
        $iRobot->addSensorEvent(200,sub {!$action && ($sensorState->{bumpRight} || $sensorState->{bumpLeft})},
                sub {
                        #figure out which way to turn
                        $action=$sensorState->{bumpRight}?1:2;
                        
                        #back up
                        $iRobot->reverse(200);
                        
                        #after .5s
                        $iRobot->waitTime(200,.5,sub {
                        
                                #rotate away from bump
                                if ($action==1) {
                                        $iRobot->rotateLeft(200);
                                } else {
                                        $iRobot->rotateRight(200);
                                }
                                
                                #wait for random angle
                                $iRobot->waitAngle(200,deg2rad(10 + 120*rand()),
                                        sub {
                                                
                                                #then continue forward
                                                $iRobot->forward(300);
                                                $action=0;
                                        }
                                );
                        });
                },0,0);
        
        #begin moving forward
        $iRobot->forward(300);
        
        #start sensor loop and event processing
        $iRobot->runSensorLoop();
        
        #close connection
        $iRobot->close();
        
        ReadMode 0, STDIN;

Scripting

Uses robot's on board scripting to continuously move 500mm back and forth. Robot will continue to do this until power button is pressed.

See OI Documentation for more details.

        #!/usr/bin/perl

        use Robotics::IRobot;

        my $robot=Robotics::IRobot->new();

        $robot->init();
        $robot->startSafeMode();

        $robot->startScript();

                $robot->forward(300);
                $robot->waitDistance(500);
                $robot->rotateLeft(200);
                $robot->waitAngle(180);
                $robot->forward(300);
                $robot->waitDistance(500);
                $robot->rotateLeft(200);
                $robot->waitAngle(180);
                $robot->repeatScript();

        $robot->endScript();

        $robot->runScript();

AUTHOR

Michael Ratliff, <$_='email@michaelratlixx.com'; s/x/f/g; print;>

BUGS

Please report any bugs or feature requests to bug-robotics-irobot at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Robotics-IRobot. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

I only have an iRobot Create to use for testing. So, any Roomba bugs that are unable to be reproduced on a Create may go unresolved.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Robotics::IRobot

You can also look for information at:

LICENSE AND COPYRIGHT

Copyright 2011 Michael Ratliff.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See section NOTICE at the top of this document.

See http://dev.perl.org/licenses/ for more information.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 1191:

Expected text after =item, not a bullet