Added PacGoat code for C++.

Change-Id: I4fd19fbdc65c25c5bbcdce937a31bc6fa1c11cb4
This commit is contained in:
Alex Henning
2014-06-24 16:54:17 -07:00
parent 0d62d0985a
commit c7e17b8e35
47 changed files with 1659 additions and 4 deletions

View File

@@ -152,8 +152,8 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/src&quot;"/>
<listOptionValue builtIn="false" value="$cpp-location/sim/include"/>
<listOptionValue builtIn="false" value="/usr/include"/>
<listOptionValue builtIn="false" value="/usr/include/gazebo-2.2"/>
<listOptionValue builtIn="false" value="/usr/include/sdformat-1.4"/>
<listOptionValue builtIn="false" value="/usr/include/gazebo-3.0"/>
<listOptionValue builtIn="false" value="/usr/include/sdformat-2.0"/>
</option>
<option id="gnu.cpp.compiler.option.optimization.level.1648211502" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
<option id="gnu.cpp.compiler.option.debugging.level.937474733" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>

View File

@@ -0,0 +1,25 @@
#include "CheckForHotGoal.h"
#include "Robot.h"
CheckForHotGoal::CheckForHotGoal(double time) {
SetTimeout(time);
}
// Called just before this Command runs the first time
void CheckForHotGoal::Initialize() {}
// Called repeatedly when this Command is scheduled to run
void CheckForHotGoal::Execute() {}
// Make this return true when this Command no longer needs to run execute()
bool CheckForHotGoal::IsFinished() {
return IsTimedOut() || Robot::shooter->GoalIsHot();
}
// Called once after isFinished returns true
void CheckForHotGoal::End() {}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void CheckForHotGoal::Interrupted() {}

View File

@@ -0,0 +1,22 @@
#ifndef CheckForHotGoal_H
#define CheckForHotGoal_H
#include "WPILib.h"
/**
* This command looks for the hot goal and waits until it's detected or timed
* out. The timeout is because it's better to shoot and get some autonomous
* points than get none. When called sequentially, this command will block until
* the hot goal is detected or until it is timed out.
*/
class CheckForHotGoal : Command {
public:
CheckForHotGoal(double time);
void Initialize();
void Execute();
bool IsFinished();
void End();
void Interrupted();
};
#endif

View File

@@ -0,0 +1,27 @@
#include "CloseClaw.h"
#include "Robot.h"
CloseClaw::CloseClaw() {
Requires(Robot::collector);
}
// Called just before this Command runs the first time
void CloseClaw::Initialize() {
Robot::collector->Close();
}
// Called repeatedly when this Command is scheduled to run
void CloseClaw::Execute() {}
// Make this return true when this Command no longer needs to run execute()
bool CloseClaw::IsFinished() {
return true;
}
// Called once after isFinished returns true
void CloseClaw::End() {}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void CloseClaw::Interrupted() {}

View File

@@ -0,0 +1,22 @@
#ifndef CloseClaw_H
#define CloseClaw_H
#include "WPILib.h"
/**
* Close the claw.
*
* NOTE: It doesn't wait for the claw to close since there is no sensor to
* detect that.
*/
class CloseClaw: public Command {
public:
CloseClaw();
void Initialize();
void Execute();
bool IsFinished();
void End();
void Interrupted();
};
#endif

View File

@@ -0,0 +1,14 @@
#include "Collect.h"
#include "Robot.h"
#include "Commands/SetCollectionSpeed.h"
#include "Commands/CloseClaw.h"
#include "Commands/SetPivotSetpoint.h"
#include "Commands/WaitForBall.h"
Collect::Collect() {
AddSequential(new SetCollectionSpeed(Collector::FORWARD));
AddParallel(new CloseClaw());
AddSequential(new SetPivotSetpoint(Pivot::COLLECT));
AddSequential(new WaitForBall());
}

View File

@@ -0,0 +1,14 @@
#ifndef Collect_H
#define Collect_H
#include "WPILib.h"
/**
* Get the robot set to collect balls.
*/
class Collect: public CommandGroup {
public:
Collect();
};
#endif

View File

@@ -0,0 +1,20 @@
#include "DriveAndShootAutonomous.h"
#include "Robot.h"
#include "Commands/WaitForPressure.h"
#include "Commands/CloseClaw.h"
#include "Commands/SetPivotSetpoint.h"
#include "Commands/DriveForward.h"
#include "Commands/Shoot.h"
DriveAndShootAutonomous::DriveAndShootAutonomous() {
AddSequential(new WaitForPressure(), 2);
#ifdef REAL
// NOTE: Simulation doesn't currently have the concept of hot.
AddSequential(new CheckForHotGoal(2));
#endif
AddSequential(new CloseClaw());
AddSequential(new SetPivotSetpoint(45));
AddSequential(new DriveForward(8, 0.4));
AddSequential(new Shoot());
}

View File

@@ -0,0 +1,15 @@
#ifndef DriveAndShootAutonomous_H
#define DriveAndShootAutonomous_H
#include "WPILib.h"
/**
* Drive over the line and then shoot the ball. If the hot goal is not detected,
* it will wait briefly.
*/
class DriveAndShootAutonomous: public CommandGroup {
public:
DriveAndShootAutonomous();
};
#endif

View File

@@ -0,0 +1,55 @@
#include "DriveForward.h"
#include "Robot.h"
void DriveForward::init(double dist, double maxSpeed) {
Requires(Robot::drivetrain);
distance = dist;
driveForwardSpeed = maxSpeed;
error = 0;
}
DriveForward::DriveForward() {
init(10, 0.5);
}
DriveForward::DriveForward(double dist) {
init(dist, 0.5);
}
DriveForward::DriveForward(double dist, double maxSpeed) {
init(dist, maxSpeed);
}
// Called just before this Command runs the first time
void DriveForward::Initialize() {
Robot::drivetrain->GetRightEncoder()->Reset();
SetTimeout(2);
}
// Called repeatedly when this Command is scheduled to run
void DriveForward::Execute() {
error = (distance - Robot::drivetrain->GetRightEncoder()->GetDistance());
if (driveForwardSpeed * KP * error >= driveForwardSpeed) {
Robot::drivetrain->TankDrive(driveForwardSpeed, driveForwardSpeed);
} else {
Robot::drivetrain->TankDrive(driveForwardSpeed * KP * error,
driveForwardSpeed * KP * error);
}
}
// Make this return true when this Command no longer needs to run execute()
bool DriveForward::IsFinished() {
return (abs(error) <= TOLERANCE) || IsTimedOut();
}
// Called once after isFinished returns true
void DriveForward::End() {
Robot::drivetrain->Stop();
}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void DriveForward::Interrupted() {
End();
}

View File

@@ -0,0 +1,29 @@
#ifndef DriveForward_H
#define DriveForward_H
#include "WPILib.h"
/**
* This command drives the robot over a given distance with simple proportional
* control This command will drive a given distance limiting to a maximum speed.
*/
class DriveForward: public Command {
private:
double driveForwardSpeed;
double distance;
double error;
static const double TOLERANCE = .1;
static const double KP = -1.0 / 5.0;
void init(double dist, double maxSpeed);
public:
DriveForward();
DriveForward(double dist);
DriveForward(double dist, double maxSpeed);
void Initialize();
void Execute();
bool IsFinished();
void End();
void Interrupted();
};
#endif

View File

@@ -0,0 +1,31 @@
#include "DriveWithJoystick.h"
#include "Robot.h"
DriveWithJoystick::DriveWithJoystick() {
Requires(Robot::drivetrain);
}
// Called just before this Command runs the first time
void DriveWithJoystick::Initialize() {}
// Called repeatedly when this Command is scheduled to run
void DriveWithJoystick::Execute() {
Robot::drivetrain->TankDrive(Robot::oi->GetJoystick());
}
// Make this return true when this Command no longer needs to run execute()
bool DriveWithJoystick::IsFinished() {
return false;
}
// Called once after isFinished returns true
void DriveWithJoystick::End() {
Robot::drivetrain->Stop();
}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void DriveWithJoystick::Interrupted() {
End();
}

View File

@@ -0,0 +1,20 @@
#ifndef DriveWithJoystick_H
#define DriveWithJoystick_H
#include "WPILib.h"
/**
* This command allows PS3 joystick to drive the robot. It is always running
* except when interrupted by another command.
*/
class DriveWithJoystick: public Command {
public:
DriveWithJoystick();
void Initialize();
void Execute();
bool IsFinished();
void End();
void Interrupted();
};
#endif

View File

@@ -0,0 +1,32 @@
#include "ExtendShooter.h"
#include "Robot.h"
ExtendShooter::ExtendShooter() {
Requires(Robot::shooter);
SetTimeout(1);
}
// Called just before this Command runs the first time
void ExtendShooter::Initialize() {
Robot::shooter->ExtendBoth();
}
// Called repeatedly when this Command is scheduled to run
void ExtendShooter::Execute() {}
// Make this return true when this Command no longer needs to run execute()
bool ExtendShooter::IsFinished() {
return IsTimedOut();
}
// Called once after isFinished returns true
void ExtendShooter::End() {
Robot::shooter->RetractBoth();
}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void ExtendShooter::Interrupted() {
End();
}

View File

@@ -0,0 +1,19 @@
#ifndef ExtendShooter_H
#define ExtendShooter_H
#include "WPILib.h"
/**
* Extend the shooter and then retract it after a second.
*/
class ExtendShooter: public Command {
public:
ExtendShooter();
void Initialize();
void Execute();
bool IsFinished();
void End();
void Interrupted();
};
#endif

View File

@@ -0,0 +1,12 @@
#include "LowGoal.h"
#include "Robot.h"
#include "Commands/SetPivotSetpoint.h"
#include "Commands/SetCollectionSpeed.h"
#include "Commands/ExtendShooter.h"
LowGoal::LowGoal() {
AddSequential(new SetPivotSetpoint(Pivot::LOW_GOAL));
AddSequential(new SetCollectionSpeed(Collector::REVERSE));
AddSequential(new ExtendShooter());
}

View File

@@ -0,0 +1,14 @@
#ifndef LowGoal_H
#define LowGoal_H
#include "WPILib.h"
/**
* Spit the ball out into the low goal assuming that the robot is in front of it.
*/
class LowGoal: public CommandGroup {
public:
LowGoal();
};
#endif

View File

@@ -0,0 +1,27 @@
#include "OpenClaw.h"
#include "Robot.h"
OpenClaw::OpenClaw() {
Requires(Robot::collector);
}
// Called just before this Command runs the first time
void OpenClaw::Initialize() {
Robot::collector->Open();
}
// Called repeatedly when this Command is scheduled to run
void OpenClaw::Execute() {}
// Make this return true when this Command no longer needs to run execute()
bool OpenClaw::IsFinished() {
return Robot::collector->IsOpen();
}
// Called once after isFinished returns true
void OpenClaw::End() {}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void OpenClaw::Interrupted() {}

View File

@@ -0,0 +1,19 @@
#ifndef OpenClaw_H
#define OpenClaw_H
#include "WPILib.h"
/**
* Opens the claw
*/
class OpenClaw: public Command {
public:
OpenClaw();
void Initialize();
void Execute();
bool IsFinished();
void End();
void Interrupted();
};
#endif

View File

@@ -0,0 +1,28 @@
#include "SetCollectionSpeed.h"
#include "Robot.h"
SetCollectionSpeed::SetCollectionSpeed(double speed) {
Requires(Robot::collector);
this->speed = speed;
}
// Called just before this Command runs the first time
void SetCollectionSpeed::Initialize() {
Robot::collector->SetSpeed(speed);
}
// Called repeatedly when this Command is scheduled to run
void SetCollectionSpeed::Execute() {}
// Make this return true when this Command no longer needs to run execute()
bool SetCollectionSpeed::IsFinished() {
return true;
}
// Called once after isFinished returns true
void SetCollectionSpeed::End() {}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void SetCollectionSpeed::Interrupted() {}

View File

@@ -0,0 +1,23 @@
#ifndef SetCollectionSpeed_H
#define SetCollectionSpeed_H
#include "WPILib.h"
/**
* This command sets the collector rollers spinning at the given speed. Since
* there is no sensor for detecting speed, it finishes immediately. As a result,
* the spinners may still be adjusting their speed.
*/
class SetCollectionSpeed: public Command {
private:
double speed;
public:
SetCollectionSpeed(double speed);
void Initialize();
void Execute();
bool IsFinished();
void End();
void Interrupted();
};
#endif

View File

@@ -0,0 +1,30 @@
#include "SetPivotSetpoint.h"
#include "Robot.h"
SetPivotSetpoint::SetPivotSetpoint(double setpoint) {
this->setpoint = setpoint;
Requires(Robot::pivot);
}
// Called just before this Command runs the first time
void SetPivotSetpoint::Initialize() {
Robot::pivot->Enable();
Robot::pivot->SetSetpoint(setpoint);
}
// Called repeatedly when this Command is scheduled to run
void SetPivotSetpoint::Execute() {}
// Make this return true when this Command no longer needs to run execute()
bool SetPivotSetpoint::IsFinished()
{
return Robot::pivot->OnTarget();
}
// Called once after isFinished returns true
void SetPivotSetpoint::End() {}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void SetPivotSetpoint::Interrupted() {}

View File

@@ -0,0 +1,24 @@
#ifndef SetPivotSetpoint_H
#define SetPivotSetpoint_H
#include "WPILib.h"
/**
* Moves the pivot to a given angle. This command finishes when it is within
* the tolerance, but leaves the PID loop running to maintain the position.
* Other commands using the pivot should make sure they disable PID!
*/
class SetPivotSetpoint: public Command {
public:
SetPivotSetpoint(double setpoint);
void Initialize();
void Execute();
bool IsFinished();
void End();
void Interrupted();
private:
double setpoint;
};
#endif

View File

@@ -0,0 +1,14 @@
#include "Shoot.h"
#include "Robot.h"
#include "Commands/WaitForPressure.h"
#include "Commands/SetCollectionSpeed.h"
#include "Commands/OpenClaw.h"
#include "Commands/ExtendShooter.h"
Shoot::Shoot() {
AddSequential(new WaitForPressure());
AddSequential(new SetCollectionSpeed(Collector::STOP));
AddSequential(new OpenClaw());
AddSequential(new ExtendShooter());
}

View File

@@ -0,0 +1,14 @@
#ifndef Shoot_H
#define Shoot_H
#include "WPILib.h"
/**
* Shoot the ball at the current angle.
*/
class Shoot: public CommandGroup {
public:
Shoot();
};
#endif

View File

@@ -0,0 +1,26 @@
#include "WaitForBall.h"
#include "Robot.h"
WaitForBall::WaitForBall() {
Requires(Robot::collector);
}
// Called just before this Command runs the first time
void WaitForBall::Initialize() {}
// Called repeatedly when this Command is scheduled to run
void WaitForBall::Execute() {}
// Make this return true when this Command no longer needs to run execute()
bool WaitForBall::IsFinished()
{
return Robot::collector->HasBall();
}
// Called once after isFinished returns true
void WaitForBall::End() {}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void WaitForBall::Interrupted() {}

View File

@@ -0,0 +1,21 @@
#ifndef WaitForBall_H
#define WaitForBall_H
#include "WPILib.h"
/**
* Wait until the collector senses that it has the ball. This command does
* nothing and is intended to be used in command groups to wait for this
* condition.
*/
class WaitForBall: public Command {
public:
WaitForBall();
void Initialize();
void Execute();
bool IsFinished();
void End();
void Interrupted();
};
#endif

View File

@@ -0,0 +1,27 @@
#include "WaitForPressure.h"
#include "Robot.h"
WaitForPressure::WaitForPressure()
{
Requires(Robot::pneumatics);
}
// Called just before this Command runs the first time
void WaitForPressure::Initialize() {}
// Called repeatedly when this Command is scheduled to run
void WaitForPressure::Execute() {}
// Make this return true when this Command no longer needs to run execute()
bool WaitForPressure::IsFinished()
{
return Robot::pneumatics->IsPressurized();
}
// Called once after isFinished returns true
void WaitForPressure::End() {}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void WaitForPressure::Interrupted() {}

View File

@@ -0,0 +1,20 @@
#ifndef WaitForPressure_H
#define WaitForPressure_H
#include "WPILib.h"
/**
* Wait until the pneumatics are fully pressurized. This command does nothing
* and is intended to be used in command groups to wait for this condition.
*/
class WaitForPressure: public Command {
public:
WaitForPressure();
void Initialize();
void Execute();
bool IsFinished();
void End();
void Interrupted();
};
#endif

View File

@@ -0,0 +1,40 @@
#include "OI.h"
#include "Subsystems/Pivot.h"
#include "Subsystems/Collector.h"
#include "Commands/LowGoal.h"
#include "Commands/Collect.h"
#include "Commands/SetPivotSetpoint.h"
#include "Commands/Shoot.h"
#include "Commands/DriveForward.h"
#include "Commands/SetCollectionSpeed.h"
OI::OI() {
joystick = new Joystick(1);
R1 = new JoystickButton(joystick, 12);
R1->WhenPressed(new LowGoal());
R2 = new JoystickButton(joystick, 10);
R2->WhenPressed(new Collect());
L1 = new JoystickButton(joystick, 11);
L1->WhenPressed(new SetPivotSetpoint(Pivot::SHOOT));
L2 = new JoystickButton(joystick, 9);
L2->WhenPressed(new SetPivotSetpoint(Pivot::SHOOT_NEAR));
sticks = new DoubleButton(joystick, 2, 3);
sticks->WhenActive(new Shoot());
// SmartDashboard Buttons
SmartDashboard::PutData("Drive Forward", new DriveForward(2.25));
SmartDashboard::PutData("Drive Backward", new DriveForward(-2.25));
SmartDashboard::PutData("Start Rollers", new SetCollectionSpeed(Collector::FORWARD));
SmartDashboard::PutData("Stop Rollers", new SetCollectionSpeed(Collector::STOP));
SmartDashboard::PutData("Reverse Rollers", new SetCollectionSpeed(Collector::REVERSE));
}
Joystick* OI::GetJoystick() {
return joystick;
}

View File

@@ -0,0 +1,17 @@
#ifndef OI_H
#define OI_H
#include "WPILib.h"
#include "Triggers/DoubleButton.h"
class OI {
private:
Joystick* joystick;
JoystickButton *L1, *L2, *R1, *R2;
DoubleButton* sticks;
public:
OI();
Joystick* GetJoystick();
};
#endif

View File

@@ -0,0 +1,90 @@
#include "Robot.h"
#include "Commands/DriveAndShootAutonomous.h"
#include "Commands/DriveForward.h"
DriveTrain* Robot::drivetrain = NULL;
Pivot* Robot::pivot = NULL;
Collector* Robot::collector = NULL;
Shooter* Robot::shooter = NULL;
Pneumatics* Robot::pneumatics = NULL;
OI* Robot::oi = NULL;
void Robot::RobotInit() {
drivetrain = new DriveTrain();
pivot = new Pivot();
collector = new Collector();
shooter = new Shooter();
pneumatics = new Pneumatics();
// Show what command your subsystem is running on the SmartDashboard
SmartDashboard::PutData(drivetrain);
SmartDashboard::PutData(pivot);
SmartDashboard::PutData(collector);
SmartDashboard::PutData(shooter);
SmartDashboard::PutData(pneumatics);
oi = new OI();
autonomousCommand = new DriveAndShootAutonomous();
lw = LiveWindow::GetInstance();
// instantiate the command used for the autonomous period
autoChooser = new SendableChooser();
autoChooser->AddDefault("Drive and Shoot", new DriveAndShootAutonomous());
autoChooser->AddObject("Drive Forward", new DriveForward());
SmartDashboard::PutData("Auto Mode", autoChooser);
pneumatics->Start(); // Pressurize the pneumatics.
}
void Robot::AutonomousInit() {
autonomousCommand = (Command*) autoChooser->GetSelected();
autonomousCommand->Start();
}
void Robot::AutonomousPeriodic() {
Scheduler::GetInstance()->Run();
Log();
}
void Robot::TeleopInit() {
// This makes sure that the autonomous stops running when
// teleop starts running. If you want the autonomous to
// continue until interrupted by another command, remove
// this line or comment it out.
if (autonomousCommand != NULL) {
autonomousCommand->Cancel();
}
std::cout << "Starting Teleop" << std::endl;
}
void Robot::TeleopPeriodic() {
Scheduler::GetInstance()->Run();
Log();
}
void Robot::TestPeriodic() {
lw->Run();
}
void Robot::DisabledInit() {
shooter->Unlatch();
}
void Robot::DisabledPeriodic() {
Log();
}
/**
* Log interesting values to the SmartDashboard.
*/
void Robot::Log() {
Robot::pneumatics->WritePressure();
SmartDashboard::PutNumber("Pivot Pot Value", pivot->GetAngle());
SmartDashboard::PutNumber("Left Distance", drivetrain->GetLeftEncoder()->GetDistance());
SmartDashboard::PutNumber("Right Distance", drivetrain->GetRightEncoder()->GetDistance());
}
START_ROBOT_CLASS(Robot);

View File

@@ -0,0 +1,48 @@
/*
* Robot.h
*
* Created on: Jun 3, 2014
* Author: alex
*/
#ifndef MY_ROBOT_H_
#define MY_ROBOT_H_
#include "WPILib.h"
#include "Commands/Command.h"
#include "Subsystems/DriveTrain.h"
#include "Subsystems/Pivot.h"
#include "Subsystems/Collector.h"
#include "Subsystems/Shooter.h"
#include "Subsystems/Pneumatics.h"
#include "OI.h"
class Robot: public IterativeRobot {
public:
static DriveTrain* drivetrain;
static Pivot* pivot;
static Collector* collector;
static Shooter* shooter;
static Pneumatics* pneumatics;
static OI* oi;
private:
Command *autonomousCommand;
LiveWindow *lw;
SendableChooser* autoChooser;
void RobotInit();
void AutonomousInit();
void AutonomousPeriodic();
void TeleopInit();
void TeleopPeriodic();
void TestPeriodic();
void DisabledInit();
void DisabledPeriodic();
void Log();
};
#endif /* ROBOT_H_ */

View File

@@ -0,0 +1,43 @@
#include "Collector.h"
Collector::Collector() :
Subsystem("Collector")
{
// Configure devices
rollerMotor = new Victor(1, 6);
ballDetector = new DigitalInput(1, 10);
openDetector = new DigitalInput(1, 6);
piston = new Solenoid(1, 1);
// Put everything to the LiveWindow for testing.
// XXX: LiveWindow::GetInstance()->AddActuator("Collector", "Roller Motor", (Victor) rollerMotor);
LiveWindow::GetInstance()->AddSensor("Collector", "Ball Detector", ballDetector);
LiveWindow::GetInstance()->AddSensor("Collector", "Claw Open Detector", openDetector);
LiveWindow::GetInstance()->AddActuator("Collector", "Piston", piston);
}
bool Collector::HasBall() {
return ballDetector->Get(); // TODO: prepend ! to reflect real robot
}
void Collector::SetSpeed(double speed) {
rollerMotor->Set(-speed);
}
void Collector::Stop() {
rollerMotor->Set(0);
}
bool Collector::IsOpen() {
return openDetector->Get(); // TODO: prepend ! to reflect real robot
}
void Collector::Open() {
piston->Set(true);
}
void Collector::Close() {
piston->Set(false);
}
void Collector::InitDefaultCommand() {}

View File

@@ -0,0 +1,70 @@
#ifndef Collector_H
#define Collector_H
#include "Commands/Subsystem.h"
#include "WPILib.h"
/**
* The Collector subsystem has one motor for the rollers, a limit switch for ball
* detection, a piston for opening and closing the claw, and a reed switch to
* check if the piston is open.
*/
class Collector: public Subsystem
{
public:
// Constants for some useful speeds
static const double FORWARD = 1;
static const double STOP = 0;
static const double REVERSE = -1;
private:
// Subsystem devices
SpeedController* rollerMotor;
DigitalInput* ballDetector;
Solenoid* piston;
DigitalInput* openDetector;
public:
Collector();
/**
* NOTE: The current simulation model uses the the lower part of the claw
* since the limit switch wasn't exported. At some point, this will be
* updated.
*
* @return Whether or not the robot has the ball.
*/
bool HasBall();
/**
* @param speed The speed to spin the rollers.
*/
void SetSpeed(double speed);
/**
* Stop the rollers from spinning
*/
void Stop();
/**
* @return Whether or not the claw is open.
*/
bool IsOpen();
/**
* Open the claw up. (For shooting)
*/
void Open();
/**
* Close the claw. (For collecting and driving)
*/
void Close();
/**
* No default command.
*/
void InitDefaultCommand();
};
#endif

View File

@@ -0,0 +1,85 @@
#include "DriveTrain.h"
#include "Commands/DriveWithJoystick.h"
#define _USE_MATH_DEFINES
#include <math.h>
DriveTrain::DriveTrain() :
Subsystem("DriveTrain") {
// Configure drive motors
frontLeftCIM = new Victor(1, 1);
frontRightCIM = new Victor(1, 2);
backLeftCIM = new Victor(1, 3);
backRightCIM = new Victor(1, 4);
// XXX: LiveWindow::GetInstance()->AddActuator("DriveTrain", "Front Left CIM", (Victor) frontLeftCIM);
// XXX: LiveWindow::GetInstance()->AddActuator("DriveTrain", "Front Right CIM", (Victor) frontRightCIM);
// XXX: LiveWindow::GetInstance()->AddActuator("DriveTrain", "Back Left CIM", (Victor) backLeftCIM);
// XXX: LiveWindow::GetInstance()->AddActuator("DriveTrain", "Back Right CIM", (Victor) backRightCIM);
// Configure the RobotDrive to reflect the fact that all our motors are
// wired backwards and our drivers sensitivity preferences.
drive = new RobotDrive(frontLeftCIM, backLeftCIM, frontRightCIM, backRightCIM);
drive->SetSafetyEnabled(true);
drive->SetExpiration(0.1);
drive->SetSensitivity(0.5);
drive->SetMaxOutput(1.0);
drive->SetInvertedMotor(RobotDrive::kFrontLeftMotor, true);
drive->SetInvertedMotor(RobotDrive::kRearLeftMotor, true);
drive->SetInvertedMotor(RobotDrive::kFrontRightMotor, true);
drive->SetInvertedMotor(RobotDrive::kRearRightMotor, true);
// Configure encoders
rightEncoder = new Encoder(1, 1, 1, 2, true, Encoder::k4X);
leftEncoder = new Encoder(2, 5, 2, 6, false, Encoder::k4X);
rightEncoder->SetPIDSourceParameter(PIDSource::kDistance);
leftEncoder->SetPIDSourceParameter(PIDSource::kDistance);
#ifdef REAL
// Converts to feet
rightEncoder->SetDistancePerPulse(0.0785398);
leftEncoder->SetDistancePerPulse(0.0785398);
#else
// Convert to feet 4in diameter wheels with 360 tick simulated encoders
rightEncoder->SetDistancePerPulse((4.0/*in*/*M_PI)/(360.0*12.0/*in/ft*/));
leftEncoder->SetDistancePerPulse((4.0/*in*/*M_PI)/(360.0*12.0/*in/ft*/));
#endif
rightEncoder->Start();
leftEncoder->Start();
LiveWindow::GetInstance()->AddSensor("DriveTrain", "Right Encoder", rightEncoder);
LiveWindow::GetInstance()->AddSensor("DriveTrain", "Left Encoder", leftEncoder);
// Configure gyro
gyro = new Gyro(1, 2);
#ifdef REAL
gyro->SetSensitivity(0.007); // TODO: Handle more gracefully?
#endif
LiveWindow::GetInstance()->AddSensor("DriveTrain", "Gyro", gyro);
}
void DriveTrain::InitDefaultCommand() {
SetDefaultCommand(new DriveWithJoystick());
}
void DriveTrain::TankDrive(Joystick* joy) {
drive->TankDrive(joy->GetY(), joy->GetRawAxis(4));
}
void DriveTrain::TankDrive(double leftAxis, double rightAxis) {
drive->TankDrive(leftAxis, rightAxis);
}
void DriveTrain::Stop() {
drive->TankDrive(0.0, 0.0);
}
Encoder* DriveTrain::GetLeftEncoder() {
return leftEncoder;
}
Encoder* DriveTrain::GetRightEncoder() {
return rightEncoder;
}
double DriveTrain::GetAngle() {
return gyro->GetAngle();
}

View File

@@ -0,0 +1,62 @@
#ifndef DriveTrain_H
#define DriveTrain_H
#include "Commands/Subsystem.h"
#include "WPILib.h"
/**
* The DriveTrain subsystem controls the robot's chassis and reads in
* information about it's speed and position.
*/
class DriveTrain: public Subsystem
{
private:
// Subsystem devices
SpeedController *frontLeftCIM, *frontRightCIM;
SpeedController *backLeftCIM, *backRightCIM;
RobotDrive* drive;
Encoder *rightEncoder, *leftEncoder;
Gyro* gyro;
public:
DriveTrain();
/**
* When other commands aren't using the drivetrain, allow tank drive with
* the joystick.
*/
void InitDefaultCommand();
/**
* @param joy PS3 style joystick to use as the input for tank drive.
*/
void TankDrive(Joystick* joy);
/**
* @param leftAxis Left sides value
* @param rightAxis Right sides value
*/
void TankDrive(double leftAxis, double rightAxis);
/**
* Stop the drivetrain from moving.
*/
void Stop();
/**
* @return The encoder getting the distance and speed of left side of the drivetrain.
*/
Encoder* GetLeftEncoder();
/**
* @return The encoder getting the distance and speed of right side of the drivetrain.
*/
Encoder* GetRightEncoder();
/**
* @return The current angle of the drivetrain.
*/
double GetAngle();
};
#endif

View File

@@ -0,0 +1,53 @@
#include "Pivot.h"
Pivot::Pivot() :
PIDSubsystem("Pivot", 7.0, 0.0, 8.0)
{
SetAbsoluteTolerance(0.005);
GetPIDController()->SetContinuous(false);
#ifdef SIMULATION
// PID is different in simulation.
GetPIDController()->SetPID(0.5, 0.00001, 4.5);
SetAbsoluteTolerance(2.5);
#endif
// Motor to move the pivot.
motor = new Victor(5);
// Sensors for measuring the position of the pivot.
upperLimitSwitch = new DigitalInput(13);
lowerLimitSwitch = new DigitalInput(12);
// 0 degrees is vertical facing up.
// Angle increases the more forward the pivot goes.
pot = new AnalogPotentiometer(1);
// Put everything to the LiveWindow for testing.
LiveWindow::GetInstance()->AddSensor("Pivot", "Upper Limit Switch", upperLimitSwitch);
LiveWindow::GetInstance()->AddSensor("Pivot", "Lower Limit Switch", lowerLimitSwitch);
// XXX: LiveWindow::GetInstance()->AddSensor("Pivot", "Pot", (AnalogPotentiometer) pot);
// XXX: LiveWindow::GetInstance()->AddActuator("Pivot", "Motor", (Victor) motor);
LiveWindow::GetInstance()->AddActuator("Pivot", "PIDSubsystem Controller", GetPIDController());
}
void InitDefaultCommand() {}
double Pivot::ReturnPIDInput() {
return pot->Get();
}
void Pivot::UsePIDOutput(double output) {
motor->PIDWrite(output);
}
bool Pivot::IsAtUpperLimit() {
return upperLimitSwitch->Get(); // TODO: inverted from real robot (prefix with !)
}
bool Pivot::IsAtLowerLimit() {
return lowerLimitSwitch->Get(); // TODO: inverted from real robot (prefix with !)
}
double Pivot::GetAngle() {
return pot->Get();
}

View File

@@ -0,0 +1,61 @@
#ifndef Pivot_H
#define Pivot_H
#include "Commands/PIDSubsystem.h"
#include "WPILib.h"
/**
* The Pivot subsystem contains the Van-door motor and the pot for PID control
* of angle of the pivot and claw.
*/
class Pivot: public PIDSubsystem
{
public:
// Constants for some useful angles
static const double COLLECT = 105;
static const double LOW_GOAL = 90;
static const double SHOOT = 45;
static const double SHOOT_NEAR = 30;
private:
// Subsystem devices
DigitalInput* upperLimitSwitch;
DigitalInput* lowerLimitSwitch;
Potentiometer* pot;
SpeedController* motor;
public:
Pivot();
/**
* No default command, if PID is enabled, the current setpoint will be maintained.
*/
void InitDefaultCommand() {}
/**
* @return The angle read in by the potentiometer
*/
double ReturnPIDInput();
/**
* Set the motor speed based off of the PID output
*/
void UsePIDOutput(double output);
/**
* @return If the pivot is at its upper limit.
*/
bool IsAtUpperLimit();
/**
* @return If the pivot is at its lower limit.
*/
bool IsAtLowerLimit();
/**
* @return The current angle of the pivot.
*/
double GetAngle();
};
#endif

View File

@@ -0,0 +1,44 @@
#include "Pneumatics.h"
Pneumatics::Pneumatics() :
Subsystem("Pneumatics")
{
pressureSensor = new AnalogChannel(3);
#ifdef REAL
compressor = new Compressor(uint8_t(1)); // TODO: (1, 14, 1, 8);
#endif
LiveWindow::GetInstance()->AddSensor("Pneumatics", "Pressure Sensor", pressureSensor);
}
/**
* No default command
*/
void Pneumatics::InitDefaultCommand() {}
/**
* Start the compressor going. The compressor automatically starts and stops as it goes above and below maximum pressure.
*/
void Pneumatics::Start() {
#ifdef REAL
compressor->Start();
#endif
}
/**
* @return Whether or not the system is fully pressurized.
*/
bool Pneumatics::IsPressurized() {
#ifdef REAL
return MAX_PRESSURE <= pressureSensor->GetVoltage();
#else
return true; // NOTE: Simulation always has full pressure
#endif
}
/**
* Puts the pressure on the SmartDashboard.
*/
void Pneumatics::WritePressure() {
SmartDashboard::PutNumber("Pressure", pressureSensor->GetVoltage());
}

View File

@@ -0,0 +1,46 @@
#ifndef Pneumatics_H
#define Pneumatics_H
#include "Commands/Subsystem.h"
#include "WPILib.h"
/**
* The Pneumatics subsystem contains the compressor and a pressure sensor.
*
* NOTE: The simulator currently doesn't support the compressor or pressure sensors.
*/
class Pneumatics: public Subsystem
{
private:
AnalogChannel* pressureSensor;
#ifdef REAL
Compressor* compressor;
#endif
static const double MAX_PRESSURE = 2.55;
public:
Pneumatics();
/**
* No default command
*/
void InitDefaultCommand();
/**
* Start the compressor going. The compressor automatically starts and stops as it goes above and below maximum pressure.
*/
void Start();
/**
* @return Whether or not the system is fully pressurized.
*/
bool IsPressurized();
/**
* Puts the pressure on the SmartDashboard.
*/
void WritePressure();
};
#endif

View File

@@ -0,0 +1,88 @@
#include "Shooter.h"
Shooter::Shooter() :
Subsystem("Shooter")
{
// Configure Devices
hotGoalSensor = new DigitalInput(1, 3);
piston1 = new DoubleSolenoid(1, 3, 4);
piston2 = new DoubleSolenoid(1, 5, 6);
latchPiston = new Solenoid(1, 2);
piston1ReedSwitchFront = new DigitalInput(1, 9);
piston1ReedSwitchBack = new DigitalInput(1, 11);
// Put everything to the LiveWindow for testing.
LiveWindow::GetInstance()->AddSensor("Shooter", "Hot Goal Sensor", hotGoalSensor);
LiveWindow::GetInstance()->AddSensor("Shooter", "Piston1 Reed Switch Front ", piston1ReedSwitchFront);
LiveWindow::GetInstance()->AddSensor("Shooter", "Piston1 Reed Switch Back ", piston1ReedSwitchBack);
LiveWindow::GetInstance()->AddActuator("Shooter", "Latch Piston", latchPiston);
}
void Shooter::InitDefaultCommand()
{
// Set the default command for a subsystem here.
//SetDefaultCommand(new MySpecialCommand());
}
void Shooter::ExtendBoth() {
piston1->Set(DoubleSolenoid::kForward);
piston2->Set(DoubleSolenoid::kForward);
}
void Shooter::RetractBoth() {
piston1->Set(DoubleSolenoid::kReverse);
piston2->Set(DoubleSolenoid::kReverse);
}
void Shooter::Extend1() {
piston1->Set(DoubleSolenoid::kForward);
}
void Shooter::Retract1() {
piston1->Set(DoubleSolenoid::kReverse);
}
void Shooter::Extend2() {
piston2->Set(DoubleSolenoid::kReverse);
}
void Shooter::Retract2() {
piston2->Set(DoubleSolenoid::kForward);
}
void Shooter::Off1() {
piston1->Set(DoubleSolenoid::kOff);
}
void Shooter::Off2() {
piston2->Set(DoubleSolenoid::kOff);
}
void Shooter::Unlatch() {
latchPiston->Set(true);
}
void Shooter::Latch() {
latchPiston->Set(false);
}
void Shooter::ToggleLatchPosition() {
latchPiston->Set(!latchPiston->Get());
}
bool Shooter::Piston1IsExtended() {
return !piston1ReedSwitchFront->Get();
}
bool Shooter::Piston1IsRetracted() {
return !piston1ReedSwitchBack->Get();
}
void Shooter::OffBoth() {
piston1->Set(DoubleSolenoid::kOff);
piston2->Set(DoubleSolenoid::kOff);
}
bool Shooter::GoalIsHot() {
return hotGoalSensor->Get();
}

View File

@@ -0,0 +1,117 @@
#ifndef Shooter_H
#define Shooter_H
#include "Commands/Subsystem.h"
#include "WPILib.h"
/**
* The Shooter subsystem handles shooting. The mechanism for shooting is
* slightly complicated because it has to pneumatic cylinders for shooting, and
* a third latch to allow the pressure to partially build up and reduce the
* effect of the airflow. For shorter shots, when full power isn't needed, only
* one cylinder fires.
*
* NOTE: Simulation currently approximates this as as single pneumatic cylinder
* and ignores the latch.
*/
class Shooter: public Subsystem
{
private:
// Devices
DoubleSolenoid* piston1;
DoubleSolenoid* piston2;
Solenoid* latchPiston;
DigitalInput* piston1ReedSwitchFront;
DigitalInput* piston1ReedSwitchBack;
DigitalInput* hotGoalSensor; // NOTE: Currently ignored in simulation
public:
Shooter();
void InitDefaultCommand();
/**
* Extend both solenoids to shoot.
*/
void ExtendBoth();
/**
* Retract both solenoids to prepare to shoot.
*/
void RetractBoth();
/**
* Extend solenoid 1 to shoot.
*/
void Extend1();
/**
* Retract solenoid 1 to prepare to shoot.
*/
void Retract1();
/**
* Extend solenoid 2 to shoot.
*/
void Extend2();
/**
* Retract solenoid 2 to prepare to shoot.
*/
void Retract2();
/**
* Turns off the piston1 double solenoid. This won't actuate anything
* because double solenoids preserve their state when turned off. This
* should be called in order to reduce the amount of time that the coils are
* powered.
*/
void Off1();
/**
* Turns off the piston1 double solenoid. This won't actuate anything
* because double solenoids preserve their state when turned off. This
* should be called in order to reduce the amount of time that the coils are
* powered.
*/
void Off2();
/**
* Release the latch so that we can shoot
*/
void Unlatch();
/**
* Latch so that pressure can build up and we aren't limited by air flow.
*/
void Latch();
/**
* Toggles the latch postions
*/
void ToggleLatchPosition();
/**
* @return Whether or not piston 1 is fully extended.
*/
bool Piston1IsExtended();
/**
* @return Whether or not piston 1 is fully retracted.
*/
bool Piston1IsRetracted();
/**
* Turns off all double solenoids. Double solenoids hold their position when
* they are turned off. We should turn them off whenever possible to extend
* the life of the coils
*/
void OffBoth();
/**
* @return Whether or not the goal is hot as read by the banner sensor
*/
bool GoalIsHot();
};
#endif

View File

@@ -0,0 +1,19 @@
/*
* DoubleButton.cpp
*
* Created on: Jun 24, 2014
* Author: alex
*/
#include "DoubleButton.h"
DoubleButton::DoubleButton(Joystick* joy, int button1, int button2) {
this->joy = joy;
this->button1 = button1;
this->button2 = button2;
}
bool DoubleButton::Get() {
return joy->GetRawButton(button1) && joy->GetRawButton(button2);
}

View File

@@ -0,0 +1,24 @@
/*
* DoubleButton.h
*
* Created on: Jun 24, 2014
* Author: alex
*/
#ifndef DOUBLEBUTTON_H_
#define DOUBLEBUTTON_H_
#include "WPILib.h"
class DoubleButton : public Trigger {
private:
Joystick* joy;
int button1, button2;
public:
DoubleButton(Joystick* joy, int button1, int button2);
bool Get();
};
#endif /* DOUBLEBUTTON_H_ */

View File

@@ -137,6 +137,110 @@
destination="src/Subsystems/Wrist.h"></file>
</files>
</example>
<example>
<name>PacGoat</name>
<description>A fully functional example CommandBased program for FRC Team 190&#39;s 2014 robot. This code can run on your computer if it supports simulation.</description>
<tags>
<tag>CommandBased Robot</tag>
<tag>Simulation</tag>
<tag>2014 Season</tag>
</tags>
<packages>
<package>src</package>
<package>src/Commands</package>
<package>src/Subsystems</package>
<package>src/Triggers</package>
</packages>
<files>
<file source="examples/PacGoat/src/Commands/CheckForHotGoal.cpp"
destination="src/Commands/CheckForHotGoal.cpp"></file>
<file source="examples/PacGoat/src/Commands/CheckForHotGoal.h"
destination="src/Commands/CheckForHotGoal.h"></file>
<file source="examples/PacGoat/src/Commands/CloseClaw.cpp"
destination="src/Commands/CloseClaw.cpp"></file>
<file source="examples/PacGoat/src/Commands/CloseClaw.h"
destination="src/Commands/CloseClaw.h"></file>
<file source="examples/PacGoat/src/Commands/Collect.cpp"
destination="src/Commands/Collect.cpp"></file>
<file source="examples/PacGoat/src/Commands/Collect.h"
destination="src/Commands/Collect.h"></file>
<file source="examples/PacGoat/src/Commands/DriveAndShootAutonomous.cpp"
destination="src/Commands/DriveAndShootAutonomous.cpp"></file>
<file source="examples/PacGoat/src/Commands/DriveAndShootAutonomous.h"
destination="src/Commands/DriveAndShootAutonomous.h"></file>
<file source="examples/PacGoat/src/Commands/DriveForward.cpp"
destination="src/Commands/DriveForward.cpp"></file>
<file source="examples/PacGoat/src/Commands/DriveForward.h"
destination="src/Commands/DriveForward.h"></file>
<file source="examples/PacGoat/src/Commands/DriveWithJoystick.cpp"
destination="src/Commands/DriveWithJoystick.cpp"></file>
<file source="examples/PacGoat/src/Commands/DriveWithJoystick.h"
destination="src/Commands/DriveWithJoystick.h"></file>
<file source="examples/PacGoat/src/Commands/ExtendShooter.cpp"
destination="src/Commands/ExtendShooter.cpp"></file>
<file source="examples/PacGoat/src/Commands/ExtendShooter.h"
destination="src/Commands/ExtendShooter.h"></file>
<file source="examples/PacGoat/src/Commands/LowGoal.cpp"
destination="src/Commands/LowGoal.cpp"></file>
<file source="examples/PacGoat/src/Commands/LowGoal.h"
destination="src/Commands/LowGoal.h"></file>
<file source="examples/PacGoat/src/Commands/OpenClaw.cpp"
destination="src/Commands/OpenClaw.cpp"></file>
<file source="examples/PacGoat/src/Commands/OpenClaw.h"
destination="src/Commands/OpenClaw.h"></file>
<file source="examples/PacGoat/src/Commands/SetCollectionSpeed.cpp"
destination="src/Commands/SetCollectionSpeed.cpp"></file>
<file source="examples/PacGoat/src/Commands/SetCollectionSpeed.h"
destination="src/Commands/SetCollectionSpeed.h"></file>
<file source="examples/PacGoat/src/Commands/SetPivotSetpoint.cpp"
destination="src/Commands/SetPivotSetpoint.cpp"></file>
<file source="examples/PacGoat/src/Commands/SetPivotSetpoint.h"
destination="src/Commands/SetPivotSetpoint.h"></file>
<file source="examples/PacGoat/src/Commands/Shoot.cpp"
destination="src/Commands/Shoot.cpp"></file>
<file source="examples/PacGoat/src/Commands/Shoot.h"
destination="src/Commands/Shoot.h"></file>
<file source="examples/PacGoat/src/Commands/WaitForBall.cpp"
destination="src/Commands/WaitForBall.cpp"></file>
<file source="examples/PacGoat/src/Commands/WaitForBall.h"
destination="src/Commands/WaitForBall.h"></file>
<file source="examples/PacGoat/src/Commands/WaitForPressure.cpp"
destination="src/Commands/WaitForPressure.cpp"></file>
<file source="examples/PacGoat/src/Commands/WaitForPressure.h"
destination="src/Commands/WaitForPressure.h"></file>
<file source="examples/PacGoat/src/OI.cpp"
destination="src/OI.cpp"></file>
<file source="examples/PacGoat/src/OI.h"
destination="src/OI.h"></file>
<file source="examples/PacGoat/src/Robot.cpp"
destination="src/Robot.cpp"></file>
<file source="examples/PacGoat/src/Robot.h"
destination="src/Robot.h"></file>
<file source="examples/PacGoat/src/Subsystems/Collector.cpp"
destination="src/Subsystems/Collector.cpp"></file>
<file source="examples/PacGoat/src/Subsystems/Collector.h"
destination="src/Subsystems/Collector.h"></file>
<file source="examples/PacGoat/src/Subsystems/DriveTrain.cpp"
destination="src/Subsystems/DriveTrain.cpp"></file>
<file source="examples/PacGoat/src/Subsystems/DriveTrain.h"
destination="src/Subsystems/DriveTrain.h"></file>
<file source="examples/PacGoat/src/Subsystems/Pivot.cpp"
destination="src/Subsystems/Pivot.cpp"></file>
<file source="examples/PacGoat/src/Subsystems/Pivot.h"
destination="src/Subsystems/Pivot.h"></file>
<file source="examples/PacGoat/src/Subsystems/Pneumatics.cpp"
destination="src/Subsystems/Pneumatics.cpp"></file>
<file source="examples/PacGoat/src/Subsystems/Pneumatics.h"
destination="src/Subsystems/Pneumatics.h"></file>
<file source="examples/PacGoat/src/Subsystems/Shooter.cpp"
destination="src/Subsystems/Shooter.cpp"></file>
<file source="examples/PacGoat/src/Subsystems/Shooter.h"
destination="src/Subsystems/Shooter.h"></file>
<file source="examples/PacGoat/src/Triggers/DoubleButton.cpp"
destination="src/Triggers/DoubleButton.cpp"></file>
<file source="examples/PacGoat/src/Triggers/DoubleButton.h"
destination="src/Triggers/DoubleButton.h"></file>
</files>
</example>
</examples>