Class Turret
- All Implemented Interfaces:
Subsystem
Turret turret = Turret.create(hardwareMap, "turret")
.countsPerDegree(1479 / 360.0) // encoder counts per turret degree
.limits(-190, 190) // degrees; 0 = straight forward
.homeSwitch(hardwareMap, "turret_home", 45) // switch closes at 45 deg
.pid(0.02, 0, 0.001, 0)
.tolerance(1.0);
turret.aimAt(30); // robot-relative, counterclockwise +
turret.aimField(90, ImuSetup.headingDeg(imu)); // hold field direction 90 while driving
turret.aimBy(target.bearingDeg); // vision: turn by the target's bearing
Angles: 0 = robot forward, counterclockwise (left) is positive, like the IMU. Positive power
must turn the turret counterclockwise (use reversed() if not). The signs are in
docs/conventions.md.
The safe way round: with limits like -190..190 there can be two ways to reach an angle
(e.g. 170 and -190 are the same direction). The turret picks the one inside the limits closest to
where it is, and always moves there WITHOUT passing a limit. Asked for something outside the
limits, it goes to the nearest limit and isOutOfRange() turns true.
(Picture: docs/images/turret-limits.svg.)
Homing: with a home switch, the turret does not know its angle until the switch is
seen once. Call home(double) (it turns slowly until the switch). Without a switch, it
trusts startAngle(double) (the angle when the robot was turned on).
What turns it. A motor with its encoder (Turret(String, DcMotorEx)); a
continuous-rotation (CR) servo with any encoder (Turret(String, DoubleConsumer, DoubleSupplier):
a REV Through Bore on a motor port, or an absolute encoder read in degrees); or a standard servo that
goes to an angle by itself (servo(String, PositionServo): its angle is where it was sent, and
"arrived" is a time estimate). A slip ring lets it turn for ever: continuous().
Fence (fence(double, double)): a second, temporary range set every loop by the
robot's interlock rules (two parts that must not be in the same space). The turret never turns past
it; a target on the other side waits at its edge (isHeld()), or goes the other way round if
the range allows.
Like every helper, the aim commands only set a target; update() turns the motor, a little
every loop, using a PID controller (tutorial 07 explains PID). Tutorial 18 aims a turret with a camera.
Docs: docs/modules/launcher.md
-
Constructor Summary
ConstructorsConstructorDescriptionWraps a motor you already set up (brake, encoder reset).Turret(String name, DoubleConsumer power, DoubleSupplier counts) A turret turned by something that takes a power (a CR servo) with its angle from any encoder. -
Method Summary
Modifier and TypeMethodDescriptionvoidShows the angle and AIMED; warnings for faults, not homed, and out of range; the target in debug mode.voidOnly the warnings ofaddTelemetry(com.crossbotics.ftchelper.telemetry.RobotTelemetry)(a fault, not homed, a target out of range), for code that writes its own line for the turret (the robot module's Turret does).voidaimAt(double robotDeg) Turns to a robot-relative angle (0 = forward, counterclockwise +), the safe way round.booleanaimAtTarget(TargetObservation target, boolean cameraOnTurret) Aims at a camera target, safely: only a FRESH picture is used, and each picture only once (an old or repeated picture would push the turret further and further).voidaimBy(double deltaDeg) Turns BY an amount from where it is now.voidaimField(double fieldDeg, double headingCcwDeg) Points at a FIELD direction, whatever way the robot faces.aimStep(double robotDeg, double timeoutSec) A step (autonomous): turn to a robot-relative angle and wait until aimed (ortimeoutSec).cameraOffset(double deg) Where the target should sit in the camera's view when the LAUNCHER points straight at it, in degrees (positive = left of the camera's center), for a camera that is not centered on the launcher.Removes thefence(double, double).No limits: the turret can turn round and round (a slip ring carries its wires).countsPerDegree(double counts) Encoder counts per degree of TURRET rotation (motor counts x gear ratio / 360).static TurretGets the motor (brake, encoder reset, plain power) and wraps it.doubledegreesOutOfRange(double robotDeg) How far past its limits a direction is, degrees: 0 if the turret can point there (some equal angle, + or - 360, is inside the limits), otherwise how far it is from the nearest limit, measured around the circle.The encoder counts the other way (a separate encoder whose count goes down while the turret turns counterclockwise).fence(double lo, double hi) A temporary range inside the limits, set every loop by an interlock rule (see the robot module's Interlock): the turret does not turn past it.fence(double lo, double hi, double upPower, double downPower) fence(double, double), and the most power it may use toward each side now.doublegetAngle()The angle now (degrees, counterclockwise +).getFault()"" or a problem, e.g.doublegetMax()The upper limit, degrees (infinity whencontinuous()).doublegetMin()The lower limit, degrees (minus infinity whencontinuous()).double[]getSweep()The angles the turret may be at now, {lowest, highest}: for a motor or CR servo turret its angle (both the same), for a servo turret everything between where it was and where it is going until it should have arrived (it cannot say where it is).doubleThe angle it is going to (NaN if none).doubleThe tolerance, degrees:isAimed()is true within this of the target.doublegetAngle()as -180..180 (for acontinuous()turret, whose angle keeps counting).voidhome(double direction) Starts homing: turns slowly toward the switch until it closes.homeSwitch(com.qualcomm.robotcore.hardware.HardwareMap hardwareMap, String switchName, double angleDeg) A home switch by configuration name (touch sensor), closing atangleDeg.homeSwitch(BooleanSupplier isClosed, double angleDeg) A home switch read your own way (magnetic:() -> !channel.getState()).homingPower(double p) Power while homing, 0 to 1.homingTimeout(double seconds) Homing stops with a fault if the switch is not found within this many seconds.booleanisAimed()True when homed, holding a target that is REACHABLE (not out of range), and within the tolerance.booleanTrue aftercontinuous().booleanisHeld()True while the fence keeps it from its target (it waits at the fence's edge).booleanisHomed()True once the angle is known (switch seen, or there is no switch).booleanisHoming()True while turning slowly to find the home switch.booleanTrue if the last aim was outside the limits (it went to the nearest limit instead).booleanisServo()True for a servo turret (servo): its angle is where it was sent (an estimate while it moves).booleanTrue whilewaitWhileUnknown(boolean)holds it still (its angle not known, the rule says wait).limits(double min, double max) The allowed range, degrees.voidmanual(double power) Manual control (a stick), -1 to 1.Marks the angle as known now (homed), e.g.maxPower(double p) The most power it ever gets, 0 to 1.maxTargetAgeMs(double ms) aimAtTarget(com.crossbotics.ftchelper.vision.TargetObservation, boolean)ignores camera pictures older than this (milliseconds).name()The name shown in telemetry and in the hardware check.pid(double kP, double kI, double kD, double kF) PID gains (see docs/modules/control.md).reversed()Positive power turns the other way.static Turretservo(String name, PositionServo servo) A turret on a standard servo that goes to an angle by itself (no encoder, no PID, no homing).doubleA servo turret: the angle it counts from before its first command (startAngle(double), or the middle of its range when none was given).servoStickSec(double seconds) A servo turret: seconds for the stick to turn it across its whole range at full stick (default 0.5).slowZone(double deg, double powerAtLimit) Slow down withindegof a limit, down topowerAtLimit(0 to 1).startAngle(double deg) The turret's angle when the robot is turned on (used when there is no home switch).voidstop()Stops: no homing, no target, no power.tolerance(double deg) Aimed when within this many degrees.voidupdate()Once per loop: checks the home switch, picks the power (homing, stick or PID), applies the limits.waitWhileUnknown(boolean wait) Set every loop by an interlock rule: while true, a turret whose angle is not known yet (not homed, or a servo turret never sent anywhere) does not move at all: no homing (its time limit waits too), no stick, no first servo move.
-
Constructor Details
-
Turret
Wraps a motor you already set up (brake, encoder reset). -
Turret
A turret turned by something that takes a power (a CR servo) with its angle from any encoder.DcMotorEx encoderPort = hardwareMap.get(DcMotorEx.class, "turret_enc"); // a Through Bore on a motor port Turret t = new Turret("turret", crServo::setPower, encoderPort::getCurrentPosition) .countsPerDegree(8192 / 360.0).limits(-90, 90);- Parameters:
name- shown on the Driver Stationpower- where the power goes, -1 to 1 (+ = counterclockwise; seereversed())counts- the encoder now, in counts (any start:startAngle(double)sets which angle it is)
-
-
Method Details
-
create
Gets the motor (brake, encoder reset, plain power) and wraps it. -
servo
A turret on a standard servo that goes to an angle by itself (no encoder, no PID, no homing). The servo needs its angles set up (PositionServo.degrees(double, double, double, double)) and its travel time (for "arrived").PositionServo s = PositionServo.create(hardwareMap, "turret").degrees(0.1, -90, 0.9, 90).travelTime(0.6); Turret t = Turret.servo("turret", s).limits(-90, 90); -
isServo
public boolean isServo()True for a servo turret (servo): its angle is where it was sent (an estimate while it moves). -
reversed
Positive power turns the other way. Use it if positive power turns the turret clockwise. -
encoderReversed
The encoder counts the other way (a separate encoder whose count goes down while the turret turns counterclockwise). Not needed for a motor's own encoder (reversed()flips both). -
continuous
No limits: the turret can turn round and round (a slip ring carries its wires). It always takes the shortest way, and a direction is never "out of range". The angle keeps counting past 360 (getAngle());getWrappedAngle()gives it as -180..180. -
isContinuous
public boolean isContinuous()True aftercontinuous(). -
countsPerDegree
Encoder counts per degree of TURRET rotation (motor counts x gear ratio / 360). -
limits
The allowed range, degrees. May be wider than 360 total (e.g. -190..190). Endscontinuous(). -
getMin
public double getMin()The lower limit, degrees (minus infinity whencontinuous()). -
getMax
public double getMax()The upper limit, degrees (infinity whencontinuous()). -
fence
A temporary range inside the limits, set every loop by an interlock rule (see the robot module's Interlock): the turret does not turn past it. A target outside it goes the other way round if an equal direction (+ or - 360) is inside both the limits and the fence, else it waits at the fence's edge (isHeld()).fence(-inf, +inf)orclearFence()removes it.- Parameters:
lo- lowest allowed angle now, degreeshi- highest allowed angle now, degrees
-
fence
fence(double, double), and the most power it may use toward each side now. An interlock rule lowers these as the turret comes near its fence fast (and sets 0 to brake), so it stops before the edge instead of coasting past it.- Parameters:
lo- lowest allowed angle now, degreeshi- highest allowed angle now, degreesupPower- the most power counterclockwise (toward higher angles) now, 0 to 1 (1 = no cap)downPower- the most power clockwise now, 0 to 1
-
waitWhileUnknown
Set every loop by an interlock rule: while true, a turret whose angle is not known yet (not homed, or a servo turret never sent anywhere) does not move at all: no homing (its time limit waits too), no stick, no first servo move. From "anywhere" it could sweep through another part that is in its zone. Once its angle is known this does nothing (thefence(double, double)keeps it out).- Parameters:
wait- true = hold still while the angle is unknown- Returns:
- this turret
-
isWaitingUnknown
public boolean isWaitingUnknown()True whilewaitWhileUnknown(boolean)holds it still (its angle not known, the rule says wait). -
clearFence
Removes thefence(double, double). -
isHeld
public boolean isHeld()True while the fence keeps it from its target (it waits at the fence's edge). -
markHomed
Marks the angle as known now (homed), e.g. afterstartAngle(double)from a remembered angle. -
startAngle
The turret's angle when the robot is turned on (used when there is no home switch). Default 0. Call it aftercountsPerDegreeandreversed(), since it uses the encoder reading.A servo turret: where it counts from before its first command (a stick,
aimBy(double)). A servo says nothing about where it is, so send it there at START (aimAt(startAngle)) to make it true; without startAngle it counts from the middle of its range. -
homeSwitch
public Turret homeSwitch(com.qualcomm.robotcore.hardware.HardwareMap hardwareMap, String switchName, double angleDeg) A home switch by configuration name (touch sensor), closing atangleDeg. Skipped if missing. -
homeSwitch
A home switch read your own way (magnetic:() -> !channel.getState()).() -> ...is a small piece of code handed over to run later (here: every loop). -
homingPower
Power while homing, 0 to 1. Default 0.2. Also the most manual power before homing. -
homingTimeout
Homing stops with a fault if the switch is not found within this many seconds. Default 5. -
cameraOffset
Where the target should sit in the camera's view when the LAUNCHER points straight at it, in degrees (positive = left of the camera's center), for a camera that is not centered on the launcher. Used byaimAtTarget(com.crossbotics.ftchelper.vision.TargetObservation, boolean). Find it with the aim tuner. Default 0. -
maxTargetAgeMs
aimAtTarget(com.crossbotics.ftchelper.vision.TargetObservation, boolean)ignores camera pictures older than this (milliseconds). Default 150. -
pid
PID gains (see docs/modules/control.md). They work on degrees of error: kP = push harder the further off it points, kI = push more if it stays a little off, kD = calm it down when it turns fast (stops overshoot), kF = a steady extra push. -
tolerance
Aimed when within this many degrees. Default 1. -
maxPower
The most power it ever gets, 0 to 1. Default 0.8. -
slowZone
Slow down withindegof a limit, down topowerAtLimit(0 to 1). Default 10 deg, 0.25 power. -
aimAt
public void aimAt(double robotDeg) Turns to a robot-relative angle (0 = forward, counterclockwise +), the safe way round. -
aimField
public void aimField(double fieldDeg, double headingCcwDeg) Points at a FIELD direction, whatever way the robot faces. Call it every loop with the current heading so it keeps pointing there while the robot turns.- Parameters:
fieldDeg- field direction, counterclockwise from where heading 0 pointsheadingCcwDeg- the robot's IMU heading
-
aimBy
public void aimBy(double deltaDeg) Turns BY an amount from where it is now. For camera targets useaimAtTarget(com.crossbotics.ftchelper.vision.TargetObservation, boolean)instead. -
servoStartAngle
public double servoStartAngle()A servo turret: the angle it counts from before its first command (startAngle(double), or the middle of its range when none was given). Motor turrets: the same asgetAngle(). -
aimAtTarget
Aims at a camera target, safely: only a FRESH picture is used, and each picture only once (an old or repeated picture would push the turret further and further). No fresh target = the turret holds where it is.- Parameters:
target- fromcamera.target(...)(may be null)cameraOnTurret- true if the camera turns with the turret, false if it is on the robot body- Returns:
- true if this picture was used
-
manual
public void manual(double power) Manual control (a stick), -1 to 1. Limits apply once homed. Before homing the angle is not known, so manual power is kept to the homing power. 0 = hold where it is. -
home
public void home(double direction) Starts homing: turns slowly toward the switch until it closes.- Parameters:
direction- +1 = counterclockwise, -1 = clockwise (the way the switch is)
-
update
public void update()Once per loop: checks the home switch, picks the power (homing, stick or PID), applies the limits. -
servoStickSec
A servo turret: seconds for the stick to turn it across its whole range at full stick (default 0.5). -
stop
public void stop()Stops: no homing, no target, no power. It stays stopped until a new command. -
getAngle
public double getAngle()The angle now (degrees, counterclockwise +). Meaningless until homed. A servo turret: where it was sent, or part way there while it moves (an estimate); NaN before its first command. -
getWrappedAngle
public double getWrappedAngle()getAngle()as -180..180 (for acontinuous()turret, whose angle keeps counting). -
getSweep
public double[] getSweep()The angles the turret may be at now, {lowest, highest}: for a motor or CR servo turret its angle (both the same), for a servo turret everything between where it was and where it is going until it should have arrived (it cannot say where it is). Before a servo turret's first command: its whole range. Used by interlock rules. -
getTargetAngle
public double getTargetAngle()The angle it is going to (NaN if none). -
isAimed
public boolean isAimed()True when homed, holding a target that is REACHABLE (not out of range), and within the tolerance. Safe to use as a launcher ready check. -
getTolerance
public double getTolerance()The tolerance, degrees:isAimed()is true within this of the target. -
degreesOutOfRange
public double degreesOutOfRange(double robotDeg) How far past its limits a direction is, degrees: 0 if the turret can point there (some equal angle, + or - 360, is inside the limits), otherwise how far it is from the nearest limit, measured around the circle. Used to tell "just past the limit" from "behind the robot".- Parameters:
robotDeg- the direction, robot-relative, counterclockwise +
-
getFault
"" or a problem, e.g. "homing failed: switch not found". -
isOutOfRange
public boolean isOutOfRange()True if the last aim was outside the limits (it went to the nearest limit instead). -
isHomed
public boolean isHomed()True once the angle is known (switch seen, or there is no switch). -
isHoming
public boolean isHoming()True while turning slowly to find the home switch. -
name
Description copied from interface:SubsystemThe name shown in telemetry and in the hardware check. -
aimStep
A step (autonomous): turn to a robot-relative angle and wait until aimed (ortimeoutSec). -
addTelemetry
Shows the angle and AIMED; warnings for faults, not homed, and out of range; the target in debug mode.- Specified by:
addTelemetryin interfaceSubsystem
-
addWarnings
Only the warnings ofaddTelemetry(com.crossbotics.ftchelper.telemetry.RobotTelemetry)(a fault, not homed, a target out of range), for code that writes its own line for the turret (the robot module's Turret does).
-