To LUGNET HomepageTo LUGNET News HomepageTo LUGNET Guide Homepage
 Help on Searching
 
Post new message to lugnet.roboticsOpen lugnet.robotics in your NNTP NewsreaderTo LUGNET News Traffic PageSign In (Members)
 Robotics / 57
56  |  58
Subject: 
RoboTag version 0.8 -- explaination & NQC source
Newsgroups: 
lugnet.robotics
Date: 
Tue, 6 Oct 1998 17:46:46 GMT
Reply-To: 
mattdm@mattdm.orgNOSPAM
Viewed: 
2037 times
  
/*  Matthew's RoboTag 0.8 for Lego Mindstorms.
*
*  written in NQC version 0.5b1 -- http://www.enteract.com/~dbaum/lego/nqc/
*
*  Copyright (c) 1998 Matthew Miller. You're free to use and modify this as
*  you wish. You can also redistribute it, but please give me credit and
*  don't make any changes you haven't told me about. Thanks!
*
*  mattdm@mattdm.org -- http://www.mattdm.org/mindstorms/
*
* The basic game:
*
*   Two robots run around a playing field. When one tags another, the
*   "victim" must sit still for a few seconds.
*
* The playing field:
*
*   A big piece of paper, with a think black line for a border. There can
*   also be other lines on the paper for interest, although too many
*   doesn't work very well -- these aren't very smart robots. I find that a
*   simple partial line in the middle works well, like this:
*
*       -------------------------------------------------------
*      |                                                       |
*      |                                                       |
*      |                         |                             |
*      |                         |                             |
*      |                         |                             |
*      |                         |                             |
*      |                         |                             |
*      |                                                       |
*      |                                                       |
*       -------------------------------------------------------
*
*   The line is the border -- if the robot senses it, it must turn around.
*
*   The only actual objects allowed on the field are the robots, so if one
*   hits something, it's safe to assume it was the other robot.
*
* The robots:
*
*  Very simple. Treaded bulldozer-like robots, except that the 'blade' is
*  connected to a touch sensor, so that if it's bumped, the sensor is
*  triggered. (Shock absorbers, either large or small, are invaluable for
*  making this work. I'm really surprised Mindstorms doesn't come with any,
*  since it's such a useful construction. How do other people make their
*  bump sensors broad enough to be useful?) The light sensor is mounted
*  front-center and looks for the black line.
*
*  Light sensor is on input 2, touch sensor on 1. Motors on A and C. No
*  particular reason -- that's just the Way It Is.
*
*  The treads, by the way, have a 24t gear on attached directly to their
*  axles, and that meshes with an 8t gear attached to the motor shaft. This
*  gearing works well and is nice and compact. I wouldn't recommend it on
*  shag carpet or a dirty floor though, as the 24t gears are large enough
*  and close enough to the ground that they can gather junk. Works fine on
*  a paper play surface though.
*
*  (I'll post pictures and a movie of these sometime soon.)
*
* The protocol:
*
*  A lot of trust involved here. The RCXs are too dumb^H^H^H^H simple to do
*  otherwise. So, each robot believes what the other one says, and in fact
*  relies on the other to know if _it_ has been hit.
*
*  If robot A hits robot B, A sends out a "Bang" signal. When robot B hears
*  this, it responds with "Ow" and goes into "punishment" mode -- sits
*  still beeping mournfully for a few seconds. If robot A hears this Ow, it
*  goes about its business. (Namely, meandering meaninglessly.) But if it
*  doesn't get the response after a few seconds, it starts spinning and
*  yelling "Ditto Ditto Ditto" until a response is heard. (Spinning 'cause
*  that has a good chance of making the IR ports line up, the lack of which
*  being the usual cause of lost messages.) If robot B hears a Ditto, it
*  responds with an Ow, and if it isn't in punishment mode already, starts
*  being punished. If already is being punished, it doesn't add to the
*  punishment (but still says Ow, just to get robot A to shut up).
*
*  This may sound confusing, but it works beautifully.
*
*
* Notes:
*
*  Right now both robots run the same code. Maybe someday they'll each have
*  their own independent devious schemes....
*
*  For some reason, one light sensor gives readings about 10 lower than the
*  other. Which is sort of a pain. Originally, I just used a #define and
*  changed it before compiling/downloading, but that's annoying. So now the
*  robot reads 'normal' at startup, and assumes the dark line is going to
*  be about (at least) 7 darker than that. This is good for other reasons
*  too -- you could play on different colored paper without recompiling.
*  It also means you have to press "Run" while the robot is on the ground
*  on the playing field -- for some reason some of my friends' natural
*  instinct is to pick up the robot, press Run, and set it down. That won't
*  work.  Future (fairly easy) adjustment -- make it so it also triggers on
*  7 (or so) brighter than normal, for use with tape on carpets.
*
*  Also, we used the Mindstorms/GUI to set the IR port into long-range
*  mode.  This seemed like a good idea. We haven't tested it in
*  short-range. And I couldn't find any documentation on this anywhere --
*  has anybody looked into this? Can any alternative tools set/read what
*  mode it's in?
*
*  When I say "we", I mean Paul Stauffer, who owns the other RCX. I wish I
*  were that wealthy.
*
*  When we first built the robots, my bump-sensor kinda sucked and was
*  breaking all the time and stuff. So I re-built it, and now it's really
*  good (I'm proud of myself; can you tell?). It's especially good at
*  making Paul whine, because in a head-on collision, my robot always
*  triggers first, and therefore wins. Hahahahahahaha.
*
*/


int randnum;
int bumpcount;
int needackflag;
int gotackflag;
int blackvalue;

task main
{
    //set up sensors properly
    Sensor(IN_1,IN_SWITCH);
    Sensor(IN_2,IN_LIGHT);

    initlight(); //set trigger-value for border lines, since apparently
                 //different sensors give different readings, and
                 //because different surfaces obviously are different.

    //clear all flags
    bumpcount=0;
    needackflag=0;
    gotackflag=0;

    //start message-watching service
    start postoffice;

    //start black-line-watching service
    start checkline;

    //start bumper-watching service
    start checkbump;


    //full forward (um, the motors are connected backwards, so
    // Rev=Forward. sorry)

    Rev(OUT_A + OUT_C,OUT_FULL);

    while(true)        //loop forever
    {
        if (bumpcount>0)        // if we got hit
        {
            punishment();     // sit still for a while
            bumpcount -=1;    // and then decrement hit counter
        }


        if (needackflag>1 && gotackflag==0) // if we need to hear ack of
        {                              // our bump signal and we haven't yet
            startspinning(); //start turning a random dir
            ClearTimer(0);   //count how long we've spun
            while(gotackflag==0)  //wait until we get the ack signal
            {
                SendMessage(34);  //yell ditto
                PlaySound(0);     //and beep nicely

                Sleep(10);  // if we yell too fast, we can't listen.
                            // so we have to pause for a while. 5 was
                            // too little -- 10 works. haven't bothered
                            // to find the exact value

                if (Timer(0)>100)
                {  // it's been a long time
                    gotackflag=1;   //pretend we got an ack
                    needackflag=0;  //and stop caring.
                }
            }

            //ok done spinning now go.
            Rev(OUT_A + OUT_C,OUT_FULL);
        }
    }
}

// this task watches for incoming messages.
task postoffice
{
    ClearMessage(); //start by erasing whatever's in the air
    while(true)
    {
        if (Message()==33)  //bang! we've been hit!
        {
            SendMessage(6); //send ack
            bumpcount +=1;  //increase our damage. ow.
            ClearMessage(); //and of course clear the message now that
                            // we've dealt with it.
        }
        if (Message()==34)  //we've been hit but didn't respond. bad us.
        {
            SendMessage(6);  //ack
            if (bumpcount==0) // but only do anything if we're
            {                 // supposed to be paying attention. if we're
                              // down already, we ignore " signals.
                bumpcount +=1;
            }
            ClearMessage();
        }
        if (Message()==6)  //an ack
        {
            if (needackflag>0)  //we only care if we're listening.
            {
                needackflag=0;  //ok, so we don't care anymore
                gotackflag=1;   //and we have what we're lookin' for
            }
            ClearMessage();
        }
    }
}

task checkline
{
    while(true)
    {
        if (IN_2 < blackvalue)  //if the sensor detects dark
        {
            PlayNote(442,10);
            revturn();  //back up and turn
            Rev(OUT_A + OUT_C,OUT_FULL);  //then go forward again
        }
    }
}

task checkbump
{
    while(true)
    {
        if (IN_1 == 1)  //if the bump sensor is pressed
        {
            SendMessage(33); //yell bang
            PlaySound(0);

            gotackflag=0;    //clear old acks -- they're not relevant anymore

            needackflag=1;   //we need an ack now
            revturn();       //back up and turn
            Rev(OUT_A + OUT_C,OUT_FULL); //the forward again

            if (needackflag==1)  //if we haven't gotten an ack yet...
            {
                needackflag=2;  //then advance to spinning around yelling
            }
        }
    }
}



sub revturn  //back up and turn a random direction
{
    Fwd(OUT_A + OUT_C, OUT_FULL);  //back up
    Sleep(100);                    //for one second
    Off(OUT_A + OUT_C);        // stop motors -- is this needed? probly not.

    randnum=Random(2);   //kludge 'cause Random(x) doesn't work in an "if"
    if (randnum == 1)        // 50/50 chance.
    {
        Rev(OUT_A,OUT_FULL);   //turn uh, left or right. whichever this is.
        Fwd(OUT_C,OUT_FULL);
    }
    else
    {
        Rev(OUT_C,OUT_FULL);   //turn uh, right or left.
        Fwd(OUT_A,OUT_FULL);
    }

    Sleep(50);                   //keep turning for .5+Random(3) seconds
    Sleep(Random(300));
    Off(OUT_A + OUT_C);         //stop motors
}

sub startspinning   // start spinning a random direction.
{                   // if we could nest subs, we would. (same code above)

    Off(OUT_A + OUT_C);

    randnum=Random(2);
    if (randnum == 1)
    {
        Rev(OUT_A,OUT_FULL);
        Fwd(OUT_C,OUT_FULL);
    }
    else
    {
        Rev(OUT_C,OUT_FULL);
        Fwd(OUT_A,OUT_FULL);
    }
}

sub punishment   //bad robot. must sit still for 8 seconds.
{
    stop checkline;   // ignore everything else. we're DEAD. for now at least
    stop checkbump;   //    note that we still process messages.

    Off(OUT_A + OUT_C);

    repeat(4)
    {
        PlaySound(4);  //cry
        Sleep(200);
    }

    Rev(OUT_A + OUT_C,OUT_FULL);       // ok go forward again.

    start checkline;  //and pay attention to stuff
    start checkbump;
}


sub initlight   //reads the value of 'normal', and assumes that the
{               // black-line border is about 7 darker. no real reason to
                // put this in a sub, except for neatness.

        blackvalue=IN_2;
        blackvalue-=7;  //may have to adjust this.
                        //also -- what about white lines?
}


--
Matthew Miller                      --->                  mattdm@mattdm.org
Quotes 'R' Us                       --->             http://quotes-r-us.org/



1 Message in This Thread:

Entire Thread on One Page:
Nested:  All | Brief | Compact | Dots
Linear:  All | Brief | Compact
    

Custom Search

©2005 LUGNET. All rights reserved. - hosted by steinbruch.info GbR