-
Notifications
You must be signed in to change notification settings - Fork 0
Ls vision simulation #84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,63 @@ | ||
| package frc.robot.apriltags; | ||
|
|
||
| import edu.wpi.first.math.Vector; | ||
| import edu.wpi.first.math.geometry.*; | ||
| import edu.wpi.first.math.numbers.N3; | ||
| import frc.robot.constants.Constants; | ||
| import frc.robot.subsystems.ApriltagSubsystem; | ||
| import frc.robot.subsystems.swervedrive.vision.estimation.PoseEstimator; | ||
| import frc.robot.subsystems.swervedrive.vision.truster.BasicVisionFilter; | ||
| import frc.robot.subsystems.swervedrive.vision.truster.VisionMeasurement; | ||
| import frc.robot.subsystems.swervedrive.vision.truster.VisionTruster; | ||
| import frc.robot.utils.Apriltag; | ||
| import frc.robot.utils.logging.io.BaseIoImpl; | ||
|
|
||
| import java.util.Optional; | ||
| import java.util.Queue; | ||
| import java.util.Random; | ||
| import java.util.function.Supplier; | ||
|
|
||
| import frc.robot.utils.math.ObjectUtils; | ||
| import org.littletonrobotics.junction.Logger; | ||
|
|
||
| public class SimApriltagIO extends TCPApriltagIo { | ||
| public SimApriltagIO(String name, ApriltagInputs inputs, SimTCPServer server) { | ||
| private final Random random = new Random(); | ||
| private final VisionTruster truster; | ||
| private final Supplier<Optional<Pose2d>> robotPoseSupplier; | ||
| public SimApriltagIO(String name, ApriltagInputs inputs, SimTCPServer server, VisionTruster truster, Supplier<Optional<Pose2d>> robotPoseSupplier) { | ||
| super(name, inputs, server); | ||
| this.truster = truster; | ||
| this.robotPoseSupplier = robotPoseSupplier; | ||
| } | ||
| public void simReadings() { | ||
| if (robotPoseSupplier.get().isPresent()) { | ||
| for (Apriltag tag : Apriltag.values()) { | ||
| Pose3d cameraPos = new Pose3d(robotPoseSupplier.get().get()).transformBy(Constants.ROBOT_TO_CAMERA); | ||
| if (ObjectUtils.canSee(tag.getPose(), cameraPos, Constants.HORIZONTAL_FOV, Constants.VERTICAL_FOV)) { | ||
| Pose3d adjPose = tag.getPose().relativeTo(cameraPos); | ||
| double cosIncidenceAngle = (-adjPose.getX() * Math.cos(adjPose.getRotation().getZ()) - adjPose.getY() * Math.sin(adjPose.getRotation().getZ())) / (adjPose.getTranslation().getNorm()); | ||
| double distance = tag.getTranslation().getDistance(cameraPos.getTranslation()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what if the |
||
| if (distance / cosIncidenceAngle < Constants.MAX_VISION_DISTANCE_SIMULATION) { | ||
| VisionMeasurement measurement = new VisionMeasurement(new Pose2d(), distance, 0); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Calling |
||
| Vector<N3> stdDevs = truster.calculateTrust(measurement); | ||
| double readingX = robotPoseSupplier.get().get().getX() + random.nextGaussian() * stdDevs.get(0); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Calling |
||
| double readingY = robotPoseSupplier.get().get().getY() + random.nextGaussian() * stdDevs.get(1); | ||
| double readingYaw = robotPoseSupplier.get().get().getRotation().getDegrees() + random.nextGaussian() * stdDevs.get(2); | ||
| Pose2d readingPos = new Pose2d(readingX, readingY, Rotation2d.fromDegrees(readingYaw)); | ||
| distance = readingPos.getTranslation().getDistance(tag.getPose().toPose2d().getTranslation()); | ||
| if (BasicVisionFilter.inBounds(readingPos)) { | ||
| addReading(new ApriltagReading(readingX, readingY, readingYaw, | ||
| distance, tag.number(), Constants.AVERAGE_CAM_LATENCY + random.nextGaussian() * Constants.AVERAGE_CAM_LATENCY_STD_DEV, Logger.getTimestamp() / 1000.0)); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| @Override | ||
| public void periodic() { | ||
| updateInputs(inputs); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. call |
||
| Logger.processInputs(prefix, inputs); | ||
| simReadings(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| package frc.robot.commands.drive; | ||
|
|
||
| import edu.wpi.first.math.geometry.Translation2d; | ||
| import edu.wpi.first.wpilibj.Timer; | ||
| import frc.robot.subsystems.swervedrive.SwerveSubsystem; | ||
| import frc.robot.utils.logging.commands.LoggableCommand; | ||
|
|
||
| public class DriveCircle extends LoggableCommand { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this now that we can actually drive using simulation? |
||
| private final SwerveSubsystem drivebase; | ||
| private final double radiusMeters; | ||
| private final double angularVelocityRadPerSec; | ||
| private final double time; | ||
| private final Timer timer; | ||
| public DriveCircle(SwerveSubsystem drivebase, double radiusMeters, double angularVelocityRadPerSec, double time) { | ||
| this.drivebase = drivebase; | ||
| this.radiusMeters = radiusMeters; | ||
| this.angularVelocityRadPerSec = angularVelocityRadPerSec; | ||
| this.time = time; | ||
| this.timer = new Timer(); | ||
| addRequirements(drivebase); | ||
| } | ||
|
|
||
| @Override | ||
| public void initialize() { | ||
| timer.restart(); | ||
| } | ||
|
|
||
| @Override | ||
| public void execute() { | ||
| double tangentialSpeed = radiusMeters * angularVelocityRadPerSec; | ||
| double yVelocity = -tangentialSpeed; | ||
| drivebase.drive(new Translation2d(0, yVelocity), angularVelocityRadPerSec, false); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isFinished() { | ||
| return timer.hasElapsed(time); | ||
| } | ||
|
|
||
| @Override | ||
| public void end(boolean interrupted) { | ||
| drivebase.drive(new Translation2d(), 0, false); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,26 @@ | ||
| package frc.robot.subsystems; | ||
|
|
||
| import edu.wpi.first.math.VecBuilder; | ||
| import edu.wpi.first.math.Vector; | ||
| import edu.wpi.first.math.geometry.Pose2d; | ||
| import edu.wpi.first.math.geometry.Pose3d; | ||
| import edu.wpi.first.math.geometry.Rotation2d; | ||
| import edu.wpi.first.math.numbers.N3; | ||
| import edu.wpi.first.wpilibj2.command.SubsystemBase; | ||
| import frc.robot.apriltags.*; | ||
| import frc.robot.constants.Constants; | ||
| import frc.robot.subsystems.swervedrive.SwerveSubsystem; | ||
| import frc.robot.subsystems.swervedrive.vision.estimation.PoseEstimator; | ||
| import frc.robot.subsystems.swervedrive.vision.truster.BasicVisionFilter; | ||
| import frc.robot.subsystems.swervedrive.vision.truster.VisionMeasurement; | ||
| import frc.robot.subsystems.swervedrive.vision.truster.VisionTruster; | ||
| import frc.robot.utils.Apriltag; | ||
| import frc.robot.utils.logging.io.BaseIoImpl; | ||
| import frc.robot.utils.math.ObjectUtils; | ||
| import org.littletonrobotics.junction.Logger; | ||
|
|
||
| import java.util.Random; | ||
| import java.util.function.Supplier; | ||
|
|
||
| public class ApriltagSubsystem extends SubsystemBase { | ||
|
|
||
|
|
@@ -15,10 +29,11 @@ public class ApriltagSubsystem extends SubsystemBase { | |
| private final PoseEstimator estimator; | ||
| private final SwerveSubsystem drivebase; | ||
|
|
||
| public ApriltagSubsystem(ApriltagIO io, SwerveSubsystem drivebase) { | ||
|
|
||
| public ApriltagSubsystem(ApriltagIO io, SwerveSubsystem drivebase, VisionTruster truster) { | ||
| this.drivebase = drivebase; | ||
| this.io = io; | ||
| estimator = new PoseEstimator(drivebase.getKinematics(), drivebase, 0, this); | ||
| estimator = new PoseEstimator(drivebase.getKinematics(), drivebase, 0, this, truster); | ||
| } | ||
|
|
||
| public static ApriltagIO createRealIo() { | ||
|
|
@@ -30,8 +45,8 @@ public static ApriltagIO createMockIo() { | |
| return new MockApriltagIo(LOGGING_NAME, new ApriltagInputs()); | ||
| } | ||
|
|
||
| public static ApriltagIO createSimIo() { | ||
| return new SimApriltagIO(LOGGING_NAME, new ApriltagInputs(), new SimTCPServer(0)); // port doesnt matter at all | ||
| public static ApriltagIO createSimIo(VisionTruster truster, SwerveSubsystem drivebase) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you'd like to get rid of the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But then again, passing the truster into the AprilTagSubsystem is not a bad practice. |
||
| return new SimApriltagIO(LOGGING_NAME, new ApriltagInputs(), new SimTCPServer(0), truster, drivebase::getSimulationPose); // port doesnt matter at all | ||
| } | ||
| // This is used to inject april tag readings manually and will pretty much only be used for simulation. | ||
| public void addSimReading(ApriltagReading reading) { | ||
|
|
@@ -40,11 +55,16 @@ public void addSimReading(ApriltagReading reading) { | |
| public ApriltagIO getIO(){ | ||
| return io; | ||
| } | ||
|
|
||
| public VisionTruster getVisionTruster() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is not used? |
||
| return estimator.getVisionTruster(); | ||
| } | ||
| @Override | ||
| public void periodic() { | ||
| estimator.updateVision(); | ||
| estimator.updatePosition(drivebase.getOdom()); | ||
| io.periodic(); | ||
| } | ||
| public Vector<N3> calculateTrust(VisionMeasurement measurement) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is not used? |
||
| return estimator.getVisionTruster().calculateTrust(measurement); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |
| import frc.robot.subsystems.swervedrive.vision.truster.BasicVisionFilter; | ||
| import frc.robot.subsystems.swervedrive.vision.truster.ConstantVisionTruster; | ||
| import frc.robot.subsystems.swervedrive.vision.truster.VisionMeasurement; | ||
| import frc.robot.subsystems.swervedrive.vision.truster.VisionTruster; | ||
| import frc.robot.utils.Apriltag; | ||
| import frc.robot.utils.math.ArrayUtils; | ||
|
|
||
|
|
@@ -61,7 +62,8 @@ public PoseEstimator( | |
| SwerveDriveKinematics kinematics, | ||
| SwerveSubsystem drivebase, | ||
| double initGyroValueDeg, | ||
| ApriltagSubsystem apriltagSystem) { | ||
| ApriltagSubsystem apriltagSystem, | ||
| VisionTruster truster) { | ||
| /*this.frontLeft = frontLeftMotor; | ||
| this.frontRight = frontRightMotor; | ||
| this.backLeft = backLeftMotor; | ||
|
|
@@ -89,8 +91,7 @@ public PoseEstimator( | |
| public Pose2d getVisionPose(VisionMeasurement measurement) { | ||
| return measurement.measurement(); | ||
| } | ||
| }, | ||
| new ConstantVisionTruster(visionMeasurementStdDevs2)); | ||
| }, truster); | ||
| SmartDashboard.putData(field); | ||
| } | ||
|
|
||
|
|
@@ -144,7 +145,7 @@ private VisionMeasurement getVisionMeasurement(double[] pos, int index) { | |
| double serverTime = apriltagSystem.getIO().getInputs().serverTime[index]; | ||
| //double timestamp = 0; // latency is not right we are assuming zero | ||
| double timestamp = apriltagSystem.getIO().getInputs().timestamp[index]; | ||
| Pose2d visionPose = new Pose2d(pos[0], pos[1], getEstimatedPose().getRotation()); | ||
| Pose2d visionPose = new Pose2d(pos[0], pos[1], Rotation2d.fromDegrees(pos[2])); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is done on purpose to ignore the yaw from the camera since it is less accurate than the Gyro. So need to revert this change (and add a comment on why this is done this way) |
||
| double distanceFromTag = apriltagSystem.getIO().getInputs().distanceToTag[index]; | ||
| return new VisionMeasurement(visionPose, distanceFromTag, timestamp/1000); | ||
| } | ||
|
|
@@ -202,4 +203,7 @@ public void addMockVisionMeasurement() { | |
| poseManager.registerVisionMeasurement( | ||
| new VisionMeasurement(getEstimatedPose(), 0, Logger.getTimestamp() / 1e6)); | ||
| } | ||
| public VisionTruster getVisionTruster() { | ||
| return poseManager.getVisionTruster(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -79,7 +79,7 @@ private boolean filterVision(Pose2d m1Pose, Pose2d m2Pose, double m1Time, double | |
| return Math.abs(diff) <= Constants.VISION_CONSISTENCY_THRESHOLD; | ||
| } | ||
|
|
||
| private boolean inBounds(Pose2d pose2d) { | ||
| return pose2d.getX() > 0 && pose2d.getX() < 20 && pose2d.getY() > 0 && pose2d.getY() < 20; | ||
| public static boolean inBounds(Pose2d pose2d) { | ||
| return pose2d.getX() > 0 && pose2d.getX() < 16.5 && pose2d.getY() > 0 && pose2d.getY() < 8.1; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make constants for FIELD_LENGTH and FIELD_WIDTH |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be using this truster or the square one?