300 likes | 442 Views
The Basics of Java Programming and Command-Based Robot Projects. TheRobettes.com. Agenda. Packages and Classes Variables and Objects Methods Command-Robot Concepts If/Else Statements For Loops and While Loops Key Command-Robot Classes Glossary, Q&A, Conclusions.
E N D
The Basics of Java Programming and Command-Based Robot Projects TheRobettes.com
Agenda • Packages and Classes • Variables and Objects • Methods • Command-Robot Concepts • If/Else Statements • For Loops and While Loops • Key Command-Robot Classes • Glossary, Q&A, Conclusions
All java code belongs to a specific class. Packages are sets of related Classes Every project starts with one ‘main’ class/method More detailed classes are defined and called on to handle various specific duties. Packages and Classes
Generic classes that sort and organize import java.util.*; import com.first.team2177.common.*; Standard java classes for ‘streams’ and internet import java.io.*; // read from and write to files (and to & from web sites) import java.net.*; // internet utility library import javax.servlet.*; // http web hosting library import javax.mail.*; // use this to spam your parents all night US F.I.R.S.T. library packages import edu.wpi.first.wpilibj.*; // Talon, Limit, Joystick… import edu.wpi.first.wpilibj.command.*; Split your Robot into 3 or more packages import com.first.team2177.robot.*; // the main stuff import com.first.team2177.robot.subsystems.*; // 2-4 physical subsets import com.first.team2177.robot.commands.*; // 5-15 ‘actions’ that the subsystem need to do Packages and Classes - examples
The actual class-list of our Ultimate robot. Robot extends ...wpilib.IterativeRobot // package is ...team2177.robot.* RobotMap extends java.lang.Object (implied) OI extends java.lang.Object (implied) DriveTrain extends ...wpilib.SubSystem // package is …team2177.robot.Subsystems.* ClimberSysextends …wpilib.SubSystem DumperSysextends …wpilib.SubSystem CommandBase extends ...wpilib.Command; // package is ...team2177.robot.Commands.* AutonomousCmd extends CommandBase TankDrive extends CommandBase ArcadeDriveextends CommandBase ClimbSetup extends CommandBase ClimbPreclimb extends CommandBase ClimbNextStep extends CommandBase ClimbTowerextends …wpilib.CommandGroup; Packages and Classes – examples 2
Variables hold a value or setting. Variables give a name & type to what the value is for. Variables can be passed between classes & methods. Variables can keep the same value, or be changed. There are several basic java variable types. Integers, Long Floats, Doubles Booleans “Object” variables hold a reference to a java-Class. String variable are Objects, but work like a basic type. Variables and Objects
In our project, ‘CommandBase’ defines many variables that are used by other ‘Action’ classes. DriveTraindrivetrain; // each subsystem is its own type. ClimberSysclimber; DumperSysdumper; Joystick leftStick; // 3 instances of the same type Joystick rightStick; Joystick shootStick; // these value can change during a game, but more likely just once on startup double driveBias= 0.7; // 0.5 would be a perfect left-right balance double practiceSpeedFactor= 1.0; // 1.0 = full-power, down to .6 or .7 for freshmem…. booleanisPitTesting = false; // if true, the Climber system needs to reduce lift-power // "debug" logging variables java.util.VectormessageTank; long starttime = System.currentTimeMillis() / 1000; Variables and Objects - examples
Groups of statements performed as a set. Defined by a name, (parameters), and a return type. Class MySampleClass { booleanisButtonPressed() { statements…; return joyStick.getButtonPressed(1);} void startOrStop(boolean) { statements; …; } long setArmHeight(double left, double right) { …; } Talon getActiveMotor() { …; return leftFrontMotor; } void doSomething() { // sample statement … // calling ‘local’ methods -- i.e. from MySampleClass, or else any class it extended… startOrStop( isButtonPressed() ); // bool return used as a bool parameter long h = setArmHeight( fX() , fY() ); // double,double IN, long OUT // calling methods from other classes -- i.e. ‘imported’ variables and types driveTrain.tankDrive( joystick.getY(), joystick2.getY() ); // double-double } // end of doSomething method } // end of MySampleClass Methods
“It will make simple programs more complicated and the more complicated programs simpler.” Organized into Subsystem and Command Easier to make adjustments throughout the season Code is more spread out throughout the classes Command-Based Robot Concepts
Robot RobotMap OI TankDrive ArcadeDrive Dumper AutonomousCmd ClimbSetup ClimbPreClimb ClimbTower ClimbNextStep ClimbNextStep DriveTrain DumperSys ClimberSys ClimbNextStep Motor controllers, sensors, etc Control Classes Subsystems Commands Command Groups
‘Robot’ creates our Autonomous & CommandBase CommandBase creates each of our subsystems. CmdBase->OI->init() then creates teleOp commands. ClimbTower and Autonomous are groups, they also create other Cmds. Robot - one instance, created by .wpilib RobotMap & OI – no instances. DriveTrain, ClimberSys, DumperSys - one instance each. AutonomousCmd - one instance, started and stopped by .wpilib/Robot TankDrive & ArcadeDrive – 1 & 2 instances, started by OI-designated buttons ClimbSetup – one instance, created and started by ClimberSys (then optionally by OI/joystick) ClimbPreclimb – one instance, created and started by OI/joystick ClimbTower – one instance, created and started by OI/joystick ClimbNextStep– 9 instances, created and started by ClimbTower CommandBase – 14 (extended) instances. Command-Robot Concepts – examples
Calling “new” [ClassName](); truns a Class into an Object. Here is the one global method of OI which generates our teleOp commands. init(Joystick leftStick, Joystick rightStick, Joystick shootStick) { // this is just condense slightly. // define the climb-actions based on top 3 “shooter” buttons { left, middle, right } Button climbSetupbutton = new JoystickButton(shootStick, 4); // left button climbSetupbutton.whenPressed(new ClimbSetup()); // besides being ‘default ‘, now also allow user to select this action climbSetupbutton= new JoystickButton(shootStick, 3); // middle button climbSetupbutton.whenPressed(new ClimbPreclimb()); // user-action, perform when within the tower perimeter Button climbExecuteButton= new JoystickButton(shootStick, 5); // right button climbExecuteButton.whenPressed(new ClimbTower()); // in position & verified, "GO" /* * Drive-Style Options * use left-driver’s top 3 buttons { left, middle, right } * to select between T-A-BS = Tank - Arcade – BananaSplit (aka Kaj) */ /*left*/ new JoystickButton(leftStick, 4).whenPressed(new TankDriving()); /*middle*/ new JoystickButton(leftStick, 3).whenPressed(new ArcadeDriving(false)); /*right*/ new JoystickButton(leftStick, 5).whenPressed(new ArcadeDriving(true)); // true signals the right-stick for the rotation } Command-Robot Concepts – code sample
One, two, or many ‘conditions’ can cause different actions. public void exampleCode(intmotorSpeed) { booleanbuttonPressed = joystick.getRawButton(4); if ( buttonPressed) { doThis(1.0); // because of {}, ‘this’ and doMore(); // ‘more’ are always executed back to back. } else if ( booleanA && booleanB) sideMotor.set( -1.0 ); else if ( limitSwitch.isPressed() || motorSpeed==0 ) sideMotor.set( 1.0); else defaultAction(); } If/ElseStatements
Our ‘preclimb’ command-code uses multiple ifs. public class ClimbPreclimbextends CommandBase { booleanisOnTarget = false; // this is used by both different methods below public void execute() { if (climber.shoulderPoint() < 1900) // Early on-- Raise the shoulder(&winch) quicker, and the elbow slower. climber.NudgeArms( .50, .25, .35 ); else if (isOnTarget) // Once raised -- Stall the shoulder-motor with positive-lift, this is to avoid ‘bouncing’ climber.NudgeArms( .1, 0, 0 ); else {// Default-Action, “lower” to the target set-points. isOnTarget= climber.SetTargetPositions("RaiseHooks - elbow-up", .6, 2600, 951, 1300 ); if (isOnTarget) // a nested test, log when we have completed this movement debugPrint(“now at preclimbpositions " + climber.shoulderPoint() + ", …. "); } protected void interrupted() { isOnTarget= false; // this reset is needed when we repeatedly go between driving and preclimb } } If/ElseStatements – Sample Code
While loops run while a certain condition is true. void raiseRobotArm() { while (armHeight < 30) // condition { // loop actions… outputPower = …statement…; armHeight= setArm( outputPower ); } } While Loops
Our ‘ClimbSetup’ Command performs back-to-back loops. public void execute() { if (climber.winchPoint() > 900) { // only perform these loops once, on startup. // Early on, Loosen the straps and Raise the shoulder, to assure that the elbow can be reversed-to-down. // target is effectively a forward-leaning high-five position while (climber.shoulderPoint() < 2500 || climber.winchPoint() < 2600 ) { climber.setTargetPositions("pre-driving-1", 0.5, 2700, 1417, 2809 ); } // Once raised, Swing the shoulder & elbow 'down', match speeds to minimize slack. while (climber.winchPoint() > 800) { climber.nudgeArms( -.15, -.60, -.55 ); } } // end of if // …always…, get to and maintain the proper ready-for-preclimb position climber.setTargetPositions("driving", 0.3, 839, 2612, 700 )); } // end of method While Loops – Sample Code
For Loops • For loops run for a certain count of times. (here the count is the condition) void runAutonomous() { // for each ‘N’, 1-5 for (int N=1; N<=5; N++) // something has to eventually change N to end the loop… // here N++ is a statement that does an N+1 each time. { // loop actions… fireCannon( N ); } // end of for loop } // end of runAutonomous()
For Loops - example • What if you needed to steer this ? final int ROWS = 4; final int AXELS = 30; …initialize…() { DriveWheel wheels[][] = new DriveWheels[AXELS][ROWS]; for (int row = 0; row < ROWS; row++ ) for (int axel = 0; axel < AXELS; axel++ ) wheels[axel][row] = new DriveWheel( (row*AXELS) + axel ); }
Subsystem Command CommandGroup Key Command-Robot Classes
The various parts of your robot drivetrain, climber, dumper. Make a class for each subsystem File, new file, Command-Based Robot, Subsystem Add sensor variables, to get readings (read=input). // i.e. long count = myEncoder.get(); Add motor variables, to set motions (write=output). // i.e. myTalon.set( voltage ); Add action methods, to be used by Commands. // i.e. MyCommand() { mySubSystem.doSomething(); } Key Classes – SubSystems
Private variables for sensors and motors Talon leftFront, rightFront, etc. Encoder leftSpeed, rightSpeed; Public action methods, for use by the Commands. void tankDrive(double left, double right) {…} void arcadeDrive(double momentum, double angle) {…} Key Classes – Subsystems – DriveChassis example
Private variables for sensors and motors Talon shoulder = new Talon( RobotMap.SHOULDER_MOTOR); Talon elbow =…; Talon winch1, winch2; “Potentiometer” shoulderPot = new AnalogChannel( RobotMap.SHOULDER_POT); Potentiometer elbowPot = …; Potentiometer winchPot = …; Private action methods, for local (climber) use. void setShoulderPosition(long) {…} void setElbowPosition(long) {…} void setWinchPosition(long) {…} Public action methods, for use by the Commands. void nudge(double shoulderPwr, double elbowPwr, double winchPwr) {…} void setPos(long shoulderTgt, long elbowTgt, long winchTgt) {…} long get___Position() { return ___Pot.getAverageValue(); } Key Classes – Subsystems – Climber example
Classes that use the functions of the subsystems to perform operations Make a class for each command File, new file, Command-Based Robot, command One(1) Autonomous command may use every Subsystem Each Subsystem usually creates one default-command for TeleOp. The OI class can make commands that exchange control of a Subsystem. Key Classes – Commands
Typically each command will ‘require’ a SubSystem in its constructor. public class TankDriving extends CommandBase { public TankDriving() { requires(drivetrain); // requires(Subsystem) is defined by .wpilib.Command } // end of method } // end of class ‘execute()’ has to be defined by every Command. What execute defines are statements performed by a near-continuous .wpilib-defined while loop. // Called repeatedly when this Command is scheduled to run protected void execute() { drivetrain.tankDrive( leftStick.getY(), rightStick.getY() ); } Key Classes – Commands – ‘execute’ code
We define ‘isFinished’ in our CommandBase, to just return false. So generally an OI-joystick action is the only thing to interrupt the execute()-loop We needed to define isFinished() within our ClimbNextStep. This is because they are each needed back-to-back while actually climbing. public void execute() { // simplified isFinished = climber.SetTargetPositions(cmdName, liftPower, shoulderTgt, elbowTgt, winchTgt); } // interrupt one ClimbNextStep command so the next can begin. public booleanisFinished() { return isFinished; } Key Classes – Commands – ‘isFinished’ code
These methods must be defined somewhere every Command. We do so as shown within our CommandBase class. // Called just before this Command runs the first time protected void initialize() { } // Make this return true when this Command no longer needs to run execute() protected booleanisFinished() { return false; } // Called once after isFinished returns true protected void end() { } // Called when another command which requires one or more of the same // subsystems is scheduled to run protected void interrupted() { } Key Classes – Commands – other code
A class that performs a chain of commands. Key library methods addSequential(Command) addParallel(Command) Key Classes - Command Groups
We start this group in tele-op mode… Effectively when the group needs to be executed, .wpilib code will execute each command at the right time, ‘while needed’. ClimbTower() { // this method gets called by ‘new ClimbTower()’. Within OI-init(). // Lift onto level-1 bar addSequential(new ClimbNextStep("lift-1", 1.0, 1800, 999, 150 )); addSequential(new WaitCommand( 1 )); // pause to stop swinging // Lift arms to level-2 bar (elbow towards 'up') addSequential(new ClimbNextStep("pre-up-1", .35, 3098, 999, 3550 ));// raise shoulder, addSequential(new ClimbNextStep("pre-up-2", .35, 3098, 1536, 3788 ));// straighten elbow addSequential(new ClimbNextStep("pre-up-3", .35, 2872, 1517, 3550 ));// swing shoulder forward addSequential(new ClimbNextStep("lift-2", 1.0, 1800, 999, 150 )); addSequential(new WaitCommand( 7 )); // WaitCommand is defined in .wpilib… // … then prepare for and lift onto level 3, it is similar steps as level-2 above, just different numbers…. Key Classes - Command Groups – ClimbTower code
Examples of Next-Step positions… addSequential(new ClimbNextStep("pre-up-1", lowPower, #, #, #...) addSequential(new ClimbNextStep("pre-up-3", lowPower, #, #, #... addSequential(new ClimbNextStep("lift-2", fullPower, #, #, # )); Key Classes - Command Groups – ClimbTower code
Glossary, Q&A • More or less complicated java key-words… package import public private protected new static final void (…and concepts) precision type-cast array scope • Time for