├── src ├── main │ ├── java │ │ ├── xbot │ │ │ ├── common │ │ │ │ ├── math │ │ │ │ │ ├── package-info.java │ │ │ │ │ ├── MovingAverageForDouble.java │ │ │ │ │ ├── MovingAverageForTranslation2d.java │ │ │ │ │ ├── XYPairStruct.java │ │ │ │ │ ├── MovingAverage.java │ │ │ │ │ ├── PIDDefaults.java │ │ │ │ │ └── InterpolatingFieldPoseBuffer.java │ │ │ │ ├── logic │ │ │ │ │ ├── package-info.java │ │ │ │ │ ├── LogicUtils.java │ │ │ │ │ ├── CalibrationDecider.java │ │ │ │ │ └── WatchdogTimer.java │ │ │ │ ├── networking │ │ │ │ │ ├── package-info.java │ │ │ │ │ ├── XZeromqListener.java │ │ │ │ │ └── MockZeromqListener.java │ │ │ │ ├── injection │ │ │ │ │ ├── modules │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ ├── DefaultVisionModule.java │ │ │ │ │ │ ├── UnitTestRobotModule.java │ │ │ │ │ │ ├── MockControlsModule.java │ │ │ │ │ │ └── RealControlsModule.java │ │ │ │ │ ├── components │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ ├── SimulationComponent.java │ │ │ │ │ │ └── PurePursuitTestComponent.java │ │ │ │ │ ├── swerve │ │ │ │ │ │ ├── SwerveModule.java │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ ├── SwerveInstance.java │ │ │ │ │ │ ├── RearLeftDrive.java │ │ │ │ │ │ ├── FrontLeftDrive.java │ │ │ │ │ │ ├── RearRightDrive.java │ │ │ │ │ │ ├── FrontRightDrive.java │ │ │ │ │ │ ├── SwerveSingleton.java │ │ │ │ │ │ ├── SwerveComponentHolder.java │ │ │ │ │ │ └── SwerveComponent.java │ │ │ │ │ ├── electrical_contract │ │ │ │ │ │ ├── MotorControllerType.java │ │ │ │ │ │ ├── CANBusId.java │ │ │ │ │ │ ├── XDeadwheelElectricalContract.java │ │ │ │ │ │ ├── CANMotorControllerInfo.java │ │ │ │ │ │ ├── IMUInfo.java │ │ │ │ │ │ ├── CameraInfo.java │ │ │ │ │ │ ├── XCameraElectricalContract.java │ │ │ │ │ │ ├── DeviceInfo.java │ │ │ │ │ │ └── CANMotorControllerOutputConfig.java │ │ │ │ │ └── BaseWPITest.java │ │ │ │ ├── controls │ │ │ │ │ ├── XBaseIO.java │ │ │ │ │ ├── actuators │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ ├── mock_adapters │ │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ │ ├── MockRelay.java │ │ │ │ │ │ │ └── MockCompressor.java │ │ │ │ │ │ ├── wpi_adapters │ │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ │ ├── RelayWPIAdapter.java │ │ │ │ │ │ │ ├── ServoWPIAdapter.java │ │ │ │ │ │ │ ├── SpeedControllerWPIAdapter.java │ │ │ │ │ │ │ ├── CompressorWPIAdapter.java │ │ │ │ │ │ │ ├── SolenoidWPIAdapter.java │ │ │ │ │ │ │ ├── PWMWPIAdapter.java │ │ │ │ │ │ │ └── DigitalOutputWPIAdapter.java │ │ │ │ │ │ ├── XCANMotorControllerPIDProperties.java │ │ │ │ │ │ ├── XDigitalOutput.java │ │ │ │ │ │ ├── XSolenoid.java │ │ │ │ │ │ ├── XCompressor.java │ │ │ │ │ │ ├── XSpeedController.java │ │ │ │ │ │ ├── XRelay.java │ │ │ │ │ │ └── XPWM.java │ │ │ │ │ ├── sensors │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ ├── mock_adapters │ │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ │ ├── MockSparkAbsoluteEncoder.java │ │ │ │ │ │ │ └── MockDutyCycleEncoder.java │ │ │ │ │ │ ├── buttons │ │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ │ ├── SettableBooleanSuppler.java │ │ │ │ │ │ │ ├── InvertingBooleanSupplier.java │ │ │ │ │ │ │ ├── ChordTrigger.java │ │ │ │ │ │ │ ├── AdvancedTrigger.java │ │ │ │ │ │ │ ├── AnalogHIDButtonConfiguration.java │ │ │ │ │ │ │ ├── VirtualTrigger.java │ │ │ │ │ │ │ ├── AdvancedPovButtonTrigger.java │ │ │ │ │ │ │ ├── AdvancedJoystickButtonTrigger.java │ │ │ │ │ │ │ └── AdvancedXboxAxisTrigger.java │ │ │ │ │ │ ├── wpi_adapters │ │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ │ ├── PowerDistributionPanelWPIAdapter.java │ │ │ │ │ │ │ ├── TimerWpiAdapter.java │ │ │ │ │ │ │ ├── DutyCycleEncoderWpiAdapter.java │ │ │ │ │ │ │ ├── LidarLiteWpiAdapter.java │ │ │ │ │ │ │ └── AnalogInputWPIAdapater.java │ │ │ │ │ │ ├── DistanceSensor.java │ │ │ │ │ │ ├── XTimerImpl.java │ │ │ │ │ │ ├── DistanceSensorPair.java │ │ │ │ │ │ ├── XPowerDistributionPanel.java │ │ │ │ │ │ ├── XSettableTimerImpl.java │ │ │ │ │ │ ├── IGamepad.java │ │ │ │ │ │ ├── XAnalogInput.java │ │ │ │ │ │ ├── XTimer.java │ │ │ │ │ │ ├── XSparkAbsoluteEncoder.java │ │ │ │ │ │ ├── XGyroFactoryImpl.java │ │ │ │ │ │ ├── XAS5600.java │ │ │ │ │ │ ├── XAnalogDistanceSensor.java │ │ │ │ │ │ └── XCANImu.java │ │ │ │ │ └── io_inputs │ │ │ │ │ │ ├── XDigitalInputs.java │ │ │ │ │ │ ├── XDutyCycleEncoderInputs.java │ │ │ │ │ │ ├── XEncoderInputs.java │ │ │ │ │ │ ├── XCANCoderInputs.java │ │ │ │ │ │ ├── XAbsoluteEncoderInputs.java │ │ │ │ │ │ ├── LaserCANInputs.java │ │ │ │ │ │ ├── XCANSparkMaxInputs.java │ │ │ │ │ │ ├── PhotonCameraExtendedInputs.java │ │ │ │ │ │ ├── XGyroIoInputs.java │ │ │ │ │ │ └── XCANMotorControllerInputs.java │ │ │ │ ├── resiliency │ │ │ │ │ └── DeviceHealth.java │ │ │ │ ├── simulation │ │ │ │ │ ├── package-info.java │ │ │ │ │ ├── ISimulatableSensor.java │ │ │ │ │ ├── ISimulatableMotor.java │ │ │ │ │ ├── ExampleSensorData.json │ │ │ │ │ └── ISimulatableSolenoid.java │ │ │ │ ├── subsystems │ │ │ │ │ ├── drive │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ ├── swerve │ │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ │ ├── commands │ │ │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ │ │ └── ChangeActiveSwerveModuleCommand.java │ │ │ │ │ │ │ ├── ISwerveAdvisorPoseSupport.java │ │ │ │ │ │ │ ├── ISwerveAdvisorDriveSupport.java │ │ │ │ │ │ │ ├── SwerveModuleStates.java │ │ │ │ │ │ │ └── SwerveSuggestedRotation.java │ │ │ │ │ │ ├── CalculatorNode.java │ │ │ │ │ │ ├── SwerveSimpleTrajectoryMode.java │ │ │ │ │ │ ├── RabbitPointBuilder.java │ │ │ │ │ │ └── SwervePointKinematics.java │ │ │ │ │ ├── simple │ │ │ │ │ │ └── package-info.java │ │ │ │ │ ├── autonomous │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ └── SetAutonomousCommand.java │ │ │ │ │ ├── compressor │ │ │ │ │ │ └── package-info.java │ │ │ │ │ ├── feedback │ │ │ │ │ │ ├── package-info.java │ │ │ │ │ │ ├── IRumbler.java │ │ │ │ │ │ └── XRumbleManager.java │ │ │ │ │ ├── pose │ │ │ │ │ │ ├── SimulatedPositionSupplier.java │ │ │ │ │ │ └── commands │ │ │ │ │ │ │ ├── ResetDistanceCommand.java │ │ │ │ │ │ │ └── SetRobotHeadingCommand.java │ │ │ │ │ └── vision │ │ │ │ │ │ ├── AprilTagVisionIOFactory.java │ │ │ │ │ │ ├── CameraCapabilities.java │ │ │ │ │ │ ├── VisionPoseObservation.java │ │ │ │ │ │ └── SimpleCamera.java │ │ │ │ ├── properties │ │ │ │ │ ├── PermanentStorage.java │ │ │ │ │ ├── IPropertySupport.java │ │ │ │ │ ├── DebugFlag.java │ │ │ │ │ ├── ConfigurePropertiesCommand.java │ │ │ │ │ └── MockPermanentStorage.java │ │ │ │ ├── command │ │ │ │ │ ├── SupportsSetpointLock.java │ │ │ │ │ ├── SmartDashboardCommandPutter.java │ │ │ │ │ ├── BaseSimpleSetpointSubsystem.java │ │ │ │ │ ├── NamedInstantCommand.java │ │ │ │ │ ├── RealSmartDashboardCommandPutter.java │ │ │ │ │ ├── MockSmartDashboardCommandPutter.java │ │ │ │ │ ├── NamedRunCommand.java │ │ │ │ │ ├── BaseSetpointCommand.java │ │ │ │ │ ├── DelayViaSupplierCommand.java │ │ │ │ │ ├── SetTargetCommand.java │ │ │ │ │ ├── BaseSimpleMaintainerCommand.java │ │ │ │ │ ├── BaseWaitForMaintainerCommand.java │ │ │ │ │ └── SimpleWaitForMaintainerCommand.java │ │ │ │ ├── trajectory │ │ │ │ │ ├── ProvidesWaypoints.java │ │ │ │ │ └── ProvidesInterpolationData.java │ │ │ │ ├── logging │ │ │ │ │ ├── RobotAssertionException.java │ │ │ │ │ ├── AlertGroups.java │ │ │ │ │ ├── IntermittentConsoleLogger.java │ │ │ │ │ ├── Pluralizer.java │ │ │ │ │ ├── SilentRobotAssertionManager.java │ │ │ │ │ ├── LoudRobotAssertionManager.java │ │ │ │ │ ├── LoggingLatch.java │ │ │ │ │ └── RobotAssertionManager.java │ │ │ │ └── advantage │ │ │ │ │ └── DataFrameRefreshable.java │ │ │ └── electrical │ │ │ │ ├── analysis │ │ │ │ └── Main.java │ │ │ │ └── contract_report │ │ │ │ └── Main.java │ │ ├── edu │ │ │ └── wpi │ │ │ │ └── first │ │ │ │ └── wpilibj │ │ │ │ ├── MockDistanceSensor.java │ │ │ │ ├── MockDistanceSensorPair.java │ │ │ │ ├── MockServo.java │ │ │ │ ├── MockTimer.java │ │ │ │ ├── MockSpeedController.java │ │ │ │ ├── MockPowerDistributionPanel.java │ │ │ │ ├── MockSolenoid.java │ │ │ │ ├── MockPWM.java │ │ │ │ ├── MockLidarLite.java │ │ │ │ ├── MockDigitalOutput.java │ │ │ │ └── MockAnalogInput.java │ │ └── overview.html │ └── resources │ │ ├── log4j2.xml │ │ └── checkstyle_suppressions.xml └── test │ └── java │ └── xbot │ └── common │ ├── command │ ├── MockCommand.java │ ├── MockWaitForMaintainerCommand.java │ ├── MockSetpointCommand.java │ ├── BaseCommandTest.java │ ├── MockSetpointSubsystem.java │ ├── BaseWaitForMaintainerCommandTest.java │ └── SimpleWaitForMaintainerCommandTest.java │ ├── subsystems │ ├── simple │ │ └── MockSimpleMotorSubsystem.java │ ├── pose │ │ └── commands │ │ │ └── SetRobotHeadingCommandTest.java │ ├── drive │ │ └── MockSwerveDriveSubsystem.java │ └── feedback │ │ └── RumbleManagerTest.java │ ├── math │ ├── FieldPoseManagerTest.java │ ├── MathUtilsTest.java │ ├── HistoryBufferTests.java │ └── DoubleInterpolatorTest.java │ ├── controls │ └── sensors │ │ ├── AnalogDistanceSensorTest.java │ │ ├── DigitalInputTest.java │ │ ├── JoystickTest.java │ │ └── DutyCycleEncoderTest.java │ ├── injection │ ├── MockCameraElectricalContract.java │ ├── BaseCommonLibTest.java │ └── modules │ │ ├── CommonLibTestModule.java │ │ └── SwerveInjectionModule.java │ ├── logic │ └── LogicUtilsTests.java │ ├── logging │ └── TimeLoggerTest.java │ ├── simulation │ ├── SimulatedSolenoidTest.java │ ├── SimulatedDistanceSensorTest.java │ ├── SimulatedIMUTest.java │ ├── SimulateMockCANTalonTest.java │ └── SimulatedMockAbsoluteEncoderTest.java │ └── networking │ ├── ZeromqTestServer.java │ └── ZeromqListenerTest.java ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .wpilib └── wpilib_preferences.json ├── .github ├── CODEOWNERS └── pull_request_template.md ├── .vscode ├── extensions.json ├── settings.json └── launch.json ├── .checkstyle ├── checkstyle_suppressions.xml ├── .gitignore ├── vendordeps ├── AdvantageKit.json ├── PathplannerLib.json └── WPILibNewCommands.json └── settings.gradle /src/main/java/xbot/common/math/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Math utilities. 3 | */ 4 | package xbot.common.math; -------------------------------------------------------------------------------- /src/main/java/xbot/common/logic/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Logic utilities. 3 | */ 4 | package xbot.common.logic; -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team488/SeriouslyCommonLib/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/java/xbot/common/networking/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Networking utilities. 3 | */ 4 | package xbot.common.networking; -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/modules/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Modules for use with Dagger. 3 | */ 4 | package xbot.common.injection.modules; -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/XBaseIO.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls; 2 | 3 | public interface XBaseIO { 4 | public int getChannel(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/components/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Components for use with Dagger. 3 | */ 4 | package xbot.common.injection.components; -------------------------------------------------------------------------------- /src/main/java/xbot/common/resiliency/DeviceHealth.java: -------------------------------------------------------------------------------- 1 | package xbot.common.resiliency; 2 | 3 | public enum DeviceHealth { 4 | Healthy, 5 | Unhealthy 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/simulation/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Utilities for simulating robot operation on a computer. 3 | */ 4 | package xbot.common.simulation; -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/drive/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Subsystems related to the robot drive-train. 3 | */ 4 | package xbot.common.subsystems.drive; -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/simple/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Base subsystems helpful for common devices. 3 | */ 4 | package xbot.common.subsystems.simple; -------------------------------------------------------------------------------- /.wpilib/wpilib_preferences.json: -------------------------------------------------------------------------------- 1 | { 2 | "enableCppIntellisense": false, 3 | "currentLanguage": "java", 4 | "projectYear": "2025", 5 | "teamNumber": 488 6 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/properties/PermanentStorage.java: -------------------------------------------------------------------------------- 1 | package xbot.common.properties; 2 | 3 | public interface PermanentStorage extends ITableProxy { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Interfaces for interacting with actuator devices. 3 | */ 4 | package xbot.common.controls.actuators; -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Interfaces for input devices like buttons and sensors. 3 | */ 4 | package xbot.common.controls.sensors; -------------------------------------------------------------------------------- /src/main/java/xbot/common/properties/IPropertySupport.java: -------------------------------------------------------------------------------- 1 | package xbot.common.properties; 2 | 3 | public interface IPropertySupport { 4 | public String getPrefix(); 5 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/autonomous/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Utilities used in writing autonomous programs. 3 | */ 4 | package xbot.common.subsystems.autonomous; -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in 2 | # the repo. Unless a later match takes precedence, 3 | * @Team488/core-robot-maintainers 4 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/swerve/SwerveModule.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.swerve; 2 | 3 | import dagger.Module; 4 | 5 | @Module 6 | public class SwerveModule { 7 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/compressor/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Subsystems related to operating air compressors. 3 | */ 4 | package xbot.common.subsystems.compressor; -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/drive/swerve/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Subsystems for managing swerve drive modules. 3 | */ 4 | package xbot.common.subsystems.drive.swerve; -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/feedback/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Subsystems for feedback devices, like rumble motors. 3 | */ 4 | package xbot.common.subsystems.feedback; -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/mock_adapters/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Mock implementations of sensor devices. 3 | */ 4 | package xbot.common.controls.sensors.mock_adapters; -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ryanluker.vscode-coverage-gutters", 4 | "vscjava.vscode-java-test", 5 | "shengchen.vscode-checkstyle" 6 | ] 7 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/mock_adapters/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Mock implementations of actuator devices. 3 | */ 4 | package xbot.common.controls.actuators.mock_adapters; -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/drive/swerve/commands/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Commands for use with swerve drive modules. 3 | */ 4 | package xbot.common.subsystems.drive.swerve.commands; -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/feedback/IRumbler.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.feedback; 2 | 3 | public interface IRumbler { 4 | public XRumbleManager getRumbleManager(); 5 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/buttons/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Classes for custom input types, like buttons or joystick axes. 3 | */ 4 | package xbot.common.controls.sensors.buttons; -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/wpi_adapters/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementations of sensor devices that work on physical robots. 3 | */ 4 | package xbot.common.controls.sensors.wpi_adapters; -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/swerve/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains classes that are used to help with dependency injection with swerve drive robots. 3 | */ 4 | package xbot.common.injection.swerve; -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/wpi_adapters/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementations of actuator deices that work on physical robots. 3 | */ 4 | package xbot.common.controls.actuators.wpi_adapters; -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Why are we doing this? 2 | 3 | # Whats changing? 4 | 5 | # Questions/notes for reviewers 6 | 7 | # How this was tested 8 | - [ ] unit tests added 9 | - [ ] tested on robot 10 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/electrical_contract/MotorControllerType.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.electrical_contract; 2 | 3 | public enum MotorControllerType { 4 | SparkMax, 5 | TalonFx, 6 | VictorSPX 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/simulation/ISimulatableSensor.java: -------------------------------------------------------------------------------- 1 | package xbot.common.simulation; 2 | 3 | import org.json.JSONObject; 4 | 5 | public interface ISimulatableSensor { 6 | public void ingestSimulationData(JSONObject payload); 7 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/swerve/SwerveInstance.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.swerve; 2 | 3 | /** 4 | * Labels a swerve module instance. 5 | * @param label The label. 6 | */ 7 | public record SwerveInstance(String label) { 8 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/io_inputs/XDigitalInputs.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.io_inputs; 2 | 3 | import org.littletonrobotics.junction.AutoLog; 4 | 5 | @AutoLog 6 | public class XDigitalInputs { 7 | public boolean signal; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/command/SupportsSetpointLock.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import edu.wpi.first.wpilibj2.command.Subsystem; 4 | 5 | public interface SupportsSetpointLock { 6 | 7 | public Subsystem getSetpointLock(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/DistanceSensor.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | public interface DistanceSensor { 4 | 5 | public double getDistance(); 6 | 7 | public void setAveraging(boolean shouldAverage); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/XTimerImpl.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | public interface XTimerImpl { 4 | public double getFPGATimestamp(); 5 | public double getMatchTime(); 6 | public void delay(double seconds); 7 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/pose/SimulatedPositionSupplier.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.pose; 2 | 3 | import edu.wpi.first.math.geometry.Pose2d; 4 | 5 | public interface SimulatedPositionSupplier { 6 | public Pose2d getGroundTruthPose(); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/io_inputs/XDutyCycleEncoderInputs.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.io_inputs; 2 | 3 | import org.littletonrobotics.junction.AutoLog; 4 | 5 | @AutoLog 6 | public class XDutyCycleEncoderInputs { 7 | public double absoluteRawPosition; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/DistanceSensorPair.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | public interface DistanceSensorPair { 4 | public DistanceSensor getSensorA(); 5 | public DistanceSensor getSensorB(); 6 | 7 | public void update(); 8 | } 9 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/command/MockCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | public class MockCommand extends BaseCommand { 4 | @Override 5 | public void initialize() { 6 | } 7 | 8 | @Override 9 | public void execute() { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/io_inputs/XEncoderInputs.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.io_inputs; 2 | 3 | import org.littletonrobotics.junction.AutoLog; 4 | 5 | @AutoLog 6 | public class XEncoderInputs { 7 | public double rate; 8 | public double distance; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/io_inputs/XCANCoderInputs.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.io_inputs; 2 | 3 | import org.littletonrobotics.junction.AutoLog; 4 | 5 | @AutoLog 6 | public class XCANCoderInputs extends XAbsoluteEncoderInputs { 7 | public boolean hasResetOccurred; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/vision/AprilTagVisionIOFactory.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.vision; 2 | 3 | import edu.wpi.first.math.geometry.Transform3d; 4 | 5 | public interface AprilTagVisionIOFactory { 6 | AprilTagVisionIO create(String name, Transform3d robotToCamera); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/command/SmartDashboardCommandPutter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | public interface SmartDashboardCommandPutter { 4 | public void addCommandToSmartDashboard(BaseCommand command); 5 | public void addCommandToSmartDashboard(String label, BaseCommand command); 6 | } -------------------------------------------------------------------------------- /src/main/java/xbot/electrical/analysis/Main.java: -------------------------------------------------------------------------------- 1 | package xbot.electrical.analysis; 2 | 3 | public class Main { 4 | public static void main(String[] args) { 5 | System.out.println("Electrical Analysis System Initialized."); 6 | // Additional initialization code can go here 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/trajectory/ProvidesWaypoints.java: -------------------------------------------------------------------------------- 1 | package xbot.common.trajectory; 2 | 3 | import edu.wpi.first.math.geometry.Pose2d; 4 | 5 | import java.util.List; 6 | 7 | public interface ProvidesWaypoints { 8 | public List generatePath(Pose2d start, Pose2d end); 9 | } 10 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=permwrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=permwrapper/dists 8 | -------------------------------------------------------------------------------- /src/main/java/xbot/electrical/contract_report/Main.java: -------------------------------------------------------------------------------- 1 | package xbot.electrical.contract_report; 2 | 3 | public class Main { 4 | public static void main(String[] args) { 5 | System.out.println("Electrical Contract Report System Initialized."); 6 | // Additional initialization code can go here 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/logging/RobotAssertionException.java: -------------------------------------------------------------------------------- 1 | package xbot.common.logging; 2 | 3 | //@SuppressWarnings("serial") 4 | public class RobotAssertionException extends RuntimeException { 5 | public RobotAssertionException(String failureCauseCause) { 6 | super("Assertion error: " + failureCauseCause); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/XPowerDistributionPanel.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | public abstract class XPowerDistributionPanel 4 | { 5 | public interface XPowerDistributionPanelFactory { 6 | XPowerDistributionPanel create(); 7 | } 8 | 9 | public abstract double getCurrent(int channel); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/electrical_contract/CANBusId.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.electrical_contract; 2 | 3 | /** 4 | * Represents a CAN bus ID 5 | * @param id Bus name string 6 | */ 7 | public record CANBusId(String id) { 8 | public static final CANBusId RIO = new CANBusId("rio"); 9 | public static final CANBusId DefaultCanivore = new CANBusId("*"); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/properties/DebugFlag.java: -------------------------------------------------------------------------------- 1 | package xbot.common.properties; 2 | 3 | import javax.inject.Singleton; 4 | 5 | @Singleton 6 | public class DebugFlag { 7 | boolean isDebug = false; 8 | 9 | public void setDebug(boolean debug) { 10 | isDebug = debug; 11 | } 12 | 13 | public boolean isDebug() { 14 | return isDebug; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/swerve/RearLeftDrive.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.swerve; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | import javax.inject.Qualifier; 7 | 8 | /** 9 | * This annotation denotes the rear left swerve module. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Qualifier 13 | public @interface RearLeftDrive {} -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/swerve/FrontLeftDrive.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.swerve; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | import javax.inject.Qualifier; 7 | 8 | /** 9 | * This annotation denotes the front left swerve module. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Qualifier 13 | public @interface FrontLeftDrive {} -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/swerve/RearRightDrive.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.swerve; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | import javax.inject.Qualifier; 7 | 8 | /** 9 | * This annotation denotes the rear right swerve module. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Qualifier 13 | public @interface RearRightDrive {} -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/swerve/FrontRightDrive.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.swerve; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | import javax.inject.Qualifier; 7 | 8 | /** 9 | * This annotation denotes the front right swerve module. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Qualifier 13 | public @interface FrontRightDrive {} -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/swerve/SwerveSingleton.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.swerve; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | import javax.inject.Scope; 7 | 8 | /** 9 | * This annotation denotes a singleton scoped to a single swerve module. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Scope 13 | public @interface SwerveSingleton {} -------------------------------------------------------------------------------- /src/main/java/xbot/common/networking/XZeromqListener.java: -------------------------------------------------------------------------------- 1 | package xbot.common.networking; 2 | 3 | import java.util.function.Consumer; 4 | 5 | public interface XZeromqListener { 6 | 7 | public interface XZeromqListenerFactory { 8 | XZeromqListener create(String connectionString, String topic); 9 | } 10 | 11 | public void start(); 12 | public void setNewPacketHandler(Consumer handler); 13 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/logging/AlertGroups.java: -------------------------------------------------------------------------------- 1 | package xbot.common.logging; 2 | 3 | /** 4 | * This class contains the names of the alert groups that are used in the logging system. 5 | */ 6 | public final class AlertGroups { 7 | /** 8 | * The name of the alert group that is used for all alerts that are related to the robot's devices. 9 | */ 10 | public static final String DEVICE_HEALTH = "DeviceHealth"; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/drive/swerve/ISwerveAdvisorPoseSupport.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.drive.swerve; 2 | 3 | import edu.wpi.first.math.geometry.Pose2d; 4 | import xbot.common.math.WrappedRotation2d; 5 | 6 | public interface ISwerveAdvisorPoseSupport { 7 | 8 | public boolean getHeadingResetRecently(); 9 | public WrappedRotation2d getCurrentHeading(); 10 | public Pose2d getCurrentPose2d(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/command/MockWaitForMaintainerCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import javax.inject.Inject; 4 | 5 | import xbot.common.properties.PropertyFactory; 6 | 7 | public class MockWaitForMaintainerCommand extends BaseWaitForMaintainerCommand { 8 | 9 | @Inject 10 | public MockWaitForMaintainerCommand(MockSetpointSubsystem system, PropertyFactory pf) { 11 | super(system, pf, 1); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/command/MockSetpointCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import javax.inject.Inject; 4 | 5 | public class MockSetpointCommand extends BaseSetpointCommand { 6 | 7 | @Inject 8 | public MockSetpointCommand(MockSetpointSubsystem system) { 9 | super(system); 10 | } 11 | 12 | @Override 13 | public void initialize() { 14 | } 15 | 16 | @Override 17 | public void execute() { 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/electrical_contract/XDeadwheelElectricalContract.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.electrical_contract; 2 | 3 | import edu.wpi.first.units.measure.Distance; 4 | 5 | /** 6 | * This interface defines the base electrical contract 7 | * for robots implementing a deadwheel assisted drive based system. 8 | */ 9 | public interface XDeadwheelElectricalContract { 10 | public abstract Distance getDistanceFromCenterToOuterBumperX(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/io_inputs/XAbsoluteEncoderInputs.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.io_inputs; 2 | 3 | import edu.wpi.first.units.measure.Angle; 4 | import edu.wpi.first.units.measure.AngularVelocity; 5 | import org.littletonrobotics.junction.AutoLog; 6 | 7 | @AutoLog 8 | public class XAbsoluteEncoderInputs { 9 | public Angle position; 10 | public Angle absolutePosition; 11 | public AngularVelocity velocity; 12 | public String deviceHealth; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/vision/CameraCapabilities.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.vision; 2 | 3 | /** 4 | * This enum is used to specify the capabilities of a camera. 5 | */ 6 | public enum CameraCapabilities { 7 | /** 8 | * The camera is capable of providing April Tag localization information. 9 | */ 10 | APRIL_TAG, 11 | /** 12 | * The camera is capable of providing game-specific information. 13 | */ 14 | GAME_SPECIFIC 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/logging/IntermittentConsoleLogger.java: -------------------------------------------------------------------------------- 1 | package xbot.common.logging; 2 | 3 | public class IntermittentConsoleLogger { 4 | 5 | private int i = 0; 6 | private int modulus = 500; 7 | 8 | public void logSometimes(String message) { 9 | if (i % modulus == 0) { 10 | System.out.println(message); 11 | } 12 | i++; 13 | } 14 | 15 | public void setModulus(int modulus) { 16 | this.modulus = modulus; 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/java/xbot/common/command/BaseCommandTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import org.junit.Test; 4 | 5 | import xbot.common.injection.BaseCommonLibTest; 6 | 7 | public class BaseCommandTest extends BaseCommonLibTest { 8 | 9 | @Test 10 | public void testPuttingOnSmartDashboardDoesntCrashTest() { 11 | BaseCommand command = new MockCommand(); 12 | command.includeOnSmartDashboard("label"); 13 | command.includeOnSmartDashboard(); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/vision/VisionPoseObservation.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.vision; 2 | 3 | import edu.wpi.first.math.Matrix; 4 | import edu.wpi.first.math.geometry.Pose2d; 5 | import edu.wpi.first.math.numbers.N1; 6 | import edu.wpi.first.math.numbers.N3; 7 | 8 | public record VisionPoseObservation(Pose2d visionRobotPoseMeters, 9 | double timestampSeconds, 10 | Matrix visionMeasurementStdDevs) { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/command/BaseSimpleSetpointSubsystem.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | /** 4 | * A base class for setpoint subsystems that use simple Double values for both 5 | * current and target values. 6 | */ 7 | public abstract class BaseSimpleSetpointSubsystem extends BaseSetpointSubsystem { 8 | @Override 9 | protected boolean areTwoTargetsEquivalent(Double target1, Double target2) { 10 | return areTwoDoublesEquivalent(target1, target2); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/XSettableTimerImpl.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | public interface XSettableTimerImpl extends XTimerImpl { 4 | 5 | /** 6 | * Set the current time 7 | * @param time The current time in seconds 8 | */ 9 | public void setTimeInSeconds(double time); 10 | 11 | /** 12 | * Advance the timer 13 | * @param time Duration in seconds to advance by 14 | */ 15 | public void advanceTimeInSecondsBy(double time); 16 | 17 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/trajectory/ProvidesInterpolationData.java: -------------------------------------------------------------------------------- 1 | package xbot.common.trajectory; 2 | 3 | import edu.wpi.first.math.geometry.Rotation2d; 4 | import edu.wpi.first.math.geometry.Translation2d; 5 | import xbot.common.subsystems.drive.SwervePointKinematics; 6 | 7 | public interface ProvidesInterpolationData { 8 | public Translation2d getTranslation2d(); 9 | 10 | public double getSecondsForSegment(); 11 | 12 | public Rotation2d getRotation2d(); 13 | 14 | public SwervePointKinematics getKinematics(); 15 | } -------------------------------------------------------------------------------- /.checkstyle: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/modules/DefaultVisionModule.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.modules; 2 | 3 | import dagger.Module; 4 | import dagger.Provides; 5 | import edu.wpi.first.apriltag.AprilTagFieldLayout; 6 | import edu.wpi.first.apriltag.AprilTagFields; 7 | 8 | import javax.inject.Singleton; 9 | 10 | @Module 11 | public class DefaultVisionModule { 12 | @Provides 13 | @Singleton 14 | static AprilTagFieldLayout getAprilTagFieldLayout() { 15 | return AprilTagFieldLayout.loadField(AprilTagFields.kDefaultField); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/io_inputs/LaserCANInputs.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.io_inputs; 2 | 3 | import edu.wpi.first.units.measure.Distance; 4 | import edu.wpi.first.units.measure.Time; 5 | import org.littletonrobotics.junction.AutoLog; 6 | 7 | import static edu.wpi.first.units.Units.Meters; 8 | import static edu.wpi.first.units.Units.Seconds; 9 | 10 | @AutoLog 11 | public class LaserCANInputs { 12 | public boolean isMeasurementValid = false; 13 | public Distance distance = Meters.zero(); 14 | public Time measurementLatency = Seconds.zero(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/io_inputs/XCANSparkMaxInputs.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.io_inputs; 2 | 3 | import org.littletonrobotics.junction.AutoLog; 4 | 5 | @AutoLog 6 | public class XCANSparkMaxInputs 7 | { 8 | public boolean stickyFaultHasReset; 9 | public long lastErrorId; 10 | public double velocity; 11 | public double position; 12 | public double appliedOutput; 13 | public double busVoltage; 14 | public double outputCurrent; 15 | public boolean isForwardLimitSwitchPressed; 16 | public boolean isReverseLimitSwitchPressed; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/command/NamedInstantCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import edu.wpi.first.wpilibj2.command.InstantCommand; 4 | import edu.wpi.first.wpilibj2.command.Subsystem; 5 | 6 | /** 7 | * Convenience wrapper of InstantCommand that allows setting a human readable name for 8 | * smartdashboard/logging readability. 9 | */ 10 | public class NamedInstantCommand extends InstantCommand { 11 | public NamedInstantCommand(String name, Runnable toRun, Subsystem... requirements) { 12 | super(toRun, requirements); 13 | this.setName(name); 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/io_inputs/PhotonCameraExtendedInputs.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.io_inputs; 2 | 3 | import org.littletonrobotics.junction.AutoLog; 4 | import org.photonvision.targeting.PhotonPipelineResult; 5 | 6 | //@AutoLog 7 | public class PhotonCameraExtendedInputs { 8 | public PhotonPipelineResult[] pipelineResults; 9 | public double[] pipelineResultTimestamps; 10 | public double[] cameraMatrix; 11 | public double[] distCoeffs; 12 | public boolean inputsUnhealthy; 13 | public String versionEntry; 14 | public boolean isConnected; 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/subsystems/simple/MockSimpleMotorSubsystem.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.simple; 2 | 3 | import xbot.common.properties.PropertyFactory; 4 | 5 | import javax.inject.Inject; 6 | 7 | public class MockSimpleMotorSubsystem extends SimpleMotorSubsystem { 8 | public double currentPower; 9 | 10 | @Inject 11 | public MockSimpleMotorSubsystem(PropertyFactory pf) { 12 | super("mock", pf); 13 | currentPower = 0; 14 | } 15 | 16 | @Override 17 | public void setPower(double power) { 18 | this.currentPower = power; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/drive/swerve/ISwerveAdvisorDriveSupport.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.drive.swerve; 2 | 3 | import edu.wpi.first.math.geometry.Rotation2d; 4 | import edu.wpi.first.math.geometry.Translation2d; 5 | 6 | public interface ISwerveAdvisorDriveSupport { 7 | 8 | public void setDesiredHeading(double heading); 9 | public double getDesiredHeading(); 10 | 11 | public boolean getStaticHeadingActive(); 12 | public boolean getLookAtPointActive(); 13 | 14 | public Rotation2d getStaticHeadingTarget(); 15 | public Translation2d getLookAtPointTarget(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/logging/Pluralizer.java: -------------------------------------------------------------------------------- 1 | package xbot.common.logging; 2 | 3 | // basic logic written by Copilot 4 | // CHECKSTYLE:OFF 5 | public class Pluralizer { 6 | public static String pluralize(String word) { 7 | // Basic pluralization logic 8 | if (word.endsWith("y")) { 9 | return word.substring(0, word.length() - 1) + "ies"; 10 | } else if (word.endsWith("s") || word.endsWith("x") || word.endsWith("z") || word.endsWith("ch") 11 | || word.endsWith("sh")) { 12 | return word + "es"; 13 | } else { 14 | return word + "s"; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/IGamepad.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | import edu.wpi.first.math.geometry.Translation2d; 4 | 5 | public interface IGamepad { 6 | 7 | public Translation2d getLeftVector(); 8 | public Translation2d getRightVector(); 9 | 10 | public Translation2d getLeftFieldOrientedVector(); 11 | public Translation2d getRightFieldOrientedVector(); 12 | 13 | public double getLeftTrigger(); 14 | public double getRightTrigger(); 15 | 16 | public void setLeftInversion(boolean xInverted, boolean yInverted); 17 | public void setRightInversion(boolean xInverted, boolean yInverted); 18 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/simulation/ISimulatableMotor.java: -------------------------------------------------------------------------------- 1 | package xbot.common.simulation; 2 | 3 | import org.json.JSONObject; 4 | 5 | public interface ISimulatableMotor { 6 | public JSONObject getSimulationData(); 7 | 8 | default JSONObject buildMotorObject(String name, float value) { 9 | JSONObject result = new JSONObject(); 10 | // For now the simulation robot expects "Motor1, Motor2" etc but at some point 11 | // we'll change this so it's better linked to DevicePolice or some other name mapping 12 | result.put("id", name.replace("CAN", "Motor")); 13 | result.put("val", value); 14 | return result; 15 | } 16 | } -------------------------------------------------------------------------------- /checkstyle_suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/buttons/SettableBooleanSuppler.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.buttons; 2 | 3 | import java.util.function.BooleanSupplier; 4 | 5 | public class SettableBooleanSuppler implements BooleanSupplier { 6 | 7 | private boolean value; 8 | 9 | public SettableBooleanSuppler(boolean defaultValue) { 10 | this.value = defaultValue; 11 | } 12 | 13 | @Override 14 | public boolean getAsBoolean() { 15 | return value; 16 | } 17 | 18 | public void set(boolean value) { 19 | this.value = value; 20 | } 21 | 22 | public void toggle() { 23 | this.value = !this.value; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/simulation/ExampleSensorData.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sensors": [ 3 | { 4 | "ID": "DigitalIO3", 5 | "Payload": { 6 | "EncoderTicks": 123 7 | } 8 | }, 9 | { 10 | "ID": "Analog5", 11 | "Payload": { 12 | "Voltage": 2.45784 13 | } 14 | }, 15 | { 16 | "ID": "Analog6", 17 | "Payload": { 18 | "Distance": 129.323 19 | } 20 | }, 21 | { 22 | "ID": "CAN12", 23 | "Payload": { 24 | "EncoderTicks": 224 25 | } 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /src/main/resources/checkstyle_suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/logging/SilentRobotAssertionManager.java: -------------------------------------------------------------------------------- 1 | package xbot.common.logging; 2 | 3 | import javax.inject.Inject; 4 | 5 | /** 6 | * Version of RobotAssertionManager that prevents throwing of exceptions. Should 7 | * be used on-robot in competitions. 8 | */ 9 | public class SilentRobotAssertionManager extends RobotAssertionManager { 10 | 11 | @Inject 12 | public SilentRobotAssertionManager() {} 13 | 14 | @Override 15 | protected void handlePlatformException(RuntimeException e) { 16 | // Don't do anything: we don't need to throw 17 | } 18 | 19 | @Override 20 | public boolean isExceptionsEnabled() { 21 | return false; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/math/FieldPoseManagerTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.math; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | import xbot.common.injection.BaseCommonLibTest; 8 | 9 | public class FieldPoseManagerTest extends BaseCommonLibTest { 10 | 11 | @Test 12 | public void testCreation() { 13 | FieldPosePropertyManager fppm = getInjectorComponent().fieldPosePropertyManagerFactory().create("Suffix", 1, 2, 3); 14 | fppm.getPose(); 15 | assertEquals(1, fppm.getPose().getPoint().x, 0.001); 16 | assertEquals(2, fppm.getPose().getPoint().y, 0.001); 17 | assertEquals(3, fppm.getPose().getHeading().getDegrees(), 0.001); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/electrical_contract/CANMotorControllerInfo.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.electrical_contract; 2 | 3 | public record CANMotorControllerInfo( 4 | String name, 5 | MotorControllerType type, 6 | CANBusId busId, 7 | int deviceId, 8 | CANMotorControllerOutputConfig outputConfig) { 9 | 10 | public CANMotorControllerInfo(String name, int deviceId) { 11 | this(name, MotorControllerType.SparkMax, CANBusId.RIO, deviceId); 12 | } 13 | 14 | public CANMotorControllerInfo(String name, MotorControllerType type, CANBusId busId, int deviceId) { 15 | this(name, type, busId, deviceId, new CANMotorControllerOutputConfig()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/logging/LoudRobotAssertionManager.java: -------------------------------------------------------------------------------- 1 | package xbot.common.logging; 2 | 3 | import javax.inject.Inject; 4 | 5 | /** 6 | * Version of RobotAssertionManager that allows exceptions to be thrown. Should 7 | * only be used off-robot or during controlled testing sessions; should never 8 | * be used in competition. 9 | */ 10 | public class LoudRobotAssertionManager extends RobotAssertionManager { 11 | 12 | @Inject 13 | public LoudRobotAssertionManager() {} 14 | 15 | @Override 16 | protected void handlePlatformException(RuntimeException e) { 17 | throw e; 18 | } 19 | 20 | @Override 21 | public boolean isExceptionsEnabled() { 22 | return true; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/simulation/ISimulatableSolenoid.java: -------------------------------------------------------------------------------- 1 | package xbot.common.simulation; 2 | 3 | import org.json.JSONObject; 4 | 5 | public interface ISimulatableSolenoid { 6 | public JSONObject getSimulationData(); 7 | public final String SOLENOID_POWER_MODE = "VIRTUAL_SOLENOID"; 8 | 9 | default JSONObject buildMotorObject(int channel, boolean isOn) { 10 | JSONObject result = new JSONObject(); 11 | 12 | result.put("id", "Solenoid" + channel); 13 | result.put("mode", SOLENOID_POWER_MODE); 14 | if(isOn) { 15 | result.put("val", "ON"); 16 | } else { 17 | result.put("val", "OFF"); 18 | } 19 | 20 | return result; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/io_inputs/XGyroIoInputs.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.io_inputs; 2 | 3 | import edu.wpi.first.units.measure.Angle; 4 | import edu.wpi.first.units.measure.AngularVelocity; 5 | import org.littletonrobotics.junction.AutoLog; 6 | 7 | import static edu.wpi.first.units.Units.Degrees; 8 | import static edu.wpi.first.units.Units.DegreesPerSecond; 9 | 10 | @AutoLog 11 | public class XGyroIoInputs { 12 | public Angle yaw = Degrees.zero(); 13 | public AngularVelocity yawAngularVelocity = DegreesPerSecond.zero(); 14 | public Angle pitch = Degrees.zero(); 15 | public Angle roll = Degrees.zero(); 16 | public double[] acceleration = new double[3]; 17 | public boolean isConnected = false; 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/controls/sensors/AnalogDistanceSensorTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import xbot.common.injection.BaseCommonLibTest; 7 | 8 | public class AnalogDistanceSensorTest extends BaseCommonLibTest { 9 | 10 | AnalogDistanceSensor sensor; 11 | 12 | @Before 13 | public void setup() { 14 | //sensor = (AnalogDistanceSensor)clf.createAnalogDistanceSensor(0, AnalogDistanceSensor.VoltageMaps::sharp0A51SK, "Test"); 15 | } 16 | 17 | @Test 18 | public void testSensor() { 19 | //((MockAnalogInput)sensor.input).setVoltage(0.6d); 20 | //assertEquals(3.93700787d, sensor.getDistance(), 0.2); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/command/RealSmartDashboardCommandPutter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import javax.inject.Inject; 4 | 5 | //import edu.wpi.first.wpilibj2.command.Command; 6 | import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; 7 | 8 | public class RealSmartDashboardCommandPutter implements SmartDashboardCommandPutter { 9 | 10 | @Inject 11 | public RealSmartDashboardCommandPutter() {} 12 | 13 | @Override 14 | public void addCommandToSmartDashboard(BaseCommand command) { 15 | SmartDashboard.putData(command); 16 | } 17 | 18 | @Override 19 | public void addCommandToSmartDashboard(String label, BaseCommand command) { 20 | SmartDashboard.putData(label, command); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /src/main/java/edu/wpi/first/wpilibj/MockDistanceSensor.java: -------------------------------------------------------------------------------- 1 | package edu.wpi.first.wpilibj; 2 | 3 | import xbot.common.controls.sensors.DistanceSensor; 4 | 5 | public class MockDistanceSensor implements DistanceSensor { 6 | 7 | double distance; 8 | 9 | public MockDistanceSensor() { 10 | } 11 | 12 | public double getDistance() { 13 | return distance; 14 | } 15 | 16 | public void setDistance(double distance) { 17 | this.distance = distance; 18 | } 19 | 20 | public void incrementDistance(double delta) { 21 | this.distance += delta; 22 | } 23 | 24 | @Override 25 | public void setAveraging(boolean shouldAverage) { 26 | // Nothing to do in mock implementation 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/command/MockSmartDashboardCommandPutter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import javax.inject.Inject; 4 | 5 | public class MockSmartDashboardCommandPutter implements SmartDashboardCommandPutter { 6 | 7 | @Inject 8 | public MockSmartDashboardCommandPutter() {} 9 | 10 | @Override 11 | public void addCommandToSmartDashboard(BaseCommand command) { 12 | // intentionally left blank as the SmartDashboard isn't available off the robot right now 13 | 14 | } 15 | 16 | @Override 17 | public void addCommandToSmartDashboard(String label, BaseCommand command) { 18 | // intentionally left blank as the SmartDashboard isn't available off the robot right now 19 | 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/command/NamedRunCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | 6 | import edu.wpi.first.wpilibj2.command.RunCommand; 7 | import edu.wpi.first.wpilibj2.command.Subsystem; 8 | 9 | public class NamedRunCommand extends RunCommand { 10 | protected Logger log; 11 | 12 | public NamedRunCommand(String name, Runnable toRun, Subsystem... requirements) { 13 | super(toRun, requirements); 14 | this.setName(name); 15 | log = LogManager.getLogger(this.getName()); 16 | } 17 | 18 | @Override 19 | public void initialize() { 20 | super.initialize(); 21 | log.info("Initializing"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/math/MovingAverageForDouble.java: -------------------------------------------------------------------------------- 1 | package xbot.common.math; 2 | 3 | import xbot.common.math.MovingAverage; 4 | 5 | public class MovingAverageForDouble extends MovingAverage { 6 | public MovingAverageForDouble(int size) { 7 | super(new SumFunction() { 8 | @Override 9 | public Double add(Double a, Double b) { 10 | return a + b; 11 | } 12 | 13 | @Override 14 | public Double subtract(Double a, Double b) { 15 | return a - b; 16 | } 17 | 18 | @Override 19 | public Double divide(Double a, int b) { 20 | return a / b; 21 | } 22 | }, 0.0, size); 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/drive/swerve/SwerveModuleStates.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.drive.swerve; 2 | 3 | import edu.wpi.first.math.kinematics.SwerveModuleState; 4 | 5 | /** 6 | * A simple record to hold the states of all four swerve modules. 7 | */ 8 | public record SwerveModuleStates(SwerveModuleState frontLeft, 9 | SwerveModuleState frontRight, 10 | SwerveModuleState rearLeft, 11 | SwerveModuleState rearRight) { 12 | public SwerveModuleState[] toArray() { 13 | return new SwerveModuleState[] { 14 | frontLeft, 15 | frontRight, 16 | rearLeft, 17 | rearRight 18 | }; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | ./*.jar 8 | #*.war 9 | #*.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | 14 | # binary dir 15 | bin/ 16 | build/ 17 | dist/ 18 | 19 | # git diff files 20 | *.orig 21 | 22 | # test logs 23 | derby.log 24 | /TeamDatabase 25 | /488Logs 26 | 27 | # dynamically generated properties files 28 | netconsole-host.properties 29 | WPI_Native_Libraries.properties 30 | 31 | # JetBrains 32 | .idea/ 33 | /*.iml 34 | 35 | #Gradle 36 | .gradle/ 37 | 38 | #Eclipse (build tools used by VS Code) 39 | .settings/ 40 | .classpath 41 | .factorypath 42 | .project 43 | .apt_generated* 44 | *.dll 45 | 46 | #Claude 47 | .claude/ -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/XCANMotorControllerPIDProperties.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators; 2 | 3 | public record XCANMotorControllerPIDProperties(double p, 4 | double i, 5 | double d, 6 | double velocityFeedForward, 7 | double gravityFeedForward, 8 | double maxPowerOutput, 9 | double minPowerOutput 10 | ) { 11 | public XCANMotorControllerPIDProperties() 12 | { 13 | this(0, 0, 0); 14 | } 15 | 16 | public XCANMotorControllerPIDProperties(double p, double i, double d) { 17 | this(p, i, d, 0, 0, 1, -1); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/command/BaseSetpointCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | public abstract class BaseSetpointCommand extends BaseCommand { 4 | 5 | public BaseSetpointCommand(SupportsSetpointLock system, SupportsSetpointLock... additionalSystems) { 6 | // must require at least 1 system 7 | this.addRequirements(system.getSetpointLock()); 8 | for (SupportsSetpointLock additionalSystem : additionalSystems) { 9 | this.addRequirements(additionalSystem.getSetpointLock()); 10 | } 11 | } 12 | 13 | @Override 14 | public boolean isFinished() { 15 | // Setpoint commands end instantly by default since the set operation usually 16 | // happens in initialize and then nothing else needs to happen 17 | return true; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/electrical_contract/IMUInfo.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.electrical_contract; 2 | 3 | import xbot.common.controls.sensors.XGyro; 4 | 5 | public record IMUInfo(String name, XGyro.ImuType imuType, XGyro.InterfaceType interfaceType, CANBusId canBusId, int deviceId) { 6 | public IMUInfo(XGyro.InterfaceType interfaceType) { 7 | this("IMU", XGyro.ImuType.navX, interfaceType, null, 0); 8 | } 9 | 10 | public IMUInfo(CANBusId canBusId, int deviceId) { 11 | this("IMU", XGyro.ImuType.pigeon2, null, canBusId, deviceId); 12 | } 13 | 14 | public static IMUInfo createMock(IMUInfo realInstance) { 15 | return new IMUInfo(realInstance.name(), XGyro.ImuType.mock, realInstance.interfaceType(), realInstance.canBusId(), realInstance.deviceId()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/buttons/InvertingBooleanSupplier.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.buttons; 2 | 3 | import java.util.function.BooleanSupplier; 4 | 5 | public class InvertingBooleanSupplier implements BooleanSupplier { 6 | 7 | private boolean isInverted = false; 8 | private BooleanSupplier supplier; 9 | 10 | public InvertingBooleanSupplier(BooleanSupplier supplier) { 11 | this.supplier = supplier; 12 | } 13 | 14 | public void setInverted(boolean isInverted) { 15 | this.isInverted = isInverted; 16 | } 17 | 18 | public boolean getInverted() { 19 | return this.isInverted; 20 | } 21 | 22 | @Override 23 | public boolean getAsBoolean() { 24 | return this.supplier.getAsBoolean() ^ this.isInverted; 25 | } 26 | 27 | 28 | 29 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/io_inputs/XCANMotorControllerInputs.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.io_inputs; 2 | 3 | import edu.wpi.first.units.measure.Angle; 4 | import edu.wpi.first.units.measure.AngularVelocity; 5 | import edu.wpi.first.units.measure.Current; 6 | import edu.wpi.first.units.measure.Voltage; 7 | import org.littletonrobotics.junction.AutoLog; 8 | 9 | import static edu.wpi.first.units.Units.Amps; 10 | import static edu.wpi.first.units.Units.RPM; 11 | import static edu.wpi.first.units.Units.Rotations; 12 | import static edu.wpi.first.units.Units.Volts; 13 | 14 | @AutoLog 15 | public class XCANMotorControllerInputs { 16 | public Angle angle = Rotations.zero(); 17 | public AngularVelocity angularVelocity = RPM.zero(); 18 | public Voltage voltage = Volts.zero(); 19 | public Current current = Amps.zero(); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/buttons/ChordTrigger.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.buttons; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | import edu.wpi.first.wpilibj2.command.button.Trigger; 7 | 8 | public class ChordTrigger extends AdvancedTrigger { 9 | 10 | AdvancedTrigger a; 11 | AdvancedTrigger b; 12 | 13 | @AssistedFactory 14 | public abstract static class ChordTriggerFactory { 15 | public abstract ChordTrigger create( 16 | @Assisted("a") Trigger a, 17 | @Assisted("b") Trigger b); 18 | } 19 | 20 | @AssistedInject 21 | public ChordTrigger(@Assisted("a") Trigger a, @Assisted("b") Trigger b) { 22 | super(() -> a.getAsBoolean() && b.getAsBoolean()); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/modules/UnitTestRobotModule.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.modules; 2 | 3 | import javax.inject.Singleton; 4 | 5 | import dagger.Binds; 6 | import dagger.Module; 7 | import xbot.common.subsystems.drive.BaseDriveSubsystem; 8 | import xbot.common.subsystems.drive.MockDriveSubsystem; 9 | import xbot.common.subsystems.pose.BasePoseSubsystem; 10 | import xbot.common.subsystems.pose.MockBasePoseSubsystem; 11 | 12 | /** 13 | * Module mapping interfaces to implementations for a unit-test robot. 14 | */ 15 | @Module 16 | public abstract class UnitTestRobotModule { 17 | @Binds 18 | @Singleton 19 | abstract BasePoseSubsystem getBasePoseSubsystem(MockBasePoseSubsystem impl); 20 | 21 | @Binds 22 | @Singleton 23 | abstract BaseDriveSubsystem getBaseDriveSubsystem(MockDriveSubsystem impl); 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/injection/MockCameraElectricalContract.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection; 2 | 3 | import edu.wpi.first.math.geometry.Transform3d; 4 | import xbot.common.injection.electrical_contract.CameraInfo; 5 | import xbot.common.injection.electrical_contract.XCameraElectricalContract; 6 | import xbot.common.subsystems.vision.CameraCapabilities; 7 | 8 | import javax.inject.Inject; 9 | import java.util.EnumSet; 10 | 11 | public class MockCameraElectricalContract implements XCameraElectricalContract { 12 | 13 | @Inject 14 | public MockCameraElectricalContract() { 15 | } 16 | 17 | @Override 18 | public CameraInfo[] getCameraInfo() { 19 | return new CameraInfo[] { 20 | new CameraInfo("test", "test", new Transform3d(), EnumSet.of(CameraCapabilities.APRIL_TAG)) 21 | }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/components/SimulationComponent.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.components; 2 | 3 | import javax.inject.Singleton; 4 | 5 | import dagger.Component; 6 | import xbot.common.injection.modules.DefaultVisionModule; 7 | import xbot.common.injection.modules.MockDevicesModule; 8 | import xbot.common.injection.modules.RealControlsModule; 9 | import xbot.common.injection.modules.SimulationModule; 10 | import xbot.common.injection.modules.UnitTestRobotModule; 11 | 12 | /** 13 | * Do not use this directly. Use auto-generated class DaggerSimulationComponent. 14 | */ 15 | @Singleton 16 | @Component(modules = { SimulationModule.class, MockDevicesModule.class, RealControlsModule.class, UnitTestRobotModule.class, DefaultVisionModule.class }) 17 | public abstract class SimulationComponent extends BaseComponent { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/buttons/AdvancedTrigger.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.buttons; 2 | 3 | import java.util.function.BooleanSupplier; 4 | 5 | import edu.wpi.first.wpilibj2.command.button.Trigger; 6 | 7 | public abstract class AdvancedTrigger extends Trigger { 8 | protected InvertingBooleanSupplier supplier; 9 | 10 | public AdvancedTrigger(BooleanSupplier supplier) { 11 | this(new InvertingBooleanSupplier(supplier)); 12 | } 13 | 14 | private AdvancedTrigger(InvertingBooleanSupplier supplier) { 15 | super(supplier); 16 | this.supplier = supplier; 17 | } 18 | 19 | public void setInverted(boolean inverted) { 20 | this.supplier.setInverted(inverted); 21 | } 22 | 23 | public boolean getInverted() { 24 | return this.supplier.getInverted(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/drive/swerve/commands/ChangeActiveSwerveModuleCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.drive.swerve.commands; 2 | 3 | import xbot.common.command.BaseCommand; 4 | import xbot.common.subsystems.drive.BaseSwerveDriveSubsystem; 5 | 6 | import javax.inject.Inject; 7 | 8 | public class ChangeActiveSwerveModuleCommand extends BaseCommand { 9 | 10 | final BaseSwerveDriveSubsystem drive; 11 | 12 | @Inject 13 | public ChangeActiveSwerveModuleCommand(BaseSwerveDriveSubsystem drive) { 14 | this.drive = drive; 15 | } 16 | 17 | @Override 18 | public void initialize() { 19 | drive.setNextModuleAsActiveModule(); 20 | } 21 | 22 | @Override 23 | public void execute() { 24 | } 25 | 26 | @Override 27 | public boolean isFinished() { 28 | return true; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/injection/BaseCommonLibTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection; 2 | 3 | import xbot.common.injection.components.CommonLibTestComponent; 4 | import xbot.common.injection.components.DaggerCommonLibTestComponent; 5 | import xbot.common.properties.PropertyFactory; 6 | import xbot.common.properties.XPropertyManager; 7 | 8 | public class BaseCommonLibTest extends BaseWPITest { 9 | 10 | protected CommonLibTestComponent getInjectorComponent() { 11 | return (CommonLibTestComponent)super.getInjectorComponent(); 12 | } 13 | 14 | protected XPropertyManager getPropertyManager() { 15 | return getInjectorComponent().propertyManager(); 16 | } 17 | 18 | @Override 19 | protected CommonLibTestComponent createDaggerComponent() { 20 | return DaggerCommonLibTestComponent.create(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/XAnalogInput.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | import xbot.common.controls.XBaseIO; 4 | import xbot.common.injection.DevicePolice; 5 | import xbot.common.injection.DevicePolice.DeviceType; 6 | 7 | public abstract class XAnalogInput implements XBaseIO { 8 | 9 | protected int channel; 10 | 11 | public interface XAnalogInputFactory { 12 | XAnalogInput create(int channel); 13 | } 14 | 15 | public XAnalogInput(int channel, DevicePolice police) { 16 | this.channel = channel; 17 | police.registerDevice(DeviceType.Analog, channel, this); 18 | } 19 | 20 | public abstract double getVoltage(); 21 | 22 | public abstract double getAverageVoltage(); 23 | 24 | public abstract void setAverageBits(int bits); 25 | 26 | public abstract boolean getAsDigital(double threshold); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/electrical_contract/CameraInfo.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.electrical_contract; 2 | 3 | import edu.wpi.first.math.geometry.Transform3d; 4 | import xbot.common.subsystems.vision.CameraCapabilities; 5 | 6 | import java.util.EnumSet; 7 | 8 | /** 9 | * This class is used to provide information about the cameras on the robot. 10 | */ 11 | public record CameraInfo( 12 | String networkTablesName, 13 | String friendlyName, 14 | Transform3d position, 15 | EnumSet capabilities, 16 | boolean useForPoseEstimates) { 17 | 18 | public CameraInfo( 19 | String networkTablesName, 20 | String friendlyName, 21 | Transform3d position, 22 | EnumSet capabilities) { 23 | this(networkTablesName, friendlyName, position, capabilities, true); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/logging/LoggingLatch.java: -------------------------------------------------------------------------------- 1 | package xbot.common.logging; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | 6 | import xbot.common.logic.Latch; 7 | import xbot.common.logic.Latch.EdgeType; 8 | 9 | public class LoggingLatch { 10 | 11 | static Logger log = LogManager.getLogger(LoggingLatch.class); 12 | 13 | private final Latch latch; 14 | 15 | public LoggingLatch(String callerName, String message, EdgeType edgeType) { 16 | this.latch = new Latch(false, edgeType); 17 | 18 | latch.setObserver((e) -> { 19 | EdgeType edge =e; 20 | if(edge == edgeType) { 21 | log.info(callerName + ": " + message); 22 | } 23 | }); 24 | } 25 | 26 | public void checkValue(boolean value) { 27 | latch.setValue(value); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/logic/LogicUtilsTests.java: -------------------------------------------------------------------------------- 1 | package xbot.common.logic; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class LogicUtilsTests { 9 | 10 | @Test 11 | public void testAnyOf() { 12 | assertFalse(LogicUtils.anyOf()); 13 | assertTrue(LogicUtils.anyOf(true, true)); 14 | assertTrue(LogicUtils.anyOf(true, false)); 15 | assertTrue(LogicUtils.anyOf(false, true)); 16 | assertFalse(LogicUtils.anyOf(false, false)); 17 | } 18 | 19 | @Test 20 | public void testAllOf() { 21 | assertTrue(LogicUtils.allOf()); 22 | assertTrue(LogicUtils.allOf(true, true)); 23 | assertFalse(LogicUtils.allOf(true, false)); 24 | assertFalse(LogicUtils.allOf(false, true)); 25 | assertFalse(LogicUtils.allOf(false, false)); 26 | } 27 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/mock_adapters/MockSparkAbsoluteEncoder.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.mock_adapters; 2 | 3 | import edu.wpi.first.units.measure.Angle; 4 | import xbot.common.controls.io_inputs.XAbsoluteEncoderInputs; 5 | import xbot.common.controls.sensors.XSparkAbsoluteEncoder; 6 | 7 | public class MockSparkAbsoluteEncoder extends XSparkAbsoluteEncoder { 8 | 9 | public MockSparkAbsoluteEncoder(String nameWithPrefix, boolean inverted) { 10 | super(nameWithPrefix, inverted); 11 | } 12 | 13 | public void setMockPosition(Angle position) { 14 | inputs.position = position; 15 | } 16 | 17 | @Override 18 | public Angle getUnderlyingPosition() { 19 | return inputs.position; 20 | } 21 | 22 | @Override 23 | public void updateInputs(XAbsoluteEncoderInputs inputs) { 24 | // Nothing needed here for mock. 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/drive/swerve/SwerveSuggestedRotation.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.drive.swerve; 2 | 3 | public class SwerveSuggestedRotation { 4 | 5 | /** 6 | * Used for SwerveDriveRotationAdvisor to pass back values in one of two ways: 7 | * DesiredHeading (The heading you want to be at) 8 | * HeadingPower (The power of which you should be rotating) 9 | */ 10 | public double value; 11 | public RotationGoalType type; 12 | 13 | public enum RotationGoalType { 14 | DesiredHeading, 15 | HumanControlHeadingPower 16 | } 17 | 18 | public SwerveSuggestedRotation(double value, RotationGoalType type) { 19 | this.value = value; 20 | this.type = type; 21 | } 22 | 23 | public SwerveSuggestedRotation() { 24 | this.value = 0; 25 | this.type = RotationGoalType.HumanControlHeadingPower; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/edu/wpi/first/wpilibj/MockDistanceSensorPair.java: -------------------------------------------------------------------------------- 1 | package edu.wpi.first.wpilibj; 2 | 3 | import javax.inject.Inject; 4 | 5 | import xbot.common.controls.sensors.DistanceSensor; 6 | import xbot.common.controls.sensors.DistanceSensorPair; 7 | 8 | public class MockDistanceSensorPair implements DistanceSensorPair { 9 | 10 | private DistanceSensor sensorA; 11 | private DistanceSensor sensorB; 12 | 13 | @Inject 14 | public MockDistanceSensorPair() { 15 | sensorA = new MockDistanceSensor(); 16 | sensorB = new MockDistanceSensor(); 17 | } 18 | 19 | @Override 20 | public DistanceSensor getSensorA() { 21 | return sensorA; 22 | } 23 | 24 | @Override 25 | public DistanceSensor getSensorB() { 26 | return sensorB; 27 | } 28 | 29 | @Override 30 | public void update() { 31 | // Intentionally left blank 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/math/MovingAverageForTranslation2d.java: -------------------------------------------------------------------------------- 1 | package xbot.common.math; 2 | 3 | import edu.wpi.first.math.geometry.Translation2d; 4 | 5 | public class MovingAverageForTranslation2d extends MovingAverage { 6 | public MovingAverageForTranslation2d(int size) { 7 | super(new SumFunction() { 8 | @Override 9 | public Translation2d add(Translation2d a, Translation2d b) { 10 | return a.plus(b); 11 | } 12 | 13 | @Override 14 | public Translation2d subtract(Translation2d a, Translation2d b) { 15 | return a.minus(b); 16 | } 17 | 18 | @Override 19 | public Translation2d divide(Translation2d a, int b) { 20 | return new Translation2d(a.getX() / b, a.getY() / b); 21 | } 22 | }, new Translation2d(), size); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/swerve/SwerveComponentHolder.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.swerve; 2 | 3 | import javax.inject.Inject; 4 | import javax.inject.Singleton; 5 | 6 | /** 7 | * Contains components representing each swerve module. 8 | */ 9 | @Singleton 10 | public final class SwerveComponentHolder { 11 | public final SwerveComponent frontLeft; 12 | public final SwerveComponent frontRight; 13 | public final SwerveComponent rearLeft; 14 | public final SwerveComponent rearRight; 15 | 16 | @Inject 17 | public SwerveComponentHolder(@FrontLeftDrive SwerveComponent frontLeft, @FrontRightDrive SwerveComponent frontRight, 18 | @RearLeftDrive SwerveComponent rearLeft, @RearRightDrive SwerveComponent rearRight) { 19 | this.frontLeft = frontLeft; 20 | this.frontRight = frontRight; 21 | this.rearLeft = rearLeft; 22 | this.rearRight = rearRight; 23 | } 24 | } -------------------------------------------------------------------------------- /src/test/java/xbot/common/controls/sensors/DigitalInputTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | import org.junit.Test; 4 | import xbot.common.injection.BaseCommonLibTest; 5 | import xbot.common.injection.electrical_contract.DeviceInfo; 6 | 7 | import static org.junit.Assert.assertFalse; 8 | import static org.junit.Assert.assertTrue; 9 | 10 | public class DigitalInputTest extends BaseCommonLibTest { 11 | @Test 12 | public void testInversion() { 13 | DeviceInfo info = new DeviceInfo("TestInput", 0, false, 0); 14 | XDigitalInput digitalInput = getInjectorComponent().digitalInputFactory().create(info, "testPrefix"); 15 | 16 | assertFalse(digitalInput.getInverted()); 17 | 18 | info = new DeviceInfo("TestInput", 1, true, 0); 19 | digitalInput = getInjectorComponent().digitalInputFactory().create(info, "testPrefix"); 20 | 21 | assertTrue(digitalInput.getInverted()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/math/MathUtilsTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.math; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | import xbot.common.injection.BaseCommonLibTest; 8 | 9 | public class MathUtilsTest extends BaseCommonLibTest { 10 | 11 | @Test 12 | public void testSquareRetainSign() { 13 | assertEquals(0.75*0.75, MathUtils.squareAndRetainSign(0.75), 0.001); 14 | assertEquals(-0.75*0.75, MathUtils.squareAndRetainSign(-0.75), 0.001); 15 | } 16 | 17 | @Test 18 | public void testExponentRetainSign() { 19 | assertEquals(0.5*0.5*0.5, MathUtils.exponentAndRetainSign(0.5, 3), 0.001); 20 | assertEquals(-0.5*0.5*0.5, MathUtils.exponentAndRetainSign(-0.5, 3), 0.001); 21 | 22 | assertEquals(0.5*0.5*0.5*0.5, MathUtils.exponentAndRetainSign(0.5, 4), 0.001); 23 | assertEquals(-0.5*0.5*0.5*0.5, MathUtils.exponentAndRetainSign(-0.5, 4), 0.001); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/controls/sensors/JoystickTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Test; 6 | 7 | import xbot.common.controls.sensors.buttons.AnalogHIDButtonTrigger.AnalogHIDDescription; 8 | import xbot.common.controls.sensors.mock_adapters.MockJoystick; 9 | import xbot.common.injection.BaseCommonLibTest; 10 | 11 | public class JoystickTest extends BaseCommonLibTest { 12 | 13 | MockJoystick joystick; 14 | 15 | @Override 16 | public void setUp() { 17 | super.setUp(); 18 | 19 | joystick = (MockJoystick)getInjectorComponent().joystickFactory().create(0, 10); 20 | } 21 | 22 | @Test 23 | public void testAnalogButton() { 24 | AnalogHIDDescription desc = new AnalogHIDDescription(0, -1, -.1); 25 | joystick.addAnalogButton(desc); 26 | assertTrue(joystick.getAnalogIfAvailable(desc) != null); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.configuration.updateBuildConfiguration": "automatic", 3 | "java.test.defaultConfig": "SeriouslyCommonLib", 4 | "java.test.config": [ 5 | { 6 | "name": "SeriouslyCommonLib", 7 | "workingDirectory": "${workspaceFolder}/build/jni/release", 8 | "vmargs": [ "-Djava.library.path=${workspaceFolder}/build/jni/release" ], 9 | "env": { "LD_LIBRARY_PATH": "${workspaceFolder}/build/jni/release" , 10 | "DYLD_LIBRARY_PATH": "${workspaceFolder}/build/jni/release" } 11 | }, 12 | ], 13 | "coverage-gutters.coverageReportFileName": "html/index.html", 14 | "coverage-gutters.coverageBaseDir": "build/reports/jacoco/test", 15 | "coverage-gutters.coverageFileNames": [ 16 | "jacocoTestReport.xml" 17 | ], 18 | "java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx2G -Xms100m" 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/advantage/DataFrameRefreshable.java: -------------------------------------------------------------------------------- 1 | package xbot.common.advantage; 2 | 3 | /** 4 | * Interface for objects that need to have state refreshed before the subsystem periodic loop. 5 | *
 6 |  * graph TD
 7 |  *     A[Start scheduler loop] --> B[refreshDataFrame]
 8 |  *     B --> C[periodic]
 9 |  *     C -->D[End scheduler loop]
10 |  *     D --> A
11 |  * 
12 | */ 13 | public interface DataFrameRefreshable { 14 | 15 | /** 16 | * Consumes and processes inputs from the device or subsystem. 17 | * @apiNote This method is called before {@link xbot.common.command.BaseSubsystem#periodic} 18 | * to update the object state before the scheduler runs periodic() on all the subsystems. 19 | * You can call {@link xbot.common.command.BaseSubsystem#registerDataFrameRefreshable(DataFrameRefreshable)} 20 | * to have this method called automatically by the subsystem. 21 | */ 22 | void refreshDataFrame(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/properties/ConfigurePropertiesCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.properties; 2 | 3 | import javax.inject.Inject; 4 | 5 | import xbot.common.command.BaseCommand; 6 | 7 | public class ConfigurePropertiesCommand extends BaseCommand { 8 | 9 | ITableProxy table; 10 | boolean fastMode; 11 | 12 | @Inject 13 | public ConfigurePropertiesCommand(ITableProxy table) { 14 | this.table = table; 15 | } 16 | 17 | @Override 18 | public boolean runsWhenDisabled() { 19 | return true; 20 | } 21 | 22 | public void setFastMode(boolean on) { 23 | fastMode = on; 24 | } 25 | 26 | @Override 27 | public void initialize() { 28 | log.info("Initializing with fastMode: " + fastMode); 29 | table.setFastMode(fastMode); 30 | } 31 | 32 | @Override 33 | public void execute() { 34 | } 35 | 36 | @Override 37 | public boolean isFinished() { 38 | return true; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/pose/commands/ResetDistanceCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.pose.commands; 2 | 3 | import javax.inject.Inject; 4 | 5 | import xbot.common.command.BaseCommand; 6 | import xbot.common.subsystems.pose.BasePoseSubsystem; 7 | 8 | public class ResetDistanceCommand extends BaseCommand { 9 | 10 | protected final BasePoseSubsystem poseSubsystem; 11 | 12 | @Inject 13 | public ResetDistanceCommand(BasePoseSubsystem poseSubsystem) { 14 | this.poseSubsystem = poseSubsystem; 15 | } 16 | 17 | @Override 18 | public boolean runsWhenDisabled() { 19 | return true; 20 | } 21 | 22 | @Override 23 | public void initialize() { 24 | log.info("Initializing"); 25 | poseSubsystem.resetDistanceTraveled(); 26 | } 27 | 28 | @Override 29 | public void execute() { 30 | 31 | } 32 | 33 | @Override 34 | public boolean isFinished() { 35 | return true; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/components/PurePursuitTestComponent.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.components; 2 | 3 | import javax.inject.Singleton; 4 | 5 | import dagger.Component; 6 | import xbot.common.injection.modules.DefaultVisionModule; 7 | import xbot.common.injection.modules.MockControlsModule; 8 | import xbot.common.injection.modules.MockDevicesModule; 9 | import xbot.common.injection.modules.UnitTestModule; 10 | import xbot.common.injection.modules.UnitTestRobotModule; 11 | import xbot.common.subsystems.drive.ConfigurablePurePursuitCommand; 12 | 13 | /** 14 | * Do not use this directly. Use auto-generated class DaggerUnitTestComponent. 15 | */ 16 | @Singleton 17 | @Component(modules = {UnitTestModule.class, MockDevicesModule.class, MockControlsModule.class, UnitTestRobotModule.class, DefaultVisionModule.class}) 18 | public abstract class PurePursuitTestComponent extends BaseComponent { 19 | public abstract ConfigurablePurePursuitCommand configurablePurePursuitCommand(); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/feedback/XRumbleManager.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.feedback; 2 | 3 | import xbot.common.controls.sensors.XJoystick; 4 | 5 | public interface XRumbleManager { 6 | 7 | public interface XRumbleManagerFactory { 8 | XRumbleManager create(XJoystick gamepad); 9 | } 10 | 11 | /** 12 | * Rumbles the gamepad at the specified intensity for the given duration. 13 | * @param intensity Rumble intensity, between 0 and 1. 14 | * @param length Rumble duration, in seconds 15 | */ 16 | void rumbleGamepad(double intensity, double length); 17 | 18 | /** 19 | * Immediately stops rumbling on the gamepad. 20 | */ 21 | void stopGamepadRumble(); 22 | 23 | /** 24 | * Gets the current rumble state. 25 | * @return true if the gamepad is currently rumbling. 26 | */ 27 | boolean getIsRumbling(); 28 | 29 | /** 30 | * Called periodically to update the rumble state. 31 | */ 32 | void periodic(); 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/wpi_adapters/PowerDistributionPanelWPIAdapter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.wpi_adapters; 2 | 3 | import dagger.assisted.AssistedFactory; 4 | import dagger.assisted.AssistedInject; 5 | 6 | import edu.wpi.first.wpilibj.PowerDistribution; 7 | import xbot.common.controls.sensors.XPowerDistributionPanel; 8 | 9 | public class PowerDistributionPanelWPIAdapter extends XPowerDistributionPanel { 10 | 11 | private PowerDistribution pdp; 12 | 13 | @AssistedFactory 14 | public abstract static class PowerDistributionPanelWPIAdapaterFactory implements XPowerDistributionPanelFactory { 15 | @Override 16 | public abstract PowerDistributionPanelWPIAdapter create(); 17 | } 18 | 19 | @AssistedInject 20 | public PowerDistributionPanelWPIAdapter() { 21 | pdp = new PowerDistribution(); 22 | } 23 | 24 | @Override 25 | public double getCurrent(int channel) { 26 | return pdp.getCurrent(channel); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/edu/wpi/first/wpilibj/MockServo.java: -------------------------------------------------------------------------------- 1 | package edu.wpi.first.wpilibj; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | 7 | import xbot.common.controls.actuators.XServo; 8 | import xbot.common.injection.DevicePolice; 9 | 10 | public class MockServo extends XServo { 11 | 12 | protected double value; 13 | 14 | @AssistedFactory 15 | public abstract static class MockServoFactory implements XServoFactory { 16 | public abstract MockServo create(@Assisted("channel") int channel, @Assisted("name") String name); 17 | } 18 | 19 | @AssistedInject 20 | public MockServo(@Assisted("channel") int channel, @Assisted("name") String name, DevicePolice police) { 21 | super(channel, name, police); 22 | } 23 | 24 | @Override 25 | public void set(double value) { 26 | this.value = value; 27 | } 28 | 29 | @Override 30 | public double get(){ 31 | return value; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /vendordeps/AdvantageKit.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileName": "AdvantageKit.json", 3 | "name": "AdvantageKit", 4 | "version": "4.0.0", 5 | "uuid": "d820cc26-74e3-11ec-90d6-0242ac120003", 6 | "frcYear": "2025", 7 | "mavenUrls": [ 8 | "https://frcmaven.wpi.edu/artifactory/littletonrobotics-mvn-release/" 9 | ], 10 | "jsonUrl": "https://github.com/Mechanical-Advantage/AdvantageKit/releases/latest/download/AdvantageKit.json", 11 | "javaDependencies": [ 12 | { 13 | "groupId": "org.littletonrobotics.akit", 14 | "artifactId": "akit-java", 15 | "version": "4.0.0" 16 | } 17 | ], 18 | "jniDependencies": [ 19 | { 20 | "groupId": "org.littletonrobotics.akit", 21 | "artifactId": "akit-wpilibio", 22 | "version": "4.0.0", 23 | "skipInvalidPlatforms": false, 24 | "isJar": false, 25 | "validPlatforms": [ 26 | "linuxathena", 27 | "windowsx86-64", 28 | "linuxx86-64", 29 | "osxuniversal" 30 | ] 31 | } 32 | ], 33 | "cppDependencies": [] 34 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/drive/CalculatorNode.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.drive; 2 | 3 | 4 | import edu.wpi.first.units.measure.LinearAcceleration; 5 | import edu.wpi.first.units.measure.LinearVelocity; 6 | import edu.wpi.first.units.measure.Time; 7 | 8 | import static edu.wpi.first.units.Units.MetersPerSecond; 9 | import static edu.wpi.first.units.Units.MetersPerSecondPerSecond; 10 | import static edu.wpi.first.units.Units.Seconds; 11 | 12 | /** 13 | * CalculatorNodes are small little steps to be interpreted and formed together to 14 | * create a path to be used for the SwerveKinematicsCalculator 15 | */ 16 | public record CalculatorNode(Time operationTime, LinearAcceleration operationAcceleration, LinearVelocity operationEndingVelocity) { 17 | 18 | public CalculatorNode(double operationTimeInSeconds, double operationAcceleration, double operationEndingVelocity) { 19 | this(Seconds.of(operationTimeInSeconds), MetersPerSecondPerSecond.of(operationAcceleration), MetersPerSecond.of(operationEndingVelocity)); 20 | } 21 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/electrical_contract/XCameraElectricalContract.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.electrical_contract; 2 | 3 | import xbot.common.subsystems.vision.CameraCapabilities; 4 | 5 | import java.util.Arrays; 6 | 7 | /** 8 | * This interface is used to provide information about the cameras on the robot. 9 | */ 10 | public interface XCameraElectricalContract { 11 | /** 12 | * Get the information about the cameras on the robot. 13 | * 14 | * @return An array of CameraInfo objects, each representing a camera on the robot. 15 | */ 16 | CameraInfo[] getCameraInfo(); 17 | 18 | /** 19 | * Get the information about the cameras on the robot that support AprilTag detection. 20 | * 21 | * @return An array of CameraInfo objects, each representing a camera on the robot. 22 | */ 23 | default CameraInfo[] getAprilTagCameras() { 24 | return Arrays.stream(getCameraInfo()).filter(info -> info.capabilities().contains(CameraCapabilities.APRIL_TAG)).toArray(CameraInfo[]::new); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/wpi_adapters/TimerWpiAdapter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.wpi_adapters; 2 | 3 | import javax.inject.Inject; 4 | import javax.inject.Singleton; 5 | 6 | import edu.wpi.first.wpilibj.Timer; 7 | import xbot.common.controls.sensors.XSettableTimerImpl; 8 | 9 | @Singleton 10 | public class TimerWpiAdapter implements XSettableTimerImpl { 11 | 12 | @Inject 13 | public TimerWpiAdapter() {} 14 | 15 | @Override 16 | public double getFPGATimestamp() { 17 | return Timer.getFPGATimestamp(); 18 | } 19 | 20 | @Override 21 | public double getMatchTime() { 22 | return Timer.getMatchTime(); 23 | } 24 | 25 | @Override 26 | public void delay(double seconds) { 27 | Timer.delay(seconds); 28 | } 29 | 30 | @Override 31 | public void setTimeInSeconds(double time) { 32 | // Deliberately do nothing. 33 | } 34 | 35 | @Override 36 | public void advanceTimeInSecondsBy(double time) { 37 | // Deliberately do nothing. 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/drive/SwerveSimpleTrajectoryMode.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.drive; 2 | 3 | /** 4 | * Different ways to input values for SwerveSimpleTrajectoryCommand 5 | */ 6 | public enum SwerveSimpleTrajectoryMode { 7 | 8 | /** 9 | * A constant velocity (in meters) throughout the course of our travel 10 | */ 11 | ConstantVelocity, 12 | 13 | /** 14 | * A duration from point A to point B throughout the course of our travel 15 | * NOTE: It is suggested to use ConstantVelocity mode instead for better consistency! 16 | */ 17 | DurationInSeconds, 18 | 19 | /** 20 | * Each point will have its own set of kinematics values it'll use (acceleration, velocity, etc.) 21 | * NOTE: You'll have to calculate the start and ending velocities of each individual point! 22 | * Suggested to use GlobalKinematicsValue instead! 23 | */ 24 | KinematicsForIndividualPoints, 25 | 26 | /** 27 | * One set of kinematics values for the entire route 28 | */ 29 | GlobalKinematicsValue 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/wpi_adapters/RelayWPIAdapter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators.wpi_adapters; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | 7 | import edu.wpi.first.wpilibj.Relay; 8 | import edu.wpi.first.wpilibj.Relay.Value; 9 | import xbot.common.controls.actuators.XRelay; 10 | import xbot.common.injection.DevicePolice; 11 | 12 | public class RelayWPIAdapter extends XRelay { 13 | 14 | Relay internalRelay; 15 | 16 | @AssistedFactory 17 | public abstract static class RelayWPIAdapterFactory implements XRelayFactory { 18 | public abstract RelayWPIAdapter create(@Assisted("channel") int channel); 19 | } 20 | 21 | @AssistedInject 22 | public RelayWPIAdapter(@Assisted("channel") int channel, DevicePolice police) { 23 | super(channel, police); 24 | internalRelay = new Relay(channel); 25 | } 26 | 27 | @Override 28 | public void set(Value value) { 29 | internalRelay.set(value); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/command/DelayViaSupplierCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import java.util.function.DoubleSupplier; 4 | 5 | import xbot.common.controls.sensors.XTimer; 6 | 7 | public class DelayViaSupplierCommand extends BaseCommand { 8 | 9 | protected double startTime; 10 | protected DoubleSupplier delaySupplier; 11 | 12 | public DelayViaSupplierCommand(DoubleSupplier delaySupplier) { 13 | this.delaySupplier = delaySupplier; 14 | } 15 | 16 | @Override 17 | public void initialize() { 18 | this.startTime = XTimer.getFPGATimestamp(); 19 | log.info("Initializing with intial time: " + startTime + " and waiting for " + delaySupplier.getAsDouble() + " seconds"); 20 | } 21 | 22 | @Override 23 | public void execute() { 24 | // Do nothing 25 | } 26 | 27 | @Override 28 | public boolean isFinished() { 29 | return isTimeoutExpired(); 30 | } 31 | 32 | private boolean isTimeoutExpired() { 33 | return XTimer.getFPGATimestamp() > startTime + delaySupplier.getAsDouble(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/mock_adapters/MockRelay.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators.mock_adapters; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | 7 | import edu.wpi.first.wpilibj.Relay.Value; 8 | import xbot.common.controls.actuators.XRelay; 9 | import xbot.common.injection.DevicePolice; 10 | 11 | public class MockRelay extends XRelay { 12 | 13 | private Value internalValue; 14 | 15 | @AssistedFactory 16 | public abstract static class MockRelayFactory implements XRelayFactory { 17 | public abstract MockRelay create(@Assisted("channel") int channel); 18 | } 19 | 20 | @AssistedInject 21 | public MockRelay(@Assisted("channel") int channel, DevicePolice police) { 22 | super(channel, police); 23 | 24 | internalValue = Value.kOff; 25 | } 26 | @Override 27 | public void set(Value value) { 28 | internalValue = value; 29 | } 30 | 31 | public Value get() { 32 | return internalValue; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/XTimer.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | import static edu.wpi.first.units.Units.Seconds; 4 | 5 | import edu.wpi.first.units.measure.Time; 6 | 7 | public class XTimer 8 | { 9 | private static XTimerImpl impl; 10 | 11 | public static void setImplementation(XTimerImpl implementation) { 12 | impl = implementation; 13 | } 14 | 15 | /** 16 | * Returns the current time in seconds since the FPGA was powered on. 17 | * @return Time in seconds 18 | */ 19 | public static double getFPGATimestamp() { 20 | return impl.getFPGATimestamp(); 21 | } 22 | 23 | /** 24 | * Returns the current time in seconds since the FPGA was powered on. 25 | * @return Time in seconds 26 | */ 27 | public static Time getFPGATimestampTime() { 28 | return Seconds.of(impl.getFPGATimestamp()); 29 | } 30 | 31 | public static double getMatchTime() { 32 | return impl.getMatchTime(); 33 | } 34 | public static void delay(double seconds) { 35 | impl.delay(seconds); 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/math/XYPairStruct.java: -------------------------------------------------------------------------------- 1 | package xbot.common.math; 2 | 3 | import edu.wpi.first.util.struct.Struct; 4 | 5 | import java.nio.ByteBuffer; 6 | 7 | public class XYPairStruct implements Struct { 8 | @Override 9 | public Class getTypeClass() { 10 | return XYPair.class; 11 | } 12 | 13 | @Override 14 | public String getTypeString() { 15 | return "struct:XYPair"; 16 | } 17 | 18 | @Override 19 | public int getSize() { 20 | return kSizeDouble * 2; 21 | } 22 | 23 | @Override 24 | public String getSchema() { 25 | return "double x;double y"; 26 | } 27 | 28 | @Override 29 | public XYPair unpack(ByteBuffer bb) { 30 | double x = bb.getDouble(); 31 | double y = bb.getDouble(); 32 | return new XYPair(x, y); 33 | } 34 | 35 | @Override 36 | public void pack(ByteBuffer bb, XYPair value) { 37 | bb.putDouble(value.x); 38 | bb.putDouble(value.y); 39 | } 40 | 41 | @Override 42 | public String getTypeName() { 43 | return "XYPair"; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | Seriously Common Lib is a collection of common solutions to robot problems 5 | that FRC teams face while using WPILib and Java. It attempts to streamline 6 | basic functionality, provide the framework for more advanced programs, and 7 | promote clean and well-written code. It functions primarily as a wrapper 8 | around WPILib which allows the robot code to run separately from the 9 | robot-specific library and HAL, enabling unit tests that can be run on a 10 | PC or CI server. 11 |

12 |

13 | For new teams that are haven't done much advanced programming before, 14 | this library has all the core code that is needed to get a robot running 15 | with advanced functionality without having to write the core systems 16 | from scratch. For more advanced teams, the common lib gives you a solid 17 | foundation of all the basics to start building your robot code on top of. 18 | You don't need to use the pre-built drive system or any of the other parts 19 | of the library if you don't want to; it's all modular. 20 |

21 | 22 | 23 | -------------------------------------------------------------------------------- /vendordeps/PathplannerLib.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileName": "PathplannerLib.json", 3 | "name": "PathplannerLib", 4 | "version": "2025.1.1", 5 | "uuid": "1b42324f-17c6-4875-8e77-1c312bc8c786", 6 | "frcYear": "2025", 7 | "mavenUrls": [ 8 | "https://3015rangerrobotics.github.io/pathplannerlib/repo" 9 | ], 10 | "jsonUrl": "https://3015rangerrobotics.github.io/pathplannerlib/PathplannerLib.json", 11 | "javaDependencies": [ 12 | { 13 | "groupId": "com.pathplanner.lib", 14 | "artifactId": "PathplannerLib-java", 15 | "version": "2025.1.1" 16 | } 17 | ], 18 | "jniDependencies": [], 19 | "cppDependencies": [ 20 | { 21 | "groupId": "com.pathplanner.lib", 22 | "artifactId": "PathplannerLib-cpp", 23 | "version": "2025.1.1", 24 | "libName": "PathplannerLib", 25 | "headerClassifier": "headers", 26 | "sharedLibrary": false, 27 | "skipInvalidPlatforms": true, 28 | "binaryPlatforms": [ 29 | "windowsx86-64", 30 | "linuxx86-64", 31 | "osxuniversal", 32 | "linuxathena", 33 | "linuxarm32", 34 | "linuxarm64" 35 | ] 36 | } 37 | ] 38 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/mock_adapters/MockCompressor.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators.mock_adapters; 2 | 3 | import dagger.assisted.AssistedFactory; 4 | import dagger.assisted.AssistedInject; 5 | 6 | import xbot.common.controls.actuators.XCompressor; 7 | 8 | public class MockCompressor extends XCompressor { 9 | 10 | private boolean isEnabled = true; 11 | 12 | @AssistedFactory 13 | public abstract static class MockCompressorFactory implements XCompressorFactory { 14 | public abstract MockCompressor create(); 15 | } 16 | 17 | @AssistedInject 18 | public MockCompressor() { 19 | 20 | } 21 | 22 | @Override 23 | public void disable() { 24 | isEnabled = false; 25 | } 26 | 27 | @Override 28 | public void enable() { 29 | isEnabled = true; 30 | } 31 | 32 | @Override 33 | public boolean isEnabled() { 34 | return isEnabled; 35 | } 36 | 37 | @Override 38 | public double getCurrent() { 39 | return 0; 40 | } 41 | 42 | @Override 43 | public boolean isAtTargetPressure() { 44 | return true; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/edu/wpi/first/wpilibj/MockTimer.java: -------------------------------------------------------------------------------- 1 | package edu.wpi.first.wpilibj; 2 | 3 | import javax.inject.Inject; 4 | import javax.inject.Singleton; 5 | 6 | import xbot.common.controls.sensors.XSettableTimerImpl; 7 | 8 | @Singleton 9 | public class MockTimer implements XSettableTimerImpl { 10 | 11 | @Inject 12 | public MockTimer() {} 13 | 14 | double timeInSeconds; 15 | 16 | @Override 17 | public void setTimeInSeconds(double time) { 18 | timeInSeconds = time; 19 | } 20 | 21 | @Override 22 | public void advanceTimeInSecondsBy(double time) { 23 | timeInSeconds += time; 24 | } 25 | 26 | /** 27 | * Return the system clock time in seconds. Return the time from the FPGA hardware clock in seconds since the FPGA 28 | * started. 29 | * 30 | * @return Robot running time in seconds. 31 | */ 32 | @Override 33 | public double getFPGATimestamp() { 34 | return timeInSeconds; 35 | } 36 | 37 | @Override 38 | public double getMatchTime() { 39 | return timeInSeconds; 40 | } 41 | 42 | @Override 43 | public void delay(double seconds) { 44 | 45 | } 46 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/math/MovingAverage.java: -------------------------------------------------------------------------------- 1 | package xbot.common.math; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | public class MovingAverage { 7 | private int size = 15; 8 | private Queue queue; 9 | private T sum; 10 | private SumFunction sumFunction; 11 | 12 | public MovingAverage(SumFunction sumFunction, T initialValue, int size) { 13 | this.queue = new LinkedList<>(); 14 | this.sum = initialValue; 15 | this.sumFunction = sumFunction; 16 | this.size = size; 17 | } 18 | 19 | public void add(T value) { 20 | sum = sumFunction.add(sum, value); 21 | queue.add(value); 22 | if (queue.size() > size) { 23 | sum = sumFunction.subtract(sum, queue.remove()); 24 | } 25 | } 26 | 27 | public T getAverage() { 28 | if (queue.isEmpty()) { 29 | return sum; 30 | } 31 | return sumFunction.divide(sum, queue.size()); 32 | } 33 | 34 | public interface SumFunction { 35 | T add(T a, T b); 36 | T subtract(T a, T b); 37 | T divide(T a, int b); 38 | } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/networking/MockZeromqListener.java: -------------------------------------------------------------------------------- 1 | package xbot.common.networking; 2 | 3 | import java.util.function.Consumer; 4 | 5 | import dagger.assisted.Assisted; 6 | import dagger.assisted.AssistedFactory; 7 | import dagger.assisted.AssistedInject; 8 | 9 | public class MockZeromqListener implements XZeromqListener { 10 | 11 | @AssistedFactory 12 | public abstract static class MockZeromqListenerFactory implements XZeromqListenerFactory { 13 | public abstract MockZeromqListener create( 14 | @Assisted("connectionString") String connectionString, 15 | @Assisted("topic") String topic); 16 | } 17 | 18 | @AssistedInject 19 | public MockZeromqListener(@Assisted("connectionString") String connectionString, @Assisted("topic") String topic) { 20 | } 21 | 22 | Consumer handler; 23 | 24 | @Override 25 | public void start() { 26 | 27 | } 28 | 29 | @Override 30 | public void setNewPacketHandler(Consumer handler) { 31 | this.handler = handler; 32 | } 33 | 34 | public void sendPacket(String packet) { 35 | handler.accept(packet); 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | import org.gradle.internal.os.OperatingSystem 2 | 3 | pluginManagement { 4 | repositories { 5 | mavenLocal() 6 | gradlePluginPortal() 7 | String frcYear = '2025' 8 | File frcHome 9 | if (OperatingSystem.current().isWindows()) { 10 | String publicFolder = System.getenv('PUBLIC') 11 | if (publicFolder == null) { 12 | publicFolder = "C:\\Users\\Public" 13 | } 14 | def homeRoot = new File(publicFolder, "wpilib") 15 | frcHome = new File(homeRoot, frcYear) 16 | } else { 17 | def userFolder = System.getProperty("user.home") 18 | def homeRoot = new File(userFolder, "wpilib") 19 | frcHome = new File(homeRoot, frcYear) 20 | } 21 | def frcHomeMaven = new File(frcHome, 'maven') 22 | maven { 23 | name 'frcHome' 24 | url frcHomeMaven 25 | } 26 | } 27 | } 28 | 29 | Properties props = System.getProperties(); 30 | props.setProperty("org.gradle.internal.native.headers.unresolved.dependencies.ignore", "true"); 31 | 32 | rootProject.name = 'SeriouslyCommonLib' 33 | 34 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/command/MockSetpointSubsystem.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import javax.inject.Inject; 4 | import javax.inject.Singleton; 5 | 6 | @Singleton 7 | public class MockSetpointSubsystem extends BaseSetpointSubsystem { 8 | 9 | private Double currentValue = 0.0; 10 | 11 | @Inject 12 | public MockSetpointSubsystem() {} 13 | 14 | @Override 15 | public Double getCurrentValue() { 16 | return this.currentValue; 17 | } 18 | 19 | public void setCurrentValue(double value) { 20 | this.currentValue = value; 21 | } 22 | 23 | @Override 24 | public Double getTargetValue() { 25 | return 0.0; 26 | } 27 | 28 | @Override 29 | public void setTargetValue(Double value) { 30 | 31 | } 32 | 33 | @Override 34 | public void setPower(Double power) { 35 | } 36 | 37 | @Override 38 | public boolean isCalibrated() { 39 | return false; 40 | } 41 | 42 | @Override 43 | protected boolean areTwoTargetsEquivalent(Double target1, Double target2) { 44 | return BaseSetpointSubsystem.areTwoDoublesEquivalent(target1, target2); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/wpi_adapters/ServoWPIAdapter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators.wpi_adapters; 2 | 3 | import xbot.common.controls.actuators.XServo; 4 | import xbot.common.injection.DevicePolice; 5 | import dagger.assisted.Assisted; 6 | import dagger.assisted.AssistedFactory; 7 | import dagger.assisted.AssistedInject; 8 | 9 | import edu.wpi.first.wpilibj.Servo; 10 | 11 | public class ServoWPIAdapter extends XServo { 12 | 13 | Servo servo; 14 | 15 | @AssistedFactory 16 | public abstract static class ServoWPIAdapterFactory implements XServoFactory { 17 | public abstract ServoWPIAdapter create(@Assisted("channel") int channel, @Assisted("name") String name); 18 | } 19 | 20 | @AssistedInject 21 | public ServoWPIAdapter(@Assisted("channel") int channel, @Assisted("name") String name, DevicePolice police) { 22 | super(channel, name, police); 23 | this.servo = new Servo(channel); 24 | } 25 | 26 | @Override 27 | public void set(double value) { 28 | this.servo.set(value); 29 | } 30 | 31 | @Override 32 | public double get() { 33 | return this.servo.get(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/command/SetTargetCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | /** 4 | * A command that sets a target value on a BaseSetpointSubsystem. 5 | * @param The type of the target value. 6 | */ 7 | public class SetTargetCommand extends BaseSetpointCommand { 8 | 9 | protected TargetT targetValue; 10 | protected final BaseSetpointSubsystem system; 11 | 12 | /** 13 | * Creates a new SetTargetCommand. 14 | * @param system The BaseSetpointSubsystem to set the target value on. 15 | */ 16 | public SetTargetCommand(BaseSetpointSubsystem system) { 17 | super(system); 18 | 19 | this.system = system; 20 | } 21 | 22 | /** 23 | * Sets the target value to be applied when the command is initialized. 24 | * @param value The target value to set. 25 | */ 26 | public void setTargetValue(TargetT value) { 27 | this.targetValue = value; 28 | } 29 | 30 | @Override 31 | public void initialize() { 32 | system.setTargetValue(this.targetValue); 33 | } 34 | 35 | @Override 36 | public boolean isFinished() { 37 | return false; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/electrical_contract/DeviceInfo.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.electrical_contract; 2 | 3 | public class DeviceInfo { 4 | public int channel; 5 | public boolean inverted; 6 | public double simulationScalingValue; 7 | public String name; 8 | public CANBusId canBusId = CANBusId.RIO; 9 | 10 | public DeviceInfo(String name, int channel){ 11 | this.name = name; 12 | this.channel = channel; 13 | } 14 | 15 | public DeviceInfo(String name, CANBusId canBusId, int channel){ 16 | this(name, channel); 17 | this.canBusId = canBusId; 18 | } 19 | 20 | public DeviceInfo(String name, CANBusId canBusId, int channel, boolean inverted){ 21 | this(name, canBusId, channel); 22 | this.inverted = inverted; 23 | } 24 | 25 | public DeviceInfo(String name, int channel, boolean inverted) { 26 | this(name, channel); 27 | this.inverted = inverted; 28 | } 29 | 30 | public DeviceInfo(String name, int channel, boolean inverted, double simulationScalingValue) { 31 | this(name, channel, inverted); 32 | this.simulationScalingValue = simulationScalingValue; 33 | } 34 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/buttons/AnalogHIDButtonConfiguration.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.buttons; 2 | 3 | import java.util.function.BooleanSupplier; 4 | 5 | import xbot.common.controls.sensors.XJoystick; 6 | 7 | public class AnalogHIDButtonConfiguration { 8 | 9 | XJoystick m_joystick; 10 | int m_axisNumber; 11 | 12 | double m_analogMinThreshold; 13 | double m_analogMaxThreshold; 14 | 15 | public AnalogHIDButtonConfiguration(XJoystick joystick, int axisNumber, double analogMinThreshold, double analogMaxThreshold) { 16 | m_joystick = joystick; 17 | m_axisNumber = axisNumber; 18 | m_analogMinThreshold = analogMinThreshold; 19 | m_analogMaxThreshold = analogMaxThreshold; 20 | } 21 | 22 | /** 23 | * Supplier indicates whether the analog value is in the button's range 24 | * 25 | * @return A supplier for the value of the joystick button 26 | */ 27 | public BooleanSupplier getSupplier() { 28 | return () -> { 29 | double data = m_joystick.getRawAxis(m_axisNumber); 30 | return data >= m_analogMinThreshold && data <= m_analogMaxThreshold; 31 | }; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/XDigitalOutput.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators; 2 | 3 | import xbot.common.controls.XBaseIO; 4 | import xbot.common.injection.DevicePolice; 5 | import xbot.common.injection.DevicePolice.DeviceType; 6 | 7 | public abstract class XDigitalOutput implements XBaseIO { 8 | 9 | protected int channel; 10 | 11 | public interface XDigitalOutputFactory { 12 | XDigitalOutput create(int channel); 13 | } 14 | 15 | protected XDigitalOutput(int channel, DevicePolice police) { 16 | this.channel = channel; 17 | police.registerDevice(DeviceType.DigitalIO, channel, this); 18 | } 19 | 20 | public int getChannel() { 21 | return channel; 22 | } 23 | 24 | public abstract void set(boolean value); 25 | 26 | /** 27 | * Set the PWM frequency of ALL DIGITAL OUTPUT PWM CHANNELS 28 | * @param frequency PWM frequency 29 | */ 30 | public abstract void setPWMRate(double frequency); 31 | public abstract void enablePWM(double initialDutyCycle); 32 | public abstract void updateDutyCycle(double dutyCycle); 33 | public abstract void disablePWM(); 34 | public abstract boolean get(); 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/electrical_contract/CANMotorControllerOutputConfig.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.electrical_contract; 2 | 3 | import edu.wpi.first.units.measure.Current; 4 | 5 | import static edu.wpi.first.units.Units.Amps; 6 | 7 | public class CANMotorControllerOutputConfig { 8 | public enum InversionType { 9 | Normal, 10 | Inverted 11 | } 12 | 13 | public enum NeutralMode { 14 | Brake, 15 | Coast 16 | } 17 | 18 | public InversionType inversionType = InversionType.Normal; 19 | 20 | public NeutralMode neutralMode = NeutralMode.Coast; 21 | 22 | public Current statorCurrentLimit = Amps.of(80); 23 | 24 | public CANMotorControllerOutputConfig withInversionType(InversionType inversionType) { 25 | this.inversionType = inversionType; 26 | return this; 27 | } 28 | 29 | public CANMotorControllerOutputConfig withNeutralMode(NeutralMode neutralMode) { 30 | this.neutralMode = neutralMode; 31 | return this; 32 | } 33 | 34 | public CANMotorControllerOutputConfig withStatorCurrentLimit(Current statorCurrentLimit) { 35 | this.statorCurrentLimit = statorCurrentLimit; 36 | return this; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/logging/TimeLoggerTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.logging; 2 | 3 | import org.junit.Test; 4 | 5 | import xbot.common.injection.BaseCommonLibTest; 6 | 7 | public class TimeLoggerTest extends BaseCommonLibTest { 8 | 9 | TimeLogger tl; 10 | 11 | @Override 12 | public void setUp() { 13 | super.setUp(); 14 | tl = new TimeLogger("Examplo", 1); 15 | } 16 | 17 | @Test 18 | public void simpleTest() { 19 | tl.start(); 20 | 21 | timer.advanceTimeInSecondsBy(2); 22 | tl.stop(); 23 | } 24 | 25 | @Test 26 | public void testMultipleMeasurements() { 27 | tl.start(); 28 | timer.advanceTimeInSecondsBy(0.25); 29 | tl.stop(); 30 | 31 | timer.advanceTimeInSecondsBy(1); 32 | 33 | tl.start(); 34 | timer.advanceTimeInSecondsBy(0.75); 35 | tl.stop(); 36 | } 37 | 38 | @Test 39 | public void testOutOfOrder() { 40 | tl.stop(); 41 | tl.stop(); 42 | tl.stop(); 43 | 44 | tl.start(); 45 | tl.start(); 46 | tl.start(); 47 | 48 | tl.stop(); 49 | tl.stop(); 50 | tl.stop(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/XSolenoid.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators; 2 | 3 | import xbot.common.controls.XBaseIO; 4 | import xbot.common.injection.DevicePolice; 5 | import xbot.common.injection.DevicePolice.DeviceType; 6 | 7 | public abstract class XSolenoid implements XBaseIO { 8 | 9 | protected boolean isInverted = false; 10 | protected final int channel; 11 | 12 | public interface XSolenoidFactory { 13 | XSolenoid create(int channel); 14 | } 15 | 16 | protected XSolenoid(int channel, DevicePolice police) { 17 | this.channel = channel; 18 | police.registerDevice(DeviceType.Solenoid, this.channel, 0, getMaxSupportedChannel()); 19 | } 20 | 21 | public void setOn(boolean on) { 22 | set(on ^ isInverted); 23 | } 24 | 25 | public boolean getAdjusted() { 26 | return get() ^ isInverted; 27 | } 28 | 29 | public void setInverted(boolean isInverted) { 30 | this.isInverted = isInverted; 31 | } 32 | 33 | public int getChannel() { 34 | return channel; 35 | } 36 | 37 | protected abstract void set(boolean on); 38 | protected abstract boolean get(); 39 | protected abstract int getMaxSupportedChannel(); 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/XSparkAbsoluteEncoder.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | import edu.wpi.first.units.measure.Angle; 4 | import org.littletonrobotics.junction.Logger; 5 | 6 | import xbot.common.advantage.DataFrameRefreshable; 7 | import xbot.common.controls.io_inputs.XAbsoluteEncoderInputs; 8 | import xbot.common.controls.io_inputs.XAbsoluteEncoderInputsAutoLogged; 9 | 10 | public abstract class XSparkAbsoluteEncoder implements DataFrameRefreshable { 11 | 12 | protected XAbsoluteEncoderInputsAutoLogged inputs; 13 | boolean inverted; 14 | 15 | String nameWithPrefix; 16 | 17 | public XSparkAbsoluteEncoder(String nameWithPrefix, boolean inverted) { 18 | inputs = new XAbsoluteEncoderInputsAutoLogged(); 19 | this.nameWithPrefix = nameWithPrefix; 20 | this.inverted = inverted; 21 | } 22 | 23 | public Angle getPosition() { 24 | return getUnderlyingPosition().times(inverted ? -1 : 1); 25 | } 26 | 27 | public abstract Angle getUnderlyingPosition(); 28 | 29 | public abstract void updateInputs(XAbsoluteEncoderInputs inputs); 30 | 31 | public void refreshDataFrame() { 32 | updateInputs(inputs); 33 | Logger.processInputs(nameWithPrefix, inputs); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/edu/wpi/first/wpilibj/MockSpeedController.java: -------------------------------------------------------------------------------- 1 | package edu.wpi.first.wpilibj; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | 6 | import dagger.assisted.Assisted; 7 | import dagger.assisted.AssistedFactory; 8 | import dagger.assisted.AssistedInject; 9 | 10 | import xbot.common.controls.actuators.XSpeedController; 11 | import xbot.common.injection.DevicePolice; 12 | 13 | public class MockSpeedController extends XSpeedController { 14 | 15 | private static Logger log = LogManager.getLogger(MockSpeedController.class); 16 | protected double value; 17 | 18 | @AssistedFactory 19 | public abstract static class MockSpeedControllerFactory implements XSpeedControllerFactory { 20 | public abstract MockSpeedController create(@Assisted("channel") int channel); 21 | } 22 | 23 | @AssistedInject 24 | public MockSpeedController(@Assisted("channel") int channel, DevicePolice police) { 25 | super(channel, police); 26 | log.info("Creating speed controller on channel:" + channel); 27 | } 28 | 29 | @Override 30 | public double get() { 31 | return value; 32 | } 33 | 34 | @Override 35 | public void set(double output) { 36 | value = output; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vendordeps/WPILibNewCommands.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileName": "WPILibNewCommands.json", 3 | "name": "WPILib-New-Commands", 4 | "version": "1.0.0", 5 | "uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266", 6 | "frcYear": "2025", 7 | "mavenUrls": [], 8 | "jsonUrl": "", 9 | "javaDependencies": [ 10 | { 11 | "groupId": "edu.wpi.first.wpilibNewCommands", 12 | "artifactId": "wpilibNewCommands-java", 13 | "version": "wpilib" 14 | } 15 | ], 16 | "jniDependencies": [], 17 | "cppDependencies": [ 18 | { 19 | "groupId": "edu.wpi.first.wpilibNewCommands", 20 | "artifactId": "wpilibNewCommands-cpp", 21 | "version": "wpilib", 22 | "libName": "wpilibNewCommands", 23 | "headerClassifier": "headers", 24 | "sourcesClassifier": "sources", 25 | "sharedLibrary": true, 26 | "skipInvalidPlatforms": true, 27 | "binaryPlatforms": [ 28 | "linuxathena", 29 | "linuxarm32", 30 | "linuxarm64", 31 | "windowsx86-64", 32 | "windowsx86", 33 | "linuxx86-64", 34 | "osxuniversal" 35 | ] 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/XGyroFactoryImpl.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | import xbot.common.controls.sensors.wpi_adapters.InertialMeasurementUnitAdapter; 4 | import xbot.common.controls.sensors.wpi_adapters.Pigeon2Adapter; 5 | import xbot.common.injection.electrical_contract.IMUInfo; 6 | 7 | import javax.inject.Inject; 8 | 9 | public class XGyroFactoryImpl extends XGyro.XGyroFactory { 10 | private final Pigeon2Adapter.Pigeon2AdapterFactory pigeon2Factory; 11 | private final InertialMeasurementUnitAdapter.InertialMeasurementUnitAdapterFactory navXFactory; 12 | 13 | @Inject 14 | public XGyroFactoryImpl( 15 | Pigeon2Adapter.Pigeon2AdapterFactory pigeon2Factory, 16 | InertialMeasurementUnitAdapter.InertialMeasurementUnitAdapterFactory navXFactory 17 | ) { 18 | this.pigeon2Factory = pigeon2Factory; 19 | this.navXFactory = navXFactory; 20 | } 21 | 22 | @Override 23 | public XGyro create(IMUInfo imuInfo) { 24 | switch (imuInfo.imuType()) { 25 | case pigeon2 -> { 26 | return pigeon2Factory.create(imuInfo); 27 | } 28 | default -> { 29 | return navXFactory.create(imuInfo); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/wpi_adapters/SpeedControllerWPIAdapter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators.wpi_adapters; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | 7 | import edu.wpi.first.wpilibj.motorcontrol.PWMMotorController; 8 | import edu.wpi.first.wpilibj.motorcontrol.Talon; 9 | import xbot.common.controls.actuators.XSpeedController; 10 | import xbot.common.injection.DevicePolice; 11 | 12 | public class SpeedControllerWPIAdapter extends XSpeedController 13 | { 14 | private PWMMotorController controller; 15 | 16 | @AssistedFactory 17 | public abstract static class SpeedControllerWPIAdapterFactory implements XSpeedControllerFactory { 18 | public abstract SpeedControllerWPIAdapter create(@Assisted("channel") int channel); 19 | } 20 | 21 | @AssistedInject 22 | public SpeedControllerWPIAdapter(@Assisted("channel") int channel, DevicePolice police) 23 | { 24 | super(channel, police); 25 | controller = new Talon(channel); 26 | } 27 | 28 | public double get() 29 | { 30 | return controller.get(); 31 | } 32 | 33 | public void set(double value) 34 | { 35 | controller.set(value); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/XCompressor.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators; 2 | 3 | /** 4 | * Represents an air compressor. 5 | */ 6 | public abstract class XCompressor { 7 | /** 8 | * A factory to create XCompressor instances. 9 | */ 10 | public interface XCompressorFactory { 11 | /** 12 | * Creates an XCompressor instance. 13 | * @return The XCompressor instance. 14 | */ 15 | XCompressor create(); 16 | } 17 | 18 | /** 19 | * Disable the compressor. 20 | */ 21 | public abstract void disable(); 22 | 23 | /** 24 | * Enable the compressor. 25 | */ 26 | public abstract void enable(); 27 | 28 | /** 29 | * Get if the compressor is currently enabled. 30 | * @return True if the compressor is enabled. 31 | */ 32 | public abstract boolean isEnabled(); 33 | 34 | /** 35 | * Gets the current drawn by the compressor. 36 | * @return The current drawn by the compressor, in amps. 37 | */ 38 | public abstract double getCurrent(); 39 | 40 | /** 41 | * Gets whether the compressor is at its target pressure. 42 | * @return True if the compressor is at its target pressure. 43 | */ 44 | public abstract boolean isAtTargetPressure(); 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/XSpeedController.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators; 2 | 3 | import xbot.common.controls.XBaseIO; 4 | import xbot.common.injection.DevicePolice; 5 | import xbot.common.injection.DevicePolice.DeviceType; 6 | 7 | public abstract class XSpeedController implements XBaseIO 8 | { 9 | protected int channel; 10 | protected boolean isInverted; 11 | 12 | public interface XSpeedControllerFactory { 13 | XSpeedController create(int channel); 14 | } 15 | 16 | public XSpeedController(int channel, DevicePolice police) { 17 | this.channel = channel; 18 | police.registerDevice(DeviceType.PWM, channel, this); 19 | } 20 | 21 | public int getChannel() { 22 | return channel; 23 | } 24 | 25 | public boolean getInverted() { 26 | return isInverted; 27 | } 28 | public void setInverted(boolean isInverted) { 29 | this.isInverted = isInverted; 30 | } 31 | 32 | public void setPower(double power) { 33 | set(power * (isInverted ? -1 : 1)); 34 | } 35 | 36 | public double getPower() { 37 | return get() * (isInverted ? -1 : 1); 38 | } 39 | 40 | protected abstract double get(); 41 | protected abstract void set(double value); 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/edu/wpi/first/wpilibj/MockPowerDistributionPanel.java: -------------------------------------------------------------------------------- 1 | package edu.wpi.first.wpilibj; 2 | 3 | import java.util.HashMap; 4 | 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | 8 | import dagger.assisted.AssistedFactory; 9 | import dagger.assisted.AssistedInject; 10 | 11 | import xbot.common.controls.sensors.XPowerDistributionPanel; 12 | 13 | public class MockPowerDistributionPanel extends XPowerDistributionPanel { 14 | private HashMap outputCurrents; 15 | 16 | private static Logger log = LogManager.getLogger(MockPowerDistributionPanel.class); 17 | 18 | @AssistedFactory 19 | public abstract static class MockPowerDistributionPanelFactory implements XPowerDistributionPanelFactory { 20 | @Override 21 | public abstract MockPowerDistributionPanel create(); 22 | } 23 | 24 | @AssistedInject 25 | public MockPowerDistributionPanel() { 26 | log.info("Creating PDP"); 27 | outputCurrents = new HashMap<>(); 28 | } 29 | 30 | public void setCurrent(int channel, double current) { 31 | outputCurrents.put(channel, current); 32 | } 33 | 34 | @Override 35 | public double getCurrent(int channel) { 36 | return outputCurrents.getOrDefault(channel, 0d); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "java", 9 | "name": "Debug (Launch)", 10 | "request": "launch", 11 | "cwd": "${workspaceFolder}", 12 | "console": "internalConsole", 13 | "stopOnEntry": false, 14 | "mainClass": "", 15 | "args": "" 16 | }, 17 | { 18 | "type": "java", 19 | "name": "Debug (Launch)-PlanarTestVisualizer", 20 | "request": "launch", 21 | "cwd": "${workspaceFolder}", 22 | "console": "internalConsole", 23 | "stopOnEntry": false, 24 | "mainClass": "xbot.common.math.PlanarTestVisualizer", 25 | "args": "", 26 | "projectName": "SeriouslyCommonLib" 27 | }, 28 | { 29 | "type": "java", 30 | "name": "Debug (Attach)", 31 | "request": "attach", 32 | "hostName": "localhost", 33 | "port": "" 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/buttons/VirtualTrigger.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.buttons; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | 7 | /** 8 | * A virtual button under program control that can be used for creating chords. 9 | * This is useful to repurpose buttons in multiple "modes". 10 | */ 11 | public class VirtualTrigger extends AdvancedTrigger { 12 | 13 | private SettableBooleanSuppler supplier; 14 | 15 | @AssistedFactory 16 | public abstract static class VirtualTriggerFactory { 17 | public abstract VirtualTrigger create(@Assisted boolean defaultPressed); 18 | 19 | public VirtualTrigger create() { 20 | return create(false); 21 | } 22 | } 23 | 24 | @AssistedInject 25 | public VirtualTrigger(@Assisted boolean defaultPressed) { 26 | this(new SettableBooleanSuppler(defaultPressed)); 27 | } 28 | 29 | public VirtualTrigger(SettableBooleanSuppler supplier) { 30 | super(supplier); 31 | this.supplier = supplier; 32 | } 33 | 34 | public void set(boolean value) { 35 | this.supplier.set(value); 36 | } 37 | 38 | public void toggle() { 39 | this.supplier.toggle(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/BaseWPITest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection; 2 | 3 | import org.junit.Before; 4 | import org.junit.Ignore; 5 | 6 | import edu.wpi.first.wpilibj.MockTimer; 7 | import xbot.common.controls.sensors.XTimer; 8 | import xbot.common.injection.components.BaseComponent; 9 | import xbot.common.math.PIDManager.PIDManagerFactory; 10 | import xbot.common.properties.PropertyFactory; 11 | 12 | @Ignore 13 | public abstract class BaseWPITest { 14 | private BaseComponent injectorComponent; 15 | 16 | public PropertyFactory propertyFactory; 17 | 18 | protected PIDManagerFactory pf; 19 | 20 | protected MockTimer timer; 21 | 22 | /** 23 | * Returns the {@link BaseComponent} instance used for dependency injection 24 | */ 25 | protected abstract BaseComponent createDaggerComponent(); 26 | 27 | protected BaseComponent getInjectorComponent() { 28 | return injectorComponent; 29 | } 30 | 31 | @Before 32 | public void setUp() { 33 | injectorComponent = createDaggerComponent(); 34 | timer = (MockTimer)injectorComponent.timerImplementation(); 35 | XTimer.setImplementation(timer); 36 | 37 | propertyFactory = injectorComponent.propertyFactory(); 38 | 39 | pf = injectorComponent.pidFactory(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/simulation/SimulatedSolenoidTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.simulation; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.json.JSONObject; 6 | import org.junit.Ignore; 7 | import org.junit.Test; 8 | 9 | import edu.wpi.first.wpilibj.MockSolenoid; 10 | 11 | @Ignore 12 | public class SimulatedSolenoidTest extends BaseSimulationTest { 13 | 14 | MockSolenoid mockSolenoid; 15 | final int channel = 1; 16 | 17 | @Override 18 | public void setUp() { 19 | super.setUp(); 20 | 21 | mockSolenoid = (MockSolenoid)injectorComponent.solenoidFactory().create(channel); 22 | } 23 | 24 | @Test 25 | public void testOn() { 26 | mockSolenoid.set(true); 27 | JSONObject result = mockSolenoid.getSimulationData(); 28 | 29 | assertEquals("Solenoid1", result.get("id")); 30 | assertEquals("VIRTUAL_SOLENOID", result.get("mode")); 31 | assertEquals("ON", result.get("val")); 32 | } 33 | 34 | @Test 35 | public void testOff() { 36 | mockSolenoid.set(false); 37 | JSONObject result = mockSolenoid.getSimulationData(); 38 | 39 | assertEquals("Solenoid1", result.get("id")); 40 | assertEquals("VIRTUAL_SOLENOID", result.get("mode")); 41 | assertEquals("OFF", result.get("val")); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/math/PIDDefaults.java: -------------------------------------------------------------------------------- 1 | package xbot.common.math; 2 | 3 | /** 4 | * This class is used to define the default values for a PID controller. 5 | */ 6 | public record PIDDefaults( 7 | double p, 8 | double i, 9 | double d, 10 | double f, 11 | double maxOutput, 12 | double minOutput, 13 | double errorThreshold, 14 | double derivativeThreshold, 15 | double timeThreshold, 16 | double iZone) { 17 | 18 | public PIDDefaults(double p, double i, double d, double f, double maxOutput, double minOutput, 19 | double errorThreshold, double derivativeThreshold, double timeThreshold) { 20 | this(p, i, d, f, maxOutput, minOutput, errorThreshold, derivativeThreshold, timeThreshold, -1); 21 | } 22 | 23 | public PIDDefaults(double p, double i, double d, double f, double maxOutput, double minOutput) { 24 | this(p, i, d, f, maxOutput, minOutput, -1, -1, -1); 25 | } 26 | 27 | public PIDDefaults(double p, double i, double d, double maxOutput, double minOutput) { 28 | this(p, i, d, 0, maxOutput, minOutput); 29 | } 30 | 31 | public PIDDefaults(double p, double i, double d) { 32 | this(p, i, d, 1.0, -1.0); 33 | } 34 | 35 | public PIDDefaults() { 36 | this(0, 0, 0); 37 | } 38 | }; -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/buttons/AdvancedPovButtonTrigger.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.buttons; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | 6 | import dagger.assisted.Assisted; 7 | import dagger.assisted.AssistedFactory; 8 | import dagger.assisted.AssistedInject; 9 | import xbot.common.controls.sensors.XJoystick; 10 | 11 | public class AdvancedPovButtonTrigger extends AdvancedTrigger { 12 | 13 | private static final Logger log = LogManager.getLogger(AdvancedPovButtonTrigger.class); 14 | 15 | XJoystick joystick; 16 | int povNumber; 17 | 18 | @AssistedFactory 19 | public abstract static class AdvancedPovButtonTriggerFactory { 20 | public abstract AdvancedPovButtonTrigger create( 21 | @Assisted("joystick") XJoystick joystick, 22 | @Assisted("povNumber") int povNumber); 23 | } 24 | 25 | @AssistedInject 26 | public AdvancedPovButtonTrigger( 27 | @Assisted("joystick") XJoystick joystick, 28 | @Assisted("povNumber")int povNumber) { 29 | super(() -> joystick.getPOV() == povNumber); 30 | log.debug("Creating D-Pad button " + povNumber + " on port " + joystick.getPort()); 31 | this.joystick = joystick; 32 | this.povNumber = povNumber; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/simulation/SimulatedDistanceSensorTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.simulation; 2 | 3 | import xbot.common.controls.sensors.SimulatedAnalogDistanceSensor; 4 | 5 | public class SimulatedDistanceSensorTest extends BaseSimulationTest { 6 | 7 | SimulatedAnalogDistanceSensor distanceSensor; 8 | 9 | @Override 10 | public void setUp() { 11 | super.setUp(); 12 | // 13 | // distanceSensor = (SimulatedAnalogDistanceSensor) clf.createAnalogDistanceSensor(1, 14 | // xbot.common.controls.sensors.XAnalogDistanceSensor.VoltageMaps::sharp0A51SK, "Test"); 15 | } 16 | /* 17 | @Test 18 | public void basicTest() { 19 | 20 | JSONObject overallPayload = new JSONObject(); 21 | JSONObject singleSensor = new JSONObject(); 22 | singleSensor.put("ID", "Analog1"); 23 | JSONObject singleSensorPayload = new JSONObject(); 24 | singleSensorPayload.put("Distance", new BigDecimal("123.002")); 25 | singleSensor.put("Payload", singleSensorPayload); 26 | JSONArray sensorList = new JSONArray(); 27 | sensorList.put(singleSensor); 28 | overallPayload.put("Sensors", sensorList); 29 | 30 | distributor.distributeSimulationPayload(overallPayload); 31 | 32 | assertEquals(123.002, distanceSensor.getDistance(), 0.001); 33 | } 34 | */ 35 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/XRelay.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators; 2 | 3 | import edu.wpi.first.wpilibj.Relay.Value; 4 | import xbot.common.injection.DevicePolice; 5 | import xbot.common.injection.DevicePolice.DeviceType; 6 | 7 | public abstract class XRelay { 8 | 9 | protected int channel; 10 | protected boolean inverted; 11 | 12 | public interface XRelayFactory { 13 | XRelay create(int channel); 14 | } 15 | 16 | protected XRelay(int channel, DevicePolice police) { 17 | this.channel = channel; 18 | police.registerDevice(DeviceType.PWM, channel, this); 19 | } 20 | 21 | public void setForward() { 22 | Value valueToSet = Value.kForward; 23 | if (inverted) { 24 | valueToSet = Value.kReverse; 25 | } 26 | 27 | set(valueToSet); 28 | } 29 | 30 | public void setReverse() { 31 | Value valueToSet = Value.kReverse; 32 | if (inverted) { 33 | valueToSet = Value.kForward; 34 | } 35 | 36 | set(valueToSet); 37 | } 38 | 39 | public void stop() { 40 | set(Value.kOff); 41 | } 42 | 43 | public void setInverted(boolean inverted) { 44 | this.inverted = inverted; 45 | } 46 | 47 | public abstract void set(Value value); 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/XPWM.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators; 2 | 3 | import xbot.common.controls.XBaseIO; 4 | import xbot.common.injection.DevicePolice; 5 | import xbot.common.injection.DevicePolice.DeviceType; 6 | 7 | public abstract class XPWM implements XBaseIO 8 | { 9 | protected int channel; 10 | 11 | public interface XPWMFactory { 12 | XPWM create(int channel); 13 | } 14 | 15 | protected XPWM(int channel, DevicePolice police) { 16 | this.channel = channel; 17 | police.registerDevice(DeviceType.PWM, channel, this); 18 | } 19 | 20 | public int getChannel() { 21 | return channel; 22 | } 23 | 24 | /** 25 | * Sets the PWM duty cycle 26 | * @param value the value to set, in the range [0, 255] 27 | */ 28 | public abstract void setRaw(int value); 29 | public abstract int getRaw(); 30 | 31 | /** 32 | * Sets the PWM duty cycle 33 | * @param value the value to set, in the range [-1, 1] 34 | */ 35 | public abstract void setSigned(double value); 36 | public abstract double getSigned(); 37 | 38 | /** 39 | * Sets the PWM duty cycle 40 | * @param value the value to set, in the range [0, 1] 41 | */ 42 | public abstract void setUnsigned(double value); 43 | public abstract double getUnsigned(); 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/edu/wpi/first/wpilibj/MockSolenoid.java: -------------------------------------------------------------------------------- 1 | package edu.wpi.first.wpilibj; 2 | 3 | import org.json.JSONObject; 4 | 5 | import dagger.assisted.Assisted; 6 | import dagger.assisted.AssistedFactory; 7 | import dagger.assisted.AssistedInject; 8 | 9 | import xbot.common.controls.actuators.XSolenoid; 10 | import xbot.common.injection.DevicePolice; 11 | import xbot.common.simulation.ISimulatableSolenoid; 12 | 13 | public class MockSolenoid extends XSolenoid implements ISimulatableSolenoid { 14 | final int channel; 15 | protected boolean on; 16 | 17 | @AssistedFactory 18 | public abstract static class MockSolenoidFactory implements XSolenoidFactory { 19 | public abstract MockSolenoid create(@Assisted("channel") int channel); 20 | } 21 | 22 | @AssistedInject 23 | public MockSolenoid(@Assisted("channel") int channel, DevicePolice police) { 24 | super(channel, police); 25 | this.channel = channel; 26 | } 27 | 28 | @Override 29 | public void set(boolean on) { 30 | this.on = on; 31 | } 32 | 33 | public boolean get() { 34 | return on; 35 | } 36 | 37 | @Override 38 | public int getMaxSupportedChannel() { 39 | return 15; 40 | } 41 | 42 | @Override 43 | public JSONObject getSimulationData() { 44 | return buildMotorObject(channel, get()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/logic/LogicUtils.java: -------------------------------------------------------------------------------- 1 | package xbot.common.logic; 2 | 3 | /** 4 | * Utility methods for working with logic. 5 | */ 6 | public final class LogicUtils { 7 | /** 8 | * Returns true if any of the given values are true. 9 | * @apiNote This is helpful if Checkstyle complains about boolean expression complexity. 10 | * @param values The values to check. 11 | * If no values are given, this method will return false. 12 | * @return True if any of the given values are true. 13 | */ 14 | public static boolean anyOf(boolean... values) { 15 | for (boolean value : values) { 16 | if (value) { 17 | return true; 18 | } 19 | } 20 | return false; 21 | } 22 | 23 | /** 24 | * Returns true if all the given values are true. 25 | * @apiNote This is helpful if Checkstyle complains about boolean expression complexity. 26 | * @param values The values to check. 27 | * If no values are given, this method will return true. 28 | * @return True if all the given values are true. 29 | */ 30 | public static boolean allOf(boolean... values) { 31 | for (boolean value : values) { 32 | if (!value) { 33 | return false; 34 | } 35 | } 36 | return true; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/command/BaseWaitForMaintainerCommandTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import static org.junit.Assert.assertFalse; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import org.junit.Test; 7 | 8 | import xbot.common.injection.BaseCommonLibTest; 9 | 10 | public class BaseWaitForMaintainerCommandTest extends BaseCommonLibTest { 11 | 12 | @Test 13 | public void testReachedGoal() { 14 | BaseSetpointSubsystem subsystem = getInjectorComponent().mockSetpointSubsystem(); 15 | BaseWaitForMaintainerCommand command = getInjectorComponent().mockWaitForMaintainerCommand(); 16 | 17 | command.initialize(); 18 | 19 | subsystem.setMaintainerIsAtGoal(false); 20 | assertFalse(command.isFinished()); 21 | 22 | subsystem.setMaintainerIsAtGoal(true); 23 | assertTrue(command.isFinished()); 24 | } 25 | 26 | @Test 27 | public void testTimeout() { 28 | BaseSetpointSubsystem subsystem = getInjectorComponent().mockSetpointSubsystem(); 29 | BaseWaitForMaintainerCommand command = getInjectorComponent().mockWaitForMaintainerCommand(); 30 | 31 | command.initialize(); 32 | 33 | subsystem.setMaintainerIsAtGoal(false); 34 | assertFalse(command.isFinished()); 35 | 36 | this.timer.advanceTimeInSecondsBy(10); 37 | assertTrue(command.isFinished()); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/main/java/edu/wpi/first/wpilibj/MockPWM.java: -------------------------------------------------------------------------------- 1 | package edu.wpi.first.wpilibj; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | 7 | import xbot.common.controls.actuators.XPWM; 8 | import xbot.common.injection.DevicePolice; 9 | 10 | public class MockPWM extends XPWM { 11 | protected int channel; 12 | protected double value; 13 | 14 | @AssistedFactory 15 | public abstract static class MockPWMFactory implements XPWMFactory { 16 | public abstract MockPWM create(@Assisted("channel") int channel); 17 | } 18 | 19 | @AssistedInject 20 | public MockPWM(@Assisted("channel") int channel, DevicePolice police) { 21 | super(channel, police); 22 | } 23 | 24 | @Override 25 | public void setRaw(int value) { 26 | this.value = value / 255d; 27 | } 28 | 29 | @Override 30 | public int getRaw() { 31 | return (int)(value * 255); 32 | } 33 | 34 | @Override 35 | public void setSigned(double value) { 36 | this.value = value; 37 | } 38 | 39 | @Override 40 | public double getSigned() { 41 | return value; 42 | } 43 | 44 | @Override 45 | public void setUnsigned(double value) { 46 | this.value = value; 47 | } 48 | 49 | @Override 50 | public double getUnsigned() { 51 | return value; 52 | } 53 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/wpi_adapters/CompressorWPIAdapter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators.wpi_adapters; 2 | 3 | import dagger.assisted.AssistedFactory; 4 | import dagger.assisted.AssistedInject; 5 | 6 | import edu.wpi.first.wpilibj.Compressor; 7 | import edu.wpi.first.wpilibj.PneumaticsModuleType; 8 | import xbot.common.controls.actuators.XCompressor; 9 | 10 | public class CompressorWPIAdapter extends XCompressor { 11 | Compressor compressor; 12 | 13 | @AssistedFactory 14 | public abstract static class CompressorWPIAdapterFactory implements XCompressorFactory { 15 | public abstract CompressorWPIAdapter create(); 16 | } 17 | 18 | @AssistedInject 19 | public CompressorWPIAdapter() { 20 | this.compressor = new Compressor(PneumaticsModuleType.REVPH); 21 | } 22 | 23 | @Override 24 | public void disable() { 25 | compressor.disable(); 26 | } 27 | 28 | @Override 29 | public void enable() { 30 | compressor.enableDigital(); 31 | } 32 | 33 | @Override 34 | public boolean isEnabled() { 35 | return compressor.isEnabled(); 36 | } 37 | 38 | @Override 39 | public double getCurrent() { 40 | return compressor.getCurrent(); 41 | } 42 | 43 | @Override 44 | public boolean isAtTargetPressure() { 45 | return !compressor.getPressureSwitchValue(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/XAS5600.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | /* 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | 6 | import dagger.assisted.Assisted; 7 | import dagger.assisted.AssistedFactory; 8 | import dagger.assisted.AssistedInject; 9 | 10 | import xbot.common.controls.actuators.XCANTalon; 11 | 12 | public class XAS5600 { 13 | 14 | XCANTalon talon; 15 | int lastValue = Integer.MIN_VALUE; 16 | protected Logger log = LogManager.getLogger(XAS5600.class); 17 | 18 | @AssistedFactory 19 | public abstract static class XAS5600Factory { 20 | public abstract XAS5600 create(@Assisted("talon") XCANTalon talon); 21 | } 22 | 23 | @AssistedInject 24 | public XAS5600(@Assisted("talon") XCANTalon talon) { 25 | this.talon = talon; 26 | log.info("Creating XAS5600 using Talon with ID:" + talon.getDeviceID()); 27 | } 28 | 29 | public int getPosition() { 30 | int raw = talon.getPulseWidthRiseToFallUs(); 31 | if (raw == 0) { 32 | int lastValue = this.lastValue; 33 | if (lastValue == Integer.MIN_VALUE) { 34 | return 0; 35 | } 36 | return lastValue; 37 | } 38 | int actualValue = Math.min(4096, raw - 128); 39 | lastValue = actualValue; 40 | return actualValue; 41 | } 42 | } 43 | */ -------------------------------------------------------------------------------- /src/test/java/xbot/common/networking/ZeromqTestServer.java: -------------------------------------------------------------------------------- 1 | package xbot.common.networking; 2 | 3 | import java.util.Random; 4 | 5 | import org.zeromq.SocketType; 6 | import org.zeromq.ZMQ; 7 | 8 | public class ZeromqTestServer implements Runnable { 9 | 10 | @Override 11 | public void run() { 12 | // Prepare our context and publisher 13 | ZMQ.Context context = ZMQ.context(1); 14 | 15 | ZMQ.Socket publisher = context.socket(SocketType.PUB); 16 | publisher.setConflate(true); 17 | publisher.bind("tcp://*:5556"); 18 | publisher.bind("ipc://weather"); 19 | 20 | // Initialize random number generator 21 | Random srandom = new Random(System.currentTimeMillis()); 22 | while (!Thread.currentThread ().isInterrupted ()) { 23 | // Get values that will fool the boss 24 | int zipcode; 25 | int temperature; 26 | int relhumidity; 27 | zipcode = 10000 + srandom.nextInt(10000) ; 28 | temperature = srandom.nextInt(215) - 80 + 1; 29 | relhumidity = srandom.nextInt(50) + 10 + 1; 30 | 31 | // Send message to all subscribers 32 | String update = String.format("%05d %d %d", zipcode, temperature, relhumidity); 33 | publisher.send(update, 0); 34 | } 35 | 36 | publisher.close (); 37 | context.term (); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/wpi_adapters/DutyCycleEncoderWpiAdapter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.wpi_adapters; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | import edu.wpi.first.wpilibj.DutyCycleEncoder; 7 | import xbot.common.controls.io_inputs.XDutyCycleEncoderInputs; 8 | import xbot.common.controls.sensors.XDutyCycleEncoder; 9 | import xbot.common.controls.sensors.mock_adapters.MockDutyCycleEncoder; 10 | import xbot.common.injection.DevicePolice; 11 | import xbot.common.injection.electrical_contract.DeviceInfo; 12 | 13 | public class DutyCycleEncoderWpiAdapter extends XDutyCycleEncoder { 14 | 15 | DutyCycleEncoder internalEncoder; 16 | 17 | @AssistedFactory 18 | public abstract static class DutyCycleEncoderWpiAdapterFactory implements XDutyCycleEncoder.XDutyCycleEncoderFactory { 19 | public abstract DutyCycleEncoderWpiAdapter create(@Assisted("info") DeviceInfo info); 20 | } 21 | 22 | @AssistedInject 23 | public DutyCycleEncoderWpiAdapter(@Assisted("info") DeviceInfo info, DevicePolice police) { 24 | super(info, police); 25 | internalEncoder = new DutyCycleEncoder(info.channel); 26 | } 27 | 28 | @Override 29 | public void updateInputs(XDutyCycleEncoderInputs inputs) { 30 | inputs.absoluteRawPosition = internalEncoder.get(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/command/BaseSimpleMaintainerCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import xbot.common.logic.HumanVsMachineDecider; 4 | import xbot.common.properties.PropertyFactory; 5 | 6 | /** 7 | * A base class for maintainer commands that use simple Double values for both 8 | * current and target values. 9 | */ 10 | public abstract class BaseSimpleMaintainerCommand extends BaseMaintainerCommand { 11 | 12 | /** 13 | * Creates a new maintainer command. 14 | * 15 | * @param subsystemToMaintain The subsystem to maintain. 16 | * @param pf The property factory to use for creating properties. 17 | * @param humanVsMachineDeciderFactory The decider factory to use for creating the decider. 18 | * @param defaultErrorTolerance The default error tolerance. 19 | * @param defaultTimeStableWindow The default time stable window. 20 | */ 21 | public BaseSimpleMaintainerCommand(BaseSetpointSubsystem subsystemToMaintain, PropertyFactory pf, 22 | HumanVsMachineDecider.HumanVsMachineDeciderFactory humanVsMachineDeciderFactory, double defaultErrorTolerance, 23 | double defaultTimeStableWindow) { 24 | super(subsystemToMaintain, pf, humanVsMachineDeciderFactory, defaultErrorTolerance, defaultTimeStableWindow); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/wpi_adapters/SolenoidWPIAdapter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators.wpi_adapters; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | 7 | import edu.wpi.first.wpilibj.PneumaticsModuleType; 8 | import edu.wpi.first.wpilibj.Solenoid; 9 | import xbot.common.controls.actuators.XSolenoid; 10 | import xbot.common.injection.DevicePolice; 11 | 12 | public class SolenoidWPIAdapter extends XSolenoid { 13 | 14 | private static final int SOLENOID_CHANNEL_COUNT = 16; 15 | 16 | Solenoid solenoid; 17 | 18 | @AssistedFactory 19 | public abstract static class SolenoidWPIAdapterFactory implements XSolenoidFactory { 20 | public abstract SolenoidWPIAdapter create(@Assisted("channel") int channel); 21 | } 22 | 23 | @AssistedInject 24 | public SolenoidWPIAdapter(@Assisted("channel") int channel, DevicePolice police) { 25 | super(channel, police); 26 | this.solenoid = new Solenoid(PneumaticsModuleType.REVPH, channel); 27 | } 28 | 29 | @Override 30 | public void set(boolean on) { 31 | this.solenoid.set(on); 32 | } 33 | 34 | @Override 35 | public boolean get() { 36 | return this.solenoid.get(); 37 | } 38 | 39 | @Override 40 | public int getMaxSupportedChannel() { 41 | return SOLENOID_CHANNEL_COUNT - 1; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/XAnalogDistanceSensor.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | import java.util.function.DoubleUnaryOperator; 4 | 5 | public abstract class XAnalogDistanceSensor implements DistanceSensor { 6 | 7 | DoubleUnaryOperator voltageMap; 8 | 9 | public interface XAnalogDistanceSensorFactory { 10 | XAnalogDistanceSensor create( 11 | int channel, 12 | DoubleUnaryOperator voltageMap, 13 | String prefix); 14 | } 15 | 16 | protected XAnalogDistanceSensor( 17 | int channel, 18 | DoubleUnaryOperator voltageMap) { 19 | this.voltageMap = voltageMap; 20 | } 21 | 22 | public abstract double getDistance(); 23 | 24 | public abstract void setAveraging(boolean shouldAverage); 25 | 26 | public abstract void setVoltageOffset(double offset); 27 | 28 | public abstract void setDistanceOffset(double offset); 29 | 30 | public static class VoltageMaps 31 | { 32 | public static final double sharp0A51SK(double voltage) 33 | { 34 | // 3.6601x4 - 20.375x3 + 41.593x2 - 38.528x + 15.848 35 | return (3.6601 * Math.pow(voltage, 4d)) 36 | - (20.375 * Math.pow(voltage, 3d)) 37 | + (41.593 * Math.pow(voltage, 2d)) 38 | - (38.528 * voltage) 39 | + 15.848; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/command/BaseWaitForMaintainerCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import xbot.common.controls.sensors.XTimer; 4 | import xbot.common.properties.DoubleProperty; 5 | import xbot.common.properties.PropertyFactory; 6 | 7 | /** 8 | * Command that waits for a setpoint subsystem to reach its goal 9 | */ 10 | public abstract class BaseWaitForMaintainerCommand extends BaseCommand { 11 | 12 | private final BaseSetpointSubsystem system; 13 | private final DoubleProperty timeoutProperty; 14 | 15 | private double startTime; 16 | 17 | public BaseWaitForMaintainerCommand(BaseSetpointSubsystem system, PropertyFactory pf, double defaultTimeout) { 18 | this.system = system; 19 | 20 | pf.setPrefix(this); 21 | this.timeoutProperty = pf.createPersistentProperty("Timeout Seconds", defaultTimeout); 22 | } 23 | 24 | @Override 25 | public void initialize() { 26 | this.startTime = XTimer.getFPGATimestamp(); 27 | } 28 | 29 | @Override 30 | public void execute() { 31 | // this command doesn't do anything in the execute phase 32 | } 33 | 34 | @Override 35 | public boolean isFinished() { 36 | return (this.system.isMaintainerAtGoal() || isTimeoutExpired()); 37 | } 38 | 39 | private boolean isTimeoutExpired() { 40 | return XTimer.getFPGATimestamp() > this.startTime + this.timeoutProperty.get(); 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/swerve/SwerveComponent.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.swerve; 2 | 3 | import xbot.common.subsystems.drive.swerve.SwerveDriveSubsystem; 4 | import xbot.common.subsystems.drive.swerve.SwerveModuleSubsystem; 5 | import xbot.common.subsystems.drive.swerve.SwerveSteeringSubsystem; 6 | import dagger.BindsInstance; 7 | import dagger.Subcomponent; 8 | import xbot.common.subsystems.drive.swerve.commands.SwerveDriveMaintainerCommand; 9 | import xbot.common.subsystems.drive.swerve.commands.SwerveSteeringMaintainerCommand; 10 | 11 | /** 12 | * Subcomponent for a handling dependency injection related to a single swerve drive module. 13 | */ 14 | @SwerveSingleton 15 | @Subcomponent(modules = SwerveModule.class) 16 | public abstract class SwerveComponent { 17 | public abstract SwerveInstance swerveInstance(); 18 | 19 | public abstract SwerveModuleSubsystem swerveModuleSubsystem(); 20 | 21 | public abstract SwerveDriveSubsystem swerveDriveSubsystem(); 22 | 23 | public abstract SwerveDriveMaintainerCommand swerveDriveMaintainerCommand(); 24 | 25 | public abstract SwerveSteeringSubsystem swerveSteeringSubsystem(); 26 | 27 | public abstract SwerveSteeringMaintainerCommand swerveSteeringMaintainerCommand(); 28 | 29 | @Subcomponent.Builder 30 | public interface Builder { 31 | @BindsInstance 32 | Builder swerveInstance(SwerveInstance instance); 33 | 34 | SwerveComponent build(); 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/buttons/AdvancedJoystickButtonTrigger.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.buttons; 2 | 3 | import java.util.function.BooleanSupplier; 4 | 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | 8 | import dagger.assisted.Assisted; 9 | import dagger.assisted.AssistedFactory; 10 | import dagger.assisted.AssistedInject; 11 | import xbot.common.controls.sensors.XJoystick; 12 | 13 | public class AdvancedJoystickButtonTrigger extends AdvancedTrigger 14 | { 15 | private static final Logger log = LogManager.getLogger(AdvancedJoystickButtonTrigger.class); 16 | 17 | XJoystick joystick; 18 | int buttonNumber; 19 | 20 | @AssistedFactory 21 | public abstract static class AdvancedJoystickButtonTriggerFactory { 22 | public abstract AdvancedJoystickButtonTrigger create( 23 | @Assisted("joystick") XJoystick joystick, 24 | @Assisted("buttonNumber") int buttonNumber); 25 | } 26 | 27 | @AssistedInject 28 | public AdvancedJoystickButtonTrigger( 29 | @Assisted("joystick") XJoystick joystick, 30 | @Assisted("buttonNumber")int buttonNumber) { 31 | super((BooleanSupplier)(() -> joystick.getButton(buttonNumber))); 32 | log.debug("Creating button " + buttonNumber + " on port " + joystick.getPort()); 33 | this.joystick = joystick; 34 | this.buttonNumber = buttonNumber; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/command/SimpleWaitForMaintainerCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import java.util.function.DoubleSupplier; 4 | 5 | import xbot.common.controls.sensors.XTimer; 6 | 7 | /** 8 | * Command that waits for a maintainer to be at its goal or until a timeout. 9 | */ 10 | public class SimpleWaitForMaintainerCommand extends BaseCommand { 11 | 12 | private final BaseSetpointSubsystem subsystem; 13 | private final DoubleSupplier delaySupplier; 14 | private double startTime; 15 | 16 | /** 17 | * Creates a new SimpleWaitForMaintainerCommand instance. 18 | * @param subsystem The maintainer subsystem. 19 | * @param delaySupplier The timeout duration in seconds via a supplier. 20 | */ 21 | public SimpleWaitForMaintainerCommand(BaseSetpointSubsystem subsystem, DoubleSupplier delaySupplier) { 22 | this.subsystem = subsystem; 23 | this.delaySupplier = delaySupplier; 24 | } 25 | 26 | @Override 27 | public void initialize() { 28 | this.startTime = XTimer.getFPGATimestamp(); 29 | } 30 | 31 | @Override 32 | public void execute() { 33 | // Do nothing 34 | } 35 | 36 | @Override 37 | public boolean isFinished() { 38 | return isTimeoutExpired() || subsystem.isMaintainerAtGoal(); 39 | } 40 | 41 | private boolean isTimeoutExpired() { 42 | return XTimer.getFPGATimestamp() > startTime + delaySupplier.getAsDouble(); 43 | } 44 | } -------------------------------------------------------------------------------- /src/main/java/edu/wpi/first/wpilibj/MockLidarLite.java: -------------------------------------------------------------------------------- 1 | package edu.wpi.first.wpilibj; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | 7 | import edu.wpi.first.wpilibj.I2C.Port; 8 | import xbot.common.controls.sensors.XLidarLite; 9 | import xbot.common.injection.DevicePolice; 10 | import xbot.common.properties.PropertyFactory; 11 | 12 | public class MockLidarLite extends XLidarLite { 13 | 14 | @AssistedFactory 15 | public abstract static class MockLidarLiteFactory implements XLidarLiteFactory { 16 | public abstract MockLidarLite create(@Assisted("port") Port port, @Assisted("prefix") String prefix); 17 | } 18 | 19 | @AssistedInject 20 | public MockLidarLite(@Assisted("port") Port port, PropertyFactory propMan, DevicePolice police, @Assisted("prefix") String prefix) { 21 | super(port, propMan, police, prefix); 22 | } 23 | 24 | @Override 25 | protected void update() { 26 | // no-op, but still need to delay to prevent high speed loop 27 | try { 28 | Thread.sleep(5); 29 | } catch (InterruptedException e) { 30 | e.printStackTrace(); 31 | } 32 | } 33 | 34 | public void setTestDistance(int testDistance) { 35 | byte[] fakeDistance = new byte[2]; 36 | fakeDistance[0] = (byte)(testDistance >> 8); 37 | fakeDistance[1] = (byte)(testDistance % 256); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/XCANImu.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | import edu.wpi.first.math.geometry.Rotation2d; 4 | import edu.wpi.first.math.geometry.Rotation3d; 5 | import edu.wpi.first.units.measure.Angle; 6 | import edu.wpi.first.units.measure.LinearAcceleration; 7 | import edu.wpi.first.units.measure.Temperature; 8 | import edu.wpi.first.units.measure.Voltage; 9 | import edu.wpi.first.util.sendable.SendableBuilder; 10 | 11 | public abstract class XCANImu implements AutoCloseable { 12 | 13 | public abstract void reset(); 14 | 15 | public abstract Rotation2d getRotation2d(); 16 | 17 | public abstract Rotation3d getRotation3d(); 18 | 19 | public abstract LinearAcceleration getAccelerationX(); 20 | 21 | public abstract LinearAcceleration getAccelerationY(); 22 | 23 | public abstract Angle getYaw(); 24 | 25 | public abstract Angle getPitch(); 26 | 27 | public abstract Angle getRoll(); 28 | 29 | public abstract boolean isConnected(); 30 | 31 | public abstract LinearAcceleration getAccelerationZ(); 32 | 33 | public abstract Voltage getSupplyVoltage(); 34 | 35 | public abstract void setYaw(Angle newValue); 36 | 37 | public abstract Temperature getTemperature(); 38 | 39 | public abstract void initSendable(SendableBuilder builder); 40 | 41 | public abstract Angle getAccumGyroX(); 42 | 43 | public abstract Angle getAccumGyroY(); 44 | 45 | public abstract Angle getAccumGyroZ(); 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/pose/commands/SetRobotHeadingCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.pose.commands; 2 | 3 | import javax.inject.Inject; 4 | 5 | import xbot.common.command.BaseCommand; 6 | import xbot.common.subsystems.pose.BasePoseSubsystem; 7 | 8 | import java.util.function.DoubleSupplier; 9 | 10 | public class SetRobotHeadingCommand extends BaseCommand { 11 | 12 | protected final BasePoseSubsystem poseSubsystem; 13 | private DoubleSupplier headingSupplier; 14 | 15 | @Inject 16 | public SetRobotHeadingCommand(BasePoseSubsystem poseSubsystem) { 17 | this.poseSubsystem = poseSubsystem; 18 | headingSupplier = () -> BasePoseSubsystem.FACING_AWAY_FROM_DRIVERS; 19 | } 20 | 21 | @Override 22 | public boolean runsWhenDisabled() { 23 | return true; 24 | } 25 | 26 | public void setHeadingToApply(double heading) { 27 | this.headingSupplier = () -> heading; 28 | } 29 | 30 | public void setHeadingToApply(DoubleSupplier headingSupplier) { 31 | this.headingSupplier = headingSupplier; 32 | } 33 | 34 | @Override 35 | public void initialize() { 36 | log.info("Initializing"); 37 | log.info("Setting heading to " + headingSupplier.getAsDouble()); 38 | poseSubsystem.setCurrentHeading(headingSupplier.getAsDouble()); 39 | } 40 | 41 | @Override 42 | public void execute() {} 43 | 44 | @Override 45 | public boolean isFinished() { 46 | return true; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/mock_adapters/MockDutyCycleEncoder.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.mock_adapters; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | import edu.wpi.first.wpilibj.MockAnalogInput; 7 | import xbot.common.controls.io_inputs.XDutyCycleEncoderInputs; 8 | import xbot.common.controls.sensors.XAnalogInput; 9 | import xbot.common.controls.sensors.XDutyCycleEncoder; 10 | import xbot.common.injection.DevicePolice; 11 | import xbot.common.injection.electrical_contract.DeviceInfo; 12 | 13 | public class MockDutyCycleEncoder extends XDutyCycleEncoder { 14 | 15 | private double rawPosition; 16 | 17 | @AssistedFactory 18 | public abstract static class MockDutyCycleEncoderFactory implements XDutyCycleEncoder.XDutyCycleEncoderFactory { 19 | public abstract MockDutyCycleEncoder create(@Assisted("info") DeviceInfo info); 20 | } 21 | 22 | @AssistedInject 23 | public MockDutyCycleEncoder(@Assisted("info") DeviceInfo info, DevicePolice police) { 24 | super(info, police); 25 | } 26 | 27 | public void setRawPosition(double rawPosition) { 28 | this.rawPosition = rawPosition * inversionFactor(); 29 | } 30 | 31 | @Override 32 | public int getChannel() { 33 | return channel; 34 | } 35 | 36 | @Override 37 | public void updateInputs(XDutyCycleEncoderInputs inputs) { 38 | inputs.absoluteRawPosition = rawPosition; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/modules/MockControlsModule.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.modules; 2 | 3 | import javax.inject.Singleton; 4 | 5 | import dagger.Binds; 6 | import dagger.Module; 7 | import edu.wpi.first.wpilibj.MockXboxControllerAdapter.MockXboxControllerFactory; 8 | import xbot.common.controls.sensors.XFTCGamepad.XFTCGamepadFactory; 9 | import xbot.common.controls.sensors.XJoystick.XJoystickFactory; 10 | import xbot.common.controls.sensors.XXboxController.XXboxControllerFactory; 11 | import xbot.common.controls.sensors.mock_adapters.MockFTCGamepad.MockFTCGamepadFactory; 12 | import xbot.common.controls.sensors.mock_adapters.MockJoystick.MockJoystickFactory; 13 | import xbot.common.subsystems.feedback.RumbleManager.RumbleManagerFactory; 14 | import xbot.common.subsystems.feedback.XRumbleManager.XRumbleManagerFactory; 15 | 16 | /** 17 | * Module for mapping control device interfaces to mock implementations. 18 | */ 19 | @Module 20 | public abstract class MockControlsModule { 21 | @Binds 22 | @Singleton 23 | public abstract XJoystickFactory getJoystickFactory(MockJoystickFactory impl); 24 | 25 | @Binds 26 | @Singleton 27 | public abstract XXboxControllerFactory getXboxControllerFactory(MockXboxControllerFactory impl); 28 | 29 | @Binds 30 | @Singleton 31 | public abstract XFTCGamepadFactory getFTCGamepadFactory(MockFTCGamepadFactory impl); 32 | 33 | @Binds 34 | @Singleton 35 | public abstract XRumbleManagerFactory getRumbleManagerFactory(RumbleManagerFactory impl); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/logic/CalibrationDecider.java: -------------------------------------------------------------------------------- 1 | package xbot.common.logic; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | 7 | import xbot.common.controls.sensors.XTimer; 8 | import xbot.common.properties.DoubleProperty; 9 | import xbot.common.properties.PropertyFactory; 10 | 11 | public class CalibrationDecider { 12 | 13 | public enum CalibrationMode { 14 | Attempting, Calibrated, GaveUp 15 | } 16 | 17 | final DoubleProperty calibrationTimeProp; 18 | double startTime; 19 | 20 | @AssistedFactory 21 | public abstract static class CalibrationDeciderFactory { 22 | public abstract CalibrationDecider create(@Assisted("name") String name); 23 | } 24 | 25 | @AssistedInject 26 | public CalibrationDecider(@Assisted("name") String name, PropertyFactory propMan) { 27 | propMan.setPrefix(name); 28 | calibrationTimeProp = propMan.createPersistentProperty("CalibrationDecider/Attempt Time", 3); 29 | reset(); 30 | } 31 | 32 | public void reset() { 33 | startTime = XTimer.getFPGATimestamp(); 34 | } 35 | 36 | public CalibrationMode decideMode(boolean isCalibrated) { 37 | if (isCalibrated) { 38 | return CalibrationMode.Calibrated; 39 | } 40 | 41 | if (XTimer.getFPGATimestamp() - startTime > calibrationTimeProp.get()) { 42 | return CalibrationMode.GaveUp; 43 | } 44 | 45 | return CalibrationMode.Attempting; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/controls/sensors/DutyCycleEncoderTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import xbot.common.controls.sensors.mock_adapters.MockDutyCycleEncoder; 6 | import xbot.common.injection.BaseCommonLibTest; 7 | import xbot.common.injection.BaseWPITest; 8 | import xbot.common.injection.electrical_contract.DeviceInfo; 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class DutyCycleEncoderTest extends BaseCommonLibTest { 12 | 13 | @Test 14 | public void simpleScaling() { 15 | MockDutyCycleEncoder encoder = 16 | (MockDutyCycleEncoder)this.getInjectorComponent().dutyCycleEncoderFactory().create( 17 | new DeviceInfo("Test",0, false)); 18 | 19 | encoder.setRawPosition(0); 20 | encoder.refreshDataFrame(); 21 | assertEquals(0, encoder.getAbsolutePosition().getDegrees(), 0.001); 22 | assertEquals(0, encoder.getWrappedPosition().getDegrees(), 0.001); 23 | 24 | encoder.setRawPosition(0.499999999999999999); 25 | encoder.refreshDataFrame(); 26 | assertEquals(180, encoder.getAbsolutePosition().getDegrees(), 0.001); 27 | assertEquals(180, encoder.getWrappedPosition().getDegrees(), 0.001); 28 | 29 | encoder.setRawPosition(1.00000000001); 30 | encoder.refreshDataFrame(); 31 | assertEquals(360, encoder.getAbsolutePosition().getDegrees(), 0.001); 32 | assertEquals(0, encoder.getWrappedPosition().getDegrees(), 0.001); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/simulation/SimulatedIMUTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.simulation; 2 | 3 | import static edu.wpi.first.units.Units.Degrees; 4 | import static edu.wpi.first.units.Units.DegreesPerSecond; 5 | import static org.junit.Assert.assertEquals; 6 | 7 | import java.math.BigDecimal; 8 | 9 | import org.json.JSONObject; 10 | import org.junit.Ignore; 11 | import org.junit.Test; 12 | 13 | import xbot.common.controls.sensors.XGyro; 14 | import xbot.common.controls.sensors.mock_adapters.MockGyro; 15 | import xbot.common.injection.electrical_contract.IMUInfo; 16 | 17 | @Ignore 18 | public class SimulatedIMUTest extends BaseSimulationTest { 19 | 20 | MockGyro simulatedGyro; 21 | 22 | @Override 23 | public void setUp() { 24 | super.setUp(); 25 | 26 | simulatedGyro = (MockGyro)injectorComponent.gyroFactory().create(new IMUInfo(XGyro.InterfaceType.serial)); 27 | } 28 | 29 | @Test 30 | public void basicTest() { 31 | JSONObject imuPayload = new JSONObject(); 32 | imuPayload.put("Roll", new BigDecimal(45.223 / 180.0 * Math.PI)); 33 | imuPayload.put("YawVelocity", new BigDecimal(12 / 180.0 * Math.PI)); 34 | JSONObject fullSensorPayload = createSimpleSensorPayload("IMU1", imuPayload); 35 | 36 | this.distributor.distributeSimulationPayload(fullSensorPayload); 37 | simulatedGyro.refreshDataFrame(); 38 | assertEquals(45.223, simulatedGyro.getHeading().in(Degrees), 0.001); 39 | assertEquals(12, simulatedGyro.getYawAngularVelocity().in(DegreesPerSecond), 0.001); 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/wpi_adapters/LidarLiteWpiAdapter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.wpi_adapters; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | import edu.wpi.first.wpilibj.I2C; 7 | import edu.wpi.first.wpilibj.I2C.Port; 8 | import xbot.common.controls.sensors.XLidarLite; 9 | import xbot.common.controls.sensors.XTimer; 10 | import xbot.common.injection.DevicePolice; 11 | import xbot.common.properties.PropertyFactory; 12 | 13 | public class LidarLiteWpiAdapter extends XLidarLite{ 14 | 15 | private I2C i2c; 16 | 17 | @AssistedFactory 18 | public abstract static class LidarLiteWpiAdapterFactory implements XLidarLiteFactory { 19 | public abstract LidarLiteWpiAdapter create(@Assisted("port") Port port, @Assisted("prefix") String prefix); 20 | } 21 | 22 | @AssistedInject 23 | public LidarLiteWpiAdapter(@Assisted("port") Port port, PropertyFactory propMan, DevicePolice police, @Assisted("prefix") String prefix) { 24 | super(port, propMan, police, prefix); 25 | 26 | i2c = new I2C(port, lidar_address); 27 | } 28 | 29 | @Override 30 | // Update distance variable 31 | public void update() { 32 | i2c.write(lidar_config_register, 0x04); // Initiate measurement 33 | XTimer.delay(0.04); // Delay for measurement to be taken 34 | i2c.read(lidar_distance_register, 2, distance); // Read in measurement 35 | XTimer.delay(0.01); // Delay to prevent over polling 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/vision/SimpleCamera.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.vision; 2 | 3 | import org.photonvision.PhotonCameraExtended; 4 | import xbot.common.injection.electrical_contract.CameraInfo; 5 | 6 | /** 7 | * This class provides common base implementation for cameras on the robot. 8 | */ 9 | public abstract class SimpleCamera { 10 | protected final PhotonCameraExtended camera; 11 | protected final String friendlyName; 12 | 13 | /** 14 | * Create a new SimpleCamera. 15 | * 16 | * @param cameraInfo The information about the camera. 17 | */ 18 | protected SimpleCamera(CameraInfo cameraInfo, String prefix) { 19 | this.camera = new PhotonCameraExtended(cameraInfo.networkTablesName(), prefix); 20 | this.friendlyName = cameraInfo.friendlyName(); 21 | } 22 | 23 | /** 24 | * Get the name of the camera. 25 | * 26 | * @return The name of the camera. 27 | */ 28 | public String getName() { 29 | return this.friendlyName; 30 | } 31 | 32 | /** 33 | * Get the camera. 34 | * 35 | * @return The camera. 36 | */ 37 | public PhotonCameraExtended getCamera() { 38 | return this.camera; 39 | } 40 | 41 | /** 42 | * Check if the camera is working. 43 | * 44 | * @return True if the camera is working, false otherwise. 45 | */ 46 | public boolean isCameraWorking() { 47 | return getCamera().doesLibraryVersionMatchCoprocessorVersion() 48 | && getCamera().isConnectedAkitCompatible(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/edu/wpi/first/wpilibj/MockDigitalOutput.java: -------------------------------------------------------------------------------- 1 | package edu.wpi.first.wpilibj; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | 7 | import xbot.common.controls.actuators.XDigitalOutput; 8 | import xbot.common.injection.DevicePolice; 9 | 10 | public class MockDigitalOutput extends XDigitalOutput { 11 | protected int channel; 12 | protected boolean value; 13 | 14 | @AssistedFactory 15 | public abstract static class MockDigitalOutputFactory implements XDigitalOutputFactory { 16 | public abstract MockDigitalOutput create(@Assisted("channel") int channel); 17 | } 18 | 19 | @AssistedInject 20 | public MockDigitalOutput(@Assisted("channel") int channel, DevicePolice police) { 21 | super(channel, police); 22 | } 23 | 24 | @Override 25 | public void set(boolean value) { 26 | this.value = value; 27 | } 28 | 29 | @Override 30 | public void setPWMRate(double frequency) { 31 | // Unsupported in mock implementation. 32 | } 33 | 34 | @Override 35 | public void enablePWM(double initialDutyCycle) { 36 | // Unsupported in mock implementation. 37 | } 38 | 39 | @Override 40 | public void updateDutyCycle(double dutyCycle) { 41 | // Unsupported in mock implementation. 42 | } 43 | 44 | @Override 45 | public void disablePWM() { 46 | // Unsupported in mock implementation. 47 | } 48 | 49 | @Override 50 | public boolean get() { 51 | return value; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/wpi_adapters/PWMWPIAdapter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators.wpi_adapters; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | 7 | import edu.wpi.first.wpilibj.PWM; 8 | import xbot.common.controls.actuators.XPWM; 9 | import xbot.common.injection.DevicePolice; 10 | 11 | public class PWMWPIAdapter extends XPWM 12 | { 13 | private final PWM pwm; 14 | 15 | @AssistedFactory 16 | public abstract static class PWMWPIAdapterFactory implements XPWMFactory { 17 | public abstract PWMWPIAdapter create(@Assisted("channel") int channel); 18 | } 19 | 20 | @AssistedInject 21 | public PWMWPIAdapter(@Assisted("channel") int channel, DevicePolice police) 22 | { 23 | super(channel, police); 24 | pwm = new PWM(channel); 25 | } 26 | 27 | @Override 28 | public void setRaw(int value) { 29 | pwm.setPulseTimeMicroseconds(value); 30 | } 31 | 32 | @Override 33 | public int getRaw() { 34 | return pwm.getPulseTimeMicroseconds(); 35 | } 36 | 37 | @Override 38 | public void setSigned(double value) { 39 | pwm.setSpeed(value); 40 | } 41 | 42 | @Override 43 | public double getSigned() { 44 | return pwm.getSpeed(); 45 | } 46 | 47 | @Override 48 | public void setUnsigned(double value) { 49 | pwm.setPosition(value); 50 | } 51 | 52 | @Override 53 | public double getUnsigned() { 54 | return pwm.getPosition(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/command/SimpleWaitForMaintainerCommandTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.command; 2 | 3 | import org.junit.Test; 4 | import xbot.common.injection.BaseCommonLibTest; 5 | 6 | import static org.junit.Assert.assertFalse; 7 | import static org.junit.Assert.assertTrue; 8 | 9 | public class SimpleWaitForMaintainerCommandTest extends BaseCommonLibTest { 10 | @Test 11 | public void testTimeout() { 12 | var subsystem = new MockSetpointSubsystem(); 13 | var command = new SimpleWaitForMaintainerCommand(subsystem, () -> 1.0); 14 | subsystem.setCurrentValue(1.0); 15 | assertFalse(subsystem.isMaintainerAtGoal()); 16 | 17 | command.initialize(); 18 | command.execute(); 19 | assertFalse(command.isFinished()); 20 | 21 | this.timer.advanceTimeInSecondsBy(1.5); 22 | command.execute(); 23 | assertTrue(command.isFinished()); 24 | } 25 | 26 | @Test 27 | public void testMaintainerAtGoal() { 28 | var subsystem = new MockSetpointSubsystem(); 29 | var command = new SimpleWaitForMaintainerCommand(subsystem, () -> 1.0); 30 | subsystem.setCurrentValue(1.0); 31 | assertFalse(subsystem.isMaintainerAtGoal()); 32 | 33 | command.initialize(); 34 | command.execute(); 35 | assertFalse(command.isFinished()); 36 | 37 | subsystem.setCurrentValue(0.0); 38 | subsystem.setMaintainerIsAtGoal(true); 39 | this.timer.advanceTimeInSecondsBy(0.2); 40 | command.execute(); 41 | assertTrue(command.isFinished()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/injection/modules/RealControlsModule.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.modules; 2 | 3 | import javax.inject.Singleton; 4 | 5 | import dagger.Binds; 6 | import dagger.Module; 7 | import xbot.common.controls.sensors.XFTCGamepad.XFTCGamepadFactory; 8 | import xbot.common.controls.sensors.XJoystick.XJoystickFactory; 9 | import xbot.common.controls.sensors.XXboxController.XXboxControllerFactory; 10 | import xbot.common.controls.sensors.wpi_adapters.FTCGamepadWpiAdapter.FTCGamepadWpiAdapterFactory; 11 | import xbot.common.controls.sensors.wpi_adapters.JoystickWPIAdapter.JoystickWPIAdapterFactory; 12 | import xbot.common.controls.sensors.wpi_adapters.XboxControllerWpiAdapter.XboxControllerWpiAdapterFactory; 13 | import xbot.common.subsystems.feedback.RumbleManager.RumbleManagerFactory; 14 | import xbot.common.subsystems.feedback.XRumbleManager.XRumbleManagerFactory; 15 | 16 | /** 17 | * Module for mapping control device interfaces to real hardware. 18 | */ 19 | @Module 20 | public abstract class RealControlsModule { 21 | @Binds 22 | @Singleton 23 | public abstract XJoystickFactory getJoystickFactory(JoystickWPIAdapterFactory impl); 24 | 25 | @Binds 26 | @Singleton 27 | public abstract XXboxControllerFactory getXboxControllerFactory(XboxControllerWpiAdapterFactory impl); 28 | 29 | @Binds 30 | @Singleton 31 | public abstract XFTCGamepadFactory getFTCGamepadFactory(FTCGamepadWpiAdapterFactory impl); 32 | 33 | @Binds 34 | @Singleton 35 | public abstract XRumbleManagerFactory getRumbleManagerFactory(RumbleManagerFactory impl); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/math/InterpolatingFieldPoseBuffer.java: -------------------------------------------------------------------------------- 1 | package xbot.common.math; 2 | 3 | import edu.wpi.first.math.geometry.Rotation2d; 4 | import xbot.common.controls.sensors.XTimer; 5 | 6 | public class InterpolatingFieldPoseBuffer { 7 | 8 | private InterpolatingHistoryBuffer xBuffer; 9 | private InterpolatingHistoryBuffer yBuffer; 10 | private InterpolatingHistoryBuffer headingBuffer; 11 | 12 | private double unwrappedHeading; 13 | 14 | public InterpolatingFieldPoseBuffer(FieldPose pose) { 15 | xBuffer = new InterpolatingHistoryBuffer(50, pose.getPoint().x); 16 | yBuffer = new InterpolatingHistoryBuffer(50, pose.getPoint().y); 17 | unwrappedHeading = pose.getHeading().getDegrees(); 18 | headingBuffer = new InterpolatingHistoryBuffer(50, unwrappedHeading); 19 | } 20 | 21 | public void insert(FieldPose pose) { 22 | xBuffer.insert(XTimer.getFPGATimestamp(), pose.getPoint().x); 23 | yBuffer.insert(XTimer.getFPGATimestamp(), pose.getPoint().y); 24 | 25 | double headingDelta = pose.getHeading().minus(Rotation2d.fromDegrees(unwrappedHeading)).getDegrees(); 26 | unwrappedHeading += headingDelta; 27 | headingBuffer.insert(XTimer.getFPGATimestamp(), unwrappedHeading); 28 | } 29 | 30 | public FieldPose getPoseAtTime(double timeInSeconds) { 31 | return new FieldPose(new XYPair( 32 | xBuffer.getValAtTime(timeInSeconds), 33 | yBuffer.getValAtTime(timeInSeconds)), 34 | Rotation2d.fromDegrees(headingBuffer.getValAtTime(timeInSeconds))); 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/logging/RobotAssertionManager.java: -------------------------------------------------------------------------------- 1 | package xbot.common.logging; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.Collectors; 5 | 6 | import org.apache.logging.log4j.LogManager; 7 | import org.apache.logging.log4j.Logger; 8 | 9 | /** 10 | * Base class for safe assertion manager. Allows context-based management of 11 | * exceptions and assertion conditions. 12 | */ 13 | public abstract class RobotAssertionManager { 14 | static Logger log = LogManager.getLogger(RobotAssertionManager.class); 15 | 16 | public final void throwException(RuntimeException e) { 17 | log.error("Safe exception encountered (exception throw {}): {}", this.isExceptionsEnabled() ? "enabled" : "disabled", e.getMessage()); 18 | log.error("Stack trace: \n {}", Arrays.stream(e.getStackTrace()) 19 | .map(StackTraceElement::toString) 20 | .collect(Collectors.joining("\n "))); 21 | 22 | handlePlatformException(e); 23 | } 24 | 25 | public final void throwException(String message, Throwable cause) { 26 | throwException(new RuntimeException(message, cause)); 27 | } 28 | 29 | protected abstract void handlePlatformException(RuntimeException e); 30 | 31 | public abstract boolean isExceptionsEnabled(); 32 | 33 | public final void fail(String message) { 34 | throwException(new RobotAssertionException(message)); 35 | } 36 | 37 | public final void assertTrue(boolean value, String assertionFaliureCause) { 38 | if(!value) { 39 | fail(assertionFaliureCause); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/drive/RabbitPointBuilder.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.drive; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import xbot.common.math.FieldPose; 7 | import xbot.common.subsystems.drive.RabbitPoint.PointDriveStyle; 8 | import xbot.common.subsystems.drive.RabbitPoint.PointTerminatingType; 9 | import xbot.common.subsystems.drive.RabbitPoint.PointType; 10 | 11 | public class RabbitPointBuilder { 12 | 13 | List output; 14 | 15 | private PointType pointType = PointType.PositionAndHeading; 16 | private PointTerminatingType terminatingType = PointTerminatingType.Continue; 17 | private PointDriveStyle driveStyle = PointDriveStyle.Macro; 18 | 19 | public RabbitPointBuilder() { 20 | output = new ArrayList<>(); 21 | } 22 | 23 | public RabbitPointBuilder addPose(FieldPose pose) { 24 | output.add(new RabbitPoint(pose, pointType, terminatingType, driveStyle)); 25 | return this; 26 | } 27 | 28 | public RabbitPointBuilder changePointType(PointType newPointType) { 29 | pointType = newPointType; 30 | return this; 31 | } 32 | 33 | public RabbitPointBuilder changeTerminatingType(PointTerminatingType newTerminatingType) { 34 | terminatingType = newTerminatingType; 35 | return this; 36 | } 37 | 38 | public RabbitPointBuilder changeDriveStyle(PointDriveStyle newStyle) { 39 | driveStyle = newStyle; 40 | return this; 41 | } 42 | 43 | public List build() { 44 | return output; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/networking/ZeromqListenerTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.networking; 2 | 3 | import org.junit.Test; 4 | 5 | import xbot.common.injection.BaseCommonLibTest; 6 | 7 | public class ZeromqListenerTest extends BaseCommonLibTest { 8 | 9 | int packets = 0; 10 | 11 | @Test 12 | public void pubsub() throws InterruptedException { 13 | ZeromqTestServer server = new ZeromqTestServer(); 14 | Thread serverThread = new Thread(server); 15 | serverThread.start(); 16 | 17 | ZeromqListener client = new ZeromqListener("tcp://localhost:5556", "10001 "); 18 | client.setNewPacketHandler(packet -> handlePacket(packet)); 19 | 20 | 21 | client.start(); 22 | 23 | while (true) { 24 | if (packets > 10) { 25 | break; 26 | } 27 | System.out.println("Packet count at : " + packets); 28 | Thread.sleep(100); 29 | } 30 | } 31 | 32 | @Test 33 | public void startWithNoHandler() { 34 | ZeromqTestServer server = new ZeromqTestServer(); 35 | Thread serverThread = new Thread(server); 36 | serverThread.start(); 37 | 38 | ZeromqListener client = new ZeromqListener("tcp://localhost:5556", "10001 "); 39 | client.start(); 40 | } 41 | 42 | @Test 43 | public void stopBeforeStart() { 44 | ZeromqListener client = new ZeromqListener("tcp://localhost:5556", "10001 "); 45 | client.stop(); 46 | } 47 | 48 | private void handlePacket(String packet) { 49 | System.out.println(packet); 50 | packets++; 51 | } 52 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/drive/SwervePointKinematics.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.drive; 2 | 3 | import edu.wpi.first.units.measure.LinearAcceleration; 4 | import edu.wpi.first.units.measure.LinearVelocity; 5 | 6 | import static edu.wpi.first.units.Units.MetersPerSecond; 7 | import static edu.wpi.first.units.Units.MetersPerSecondPerSecond; 8 | 9 | public record SwervePointKinematics(LinearAcceleration acceleration, LinearVelocity initialVelocity, LinearVelocity goalVelocity, LinearVelocity maxVelocity) { 10 | /** 11 | * Creates a set of Kinematics values with METERS 12 | * @param acceleration in meters/second^2 13 | * @param initialVelocity in meters/second; velocity at start 14 | * @param goalVelocity in meters/second; velocity we WANT to end at, in range of [-maxVelocity, maxVelocity] 15 | * @param maxVelocity in meters/second; max speed constraint 16 | */ 17 | public SwervePointKinematics(double acceleration, double initialVelocity, double goalVelocity, double maxVelocity) { 18 | this(MetersPerSecondPerSecond.of(acceleration), MetersPerSecond.of(initialVelocity), MetersPerSecond.of(Math.max(Math.min(maxVelocity, goalVelocity), 19 | -maxVelocity)), MetersPerSecond.of(maxVelocity)); 20 | } 21 | 22 | /** 23 | * @param newInitialVelocity for the set of kinematics 24 | * @return a new set of kinematics values! 25 | */ 26 | public SwervePointKinematics kinematicsWithNewInitialVelocity(LinearVelocity newInitialVelocity) { 27 | return new SwervePointKinematics(acceleration, newInitialVelocity, goalVelocity, maxVelocity); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/simulation/SimulateMockCANTalonTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.simulation; 2 | /* 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.math.BigDecimal; 6 | 7 | import com.ctre.phoenix.motorcontrol.FeedbackDevice; 8 | 9 | import org.json.JSONArray; 10 | import org.json.JSONObject; 11 | import org.junit.Ignore; 12 | import org.junit.Test; 13 | 14 | import xbot.common.controls.actuators.mock_adapters.MockCANTalon; 15 | import xbot.common.injection.electrical_contract.CANTalonInfo; 16 | 17 | @Ignore 18 | public class SimulateMockCANTalonTest extends BaseSimulationTest { 19 | 20 | MockCANTalon mockCANTalon; 21 | 22 | @Override 23 | public void setUp() { 24 | super.setUp(); 25 | 26 | mockCANTalon = (MockCANTalon)injectorComponent.canTalonFactory().create(new CANTalonInfo(34, false, FeedbackDevice.CTRE_MagEncoder_Absolute, false, 1)); 27 | } 28 | 29 | @Test 30 | public void basicTest() { 31 | 32 | JSONObject overallPayload = new JSONObject(); 33 | JSONObject singleSensor = new JSONObject(); 34 | singleSensor.put("ID", "CAN34"); 35 | JSONObject singleSensorPayload = new JSONObject(); 36 | singleSensorPayload.put("EncoderTicks", new BigDecimal("123.002")); 37 | singleSensor.put("Payload", singleSensorPayload); 38 | JSONArray sensorList = new JSONArray(); 39 | sensorList.put(singleSensor); 40 | overallPayload.put("Sensors", sensorList); 41 | 42 | distributor.distributeSimulationPayload(overallPayload); 43 | 44 | assertEquals(123.0, mockCANTalon.getPosition(), 0.001); 45 | } 46 | } 47 | */ -------------------------------------------------------------------------------- /src/test/java/xbot/common/simulation/SimulatedMockAbsoluteEncoderTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.simulation; 2 | 3 | import static edu.wpi.first.units.Units.Rotations; 4 | import static org.junit.Assert.assertEquals; 5 | 6 | import java.math.BigDecimal; 7 | 8 | import org.json.JSONArray; 9 | import org.json.JSONObject; 10 | import org.junit.Ignore; 11 | import org.junit.Test; 12 | 13 | import xbot.common.controls.sensors.mock_adapters.MockAbsoluteEncoder; 14 | import xbot.common.injection.electrical_contract.DeviceInfo; 15 | 16 | @Ignore 17 | public class SimulatedMockAbsoluteEncoderTest extends BaseSimulationTest { 18 | 19 | MockAbsoluteEncoder simulatedEncoder; 20 | 21 | @Override 22 | public void setUp() { 23 | super.setUp(); 24 | 25 | simulatedEncoder = (MockAbsoluteEncoder)injectorComponent.absoluteEncoderFactory().create(new DeviceInfo("Simulated",34, false, 360.0), "test"); 26 | } 27 | 28 | @Test 29 | public void basicTest() { 30 | JSONObject overallPayload = new JSONObject(); 31 | JSONObject singleSensor = new JSONObject(); 32 | singleSensor.put("ID", "CAN34"); 33 | JSONObject singleSensorPayload = new JSONObject(); 34 | singleSensorPayload.put("EncoderTicks", new BigDecimal("1.12")); 35 | singleSensor.put("Payload", singleSensorPayload); 36 | JSONArray sensorList = new JSONArray(); 37 | sensorList.put(singleSensor); 38 | overallPayload.put("Sensors", sensorList); 39 | 40 | distributor.distributeSimulationPayload(overallPayload); 41 | 42 | assertEquals(Rotations.of(43.2), this.simulatedEncoder.getAbsolutePosition_internal()); 43 | } 44 | } -------------------------------------------------------------------------------- /src/test/java/xbot/common/subsystems/pose/commands/SetRobotHeadingCommandTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.pose.commands; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import xbot.common.subsystems.pose.BasePoseSubsystem; 7 | import xbot.common.subsystems.pose.BasePoseTest; 8 | 9 | public class SetRobotHeadingCommandTest extends BasePoseTest { 10 | 11 | SetRobotHeadingCommand setHeading; 12 | 13 | @Before 14 | public void setup() { 15 | super.setup(); 16 | setHeading = getInjectorComponent().setRobotHeadingCommand(); 17 | } 18 | 19 | @Test 20 | public void testSetHeading() { 21 | mockTimer.setTimeInSeconds(mockTimer.getFPGATimestamp() + 1); 22 | verifyRobotHeading(BasePoseSubsystem.FACING_AWAY_FROM_DRIVERS); 23 | 24 | setHeading.setHeadingToApply(74); 25 | setHeading.isFinished(); 26 | setHeading.initialize(); 27 | setHeading.execute(); 28 | 29 | verifyRobotHeading(74); 30 | } 31 | 32 | @Test 33 | public void testSetHeadingLargeValues() { 34 | mockTimer.setTimeInSeconds(2); 35 | verifyRobotHeading(BasePoseSubsystem.FACING_AWAY_FROM_DRIVERS); 36 | 37 | setHeading.setHeadingToApply(361); 38 | setHeading.isFinished(); 39 | setHeading.initialize(); 40 | setHeading.execute(); 41 | 42 | verifyRobotHeading(1); 43 | 44 | setHeading.setHeadingToApply(-361); 45 | setHeading.isFinished(); 46 | setHeading.initialize(); 47 | setHeading.execute(); 48 | 49 | verifyRobotHeading(-1); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/wpi_adapters/AnalogInputWPIAdapater.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.wpi_adapters; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | import edu.wpi.first.wpilibj.AnalogInput; 7 | import xbot.common.controls.sensors.XAnalogInput; 8 | import xbot.common.injection.DevicePolice; 9 | 10 | public class AnalogInputWPIAdapater extends XAnalogInput { 11 | AnalogInput input; 12 | 13 | @AssistedFactory 14 | public abstract static class AnalogInputWPIAdapaterFactory implements XAnalogInputFactory { 15 | public abstract AnalogInputWPIAdapater create(@Assisted("channel") int channel); 16 | } 17 | 18 | @AssistedInject 19 | public AnalogInputWPIAdapater(@Assisted("channel") int channel, DevicePolice police) { 20 | super(channel, police); 21 | input = new AnalogInput(channel); 22 | } 23 | 24 | public int getValue() { 25 | return input.getValue(); 26 | } 27 | 28 | public double getVoltage() { 29 | return input.getVoltage(); 30 | } 31 | 32 | public double getAverageVoltage() { 33 | return input.getAverageVoltage(); 34 | } 35 | 36 | public void setAverageBits(int bits) { 37 | input.setAverageBits(bits); 38 | } 39 | 40 | public AnalogInput getInternalDevice() { 41 | return input; 42 | } 43 | 44 | @Override 45 | public int getChannel() { 46 | return input.getChannel(); 47 | } 48 | 49 | @Override 50 | public boolean getAsDigital(double threshold) { 51 | return getVoltage() >= threshold; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/logic/WatchdogTimer.java: -------------------------------------------------------------------------------- 1 | package xbot.common.logic; 2 | 3 | import xbot.common.controls.sensors.XTimer; 4 | import xbot.common.logic.Latch.EdgeType; 5 | import xbot.common.properties.BooleanProperty; 6 | import xbot.common.properties.DoubleProperty; 7 | import xbot.common.properties.PropertyFactory; 8 | 9 | public class WatchdogTimer { 10 | private double lastKick = Double.NEGATIVE_INFINITY; 11 | private Latch latch; 12 | 13 | private boolean isUp; 14 | private double timeSinceKick; 15 | 16 | private final double timeout; 17 | private Runnable onUp = null; 18 | private Runnable onDown = null; 19 | 20 | private WatchdogTimer(double timeout) { 21 | this.timeout = timeout; 22 | latch = new Latch(false, EdgeType.Both, this::handleLatchUpdate); 23 | } 24 | 25 | public WatchdogTimer(double timeout, Runnable onUp, Runnable onDown) { 26 | this(timeout); 27 | this.onUp = onUp; 28 | this.onDown = onDown; 29 | } 30 | 31 | private void handleLatchUpdate(EdgeType edge) { 32 | if (edge == EdgeType.RisingEdge && onUp != null) { 33 | onUp.run(); 34 | } 35 | else if (edge == EdgeType.FallingEdge && onDown != null) { 36 | onDown.run(); 37 | } 38 | } 39 | 40 | public void kick() { 41 | lastKick = XTimer.getFPGATimestamp(); 42 | } 43 | 44 | public void check() { 45 | double now = XTimer.getFPGATimestamp(); 46 | timeSinceKick = now - lastKick; 47 | isUp = Double.isFinite(timeSinceKick) && timeSinceKick <= timeout; 48 | latch.setValue(isUp); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/properties/MockPermanentStorage.java: -------------------------------------------------------------------------------- 1 | package xbot.common.properties; 2 | 3 | import javax.inject.Inject; 4 | import javax.inject.Singleton; 5 | 6 | import xbot.common.properties.TableProxy; 7 | 8 | @Singleton 9 | public class MockPermanentStorage extends TableProxy implements PermanentStorage { 10 | 11 | private StringBuffer buf; 12 | 13 | /** 14 | * Permanent storage property storage delimiter 15 | */ 16 | protected String propertyDelimiter = ","; 17 | /** 18 | * Permanent storage line seperator 19 | */ 20 | protected String lineSeperator = "\n"; 21 | 22 | @Inject 23 | public MockPermanentStorage() { 24 | super(); 25 | buf = new StringBuffer(); 26 | } 27 | 28 | public void addTestDouble(String key, double value) { 29 | buf.append("double").append(propertyDelimiter).append(key).append(propertyDelimiter).append(value) 30 | .append(lineSeperator); 31 | } 32 | 33 | public void addTestBoolean(String key, boolean value) { 34 | buf.append("boolean").append(propertyDelimiter).append(key).append(propertyDelimiter).append(value) 35 | .append(lineSeperator); 36 | } 37 | 38 | public void addTestString(String key, String value) { 39 | buf.append("string").append(propertyDelimiter).append(key).append(propertyDelimiter).append(value) 40 | .append(lineSeperator); 41 | } 42 | 43 | protected String readFromFile() { 44 | return buf.toString(); 45 | } 46 | 47 | protected void writeToFile(String data) { 48 | StringBuffer sbdata = new StringBuffer(data); 49 | buf = sbdata; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/sensors/buttons/AdvancedXboxAxisTrigger.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.sensors.buttons; 2 | 3 | import java.util.function.BooleanSupplier; 4 | 5 | import xbot.common.controls.sensors.XXboxController; 6 | import xbot.common.controls.sensors.XXboxController.XboxButton; 7 | 8 | public class AdvancedXboxAxisTrigger extends AdvancedXboxButtonTrigger { 9 | 10 | public AdvancedXboxAxisTrigger(XXboxController controller, XboxButton buttonName, double threshold) { 11 | super(controller, buttonName, (BooleanSupplier)(() -> getValue(controller, buttonName, threshold))); 12 | } 13 | 14 | private static boolean getValue(XXboxController controller, XboxButton buttonName, double threshold) { 15 | double value = 0; 16 | 17 | switch(buttonName) { 18 | case LeftTrigger: 19 | value = controller.getLeftTrigger(); 20 | break; 21 | case RightTrigger: 22 | value = controller.getRightTrigger(); 23 | break; 24 | case LeftJoystickYAxisPositive: 25 | case LeftJoystickYAxisNegative: 26 | value = controller.getLeftStickY(); 27 | break; 28 | case RightJoystickYAxisPositive: 29 | case RightJoystickYAxisNegative: 30 | value = controller.getRightStickY(); 31 | break; 32 | default: 33 | break; 34 | } 35 | 36 | // For the "negative axis" buttons 37 | if (buttonName.getUsesNegativeRange()) 38 | { 39 | return value < -threshold; 40 | } 41 | return value > threshold; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/edu/wpi/first/wpilibj/MockAnalogInput.java: -------------------------------------------------------------------------------- 1 | package edu.wpi.first.wpilibj; 2 | 3 | import org.json.JSONObject; 4 | 5 | import dagger.assisted.Assisted; 6 | import dagger.assisted.AssistedFactory; 7 | import dagger.assisted.AssistedInject; 8 | 9 | import xbot.common.controls.sensors.XAnalogInput; 10 | import xbot.common.injection.DevicePolice; 11 | import xbot.common.simulation.ISimulatableSensor; 12 | 13 | public class MockAnalogInput extends XAnalogInput implements ISimulatableSensor { 14 | int channel; 15 | double voltage; 16 | 17 | @AssistedFactory 18 | public abstract static class MockAnalogInputFactory implements XAnalogInputFactory { 19 | public abstract MockAnalogInput create(@Assisted("channel") int channel); 20 | } 21 | 22 | @AssistedInject 23 | public MockAnalogInput(@Assisted("channel") int channel, DevicePolice police) { 24 | super(channel, police); 25 | this.channel = channel; 26 | } 27 | 28 | public void setVoltage(double voltage) { 29 | this.voltage = voltage; 30 | } 31 | 32 | public double getVoltage() { 33 | return voltage; 34 | } 35 | 36 | public double getAverageVoltage() { 37 | return voltage; 38 | } 39 | 40 | public void setAverageBits(int bits) { 41 | // Nothing to do here. 42 | } 43 | 44 | @Override 45 | public int getChannel() { 46 | return channel; 47 | } 48 | 49 | @Override 50 | public boolean getAsDigital(double threshold) { 51 | return getVoltage() >= threshold; 52 | } 53 | 54 | @Override 55 | public void ingestSimulationData(JSONObject payload) { 56 | setVoltage(payload.getDouble("Voltage")); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/subsystems/drive/MockSwerveDriveSubsystem.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.drive; 2 | 3 | import edu.wpi.first.math.geometry.Rotation2d; 4 | import edu.wpi.first.math.geometry.Translation2d; 5 | import xbot.common.injection.swerve.FrontLeftDrive; 6 | import xbot.common.injection.swerve.FrontRightDrive; 7 | import xbot.common.injection.swerve.RearLeftDrive; 8 | import xbot.common.injection.swerve.RearRightDrive; 9 | import xbot.common.injection.swerve.SwerveComponent; 10 | import xbot.common.math.PIDManager; 11 | import xbot.common.properties.PropertyFactory; 12 | 13 | import javax.inject.Inject; 14 | 15 | public class MockSwerveDriveSubsystem extends BaseSwerveDriveSubsystem { 16 | @Inject 17 | public MockSwerveDriveSubsystem(PIDManager.PIDManagerFactory pidFactory, PropertyFactory pf, 18 | @FrontLeftDrive SwerveComponent frontLeftSwerve, 19 | @FrontRightDrive SwerveComponent frontRightSwerve, 20 | @RearLeftDrive SwerveComponent rearLeftSwerve, 21 | @RearRightDrive SwerveComponent rearRightSwerve) { 22 | super(pidFactory, pf, frontLeftSwerve, frontRightSwerve, rearLeftSwerve, rearRightSwerve); 23 | } 24 | 25 | @Override 26 | public boolean getStaticHeadingActive() { 27 | return false; 28 | } 29 | 30 | @Override 31 | public boolean getLookAtPointActive() { 32 | return false; 33 | } 34 | 35 | @Override 36 | public Rotation2d getStaticHeadingTarget() { 37 | return null; 38 | } 39 | 40 | @Override 41 | public Translation2d getLookAtPointTarget() { 42 | return null; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/subsystems/feedback/RumbleManagerTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.feedback; 2 | 3 | import static org.junit.Assert.assertFalse; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import org.junit.Test; 7 | 8 | import edu.wpi.first.wpilibj.MockTimer; 9 | import xbot.common.controls.sensors.mock_adapters.MockFTCGamepad; 10 | import xbot.common.injection.BaseCommonLibTest; 11 | 12 | /** 13 | * Unit tests for RumbleManager 14 | */ 15 | public class RumbleManagerTest extends BaseCommonLibTest { 16 | 17 | MockFTCGamepad gamepad; 18 | RumbleManager rumbleManager; 19 | MockTimer timer; 20 | 21 | @Override 22 | public void setUp() { 23 | super.setUp(); 24 | 25 | this.gamepad = (MockFTCGamepad)getInjectorComponent().ftcGamepadFactory().create(0, 10); 26 | this.rumbleManager = new RumbleManager(this.gamepad); 27 | this.timer = (MockTimer)getInjectorComponent().timerImplementation(); 28 | } 29 | 30 | @Test 31 | public void testGetIsRumbling() { 32 | assertFalse(rumbleManager.getIsRumbling()); 33 | 34 | rumbleManager.rumbleGamepad(5, 10); 35 | assertTrue(rumbleManager.getIsRumbling()); 36 | 37 | rumbleManager.stopGamepadRumble(); 38 | assertFalse(rumbleManager.getIsRumbling()); 39 | } 40 | 41 | @Test 42 | public void testRumbleGamepad() { 43 | double rumbleDuration = 10; 44 | rumbleManager.rumbleGamepad(5, rumbleDuration); 45 | assertTrue(rumbleManager.getIsRumbling()); 46 | 47 | timer.advanceTimeInSecondsBy(rumbleDuration + 0.01); 48 | rumbleManager.periodic(); 49 | assertFalse(rumbleManager.getIsRumbling()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/math/HistoryBufferTests.java: -------------------------------------------------------------------------------- 1 | package xbot.common.math; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | import xbot.common.controls.sensors.XTimer; 8 | import xbot.common.injection.BaseCommonLibTest; 9 | 10 | public class HistoryBufferTests extends BaseCommonLibTest { 11 | 12 | @Test 13 | public void simpleBufferTest() { 14 | InterpolatingHistoryBuffer b = new InterpolatingHistoryBuffer(3, 5); 15 | timer.advanceTimeInSecondsBy(2); 16 | b.insert(XTimer.getFPGATimestamp(), 10); 17 | assertEquals(7.5, b.getValAtTime(1), 0.001); 18 | } 19 | 20 | @Test 21 | public void simplePoseBufferTest() { 22 | FieldPose startingPose = new FieldPose(0, 0, 90); 23 | InterpolatingFieldPoseBuffer b = new InterpolatingFieldPoseBuffer(startingPose); 24 | timer.advanceTimeInSecondsBy(1); 25 | b.insert(new FieldPose(20, 20, 180)); 26 | assertEquals(10, b.getPoseAtTime(0.5).getPoint().x, 0.001); 27 | assertEquals(10, b.getPoseAtTime(0.5).getPoint().y, 0.001); 28 | assertEquals(135, b.getPoseAtTime(0.5).getHeading().getDegrees(), 0.001); 29 | } 30 | 31 | @Test 32 | public void acrossBoundaryTest() { 33 | FieldPose startingPose = new FieldPose(0, 0, 140); 34 | InterpolatingFieldPoseBuffer b = new InterpolatingFieldPoseBuffer(startingPose); 35 | timer.advanceTimeInSecondsBy(1); 36 | b.insert(new FieldPose(20, 20, -130)); 37 | assertEquals(10, b.getPoseAtTime(0.5).getPoint().x, 0.001); 38 | assertEquals(10, b.getPoseAtTime(0.5).getPoint().y, 0.001); 39 | assertEquals(-175, b.getPoseAtTime(0.5).getHeading().getDegrees(), 0.001); 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/java/xbot/common/controls/actuators/wpi_adapters/DigitalOutputWPIAdapter.java: -------------------------------------------------------------------------------- 1 | package xbot.common.controls.actuators.wpi_adapters; 2 | 3 | import dagger.assisted.Assisted; 4 | import dagger.assisted.AssistedFactory; 5 | import dagger.assisted.AssistedInject; 6 | 7 | import edu.wpi.first.wpilibj.DigitalOutput; 8 | import xbot.common.controls.actuators.XDigitalOutput; 9 | import xbot.common.injection.DevicePolice; 10 | 11 | public class DigitalOutputWPIAdapter extends XDigitalOutput { 12 | 13 | DigitalOutput adapter; 14 | 15 | @AssistedFactory 16 | public abstract static class DigitalOutputWPIAdapterFactory implements XDigitalOutputFactory { 17 | public abstract DigitalOutputWPIAdapter create(@Assisted("channel") int channel); 18 | } 19 | 20 | @AssistedInject 21 | public DigitalOutputWPIAdapter(@Assisted("channel") int channel, DevicePolice police) { 22 | super(channel, police); 23 | adapter = new DigitalOutput(channel); 24 | } 25 | 26 | public void set(boolean value) { 27 | adapter.set(value); 28 | } 29 | 30 | public DigitalOutput getWPIDigitalOutput() { 31 | return adapter; 32 | } 33 | 34 | @Override 35 | public void setPWMRate(double frequency) { 36 | adapter.setPWMRate(frequency); 37 | } 38 | 39 | @Override 40 | public void enablePWM(double initialDutyCycle) { 41 | adapter.enablePWM(initialDutyCycle); 42 | } 43 | 44 | @Override 45 | public void updateDutyCycle(double dutyCycle) { 46 | adapter.updateDutyCycle(dutyCycle); 47 | } 48 | 49 | @Override 50 | public void disablePWM() { 51 | adapter.disablePWM(); 52 | } 53 | 54 | @Override 55 | public boolean get() { 56 | return adapter.get(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/xbot/common/subsystems/autonomous/SetAutonomousCommand.java: -------------------------------------------------------------------------------- 1 | package xbot.common.subsystems.autonomous; 2 | 3 | import javax.inject.Inject; 4 | 5 | import edu.wpi.first.math.geometry.Pose2d; 6 | import edu.wpi.first.wpilibj2.command.Command; 7 | import xbot.common.command.BaseCommand; 8 | 9 | public class SetAutonomousCommand extends BaseCommand { 10 | 11 | private final AutonomousCommandSelector selector; 12 | private Command autonomousCommand; 13 | 14 | private Pose2d autonomousStartingPosition; 15 | 16 | @Inject 17 | public SetAutonomousCommand(AutonomousCommandSelector selector) { 18 | this.selector = selector; 19 | } 20 | 21 | @Override 22 | public boolean runsWhenDisabled() { 23 | return true; 24 | } 25 | 26 | public void setAutoCommand(Command autonomousCommand) { 27 | setAutoCommand(autonomousCommand, new Pose2d()); 28 | } 29 | 30 | public void setAutoCommand(Command autonomousCommand, Pose2d startingPosition) { 31 | this.autonomousCommand = autonomousCommand; 32 | this.autonomousStartingPosition = startingPosition; 33 | } 34 | 35 | @Override 36 | public void initialize() { 37 | if (autonomousCommand != null) { 38 | log.info("Setting Auto to: " + autonomousCommand.getName()); 39 | selector.setCurrentAutonomousCommand(autonomousCommand); 40 | selector.setCurrentAutonomousStartingPosition(autonomousStartingPosition); 41 | } else { 42 | log.warn("No autonomous command configured. Not changing the current autonomous command."); 43 | } 44 | } 45 | 46 | @Override 47 | public void execute() { 48 | } 49 | 50 | @Override 51 | public boolean isFinished() { 52 | return true; 53 | } 54 | } -------------------------------------------------------------------------------- /src/test/java/xbot/common/injection/modules/CommonLibTestModule.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.modules; 2 | 3 | import dagger.Binds; 4 | import dagger.BindsInstance; 5 | import dagger.Module; 6 | import dagger.Provides; 7 | import xbot.common.injection.MockCameraElectricalContract; 8 | import xbot.common.injection.electrical_contract.MockSwerveDriveElectricalContract; 9 | import xbot.common.injection.electrical_contract.XCameraElectricalContract; 10 | import xbot.common.injection.electrical_contract.XSwerveDriveElectricalContract; 11 | import xbot.common.injection.swerve.FrontLeftDrive; 12 | import xbot.common.injection.swerve.FrontRightDrive; 13 | import xbot.common.injection.swerve.RearLeftDrive; 14 | import xbot.common.injection.swerve.RearRightDrive; 15 | import xbot.common.injection.swerve.SwerveComponent; 16 | import xbot.common.injection.swerve.SwerveInstance; 17 | import xbot.common.subsystems.drive.BaseSwerveDriveSubsystem; 18 | import xbot.common.subsystems.drive.MockSwerveDriveSubsystem; 19 | import xbot.common.subsystems.pose.GameField; 20 | 21 | import javax.inject.Singleton; 22 | 23 | @Module 24 | public abstract class CommonLibTestModule { 25 | @Binds 26 | @Singleton 27 | public abstract BaseSwerveDriveSubsystem getSwerveDriveSubsystem(MockSwerveDriveSubsystem mockSubsystem); 28 | 29 | @Binds 30 | @Singleton 31 | public abstract XSwerveDriveElectricalContract getMockSwerveDriveElectricalContract(MockSwerveDriveElectricalContract impl); 32 | 33 | @Binds 34 | @Singleton 35 | public abstract XCameraElectricalContract getMockCameraElectricalContract(MockCameraElectricalContract impl); 36 | 37 | @Provides 38 | @Singleton 39 | public static GameField.Symmetry getSymmetry() { 40 | return GameField.Symmetry.Rotational; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/injection/modules/SwerveInjectionModule.java: -------------------------------------------------------------------------------- 1 | package xbot.common.injection.modules; 2 | 3 | import dagger.Module; 4 | import dagger.Provides; 5 | import xbot.common.injection.swerve.FrontLeftDrive; 6 | import xbot.common.injection.swerve.FrontRightDrive; 7 | import xbot.common.injection.swerve.RearLeftDrive; 8 | import xbot.common.injection.swerve.RearRightDrive; 9 | import xbot.common.injection.swerve.SwerveComponent; 10 | import xbot.common.injection.swerve.SwerveInstance; 11 | 12 | import javax.inject.Singleton; 13 | 14 | @Module(subcomponents = { SwerveComponent.class }) 15 | public class SwerveInjectionModule { 16 | @Provides 17 | @Singleton 18 | public @FrontLeftDrive SwerveComponent frontLeftSwerveComponent(SwerveComponent.Builder builder) { 19 | return builder 20 | .swerveInstance(new SwerveInstance("FrontLeftDrive")) 21 | .build(); 22 | } 23 | 24 | @Provides 25 | @Singleton 26 | public @FrontRightDrive SwerveComponent frontRightSwerveComponent(SwerveComponent.Builder builder) { 27 | return builder 28 | .swerveInstance(new SwerveInstance("FrontRightDrive")) 29 | .build(); 30 | } 31 | 32 | @Provides 33 | @Singleton 34 | public @RearLeftDrive SwerveComponent rearLeftSwerveComponent(SwerveComponent.Builder builder) { 35 | return builder 36 | .swerveInstance(new SwerveInstance("RearLeftDrive")) 37 | .build(); 38 | } 39 | 40 | @Provides 41 | @Singleton 42 | public @RearRightDrive SwerveComponent rearRightSwerveComponent(SwerveComponent.Builder builder) { 43 | return builder 44 | .swerveInstance(new SwerveInstance("RearRightDrive")) 45 | .build(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/xbot/common/math/DoubleInterpolatorTest.java: -------------------------------------------------------------------------------- 1 | package xbot.common.math; 2 | 3 | import org.junit.Test; 4 | import xbot.common.injection.BaseCommonLibTest; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | public class DoubleInterpolatorTest extends BaseCommonLibTest { 9 | DoubleInterpolator converter; 10 | //meters 11 | double[] testDistance = {1,2,3,4,5,6,7,8,10,11}; 12 | double[] testRPM = {500,950,1300,1500,1700,2200,2500,2700,3000,3500}; 13 | 14 | @Override 15 | public void setUp() { 16 | super.setUp(); 17 | converter = new DoubleInterpolator(testDistance,testRPM); 18 | } 19 | 20 | @Test 21 | public void testConverter() { 22 | //testing when distance is exactly equal to a recorded data point (Also testing when the distance is the first and lastelement in the array) 23 | assertEquals(500, converter.getInterpolatedOutputVariable(1), 0.00001); 24 | assertEquals(3500, converter.getInterpolatedOutputVariable(11), 0.00001); 25 | assertEquals(2200, converter.getInterpolatedOutputVariable(6), 0.00001); 26 | 27 | //testing when distance is in between two points in the recorded data 28 | assertEquals(725,converter.getInterpolatedOutputVariable(1.5),0.00001); 29 | assertEquals(2850,converter.getInterpolatedOutputVariable(9),0.00001); 30 | 31 | //testing when distance is less than the lowest or 32 | // greater than the highest recorded data point(should return zero?? Unless we should return something else) 33 | assertEquals(0,converter.getInterpolatedOutputVariable(0.5),0.00001); 34 | assertEquals(0,converter.getInterpolatedOutputVariable(200),0.00001); 35 | assertEquals(0,converter.getInterpolatedOutputVariable(-192391),0.00001); 36 | 37 | } 38 | } 39 | --------------------------------------------------------------------------------