Skip to content

Commit

Permalink
Bug fixes and state management (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
SUPERCILEX authored Jan 21, 2018
1 parent 3afeb0b commit d9c87c5
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 28 deletions.
2 changes: 1 addition & 1 deletion core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ check.dependsOn 'ktlint'

dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
compile 'com.android.support:support-annotations:27.0.2'
implementation 'com.android.support:support-annotations:27.0.2'
compile 'edu.wpi.first.wpilibj:wpilibj-java:2018.1.1'
compileOnly 'openrio.mirror.third.ctre:CTRE-phoenix-java:5.1.2.1'
compileOnly 'jaci.pathfinder:Pathfinder-Java:1.8'
Expand Down
58 changes: 31 additions & 27 deletions core/src/main/kotlin/org/sertain/Robot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ public interface RobotLifecycle {
*/
public fun onStart() = Unit

/**
* Indicates that the robot is being enabled in the teleoperated mode. This method will be
* called before the robot becomes enabled in teleoperated mode.
*/
public fun onTeleopStart() = Unit

/**
* Indicates that the robot is being enabled in the autonomous mode. This method will be called
* before the robot becomes enabled in autonomous mode.
*/
public fun onAutoStart() = Unit

/**
* Indicates that the robot is being enabled in the teleoperated mode. This method will be
* called before the robot becomes enabled in teleoperated mode.
*/
public fun onTeleopStart() = Unit

/**
* Runs periodically (default = every 20ms) while the robot is turned on. It need not be enabled
* for this method to be called.
Expand Down Expand Up @@ -73,19 +73,14 @@ public interface RobotLifecycle {
*/
public fun onAutoStop() = Unit

/**
* Indicates that the disabled state has just terminated. This method will be called after the
* disabled state has terminated. This method should be equivalent to [onStart].
*/
public fun onDisabledStop() = Unit

/**
* Indicates that the robot has become disabled. This method will be called upon entering the
* disabled state.
*/
public fun onStop() = Unit

companion object {
internal var state = Robot.State.DISABLED
@VisibleForTesting
internal val listeners = mutableSetOf<RobotLifecycle>()

Expand All @@ -95,6 +90,13 @@ public interface RobotLifecycle {
* @param lifecycle the lifecycle object to receive callbacks
*/
public fun addListener(lifecycle: RobotLifecycle) {
lifecycle.onCreate()
when (state) {
Robot.State.TELEOP -> lifecycle.onTeleopStart()
Robot.State.AUTO -> lifecycle.onAutoStart()
Robot.State.DISABLED -> Unit
}

synchronized(listeners) { listeners += lifecycle }
}

Expand All @@ -112,9 +114,9 @@ public interface RobotLifecycle {

override fun onStart() = notify { onStart() }

override fun onTeleopStart() = notify { onTeleopStart() }
override fun onTeleopStart() = notify(Robot.State.TELEOP) { onTeleopStart() }

override fun onAutoStart() = notify { onAutoStart() }
override fun onAutoStart() = notify(Robot.State.AUTO) { onAutoStart() }

override fun execute() = notify { execute() }

Expand All @@ -128,11 +130,13 @@ public interface RobotLifecycle {

override fun onAutoStop() = notify { onAutoStop() }

override fun onDisabledStop() = notify { onDisabledStop() }

override fun onStop() = notify { onStop() }
override fun onStop() = notify(Robot.State.DISABLED) { onStop() }

private inline fun notify(block: RobotLifecycle.() -> Unit) {
private inline fun notify(
state: Robot.State? = null,
block: RobotLifecycle.() -> Unit
) {
state?.let { RobotLifecycle.state = it }
synchronized(listeners) { for (listener in listeners) listener.block() }
}
}
Expand All @@ -143,13 +147,13 @@ public interface RobotLifecycle {
* Base robot class which must be used for [RobotLifecycle] callbacks to work.
*/
public abstract class Robot : IterativeRobot(), RobotLifecycle {
private var mode = Mode.DISABLED
private var mode = State.DISABLED
set(value) {
if (value != field) {
when (field) {
Mode.TELEOP -> LifecycleDistributor.onTeleopStop()
Mode.AUTO -> LifecycleDistributor.onAutoStop()
Mode.DISABLED -> LifecycleDistributor.onDisabledStop()
State.TELEOP -> LifecycleDistributor.onTeleopStop()
State.AUTO -> LifecycleDistributor.onAutoStop()
State.DISABLED -> Unit
}
field = value
}
Expand All @@ -168,29 +172,29 @@ public abstract class Robot : IterativeRobot(), RobotLifecycle {
}

override fun disabledInit() {
mode = Mode.DISABLED
mode = State.DISABLED
LifecycleDistributor.onStop()
}

override fun disabledPeriodic() = LifecycleDistributor.executeDisabled()

override fun autonomousInit() {
mode = Mode.AUTO
mode = State.AUTO
LifecycleDistributor.onStart()
LifecycleDistributor.onAutoStart()
}

override fun autonomousPeriodic() = LifecycleDistributor.executeAuto()

override fun teleopInit() {
mode = Mode.TELEOP
mode = State.TELEOP
LifecycleDistributor.onStart()
LifecycleDistributor.onTeleopStart()
}

override fun teleopPeriodic() = LifecycleDistributor.executeTeleop()

private enum class Mode {
AUTO, TELEOP, DISABLED
internal enum class State {
DISABLED, AUTO, TELEOP
}
}
4 changes: 4 additions & 0 deletions core/src/main/kotlin/org/sertain/command/Subsystem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ private typealias WpiLibSubsystem = edu.wpi.first.wpilibj.command.Subsystem
* @see edu.wpi.first.wpilibj.command.Subsystem
*/
public abstract class Subsystem : WpiLibSubsystem(), RobotLifecycle {
abstract val defaultCommand: Command

override fun initSendable(builder: SendableBuilder?) {
super.initSendable(builder)
RobotLifecycle.addListener(this)
}

override fun initDefaultCommand() = setDefaultCommand(defaultCommand.mirror)
}

0 comments on commit d9c87c5

Please sign in to comment.