-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathBaseOpMode.kt
More file actions
115 lines (96 loc) · 3.47 KB
/
BaseOpMode.kt
File metadata and controls
115 lines (96 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package pioneer.opmodes
import com.acmerobotics.dashboard.telemetry.TelemetryPacket
import com.acmerobotics.dashboard.FtcDashboard
import com.qualcomm.robotcore.eventloop.opmode.OpMode
import com.qualcomm.robotcore.eventloop.opmode.TeleOp
import pioneer.Bot
import pioneer.hardware.MecanumBase
import pioneer.localization.localizers.Pinpoint
import pioneer.helpers.Chrono
import pioneer.helpers.FileLogger
import pioneer.general.Period
import pioneer.general.AllianceColor
import pioneer.helpers.OpModeDataTransfer
// Base OpMode class to be extended by all user-defined OpModes
abstract class BaseOpMode(
private val period: Period = Period.NONE,
private val allianceColor: AllianceColor = AllianceColor.NONE
) : OpMode() {
// Bot instance
protected lateinit var bot: Bot
// Telemetry packet for dashboard
protected var telemetryPacket = TelemetryPacket()
// Dashboard instance
private val dashboard =
FtcDashboard.getInstance()
// Tracker and getter for dt
protected val chrono = Chrono()
protected val dt: Double
get() = chrono.dt
val elapsedTime: Double
get() = getRuntime()
final override fun init() {
// Auto-load bot in TELEOP period
if (period == Period.TELEOP) {
OpModeDataTransfer.loadOrNull()?.let { omdt ->
// Reinitialize bot from saved object
omdt.bot?.let { savedBot ->
bot = savedBot
// bot.initAll() // Re-initialize hardware (TODO: needs testing)
}
}
}
// If bot wasn't loaded from OMDT, call user init
if (!::bot.isInitialized) {
onInit() // Call user-defined init method
if (!::bot.isInitialized) {
throw IllegalStateException("Bot not initialized. Please set 'bot' in onInit().")
}
bot.initAll() // Initialize bot hardware
} else {
// Bot was loaded, but still call onInit for any additional setup
onInit()
}
updateTelemetry()
}
final override fun loop() {
// Update bot systems
bot.updateAll(dt)
// Call user-defined loop logic
onLoop()
// Update path follower
if (bot.has<Pinpoint>() && bot.has<MecanumBase>()) {
bot.follower.update(dt)
telemetry.addLine("Updated follower")
}
// Automatically handle telemetry updates
updateTelemetry()
}
final override fun stop() {
bot.mecanumBase?.stop() // Ensure motors are stopped
FileLogger.flush() // Flush any logged data
onStop() // Call user-defined stop method
// Auto-save data in AUTO period, clear in TELEOP
when (period) {
Period.AUTO -> {
val omdt = OpModeDataTransfer.OMDT(
bot = bot,
)
OpModeDataTransfer.save(omdt)
}
Period.TELEOP -> {
OpModeDataTransfer.clear()
}
else -> { /* No data transfer for NONE */ }
}
}
private fun updateTelemetry() {
telemetry.update()
dashboard.sendTelemetryPacket(telemetryPacket)
telemetryPacket = TelemetryPacket() // Reset packet for next loop
}
// These functions are meant to be overridden in subclasses
protected open fun onInit() {}
protected open fun onLoop() {}
protected open fun onStop() {}
}