Go Down

Topic: Fully Autonomous Golf Caddy (Read 5 times) previous topic - next topic

distorteddesigns

I though about doing this a long time ago but you have a very good start. You know there is a lot easier way of doing this. No gps needed. You just want the bag to stay within a certain distance of the golfer while walking, say 4 ft behind you. You just need a small signal transmitter that could be on a key chain, Then something attached to the arduino that looks at the signal strength to determine distance. Then you just need 2 buttons go and stop so when you actually go to the tee it is not trying to follow you there. That way it works anywhere not just on 1 golf course and if you shank a ball your bag isn't 30ft away from you. Just need a way to identify you from your others in your party. Could even use infrared leds to follow.

Maybe this helps

bleedscarlet

That actually already exists and it's undesirable because it still requires attention. Senior Design is about pushing the industry, not trying to simply make something cheaper.

Shadow Caddy, Bat Caddy, and Follow-Me Caddy were our literature examples.

this will ideally drive by itself completely. So far it's getting close but it still needs a bit of tuning and optimizing.

bleedscarlet

what you're talking about was designed with active RFIDs, it works pretty well.

Essentially you have a "stop" and "follow" button on a belt clip and it does exactly that.

Not very well priced though, most of the solutions out there cost quite a bit (although somewhat insignificant when compared to the cost of golfing)

Scott Portocarrero

Are you planning on doing a full write up when the project is done?  A video with working caddy while under GPS Nav would be nice too.  Keep up the good work!!! 8-)

bleedscarlet

yeah, there's going to be a full report and presentation. Not sure if the presentation is going to be video taped but I can put the full report up here when it's done and there are already lots of videos and there will be many more.

check my youtube channel (bleedscarlet) for latest videos, when we come up with good solid tests the videos will get posted here but you can see our progress there.

We are GPS navigating! just not very well nor very fast...

bleedscarlet

with some assistance in the troubleshooting section of the forum we figured out a way to get the accuracy we need. We drop the degrees and just use the minutes and fractional minutes instead :p

since a degree is >42 miles and the golf course is in the middle of a degree we don't need to bother with that complication for now.

In a full scale deployment we would have to put an if statement around the whole thing to add some kind of directional correction if say you needed to move from 74.0001 to 73.9989 or something, but we're not concerning ourselves with that mostly because i'm burning out from staying in the lab until 2AM every night.

bleedscarlet

#36
Dec 10, 2010, 10:25 am Last Edit: Dec 10, 2010, 10:26 am by bleedscarlet Reason: 1
Some asshole decided texting and driving is cool.

We almost got run over.





Needless to say the physical damage isn't too bad, but every component is broken. Our demonstration was supposed to be at 1PM on friday.....this happened at 4PM on thursday...

bleedscarlet

#37
Dec 10, 2010, 10:27 am Last Edit: Dec 10, 2010, 10:27 am by bleedscarlet Reason: 1
Here was our last program framework.

Code: [Select]

/*******************************************************************
Avinash Arora
Carl Barreau
Stephen Dudek
Asa Roper
Senior Design - Industrial and Systems Engineering - 2010
Motor Controller uses Serial 3
GPS uses Serial 2
Serial 1 cell phone
Compass uses SCL & SLA, SCL=green, SLA=blue
*******************************************************************/


/*******************************************************************
                          Libraries
*******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <String.h>
#include <ctype.h>
#include <math.h>
#include <Wire.h>
/*******************************************************************
                       Initialize Variables
*******************************************************************/
int onModulePin = 2;        // the pin to switch on the module (without press on button)
int timesToSend = 1;        // Numbers of SMS to send
int count = 0;
int compassAddress = 0x32 >> 1;
int heading = 0;
int tilt = 0;
int roll = 0;
int ledPin = 13;
int rxPin = 0;
int txPin = 1;
int byteGPS=-1;
char linea[300] = "";
char comandoGPR[7] = "$GPRMC";
int cont=0;
int bien=0;
int conta=0;
int indices[13];
char CurrentXascii[14];
char CurrentYascii[14];
int CurrentXsingle;
int CurrentYsingle;
float CurrentX;
float CurrentY;
long CurrentX1;
long CurrentY1;
int CurrentX2;
int CurrentY2;
double CurrentXi;
double CurrentYi;
long CurrentXoff;
long CurrentYoff;
double CurrentHeading;
double CurrentHeading0;
byte responseBytes[6];
int GPStimer=0;
double DeltaX=0.000;
double DeltaY=0.000;
int Instance=0;
int InstanceSize=0;
int buttonState=0;
int buttonPin = 22;
int lastButtonState=0;
int buttonPushCounter=0;
float DesiredHeading=0.0;
int CompassComplete=0;
int LeftSpeed=0;
int RightSpeed=0;
int LeftSpeed0=0;
int RightSpeed0=0;
int MoveSwitchPin=34;
int MoveSwitch=0;
int Calibration=0;
int CalibrationCounter=0;
double ParkingLotX[3] = {31.2462,31.2475,31.2523};
double ParkingLotY[3] = {27.6146,27.5992,27.6102};
long OffsetX=0.0000;
long OffsetY=0.0000;
/*******************************************************************
                      Set Engine Speed 1
*******************************************************************/

void setEngineSpeed1(signed char cNewMotorSpeedH)
{
 
   unsigned char cSpeedVal_Motor1 = 0;
   if(cNewMotorSpeedH==0)
   {
     
       Serial3.print(0,BYTE);
       return;
       
   }
   
   cSpeedVal_Motor1 = map(cNewMotorSpeedH,-100,100,1,127);
   Serial3.print(cSpeedVal_Motor1, BYTE);
   
}

/*******************************************************************
                      Set Engine Speed 2
*******************************************************************/

void setEngineSpeed2(signed char cNewMotorSpeed2)
{    
 
   unsigned char cSpeedVal_Motor2 = 0;
   if(cNewMotorSpeed2 == 0)
   {
     
       Serial3.print(0,BYTE);
       return;
       
   }
   
   cSpeedVal_Motor2 = map(cNewMotorSpeed2,-100,100,128,255);
   Serial3.print(cSpeedVal_Motor2, BYTE);
   
}
/*******************************************************************
                  Switch Cell Phone Module On
*******************************************************************/
void switchModule()
{
 
  digitalWrite(onModulePin,HIGH);
  delay(2000);
  digitalWrite(onModulePin,LOW);
  delay(10000);
 
}
/*******************************************************************
                     Read Sensor (Compass)
*******************************************************************/

void readSensor()
{
 
   Wire.beginTransmission(compassAddress);
   Wire.send(0x50);
   Wire.endTransmission();
   delay(2);
   Wire.requestFrom(compassAddress, 6);
   if(6 <= Wire.available())
   
   {
     
       for(int i = 0; i<6; i++)
       
       {
           responseBytes[i] = Wire.receive();
           
       }
       
   }
   
   heading = ((int)responseBytes[0]<<8) | ((int)responseBytes[1]);
   tilt = (((int)responseBytes[2]<<8) | ((int)responseBytes[3]));
   roll = (((int)responseBytes[4]<<8) | ((int)responseBytes[5]));
   CurrentHeading = heading/10;
   
}

/*******************************************************************
                         Read Sensor (GPS)
*******************************************************************/

void readGPS()

{
 
   for(GPStimer=0;GPStimer<250;GPStimer++)
   
   {
     
       byteGPS=Serial2.read();
       if (byteGPS == -1)
       {
         
           delay(10);
           
       }
       
       else
       
       {
         
           linea[conta]=byteGPS;
           conta++;
           if (byteGPS==13)
           {
             
               digitalWrite(ledPin, LOW);
               cont=0;
               bien=0;
               for (int i=1;i<7;i++)
               
               {
                   if (linea[i]==comandoGPR[i-1])
                   {
                     
                       bien++;
                       
                   }
                   
               }
               
               if(bien==6)
               {
                 
                   for (int i=0;i<300;i++)
                   
                   {
                       if (linea[i]==',')
                       
                       {
                           indices[cont]=i;
                           cont++;
                           
                       }
                       
                       if (linea[i]=='*')
                       
                       {
                         
                           indices[12]=i;
                           cont++;
                           
                       }
                   }
//                    Serial.println("");
//                    Serial.println("");

                   Serial.println("---------------");
                   for (int i=0;i<12;i++)
                   
                   {
                       for (int j=indices[i],k=0;j<(indices[i+1]-1);j++,k++)
                       
                       {
                           switch(i)
                           
                           {
                             
                           case 2 :
                               CurrentXascii[k]=linea[j+1];
                            break;
                           case 4 :
                               CurrentYascii[k]=linea[j+1];
                               break;
                               
                           }
                           
                       }
                       
                   }
                   
//                    int xlength=sizeof(CurrentXascii);
//                    int ylength=sizeof(CurrentYascii);
//                    for (int i=0;i<xlength;i++){
//                        CurrentX1[i]=(int)CurrentXascii[i];
//                    }
//                    for (int i=0;i<ylength;i++){
//                        CurrentY[i]=(int)CurrentXascii[i];
//                    }
//                    CurrentX=atof(CurrentXascii)/10000;
//                    CurrentY=-atof(CurrentYascii)/10000;
/*                for (int i=0,k=5;i<5;i++,k--){
                       CurrentX1=CurrentX1+(10^k)*((int)CurrentXascii[i]);
                       Serial.println(CurrentX1);
                   }
                   for (int i=6,k=8;i<13;i++,k--){
                       CurrentX2=CurrentX2+(10^k)*((int)CurrentXascii[i]);
                       Serial.println(CurrentX2);
                   }
                   for (int i=1,k=5;i<6;i++,k--){
                       CurrentY1=CurrentY1+(10^k)*((int)CurrentYascii[i]);
                       Serial.println(CurrentY1);
                   }
                   for (int i=7,k=7;i<13;i++,k--){
                       CurrentY2=CurrentY2+(10^k)*((int)CurrentYascii[i]);
                       Serial.println(CurrentY2);
                   }
                   CurrentXi=CurrentX1+(CurrentX2/10000);
                   CurrentYi=-(CurrentY1+(CurrentY2/10000));
                   CurrentX=CurrentXi;
                   CurrentY=CurrentYi;
                   CurrentX1,CurrentX2,CurrentY1,CurrentY2,CurrentXi,CurrentYi=0;
                   String CurrentXc=CurrentXascii.replace(".",""); */
                   
                   //remove degrees to allow for greater dimensional accuracy
                   for (int i=0,j=9;i<2;i++)
                   {
                     
                       CurrentXascii[i]='0';
                       
                   }
                   
                   for (int i=0;i<3;i++)
                   {
                     
                        CurrentYascii[i]='0';
                       
                   }
                   
                   //clear extraneous digits
                   for (int i=9;i<13;i++)
                   {
                     
                       CurrentXascii[i]='0';
                       
                   }
                   
                   for (int i=10;i<13;i++)
                   {
                     
                        CurrentYascii[i]='0';
                       
                   }
                   

bleedscarlet

Code: [Select]



//                    CurrentX1=atol(CurrentXascii);
//                    CurrentY1=-atol(CurrentYascii);
//                    CurrentX=floor(CurrentX1/100000)+(CurrentX1%10000)/10000;
//                    CurrentY=floor(CurrentY1/100000)+(CurrentY1%10000)/10000;
//                    CurrentXoff=(atof(CurrentXascii));
//                    CurrentYoff=(atof(CurrentYascii));
                   CurrentX=(atof(CurrentXascii))-0.00324; //+OffsetX;
                   CurrentY=(atof(CurrentYascii))+0.01864; //+OffsetY;                    
               }
               
               conta=0;
               for (int i=0;i<300;i++)
               {
                   linea[i]=' ';                        
               }
               
           }
           
       }
       
   }
   
}

/*******************************************************************
                            Void Setup
*******************************************************************/

void setup()
{
   delay(500);
   
   Wire.begin();
   Wire.send(0x82);
   
   delay(500);
   
   //Telemetry:
   Serial.begin(9600);
   pinMode(13, OUTPUT);
   pinMode(MoveSwitchPin, INPUT);
   digitalWrite(13, HIGH);
   
   //GPS Module:
   Serial2.begin(4800);
   
   for (int i=0;i<300;i++)
   {
     
       linea[i]=' ';
       
   }
   
   //Motor Controller:
   Serial3.begin(9600);
   
   delay(2000);
   
   setEngineSpeed1(0);
   setEngineSpeed2(0);
   Instance=0;
   
   MoveSwitch=digitalRead(MoveSwitchPin);

   //Cell Phone:
   Serial1.begin(19200);               // the GPRS baud rate
//    switchModule();                    // swith the module ON
  for (int i=0;i<2;i++)
  {
      delay(5000);
     
  }
 
     Serial1.println("AT+CMGF=1");         // set the SMS mode to text
     delay(100);
     
}

/*******************************************************************
                           Void Loop
*******************************************************************/

void loop()
{
//    buttonState = digitalRead(buttonPin);
//    if (buttonState != lastButtonState) {
//        if (buttonState == HIGH) {
//            buttonPushCounter++;
//        }
//        lastButtonState = buttonState;
//    }
//    Instance=buttonPushCounter;
   MoveSwitch=digitalRead(MoveSwitchPin);
   if (Calibration==0)
   {
     readGPS();
       if (CalibrationCounter<10)
       {
           delay(10);
           CalibrationCounter++;
           Serial.println("Calibrating...");
       }
       else if (CalibrationCounter>=10)
       {
//            OffsetX=31.2523-CurrentXoff;
//            OffsetY=27.6102-CurrentYoff;
           Calibration=1;
           Serial.println("Calibration Complete.");
       }
       
   }
   
   else if (Calibration==1)
   
   {
     
       if (MoveSwitch == LOW)
       {
           if (Instance<3)
           {
               readSensor();
   //            Serial.print("Heading: ");
   //            Serial.print(CurrentHeading);
   //            Serial.print("\t Tilt: ");
   //            Serial.print(tilt / 10, DEC);
   //            Serial.print("\t Roll: ");
   //            Serial.println(roll / 10, DEC);
               delay(5);
               readGPS();
   //            Serial.print("Current X Value: ");
   //            Serial.print(CurrentX, 10);
   //            Serial.print("\t");                    
   //            Serial.print("Current Y Value: ");
   //            Serial.println(CurrentY, 10);
   //            Serial.println("---------------");
   
/*******************************************************************
                   Figure Out Delta X & Delta Y
*******************************************************************/
   
               DeltaX=ParkingLotX[Instance]-CurrentX;
               DeltaY=ParkingLotY[Instance]-CurrentY;
               
               if((abs(DeltaX)>0.002)||(abs(DeltaY)>0.002))
               {
                 
                   readGPS();
                   
/*******************************************************************
                    Calculate Desired Heading
*******************************************************************/
   
                     if (DeltaX<0) //Must Go South
                     {
                         if (DeltaY>0) // Must Go South East (Reversed from normal quadrant because of hemisphere flip)
                         {
                             DesiredHeading=270+atan(DeltaX/DeltaY)*180/3.14159265;
                         }
                         
                         else if (DeltaY<0) // Must Go South West (Reversed from normal quadrant because of hemisphere flip)
                         {
                             DesiredHeading=90+atan(DeltaX/DeltaY)*180/3.14159265;
                         }
                         
                     }

bleedscarlet

Code: [Select]

                     
                     else if (DeltaX>0) //Must Go North
                     {
                         if (DeltaY>0) // Must Go North East (Reversed from normal quadrant because of hemisphere flip)
                         {
                             DesiredHeading=270+atan(DeltaX/DeltaY)*180/3.14159265;
                         }
                         
                         else if (DeltaY<0) // Must Go North West (Reversed from normal quadrant because of hemisphere flip)
                         {
                             DesiredHeading=90+atan(DeltaX/DeltaY)*180/3.14159265;
                         }
                         
                     }
                     
   //                if (DeltaY<0)
   //                {
   //                    if (DeltaX>0)
   //                    {
   //                        DesiredHeading=270-atan(DeltaY/DeltaX)*180/3.14159265;
   //                    }
   //                    else if (DeltaX<0)
   //                    {
   //                        DesiredHeading=90+atan(DeltaY/DeltaX)*180/3.14159265;
   //                    }
   //                }
   //                else if (DeltaY>0)
   //                {
   //                    if (DeltaX>0)
   //                    {
   //                        DesiredHeading=270+atan(DeltaY/DeltaX)*180/3.14159265;
   //                    }
   //                    else if (DeltaX<0)
   //                    {
   //                        DesiredHeading=90-atan(DeltaY/DeltaX)*180/3.14159265;
   //                    }
   //                }
   
/*******************************************************************
                  Pull Current Heading & Auto Correct
*******************************************************************/
   
                   readSensor();
                   if (((DesiredHeading-CurrentHeading) < 15)&&((DesiredHeading-CurrentHeading)>6))
                   {
                       LeftSpeed=40;
                       RightSpeed=30;
                   }
                   
                   else if (((DesiredHeading-CurrentHeading) <= 30)&&((DesiredHeading-CurrentHeading)>15))
                   {
                       LeftSpeed=40;
                       RightSpeed=20;
                   }
                   
                   else if (((DesiredHeading-CurrentHeading) <= 60)&&((DesiredHeading-CurrentHeading)>30))
                   {
                       LeftSpeed=40;
                       RightSpeed=10;
                   }
                   
                   else if (((DesiredHeading-CurrentHeading) <= 180)&&((DesiredHeading-CurrentHeading)>60))
                   {
                       LeftSpeed=40;
                       RightSpeed=1;
                   }
                   else if (((DesiredHeading-CurrentHeading) <= 360)&&((DesiredHeading-CurrentHeading)>180))
                   {
                       LeftSpeed=-1;
                       RightSpeed=39;
                   }                
                   else if (((DesiredHeading-CurrentHeading) <= -6)&&((DesiredHeading-CurrentHeading)>-15))
                   {
                       LeftSpeed=30;
                       RightSpeed=39;
                   }
                   
                   else if (((DesiredHeading-CurrentHeading) <= -15)&&((DesiredHeading-CurrentHeading)>-30))
                   {
                       LeftSpeed=20;
                       RightSpeed=39;
                   }
                   
                   else if (((DesiredHeading-CurrentHeading) <= -30)&&((DesiredHeading-CurrentHeading)>-60))
                   {
                       LeftSpeed=10;
                       RightSpeed=39;
                   }
                   
                   else if (((DesiredHeading-CurrentHeading) <= -60)&&((DesiredHeading-CurrentHeading) > -180))
                   {
                       LeftSpeed=-1;
                       RightSpeed=39;
                   }
                   else if (((DesiredHeading-CurrentHeading) <= -180)&&((DesiredHeading-CurrentHeading) >= -360))
                   {
                       LeftSpeed=39;
                       RightSpeed=-1;
                   }
                   
                   else if (((DesiredHeading-CurrentHeading) <= 6)&&((DesiredHeading-CurrentHeading) >= -6))
                   {
                       LeftSpeed=40;
                       RightSpeed=39;
                   }
                   
/*******************************************************************
   Exponential Moving Average Motor Control & Send Motor Speeds
*******************************************************************/
   
                   LeftSpeed0=.9*LeftSpeed+.1*LeftSpeed0;
                   RightSpeed0=.9*RightSpeed+.1*RightSpeed0;
                   setEngineSpeed1(LeftSpeed0);
                   setEngineSpeed2(RightSpeed0);
                   
/*******************************************************************
Serial Prints for data verification (to be removed with final implementation)
*******************************************************************/
   
                   Serial.print("LeftSpeed: ");
                   Serial.print(LeftSpeed0);
                   Serial.print("\t");
                   Serial.print("RightSpeed: ");
                   Serial.print(RightSpeed0);
                   Serial.print("\t");
                   Serial.print("DesiredHeading: ");
                   Serial.print(DesiredHeading);
                   Serial.print("\t");
                   Serial.print("CurrentHeading: ");
                   Serial.print(CurrentHeading);
                   Serial.print("\t");
                   Serial.print("Calibrated? ");
                   Serial.print(Calibration);
                   Serial.print("\t");
                   Serial.print("Offset X: ");
                   Serial.print(OffsetX,6);
                   Serial.print("\t");
                   Serial.print("Offset Y: ");
                   Serial.println(OffsetY,6);
                   Serial.print("CurrentXascii: ");
                   Serial.print(CurrentXascii);
                   Serial.print("\t");
                   Serial.print("CurrentYascii: ");
                   Serial.print(CurrentYascii);
                   Serial.print("\t");
                   Serial.print("CurrentX: ");
                   Serial.print(CurrentX, 4);
                   Serial.print("\t");
                   Serial.print("CurrentY: ");
                   Serial.print(CurrentY, 4);
                   Serial.print("\t");
                   Serial.print("X: ");
                   Serial.print(ParkingLotX[Instance],6);
                   Serial.print("\t");
                   Serial.print("Y: ");
                   Serial.print(ParkingLotY[Instance],6);
                   Serial.print("\t");
                   Serial.print("Instance: ");
                   Serial.println(Instance);
                   
/*******************************************************************
                         End Telemetry
*******************************************************************/
   
               }
               
               else if((abs(DeltaX)<=0.002)&&(abs(DeltaY)<=0.002))
               {
                   Instance++;
                   setEngineSpeed1(0);
                   setEngineSpeed2(0);
                   delay(5000);
               }
           }
           
           else
           
           {
/*******************************************************************
                 Send Text Message Indicating Arrival
*******************************************************************/
            while (count < timesToSend)
            {
   
                delay(1500);
                Serial1.print("AT+CMGS=");          // send the SMS the number
                Serial1.print(0x22,BYTE);             // send the " char
                Serial1.print("17322337949");         // send the number (change ********* by the actual number)
                Serial1.println(0x22,BYTE);           // send the " char
                delay(1500);
                Serial1.println("Hey, I'm here!");     // the SMS body
                delay(500);
                Serial1.println(0x1A,BYTE);             // end of message command 1A (hex)
                delay(5000);
                count++;
   
              }
   
           }
   
/*******************************************************************
      Issue full stop for 5 seconds and start next instance
*******************************************************************/
           MoveSwitch=digitalRead(MoveSwitchPin);
       }
       
/*******************************************************************
If initial assistance switch is depressed, ignore sensors & go 100%.
*******************************************************************/
   
       else if(MoveSwitch == HIGH)
       {
         
           setEngineSpeed1(100);
           setEngineSpeed2(97);
           Serial.print("Moving...");
           delay(200);
           MoveSwitch=digitalRead(MoveSwitchPin);
           
       }

   }

     

Funky Diver

This is such a cool project... I'm very interested in the Norobo implementation as I've been a little lost with it's use since I got hte DroneCell, so a big thankyou from me for posting this up!

Go Up