Skip to content

Ls shooting momentum adjust#116

Open
Levercpu wants to merge 11 commits intomainfrom
LS_Momentum_Adjust
Open

Ls shooting momentum adjust#116
Levercpu wants to merge 11 commits intomainfrom
LS_Momentum_Adjust

Conversation

@Levercpu
Copy link
Contributor

@Levercpu Levercpu commented Mar 15, 2026

Adjust the target position for flight time and robot velocities (and angular velocity too)

@Levercpu Levercpu changed the title Ls momentum adjust Ls shooting momentum adjust Mar 15, 2026
@Levercpu Levercpu marked this pull request as ready for review March 16, 2026 02:11
Copy link
Contributor

@batchen1 batchen1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall the math looks fine, but the devil is in the details. I'm not sure how to test this. Of course if you deploy and get perfect shots we declare victory, but what if not? do you have a plan how to diagnose any problems?


public static final Pose2d BLUE_HUB_POS = new Pose2d(4.6256, 4.0345, new Rotation2d());
public static final Pose2d RED_HUB_POS = new Pose2d(11.9154, 4.0345, new Rotation2d());
public static final Transform2d TURRET_OFFSET = new Transform2d(.4, .4, new Rotation2d());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these values were just placeholders, if you removed the comment, please measure and plug in the correct valued.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Twist2d momentumAdjustment = getMomentumAdjustment(robotPose,profile.targetPose, robotSpeeds,
equalizeFlightTime(calculateDistanceMeters(robotPose, profile.targetPose), robotPose, profile.targetPose, robotSpeeds));
PoseControlProfile adjustedProfile = new PoseControlProfile(profile.targetPose, profile.defaultAnglerAngleDegrees, profile.defaultShooterVelocityRpm, profile.defaultTurretAngleDegrees);
adjustedProfile.targetPose = profile.targetPose.exp(momentumAdjustment);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should change all the calls to use your adjustedProfile instead of profile.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

return 0.0633*computedDistanceMeters + 0.647;
}

private double equalizeFlightTime(double initialDistanceMeters, Pose2d robotPose, Pose2d target, ChassisSpeeds robotSpeeds) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how was this formula derived? you need to document it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 - I'm not convinced that the flight-time should depend on the speed of the robot at all. I think it is ok to calculate the flight time based only on the distance from the hub. I doubt that considering the speed our robot will be moving this will make a big difference. There are many things that affect the trajectory that we are not considering (physics related such as friction, drag, texture/compression of the fuel will be changing etc.) and this flight-time based only on distance is one that I'm willing to compromise. It will simplify testing by a lot.

2 - regardless - I'm not even sure this code is correct. What you want is the robot's velocity projected on the robot-to-hub directions. Is this what this expression is using? have you tried it with a few cases?

}

public Twist2d getMomentumAdjustment(Pose2d robotPose, Pose2d target, ChassisSpeeds robotSpeeds, double timeOfFlight) {
Translation2d angularVelocityAdjustment = Constants.TURRET_OFFSET.times(robotSpeeds.omegaRadiansPerSecond).getTranslation();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the angular velocity due to the offset from the middle of the robot complicates the code and not sure it will affect the shot that much, it may be easier to test without it. Can you add some option to remove it from the calculation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

ChassisSpeeds adjustSpeeds = (new ChassisSpeeds(robotSpeeds.vxMetersPerSecond, robotSpeeds.vyMetersPerSecond, 0)).plus
(ChassisSpeeds.fromRobotRelativeSpeeds(-angularVelocityAdjustment.getY(),angularVelocityAdjustment.getX(),0.0,robotPose.getRotation()));
return adjustSpeeds.toTwist2d(-timeOfFlight);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a suggestion for documenting this code:

Suggested change
}
// Twist2d is a change in pose (position and rotation) over time.
// the returned value is a field-relative displacement vector (change in position and rotation) over the ball flight time.
// this means how much we need to adjust our shot.
public Twist2d getMomentumAdjustment(Pose2d robotPose, Pose2d target, ChassisSpeeds robotSpeeds, double timeOfFlight) {
// calculate the change per second of the turret's position relative to the center due to robot rotation. This
// is basically angular speed. Result is in robot coordinate system.
Translation2d angularVelocityAdjustment = Constants.TURRET_OFFSET.times(robotSpeeds.omegaRadiansPerSecond).getTranslation();
// take the robot's current speed (relative to field)
// convert the turret's angular velocity from robot-relative to field-relative
// since the rotation velocity is perpendicular to the robot x-axis, so we need to rotate it by 90 degrees
// which is why we use -Y,X instead of X,Y for the conversion.
// add the two to get the effective speed of the turret/projectile.
ChassisSpeeds adjustSpeeds = (new ChassisSpeeds(robotSpeeds.vxMetersPerSecond, robotSpeeds.vyMetersPerSecond, 0)).plus
(ChassisSpeeds.fromRobotRelativeSpeeds(-angularVelocityAdjustment.getY(),angularVelocityAdjustment.getX(),0.0,robotPose.getRotation()));
// convert the effective speed to a twist (displacement over time)
// positive timeOfFlight tells us how much we move
// negative timeOfFlight tells us how much we need to move to compensate for our movement
return adjustSpeeds.toTwist2d(-timeOfFlight);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@Levercpu
Copy link
Contributor Author

overall the math looks fine, but the devil is in the details. I'm not sure how to test this. Of course if you deploy and get perfect shots we declare victory, but what if not? do you have a plan how to diagnose any problems?

My idea is to do a Logger.recordOutput(adjustProfile.targetPose) and then look at how it changes on advantage scope as you drive around and see if it makes sense. That should (hopefully) be enough before we start testing. The one problem is that hardware seems to be unconvinced with the mathematical/physics equations I implemented. I also need Jackson's true position/delayed pose estimate adjustment branch merged in.

@Levercpu Levercpu requested a review from batchen1 March 17, 2026 00:42
@batchen1
Copy link
Contributor

I think your math is sound and this is the way to go. If hardware is skeptical of the math/physics, just add an option to disable the adjustment completely then they can shoot while not moving.
I'm not sure why you need Jackson's branch, can you explain?
I will review your changed later tonight, but I don't want it merged to main until it is tested. If you can test in simulation and compare the adjusted Angle to the unadjusted angle that should at least show if there are any major issues with the math.

}

private double calculateAnglerAngleDegrees(double computedDistanceMeters, PoseControlProfile profile) {
if ((profile == BLUE_HUB_PROFILE) || (profile == RED_HUB_PROFILE)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this condition will now always evaluate to false, the adjusted profile is a new object and the == will always fail. Just pass the color as an additional parm.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

.getTranslation().getAngle()).vxMetersPerSecond+1);
}
private double calculateShooterVelocity(double computedDistanceMeters, PoseControlProfile profile) {
if ((profile == BLUE_HUB_PROFILE) || (profile == RED_HUB_PROFILE)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as the calculateAnglerAngle.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

return 0.0633*computedDistanceMeters + 0.647;
}

private double equalizeFlightTime(double initialDistanceMeters, Pose2d robotPose, Pose2d target, ChassisSpeeds robotSpeeds) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 - I'm not convinced that the flight-time should depend on the speed of the robot at all. I think it is ok to calculate the flight time based only on the distance from the hub. I doubt that considering the speed our robot will be moving this will make a big difference. There are many things that affect the trajectory that we are not considering (physics related such as friction, drag, texture/compression of the fuel will be changing etc.) and this flight-time based only on distance is one that I'm willing to compromise. It will simplify testing by a lot.

2 - regardless - I'm not even sure this code is correct. What you want is the robot's velocity projected on the robot-to-hub directions. Is this what this expression is using? have you tried it with a few cases?

@Levercpu
Copy link
Contributor Author

Response to last comment.

  1. Well I more meant since we are pretending we are in a static problem where we are aiming towards a setPoint d-V_R*t away instead of d, thus since the setPoint varies with time of flight, and the distance to this "fake" static point varies with the velocity of the robot, the time of flight will depend on the robot velocity. At least thats my understanding might be wrong.
  2. It was wrong earlier but I fixed it in latest update
  3. Have to remove the random test logging I added.

@Levercpu Levercpu requested a review from batchen1 March 18, 2026 02:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants