Best way to implement a timed action

We need to have our frisbee injector (which is an arm attached to a window motor) actuate forward for exactly X milliseconds, and then retract backwards until it triggers a limit switch. I know there are a couple different ways to do this but I was wondering how it would be best to do so.

  1. Spawn off a second thread, set to actuate forward, Timer.delay() for X milliseconds, actuate backward, and then return isFinished() as true when the microswitch is triggered. I could have sworn I’d seen a team do it this way, but then I came across some comments saying that creating a Thread inside a command is a bad idea, etc.

  2. Create 2 commands (which I would prefer not to do), the first of which is timed using isTimedOut(), the second of which triggers via the microswitch, and call them sequentially in a command group

  3. Ways I haven’t thought of

Thoughts?

Why don’t you use the FPGA timer?

In java you could do something like
int amountOfTimeToRun = 0;//insert amount of time here to run in milliseconds
//button press or something here
int timeStamp = Timer.getFPGATimestamp();//records time
while(Timer.getFPGATimestamp() - timeStamp <= amountOfTimeToRun)
{actuate forward}

You could use the WPI Notifier Class (Anyone know if there is a Java equivalent and details on how to use it?)

The upside of using an Notifier is it uses timer interrupts and handlers rather than polling/waiting yourself

To use you could init the Notifier with a TimerEventHandler that reverses the motor. Every time you want to fire, set the motor forward and call StartSingle(delay) for the Notifier (make sure to only do this once per cycle).

Assuming that you want to implement this as a command you can do something where you use the FPGA timer to time the ‘halfway point’ of the command.
In the command initialize you set a start time variable for the command to the current time.
In the execute you do something along the lines of setting the solenoid to forward when the start time + delay time is less than the current time, and set in to reverse otherwise.
In the is finished you can then check to see if the delay has passed and the limit switch is active.

In C++ this would be something like this:
https://gist.github.com/Equinox-/5127682

If you’re using Java, anonymous classes can make adding two commands seem much less annoying:

addSequential(new Command(X/1000.0) {
    protected void initialize() {
        injector.actuateForward();
    }
    protected void execute() {}
    protected boolean isFinished() {
        return isTimedOut();
    }
    protected void end() {
        injector.stopActuating();
    }
    protected void interrupted() {
        end();
    }
});
addSequential(new Command() {
    protected void initialize() {
        injector.actuateBackward();
    }
    protected void execute() {}
    protected boolean isFinished() {
        return microswitch.isTriggered();
    }
    protected void end() {
        injector.stopActuating();
    }
    protected void interrupted() {
        end();
    }
});

Unfortunately, this will only stop the injector within whatever time increment Scheduler.run() is called, which if it’s being run in periodic() is the period between driver station packets are coming, or about 20ms. A thread may be a better choice if you need finer resolution.