loading

How to make an autonomous basketball playing robot using an iRobot Create as a base

Featured
Picture of How to make an autonomous basketball playing robot using an iRobot Create as a base
This is my entry for the iRobot Create challenge. The hardest part of this whole process for me was deciding what the robot was going to do. I wanted to demonstrate the cool features of the Create, while also adding in some robo flair. All of my ideas seemed to either fall in the category of boring but useful, or cool and impractical. In the end cool and impractical won out and the basketball playing robot was born. After some thought I realized that could be practical. Suppose that you use orange paper, and that all of your trash cans have green backboards...

 
Remove these adsRemove these ads by Signing Up

Step 1: Aquire parts

Because of the time limit of the contest, most of the parts I used were "off the shelf".

"Stock" Robot Parts Used:
Create (x1) -- from iRobot www.irobot.com
XBC V.3.0 (x1) -- from Botball www.botball.org
Create-Roomba cable (x1) -- from Botball www.botball.org
Servo (x2) -- from Botball www.botball.org
Sharp rangefinder (x1) -- from Botball www.botball.org
Assorted LEGO bricks -- from LEGO www.lego.com
6-32 machine screws (x4) -- from McMaster www.mcmaster.com

"Created" Robot Parts Used:
3/8" thick extruded PVC sheet -- this stuff is awesome, but I can't remember where I got it from, but it is just like this stuff http://www.lynxmotion.com/Category.aspx?CategoryID=62

Other parts:
Orange "POOF" ball -- from WalMart
Basketball goal looking trash can -- from Lowes
Green "backboard" -- extra PVC painted bright green

Step 2: Create the unique part

Picture of Create the unique part
The only part that I had to fabricate was a plate that bolted to the Create and offered LEGO spacing. The spacing of the LEGO brick holes is 8mm apart, but I did a double spacing to save time. The extruded PVC is a breeze to work with. It can be cut with a utility knife, but is rigid and strong. I often pick up the robot by this plate and I have not had a problem yet.

Step 1:
Cut the sheet to 3.5" x 9.5", you can cut this with a utility knife.

Step 2:
Drill the holes for the create screws. The create screws make a box that is 2 and 5/8" by 8 and 5/8".

Step 3:
Drill the LEGO brick spaced holes. Use a 3/16" drill bit and I spaced the holes 16mm apart.

Tip:
I laid out the sheet in a CAD program, printed it out full size and taped it to the sheet. Then I used this as a guide for cutting and drilling.

Step 3: Assembling the Robot

Picture of Assembling the Robot
ball arm.jpg
noet.jpg
noxbc.jpg
arms.JPG
I enjoy building things as simply as possible, that way when they jump off of the table you don't have to rebuild as much!

1. Screw the newly fashioned plate to the top of the Create
2. Build an arm to grab the ball
3. Build an arm to hold the camera
4. Build a mount for the rangefinder
5. Mount the XBC and connect all of the cables

Step 4: Programming the robot

I decided to use the XBC as my controller mainly because of its built in color tracking. Because I decided to with the XBC as the brains of the operation I programmed my robot in Interactive C, or as I call it IC. IC is free to use and can be downloaded at www.botball.org. IC is very similar to C++, but has several built in libraries. As it turns out, David Miller from the University of Oklahoma has written a library for the Create which can be downloaded from his page at http://i-borg.engr.ou.edu/~dmiller/create/.

With those resources and the manuals for the create I was ready to program. But the next big challenge was what did I want it to do? I wanted a robot that could go and pick up orange balls and score them in a basket. My goal sounded simple, and probably could have been simple, but the more I got into what the Create could do, the more i wanted it to do. My final list looked like this:

1. Find orange ball
2. Pick up orange ball
3. Locate basket
4. Put ball in basket

While

1. Avoiding objects
2. Not falling off anything(like a table)
3. Detecting the charge of the battery and docking with the home base when low

Oh, and all of this is completely autonomous, meaning that it is all preprogrammed.

Step 5: Code

It may be messy, but it works.

#use "createlib.ic"
#use "xbccamlib.ic"

#define cam 0//camera servo port
#define arm 3//arm servo port
#define et (analog(0))//et port

/*The create cable also needs to be plugged in. The power jack,
the 3 pronged plug into port 8 and the one labeled U X into JP 28
(next to the USB port) with the U towards the camera*/

#define c_down 5//camera servo down
#define a_down 17//arm servo down
#define hold 50//servo hold ball
#define caught 27//arm servo position to keep from getting caught on table
#define shoot 150//servo throw ball
#define track_c 25//camera servo track close position
#define track_f 45//camera servo track far position

#define center 120//center of camera vision
#define inrange 30//track_y coordinate when ball is in claw
#define ball 0//channel of orange ball
#define ball_x (track_x(ball,0))//x coordinate of ball
#define ball_y (track_y(ball,0))//y coordinate of ball

#define slow 100//speed of slow motor
#define fast 175//speed of fast motor

#define clear 0.2//sleep to back away from obstacles
#define time 0.5 //1.0 is a 90 degree right turn
#define rest 0.05//time to sleep while tracking blobs

#define speeda 175//speed of avoid turn
#define back_s -200//speed to back away from bumped object
#define straight 32767//drive in a straight line

#define backb 2//channel of backboard main color
#define square 1//channel of backboard accent color
#define track_d 250//camera position for tracking goal
#define track_find 70//camera position for long tracking
#define reverse 2.25//sleep time for a 180
#define back_f -150//back fast speed
#define back_sl -125//back slow speed
#define center_x 178//true x center of cam
#define center_y 146//true y center of cam

int pida;//avoid process
int pidb;//track process
int pidc;//score process
int have_ball = 0;//tells which function we are in

void main(){
long ch;
enable_servos();//enable servos
init_camera();//start camera
cconnect();//connect to create with full controll
start_a();//start avoid function
start_b();//start ball_tracking function
while(1){
if(r_button()||gc_ldrop||gc_rdrop){//if picked up or r shoulder button
kill(pida);
kill(pidb);
kill(pidc);
disable_servos();
disconnect();
break;}
create_battery_charge();
display_clear();
printf("charge = %l\n", gc_battery_charge);
if(gc_battery_charge<1200l||b_button()){
kill(pida);
kill(pidb);
kill(pidc);
throw();
have_ball=0;
create_demo(1);
while(b_button());
while(gc_battery_charge<2800l&&!b_button()){
create_battery_charge();
display_clear();
printf("charge = %l\n", gc_battery_charge);
sleep(1.0);}
cconnect();
back();
sleep(2.0);
start_a();
start_b();}
}

}

void avoid(){

while(1){//repeat forever

create_sensor_update();//update all sensor values
//create_drive (speeda,straight);
if(gc_lbump==1){//left bump
avoid_right();}//turns right to avoid
else if(gc_rbump==1){//right bump
avoid_left();}//turns left to avoid
else if(gc_lfcliff==1){//left front cliff
avoid_right();}
else if(gc_rfcliff==1){//right front cliff
avoid_left();}
else if(gc_lcliff==1){//left cliff
avoid_right();}
else if(gc_rcliff==1){//right cliff
avoid_left();}
}
}

void track_ball(){

kill(pidc);

while(!have_ball){//repeat until get ball

track_update();
far();//sets the camera
ready();//sets the arm

while(et<255){//until max value happens when ball is caught

track_update();//update camera picture

if(ball_x<=(center-5)){//if the ball is left
track_update();
create_drive_direct(slow,fast);//turn left
sleep(rest);}

else if(ball_x>=(center+5)){//if the ball is right
track_update();
create_drive_direct(fast,slow);// turn right
sleep(rest);}

else if(ball_x<(center+5)&&ball_x>(center-5)){// if the ball is centered
track_update();
create_drive_straight(fast);//go straight
sleep(rest);}
}
grab();//grab ball
beep();//make noise
stop();//stop driving
have_ball=1;//make a note that I have ball
}
start_c();//find the basket
sleep(1.0);//sleep so that I'm not doing anything when I get killed
}

void find_basket(){

kill(pidb);//kill ball tracking process
find();//put camera up
track_set_minarea(1000);//the backboard is large, so only look for large blobs

while (have_ball){//while I have the ball

track_update();
while(track_x(backb,0)<=(center_x-20)||track_x(backb,0)>=(center_x+20)){//while not centered
track_update();

if(track_x(backb,0)>=(center_x+20)){//if the backboard is left
track_update();
create_spin_CCW(100);}//turn left

else if(track_x(backb,0)<=(center_x-20)){//if the backboard is right
track_update();
create_spin_CW(300-center_x);}// turn right slowing as the center approaches
}
stop();

while(track_size(backb,0)<=(6000)){//while the target is less than 6000 pixels in size
track_update();
if(track_x(backb,0)<=(center_x-5)){//if the target is left
track_update();
create_drive_direct(slow,fast);//turn left
sleep(rest);}

else if(track_x(backb,0)>=(center_x+5)){//if the target is right
track_update();
create_drive_direct(fast,slow);// turn right
sleep(rest);}

else if(track_x(backb,0)<(center+5)&&track_x(backb,0)>(center_x-5)){// if the target is centered
track_update();
create_drive_straight(fast);//go straight
sleep(rest);}
}
stop();
//create_drive_straight(fast);// get a little bit closer
//sleep(1.0);
//stop();
sleep(1.0);
create_spin_CW(speeda);//spin right
sleep(reverse);//sleep long enough for a 180 turn
stop();
down();//put camera down to track backboard
sleep(1.0);
track_set_minarea(200);//use a smaller min size, since we are pointed at it and going to get closer

while(track_y(backb,0)>=(center_y-140)){//while the target is less than the y coordinate
track_update();
if(track_x(backb,0)<=(center_x-5)){//if the target is left
track_update();
back_right();//turn left
sleep(rest);}

else if(track_x(backb,0)>=(center_x+5)){//if the target is right
track_update();
back_left();// turn right
sleep(rest);}

else if(track_x(backb,0)<(center+5)&&track_x(backb,0)>(center_x-5)){// if the target is centered
track_update();
back();//go straight
sleep(rest);}

}
stop();
beep();
throw();//shoot
sleep(1.0);
have_ball=0;//reminder I threw ball and don't have it
}
start_b();//back to ball tracking
sleep(1.0);//don't do anything until this process dies
}

void cconnect(){
create_connect();
create_full();//for full controll of ledge sensors
create_power_led(0,255);}//green power led

void disconnect(){
stop();//stop moving
create_disconnect();}

void back_away(){
back();
sleep(clear);
stop();}

void rotate_l(){
create_spin_CCW(speeda);
sleep(time);
stop();}

void rotate_r(){
create_spin_CW(speeda);
sleep(time);
stop();}

void stop(){
create_drive(0,straight);}

void back(){
create_drive(back_s,straight);}

void ready(){
set_servo_position(arm, a_down);}

void check(){
set_servo_position(cam, track_c);}

void far(){
set_servo_position(cam, track_f);}

void ledge(){
set_servo_position(arm, caught);}

void throw(){
int a;
for(a=50; a>=30; a-=1){//get ready
set_servo_position(arm, a);}
set_servo_position(arm, shoot);}

void grab(){
int a;
for(a=0; a<=hold; a+=1){//raise the arm smoothly
set_servo_position(arm, a);}}

void down(){
set_servo_position(cam, track_d);}

void find(){
set_servo_position(cam, track_find);}

void start_a(){
pida = start_process(avoid());}

void start_b(){
pidb = start_process(track_ball());}

void start_c(){
pidc = start_process(find_basket());}

void kill(int pid){
CREATE_BUSY;//wait for current create process to finish, and take priority
kill_process(pid);
CREATE_FREE;//i'm done
stop();}

void avoid_left(){
kill(pidb);//stop everything else
kill(pidc);
ledge();//pick up claw so it does not get caught on the table
back_away();//back away
rotate_l();//rotate away from obstacle
ready();//put claw back down
if(have_ball){//if i have the ball
start_c();}//start goal tracking
else if(!have_ball){//if i don't have the ball
start_b();}//start ball tracking
}

void avoid_right(){
kill(pidb);
kill(pidc);
ledge();
back_away();
rotate_r();
ready();
if(have_ball){
start_c();}
else if(!have_ball){
start_b();}
}

void back_left(){
create_drive_direct(back_f,back_sl);}

void back_right(){
create_drive_direct(back_sl,back_f);}

Step 6: Was it worth it?

The costs were:

Create + battery+ doc = $260
XBC starter kit (xbc, cam, LEGO bricks, sensors) = $579
PVC + paint + screws = about $20
Total cost = $859

I already had the XBC starter kit from Botball, so the cost to me was the cost of the Create.

I think that it was worth it, and the best part is that all of the parts I used are reusable, if I could bring myself to part out this bot.

This video shows the avoid sub routine, on a table top.


This video shows the robot scoring 5 orange balls in a goal. I only assisted to speed the process along, it would have found ball 5 eventually on it's own.


Step 7: Conclusion

The final result is a robot that can pick up and score orange balls in a goal all on its own.

I loved working on this project. The more I worked on this robot the more attached I became to it. I now talk to it as if it were a pet. I hope that this has helped you on your next project. There are lots of people that I need to thank, but there are too many.

Like Bernard of Chartres so elegantly stated:

"we are like dwarfs on the shoulders of giants, so that we can see more than they, and things at a greater distance, not by virtue of any sharpness on sight on our part, or any physical distinction, but because we are carried high and raised up by their giant size."
msuresh37 months ago
hey, ur model was really great, can u also make a robot that can play badminton please.....I'm dancing some problems with buying the correct parts for it
Timmers2 years ago
Have you seen this, pretty cool creation.

http://www.kickstarter.com/projects/567971283/iroo?ref=live
GBC? u mad but GJ =)
Zacattack6 years ago
hmmm this is awesome, great job, im definatly using the XBC for my next robot, either for a hexapod or an autonomous race car (using one of those hobby class rc cars)
Hawaii000007 years ago
How did you get the code for the camera?
Matthew Oelke (author)  Hawaii000007 years ago
The program I am using is called IC, which is basically C. IC has library functions to return information from the camera, like blob size, x axis, y axis, ect. IC supports 16 blobs across 3 channels so I can track up to 48 blobs at a time. Then you just take the values returned and make everything else happen.

If you are interested in IC check out Botball.org for more information.
Nice job! I really like the idea of using a GBA as a microcontroller, but 300 bucks for it is too much for my budget, maybe someone could make a Open Source version, like the Arduino...
golfball7 years ago
This is so cool! I want to build one but like everyone else i couldn't possably afford it, good work!
so it senses ledges..... I want to build one and put a orange ball on the edge of the grand canyon
Dantex7 years ago
where you bought the camera?
Matthew Oelke (author)  Dantex7 years ago
Thornburg7 years ago
Nice, the only thing that I would have done, is make it pick up your dirty clothes and put it in the wastebasket. It would be pretty hard determining what not to pick up, things that are to heavy could break the the arms. Still I thought this was a really great idea.
Matthew Oelke (author)  Thornburg7 years ago
Thanks.
gilby7 years ago
So this is a great start for a laundry sorting robot or a robot to clean up my house. It goes great with the rest of the roomba products!
This bot is autonomous? It scored 5 of 5 - better than what I would have scored!
Matthew Oelke (author)  cobracommander7 years ago
Yes, this robot is completely autonomous. It was loaded with code before hand and then ran the code all on it's own, i.e. no live controls were used.
zieak7 years ago
Now if only my socks were all orange balls...
gamer7 years ago
really cool, if it wasnt 900 bucks, id make one. whats the image displayed on the gameboy screen?
Matthew Oelke (author)  gamer7 years ago
Initially the image is the Gameboy logo as the GBA boots. Then it loads IC and has a main menu. When I run the robot I have it print the battery charge. The XBC is only $292. So if you have some LEGO bricks and/or a Create or a Roomba, It can be done for much less.
meowcat147 years ago
Wow, that's really cool! You have awesome commenting on your code. I want one of my own!
Matthew Oelke (author)  meowcat147 years ago
Thanks, I wanted it to be easy for other people to use and understand. Remember kids, always comment your code. :)
wow this looks cool, and so is your pic of Scott from ctrlaltdel
Matthew Oelke (author)  btop7 years ago
Thanks.
That is very cool, what is the total cost? +
Matthew Oelke (author)  BurningApple7 years ago
Let's see...

Create + battery+ doc = $260
XBC starter kit (xbc, cam, LEGO bricks, sensors) = $579
PVC + paint + screws = about $20
Total cost = $859

I already had the XBC starter kit from Botball, so the cost to me was the cost of the Create. I think I'll add this to the instrucable.