View unanswered posts | View active topics It is currently Fri Oct 24, 2014 7:22 am






Reply to topic  [ 17 posts ]  Go to page 1, 2  Next
different autonomous programs depending on start positition 
Author Message
Rookie

Joined: Sun Sep 28, 2008 6:09 pm
Posts: 4
Post different autonomous programs depending on start positition
During software inspection, the autonomous program is checked to make sure it works. Can more than one autonomous program be used during the competition, depending where your robots starting position is?


Tue Feb 17, 2009 5:40 pm
Profile
Novice

Joined: Thu Oct 09, 2008 7:58 pm
Posts: 79
Post Re: different autonomous programs depending on start positition
I would guess, YES.


Tue Feb 17, 2009 6:19 pm
Profile
Expert
User avatar

Joined: Tue Oct 14, 2008 7:16 pm
Posts: 171
Location: Investigating an unidentified ship sighted in Sector 31428
Post Re: different autonomous programs depending on start positition
Since there is nothing that says you can't (unless someone has read something I haven't), although really what you need is a single branched Autonomus program that tests at the beginning what part to run. What you need to do then is create a series of flags that can be set before your bot goes on the field; we're using three touch sensors, this can ultimately allow for seven different autonomus programs.

This works the binary number system where each increasing place value is doubled rather than times 10 and each place can only be 1 or 0.

Thus,
  • 000 = 0
  • 001 = 1
  • 010 = 2
  • 011 = 3
  • 100 = 4
  • 101 = 5
  • 110 = 6
  • 111 = 7

You can use a function like this to test for which are pressed; my set up for the sensors is a little funky but basically it tests for each possible combination and returns the decimal equivilent of that binary sequence. Please note that touchMXPVal[] is an array I have created in my program to hold the values returned from our Touch Multiplexer; it is constantly updated by a seperate task.
Code:
int testAuto()
{
    if(!touchMXPVal[2] && !touchMXPVal[3] && (SensorValue[auto3] == 0))
    {
        return 0;
    }
    else if(touchMXPVal[2] && !touchMXPVal[3] && (SensorValue[auto3] == 0))
    {
        return 1;
    }
    else if(!touchMXPVal[2] && touchMXPVal[3] && (SensorValue[auto3] == 0))
    {
        return 2;
    }
    else if(touchMXPVal[2] && touchMXPVal[3] && (SensorValue[auto3] == 0))
    {
        return 3;
    }
    else if(!touchMXPVal[2] && !touchMXPVal[3] && (SensorValue[auto3] == 1))
    {
        return 4;
    }
    else if(touchMXPVal[2] && !touchMXPVal[3] && (SensorValue[auto3] == 1))
    {
        return 5;
    }
    else if(!touchMXPVal[2] && touchMXPVal[3] && (SensorValue[auto3] == 1))
    {
        return 6;
    }
    else if(touchMXPVal[2] && touchMXPVal[3] && (SensorValue[auto3] == 1));
    {
        return 7;
    }
}


I call this function from a switch statement and place the desired Autonomus code within each case statement, like so,
Code:
switch(testAuto())
{
case 0:
    nxtDisplayTextLine(2, "Auto 1");
    //Code for auto sequence 1 here...
    break;
case 1:
    nxtDisplayTextLine(2, "Auto 2");
    //Code for auto sequence 2 here...
    break;
case 2:
    nxtDisplayTextLine(2, "Auto 3");
    //Etc....
    break;
case 3:
    nxtDisplayTextLine(2, "Auto 4");
    break;
case 4:
    nxtDisplayTextLine(2, "Auto 5");
    break;
case 5:
    nxtDisplayTextLine(2, "Auto 6");
    break;
case 6:
    nxtDisplayTextLine(2, "Auto 7");
    break;
case 7:
    nxtDisplayTextLine(2, "Auto 8");
    break;
}

You could also, theoretically place all the code for any given sequence inside a seperate function and call the appropriate function from each case statement or even from the previous testAuto() function rather than returning a value, this is an idea I have been toying with but have yet to get a chance to experiment with for various reasons.

Mind you all of this assumes that you have the availble ports and sensors. If you couldn't do this, you could set up several different independent programs that you could pick and choose from but the FMS might not like that, nor the software inspectors.

_________________
Captain, Head programmer, School of the Arts, Silverbots Robtics Team #2890
Code:
using namespace System;
using namespace Genius;
using namespace Personality;
public ref class Nerd : Geek, IAnserable
{
    Geek::Type brainMode = Geek::Type::Programmer;
}


Wed Feb 18, 2009 12:36 am
Profile
Novice

Joined: Mon Oct 13, 2008 6:29 pm
Posts: 75
Location: Florida, USA
Post Re: different autonomous programs depending on start positition
we have 5 programs 1 tele op and 1 for each starting position. No problems after three competitions.

_________________
PHUHS Robotics
Team 516 FTW

Daytona Robofest Winning Alliance Captain
Daytona Robofest Inspire Award


Wed Feb 18, 2009 4:47 pm
Profile
Expert
User avatar

Joined: Tue Oct 14, 2008 7:16 pm
Posts: 171
Location: Investigating an unidentified ship sighted in Sector 31428
Post Re: different autonomous programs depending on start positition
I have to say, I'm really not a fan of the split file structure, I rather like the single package model.

_________________
Captain, Head programmer, School of the Arts, Silverbots Robtics Team #2890
Code:
using namespace System;
using namespace Genius;
using namespace Personality;
public ref class Nerd : Geek, IAnserable
{
    Geek::Type brainMode = Geek::Type::Programmer;
}


Wed Feb 18, 2009 5:24 pm
Profile
Novice

Joined: Fri Oct 24, 2008 8:58 am
Posts: 87
Post Re: different autonomous programs depending on start positition
You only need one autonomous program. If you have more than 1 file in your program, I think keeping multiple versions of a program is too difficult to manage correctly.

I wrote a user interface that allows selecting autonomous parameters from a menu.

Red vs Blue
On field vs Off Field
Target racks, etc

Also we save and load these parameters from a file every time the robot starts up. So you can set them before putting the robot on the field.

Here's the code that makes this happen

param.c
Code:
#if !(defined(CTYPES_H))
  #include "ctypes.h"
#endif


#define USE_ASSERT_ON_READ   0   // Check IO result after every read command
#define USE_ASSERT_ON_WRITE  0   // Check IO result after every write command

typedef enum
{
  kNearWall   = 0,      // Wall closest to the drivers
  kFarWall    = 1,      // Wall opposite to the drivers
  kRampWall   = 2,      // Wall in the direction of the ramp
  kOtherWall  = 3      // Wall closest to the other drivers
} TWallPos;

typedef enum
{
  kAutoTeam  = 0,      // Automatically select start team
  kRedTeam   = 1,
  kBlueTeam  = 2,
  kSameTeam  = 3,      // Same as alliance team color
  kOtherTeam = 4      // Opposite from alliance team color
} TTeamColor;

typedef enum
{
  kStartOffField = 0,   // Start on the Ramp
  kStartOnField  = 1    // Start on the Field
} TStartPosition;

typedef enum
{
  kDumpNone  = 0,       // Don't dump racks
  kDumpEach  = 1,       // Dump the bucket before getting next rack
  kDumpAll   = 2       // Get all racks before dumping
} TDumpMode;

typedef enum
{
  kKeepRack   = 0,      // Empty the rack and keep the pucks
  kDropRack = 1,      // Empty the rack and discard pucks
  kWaitRack    = 2      // Prepare to empty the rack, but wait
} TRackMode;

typedef struct
{
   TWallPos   wall;   // Which wall the target rack is on
   TTeamColor color;   // Which color the target
   TRackMode  mode;   // Which action to take at the target
} TAutoTarget;

typedef struct
{
   int16 rack_down;
   int16 rack_ready;
   int16 dump_ready;
   int16 dump_full;
} TArmTarget;

#define MAX_TARGETS 4
#define MAX_PARAM_SIZE 64

typedef struct
{
   int16 n;         // Numerator
   int16 d;         // Denominator
} TFraction;

#define MultFract(number, factor) number *= factor.n; number /= factor.d
#define DivFract(number,factor) number *= factor.d; number /= factor.n

typedef union
{
  struct
  {
   // Converts encoder ticks to 1/10in
     TFraction encoder_factor;

     // Converts wheel ground speed to wheel rotation speed
     TFraction left_wheel_factor;
      TFraction right_wheel_factor;

    // Convert desired wheel rotation speed to % motor power
      TFraction power_factor;

      // Conversion factor for kinematics equation
      TFraction body_width;

      // Angle offset from robot starting location
      int16 gyro_zero;

      // Calibration factor for full 360 degree rotation
      TFraction gyro_cal;

      TArmTarget      arm_target;

      // Autonomous Mode Parameters

   TTeamColor      team_color;            // Team Color: Red, Blue, Auto
   TStartPosition  start_pos;            // Starting position OnField vs OffField
   TDumpMode       dump_mode;            // How to handle pucks after clear rack
   int16         prog_num;            // Index of program that has been selected
   int16         num_targets;         // Number of targets in the program
   TAutoTarget       target1;            // Rack Target information
   TAutoTarget       target2;
   TAutoTarget       target3;
   TAutoTarget       target4;
  };

  int16 data[MAX_PARAM_SIZE];
} TRobotParam;

#if USE_ASSERT_ON_READ
#define ReadInt16(file, result,variable) ReadShort(file, result, variable); if(result) goto ReadErr
#else
#define ReadInt16(file, result,variable) ReadShort(file, result, variable)
#endif

#define ReadTypecast(file, result, variable, typecast, temp) ReadInt16(file,result,temp); variable = (typecast)temp

#if USE_ASSERT_ON_WRITE
#define WriteInt16(file, result,variable) WriteShort(file, result, variable); if(result) goto WriteErr
#else
#define WriteInt16(file, result,variable) WriteShort(file, result, variable)
#endif

void SetDefaultParam(TRobotParam &param)
{
   int i;

   // First zero everything out
   for (i=0;i<MAX_PARAM_SIZE;i++)
   {
      param.data[i] = 0;
   }

   param.left_wheel_factor.n = 360;      // 360 degrees / rotation
   param.left_wheel_factor.d = 94;       // left wheel diameter in 1/10 in = 3.1416 * 3 * 10

   param.right_wheel_factor.n = 360;     // 360 degrees / rotation
   param.right_wheel_factor.d = 92;      // right wheel diameter in 1/10 in = 3.1416 * 3 * 10

   param.power_factor.n = 100;           // 100% power
   param.power_factor.d = 766;           // 760 deg/sec (~20 in/sec) = 20 * 10 * 360 / 94

   param.body_width.n = 283;      // pi * radius of robot (between wheels) in 1/10 in = 9.0 * 3.1416 * 10.0
   param.body_width.d = 180;      // 180 (degrees to radians)

   param.encoder_factor.n = 360;
   param.encoder_factor.d = 5506;


   param.gyro_zero      = 0;
   param.gyro_cal.n      = 1;
   param.gyro_cal.d      = 1;

   param.arm_target.rack_down  = 20;   // Clear Rack Down Position
   param.arm_target.rack_ready = 45;   // Clear Rack Ready Position
   param.arm_target.dump_ready = 85;   // Dump Bucket Ready Position
   param.arm_target.dump_full  = 145;  // Dump Bucket Full Position

   param.start_pos       = kStartOnField;
   param.team_color      = kAutoTeam;
   param.dump_mode       = kDumpAll;

   param.num_targets     = 1;
   param.prog_num        = 1;
   param.target1.wall  = kNearWall;
   param.target1.color = kSameTeam;
   param.target1.mode  = kKeepRack;
}

bool WriteParamFile(TRobotParam &param, const string &sFileName )
{
   int i;
   int chksum = 0;
    int nParamFileSize = (MAX_PARAM_SIZE + 1) * 2;

   TFileHandle hFile;
   TFileIOResult nResult;

   Delete(sFileName, nResult);
   OpenWrite(hFile, nResult, sFileName, nParamFileSize);

   if (nResult == ioRsltSuccess)
   {
      for (i=0;i<MAX_PARAM_SIZE;i++)
      {
         WriteInt16(hFile, nResult, param.data[i]);
         chksum += param.data[i];
      }
   }

   // Write the checksum at the end of the file
   WriteShort(hFile, nResult, chksum);

   Close(hFile, nResult);
   return true;

WriteErr:
   Close(hFile, nResult);
   return false;
}

bool ReadParamFile(TRobotParam &param, const string &sFileName)
{
   int i,j;
   int chksum = 0;

   TFileHandle hFile;
   TFileIOResult nResult;
  int nParamFileSize = (MAX_PARAM_SIZE + 1) * 2;

   OpenRead(hFile, nResult, sFileName, nParamFileSize);

   if (nResult == ioRsltSuccess)
   {
      for (i=0;i<MAX_PARAM_SIZE;i++)
      {
         ReadInt16(hFile, nResult, param.data[i]);
         chksum += param.data[i];
      }
   }

   // Verify checksum correct
   ReadShort(hFile, nResult, j);
   if (j != chksum)
      goto ReadErr;

   Close(hFile, nResult);
   return true;

ReadErr:
   Close(hFile, nResult);
   return false;
}


This saves and loads a set of parameters to the NXT as a file. The code only uses a checksum so version control isn't perfect.
It'll usually detect a major change to the structure of the parameter file (ie you add a new parameter or delete one). It won't load a bad parameter set (instead you should load the default values in your code. If in doubt just delete the old parameter file and try again.

here's a snippet of my code that uses the above routines.
Code:

void saveParam()
{
   if(WriteParamFile(robot.param, "param_2803.txt"))
   {
      PlaySound(soundBeepBeep);
   }
   else
   {
      PlaySound(soundException);
   }
}

void initParam(bool bLoadFile)
{
  if (bLoadFile)
  {
     if(ReadParamFile(robot.param, "param_2803.txt"))
     {
        PlaySound(soundBeepBeep);
        return;
     }
     else
     {
        PlaySound(soundException);
     }
  }

  SetDefaultParam(robot.param);

  if (bLoadFile)
  {
    saveParam();
  }
}



Code:
#pragma autoStartTasks    // Automatically start this task when the main user program starts.

#if !defined(GLOBALS_H)
  #include "globals.h"
#endif

typedef enum
{
  screenNone         = 0,
  screenDiagnostics  = 1,
  screenAutoSettings = 2
} TMenuScreen;

#define PlayAcceptSound() if (bSoundEnabled) PlaySound(soundBlip)
#define PlayRejectSound() if (bSoundEnabled) PlaySound(soundShortBlip)

// Function Prototypes
void displayPageHandler(int minPageNo, int maxPageNo, bool bWrapPages, TMenuScreen exitScreen);
void showDiagnostics();
void showAutoSettings();

// Global variables used by this task

string sTelopFileName;        // stores the name of the currently assign telop program
TMenuScreen currScreen;       // the name of the active screen
TMenuScreen nextScreen;       // the name of the next screen that should become active
TButtons lastNxtButton;       // a temporary variable to detect button transitions
TButtons nxtBtnClick;         // a variable assigned whenever a button is pressed
int nDisplayLoopCounter;      // counts the number of 100msec intervals between screen updates
int nDisplayRefreshRate;      // sets the rate at which the screen is updated
int nScreenPage;              // tracks the currently active page (for multi-page screens)
int nCursorPos;               // tracks the edit cursor position (for menus and edit boxes)

bool bDisplayEnabled = true;  // Set to false in user program to disable diagnostic display
bool bSoundEnabled = true;    // Set to false to display user interface reposnse sounds.

/***********************************************
 * Display Task  - Event Handlers
 *    - displayOnChange()
 *    - displayOnKey()
 *    - displayOnUpdate()
 */

// Called when a screen change occurs
void displayOnChange()
{
   eraseDisplay();

   switch(nextScreen)
   {
      case screenDiagnostics:
      getUserControlProgram(sTelopFileName);
        break;
    case screenAutoSettings:
      nScreenPage = 0;
      nCursorPos  = 0;
      break;
   }
}

// Periodically called to update the current screen's contents
void displayOnUpdate()
{
   switch(currScreen)
   {
      case screenDiagnostics:
        showDiagnostics();
        break;
      case screenAutoSettings:
      showAutoSettings();
        break;
   }
}

void displayTargetInfo(TAutoTarget &target, int index)
{
    int j = 45-(index*9);

       nxtDisplayStringAt(0, j, "%d",  index + 1);

       nxtDisplayStringAt(8, j, (target.wall == kNearWall ? "Near" :
                        target.wall == kFarWall ? "Far" :
                         target.wall == kRampWall ? "Ramp" :
                          target.wall == kOtherWall ? "Other" : "ERR"));

       nxtDisplayStringAt(39, j, (target.color == kRedTeam? "Red" :
                         target.color == kBlueTeam ? "Blue" :
                         target.color == kSameTeam ? "Same" :
                         target.color == kOtherTeam ? "Other" : "ERR"));

       nxtDisplayStringAt(71, j, (target.mode == kKeepRack? "Keep" :
                         target.mode == kDropRack ? "Drop" :
                         target.mode == kWaitRack ? "Wait" : "ERR"));

}


// Called whenever an NXT button has been pressed
void displayOnKeyDown()
{
  switch(currScreen)
   {
      case screenDiagnostics:
        if (nxtBtnClick == kEnterButton)
          nextScreen = screenAutoSettings;
        break;

      case screenAutoSettings:
        if (nxtBtnClick == kEnterButton)
        {
          switch(nScreenPage)
          {
            // Change Team Color
            case 0:
               robot.param.team_color = (TTeamColor) ( ((int)robot.param.team_color + 1) % 3 );
               PlayAcceptSound();
               break;

            // Change Start Position
            case 1:
               robot.param.start_pos = (TStartPosition) ( ((int)robot.param.start_pos+ 1) % 2 );
               PlayAcceptSound();
               break;

            // Change Program Number
            case 2:
               robot.param.prog_num = (robot.param.prog_num + 1) % 3;
               switch(robot.param.prog_num)
               {
                   case 0:
                      robot.param.num_targets = 0;
                      break;
                   case 1:
                      robot.param.num_targets = 1;
                      robot.param.target1.wall  = kNearWall;
                      robot.param.target1.color = kSameTeam;
                      robot.param.target1.mode  = kKeepRack;
                      break;

                   case 2:
                      robot.param.num_targets = 2;
                      robot.param.target1.wall  = kNearWall;
                      robot.param.target1.color = kSameTeam;
                      robot.param.target1.mode  = kKeepRack;

                      robot.param.target2.wall  = kRampWall;
                      robot.param.target2.color = kSameTeam;
                      robot.param.target2.mode  = kKeepRack;
                      break;

               }
               PlayAcceptSound();
               break;

            // Change Dump Mode
            case 3:
               robot.param.dump_mode = (TDumpMode) (((int)robot.param.dump_mode+1) % 3);
               PlayAcceptSound();
               break;

            // Program Summary and Save
            case 4:
               saveParam();

               break;
          }
        }
        else
        {
           displayPageHandler(0,4,false,screenDiagnostics);
           eraseDisplay();
        }
        break;
  }
}

/***********************************************
 * User Routines to draw screens
 *
 */

 void showAutoSettings()
{
  string stemp;
  int i,j;

  switch (nScreenPage)
  {
    case 0:
      nxtDisplayCenteredTextLine(1, "Select Team");

      nxtDisplayCenteredBigTextLine(4, (robot.param.team_color == kRedTeam  ? "Red" :
                                        robot.param.team_color == kBlueTeam ? "Blue" :
                                        robot.param.team_color == kAutoTeam ? "Auto" :
                                        "ERR"));
      break;

    case 1:
      nxtDisplayCenteredTextLine(1, "Select Position");

      nxtDisplayCenteredBigTextLine(3, (robot.param.start_pos == kStartOnField  ? "On" :
                                        robot.param.start_pos == kStartOffField  ? "Off" :
                                               "ERR"));

      nxtDisplayCenteredBigTextLine(5, "Field");

      break;

    case 2:
      nxtDisplayCenteredTextLine(1, "Select Program");
      nxtDisplayCenteredBigTextLine(4, "%d", robot.param.prog_num);

      nxtDisplayCenteredTextLine(6,     (
                            robot.param.prog_num  == 0 ? "Do Nothing" :
                                   robot.param.prog_num  == 1 ? "Near & Dump" :
                                    robot.param.prog_num  == 2 ? "Near + Ramp" :


                            "Unknown Program"));
      nxtDisplayCenteredTextLine(7,     (
                                  robot.param.prog_num  == 2 ? "& Dump" :
                                  ""));
      break;

    case 3:
      nxtDisplayCenteredTextLine(1, "Select Dump Mode");
      nxtDisplayCenteredBigTextLine(4, (robot.param.dump_mode == kDumpNone  ? "None" :
                                        robot.param.dump_mode == kDumpEach  ? "Each" :
                              robot.param.dump_mode == kDumpAll  ? "All":
                                               "ERR"));

      nxtDisplayCenteredTextLine(6,        (robot.param.dump_mode == kDumpNone  ? "Don't dump racks" :
                                        robot.param.dump_mode == kDumpEach  ? "Dump after each" :
                              robot.param.dump_mode == kDumpAll  ? "Dump after all":
                                               ""));
      nxtDisplayCenteredTextLine(7,        (robot.param.dump_mode == kDumpNone  ? "" :
                                        robot.param.dump_mode == kDumpEach  ? "rack cleared" :
                              robot.param.dump_mode == kDumpAll  ? "racks cleared":
                                               ""));
      break;
    case 4:

      nxtDisplayStringAt(8, 56, "Rack");
      nxtDisplayStringAt(38, 56, "Color");
      nxtDisplayStringAt(71, 56, "Mode");
      nxtDrawLine(0,47,100,47);


      if(robot.param.num_targets > 0)
         displayTargetInfo(robot.param.target1, 0);
      if(robot.param.num_targets > 1)
          displayTargetInfo(robot.param.target2, 1);
      if(robot.param.num_targets > 2)
          displayTargetInfo(robot.param.target1, 2);
      if(robot.param.num_targets > 3)
          displayTargetInfo(robot.param.target1, 3);

      nxtDisplayCenteredTextLine(7, "Enter to Save");
      break;
  }
}

void showDiagnostics()
{
   getJoystickSettings(joystick);                   //Update variables with current joystick values

   if (joystick.StopPgm)
     nxtDisplayCenteredTextLine(1, "Wait for Start");
   else if (joystick.UserMode)
      nxtDisplayCenteredTextLine(1, "TeleOp Running");
   else
      nxtDisplayCenteredTextLine(1, "Auton Running");

   if ( externalBatteryAvg < 0)
      nxtDisplayTextLine(3, "Ext Batt: OFF");       //External battery is off or not connected
   else
      nxtDisplayTextLine(3, "Ext Batt:%4.1f V", externalBatteryAvg / (float) 1000);

   nxtDisplayTextLine(4, "NXT Batt:%4.1f V", nAvgBatteryLevel / (float) 1000);   // Display NXT Battery Voltage

   nxtDisplayTextLine(5, "FMS Msgs: %d", nMessageCount);   // Display Count of FMS messages

  nxtDisplayTextLine(6, "Teleop FileName:");
   nxtDisplayTextLine(7, sTelopFileName);
}


/***********************************************
 * Display Task  - Common User Interface Routines
 *    - displayPageHandler()
 */

// A generic handler for sets of pages:
//    Left  - Move to previous page
//    Right - Move to the next page
//    Exit  - Return to previous menu/screen

void displayPageHandler(int minPageNo, int maxPageNo, bool bWrapPages, TMenuScreen exitScreen)
{
  switch(nxtBtnClick)
  {
     case kExitButton:
       if (exitScreen != screenNone)
         nextScreen = screenDiagnostics;
      break;

    case kLeftButton:
       nScreenPage -= 1;
       if (nScreenPage < minPageNo)
       {
         if (bWrapPages)
         {
           PlayAcceptSound();
           nScreenPage = maxPageNo;
         }
         else
         {
           PlayRejectSound();
            nScreenPage = minPageNo;
          }
      }
      else
      {
        PlayAcceptSound();
      }
      break;

    case kRightButton:
       nScreenPage += 1;
       if (nScreenPage > maxPageNo)
       {
         if (bWrapPages)
         {
          PlayAcceptSound();
           nScreenPage = minPageNo;
         }
         else
         {
           PlayRejectSound();
            nScreenPage = maxPageNo;
          }
      }
      else
      {
        PlayAcceptSound();
      }
      break;
  }
}


/***********************************************
 * Display Task  - Application Interface Functions
 *    - displayRefreshScreen()
 *    - displayChangeScreen()
 *    - displayDisable()
 *    - displayEnable()
 */

void displaySetRefreshRate(int refreshRate)
{

}

void displayDisable()
{
  bDisplayEnabled = false;   // Disable any drawing to the screen
}

void displayEnable()
{
  bDisplayEnabled = true;
}

// forces the current screen to be reloaded
void displayRefreshScreen()
{
  bDisplayEnabled = false;

  nextScreen = currScreen;
  currScreen = screenNone;
  nDisplayLoopCounter = 0;

  bDisplayEnabled = true;
}

// call to change the currently active screen
void displayChangeScreen(TMenuScreen screen)
{
  bDisplayEnabled = false;

  nextScreen = screen;
  nDisplayLoopCounter = 0;

  bDisplayEnabled = true;
}

/***********************************************
 * Display Task  - Driver
 *
 * The display task allows simple implementation of
 * custom user interfaces and diagnostic screens on the NXT.
 *
 * By implementing a few event handlers a user interface can be
 * created that runs independent of the main application.
 */

task displayTask()
{

  bNxtLCDStatusDisplay = true;      // Show the normal top status line
  nNxtExitClicks = 2;               // Require 2 clicks to exit a program

  nextScreen = screenDiagnostics;   // Initial screen
  currScreen = screenNone;

  nDisplayLoopCounter = 0;
  nDisplayRefreshRate = 4;     // Number of 100 msec intervals between refreshes
  nScreenPage = 0;
  nCursorPos = 0;

  while (true)
   {
     // Update the display for the currently active screen
      if (bDisplayEnabled && nDisplayLoopCounter <= 0)
      {
         nDisplayLoopCounter = nDisplayRefreshRate;

        if (nextScreen != currScreen)
        {
          displayOnChange();
          currScreen = nextScreen;
        }

        displayOnUpdate();
    }

     if ((lastNxtButton != nNxtButtonPressed) && (nNxtButtonPressed != kNoButton))
       nxtBtnClick = nNxtButtonPressed;
     lastNxtButton = nNxtButtonPressed;

     if (nxtBtnClick != kNoButton)
     {
      // Process the key press
       displayOnKeyDown();

       // Wait for the button to be released.
      while(nNxtButtonPressed != kNoButton);
      nxtBtnClick = (TButtons)kNoButton;

      // Immediately update the screen
      nDisplayLoopCounter = 0;
    }
    else
    {
      wait1Msec(100);               // allow the button handling code to run faster
      nDisplayLoopCounter -= 1;     // than the display code to provide better user response
    }
   }
}


This starts a task to run the user interface code. It overwrites (and replicates) some of what they are doing in JoystickDriver.c (which was a stupid place to put user interface code in my opinion)

This menu/display code probably won't run "out-of-the-box" since I ripped it out of my project, but it'll get you going in the right direction if you make changes to the appropriate places.


Wed Feb 18, 2009 5:39 pm
Profile
Rookie

Joined: Sat Oct 25, 2008 3:04 pm
Posts: 5
Post Re: different autonomous programs depending on start positition
We had almost the same setup as 10nisman94: 4 different autonomous programs, each with the Teleop part in the same file (when teams were using Exploding Bacon's template file).


Thu Feb 19, 2009 3:40 am
Profile
Novice

Joined: Mon Oct 13, 2008 6:29 pm
Posts: 75
Location: Florida, USA
Post Re: different autonomous programs depending on start positition
unfortuately, this is no longer "allowed" the new joystick driver doesnt even check auto v tele just enable v disable, this is why the auto and tele templates are manditory

_________________
PHUHS Robotics
Team 516 FTW

Daytona Robofest Winning Alliance Captain
Daytona Robofest Inspire Award


Thu Feb 19, 2009 5:41 pm
Profile
Novice

Joined: Fri Oct 24, 2008 8:58 am
Posts: 87
Post Re: different autonomous programs depending on start positition
I disagree. There is nothing that prevents using the same program for autonomous and tele-op.
Just check for auto vs manual yourself after the template's wait-for-enable code. Its definitely still in the joystick data packet.

Disclaimer: this is just my interpretation of the rules...your mileage may vary

Look at the software inspection checklist. Its 100% functional - 0% implementation specific. I see no checks on how the code is written, just what it is supposed to do. How you get there isn't critical. The templates just get you there one way. No where on the checklist does it tell a judge to even look at or ask about your code.

Now I had someone at FIRST call me to remind me to use two files. When I asked why they told me people thought the FMS was screwing up launching the same filename for auto and manual. Which would be a legit reason not to do this, but I didn't have any problems at my last event. I think those making that complaint screwed something up (probably by having different programs and not using the program chooser correctly).


Thu Feb 19, 2009 6:39 pm
Profile
Novice

Joined: Mon Oct 13, 2008 6:29 pm
Posts: 75
Location: Florida, USA
Post Re: different autonomous programs depending on start positition
good point

_________________
PHUHS Robotics
Team 516 FTW

Daytona Robofest Winning Alliance Captain
Daytona Robofest Inspire Award


Thu Feb 19, 2009 9:57 pm
Profile
Professor

Joined: Fri Sep 19, 2008 1:22 am
Posts: 200
Post Re: different autonomous programs depending on start positition
Our team uses a single program that handles both teleop and autonomous modes and automatically detects the starting position and does the correct thing. We are using a HiTechnic Color sensor to detect the red or blue of the two upper platforms. That tells us if we are off-floor and which color we are. If we see grey we know we are on the floor but not what alliance we are. At the start of autonomous mode we move forward until we see non-grey. At that point we know which alliance we are on. At that point, regardless of our starting position, we know how far we have to move and which directions we need to turn for each step of the autonomous task.

_________________
Jeff McBride
Benson Robotics Club


Fri Feb 20, 2009 4:03 am
Profile
Novice

Joined: Mon Oct 13, 2008 6:29 pm
Posts: 75
Location: Florida, USA
Post Re: different autonomous programs depending on start positition
very cool, could that be done with a regular light sensor?

_________________
PHUHS Robotics
Team 516 FTW

Daytona Robofest Winning Alliance Captain
Daytona Robofest Inspire Award


Fri Feb 20, 2009 8:08 am
Profile
Novice

Joined: Fri Oct 24, 2008 8:58 am
Posts: 87
Post Re: different autonomous programs depending on start positition
yes. cool idea. Another option (depending on starting orientation) is to detect which side of the robot is next to the wall.

Thats how we do it. If the wall is to the right we're on the red alliance. If the wall is to the left we're on the blue alliance.
I think I'll adopt the color sensor idea too for on field vs off field.

I've been wanting to find some way of using that sensor :)


Fri Feb 20, 2009 9:52 am
Profile
Professor

Joined: Fri Sep 19, 2008 1:22 am
Posts: 200
Post Re: different autonomous programs depending on start positition
10nisman94 wrote:
very cool, could that be done with a regular light sensor?


We haven't tried it. I suggest testing it to see if you can differentiate between the specific blue, grey and red colors used on the field as different grey-scale values from the light sensor.

If you can detect grey or not grey (red is the same as blue) then you could use it to determine on-field v/s off-field start and use chadgeorge's idea of wall detection to determine the alliance color. If you are starting off-field you would go forward until you saw the wall and then would know.

If red is the same value as grey and blue is different or blue is the same as grey and red is different then you could tell where you are by using the black ramp (it looks grey but I went forward and saw black so I must have been on the RED platform, and so on.

Use your imagination. There are a lot of ways to skin this cat.

We are also using the color sensor to detect the white lines in autonomous mode for navigation. We could have just as easily used a light sensor for that part of the task.

_________________
Jeff McBride
Benson Robotics Club


Mon Feb 23, 2009 5:19 pm
Profile
Rookie

Joined: Sun Sep 28, 2008 6:09 pm
Posts: 4
Post Re: different autonomous programs depending on start positition
I posted the original question regarding the start position and thanks for all the help. I haven't entered a competition as of yet, but will be entering two the next two weeks. Could anyone tell me who actually puts the robot in the starting positions. Is it a team member or is it a referee? Would it be possible to have two touch sensors with hinged plates over them that could be easliy closed and stay that way? One touch sensor could represent the top and the other the color. If the start position is top - red, the cover on the "top" sensor could be closed to represent - True and the same for the color sensor. This way the autonomous program could jump to the correct point of the program depending on the switch positions.

By the way, today, I did check the different colors with the light sensor and there was enough of a difference (10) so it could be used to determine the start color position.

Thanks,

---Bill Jackson


Mon Feb 23, 2009 9:26 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 17 posts ]  Go to page 1, 2  Next

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  



Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.