Align to Tag
Hold a button and the robot lines up on a spot measured from one AprilTag. It never asks where it is on the field, so a wrong field pose cannot move the spot. You record the spot on each field before the event.
- Drive to Point. This lesson is the same call with a different pose.
- Vision, working on the real robot. There is no camera in the simulator.
- An AprilTag on a wall at scoring height, and room to drive two meters out from it.
Drive to Point arrives where the field pose says the spot is. If the pose is off by 10 cm, so is the robot. Scoring usually happens in front of one tag, and the camera can see that tag the whole way in. Measure the spot from that tag and the field pose drops out of the problem.
The tag map
The camera answers a few dozen times a second and late, and it loses the tag when the robot gets close. The wheels answer every loop. So each sighting puts the tag down once, in the same frame as drivetrain.getPose(). Between sightings the wheels say where the robot is from that spot.
samplePoseAt looks up where the robot was when the picture was taken. Adding the tag's offset from the robot to that pose places the tag. The call goes before the trust gates in addFrame, because one close tag is exactly the sighting those gates throw out.
// Where each tag sat in the drivetrain's pose frame the last time a camera saw it, by tag ID.private final Map<Integer, Pose2d> tagPoses = new HashMap<>(); private void rememberTags(LimelightResults frame, double timestampSeconds) { Optional<Pose2d> poseThen = drivetrain.samplePoseAt(timestampSeconds); if (poseThen.isEmpty()) { return; } for (FiducialTarget tag : frame.fiducialTargets) { Pose2d robotInTag = toTagFrame(tag.getRobotPose_TargetSpace()); // The tag's own origin, seen from the robot, added to where the robot was. Pose2d tagPose = poseThen.get().plus(new Transform2d(robotInTag, Pose2d.ZERO)); tagPoses.put(tag.fiducialId, tagPose); Telemetry.getTable("Vision").log("RobotInTag" + tag.fiducialId, robotInTag); }} public Optional<Pose2d> robotInTag(int tagId) { Pose2d tagPose = tagPoses.get(tagId); if (tagPose == null) { return Optional.empty(); } return Optional.of(drivetrain.getPose().relativeTo(tagPose));}The first line of addFrame gets the call, right after the MegaTag1 estimate: rememberTags(frame, estimate.timestampSeconds);. DriveMechanism gets a one-line samplePoseAt that passes the call to the drivetrain.
Record your spot
Do not measure the spot with a tape. Record it with the camera that will drive to it, and its mounting error goes into the number and back out again.
- Disable the robot and push it by hand to exactly where it should score, with the camera on the tag.
- Read
Vision/RobotInTag7in AdvantageScope or Elastic: X, Y and the heading in degrees. - Type them into the binding, converting the heading with
Rotation2d.fromDegrees(...), and deploy.
Record it again on the competition field at the event, before the first match. Field crews mount tags by hand, so no two fields match to the centimeter. A spot recorded on that field is right on that field.
Check your work
- Disabled, push the robot square to tag 7, about 1.5 m out, and read
Vision/RobotInTag7. Push it toward its own right, then turn it a little to the left. - Park the robot 2 to 3 m from the tag at an angle. Enable Teleop and hold X.
- Cover the camera, push the robot a meter sideways so the field pose is wrong, uncover it, and hold X again.
You should see
- About (1.5, 0, 180°) square on. Y growing as the robot moves to its right, and the heading wrapping from 180° to about −175° as it turns left.
- The robot drive to 1 m out and turn to face the tag, then stop on its own.
- The same stopping spot the second time, wrong field pose or not.
The command ends at once and nothing moves. No camera has seen that tag ID. Check the number on the tag and that Vision/RobotInTag7 is updating.
The first check reads the wrong way. A Y that shrinks as the robot moves right, or a heading that grows as it turns right, is a sign flipped in toTagFrame. Fix it there and run the first check again. Do not drive on it.
It stops a few centimeters off, the same way every time. The spot is off, not the code. Record it again with the robot parked where you want it.
Check yourself
The field pose is 20 cm wrong when the driver holds X. Where does the robot stop?
The camera loses the tag 40 cm from the spot. What happens?
How should a team get the numbers for spotInTag?
Why does rememberTags run before the trust gates in addFrame?
In the first check, Y shrinks as the robot is pushed toward its own right. What does that mean?