From 577fbf7ede963c1777893380f8732c3467397e59 Mon Sep 17 00:00:00 2001 From: Robo-Phantoms Date: Tue, 28 Jul 2026 13:18:45 -0500 Subject: [PATCH 1/3] Made setPower return a power and added a setter for voltage. Removed setVoltageSetpoint(). --- .../nextftc/hardware/actuators/NextMotor.kt | 77 +++++++++++++------ 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/hardware/src/main/kotlin/dev/nextftc/hardware/actuators/NextMotor.kt b/hardware/src/main/kotlin/dev/nextftc/hardware/actuators/NextMotor.kt index 20dd422..9af155c 100644 --- a/hardware/src/main/kotlin/dev/nextftc/hardware/actuators/NextMotor.kt +++ b/hardware/src/main/kotlin/dev/nextftc/hardware/actuators/NextMotor.kt @@ -8,6 +8,7 @@ package dev.nextftc.hardware.actuators +import com.qualcomm.robotcore.hardware.DcMotor import com.qualcomm.robotcore.hardware.DcMotorImplEx import com.qualcomm.robotcore.hardware.DcMotorSimple import com.qualcomm.robotcore.hardware.Servo @@ -25,6 +26,7 @@ import dev.nextftc.units.measuretypes.Angle import dev.nextftc.units.measuretypes.AngularVelocity import dev.nextftc.units.radians import dev.nextftc.units.seconds +import dev.nextftc.units.volts import kotlin.math.sign import dev.nextftc.units.measuretypes.Voltage as VoltageMeasure @@ -173,6 +175,21 @@ class NextMotor @JvmOverloads constructor( } } + /** + * Motor zero power behavior (FLOAT or BRAKE). + * + * When set, automatically updates the underlying motor's zero power behavior. + */ + var zeroPowerBehavior = ZeroPowerBehavior.FLOAT + set(value) { + field = value + if (lazyMotor.isInitialized) { + motor.zeroPowerBehavior = value.sdkZeroPowerBehavior + } else { + lazyMotor.applyAfterInit { it.zeroPowerBehavior = value.sdkZeroPowerBehavior } + } + } + /** * Current encoder position in physical angle units. * @@ -229,9 +246,10 @@ class NextMotor @JvmOverloads constructor( reference = setpoint.magnitude, measured = encoderPosition.into(setpoint.unit), ) + - positionConstants.kS * positionPID.error.sign + - positionConstants.kG + - positionConstants.kCos * kotlin.math.cos(encoderPosition.magnitude * positionConstants.kCosRatio) + positionConstants.kS * positionPID.error.sign + + positionConstants.kG + + positionConstants.kCos * + kotlin.math.cos(encoderPosition.magnitude * positionConstants.kCosRatio) } is ControlType.AbsolutePosition -> { val setpoint = mode.setpoint @@ -245,10 +263,10 @@ class NextMotor @JvmOverloads constructor( reference = setpoint.magnitude, measured = measuredPos, ) + - positionConstants.kS * positionPID.error.sign + - positionConstants.kG + - positionConstants.kCos * - kotlin.math.cos(absoluteEncoderPosition.magnitude * positionConstants.kCosRatio) + positionConstants.kS * positionPID.error.sign + + positionConstants.kG + + positionConstants.kCos * + kotlin.math.cos(absoluteEncoderPosition.magnitude * positionConstants.kCosRatio) } is ControlType.Velocity -> { val setpoint = mode.setpoint @@ -257,7 +275,7 @@ class NextMotor @JvmOverloads constructor( reference = setpoint.magnitude, measured = encoderVelocity.into(setpoint.unit), ) + - velocityFF.calculate(setpoint.magnitude) + velocityFF.calculate(setpoint.magnitude) } is ControlType.Follow -> { power = if (mode.direction == Direction.FORWARD) { @@ -273,24 +291,24 @@ class NextMotor @JvmOverloads constructor( * Set throttle control mode and power. * * This is the simplest control mode: power is applied directly. - * - * @param throttle Power in the range [-1.0, 1.0]. Positive is forward. */ - fun setThrottle(throttle: Double) { - controlType = ControlType.Throttle(throttle) - } + var throttle: Double + get() = power + set(value) { + controlType = ControlType.Throttle(value) + } /** - * Set voltage control mode and voltage setpoint. + * Returns the approximate motor voltage command. * - * Adjusts power to maintain the specified voltage, accounting for the - * current input rail voltage (to remain relatively hardware-independent). - * - * @param voltage Target voltage setpoint. + * Calculated from the current motor power output and battery voltage. + * This is not a measured voltage. */ - fun setVoltage(voltage: VoltageMeasure) { - controlType = ControlType.Voltage(voltage) - } + var voltage: VoltageMeasure + get() = (power * RobotController.inputVoltage.magnitude).volts + set(value) { + controlType = ControlType.Voltage(value) + } /** * Set position control mode and position setpoint. @@ -403,6 +421,21 @@ class NextMotor @JvmOverloads constructor( REVERSE(DcMotorSimple.Direction.REVERSE, Servo.Direction.REVERSE), } + /** + * Motor zero power behavior. + */ + enum class ZeroPowerBehavior(val sdkZeroPowerBehavior: DcMotor.ZeroPowerBehavior) { + /** + * Motor stops and floats (no resistance after stopping). + */ + FLOAT(DcMotor.ZeroPowerBehavior.FLOAT), + + /** + * Motor stops and brakes (resists movement after stopping). + */ + BRAKE(DcMotor.ZeroPowerBehavior.BRAKE), + } + companion object { val motorEventLoop: EventLoop = EventLoop() } @@ -492,4 +525,4 @@ data class MotorVelocityConstants( fun withS(kS: Double) = apply { this.kS = kS } fun withV(kV: Double) = apply { this.kV = kV } fun withA(kA: Double) = apply { this.kA = kA } -} +} \ No newline at end of file From 89b85dbbd3551f74256599342ebdd1eda0d9e888 Mon Sep 17 00:00:00 2001 From: Robo-Phantoms Date: Tue, 28 Jul 2026 13:21:52 -0500 Subject: [PATCH 2/3] spotless --- .../nextftc/hardware/actuators/NextMotor.kt | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/hardware/src/main/kotlin/dev/nextftc/hardware/actuators/NextMotor.kt b/hardware/src/main/kotlin/dev/nextftc/hardware/actuators/NextMotor.kt index 9af155c..654892b 100644 --- a/hardware/src/main/kotlin/dev/nextftc/hardware/actuators/NextMotor.kt +++ b/hardware/src/main/kotlin/dev/nextftc/hardware/actuators/NextMotor.kt @@ -246,10 +246,10 @@ class NextMotor @JvmOverloads constructor( reference = setpoint.magnitude, measured = encoderPosition.into(setpoint.unit), ) + - positionConstants.kS * positionPID.error.sign + - positionConstants.kG + - positionConstants.kCos * - kotlin.math.cos(encoderPosition.magnitude * positionConstants.kCosRatio) + positionConstants.kS * positionPID.error.sign + + positionConstants.kG + + positionConstants.kCos * + kotlin.math.cos(encoderPosition.magnitude * positionConstants.kCosRatio) } is ControlType.AbsolutePosition -> { val setpoint = mode.setpoint @@ -263,10 +263,10 @@ class NextMotor @JvmOverloads constructor( reference = setpoint.magnitude, measured = measuredPos, ) + - positionConstants.kS * positionPID.error.sign + - positionConstants.kG + - positionConstants.kCos * - kotlin.math.cos(absoluteEncoderPosition.magnitude * positionConstants.kCosRatio) + positionConstants.kS * positionPID.error.sign + + positionConstants.kG + + positionConstants.kCos * + kotlin.math.cos(absoluteEncoderPosition.magnitude * positionConstants.kCosRatio) } is ControlType.Velocity -> { val setpoint = mode.setpoint @@ -275,7 +275,7 @@ class NextMotor @JvmOverloads constructor( reference = setpoint.magnitude, measured = encoderVelocity.into(setpoint.unit), ) + - velocityFF.calculate(setpoint.magnitude) + velocityFF.calculate(setpoint.magnitude) } is ControlType.Follow -> { power = if (mode.direction == Direction.FORWARD) { @@ -525,4 +525,4 @@ data class MotorVelocityConstants( fun withS(kS: Double) = apply { this.kS = kS } fun withV(kV: Double) = apply { this.kV = kV } fun withA(kA: Double) = apply { this.kA = kA } -} \ No newline at end of file +} From 2542cb1d36f39672d194247e7484ca3b4645e7ab Mon Sep 17 00:00:00 2001 From: Robo-Phantoms Date: Tue, 28 Jul 2026 14:12:40 -0500 Subject: [PATCH 3/3] Replaced `setThrottle()` to `throttle` property. --- .../dev/nextftc/robot/drive/DriveCommands.kt | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/robot/src/main/kotlin/dev/nextftc/robot/drive/DriveCommands.kt b/robot/src/main/kotlin/dev/nextftc/robot/drive/DriveCommands.kt index 70e2b97..21f24d8 100644 --- a/robot/src/main/kotlin/dev/nextftc/robot/drive/DriveCommands.kt +++ b/robot/src/main/kotlin/dev/nextftc/robot/drive/DriveCommands.kt @@ -41,10 +41,10 @@ fun mecanumDrive( rx = gamepad.right_stick_x.toDouble() * scalar, ), ) - frontLeft.setThrottle(powers.frontLeft) - frontRight.setThrottle(powers.frontRight) - backLeft.setThrottle(powers.backLeft) - backRight.setThrottle(powers.backRight) + frontLeft.throttle = powers.frontLeft + frontRight.throttle = powers.frontRight + backLeft.throttle = powers.backLeft + backRight.throttle = powers.backRight } /** @@ -79,10 +79,10 @@ fun mecanumDriveFieldCentric( rx = gamepad.right_stick_x.toDouble() * scalar, ), ) - frontLeft.setThrottle(powers.frontLeft) - frontRight.setThrottle(powers.frontRight) - backLeft.setThrottle(powers.backLeft) - backRight.setThrottle(powers.backRight) + frontLeft.throttle = powers.frontLeft + frontRight.throttle = powers.frontRight + backLeft.throttle = powers.backLeft + backRight.throttle = powers.backRight } /** Command that drives a tank drivetrain from [gamepad]'s sticks. */ @@ -101,8 +101,8 @@ fun tankDrive( rx = gamepad.right_stick_x.toDouble() * scalar, ), ) - frontLeft.setThrottle(powers.left) - backLeft.setThrottle(powers.left) - frontRight.setThrottle(powers.right) - backRight.setThrottle(powers.right) + frontLeft.throttle = powers.left + backLeft.throttle = powers.left + frontRight.throttle = powers.right + backRight.throttle = powers.right }