Log in

View Full Version : Share you Autonomous


Bpk9p4
01-05-2014, 10:55
I am looking at working with are students this off-season to better off are autonomous skills. I was wondering if any teams would care to share there labview autonomous code so that we could learn from it.

Currently we only know of two ways of doing autonomous
1) Hard code
2) Playback recorded data

are there any other methods people know off?

Tom Line
01-05-2014, 11:34
I am looking at working with are students this off-season to better off are autonomous skills. I was wondering if any teams would care to share there labview autonomous code so that we could learn from it.

Currently we only know of two ways of doing autonomous
1) Hard code
2) Playback recorded data

are there any other methods people know off?

A scripted system using some type of text files that are read into the cRIO on command and then sequentially executed is fairly common.

Bpk9p4
01-05-2014, 13:09
I looked at doing this but it seems like it would be hard to do 2 things at once. Is there a way around this

adciv
01-05-2014, 15:36
State Machine? Although that may count as "hard code" to you. We'll be posting this years code at some point. Our two-ball auto involved roughly 25 steps due to a variety of things (it's being reprogrammed to be simpler). Our one ball was four steps, but also involved communicating with an additional statemachine (which also runs during Tele) for opperation.

Bpk9p4
01-05-2014, 15:51
We have done state machine in the past and it works well. Are biggest problem right now is that we hard code it so it is not very easy to change on the fly. I am wanting to find a way to rapidly produce autonomous and change it easily

marccenter
01-05-2014, 15:53
Here's FRC3548 autonomous and teleop program (w/o Camera) in Labview.

The autonomous program is very brute force using simple timers to actuate motor speed and throwing arm commands but it works, we shot 9 out of 11, 10 pointer's at MSC!

adciv
01-05-2014, 15:56
We're working on recoding the robot using behaviors (and will hopefully do this from the start next year). This should make it easier for us.Basically, we are coding a VI to control our intake and another to control the catapult. We'll then use these in a state machine or autonomous to control the robot. Similar things for the drive system. Basically, these are the equivalent of C++ function calls for controlling the subsystems. This would help you in building it faster.

As for changing it easily, what exactly do you mean? I can think of a few things we do, but I don't know what you have in mind.

Toa Circuit
01-05-2014, 16:01
Scripted autonomous is fairly... interesting.
4213 'used' it this year, but left it as the same script. We searched the cRIO root directory for the first '.auton' file, and then execute through that via state machines. Our basic structure is a bunch of <subsystem> <state> or <wait> <subsystem>. To wait for multiple subsystems, wait multiple times.

Script looks like this:

drivetrain 0.5 0 0 1 //0.5 Y, 0 X, 0 W, 1 second
catapult winched
sides deploy 3
wait drivetrain
wait catapult
wait sides
catapult fired

So this way, we know the 'bot is trying to achieve certain states. Understandable code that allows for 'parallelism' without actually using separate threads. ;)

I'll see if I can find the source code. I think it got diked/subverted/buried.

We use state machines... a lot. I highly recommend you learn how to use and implement a state machine if you don't already. It makes coding so much easier.

notmattlythgoe
01-05-2014, 16:03
What language are you using?

For the command based system, writing reusable commands that take in real world parameters and using them in a command group can give you a quick way to write new autonomous routines in the fly. Below is an example:


addSequential(new DriveStraightCommand(0.85, 60));
addSequential(new TurnToDegreeCommand(0.5, 45));
addSequential(new DriveStraightCommand(0.85, 24));


The above would drive forward at 85% power for 60 inches, then turn 45 degrees at 50% power, then drive forward for another 24 inches at 85% power.

If you have tested these commands out extensively you should know the robot will do exactly that the first time you run it.

cjl2625
01-05-2014, 16:13
To switch between auto modes, we have a dropdown menu on the dashboard. Some specific aspects of it are on other controls, like move forward time, which is on a slider.
The drop down menu selection is sent to a state machine.
For the programming of it, I package all complex functions (like a timer function, shooter sequence, and swerve drive) into sub-vi's, which makes new auto modes pretty easy to produce, though I guess it still counts as hard coded.

baumgartensam
02-05-2014, 02:42
One other method for doing autonomous is using machine learning-ish concepts. One thing we have thought about doing is having scouts in the stands recording if our robot makes shots and then using that information to find positions on the field that are viable to shoot from (using accelerometer and gyro). We then could import that information after each match and the robot could recalculate an autonomous path. I have written some code to do this and it worked quite nicely; however, we didn't get a chance to use it at comps.

SoftwareBug2.0
02-05-2014, 03:45
Our basic structure is a bunch of <subsystem> <state> or <wait> <subsystem>. To wait for multiple subsystems, wait multiple times.

Script looks like this:

drivetrain 0.5 0 0 1 //0.5 Y, 0 X, 0 W, 1 second
catapult winched
sides deploy 3
wait drivetrain
wait catapult
wait sides
catapult fired




addSequential(new DriveStraightCommand(0.85, 60));
addSequential(new TurnToDegreeCommand(0.5, 45));
addSequential(new DriveStraightCommand(0.85, 24));


The above would drive forward at 85% power for 60 inches, then turn 45 degrees at 50% power, then drive forward for another 24 inches at 85% power.

If you have tested these commands out extensively you should know the robot will do exactly that the first time you run it.

Do either of these methods allow non-linear steps? What happens in case of failure? Surely it's possible that a robot could fail to drive some distance.

Our autonomous modes were DAGs that would not only do different things but intentionally leave the robot in different states for the driver depending on what happened during autonomous.

notmattlythgoe
02-05-2014, 06:23
Do either of these methods allow non-linear steps? What happens in case of failure? Surely it's possible that a robot could fail to drive some distance.

Our autonomous modes were DAGs that would not only do different things but intentionally leave the robot in different states for the driver depending on what happened during autonomous.

With some forethought you can create some pretty interesting command groups. And yes you can account for failures. When you add any of the commands you can add timeouts to them. Of course, depending on what has failed to complete could effect if your auto mode is successful or not. Sometimes you might want the robot to not finish the auto mode if one step has failed.

Here is an example of non linear steps.

addSequential(new DriveStraightCommand(0.85, 60));
addSequential(new TurnToDegreeCommand(0.5, 45));
addSequential(new MoveAndShootCommand());
addSequential(new new TurnToDegreeCommand(0.5, -45));


MoveAndShootCommand:

DriveStraightCommand driveCommand = new DriveStraightCommand(0.85, 120);
addSequential(driveCommand);
addParallel(new WaitForDistanceCommand(40, driveCommand));
addSequential(new ShootCommand());
addParallel(new WaitForDistanceCommand(60, driveCommand));
addSequential(new ShootCommand());
addParallel(new WaitForDistanceCommand(80, driveCommand));
addSequential(new ShootCommand());


The DriveStraightCommand implements an interface called IProvidesCurrentDistance which will return the distance the command has currently moved. Using this interface you can pass the running command in to other commands and have access to the distance moved at a given time. The MoveAdnShootCommand will start the robot moving, then once it has reached 20, 40, and 60 inches will run a shoot command. The final TurnToDegreeCommand will run once the MoveAndShootCommand has finished.

tr6scott
02-05-2014, 09:37
Please check out this paper written by apalrd on beescript.

http://www.chiefdelphi.com/media/papers/2497

We implemented this a few years ago, and love the flexibility of beescript.

Our two ball script looks like this:

#Two Ball Autonomous

SET_ROLLER_SPEED 75

WAIT 100

ARM_MOVE 1

WAIT 300

SET_ROLLER_SPEED 25

WAIT 300

SET_ROLLER_SPEED 52

DRIVE_STRAIGHT 84 6000

SET_ROLLER_SPEED 0

WAIT 250

SHOOT

WAIT 250

SET_ROLLER_SPEED 90

WAIT 1550

SHOOT

STOP_ALL

Our drive straight command drives at 75% motor power, and has a gyro P loop to adjust motor powers so you actually drive straight. The first argument of the drive strait is the inches of travel by encoder counts. The second argument in the drive straight command is a timer override, so after 6 seconds, it will close and go to the shoot command.

We will be making public our github project in the next few weeks, after they clean up the commits from championship.

Bpk9p4
02-05-2014, 11:22
I really like this idea. The only problem i see with it is you can only do one command at a time. have you found a way to get around this problem?

chris.boyle
02-05-2014, 11:48
We used a record and replay system for autonomous this year. Attached are the complete projects for the custom dashboard and robot.

There is a tab on the dashboard for starting and stopping the recording process. It uses the SmartDashboard to communicate between the dashboard and robot.

tr6scott
02-05-2014, 12:07
I really like this idea. The only problem i see with it is you can only do one command at a time. have you found a way to get around this problem?

Yes, and no, you can program a command that does multiple actions, but there is only one command active at a time.

I forgot to mention the best part is that the script file is just a text file that resides on the cRio. The cRio has a built in ftp server, so you can change these sequences, and re-run without connecting to labview, compiling, etc. The whole process to change the script and ftp to the cRio can be done in about a min. We have done this while queuing for a match. It takes less time to change the auto code, and download, than it takes to charge the pneumatic system. We also have a dashboard selection that chooses between 7 automodes.

wt200999
02-05-2014, 13:27
I really like this idea. The only problem i see with it is you can only do one command at a time. have you found a way to get around this problem?

You just need to be smart in how you lay out your commands, and remember they are very high level. Lets take a choo-choo style shooter which starts with the shooter released and a ball on top of it (for whatever reason). Also it takes ~3 seconds to load. Using something like beescript you could have a routine like this:


#Load the shooting mechanism
LOAD_SHOT

#Drive forward 5 feet
DRIVE 5

#Internal timer waits until 5 second mark if not hot
DELAY_IF_NOT_HOT

#shoot when ready
WAIT_ON_LOAD
SHOOT

#Make sure the shooter is down for start of teleop
LOAD_SHOT


You can write your LOAD_SHOT command such that it can drive the shooter motor and wait on a switch. If you do this, you don't start driving until ~3 seconds into auto, which is a problem.

Instead you can write your command to tell a different process the same thing, letting the script continue. It then can meet back up with the WAIT_ON_LOAD command to make sure its ready to shoot. In this way, both the driving and the camera code are running in parallel with the code to load the shooter.

Essentially you can write your commands to set off a parallel part of the code and continue. If all of the main robot actions are handled in a separate process, this becomes much easier to do (and it carries over to teleop).

Bpk9p4
02-05-2014, 13:28
any reason you choose to save it on the crio and not just read it from a laptop?

tr6scott
02-05-2014, 16:22
Yes, I don't know how to get the cRio to read a file over the FMS to the driver station. Maybe there is something there already, but I have never tried it.

adciv
02-05-2014, 19:00
You can implement your own UDP/TCP connection to communicate between the dashboard and the cRIO. We have done this in labview when we needed extra vision processing computing power. Also, the smart dashboard may have similar capabilities.

wt200999
02-05-2014, 19:09
You can implement your own UDP/TCP connection to communicate between the dashboard and the cRIO. We have done this in labview when we needed extra vision processing computing power. Also, the smart dashboard may have similar capabilities.

Another interesting way to do this would be to use port 80 (HTTP) or 443 (HTTPS) which are both not blocked, and write some kind of snazzy web app to create/modify/save your scripts. The current cRio already runs a web server, and setting this up on the robotRIO will be even easier. If you are worried about resource usage you can do something to pause or kill the web server when you are not in a disabled mode.

SoftwareBug2.0
03-05-2014, 03:11
With some forethought you can create some pretty interesting command groups. And yes you can account for failures. When you add any of the commands you can add timeouts to them. Of course, depending on what has failed to complete could effect if your auto mode is successful or not. Sometimes you might want the robot to not finish the auto mode if one step has failed.

Here is an example of non linear steps.

addSequential(new DriveStraightCommand(0.85, 60));
addSequential(new TurnToDegreeCommand(0.5, 45));
addSequential(new MoveAndShootCommand());
addSequential(new new TurnToDegreeCommand(0.5, -45));


MoveAndShootCommand:

DriveStraightCommand driveCommand = new DriveStraightCommand(0.85, 120);
addSequential(driveCommand);
addParallel(new WaitForDistanceCommand(40, driveCommand));
addSequential(new ShootCommand());
addParallel(new WaitForDistanceCommand(60, driveCommand));
addSequential(new ShootCommand());
addParallel(new WaitForDistanceCommand(80, driveCommand));
addSequential(new ShootCommand());


The DriveStraightCommand implements an interface called IProvidesCurrentDistance which will return the distance the command has currently moved. Using this interface you can pass the running command in to other commands and have access to the distance moved at a given time. The MoveAdnShootCommand will start the robot moving, then once it has reached 20, 40, and 60 inches will run a shoot command. The final TurnToDegreeCommand will run once the MoveAndShootCommand has finished.

This still seems linear to me. All it's doing is waiting for some condition and deciding to go on to the next step or continue waiting.

What I was trying to ask is if you could do something like:

if goal is hot:
fire
drive forward
else:
turn
fire

notmattlythgoe
03-05-2014, 10:03
This still seems linear to me. All it's doing is waiting for some condition and deciding to go on to the next step or continue waiting.

What I was trying to ask is if you could do something like:

if goal is hot:
fire
drive forward
else:
turn
fire


This is one of the things I want to investigate during the off season. This is my untested theory so take it with a grain of salt.

TwoBallTwoHotGoalCommand

HotGoalFinder finder = new HotGoalFinder();
addSequential(new DriveStraightCommand(0.85, 240));
addSequential(finder, 0.5);
addSequential(new DecisionCommand (finder, new TurnandShootSeries(), new ShootCommand()));
addSequential(new DeployArmCommand(Arm.DEPLOY, RobotMap.pickupPower));
addSequential(new DriveStraightCommand(-0.85, 240));
addSequential(new WaitCommand(1));
addSequential(new DriveStraightCommand(0.85, 240));
addSequential(finder, 0.5);
addSequential(new HotGoalDecision(finder, new TurnandShootSeries(), new ShootCommand()));


HotGoalDecision

public class DecisionCommand extends Command {

public DecisionCommand (IProvidesDecision decision, Command trueCommand, Command falseCommand) {}

public void initialize() {
if (decision.getValue()) {
trueCommand.initialize();
} else {
falseCommand.initialize());
}
}

public void execute() {
if (decision.getValue()) {
trueCommand.execute();
} else {
falseCommand.execute());
}

etc...
}


IProvidesDescision

public interface IProvidesDecision {
boolean getValue();
}

pastelpony
03-05-2014, 12:39
This isn't our main autonomous (our main autonomous uses vision tracking to detect the hot goal and shoot at it; don't have access to the team's programming computer atm and left my flash drive in it) but it's a 2-ball autonomous VI that wasn't used in the final code. It's pretty basic as it was written in a blank VI and so I didn't get to use global variables or subVIs. See if it helps.

AGPapa
03-05-2014, 13:13
What I was trying to ask is if you could do something like:

if goal is hot:
fire
drive forward
else:
turn
fire


I've implemented something like that. I have an "if" command that continues autonomous from two different script files based on the result of some function. The first parameter of "if" is the name of the function to check. The next parameters are the name of the script file to run if true and then the name of the script file to run if false. For example, here is the two ball hot script.

in twoBallHot.script

SHIFT on
WAIT 1000
SET_SHOULDER 49
IF right_hot rightHot leftHot


in rightHot.script

DRIVE_STRAIGHT 75 0
TURN 12
WAIT 100
SHOOT
WAIT 400
SET_SHOULDER -5
TURN -152
INTAKE in
DRIVE_STRAIGHT 75 -152
SET_SHOULDER 49
TURN -7
INTAKE off
DRIVE_STRAIGHT 70 -7
WAIT 200
SHOOT
SHIFT off


in leftHot.script

DRIVE_STRAIGHT 75 0
TURN -12
WAIT 100
SHOOT
WAIT 400
SET_SHOULDER -5
TURN -150
INTAKE in
DRIVE_STRAIGHT 75 -150
SET_SHOULDER 49
TURN 17
INTAKE off
DRIVE_STRAIGHT 80 17
WAIT 200
SHOOT
SHIFT off

tr6scott
03-05-2014, 13:37
Our one ball hot check script was this:

#One Ball, with Hot Checking

WAIT 500

CHECK_HOT

ARM_MOVE 1

SET_ROLLER_SPEED 25

DRIVE_STRAIGHT 96 5000

#Was 3500

SHOOT_HOT 3000

STOP_ALL

The "Check_Hot" Command just checked the hot goal, and wrote the status to a global variable. The "Shoot_Hot" command would look at the global variable, and if hot would shoot without delay, and if it was not hot it would delay the argument "3000" milliseconds, then shoot.

SoftwareBug2.0
03-05-2014, 13:57
I've implemented something like that. I have an "if" command that continues autonomous from two different script files based on the result of some function. The first parameter of "if" is the name of the function to check. The next parameters are the name of the script file to run if true and then the name of the script file to run if false.

Excellent. That's exactly what I was wondering about.

SoftwareBug2.0
03-05-2014, 14:27
public class DecisionCommand extends Command {

public DecisionCommand (IProvidesDecision decision, Command trueCommand, Command falseCommand) {}

public void initialize() {
if (decision.getValue()) {
trueCommand.initialize();
} else {
falseCommand.initialize());
}
}

public void execute() {
if (decision.getValue()) {
trueCommand.execute();
} else {
falseCommand.execute());
}

etc...
}


That looks like it would work. I was pretty sure it would be possible to do something but I thought it might get really ugly really fast. That's a pretty slick way to do it.

Here's something you could do if you wanted to be avoid duplicating the end of command conditions in the subsequent if:

class Continuable extends Command{
//I don't remember whether I've set this class up is valid Java...

//this would return self unless you wnated to run a different command.
abstract public Continuable next();

public bool isFinished(){
return next()==null;
}
}

class Continues extends Command{
Continuable current;

Continues(Continuable cmd){
current=cmd;
}

void initialize(){
if(current!=null) current.initialize();
}

void execute(){
if(current!=null){
current.execute();
}
}

bool isFinished(){
if(current==null) return 1;
current=current.next();
return current==null;
}
}

notmattlythgoe
03-05-2014, 14:40
That looks like it would work. I was pretty sure it would be possible to do something but I thought it might get really ugly really fast. That's a pretty slick way to do it.

Here's something you could do if you wanted to be avoid duplicating the end of command conditions in the subsequent if:

class Continuable extends Command{
//I don't remember whether I've set this class up is valid Java...

//this would return self unless you wnated to run a different command.
abstract public Continuable next();

public bool isFinished(){
return next()==null;
}
}

class Continues extends Command{
Continuable current;

Continues(Continuable cmd){
current=cmd;
}

void initialize(){
if(current!=null) current.initialize();
}

void execute(){
if(current!=null){
current.execute();
}
}

bool isFinished(){
if(current==null) return 1;
current=current.next();
return current==null;
}
}


Thanks. This is one of the topics I want to tackle this off season. I'm still struggling with the best way to store the decision, in a command or in another object of some sort that gets passed around. It probably depends on the usage.

_untitled_
03-05-2014, 14:56
We used to hardcode our autonomous routine in C++, but we found that compilation and deploy times added too much overhead and made it hard to quickly change routines on the fly.

To address this issue, we tried a scripted approach this year to autonomous. The first iteration of our "scripting" approach was a simple list of commands that the C++ codebase interpreted step-by-step:

# sample one ball auto
drive(72.0)
collector_move(false) # collector down
fire()


For parallel routines to run (e.g. parallelize loading and turning), we had a parallel command:

parallel(load(), turn(30.0))


This worked out pretty well for us; it provided the speed and convenience that we wanted for fast, on-the-fly editing. However, when we tackled a hot-goal routine, we realized that the lack of control flow structures or loops resulted in the software team having to go back to the C++ codebase to add new routines in C++, negating the speed and convenience benefits that we achieved.

We looked at a lot of possibilities, and we decided on Lua, a scripting language popularly used in video games where processing has to finish in 20-30 millisecond time steps. As a plus, an open-source ANSI-C interpreter was available. We put together a quick prototype, exposing C++ functionality to Lua using its aliasing feature.

However, we quickly realized that an issue inherent to using Lua (or any other general-purpose scripting language, for that matter) was that we lost the step-by-step and parallelization functionalities. At the same time, we didn't want to have to pause execution of the main robot loop to run our autonomous routine or have to coordinate multi-threaded execution. It turns out that Lua's coroutine functionality is perfect for achieving this functionality. When the Lua code calls a C++ function, the function pauses execution of the script and keeps a tab on the requested function. On each update of the script interpreter, the function is checked for completion, and upon completion, the script is resumed and is run until the next pause or the end of the script. This is great because from the script's perspective, everything is clean and nice and you don't have to deal with waiting for routines to complete and whatnot.

The next issue we wanted to address was running parallel routines. To do this, we created two functions, beginActionGroup(name:string) and endActionGroup(). If calls to C++ functions are made between these two functions, the script delays execution and instead adds the routine to a list instead of running the routine immediately (and yielding execution of the script). When the action group is run, each of the sub-routines are run in parallel. To run action groups in parallel, the function runParallel(group1:string, group2:string, group3:string, ...) is called and behaves like any other routine (e.g. script execution is paused until completion).

With these issues solved, we were able to write the following for our double ball hot routine:


--[[
DoubleHot.lua

Autonomous routine for firing a two hot goals.
The robot starts in the center and drives into
the colored zone for mobility points, turns
towards the first hot goal, fires, reloads, then
turns to the other hot goal and fires.
--]]

require "common"

-- == CONFIGURABLE CONSTANTS == --
GOAL_SIDE_PADDING = 48.0 -- inches, distance from center of goals
SHOOTING_RANGE = 138.0 -- inches, distance to shoot


-- == Routine == --
routineStartTime = GetTimeMillis()

TURN_ANGLE = math.asin(GOAL_SIDE_PADDING / SHOOTING_RANGE) * 180.0 / math.pi -- calculate turn angle from params
DRIVE_DISTANCE = 216.0 - math.sqrt(SHOOTING_RANGE * SHOOTING_RANGE - GOAL_SIDE_PADDING * GOAL_SIDE_PADDING)

-- -1: Left
-- 0: Center
-- 1: Right
heading = 0 -- neutral position

function defaultTwoBall()
turn(TURN_ANGLE)
fire(true)
collect()
loadLauncher()
collectorMove(true)
pause(0.5)
fire()
end

function shootHotGoal()
local side = getHotGoalSide()
local holdDown = true

if(heading == 0) then
if side == 0 then
return false
end
elseif heading == -1 then
side = 1
holdDown = false
elseif heading == 1 then
side = -1
holdDown = false
end

local turnAngle = side * TURN_ANGLE * -1

turn(turnAngle)
fire(holdDown)

heading = side

return true
end

function centerRobot()
local turnAngle = (0 - heading) * TURN_ANGLE * -1

turn(turnAngle)
end

turn(0.0)
dribbleDrive(-1 * DRIVE_DISTANCE, 1.0)
collectorMove(true)

if shootHotGoal() then
collectorMove(true)
centerRobot() -- back to neutral pos to pick up ball
collect()
loadLauncher()
collectorMove(true)
pause(0.5)
shootHotGoal()
else
defaultTwoBall()
end

BufferedPrint("Routine completed in "..((GetTimeMillis() - routineStartTime) / 1000.0).."s.")


The above example doesn't show off parallelization, so here's an example of our ball dribbling routine in Lua:


function dribbleDrive(distance, waitTime)
beginActionGroup("drive")
pause(waitTime)
drive(distance)
endActionGroup()

beginActionGroup("dribble")
dribble()
endActionGroup()

runParallel("drive", "dribble")
end


Some post-season projects we're considering include a LabView-esque drag-and-drop editor for Lua, and we're also pursuing the possibility of using Lua to code some of our subsystems next year to lower the difficulty barrier for new members. :)

SoftwareBug2.0
03-05-2014, 20:04
Seeing all the examples here makes me realize that there are major differences not only in coding styles or technologies used but also in the logic implemented. I wonder how much what teams do in autonomous is influenced by the style in which it's written.

At each step in our autonomous program we had multiple things that could happen. Basically, there was:
1) What if autonomous mode ends?
2) What if you're running out of time in autonomous mode?
3) What if the normal action of the step has completed?
4) What if none of the above have happened?

This seems like it would be horribly awkward to code in the styles that most people appear to be using but it was no big deal for us since we had an explicit state machine. It seems weird to me that even teams that care enough to embed a Lua interpreter or write their own scripting language to run their autonomous modes don't seem to be doing anything like this.

_untitled_
03-05-2014, 23:02
My answers are in bold red:


1) What if autonomous mode ends?
The Lua interpreter is just like any other routine in our C++ codebase, and our routine system allows for graceful abortion of a routine mid-execution. When auto ends, the Lua routine is aborted, and the system restores the robot to a clean state.
2) What if you're running out of time in autonomous mode?
The above routine I posted does not implement this (although the defaultTwoBall logic is similar), but for our single hot routine, we keep track of the start time, and if we detect that the time elapsed has exceeded some value before a side has been detected, the routine defaults and shoots.
3) What if the normal action of the step has completed?
If the normal action of the step completes, the script resumes and runs the next instruction.
4) What if none of the above have happened?
This is a pretty generic question. If you mean to ask if a step doesn't successfully complete, you can add a time-out condition to abort the routine and forcefully continue the script. The logical control structures that Lua provides make it very easy to address these situations.

SoftwareBug2.0
04-05-2014, 00:52
My answers are in bold red:

What I was trying to get at with the questions was that our next state logic looked like this:

State next_state(State current_state){
switch(current_state){
case A:
if(!autonomous_mode) return W; //#1
if(almost_out_of_time) return X; //#2
if(ready) return Y; //#3
return Z; //#4
case B:
...
}
}

I hope that clears things up.

Does your robot always do the same thing on abortion of the Lua script? It seems like it should be possible to make it do different things since you could call some C++ function to set a variable to remember what mode you should go to after the script finishes.

_untitled_
04-05-2014, 01:16
Does your robot always do the same thing on abortion of the Lua script? It seems like it should be possible to make it do different things since you could call some C++ function to set a variable to remember what mode you should go to after the script finishes.

Does our codebase do it? No; we have an event-driven routine system, and when the autonomous-end event is fired, the autonomous routine (and the underlying Lua scripting service) is aborted if it is still running. We have three modes: disabled, autonomous, and teleop. When autonomous ends, it releases its handles on the robot's resources, allowing other routines to run as well as driver input.

Is it possible? Sure! Lua is really flexible in that you can call into C++, so yes, you would be able to call a C++ function to set a flag, and after autonomous your code could read that flag and act upon it.

JohnGilb
05-05-2014, 19:02
We implemented a simple state-machine framework this season. It was used in both teleop and autonomous.

It worked as such:

States (which were a lot like commands) could return SUCCESS, FAILURE, or NOT_DONE.

StateMachines would add a number of states into them, then map the state transitions. It would look something like

int one = new DetectHotState(); //returns SUCCESS for left, FAILURE for right
int two = new DriveLeftState();
int three = new DriveRightState();
int four = new FireCatapultState();

machine.addSuccess(one, two);
machine.addFailure(one, three);
machine.addSuccess(two, four);
machine.addSucecss(three, four);

At runtime, the state machine framework would execute the relevant states. This let us write autonomous (and teleop) programs with a high degree of reuse.

Arhowk
06-05-2014, 17:44
Here's our 2-ball script. Works off of a custom JavaFX text editor on the developer laptop than is FTP'd and saved on the crio in raw binary format.
Might open source it before 2015, not sure.



Auton: 2 MoveKickTargeting

DS{
2 Kick And Move
Kicks loaded
Drives
Uses Camera
Without PID Drive
}



Procedure{

shiftLow
snapshot
upperStructureManual at -0.2 for 0.25
kickerBackward at 0.17 for 0.25

after 1
intakeDown
kickerForward at 0.1 for 0.25

if startpointCenter
at 2
driveForward at 0.75 for 1.5
if toTheLeft
at 5
driveTurnRightPID at 45 for 2
else
at 5
driveTurnLeftPID at 45 for 2
endif
at 8
upperStructureManual at -0.2 for 2
kickerForward at 1 for 0.5
else
if inTheCenter
at 2
driveForward at 0.75 for 1.5
after 1.5
upperStructureManual at -0.2 for 2
kickerForward at 0.84 for 0.5
else
at 2
driveForward at 0.75 for 1.5
after 3
upperStructureManual at -0.2 for 2
kickerForward at 0.84 for 0.5
endif
endif

}




not going to explain how the flow is layed out as iits a grammatical language. Some of the indenting and spaces got messed up when copying the code, I need to redo the text editor used thats attached to the deploy program.

Indenting doesnt actually matter, but linebreaks do. The way the commands work is as follows


public class RequestPeriodic
public static void processRequest(String processId, double arg)
if(processId.equalsIgnoreCase("driveForward"){
drive.arcadeDrive(1,0,false);
}
}
}

note that thats psuedocode and not actually how its implemented, but its very close. (its not a string, its an enum) Conditionals are the same, except the function returns a boolean. (One of the things also on my agenda is cacheing conditions to prevent erratic behavior)