* Calculates shot parameters for SOTM using Physics™.
*
* @param robotVelocity The x and y velocity of the robot, field relative.
- * @param robot The position of the center of the robot, field relative.
- * @param target The position of the target, field relative.
+ * @param robotToTarget The robot to target transform. Angles are field
+ * relative, positions are with the robot as the origin.
* @param height The peak height the trajectory should reach.
* @return A TurretState that represents the shot the robot should take.
*/
- public static TurretState getShotParams(Translation2d robotVelocity, Translation2d robot, Translation3d target,
+ public static TurretState getShotParams(Translation2d robotVelocity, Translation3d robotToTarget,
double height) {
- Translation3d robotToTarget = target.minus(new Translation3d(robot));
Translation3d exitVel = getRequiredExitVelocity(robotVelocity, robotToTarget, height);
Translation2d onGround = exitVel.toTranslation2d();
return new TurretState(yaw, pitch, speed);
}
+ public static Optional<TurretState> getShotParamsBySpeed(Translation2d robotVelocity, Translation2d robot,
+ Translation3d target,
+ double speed) {
+ Translation3d robotToTarget = target.minus(new Translation3d(robot));
+ Optional<Translation3d> exitVelOpt = getExitVelocityForSpeed(robotVelocity, robotToTarget, speed);
+
+ if (exitVelOpt.isEmpty())
+ return Optional.empty();
+ Translation3d exitVel = exitVelOpt.get();
+
+ Translation2d onGround = exitVel.toTranslation2d();
+ Rotation2d yaw = onGround.getAngle();
+ double magnitude2d = onGround.getNorm();
+
+ double pitch = new Translation2d(magnitude2d, exitVel.getZ()).getAngle().getRadians();
+ pitch %= Math.PI * 2;
+ double speed2 = exitVel.getDistance(Translation3d.kZero);
+
+ return Optional.of(new TurretState(yaw, pitch, speed2));
+ }
+
/**
* Actually does the SOTM math. Assumes shots are from (0, 0, 0). This is only
* public so it can be unit tested, and shouldn't be called directly.
public static Optional<Translation3d> getExitVelocityForSpeed(Translation2d initialVelocity, Translation3d target,
double speed, double tolerance) {
- // TODO: detect when the given velocity is insufficient and exit before maxIters
+ // calculate minimum velocity: v² = g * (R + √(R² + h²))
+ double horizontalDist = target.toTranslation2d().getNorm();
+ double verticalDist = target.getZ();
+ double g = Constants.GRAVITY_ACCELERATION;
+ double robotSpeed = initialVelocity.getNorm();
+
+ double minProjectileSpeed = Math
+ .sqrt(g * (horizontalDist + Math.sqrt(horizontalDist * horizontalDist + verticalDist * verticalDist)));
+ double minSpeed = Math.max(0, minProjectileSpeed - robotSpeed);
+
+ if (speed < minSpeed - tolerance) {
+ return Optional.empty();
+ }
// guess a peak height
double guess = target.getZ() + 2;