View Single Post
  #2   Spotlight this post!  
Unread 05-03-2014, 08:07
pblankenbaker pblankenbaker is offline
Registered User
FRC #0868
 
Join Date: Feb 2012
Location: Carmel, IN, USA
Posts: 102
pblankenbaker is a glorious beacon of lightpblankenbaker is a glorious beacon of lightpblankenbaker is a glorious beacon of lightpblankenbaker is a glorious beacon of lightpblankenbaker is a glorious beacon of light
Re: ASAP Code giving outOfMemory error

I took a look through your code and have the following comments/suggestions:

You need to refactor the execute() methods in several of your commands. For example, the execute method in Shoot.java looks like:

Code:
    
    // Called repeatedly when this Command is scheduled to run                  
    public void execute() {

        if (catapult.CatapultMSStart())
        {
            while(!catapult.CatapultMSEnd()) {
                catapult.ElevatorMotor1(speed);
                catapult.ElevatorMotor2(-1 * speed);
            }

	    catapult.WaitAfterShooting();

            while(!catapult.CatapultMSStart()) {
                catapult.ElevatorMotor1(-1 * speed);
                catapult.ElevatorMotor2(speed);
            }
        }
    }
As a rule of thumb, you should never run code in the execute() method of a command that takes any measurable time (loops, delays and waits should not be used).

This is fundamental rule that needs to be followed when using the CommandBased framework (the execute() method of one active command must complete before the execute() of the next active command is invoked).

For example, if the code fragment above takes 2 seconds to run. Then none of the execute methods of the other commands on your robot will run for 2 seconds. The driver won't be able to drive the robot and the robot will continue on "cruise control" until the motor safety kicks in and kills your program with the dreaded "Robot Drive... Output not updated often enough." message.

This is most likely the reason you are seeing the "Robot Drive... Output not updated often enough." message. Once you see this message, you are probably done for the match.

To refactor this type of code, you will either need to break the Shoot command into separate simple commands that you can join into a sequential command group: WaitForCatapultReady, WaitAfterShooting, RaiseElevator, LowerElevator.

For example, if the following code fragment raises the elevator:
Code:
            while(!catapult.CatapultMSEnd()) {
                catapult.ElevatorMotor1(speed);
                catapult.ElevatorMotor2(-1 * speed);
            }
A RaiseElevator command might have the following execute(), isFinished(), end() and interrupted() implementation (NOTE: I don't know the specifics of your robot - I'm guessing there is a elevator on it and how you go about raising it):

Code:
public class RaiseElevator extends CommandBase {
  private double speed;

  public Shoot(double theSpeed) {
     // Register that we need exclusive control of the catapult
     requires(catapult);
     // Save power to apply when moving the elevator
     this.speed = theSpeed;
  }

  protected void execute() {
    // Set motors to raise the elevator
    catapult.ElevatorMotor1(speed);
    catapult.ElevatorMotor2(-1 * speed);
  }

  protected boolean isFinished() {
    // Done once the elevator is at the top position
    return catapult.CatapultMSEnd();
  }

  protected void end() {
    // Stop elevator when in position
    catapult.ElevatorMotor1(0);
    catapult.ElevatorMotor2(0);
  }

  protected void interrupted() {
    // Do normal clean up (stop motors) if command interrupted
    end();
  }
}
In the implementation above, none of the methods have any loops or delays (they run almost instantly). This command achieves an effective delay by only returning true once the elevator is in position. This command might take two seconds to complete, however it never blocks other commands from running while waiting for the completion state to be reached.

If you don't want to break your Shoot command into a group of separate command, it is possible to refactor it by keeping track of states (define a set of states to transition through, have the initialize() method put it in the initial state, have the execute() method do an action based on the state (but no loops/delays), have the isFinished method determine when to move to the next state or when it is done.

Wrapping your head around the CommandBase framework takes some time, but it does have a lot of nice advantages over the SimpleRobot framework (especially on robots with numerous subsystems). Keep at it and I'm sure you work your way through the issues.

Good Luck.
Reply With Quote