Closed nash-pillai closed 9 months ago
Does the same thing happen if the velocity is much lower? Can you link a robot log?
It continued to happen even when we lowered to:
public double maxWheelVel = 20;
public double minProfileAccel = -10;
public double maxProfileAccel = 10;
I can send robot logs tomorrow
robotControllerLog.txt 2024_01_28__17_30_28_038__MenuAuto.log
I think these are the files you are looking for. Let me know if you want something else
I had to stop the opmode in the middle because it would have hit the edge of the field. If you need it to run all the way, we can remove the trusses and run it again on a clear field
Yup, the second one is the log I need, thanks. Here's a summary of its contents
THREE_DEAD_WHEEL_PARAMS
par0YTicks: -962.0
par1YTicks: 912.0
perpXTicks: -2133.0
MECANUM_PARAMS
axialGain: 0.0
axialVelGain: 0.0
headingGain: 4.32
headingVelGain: 0.59
inPerTick: 0.0030135610246107484
kA: 1e-06
kS: 0.9589658474985132
kV: 0.0005588422234744558
lateralGain: 0.0
lateralInPerTick: 0.00018869762188191035
lateralVelGain: 0.0
logoFacingDirection: UP
maxAngAccel: 3.141592653589793
maxAngVel: 3.141592653589793
maxProfileAccel: 20.0
maxWheelVel: 40.0
minProfileAccel: -20.0
trackWidthTicks: 4432.299
usbFacingDirection: RIGHT
Channel Messages Hz
TARGET_POSE 61 20.01
ESTIMATED_POSE 62 20.23
DRIVE_COMMAND 62 20.26
MECANUM_COMMAND 62 20.92
Right off the bat, lateralInPerTick
seems very suspicious. It should be at most like 25% less than inPerTick
and not an order of magnitude off. Can you try tuning that again and sharing the results here (including the JSON)?
Thank you so much! I'm not how we messed it up in the first place, but re-tuning lateralInPerTick fixed our problems
RR FTC Version
0.1.11
Observed Behavior
Strafing while turning and strafing at a diagonal goes in the wrong direction, but the robot knows where it is
The code we are running:
Tuning Files
MecanumDrive.java:
```java package org.firstinspires.ftc.teamcode; import androidx.annotation.NonNull; import com.acmerobotics.dashboard.canvas.Canvas; import com.acmerobotics.dashboard.config.Config; import com.acmerobotics.dashboard.telemetry.TelemetryPacket; import com.acmerobotics.roadrunner.AccelConstraint; import com.acmerobotics.roadrunner.Action; import com.acmerobotics.roadrunner.Actions; import com.acmerobotics.roadrunner.AngularVelConstraint; import com.acmerobotics.roadrunner.DualNum; import com.acmerobotics.roadrunner.HolonomicController; import com.acmerobotics.roadrunner.MecanumKinematics; import com.acmerobotics.roadrunner.MinVelConstraint; import com.acmerobotics.roadrunner.MotorFeedforward; import com.acmerobotics.roadrunner.Pose2d; import com.acmerobotics.roadrunner.Pose2dDual; import com.acmerobotics.roadrunner.PoseVelocity2d; import com.acmerobotics.roadrunner.PoseVelocity2dDual; import com.acmerobotics.roadrunner.ProfileAccelConstraint; import com.acmerobotics.roadrunner.Rotation2d; import com.acmerobotics.roadrunner.Time; import com.acmerobotics.roadrunner.TimeTrajectory; import com.acmerobotics.roadrunner.TimeTurn; import com.acmerobotics.roadrunner.TrajectoryActionBuilder; import com.acmerobotics.roadrunner.TurnConstraints; import com.acmerobotics.roadrunner.Twist2dDual; import com.acmerobotics.roadrunner.Vector2d; import com.acmerobotics.roadrunner.VelConstraint; import com.acmerobotics.roadrunner.ftc.DownsampledWriter; import com.acmerobotics.roadrunner.ftc.Encoder; import com.acmerobotics.roadrunner.ftc.FlightRecorder; import com.acmerobotics.roadrunner.ftc.LynxFirmware; import com.acmerobotics.roadrunner.ftc.OverflowEncoder; import com.acmerobotics.roadrunner.ftc.PositionVelocityPair; import com.acmerobotics.roadrunner.ftc.RawEncoder; import com.qualcomm.hardware.lynx.LynxModule; import com.qualcomm.hardware.rev.RevHubOrientationOnRobot; import com.qualcomm.robotcore.hardware.DcMotor; import com.qualcomm.robotcore.hardware.DcMotorEx; import com.qualcomm.robotcore.hardware.DcMotorSimple; import com.qualcomm.robotcore.hardware.HardwareMap; import com.qualcomm.robotcore.hardware.IMU; import com.qualcomm.robotcore.hardware.VoltageSensor; import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; import org.firstinspires.ftc.teamcode.messages.DriveCommandMessage; import org.firstinspires.ftc.teamcode.messages.MecanumCommandMessage; import org.firstinspires.ftc.teamcode.messages.MecanumEncodersMessage; import org.firstinspires.ftc.teamcode.messages.PoseMessage; import java.util.Arrays; import java.util.LinkedList; import java.util.List; @Config public final class MecanumDrive { public static class Params { // IMU orientation // TODO: fill in these values based on // see https://ftc-docs.firstinspires.org/en/latest/programming_resources/imu/imu.html?highlight=imu#physical-hub-mounting public RevHubOrientationOnRobot.LogoFacingDirection logoFacingDirection = RevHubOrientationOnRobot.LogoFacingDirection.UP; public RevHubOrientationOnRobot.UsbFacingDirection usbFacingDirection = RevHubOrientationOnRobot.UsbFacingDirection.RIGHT; // drive model parameters public double inPerTick = 12 * 5 * 2 / 39820.0; public double lateralInPerTick = 0.00018869762188191035; //inPerTick; public double trackWidthTicks = 4432.299; // feedforward parameters (in tick units) public double kS = 0.9589658474985132; public double kV = 0.0005588422234744558; public double kA = 0.000001; // path profile parameters (in inches) public double maxWheelVel = 40; public double minProfileAccel = -20; public double maxProfileAccel = 20; // turn profile parameters (in radians) public double maxAngVel = Math.PI; // shared with path public double maxAngAccel = Math.PI; // path controller gains public double axialGain = 0.0; public double lateralGain = 0.0; public double headingGain = 4.32; // shared with turn public double axialVelGain = 0.0; public double lateralVelGain = 0.0; public double headingVelGain = 0.59; // shared with turn } public static Params PARAMS = new Params(); public final MecanumKinematics kinematics = new MecanumKinematics( PARAMS.inPerTick * PARAMS.trackWidthTicks, PARAMS.inPerTick / PARAMS.lateralInPerTick); public final TurnConstraints defaultTurnConstraints = new TurnConstraints( PARAMS.maxAngVel, -PARAMS.maxAngAccel, PARAMS.maxAngAccel); public final VelConstraint defaultVelConstraint = new MinVelConstraint(Arrays.asList( kinematics.new WheelVelConstraint(PARAMS.maxWheelVel), new AngularVelConstraint(PARAMS.maxAngVel) )); public final AccelConstraint defaultAccelConstraint = new ProfileAccelConstraint(PARAMS.minProfileAccel, PARAMS.maxProfileAccel); public final DcMotorEx leftFront, leftBack, rightBack, rightFront; public final VoltageSensor voltageSensor; public final IMU imu; public final Localizer localizer; public Pose2d pose; private final LinkedListThreeDeadWheelLocalizer.java:
```java package org.firstinspires.ftc.teamcode; import com.acmerobotics.dashboard.config.Config; import com.acmerobotics.roadrunner.DualNum; import com.acmerobotics.roadrunner.Time; import com.acmerobotics.roadrunner.Twist2dDual; import com.acmerobotics.roadrunner.Vector2dDual; import com.acmerobotics.roadrunner.ftc.Encoder; import com.acmerobotics.roadrunner.ftc.FlightRecorder; import com.acmerobotics.roadrunner.ftc.OverflowEncoder; import com.acmerobotics.roadrunner.ftc.PositionVelocityPair; import com.acmerobotics.roadrunner.ftc.RawEncoder; import com.qualcomm.robotcore.hardware.DcMotorEx; import com.qualcomm.robotcore.hardware.DcMotorSimple; import com.qualcomm.robotcore.hardware.HardwareMap; @Config public final class ThreeDeadWheelLocalizer implements Localizer { public static class Params { public double par0YTicks = -962.0; // y position of the first parallel encoder (in tick units) public double par1YTicks = 912.0; // y position of the second parallel encoder (in tick units) public double perpXTicks = -2133.0; // x position of the perpendicular encoder (in tick units) } public static Params PARAMS = new Params(); public final Encoder par0, par1, perp; public final double inPerTick; private int lastPar0Pos, lastPar1Pos, lastPerpPos; public ThreeDeadWheelLocalizer(HardwareMap hardwareMap, double inPerTick) { // TODO: make sure your config has **motors** with these names (or change them) // the encoders should be plugged into the slot matching the named motor // see https://ftc-docs.firstinspires.org/en/latest/hardware_and_software_configuration/configuring/index.html par0 = new OverflowEncoder(new RawEncoder(hardwareMap.get(DcMotorEx.class, "fl"))); par1 = new OverflowEncoder(new RawEncoder(hardwareMap.get(DcMotorEx.class, "bl"))); perp = new OverflowEncoder(new RawEncoder(hardwareMap.get(DcMotorEx.class, "fr"))); // TODO: reverse encoder directions if needed par0.setDirection(DcMotorSimple.Direction.REVERSE); perp.setDirection(DcMotorSimple.Direction.REVERSE); lastPar0Pos = par0.getPositionAndVelocity().position; lastPar1Pos = par1.getPositionAndVelocity().position; lastPerpPos = perp.getPositionAndVelocity().position; this.inPerTick = inPerTick; FlightRecorder.write("THREE_DEAD_WHEEL_PARAMS", PARAMS); } public Twist2dDualRobot Logs
No response