|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
|
|
Thread Tools | Rate Thread | Display Modes |
|
|
|
#1
|
||||
|
||||
|
Setting Autonomous Settings from OI
Does anyone understand the details of how values from the OI are sent to the RC prior to and during autonomous?
Last year, we had our autonomous settings on the robot, and that was a big pain. At the end of the regional, we realized that were getting readings from the OI before and during autonomous, so we could move those switches and controls to the OI and just make sure they are set correctly before the match starts. (Obviously, we can't touch them during autonomous.) This year, we have a custom control box on the OI with various LEDs, switches and one potentiometer, all running through the various ports and carefully laid out so as not to conflict with the pins that are duplicated on multiple ports. Everything works great during tele-operation, and even when we're disabled via the competition port. However, during autonomous, some switches don't work. We have one switch (hooked into p1_sw_trig) that controls whether or not our blinking light decorations are enabled; it works great at all times except during autonomous. Some other switches seemed to be having similar problems, so we changed our code to capture the switch values while disabled, then stop updating the values once autonomous starts. Our main autonomous mode is determined by the value of a potentiometer hooked up to p1_x. Most of the time, this one works great, but sometimes it doesn't. Instead it will get "stuck" on an old value. The pot has detents, so there's no problem with finding the right position, and there's plenty of difference between positions. Also, it's not like the values drifted and we get a value near the setting we expect, instead we get a fixed value that doesn't change no matter where we turn the knob. When this has happened, the only reliable way to cure it is to reset both the OI and RC using the buttons on the OI. Our procedure is to put the robot in manual and disabled, then switch to autonomous, then enable. We know that we don't get into the autonomous branch of the code until we are in both autonomous and enabled. Even if we capture the values before the "autonomous_mode" becomes true, we still get values that are always wrong on some switches and sometimes wrong on the pot. Has anyone else seen this issue? Obviously, it's pretty embarrassing when your robot runs the wrong autonomous mode in front of five other teams and a large perceptive audience! |
|
#2
|
||||
|
||||
|
Re: Setting Autonomous Settings from OI
Tom,
This year is the first time we've done autonomous mode selection from the OI. I used code supplied by Travis Hoffman from Team 48 - Delphi Elite in the following post: http://www.chiefdelphi.com/forums/sh...ad.php?t=34702 It is the third post down. In a nutshell: 1) In autonomous mode, all the OI variables (p1_x, p1_sw_trig, etc) are reset to default values - 0 for switches, 127 for analog 2) In your tele-operated code (Default_Routines) add code to copy the OI variables you need into a set of static variables when you are NOT in autonomous mode 3) In your autonomous code, use the static variables you copied everything over to in step 2, to select your autonomous mode The code in the link above from Travis should be enough to get you through. If you wish, you can contact "Embok" here on Chief Delphi. He was our programmer responsible for the OI autonomous selection code. He will be able to post our code and provide any help you may need. -SlimBoJones... |
|
#3
|
||||
|
||||
|
Re: Setting Autonomous Settings from OI
Quote:
|
|
#4
|
||||
|
||||
|
Re: Setting Autonomous Settings from OI
Tom, post your code for when you are copying the OI variables to your static variables, and the code you are using to select your autonomous code from your static variables.
It might offer some more insight as to why you're seeing this behaviour. -SlimBoJones... |
|
#5
|
||||
|
||||
|
Re: Setting Autonomous Settings from OI
Quote:
The variables with a g_ are public globals, available to the autonomous mode code in a different file. The s_ variables are statics available only to user_routines.c code, which is the tele-operation code and some utilities used in both modes. After an optional prefix, each variable name starts with a tag which describes the type of information stored in the variable. "ana" is an analog value from the RC (which needs to go through Get_Analog_Value to get a 10-bit analog value), "oana" is a direct 8-bit analog value from the OI. "digi" is a digital-in value, "digo" is digital-out. "f" is a boolean flag. "dist" is an accumulated optical encoder value. We'll get all of our code posted on our web site after cleaning up a bit of the patches and hacks thrown in while debugging and experimenting in the pit between matches. My favorite time at the PNW regional was when we were replacing a key on an arm axle that got sheered and also adding a limit switch to keep that from happening again. The mechanical stuff got finsihed amazingly quickly, but they were calling us to queue up by the time I was able to download and try the fresh new code, which of course was backwards the first time allowing us to drive against the stop, but not away from it! Code:
///////////////////////////////////
// excerpt from user_routines.h
///////////////////////////////////
enum {
stratLoaderLeft,
stratLoaderRight,
stratStartingTetra,
stratHangingTetra,
stratInterference,
stratVisionTetra,
stratMax
};
// strategy pot values
#define oanaManualLoader 1
#define oanaAutoLoader 26
#define oanaStartingTetra 55
#define oanaHangingTetra 88
#define oanaInterference 128
#define oanaVisionTetra 184
// slow loop count, our crappy timer
extern int g_cLoop;
extern uchar g_fPrint;
// measured arm positions
extern long g_mdegShoulderCur;
extern long g_mdegElbowCur;
extern long g_mdegWristCur;
// override flags
extern uchar s_fOverrideEncoders;
extern uchar s_fOverrideArmSensors;
enum {
tposLeft = -1,
tposCenter = 0,
tposRight = 1
};
extern char g_tposStartingPos;
extern uchar g_stratAutonomous;
extern uchar g_fFarLoading;
///////////////////////////////////////////
// our sensor code from user_routines.c
///////////////////////////////////////////
// call this routine every time we get new OI data during autonomous
// or tele-operation modes
//
// the function reads new values from the OI and RC and computes averages
// from values accumulated from calls to Process_Data_From_Local_IO
void UpdateSensors()
{
static ulong s_distLeftPrev = 0;
static ulong s_distRightPrev = 0;
int anaCurrentSensorAverageR;
int anaCurrentSensorAverageL;
int fOverride;
ulong distT;
long speedLeft, speedRight;
// Our dopey timer.
++g_cLoop;
g_fPrint = (g_cLoop % 10) == 0;
speedLeft = SpeedFromSample(Get_Left_Encoder_Count(), s_adistSampleLeft);
speedRight = SpeedFromSample(Get_Right_Encoder_Count(), s_adistSampleRight);
// Arm Code
s_fElbowLowLimit = digiElbowClosed == 0;
g_mdegShoulderCur = MdegFromEncoder((s_anaPotShoulderTotal / s_cSampleFast) - encoderBiasShoulder);
g_mdegElbowCur = MdegFromEncoder(encoderBiasElbow - (s_anaPotElbowTotal / s_cSampleFast));
g_mdegWristCur = MdegFromEncoder(encoderBiasWrist - (s_anaPotWristTotal / s_cSampleFast));
s_anaPotShoulderTotal = s_anaPotElbowTotal = s_anaPotWristTotal = 0;
// monitor the left encoder
distT = Get_Left_Encoder_Count();
if (s_distLeftPrev != distT || pwmDriveL1 == 127)
{
s_distLeftPrev = distT;
s_cLoopNoLeftEncoder = 0;
}
else if (s_cLoopNoLeftEncoder < 255)
{
++s_cLoopNoLeftEncoder;
}
// monitor the right encoder
distT = Get_Right_Encoder_Count();
if (s_distRightPrev != distT || pwmDriveR1 == 127)
{
s_distRightPrev = distT;
s_cLoopNoRightEncoder = 0;
}
else if (s_cLoopNoRightEncoder < 255)
{
++s_cLoopNoRightEncoder;
}
// turn on the warning LED if either encoder has stopped responding
digoEncoderLED = s_cLoopNoLeftEncoder >= 20 || s_cLoopNoRightEncoder >= 20;
// Override Switch & LED Code
//
// WARNING: the OI bits get blasted when we're in autonomous mode
//
if (!autonomous_mode)
{
s_fTurboDrive = digiTurboDrive;
fOverride = digiEncoderOverride == 0;
if(fOverride != s_fOverrideEncoders)
{
s_fOverrideEncoders = fOverride;
printf("Encoders %s\n", s_apszOverride[s_fOverrideEncoders]);
}
fOverride = digiArmSensorOverride != 0;
if(fOverride != s_fOverrideArmSensors)
{
s_fOverrideArmSensors = fOverride;
printf("digiArmSensorOverride. %d\n", (int)digiArmSensorOverride);
printf("Arm Sens. %s\n", s_apszOverride[s_fOverrideArmSensors]);
}
digoArmLimitLED = s_fOverrideArmSensors;
fOverride = digiCurrentOverride == 0;
if(fOverride != s_fDontAutoAdjustElbow)
{
s_fDontAutoAdjustElbow = fOverride;
printf("Elbow Auto Adj. %s\n", s_apszOverride[1-s_fDontAutoAdjustElbow]);
}
digoCurrentLED = s_fDontAutoAdjustElbow;
fOverride = digiFarLoading != 0;
if(fOverride != g_fFarLoading)
{
g_fFarLoading = fOverride;
printf("far loading %s\n", s_apszOverride[g_fFarLoading]);
}
digoCamLED = g_fFarLoading;
fOverride = digiCompressEnable == 0;
if(fOverride != s_fDisableCompressor)
{
s_fDisableCompressor = fOverride;
printf("Comp. %s\n", s_apszOverride[s_fDisableCompressor]);
}
// autonomous mode switches
g_tposStartingPos = 0;
if (digiStartPosLeft)
g_tposStartingPos = -1;
if (digiStartPosRight)
g_tposStartingPos = 1;
// get the strategy mode from the potentiometer on the OI
g_stratAutonomous = StratFromOana(oanaStrategy);
// check for kyle mode
s_fKyleDriveMode = g_tposStartingPos == tposLeft;
}
else
{
s_fDisableCompressor = fFalse;
s_fDontAutoAdjustElbow = fFalse;
s_fOverrideEncoders = fFalse;
s_fOverrideArmSensors = fFalse;
}
// turn on the light if the pressure has dropped low enough to want the compressor
digoCompressLED = !digiCompPressureHigh;
if (g_fRobotDisabled)
{
s_mdegShoulderPrev = g_mdegShoulderCur;
s_mdegElbowPrev = g_mdegElbowCur;
set_pid_stop(pidDriveL);
}
s_cSampleFast = 0;
}
// given the value from the autonomous strategy potentiometer,
// return the corresponding "strat" value
int StratFromOana(uchar oana)
{
return ValFromTable(oana, s_mp_strat_oana, stratMax);
}
// this array is used to determine the setting of
// the autonomous mode potentiometer
static const uchar s_mp_strat_oana[stratMax] =
{
oanaManualLoader,
oanaAutoLoader,
oanaStartingTetra,
oanaHangingTetra,
oanaInterference,
oanaVisionTetra
};
// given a reading from a detent potentiometer and a table
// of setting values, find the closest preset to the given
// value
int ValFromTable(int oana, const uchar pmp_val_oana[], int valMax)
{
int doanaBest = 255;
int valBest = 0;
int val;
for (val = 0; val < valMax; ++val)
{
int doana = oana - pmp_val_oana[val];
if (doana < 0)
doana = -doana;
if (doana < doanaBest)
{
valBest = val;
doanaBest = doana;
}
}
return valBest;
}
// call this every time through the main or autonomous loops
// to collect data from sensors attached to the RC
void Process_Data_From_Local_IO(void)
{
static uchar s_fShoulderButtonUp = fTrue;
/* Add code here that you want to be executed every program loop. */
s_anaPotShoulderTotal += Get_Analog_Value(anaPotShoulder);
s_anaPotElbowTotal += Get_Analog_Value(anaPotElbow);
s_anaPotWristTotal += Get_Analog_Value(anaPotWrist);
if (digiShoulderFwd && digiShoulderBack)
{
if (s_fShoulderButtonUp)
{
s_fToggleShoulderPos = fTrue;
s_fShoulderButtonUp = fFalse;
}
}
else
{
s_fShoulderButtonUp = fTrue;
}
++s_cSampleFast;
}
|
|
#6
|
|||||
|
|||||
|
Re: Setting Autonomous Settings from OI
WOW
This is the most complex auto selecting routine I have ever seen.Code:
extern char g_tposStartingPos; extern uchar g_stratAutonomous; extern uchar g_fFarLoading; |
|
#7
|
||||
|
||||
|
Re: Setting Autonomous Settings from OI
Quote:
Like most teams, we didn't get the vision stuff working, but we still wanted to be as flexible as possible so we could mesh well with alliance partners' autonomous modes. A lot of robots could only use the auto or human loaders, etc. We have enough flexibility that we can let our partners pick what they want to do and we can still do something useful. We didn't get everything reliably working, but we did have three functional modes available by Saturday at the PNW regional. One thing that slowed us down getting the third mode working was the problem with the wrong mode value coming through, hence this thread. Quote:
|
|
#8
|
|||||
|
|||||
|
Re: Setting Autonomous Settings from OI
Quote:
If the OI switch and joystick inputs are read as neutral whenever the auto input is activated, then there can be a time when the autonomous_mode isn't set but the OI inputs are not active. That's not something I checked when I was looking at how autonomous_mode responded to various combinations of competition port settings, but I think it's worth looking into now. |
|
#9
|
||||
|
||||
|
Re: Setting Autonomous Settings from OI
We set it from the OI as well. What I did was put a line of code in the Process_Data_From_Master routine (I probably spelled tha wrong, I haven't actually looked at the code in a while) that reads a switch on the OI (we plugged a switch on joystick 3 and made the switch use the two auxilary digital inputs) Depending on the value the switch gave, we could have 3 different autonomous modes. Basically, when the robot was disabled it was constantly checking the status of the switch and updating the value of the auto_mode variable. As soon as autonomous mode hit there were 3 if statements, basically
if(auto_mode==0) { //automode1 } else if(auto_mode==1) { //automode2 } else if(auto_mode==2) { //automode2 } It probably wasn't the most efficient code, but it worked flawlessly so I was happy. If anyone wants to see the actual code just tell me, I just don't feel like going and grabbing my laptop right now. |
|
#10
|
|||||
|
|||||
|
Re: Setting Autonomous Settings from OI
It seems like I saw a post about this earlier... You need to make sure that some setting on your OI is set correctly. Like you need to have it in user mode or something. Then just have it read all the variables the first time it runs the section where it processes data from the OI. That should work... But if it isnt then I dont know what to tell you..
|
|
#11
|
||||
|
||||
|
Re: Setting Autonomous Settings from OI
Our team has had switches for autonomous on our operator interface for years. The way this is done is you take the imput from your switch (multi-position, what-haveyou) and store it in a variable so it is not reset when you go into autonomous mode. This is the code we use this year to do that. We have 4 swithes on our OI, two 5 position for delay and variation choices. And a 6 position for position choice and another for program choice.
/*****************read program switches.c*********************/ #include "ifi_aliases.h" #include "ifi_default.h" #include "ifi_utilities.h" #include "user_routines.h" #include "printf_lib.h" void check_program (void) { //extern unsigned char variation; unsigned char delay_val; unsigned char var_val; unsigned char prog_val; unsigned char posit_val; extern unsigned char position_choice; extern unsigned char auto_choice; extern unsigned char variation_choice; extern unsigned char delay; prog_val=rxdata.oi_analog08; var_val=rxdata.oi_analog12; delay_val=rxdata.oi_analog16; posit_val = rxdata.oi_analog04; if (prog_val<10) { auto_choice = 2; } else if( prog_val >20 && prog_val < 30 ) { auto_choice = 3; } else if( prog_val >70 && prog_val < 90 ) { auto_choice = 4; } else if(prog_val >140 && prog_val < 160) { auto_choice = 5; } else if(prog_val >120 && prog_val < 130) { auto_choice = 1; } else if(prog_val>240) { auto_choice = 6; } if (var_val<10) { variation_choice = 2; } else if( var_val > 55 && var_val<70 ) { variation_choice = 3; } else if(var_val > 140 && var_val<150) { variation_choice= 4; } else if(var_val > 200) { variation_choice = 5; } else if( var_val <135 && var_val>110) { variation_choice = 1; } if (delay_val<10) { delay = 2; } else if( delay_val > 55 && delay_val<70 ) { delay = 3; } else if(delay_val > 140 && delay_val<150) { delay = 4; } else if(delay_val > 200) { delay = 5; } else if( delay_val <135 && delay_val>110) { delay = 1; } /*********Get Starting Position****************/ if (posit_val<10) { position_choice = 2; } else if( posit_val >20 && posit_val < 30 ) { position_choice = 3; } else if( posit_val >70 && posit_val < 90 ) { position_choice = 4; } else if(posit_val >140 && posit_val < 160) { position_choice = 5; } else if(posit_val >120 && posit_val < 130) { position_choice = 1; } else if(posit_val>240) { position_choice = 6; } } As you can see the outputs of the switches are not linear but those values can be obtained using a print f statement or the dashboard. The position selection is stored in an external variable "position_choise" that is defined in user_routines.c. This variable is not reset when initializing autonomous mode, and it is then looked at when it comes time to chose which auto function to run. ALSO note that this function is called in manual mode since the robot is disabled before it goes into auto, that is the only time the switches can be read. |
|
#12
|
|||
|
|||
|
Re: Setting Autonomous Settings from OI
Quote:
We used the OI to select autonomous mode back when PBASIC was being used. The first time through the loop after reset the switch values were not reliable. The last time through the loop, just prior to seeing the autonomous flag switch, the switch values were also not reliable. We wrote code that saved the values of the required switches after a couple of cycles. What you don't want to do is save the value on the first cycle, and you don't want to save the last value prior to the autonomous flag going up. In our scheme, we saved the value a couple of cycles after reset and the students knew to reset the robot after any adjustment to the switches. You could also save several versions of the value, and select one several cycles before the autonomous flag goes up to get a reliable value. Saving several samples of the value, comparing them, and selecting "do nothing" if they are not consistent is also a good idea. We have not tried using the OI to select the autonomous mode since, as there are plenty of switches/pots available in the robot. It is the same basic OI as the PBASIC days, and it is likely to suffer from the same issues when reading switches to select the autonomous mode. A little tweaking of your code that reads and saves the mode selector value and you should be fine. If not, move the pot to the robot... Last edited by eugenebrooks : 15-03-2005 at 21:20. |
|
#13
|
||||
|
||||
|
Re: Setting Autonomous Settings from OI
Quote:
When you say the values are unreliable, does that mean they all get set to defaults a few cycles before autonomous_mode changes, or do they get trashed with random values during that transition? The reset-after-change idea seems fine. Another idea I had was to hardwire one of the digital-inputs to a non-default value and use that as a canary to know when the values are wrong, depending on the answer to my previous question. I can't wait to get the robot back so I can experiment with this and get it all figured out. I hope this thread saves someone else the annoyance of needing to figure this out between matches! |
|
#14
|
|||||
|
|||||
|
Re: Setting Autonomous Settings from OI
Quote:
|
|
#15
|
|||
|
|||
|
Re: Setting Autonomous Settings from OI
Quote:
to the value selected by the switches. We patched it by waiting a few cycles to pick up the values that selected the auto mode and moved on to other things. You could write code that saves the values read in a circular buffer, if you want, and prints them out a few cycles after auto mode goes up. You could then get the answer to your question. We discovered the issue while testing the auto mode with a competition port switch box, handling disable and auto mode switches by hand. Again, it was several years ago and my memory is hazy. We have not used OI switches to select the auto mode since the PBASIC days. |
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| A Warning to Human Players During Autonomous | The Lucas | General Forum | 21 | 07-04-2005 02:29 |
| Despite what IFI says, you can configure autonomous from OI... | TedP | Programming | 19 | 31-03-2004 10:09 |
| setting autonomous mode | Allison | Programming | 10 | 08-03-2004 20:37 |
| autonomous mode problem on field | Chris_C | Programming | 17 | 26-03-2003 19:11 |