Yes I know, strange title for a thread.
I was asked this question by a student.
So if I understand the question correctly, the idea is to avoid all the sequential calls and have the autonomous instructions in an array. This is essentially what Joseph’s autonomous framework gives you, however, this is quite complicated code so I though I would throw something together very quickly that demonstrates the general idea.
We use a structure to hold the variables needed for each step of the autonomous code.
// structure to hold one autonomous step
typedef struct _auto_step {
int number;
bool clearEncoder;
int count;
long timeout;
autoFunction func;
} auto_step;
What variables you store are unto you, I have a flag to clear an encoder, a “count” used for moving a number of encoder counts or for a wait delay, a timeout used to abort the driving step, and some function to execute that I have made a new type for “autoFunction”. This can be one of the following enumerated types.
// Different autonomous things we can do
typedef enum _autoFunction {
kAutoInitialize = 0,
kAutoStop,
kAutoDrive,
kAutoDelay
} autoFunction;
I only have three functions, drive a number of encoder counts, stop motors and wait some number of milliseconds.
To store all the steps in my autonomous code I use an array of this structure.
// We don't have initialized structures (apparently)
// it would be easier to set this as an initialized array
#define MAX_STEPS 10
auto_step auto_1[MAX_STEPS];
Now ideally, we would just initialize this array with constants, however, ROBOTC won’t let you do that (still) so we have to populate the array in code.
Here is the full example, it’s for a simple 2 motor drive with one IME.
#pragma config(I2C_Usage, I2C1, i2cSensors)
#pragma config(Sensor, I2C_1, , sensorQuadEncoderOnI2CPort, , AutoAssign)
#pragma config(Motor, port1, , tmotorVex393_HBridge, openLoop, encoderPort, I2C_1)
#pragma config(Motor, port10, , tmotorVex393_HBridge, openLoop)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
/*-----------------------------------------------------------------------------*/
/* Copyright (c) James Pearman */
/* 2014 */
/* All Rights Reserved */
/*-----------------------------------------------------------------------------*/
/* */
/* Module: auto_test.c */
/* Author: James Pearman */
/* Created: 8 Oct 2014 */
/*-----------------------------------------------------------------------------*/
/* */
/* This program is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation, either version 3 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/* The author can be contacted on the vex forums as jpearman */
/* or electronic mail using jbpearman_at_mac_dot_com */
/* Mentor for team 8888 RoboLancers, Pasadena CA. */
/* */
/*-----------------------------------------------------------------------------*/
// Different autonomous things we can do
typedef enum _autoFunction {
kAutoInitialize = 0,
kAutoStop,
kAutoDrive,
kAutoDelay
} autoFunction;
// structure to hold one autonomous step
typedef struct _auto_step {
int number;
bool clearEncoder;
int count;
long timeout;
autoFunction func;
} auto_step;
// We don't have initialized structures (apparently)
// it would be easier to set this as an initialized array
#define MAX_STEPS 10
auto_step auto_1[MAX_STEPS];
// Add a new step to the autonomous instruction array
//
void
addAutoStep( auto_step *theAuto, bool clearEncoder, int count, long timeout, autoFunction func )
{
int nextIndex;
// First step should be initialize, this clears the counter in the first step we use
// to know how many steps we have
if( func == kAutoInitialize )
theAuto[0].number = 0;
nextIndex = theAuto 0 ].number;
theAuto nextIndex ].clearEncoder = clearEncoder;
theAuto nextIndex ].count = count;
theAuto nextIndex ].timeout = timeout;
theAuto nextIndex ].func = func;
theAuto 0 ].number++;
}
// Call this with each autonomous step
//
void
runAutoStep( auto_step *theAuto, int index )
{
long timeNow = nSysTime;
auto_step *p = &theAuto index ];
if( p->clearEncoder )
nMotorEncoder port1 ] = 0;
switch( p->func )
{
// Init function
// reset gyro etc.
case kAutoInitialize:
break;
// A delay function
case kAutoDelay:
wait1Msec( p->count );
break;
// Stop function
case kAutoStop:
motor port1 ] = 0;
motor port10 ] = 0;
break;
// Drive function
case kAutoDrive:
if( p->count > nMotorEncoder port1 ] )
{
motor port1 ] = 100;
motor port10 ] = 100;
// Wait until the encoder count is reached or the timeout occurs
while( (nMotorEncoder port1 ] < p->count) && ((nSysTime - timeNow) < p->timeout) )
wait1Msec(10);
}
else
if( p->count < nMotorEncoder port1 ] )
{
motor port1 ] = -100;
motor port10 ] = -100;
// Wait until the encoder count is reached or the timeout occurs
while( (nMotorEncoder port1 ] > p->count) && ((nSysTime - timeNow) < p->timeout) )
wait1Msec(10);
}
break;
default:
break;
}
}
// Main task
task main()
{
int steps;
int i;
// Setup autonomous instructions
addAutoStep( auto_1, true, 0, 0, kAutoInitialize );
addAutoStep( auto_1, true, 1000, 5000, kAutoDrive );
addAutoStep( auto_1, false, 0, 0, kAutoStop );
addAutoStep( auto_1, false, 500, 0, kAutoDelay );
addAutoStep( auto_1, true, -1000, 5000, kAutoDrive );
addAutoStep( auto_1, false, 0, 0, kAutoStop );
// Number of steps
steps = auto_1[0].number;
// run the autonomous steps
for(i=0;i<steps;i++)
runAutoStep( auto_1, i );
// Done
while(1)
wait1Msec(10);
}
Code written for ROBOTC V4.XX, may or many not work in V3.X