View Single Post
  #18   Spotlight this post!  
Unread 12-06-2010, 16:16
frasnow's Avatar
frasnow frasnow is offline
Software
no team
Team Role: Alumni
 
Join Date: Jun 2010
Rookie Year: 2010
Location: PNW
Posts: 84
frasnow is a name known to allfrasnow is a name known to allfrasnow is a name known to allfrasnow is a name known to allfrasnow is a name known to allfrasnow is a name known to all
Re: no control of bot when kicker is operating

One solution for solving this in Java is threads. Team 997’s kicker this year takes 4.5 seconds to reload. It was extremely important for us to make sure the driver maintained control during this time. I’ve copied in some of our code below and removed most of the extra stuff it for you to see how we did threading on our robot.

A couple things to keep in mind.
1. It is vital your each thread of execution have either a Thread.yield() and/or a Timer.delay(). These are required to ensure each thread gets time on the CPU. Otherwise one thread could starve (not get any time on the CPU).
2. Put things like kicking that take a long time in separate threads, but keep quick things in the main thread. I accidentally put our gear shift in the kicker thread and the driver couldn’t shift while the kicker was reloading. We fixed this after regionals.

Main thread that starts kicker thread:
Code:
public class RobotMain extends SimpleRobot {

    final int Preload = 1;
    final int Retract = 0;
    final int Latch = 1;
    final int Unlatch = 0;
    private Joystick leftStick = new Joystick(1);
    private Joystick rightStick = new Joystick(2);
    
    public RobotMain() {
    }

  
    public void operatorControl() {
        
        getWatchdog().setEnabled(true);
       
        KickerThread kickerThread = new KickerThread(this);
        kickerThread.start();
        while (true && isOperatorControl() && isEnabled()) {
            
            drivetrain.tankDrive(leftStick, rightStick);
            getWatchdog().feed();
            
            // DO NOT remove this yield. Required for kicker thread to execute.
            Thread.yield();
        }
        try {
            kickerThread.join();
        } catch (InterruptedException ex) {
            System.out.println(ex.getMessage());
        }

    }

    /**
     * Gets the right joystick
     * @return The right joystick
     */
    public Joystick getRightStick() {
        return rightStick;
    }

    /** 
     * Gets the robot ready for the big kick.
     */
    private void makeReadyForKick() {
        //Not latched and needs to be preloaded.
        if ((preloaded == false) && (latched == false)) {
            driveLatchSolenoid(Latch);
            Timer.delay(1);
            driveShooterSolenoid(Preload);
            Timer.delay(1);
        }
        //Latched, but needs to preload.
        if ((preloaded == false) && (latched == true)) {
            driveShooterSolenoid(Preload);
            Timer.delay(1);
        }
        //Preloaded, but needs to latch.
        if ((preloaded == true) && (latched == false)) {
            driveShooterSolenoid(Retract);
            Timer.delay(2);
            driveLatchSolenoid(Latch);
            Timer.delay(1);
            driveShooterSolenoid(Preload);
            Timer.delay(1);
        }
    }

    /**
     * Peforms the kick routine.  First loads the kicker if needed.
     * After kicking it loads the kicker for the next big kick.
     */
    public void performKick() {
        makeReadyForKick();
        //Kick!
        driveLatchSolenoid(Unlatch);
        Timer.delay(.5); // If this changed, change the delay in autoKick!!!
        //Reload for big kick.
        driveShooterSolenoid(Retract);
        Timer.delay(2);
        driveLatchSolenoid(Latch);
        Timer.delay(1);
        driveShooterSolenoid(Preload);
        Timer.delay(1);
        System.out.println("Kick Performed");
    }

}
Kicker Thread:
Code:
public class KickerThread extends Thread {
    private RobotMain mRobot997;
    private Joystick mRightStick;
    public KickerThread(RobotMain robot) {
        mRobot997 = robot;
        mRightStick = mRobot997.getRightStick();
    }

    public void run() {
        while (mRobot997.isOperatorControl() && mRobot997.isEnabled()) {
            if (mRightStick.getTrigger()) {
                mRobot997.performKick();
            }
            Thread.yield();
        }
    }
}
In order to allow us to drive to the next ball in autonomous while reloading, we also used threads. The main thread just set a flag on the autonomous kicker thread's class to let it know when to go ahead and perform the kick. Does require being sure to write thread safe code.