Class Hood
- All Implemented Interfaces:
Subsystem
Launcher, the hood angle comes from the shot table's third column (blended between rows, like
the speed), and the launcher waits for the hood to arrive before it feeds. It works for any hood
design: a standard servo or a motor with an encoder, a straight gear or a linkage, any range, either
direction.
launcher = add(Launcher.flywheel("launcher", "gobilda-5203-6000").feeder(Indexer.servo("indexer"))
.hood(Hood.servo("hood")) // or Hood.motor("hood", "gobilda-5203-117")
.speedFromDistance(camera));
public static class Hood { // Tunables.java
public static double posA = 0.20, posB = 0.65; // servo positions at the two hard stops (Hood Finder)
public static double angleA = 0, angleB = 25; // optional: the hood's angle there (degrees)
public static double travelSec = 0.5; // stop to stop, seconds (a servo cannot say where it is)
}
public static class Launcher {
public static double[][] speedByDistance = {{24, 2200, 4}, {48, 2550, 12}, {72, 2900, 18}}; // in, rpm, hood
}
Calibration. posA and posB are where the hood touches (a hair off) its two
hard stops: servo positions 0 to 1, or encoder ticks for Hood.motor. They are the HARD LIMITS:
every angle (a table row, a trim, a stick) is kept between them, so it never pushes on a stop. Both
are needed (a safety number never comes from a library default); the Hood Finder finds them.
- With
angleA,angleB: you work in the hood's angle (any scale, either way round), on a straight line between the two stops. - Without them: the "angle" IS the servo position (or tick count). The shot table's hood column
then holds positions (
{48, 2550, 0.42}). Fine if you never measure angles. - A linkage or cam is not a straight line:
calibration = {{0.20, 0}, {0.35, 8}, {0.50, 17}, {0.65, 25}}({position, angle} rows, from the Hood Finder) is blended between rows instead. Its first and last rows are then the hard limits (posA/posBare not used).
Ready. A motor hood is ready when its encoder says it is within tolerance. A servo
cannot say where it is, so a servo hood's "arrived" is a time estimate: travelSec for the whole
range, less for a shorter move (time a stop-to-stop move to measure it).
By hand. Suggested operator stick: left stick Y (up = a bigger angle). While the shot table
sets the angle it is a hood TRIM (added to the table, at most +/- trimMax; back to 0 with the
launcher's double-tap D-pad down); otherwise it moves the hood. Your own buttons: step(int),
setAngle(double), goToStart().
Optional Tunables (defaults scale with the range, so they suit degrees, positions and ticks):
startAngle (where it goes at START; default angleA), stepAngle (1/25 of the range),
byHandPerSec (the range in 2.5 s), trimMax (1/5 of the range). A motor hood:
kP (0.005 power per tick), maxPower (0.5), tolerance (1/50 of the range). Its
encoder counts from where it is at INIT: start the robot with the hood at the stop you call 0 ticks.
Nothing moves in INIT: the hood goes to startAngle at START.
Docs: docs/modules/robot.md (section "Hood"), lesson 9 (docs/tutorials/start/09-shooter-and-camera.md)
-
Method Summary
Modifier and TypeMethodDescriptionvoidThe part's telemetry line; each module adds its own.doubleangle()Where the hood is now: measured (a motor) or estimated from the time (a servo), likeTurret.angle().voidbyHand(double amount) By hand from a stick, every loop: -1 to 1 (up = a bigger angle),byHandPerSecat full push.booleanTrue while the angle comes from the shot table (the launcher's distance), false when it is set by hand.A servo hood uses its servo's whole turn: positions 0 to 1 send the servo's full pulse range (the part's, else 500-2500 us) instead of the FTC SDK's normal 600-2400 us.voidBack tostartAngle(Tunables): where it went at START.booleanTrue when the hood is (a motor) or should be (a servo, by time) at its target angle.booleanisMotor()True forHood.motor, false forHood.servo.booleanTrue when Robot.java saysreversed().doublemaxAngle()The biggest angle it may go to (a hard limit).doubleminAngle()The smallest angle it may go to (a hard limit).static HoodA hood on a motor with an encoder: it knows where the hood really is.part()The hood as anAngleDevice(what the launcher drives), for anything this module does not offer.double[]The pulse range (microseconds, {low, high}) its servo gets at INIT withfullRange(), or null for the SDK's normal range.voidThe hood trim back to 0 (the launcher's double-tap D-pad down does this too).reversed()It turns the other way.static HoodA hood on a standard (positional) servo.voidsetAngle(double angle) Sends the hood to this angle (kept inside its hard limits).voidsetTrim(double amount) Sets the hood trim (0 = none), kept to +/-trimMax.shotAngles(double atA, double atB) For the simulator only: the launcher's shot angle (as inLauncher.shotAngle: degrees up from the wheel shape's forward) with the hood atangleAand atangleB.doubleTunablesstartAngle: where it goes at START (default angleA).voidstep(int steps) One step per count (stepAngle): +1 = a bigger angle, -1 = smaller.voidstop()Stops all motion.doubleThe angle the hood is going to (or is at); NaN before its first move (START).doubletrim()The hood trim now (0 = none), in the hood's scale.voidtrimBy(double amount) Adds to the hood trim (added to the shot table's angle), kept to +/-trimMax.voidupdate()Called once every loop.booleanTrue with angleA/angleB or a calibration table (real angles); false when the angle is the position.
-
Method Details
-
servo
A hood on a standard (positional) servo. Its Tunables section is the name in CamelCase ("hood" ->Hood).- Parameters:
servo- the servo's configuration name
-
motor
A hood on a motor with an encoder: it knows where the hood really is.posA,posB(and calibration rows) are then encoder ticks, counted from where the hood is at INIT.- Parameters:
motor- the motor's configuration namemotorId- the motor's parts-catalog id (seeMotors), e.g. "gobilda-5203-117"
-
fullRange
A servo hood uses its servo's whole turn: positions 0 to 1 send the servo's full pulse range (the part's, else 500-2500 us) instead of the FTC SDK's normal 600-2400 us. A goBILDA 2000 servo then turns 300 degrees instead of 270. Turn it on BEFORE the Hood Finder (it uses the same range), or find posA and posB again: the same position points somewhere else after the change.- Returns:
- this hood
- Throws:
IllegalStateException- on a motor hood (it has no servo)
-
pulseRangeUs
public double[] pulseRangeUs()The pulse range (microseconds, {low, high}) its servo gets at INIT withfullRange(), or null for the SDK's normal range. The Hood Finder uses the same one. -
reversed
It turns the other way. The Hood Finder's numbers are for the hood as set up here. -
shotAngles
For the simulator only: the launcher's shot angle (as inLauncher.shotAngle: degrees up from the wheel shape's forward) with the hood atangleAand atangleB. The simulated shot then leaves steeper or flatter as the hood moves (on a straight line between the two).- Parameters:
atA- the shot angle with the hood at angleA (posA), e.g. 80atB- the shot angle with the hood at angleB (posB), e.g. 55
-
setAngle
public void setAngle(double angle) Sends the hood to this angle (kept inside its hard limits). While the shot table sets the angle, the table sets it again at the next loop: usetrimBy(double)then.- Parameters:
angle- the hood angle, in your scale (degrees, or the position without angleA/angleB)
-
goToStart
public void goToStart()Back tostartAngle(Tunables): where it went at START. -
step
public void step(int steps) One step per count (stepAngle): +1 = a bigger angle, -1 = smaller. While the shot table sets the angle it changes the hood trim; else it moves the hood. For your own buttons:g2.y.press(() -> robot.launcher.hood().step(+1)).- Parameters:
steps- e.g. +1 or -1
-
byHand
public void byHand(double amount) By hand from a stick, every loop: -1 to 1 (up = a bigger angle),byHandPerSecat full push. While the shot table sets the angle it moves the hood trim; else the hood. 0 does nothing.- Parameters:
amount- the stick, -1 to 1
-
trimBy
public void trimBy(double amount) Adds to the hood trim (added to the shot table's angle), kept to +/-trimMax. Starts at 0 at every INIT. Only used while the angle comes from the shot table.- Parameters:
amount- e.g. +1 (degree) or -0.5
-
setTrim
public void setTrim(double amount) Sets the hood trim (0 = none), kept to +/-trimMax. -
resetTrim
public void resetTrim()The hood trim back to 0 (the launcher's double-tap D-pad down does this too). -
trim
public double trim()The hood trim now (0 = none), in the hood's scale. -
angle
public double angle()Where the hood is now: measured (a motor) or estimated from the time (a servo), likeTurret.angle(). NaN before its first move (START). -
targetAngle
public double targetAngle()The angle the hood is going to (or is at); NaN before its first move (START). -
isAtTarget
public boolean isAtTarget()True when the hood is (a motor) or should be (a servo, by time) at its target angle. -
followsTable
public boolean followsTable()True while the angle comes from the shot table (the launcher's distance), false when it is set by hand. -
minAngle
public double minAngle()The smallest angle it may go to (a hard limit). NaN before INIT. -
maxAngle
public double maxAngle()The biggest angle it may go to (a hard limit). NaN before INIT. -
startAngle
public double startAngle()TunablesstartAngle: where it goes at START (default angleA). NaN before INIT. -
usesAngles
public boolean usesAngles()True with angleA/angleB or a calibration table (real angles); false when the angle is the position. -
isMotor
public boolean isMotor()True forHood.motor, false forHood.servo. -
isReversed
public boolean isReversed()True when Robot.java saysreversed(). -
part
The hood as anAngleDevice(what the launcher drives), for anything this module does not offer. -
update
public void update()Description copied from interface:SubsystemCalled once every loop. Do the hardware work here. Must be quick: no sleep, no waiting. While update() waits, the whole robot is frozen (no driving, no limits, no STOP). -
stop
public void stop()Description copied from interface:SubsystemStops all motion. Called at the end of every OpMode. -
addTelemetry
Description copied from class:ModuleThe part's telemetry line; each module adds its own.- Specified by:
addTelemetryin interfaceSubsystem- Overrides:
addTelemetryin classModule<Hood>
-