Skip to content

Commit 6e18eec

Browse files
committed
Refactor Spindexer class to enhance artifact handling and improve sensor integration
1 parent 1ec785b commit 6e18eec

File tree

1 file changed

+107
-17
lines changed

1 file changed

+107
-17
lines changed

TeamCode/src/main/kotlin/pioneer/hardware/Spindexer.kt

Lines changed: 107 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,52 @@ import com.qualcomm.hardware.rev.RevColorSensorV3
44
import com.qualcomm.robotcore.hardware.DcMotor
55
import com.qualcomm.robotcore.hardware.DcMotorEx
66
import com.qualcomm.robotcore.hardware.HardwareMap
7+
import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit
78
import pioneer.decode.Artifact
9+
import pioneer.decode.Motif
810
import kotlin.math.PI
911
import kotlin.math.abs
1012

13+
14+
15+
/*
16+
Positive ROT: CW due to under-mounted motor
17+
18+
INTAKE (INITIALIZED SPINDEXER POSITION):
19+
20+
21+
\ /
22+
\ 1 /
23+
\ /
24+
*
25+
2 | 3
26+
|
27+
|
28+
29+
OUTAKE:
30+
31+
|
32+
|
33+
2 * 1
34+
/ \
35+
/ 3 \
36+
/ \
37+
38+
*/
39+
40+
1141
class Spindexer(
1242
private val hardwareMap: HardwareMap,
1343
private val motorName: String,
1444
private val intakeSensorName: String,
15-
private val outakeSensorName: String
16-
) : HardwareComponent{
45+
private val outakeSensorName: String,
46+
private var artifacts: MutableList<Artifact?> = MutableList(3) { null },
47+
private var motif: List<Artifact> = Motif(21).getPattern(),
48+
49+
) : HardwareComponent {
50+
51+
private val ticksPerRadian = (28 * 5 * 4 / (2 * PI)).toInt()
52+
1753
enum class MotorPosition(val radians: Double) {
1854
INTAKE_1(0 * PI / 3),
1955
OUTAKE_1(1 * PI / 3),
@@ -28,13 +64,10 @@ class Spindexer(
2864
private val outakePositions =
2965
listOf(MotorPosition.OUTAKE_1, MotorPosition.OUTAKE_2, MotorPosition.OUTAKE_3)
3066

31-
override val name = "Spindexer"
32-
33-
lateinit var motor: DcMotorEx // MAKE PRIVATE
67+
private lateinit var motor: DcMotorEx
3468
private lateinit var intakeSensor: RevColorSensorV3
3569
private lateinit var outakeSensor: RevColorSensorV3
3670

37-
private var artifacts: List<Artifact?> = listOf(null, null, null)
3871
var motorState: MotorPosition = MotorPosition.INTAKE_1
3972

4073
val isFull: Boolean
@@ -48,18 +81,46 @@ class Spindexer(
4881
motor.mode = DcMotor.RunMode.STOP_AND_RESET_ENCODER
4982
}
5083

51-
fun moveToNextOpenIntake(): Boolean {
52-
artifacts.indexOfFirst { it == null }.takeIf { it != -1 }?.let {
53-
motorState = intakePositions[it]
54-
return true
84+
private fun getPositionIndex(): Int? {
85+
return when {
86+
motorState in intakePositions -> intakePositions.indexOf(motorState)
87+
motorState in outakePositions -> outakePositions.indexOf(motorState)
88+
else -> null // Safety check
5589
}
56-
return false
90+
}
91+
92+
private fun withSensor(sensor: RevColorSensorV3, enableLight: Boolean, action: (RevColorSensorV3) -> Artifact?): Artifact? {
93+
sensor.enableLed(enableLight)
94+
return action(sensor).also { sensor.enableLed(false) }
95+
}
96+
97+
private fun matchesPattern(startIndex: Int, offset: Int): Boolean {
98+
for (i in motif.indices) {
99+
val artifactIndex = (startIndex + i) % artifacts.size
100+
val motifIndex = (i + offset) % motif.size
101+
if (artifacts[artifactIndex] != motif[motifIndex]) {
102+
return false
103+
}
104+
}
105+
return true
106+
}
107+
108+
// Artifact Handling
109+
private fun storeArtifact(artifact: Artifact?) {
110+
val index = getPositionIndex() ?: return
111+
artifacts[index] = artifact
112+
}
113+
114+
private fun scanArtifact(enableLight: Boolean = false): Artifact? {
115+
return withSensor(currentSensor(), enableLight) { detectArtifact(it) }
57116
}
58117

59118
private fun detectArtifact(sensor: RevColorSensorV3): Artifact? {
60119
val (red, blue, green, _) = listOf(sensor.red(), sensor.blue(), sensor.green(), sensor.alpha())
120+
val distance = sensor.getDistance(DistanceUnit.CM)
61121

62122
return when {
123+
distance > 7.0 -> null
63124
red > 200 && blue > 200 -> Artifact.PURPLE
64125
green > 200 -> Artifact.GREEN
65126
else -> null
@@ -69,14 +130,35 @@ class Spindexer(
69130
private fun currentSensor(): RevColorSensorV3 =
70131
if (motorState in intakePositions) intakeSensor else outakeSensor
71132

72-
private fun scanArtifact(enableLight: Boolean = false): Artifact? {
73-
val sensor = currentSensor()
74-
sensor.enableLed(enableLight)
75-
return detectArtifact(sensor).also { sensor.enableLed(false) }
133+
fun scanAndStoreArtifact(enableLight: Boolean = false) {
134+
storeArtifact(scanArtifact(enableLight))
135+
}
136+
137+
private fun findStartingPatternIndex(offset: Int = 0): Int {
138+
if (motif.isEmpty()) {
139+
return artifacts.indexOfFirst { it != null }.takeIf { it != -1 } ?: 0
140+
}
141+
142+
for (startIndex in artifacts.indices) {
143+
if (matchesPattern(startIndex, offset)) {
144+
return startIndex
145+
}
146+
}
147+
return artifacts.indexOfFirst { it != null }.takeIf { it != -1 } ?: 0
148+
}
149+
150+
fun switchMode() {
151+
val index = getPositionIndex() ?: return
152+
153+
motorState = if (motorState in intakePositions) {
154+
outakePositions[index]
155+
} else {
156+
intakePositions[index]
157+
}
76158
}
77159

78160
fun update() {
79-
val targetPositionTicks = (28 * 5 * 4 * motorState.radians / (2 * PI)).toInt()
161+
val targetPositionTicks = (motorState.radians * ticksPerRadian).toInt()
80162
if (abs(targetPositionTicks - motor.currentPosition) > 1) {
81163
motor.targetPosition = targetPositionTicks
82164
motor.mode = DcMotor.RunMode.RUN_TO_POSITION
@@ -86,4 +168,12 @@ class Spindexer(
86168
motor.mode = DcMotor.RunMode.RUN_WITHOUT_ENCODER
87169
}
88170
}
89-
}
171+
172+
fun moveToNextOpenIntake(): Boolean {
173+
artifacts.indexOfFirst { it == null }.takeIf { it != -1 }?.let {
174+
motorState = intakePositions[it]
175+
return true
176+
}
177+
return false
178+
}
179+
}

0 commit comments

Comments
 (0)