2525
2626import android .annotation .SuppressLint ;
2727
28+ import com .qualcomm .hardware .lynx .LynxModule ;
2829import com .qualcomm .robotcore .eventloop .opmode .OpMode ;
2930import com .qualcomm .robotcore .eventloop .opmode .TeleOp ;
31+ import com .qualcomm .robotcore .hardware .AnalogInput ;
32+ import com .qualcomm .robotcore .hardware .CRServo ;
3033import com .qualcomm .robotcore .util .ElapsedTime ;
3134
3235import java .util .ArrayList ;
@@ -79,6 +82,11 @@ public Tuning() {
7982 p .add ("Circle" , Circle ::new );
8083 p .add ("Line90DegreeTurn" , Line90DegreeTurn ::new );
8184 });
85+ s .folder ("Swerve" , p -> {
86+ p .add ("Analog Min / Max Tuner" , AnalogMinMaxTuner ::new );
87+ p .add ("Swerve Offsets Test" , SwerveOffsetsTest ::new );
88+ p .add ("Swerve Turn Test" , SwerveTurnTest ::new );
89+ });
8290 });
8391 }
8492
@@ -123,23 +131,33 @@ public static void stopRobot() {
123131}
124132
125133/**
126- * This is the LocalizationTest OpMode. This is basically just a simple mecanum drive attached to a
134+ * This is the LocalizationTest OpMode. This is basically just a simple drive attached to a
127135 * PoseUpdater. The OpMode will print out the robot's pose to telemetry as well as draw the robot.
128136 * You should use this to check the robot's localization.
129137 *
130138 * @author Anyi Lin - 10158 Scott's Bots
131139 * @author Baron Henderson - 20077 The Indubitables
140+ * @author Kabir Goyal
132141 * @version 1.0, 5/6/2024
133142 */
134143class LocalizationTest extends OpMode {
144+ boolean debugStringEnabled = false ;
145+
135146 @ Override
136147 public void init () {}
137148
138- /** This initializes the PoseUpdater, the mecanum drive motors, and the Panels telemetry. */
149+ /** This initializes the PoseUpdater, the drive motors, and the Panels telemetry. */
139150 @ Override
140151 public void init_loop () {
152+ if (gamepad1 .aWasPressed () || gamepad2 .aWasPressed ()) {
153+ debugStringEnabled = !debugStringEnabled ;
154+ }
155+
156+
141157 telemetryM .debug ("This will print your robot's position to telemetry while "
142- + "allowing robot control through a basic mecanum drive on gamepad 1." );
158+ + "allowing robot control through a basic drive on gamepad 1." );
159+ telemetryM .debug ("Drivetrain debug string " + (((debugStringEnabled ) ? "enabled" : "disabled" )) +
160+ " (press gamepad a to toggle)" );
143161 telemetryM .update (telemetry );
144162 follower .update ();
145163 drawCurrent ();
@@ -152,18 +170,26 @@ public void start() {
152170 }
153171
154172 /**
155- * This updates the robot's pose estimate, the simple mecanum drive, and updates the
173+ * This updates the robot's pose estimate, the simple drive, and updates the
156174 * Panels telemetry with the robot's position as well as draws the robot's position.
157175 */
158176 @ Override
159177 public void loop () {
178+ if (gamepad1 .aWasPressed () || gamepad2 .aWasPressed ()) {
179+ debugStringEnabled = !debugStringEnabled ;
180+ }
181+
160182 follower .setTeleOpDrive (-gamepad1 .left_stick_y , -gamepad1 .left_stick_x , -gamepad1 .right_stick_x , true );
161183 follower .update ();
162184
163185 telemetryM .debug ("x:" + follower .getPose ().getX ());
164186 telemetryM .debug ("y:" + follower .getPose ().getY ());
165187 telemetryM .debug ("heading:" + follower .getPose ().getHeading ());
166188 telemetryM .debug ("total heading:" + follower .getTotalHeading ());
189+ if (debugStringEnabled ) {
190+ telemetryM .debug ("Drivetrain Debug String:\n " +
191+ follower .getDrivetrain ().debugString ());
192+ }
167193 telemetryM .update (telemetry );
168194
169195 drawCurrentAndHistory ();
@@ -318,7 +344,7 @@ public void loop() {
318344 * reaching the end of the distance, it averages them and prints out the velocity obtained. It is
319345 * recommended to run this multiple times on a full battery to get the best results. What this does
320346 * is, when paired with StrafeVelocityTuner, allows FollowerConstants to create a Vector that
321- * empirically represents the direction your mecanum wheels actually prefer to go in, allowing for
347+ * empirically represents the direction your wheels actually prefer to go in, allowing for
322348 * more accurate following.
323349 *
324350 * @author Anyi Lin - 10158 Scott's Bots
@@ -423,7 +449,7 @@ public void loop() {
423449 * reaching the end of the distance, it averages them and prints out the velocity obtained. It is
424450 * recommended to run this multiple times on a full battery to get the best results. What this does
425451 * is, when paired with ForwardVelocityTuner, allows FollowerConstants to create a Vector that
426- * empirically represents the direction your mecanum wheels actually prefer to go in, allowing for
452+ * empirically represents the direction your wheels actually prefer to go in, allowing for
427453 * more accurate following.
428454 *
429455 * @author Anyi Lin - 10158 Scott's Bots
@@ -1405,6 +1431,185 @@ public void loop() {
14051431 }
14061432}
14071433
1434+ /**
1435+ * Tuning OpMode to get the min and max encoder values for swerve pods
1436+ * @author Kabir Goyal
1437+ */
1438+ class AnalogMinMaxTuner extends OpMode {
1439+ //populate the below with your names for the servos and encoders
1440+ public String [] encoderNames = {"leftFrontEncoder" , "rightFrontEncoder" , "leftBackEncoder" , "rightBackEncoder" };
1441+ public AnalogInput [] encoders = new AnalogInput [encoderNames .length ];
1442+ public double [] minVoltages = new double [encoderNames .length ];
1443+ public double [] maxVoltages = new double [encoderNames .length ];
1444+
1445+ public List <LynxModule > lynxModules ; //js to improve loop times a bit yk
1446+
1447+ public void start () {
1448+ }
1449+
1450+ @ Override
1451+ public void init_loop () {
1452+ telemetryM .debug ("Press START. Then, Spin each pod slowly for 4 to 5 full rotations.\n " +
1453+ "The OpMode will keep track of the min and max voltages seen so far and print them to telemetry." );
1454+ telemetryM .update (telemetry );
1455+ }
1456+
1457+ @ Override
1458+ public void init () {
1459+ lynxModules = hardwareMap .getAll (LynxModule .class );
1460+ for (LynxModule hub : lynxModules ) {
1461+ hub .setBulkCachingMode (LynxModule .BulkCachingMode .MANUAL );
1462+ }
1463+
1464+ for (int i = 0 ; i < encoders .length ; i ++) {
1465+ encoders [i ] = hardwareMap .get (AnalogInput .class , encoderNames [i ]);
1466+ minVoltages [i ] = 5 ; //bigger value than should ever be read
1467+ }
1468+ }
1469+
1470+ /**
1471+ * This runs the OpMode, updating the Follower as well as printing out the debug statements to
1472+ * the Telemetry, as well as the FTC Dashboard.
1473+ */
1474+ @ Override
1475+ public void loop () {
1476+ for (LynxModule hub : lynxModules ) {
1477+ hub .clearBulkCache ();
1478+ }
1479+
1480+ telemetryM .debug ("Spin each pod slowly for 4 to 5 full rotations.\n " +
1481+ "The OpMode will keep track of the min and max voltages seen so far and print them to telemetry.\n \n " );
1482+
1483+ for (int i = 0 ; i < encoders .length ; i ++) {
1484+ double currentVoltage = encoders [i ].getVoltage ();
1485+ minVoltages [i ] = Math .min (minVoltages [i ], currentVoltage );
1486+ maxVoltages [i ] = Math .max (maxVoltages [i ], currentVoltage );
1487+ telemetryM .addData (encoderNames [i ] + "min value:" , minVoltages [i ]);
1488+ telemetryM .addData (encoderNames [i ] + "max value:" , maxVoltages [i ]);
1489+ telemetryM .addLine ("" );
1490+ }
1491+
1492+ telemetryM .update ();
1493+ }
1494+ }
1495+
1496+ /**
1497+ * This is the SwerveOffsetsTest
1498+ * You should use this to check how good your swerve angle offsets are and if your motor directions are correct
1499+ * @author Kabir Goyal
1500+ *
1501+ */
1502+ class SwerveOffsetsTest extends OpMode {
1503+ boolean debugStringEnabled = false ;
1504+
1505+ @ Override
1506+ public void init () {}
1507+
1508+ /** This initializes the PoseUpdater, the drive motors, and the Panels telemetry. */
1509+ @ Override
1510+ public void init_loop () {
1511+ if (gamepad1 .aWasPressed () || gamepad2 .aWasPressed ()) {
1512+ debugStringEnabled = !debugStringEnabled ;
1513+ }
1514+
1515+
1516+ telemetryM .debug ("This OpMode will run all four swerve pods in the direction they think is forward"
1517+ + "\n ensure your bot is not on the ground while running" );
1518+ telemetryM .debug ("Drivetrain debug string " + (((debugStringEnabled ) ? "enabled" : "disabled" )) +
1519+ " (press gamepad a to toggle)" );
1520+ telemetryM .update (telemetry );
1521+ follower .update ();
1522+ drawCurrent ();
1523+ }
1524+
1525+ @ Override
1526+ public void start () {
1527+ follower .startTeleopDrive ();
1528+ follower .update ();
1529+ }
1530+
1531+ /**
1532+ * This updates the robot's pose estimate, the simple drive, and updates the
1533+ * Panels telemetry with the robot's position as well as draws the robot's position.
1534+ */
1535+ @ Override
1536+ public void loop () {
1537+ if (gamepad1 .aWasPressed () || gamepad2 .aWasPressed ()) {
1538+ debugStringEnabled = !debugStringEnabled ;
1539+ }
1540+
1541+ follower .setTeleOpDrive (0.25 , 0 , 0 , true );
1542+ follower .update ();
1543+
1544+ if (debugStringEnabled ) {
1545+ telemetryM .debug ("Drivetrain Debug String:\n " +
1546+ follower .getDrivetrain ().debugString ());
1547+ }
1548+ telemetryM .update (telemetry );
1549+
1550+ drawCurrentAndHistory ();
1551+ }
1552+ }
1553+
1554+ /**
1555+ * This is the SwerveTurnTest
1556+ * You should use this to check your encoder directions and x/y pod offsets
1557+ * @author Kabir Goyal
1558+ *
1559+ */
1560+ class SwerveTurnTest extends OpMode {
1561+ boolean debugStringEnabled = false ;
1562+
1563+ @ Override
1564+ public void init () {}
1565+
1566+ /** This initializes the PoseUpdater, the drive motors, and the Panels telemetry. */
1567+ @ Override
1568+ public void init_loop () {
1569+ if (gamepad1 .aWasPressed () || gamepad2 .aWasPressed ()) {
1570+ debugStringEnabled = !debugStringEnabled ;
1571+ }
1572+
1573+
1574+ telemetryM .debug ("This OpMode will run all four swerve pods in their turning direction (perpendicular to the center of the robot) "
1575+ + "\n run this once off the ground to check servo directions and motor directions before testing on the ground" );
1576+ telemetryM .debug ("Drivetrain debug string " + (((debugStringEnabled ) ? "enabled" : "disabled" )) +
1577+ " (press gamepad a to toggle)" );
1578+ telemetryM .update (telemetry );
1579+ follower .update ();
1580+ drawCurrent ();
1581+ }
1582+
1583+ @ Override
1584+ public void start () {
1585+ follower .startTeleopDrive ();
1586+ follower .update ();
1587+ }
1588+
1589+ /**
1590+ * This updates the robot's pose estimate, the simple drive, and updates the
1591+ * Panels telemetry with the robot's position as well as draws the robot's position.
1592+ */
1593+ @ Override
1594+ public void loop () {
1595+ if (gamepad1 .aWasPressed () || gamepad2 .aWasPressed ()) {
1596+ debugStringEnabled = !debugStringEnabled ;
1597+ }
1598+
1599+ follower .setTeleOpDrive (0 , 0 , 0.25 , true );
1600+ follower .update ();
1601+
1602+ if (debugStringEnabled ) {
1603+ telemetryM .debug ("Drivetrain Debug String:\n " +
1604+ follower .getDrivetrain ().debugString ());
1605+ }
1606+ telemetryM .update (telemetry );
1607+
1608+ drawCurrentAndHistory ();
1609+ }
1610+ }
1611+
1612+
14081613/**
14091614 * This is the Drawing class. It handles the drawing of stuff on Panels Dashboard, like the robot.
14101615 *
0 commit comments