Let's Make Robots!

Update- Laser Cat


 I cant think of a good name, but im sure theres a good one somewhere, if any of you think of anything let me know. 

 

Laser Cat

 

The idea of this project is to help me learn a few things needed for my longterm project Airborne bot. It is basicaly a laser controlled by an arduino using two servos. It is for my two cats Harry and Fifi (girls cat. Fifi ffs! ) to play with.

 

WHen it is complete it will enable me to move the laser using a web page with a control panel and a video feed the user will click a position on the video feed and the laser will move to that point with the cats chasing it. Each time a cat manages to hit the laser point with its paw it will gain a point. THe first one to ten will get a treat which will be thrown to it from the unit. 

 

Im using processing to build the control panel for it to process the image from the camera and send serial output to the arduino to give the servos their position. The scoring will be worked out by dividing the target wall up into paw sized grid  blocks. I think i can work out whether the cat has scored by working out if there is a change in color in the wall in that grid and if the grid thats changed is the one that the laser is in at the time, my theory is that thelicght cream wall with eiher go ginger or black letting me know which cat got the point. Possible problems that i will have to work round is differentiating between cat paw color change and laser color change. 

 

So far i have the base unit built so that i can lay some code down, and i have the video feed going to processing and being displayed on screen. The servo is able to move along the x axis controled by mouse clicks. However im finding it difficult to control two servos through serial communication.  

 

Eventually i plan to have the unit completely wireless and mounted in the garden.

 

The aims of this project are to help me gain a better understanding of the following areas:

 

 

serial communication

working with coordinates

controling things with processing

working with video

wireless communication

 

 

 

 Update 13/ april/ 09

Ive finaly finished writing the code for the control of it. Unfortunatly i have played with it so much that my ginger cat is frustrated with it and the black cat isnt here so i cant post a video of them playing with it yet. 

 

 

 

Here is the arduino code: 

#include <Servo.h> 

 

 

 

Servo myservo1;  // create servo object to control a servo 

 

Servo myservo2;  

 

 

 

int userInput[3];   // raw input from serial buffer, 3 bytes

 

int startbyte;      // start byte, begin reading input

 

int pos = 0;    // variable to store the servo position 

 

int i;              // iterator

 

 

 

void setup() 

 

 

   // attaches the servos on pin 9 and 10 to the servo object 

   myservo1.attach(9);  //x axis

   myservo2.attach(10); //y axis

   Serial.begin(9600);

 

 

 

void loop() 

 

 

  // if the buffer has the right ammount of data in it

 

  if (Serial.available() > 2) {  

 

    //read the first byte  

 

    startbyte = Serial.read();  

    // if it's really the startbyte (255)  

 

    if (startbyte == 255) {  

 

      // then get the next two bytes  

      for (i=0;i<2;i++) {  

 

        userInput[i] = Serial.read();  

 

      }  

 

 

      // first byte is the servo we want to move

 

      int servo1 = userInput[0];  

 

      // second byte = which position?  

 

     int servoPosition1 = userInput[1]; 

 

    // print some debug lines to the serial port

 

    Serial.print("Servo: " );

 

    Serial.print(servo1);

 

    Serial.print(" Move: ");

 

    // map the input from the serial port to the min and max for the 

 

    // camera width

 

     servoPosition1 = map(servoPosition1, 0, 179, 78,108);

 

     Serial.print(servoPosition1);

 

     myservo1.write(servoPosition1);

 

      }

 

      //repeat for servo 2

 

      if (startbyte == 254) {  

 

      // then get the next two bytes  

 

      for (i=0;i<2;i++) {  

 

        userInput[i] = Serial.read();  

 

      }  

 

 

      int servo2 = userInput[0];  

 

    // second byte = which position? 

 

    int servoPosition2= userInput[1];

    Serial.print("Servo: " ); 

    Serial.print(servo2);

    Serial.print(" Move: ");

    Serial.print(servoPosition2);

    servoPosition2 = map(servoPosition2, 119, 1, 54, 78);

    Serial.print(servoPosition2);

    myservo2.write(servoPosition2);

 

      }

  }

 

}

 

 

 

I need to neaten the code up a bit and correct an error with recognising which server to move, but it works. 

 

Here is the processing code: 

import fullscreen.*;

 

import processing.serial.*;

import processing.video.*; 

 FullScreen fs; 

Serial port;

//set up a few settings for the gui. you need to change this to the

// screen resolution you are using

int scrnWidth=1024; //width of screen, full screen comming soon!!

int scrnHeight=768; //height of screen 

int camSizeX=640; //width of cam box

int camSizeY=480; //height of cam box

 

// layout settings. 

int leftMargin = round((scrnWidth - camSizeX) / 2);

 

int camPosX=leftMargin;//x coordinate of top left corner of camera box

int camPosY=0;//y coordinate of top left corner of camera box

int textOffsetX=leftMargin + 0;

int textOffsetY = camSizeY + 5;

 

// serial in variables to hold any values given back from the arduino 

String returnText="";

 

 

 Serial myPort;  // The serial port

Capture cam;

int inByte =0;

int read=0;

void setup()

{

    size(scrnWidth, scrnHeight);

    // Create the fullscreen object

   // fs = new FullScreen(this); 

 

    // enter fullscreen mode

   //  fs.enter();

 

 

 

  cam = new Capture(this, camSizeX, camSizeY);

 

 //set up the text settings

 

 

  //sets the port to the one your arduino is using

  myPort  = new Serial(this, "COM3", 9600);  

 

}

 

void draw()

{

 

  PFont font;

  font = loadFont("Verdana-48.vlw"); 

  textFont(font); 

 

 background(32, 62, 22);

   //guideLines();

 

  camDisplay(); //put cam on screen

 

   mousePos(); // put mouse pos on screen

 

 

 

  //drawGrid();

 

 while (myPort.available() > 0) {

     int gb = myPort.read();

   char fg = char(gb);

   println(fg);

 

     String inBuffer = myPort.readString();   

    if (inBuffer != null) {

      println(inBuffer);

      returnText=inBuffer;

    }

 

  // text("Recieved", 5, 482);

  //text(inByte,  220, 482);

}

 

}

 

 

void mousePressed() {

      fill(6, 191, 41);

      int posNewX = round( 179 - (mouseX  - 190) / 3.6 ) ;

      int posNewY =mouseY / 4;

 

 

 

      char c = char(255);

 

      myPort.write(c);

      myPort.write(char(1));

       myPort.write(posNewX);

      text( "Here:" + posNewX, 5, 560);

 

 

      char d = char(254);

 

      myPort.write(d);

      myPort.write(char(2));

       myPort.write(char(posNewY));

      text( posNewY, 5, 540);

 

     }

 

 

 

void mousePos(){

 

fill(6, 191, 41);

textSize(14);

text("mouseX: " + mouseX + " / " + "mouseY" + mouseY, textOffsetX, camSizeY-10); 

//text(mouseX, 210, 510);

int msPo=179 - round(mouseX / 3.6);

text("sent " + msPo, textOffsetX, camSizeY + 20);

text(returnText,  textOffsetX, camSizeY + 40);

//text("mouseY", 5, 441); 

//text(mouseY, 210, 441);

 

}

 

 void camDisplay(){

 

   if (cam.available() == true) {

    cam.read();

    image(cam, camPosX, camPosY);

    // The following does the same, and is faster when just drawing the image

    // without any additional resizing, transformations, or tint.

    //set(160, 100, cam);

  }

 

 

 }

 

 void guideLines(){

   stroke(240, 17, 17);

 line(78, 0, 78, scrnHeight);

 line(108, 0, 108, scrnHeight);

 

 }

 

 void drawGrid(){

   stroke(36, 137, 48);

for (int i = 10; i < scrnWidth; i+=10) {

     line(i, 00, i, scrnHeight);

 

    //line(i, 0, i, 150);

  }

  for (int i = camPosY; i < camPosY + camSizeY + 10; i+=10){

     //ne(0, i, scrnWidth, i);

     line(camPosX, i, camSizeX, i );

 

    //line(i, 0, i, 150);

  }

 }

 

To get processing to pic up my cam i had to install vdig, there are ways to do it without vdig though, see the processing.org site for details.

 

As soon sd my cat gets in i will post a video , in the meantime im going to tidy my code up. 

 

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Amazing!  What an awsome idea!  Poor cat tho... :)
That's great Edgee! Add a water cannon to squirt the cat if the cat gets up on the kitchen bench or somewhere else it's not meant to be and it will be a good entry to the Cat Splat challenge :D
Im in the middle of a cat recognition script for use with this. If i manage to get it working i reckon it would be pretty easy to modify it to work as a cat splat. Watch this space!! :p 
Very cool idea.  I used to have a siamese cat that would chase a laser pointer endlessly.  Are you doing any signal processing on the video stream to track the cats?

I have written a piece of code to track a lighter. Im going to skip the wireless part for now and concentrate on that till i have the money to buy what i need.  

Updated above, video comming. 

nice project you have!!!   and very ambitious  ;)   I will look forward to see more of your improvements

cats are so funny  :)

I love the rewards for the cats. That, to me, is a new twist in the lazorred cat tease gizmo.

Keeping score will be difficult indeed. How would you know it was indeed a paw that hit the rigth square? Or is this grid really high up a wall? Which would exclude tails, heads, rumps, etc from being detected.

To be honest im not 100% sure yet, i can get as far as checking the grid squares around it to get a rough position for the main mass of the cat but differentiating from the tail is proving to be a little more tricky, But that is assuming that the paw is to the left, right or above the cat. If i keep it above the cats head then i could possibly rule out the tail that way. I was planning on making the drid squares just wider than a cats paw and then counting a measure of two grid squares width as a score.

  I dont think i will find a solution till i crack on with it, im not 100% sure i can make it work. 

those are the best

to solve....