Introduction: Turning Your Roomba Into a Mars Rover

.

Step 1: Gather Your Materials

In order to complete this project, you will need to gather the following materials:

1 Roomba Robot

1 Raspberry Pi Kit

1 Video Camera

Access to MATLAB

Step 2: Download the Roomba Toolboxes for MATLAB

Run the following code in order to install the necessary toolboxes to complete this project.

function roombaInstall

clc;

% list of files to install

files = {'roomba.m','roombaSim.m','roombaSimGUI.m','roombaSimGUI.fig'};

% location to install from

options = weboptions('CertificateFilename',''); % tell it to ignore certificate requirements

server = 'https://ef.engr.utk.edu/ef230/projects/roomba-f2016/install/';

dlgTitle = 'Roomba Install/Update';

% display purpose and get confirmation

prompt = {

'This program will download these EF 230 Roomba files:'

''

strjoin(files,' ')

''

'to this folder:'

''

cd

''

'Do you want to continue? '

};

beep;

yn = questdlg(prompt, ...

dlgTitle, ...

'Yes','No','Yes');

if ~strcmp(yn,'Yes'), return; end

% get list of files that exist

existing_files = files( cellfun(@exist,files) > 0 );

if ~isempty(existing_files)

% make sure it is really ok to replace them

prompt = {'You are replacing these file(s): '

''

strjoin(existing_files,' ')

''

'OK to replace?'

};

beep;

yn = questdlg(prompt, ...

dlgTitle, ...

'Yes','No','Yes');

if ~strcmp(yn,'Yes'), return; end

end

% download the files

cnt = 0;

for i=1:length(files)

f=files{i};

disp(['Downloading ' f]);

try

url = [server f];

websave(f,url,options); % added options to avoid security errors

cnt = cnt + 1;

catch

disp(['Error downloading ' f]);

dummy = [f '.html'];

if exist(dummy,'file')==2

delete(dummy)

end

end

end

if cnt == length(files)

msg = 'Installation Successful';

waitfor(msgbox(msg,dlgTitle));

else

msg = 'Installation Error - see command window for details';

waitfor(errordlg(msg,dlgTitle));

end

end %roombaInstall

Step 3: Connect to Your Roomba

Now it is time to connect to your Roomba using WiFi. Using 2 fingers, press the Dock and Spot buttons simultaneously to turn on or reset your Roomba. Next, Run the code r=roomba(# of your Roomba) in the command window of MATLAB to connect to your robot. Once you have executed this command, your Roomba should be ready to go.

Step 4: Choose How You Want to Control Your Roomba

There are two ways that you can control your Roomba: autonomously or using a smartphone as a controller.

If you choose to drive the Roomba autonomously, you will need to use the three built-in sensors: cliff sensors, bump sensors, and light sensors.

In order to use a smartphone, you first need to connect your smartphone to your computer by following the steps below.

NOTE: Your computer and smartphone need to be on the same WiFi network in order to connect properly!

1. Download the MATLAB app from the app store on your device.

2. Type "connector on" into your command window and set a password that will need to be input into both devices.

3. After doing so, MATLAB will give you your computers IP address. You need to go into the settings page in the MATLAB app on your smartphone and add a computer using the given IP address and the password you entered earlier.

4. In the command window on your computer, type the code m=mobiledev and this should initialize your smartphone as a controller for your Roomba.

5. Your computer and smartphone should be ready to go now.

Step 5: Drive Your Roomba

Now that you have all of the necessary tools to create your Mars Rover, you are ready to create your own code. We have attached an example code below for both the autonomous driving and the smartphone-controlled driving.

Autonomous Driving

function Explore_modified(r)

%input arguments: 1 roomba object, r

%output arguments: none

%description:

%function utilizes an infinite while loop to allow autonomous

%exploration of the bot's surroundings.

%

%funciton also provides instructions to the roomba for what to do in

%the following situations: Wheel(s) lose(s) contact with the ground, an

%object is detected in front of or to either side of the bot, and a

%sudden drop is detected in front of or to either side of the bot.

%

%typical instructions include movement commands intended to maximize

%exploration or avoid a detected danger and commands to communicate

%information regarding the bots's discoveries(pictures), position (graph),

%and state (stranded warning)with the user via matlab and/or email. Several

%sound commands are added for enjoyment.

%setup email capabilities

mail = 'marsrovers59@gmail.com';

password = 'EF230Roomba';

setpref('Internet','SMTP_Server','smtp.gmail.com');

setpref('Internet','E_mail',mail);

setpref('Internet','SMTP_Username',mail);

setpref('Internet','SMTP_Password',password);

props = java.lang.System.getProperties;

props.setProperty('mail.smtp.starttls.enable','true');

props.setProperty('mail.smtp.auth','true');

props.setProperty('mail.smtp.socketFactory.class', 'javax.net.ssl.SSLSocketFactory');

props.setProperty('mail.smtp.socketFactory.port','465');

% r=roomba(19)

r.beep('G2^^,G2^^,G2^^,G2^^,A2^^,A2^^,G1^^,E1^^,C2^^,C2^^,C1^^,C1^^,D1^^,C1^^,D2^^,E4^^,G2^^,G2^^,G2^^,G2^^,A2^^,A2^^,G1^^,E1^^,C2^^,C2^^,C2^^,E1^^,E1^^,E1^^,D1^^,C4^^');

v = .1;

reflect_datum=2700; %set cliff sensors reference value

lightBumper_datum = 200; %set light Bumper sensors reference value

pos=[0,0]; %variable for position storage with datum initialized

angle=0; %set reference angle

netangle=0; %net angle displacement

i=2; %iterator for adding rows to position storage variable

dist = 0;

r.setDriveVelocity(v,v); %start roomba moving forward

while true

Cliff = r.getCliffSensors;

Bump = r.getBumpers;

Light = r.getLightBumpers;

RandAngle = randi([20,60],1); %generates 1 random angle between 20 and 60 degrees. Used to prevent bot from getting stuck in a loop

%What to do if one or more wheel loses contact with the ground:

%stop movement, send a warning email with picture of surroundings,

%and ask user whether to proceed or wait for help

if Bump.rightWheelDrop == 1 || Bump.leftWheelDrop == 1

r.stop

dist = r.getDistance;

pos(i,1)= pos(i-1,1) + dist * sind(netangle); %get x coordinate

pos(i,2)= pos(i-1,2) + dist * cosd(netangle); %get y coordinate

i=i+1;

r.beep('F#1^^,C1^^,F#1^^,C1^^,F#1^^,C1^^,F#1^^,C1^^,F#1^^,C1^^,F#1^^,C1^^,F#1^^,C1^^,F#1^^,C1^^')

img = r.getImage;

imwrite(img,'stuck.png');

%--------------------------

imfile='stuck.png';

position=savepos(pos);

%---------------------------

sendmail(mail,'HELP!','I am stranded on a cliff!',{imfile,position})

list = {'Continue', 'Stop'};

idx = menu('What should I do?',list);

if idx == 2

break

end

%What to do if an object is detected in front of bot:

%stop, move back, take picture, alert user of discovery

%via email, turn 90 degrees, and keep exploring

elseif Light.leftCenter > lightBumper_datum || Light.rightCenter > lightBumper_datum || Bump.front == 1

r.stop;

dist = r.getDistance;

pos(i,1)= pos(i-1,1) + dist * sind(netangle); %get x coordinate

pos(i,2)= pos(i-1,2) + dist * cosd(netangle); %get y coordinate

i=i+1;

r.moveDistance(-.125);

dist = r.getDistance;

pos(i,1)= pos(i-1,1) + dist * sind(netangle); %get x coordinate

pos(i,2)= pos(i-1,2) + dist * cosd(netangle); %get y coordinate

i=i+1;

r.beep('A1^,A1^,A4^,A2^,G2^,G2^,G4^,Bb2^,Bb2^,Bb3.5^,G1^,A8^')

img = r.getImage;

imwrite(img,'FrontBump.png')

%--------------------------

imfile='FrontBump.png';

position=savepos(pos);

%---------------------------

sendmail(mail,'Alert!','I found something!',{imfile,position})

angle = 90;

netangle=netangle+angle;

r.turnAngle(angle);

r.setDriveVelocity(v,v);

%What to do if object is detected to the left of bot:

%stop, turn towards object, back up, take picture, alert

%user of discovery via email, turn 90 degrees and keep exploring

elseif Light.leftFront > lightBumper_datum || Light.left > lightBumper_datum || Bump.left == 1

r.stop;

dist = r.getDistance;

pos(i,1)= pos(i-1,1) + dist * sind(netangle); %get x coordinate

pos(i,2)= pos(i-1,2) + dist * cosd(netangle); %get y coordinate

i=i+1;

angle=30;

netangle=netangle+angle;

r.turnAngle(angle);

r.moveDistance(-.125);

dist = r.getDistance;

pos(i,1)= pos(i-1,1) + dist * sind(netangle); %get x coordinate

pos(i,2)= pos(i-1,2) + dist * cosd(netangle); %get y coordinate

i=i+1;

r.beep('A4^,A4^,G1^,E1^,C3.5^,C2^^,C1^,C1^,C2^,D2^,D2^,E8^')

img = r.getImage;

imwrite(img,'LeftBump.png')

%--------------------------

imfile='LeftBump.png';

position=savepos(pos);

%---------------------------

sendmail(mail,'Alert!','I found something!',{imfile,position})

angle=-90;

netangle=netangle+angle;

r.turnAngle(angle);

r.setDriveVelocity(v,v);

%What to do if object is detected to the right of bot:

%stop, turn towards object, back up, take picture, alert

%user of discovery via email, turn 90 degrees and keep exploring

elseif Light.rightFront > lightBumper_datum || Light.right > lightBumper_datum || Bump.right == 1

r.stop;

dist = r.getDistance;

pos(i,1)= pos(i-1,1) + dist * sind(netangle); %get x coordinate

pos(i,2)= pos(i-1,2) + dist * cosd(netangle); %get y coordinate

i=i+1;

angle=-30;

netangle=netangle+angle;

r.turnAngle(angle);

r.moveDistance(-.125);

dist = r.getDistance;

pos(i,1)= pos(i-1,1) + dist * sind(netangle); %get x coordinate

pos(i,2)= pos(i-1,2) + dist * cosd(netangle); %get y coordinate

i=i+1;

pause(1.5);

r.beep('C1^,C1^,C2^,D2^,D2^,C8^')

img = r.getImage;

imwrite(img,'RightBump.png')

%--------------------------

imfile='RightBump.png';

position=savepos(pos);

%---------------------------

sendmail(mail,'Alert!','I found something!',{imfile,position});

angle=90;

netangle=netangle+angle;

r.turnAngle(angle);

r.setDriveVelocity(v,v);

%What to do if cliff is detected to the left of bot:

%stop, move backwards, turn right, continue exploring

elseif Cliff.left < reflect_datum || Cliff.leftFront < reflect_datum

r.stop;

dist = r.getDistance;

pos(i,1)= pos(i-1,1) + dist * sind(netangle); %get x coordinate

pos(i,2)= pos(i-1,2) + dist * cosd(netangle); %get y coordinate

i=i+1;

r.moveDistance(-.125);

dist = r.getDistance;

pos(i,1)= pos(i-1,1) + dist * sind(netangle); %get x coordinate

pos(i,2)= pos(i-1,2) + dist * cosd(netangle); %get y coordinate

i=i+1;

angle=-RandAngle;

netangle=netangle+angle;

r.turnAngle(angle);

r.setDriveVelocity(v,v);

%What to do if cliff is detected to the right of bot:

%stop, move backwards, turn left, continue exploring

elseif Cliff.right < reflect_datum || Cliff.rightFront < reflect_datum

r.stop;

dist = r.getDistance;

pos(i,1)= dist * sind(angle); %get x coordinate

pos(i,2)= dist * cosd(angle); %get y coordinate

i=i+1;

r.moveDistance(-.125);

angle=RandAngle;

netangle=netangle+angle;

r.turnAngle(angle);

r.setDriveVelocity(v,v);

end

end

Smartphone Controller

Options = {'Autonomous','Manual Control'}

Prompt = menu('How would you like to control the rover?',Options)

m = mobiledev

r = roomba(19)

if Prompt == 1

Explore(r)

else

while true

pause(.5)

PhoneData=m.Orientation;

Azi=PhoneData(1);

Pitch=PhoneData(2);

Side=PhoneData(3);

if Side>130 || Side<-130 %if the phone is flipped face down stop the roomba and exit loop

r.stop

r.beep('C,C,C,C')

break

elseif Side>25 && Side<40 %if the phone is turned sideways between 25 and 40 deg turn left 5 deg

r.turnAngle(-5);

elseif Side>40 %if the phone is turned sideways over 40 deg turn left 45 deg

r.turnAngle(-45)

elseif Side<-25 && Side>-40 %if the phone is turned sideways between -25 and -40 deg turn right 5 deg

r.turnAngle(5);

elseif Side<-40 %if the phone is turned sideways less than -40 deg turn left 45 deg

r.turnAngle(45)

end

%If phone is held near verticle take an image and plot it

if Pitch<-60 && image<=9

r.beep

img=r.getImage;

subplot(3,3,image)

imshow(img)

end

%move forward and backward based on the front and back orientation

if Pitch>15 && Pitch<35 %if pitch between 15 and 35 deg move forward short distance

%get light bumper data before moving

litBump=r.getLightBumpers;

if litBump.leftFront>500 || litBump.leftCenter>500 || litBump.rightCenter>500 || litBump.rightFront>500 %if something is in front of the roomba and will hit if it moves forward make noise and display message

r.beep('C^^,F#^,C^^,F#^')

else %move

r.moveDistance(.03);

%Get bumper data after moving

Bump=r.getBumpers;

if Bump.right==1 || Bump.left==1 || Bump.front==1

r.beep('A,C,E')

r.moveDistance(-.01)

end

%get cliff sensor data

Cliff=r.getCliffSensors;

if Cliff.left>1500 || Cliff.leftFront>1500 || Cliff.rightFront>1500 || Cliff.right>1500 %if something triggers the cliff sensor treat it as lava and back up

r.beep('C^^,C,C^^,C,C^^,C,C^^,C,C^^,C,C^^,C')

r.moveDistance(-.031)

end

end

elseif Pitch>35 %if pitch greater 35 deg move forward longer distance

%get light bumper data before moving

litBump=r.getLightBumpers;

if litBump.leftFront>15 || litBump.leftCenter>15 || litBump.rightCenter>15 || litBump.rightFront>15 %if something is in front of the roomba and will hit if it moves forward make noise and display message

r.beep('C^^,F#^,C^^,F#^')

else %move

r.moveDistance(.3)

%Get bumper data after moving

Bump=r.getBumpers;

if Bump.right==1 || Bump.left==1 || Bump.front==1 %if you hit something make a noise, display message, and back up

r.beep('A,C,E')

r.moveDistance(-.01)

end

%get cliff sensor data after moving

Cliff=r.getCliffSensors;

if Cliff.left>1500 || Cliff.leftFront>1500 || Cliff.rightFront>1500 || Cliff.right>1500 %if something triggers the cliff sensor treat it as lava and back up

r.beep('C^^,C,C^^,C,C^^,C,C^^,C,C^^,C,C^^,C')

r.moveDistance(-.31)

end

end

elseif Pitch<-15 && Pitch>-35 %if pitch between -15 and -35 deg move back short distance

r.moveDistance(-.03);

%get cliff sensor data after moving

Cliff=r.getCliffSensors;

if Cliff.left>1500 || Cliff.leftFront>1500 || Cliff.rightFront>1500 || Cliff.right>1500 %if something triggers the cliff sensor treat it as lava and back up

r.beep('C^^,C,C^^,C,C^^,C,C^^,C,C^^,C,C^^,C')

r.moveDistance(.04)

end

elseif Pitch<-35 && Pitch>-60 %if pitch between -35 and -60 deg move back longer distance

r.moveDistance(-.3)

%get cliff sensor data after moving

Cliff=r.getCliffSensors;

if Cliff.left>1500 || Cliff.leftFront>1500 || Cliff.rightFront>1500 || Cliff.right>1500 %if something triggers the cliff sensor treat it as lava and back up

r.beep('C^^,C,C^^,C,C^^,C,C^^,C,C^^,C,C^^,C')

r.moveDistance(.31)

end

end

end

end