Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failure manager #10

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d235382
Create FailureManager object
eckshn Dec 3, 2020
c43c402
failure manager add methods and enums
eckshn Dec 15, 2020
f8259fe
created a flag map for the failures.
vmad18 Dec 17, 2020
5e410bc
Merge branch 'master' into failureManager
aidangoettsch Dec 17, 2020
a45add9
flesh out failuremanager, add test routine and associated commands
aidangoettsch Dec 17, 2020
aece5d4
add commands for failure manager
aidangoettsch Dec 18, 2020
30bc148
validate command complete
eckshn Dec 22, 2020
b37382b
Factory reset
vmad18 Jan 14, 2021
87a486c
Create FailureManager object
eckshn Dec 3, 2020
8f0ff47
failure manager add methods and enums
eckshn Dec 15, 2020
cac8d43
created a flag map for the failures.
vmad18 Dec 17, 2020
2f2d1db
flesh out failuremanager, add test routine and associated commands
aidangoettsch Dec 17, 2020
4d4b1ee
add commands for failure manager
aidangoettsch Dec 18, 2020
ef5914a
validate command complete
eckshn Dec 22, 2020
0de7556
Merge branch 'failureManager' of github.com:team4099/InfiniteRecharge…
aidangoettsch Jan 17, 2021
4d55db6
Merge branch 'master' into failureManager
vmad18 Jan 19, 2021
2657128
Added Test Command
vmad18 Jan 19, 2021
ca27705
Fixed Logic with TestCommand
vmad18 Jan 19, 2021
a0a7f8d
Merge branch 'failureManager' of github.com:team4099/InfiniteRecharge…
aidangoettsch Jan 20, 2021
163c45b
actually use logDashboard
aidangoettsch Jan 20, 2021
e7fd657
add event for failure manager log
aidangoettsch Jan 20, 2021
35f386c
added climber failure to failures.
vmad18 Jan 20, 2021
1975db1
Merge branch 'failureManager' of https://github.com/team4099/Infinite…
vmad18 Jan 20, 2021
b988657
added new errorflag
vmad18 Jan 21, 2021
71cb6e7
added pneumatic sensor code
vmad18 Jan 21, 2021
f9bccbe
added failure checks in move and unlock climber commands
RehanKabir Jan 21, 2021
743cc86
Add comment for commands & fix UnlockClimber
eckshn Jan 27, 2021
80d28bc
Finish Climber command descriptions
eckshn Jan 27, 2021
4893e92
Finish subsystem comments & progress on FailureManager
eckshn Jan 28, 2021
cdd22c2
Finish FailureManager comments
eckshn Jan 29, 2021
8d0b077
Remove constructor comment & fix others
eckshn Feb 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions src/main/kotlin/com/team4099/robot2021/Robot.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.team4099.robot2021

import com.team4099.lib.logging.Logger
import com.team4099.robot2021.commands.MoveClimber
import com.team4099.lib.units.base.inches
import com.team4099.lib.units.base.seconds
import com.team4099.robot2021.commands.climber.MoveClimber
import com.team4099.robot2021.commands.climber.LockClimber
import com.team4099.robot2021.commands.climber.UnlockClimber
import com.team4099.robot2021.commands.failures.ValidateCommand
import com.team4099.robot2021.commands.feeder.FeederBeamBreak
import com.team4099.robot2021.commands.feeder.FeederCommand
import com.team4099.robot2021.config.Constants
Expand All @@ -13,16 +16,23 @@ import com.team4099.robot2021.commands.intake.IntakeCommand
import com.team4099.robot2021.subsystems.Intake
import edu.wpi.first.wpilibj.DigitalInput
import edu.wpi.first.wpilibj.RobotController
import com.team4099.robot2021.config.ControlBoard
import com.team4099.robot2021.loops.FailureManager
import com.team4099.robot2021.subsystems.Climber
import edu.wpi.first.wpilibj.AnalogInput
import edu.wpi.first.wpilibj.TimedRobot
import edu.wpi.first.wpilibj2.command.CommandScheduler
import edu.wpi.first.wpilibj2.command.InstantCommand
import edu.wpi.first.wpilibj2.command.SequentialCommandGroup
import kotlin.math.pow

object Robot : TimedRobot() {
val robotName: Constants.Tuning.RobotName

private val pressureSensor = AnalogInput(Constants.PressureSensor.ANALOG_PIN)

private val pneumaticsPressure: Double
get() = 250*(pressureSensor.voltage/Constants.PressureSensor.ANALOG_VOLTAGE) - 25

init {
val robotId = Constants.Tuning.ROBOT_ID_PINS.withIndex().map { (i, pin) ->
if (DigitalInput(pin).get()) 0 else 2.0.pow(i).toInt()
Expand All @@ -35,15 +45,26 @@ object Robot : TimedRobot() {

// Link between feeder Trigger and Command
Feeder.defaultCommand = FeederCommand(Feeder.FeederState.NEUTRAL)
ControlBoard.runFeederIn.whileActiveOnce(FeederCommand(Feeder.FeederState.FORWARD_FLOOR));
ControlBoard.runFeederOut.whileActiveOnce(FeederCommand(Feeder.FeederState.BACKWARD));
ControlBoard.runFeederIn.whileActiveOnce(FeederCommand(Feeder.FeederState.FORWARD_FLOOR))
ControlBoard.runFeederOut.whileActiveOnce(FeederCommand(Feeder.FeederState.BACKWARD))

Intake.defaultCommand = IntakeCommand(Constants.Intake.IntakeState.DEFAULT, Constants.Intake.ArmPosition.IN)
ControlBoard.runIntakeIn.whileActiveContinuous(IntakeCommand(Constants.Intake.IntakeState.IN, Constants.Intake.ArmPosition.OUT).alongWith(FeederBeamBreak()));
ControlBoard.runIntakeOut.whileActiveContinuous(IntakeCommand(Constants.Intake.IntakeState.OUT, Constants.Intake.ArmPosition.OUT).alongWith(FeederCommand(Feeder.FeederState.BACKWARD)));
ControlBoard.runIntakeIn.whileActiveContinuous(IntakeCommand(Constants.Intake.IntakeState.IN, Constants.Intake.ArmPosition.OUT).alongWith(FeederBeamBreak()))
ControlBoard.runIntakeOut.whileActiveContinuous(IntakeCommand(Constants.Intake.IntakeState.OUT, Constants.Intake.ArmPosition.OUT).alongWith(FeederCommand(Feeder.FeederState.BACKWARD)))

FailureManager.addFailure(FailureManager.Failures.PRESSURE_LEAK,false) { Constants.PressureSensor.PSI_THRESHOLD > pneumaticsPressure }
Logger.addSource("Pressure","Pressure Value"){ pneumaticsPressure }
}

private val autonomousCommand = InstantCommand()
private val testCommand = SequentialCommandGroup(
MoveClimber(Constants.ClimberPosition.HIGH),
(ValidateCommand(({1.inches>(Constants.ClimberPosition.HIGH.length - Climber.climberRArmSensor.position).absoluteValue && (1.inches)>(Constants.ClimberPosition.HIGH.length - Climber.climberLArmSensor.position).absoluteValue}),5.seconds,FailureManager.Failures.CLIMBER_FAILED_POS)),
MoveClimber(Constants.ClimberPosition.LOW), (ValidateCommand(({1.inches<(Constants.ClimberPosition.LOW.length - Climber.climberRArmSensor.position).absoluteValue && (1.inches)<(Constants.ClimberPosition.LOW.length - Climber.climberLArmSensor.position).absoluteValue}),5.seconds,FailureManager.Failures.CLIMBER_FAILED_POS)),
IntakeCommand(Constants.Intake.IntakeState.IN, Constants.Intake.ArmPosition.OUT),
FeederBeamBreak(),
IntakeCommand(Constants.Intake.IntakeState.OUT, Constants.Intake.ArmPosition.OUT),
FeederCommand(Feeder.FeederState.BACKWARD))

override fun autonomousInit() {
autonomousCommand.schedule()
Expand All @@ -58,6 +79,7 @@ object Robot : TimedRobot() {

override fun robotPeriodic() {
CommandScheduler.getInstance().run()
FailureManager.checkFailures()
Logger.saveLogs()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import com.team4099.lib.logging.Logger
import com.team4099.robot2021.subsystems.Climber
import edu.wpi.first.wpilibj2.command.CommandBase

/**
* Lock climber
*
* @property Climber.brakeApplied Prevents motors from powering / moving the climber
*/
class LockClimber : CommandBase() {
init {
addRequirements(Climber)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.team4099.robot2021.commands
package com.team4099.robot2021.commands.climber

import com.team4099.lib.logging.Logger
import com.team4099.robot2021.commands.climber.UnlockClimber
import com.team4099.robot2021.config.Constants
import com.team4099.robot2021.config.ControlBoard
import com.team4099.robot2021.subsystems.Climber
import edu.wpi.first.wpilibj2.command.CommandBase

/**
* Move climber
*
* @property pos Direct motor to rotate based on position
*/
class MoveClimber(val pos: Constants.ClimberPosition): CommandBase() {
init {
addRequirements(Climber)
Expand All @@ -17,10 +21,9 @@ class MoveClimber(val pos: Constants.ClimberPosition): CommandBase() {
}

override fun execute() {
if (Climber.brakeApplied) {
UnlockClimber()
if (!Climber.brakeApplied) {
Climber.setPosition(pos)
}
Climber.setPosition(pos)
}
}
//check if climber is locked, if locked don't move
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ package com.team4099.robot2021.commands.climber
import com.team4099.lib.hal.Clock
import com.team4099.lib.logging.Logger
import com.team4099.robot2021.config.Constants
import com.team4099.robot2021.loops.FailureManager
import com.team4099.robot2021.subsystems.Climber
import edu.wpi.first.wpilibj2.command.CommandBase

/**
* Unlock climber
*
* @property FailureManager.Failures.PRESSURE_LEAK State based if leak detected in pneumatics
*/
class UnlockClimber : CommandBase() {
init {
addRequirements(Climber)
Expand All @@ -14,7 +20,12 @@ class UnlockClimber : CommandBase() {
override fun initialize() {
initTime = Clock.fpgaTime
Climber.brakeApplied = false
Logger.addEvent("Climber", "Climber Unlocked")
if (FailureManager.errorFlags[FailureManager.Failures.PRESSURE_LEAK] == true){
Climber.brakeApplied = true
Logger.addEvent("Climber", "Climber Unlock Failed")
}else {
Logger.addEvent("Climber", "Climber Unlocked")
}
}

override fun isFinished(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.team4099.robot2021.commands.failures
import edu.wpi.first.wpilibj2.command.CommandBase
import com.team4099.robot2021.loops.FailureManager;

/**
* Failure reset command
*
* @property FailureManager.reset Sets all errors back to normal
*/
class FailureResetCommand : CommandBase() {
override fun initialize(){
FailureManager.reset()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.team4099.robot2021.commands.failures

import com.team4099.lib.hal.Clock
import com.team4099.lib.units.base.Time
import com.team4099.lib.units.base.seconds
import com.team4099.robot2021.loops.FailureManager
import edu.wpi.first.wpilibj2.command.CommandBase
/**
* Validate command
*
* @property condition Runs if boolean is true
* @property timeout When timeout passes a threshold it is registered as a failure
* @property failure The failure that the condition is tied to
*/
class ValidateCommand(val condition : () -> Boolean, val timeout : Time, val failure : FailureManager.Failures) : CommandBase() {
private var startTime : Time = 0.seconds
override fun initialize() {
startTime = Clock.fpgaTime

}

override fun execute() {
val elapseTime : Time = Clock.fpgaTime - startTime
if(elapseTime > timeout) {
FailureManager.errorFlags[failure] = true
}
}

override fun isFinished(): Boolean {
return condition()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ import com.team4099.lib.logging.Logger
import com.team4099.robot2021.subsystems.Feeder
import edu.wpi.first.wpilibj2.command.CommandBase

/**
* Feeder beam break
*
* @property Feeder.topBeamBroken
* @property Feeder.bottomBeamBroken
*/

class FeederBeamBreak(): CommandBase(){
init{
addRequirements(Feeder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import com.team4099.robot2021.subsystems.Feeder
import com.team4099.robot2021.subsystems.Feeder.feederState
import edu.wpi.first.wpilibj2.command.CommandBase


/**
* Feeder command
*
* @property dir Sets the direction the motors rotate
*/
class FeederCommand(var dir: Feeder.FeederState): CommandBase(){
init{
addRequirements(Feeder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import com.team4099.robot2021.config.Constants
import com.team4099.robot2021.subsystems.Intake
import edu.wpi.first.wpilibj2.command.CommandBase

/**
* Intake command
*
* @property intakeState Sets the velocity of the wheel
* @property armState Sets the position of the pneumatic arms
* @constructor Create empty Intake command
*/
class IntakeCommand(var intakeState: Constants.Intake.IntakeState, var armState: Constants.Intake.ArmPosition): CommandBase() {

init {
Expand Down
6 changes: 6 additions & 0 deletions src/main/kotlin/com/team4099/robot2021/config/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ object Constants {
const val EPSILON = 1E-9
}

object PressureSensor{
const val ANALOG_PIN = 0;
const val ANALOG_VOLTAGE = 5.00;
const val PSI_THRESHOLD = 10.00;
}

object Tuning {
const val TUNING_TOGGLE_PIN = 0
val ROBOT_ID_PINS = 1..2
Expand Down
128 changes: 128 additions & 0 deletions src/main/kotlin/com/team4099/robot2021/loops/FailureManager.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package com.team4099.robot2021.loops

import com.team4099.lib.logging.Logger
import com.team4099.robot2021.Robot
import edu.wpi.first.wpilibj.Sendable
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder

/**
* Failure manager
*
* @constructor Create empty Failure manager
*/
object FailureManager: Sendable {
/**
* Failures
*
* @param failures Map of Error Flags
* @param log String representing the output of failures
*/
private val failures = mutableListOf<FailureSource>()
private var log = ""

/**
* Error flags
*/
val errorFlags = mutableMapOf(
Failures.PRESSURE_LEAK to false,
Failures.INTAKE_SPEC_VIOLATION to false,
Failures.CLIMBER_FAILED_POS to false
)

/**
* Severity
*
* @property Severity The levels of bad of the failure
* @constructor Create empty Severity
*/
enum class Severity {
WARNING,
ERROR
}

/**
* Failures
*
* @property severity Enum above giving classification of the severity level of the failure
* @property description Gives details about the given failure
* @constructor Create empty Failures
*/
enum class Failures (val severity : Severity, val description: String) {
PRESSURE_LEAK(Severity.ERROR, "Pressure Leak, pressure under"),
INTAKE_SPEC_VIOLATION(Severity.WARNING, "intake bad"),
CLIMBER_FAILED_POS(Severity.ERROR, "Climber position is wrong");
}

/**
* Add failure
*
* @param failType Name implies
* @param latching If true failure can't be removed
* @param condition Given the condition will determine if there is a failure
* @receiver
*/
fun addFailure(failType: Failures, latching: Boolean = false, condition: () -> Boolean) {
failures.add(FailureSource(failType, latching, condition, false))
}

/**
* Add test failure (test mode)
*
* @param failType Name implies
* @param condition Given the condition will determine if there is a failure
* @receiver
*/
fun addTestFailure(failType: Failures, condition: () -> Boolean) {
failures.add(FailureSource(failType, true, condition, true))
}

/**
* Check failures
*
* Goes through each failure in the list and checks if it's true and if so logs it
*/
fun checkFailures() {
failures.forEach { failure ->
if (!failure.testOnly || Robot.isTest) {
if (!failure.latching) {
if (failure.condition() && errorFlags[failure.failType] == false) logDashboard(failure.failType.description)
errorFlags[failure.failType] = failure.condition()
} else if (failure.condition()) {
if (errorFlags[failure.failType] == false) logDashboard(failure.failType.description)
errorFlags[failure.failType] = true
}
}
}
}

/**
* Reset
*
* Method that resets each failure to false
*/
fun reset(){
failures.forEach{failure -> errorFlags[failure.failType] = false}
log = ""
}

/**
* Log dashboard
*
* @param string Description of failure
*/
fun logDashboard(string: String) {
Logger.addEvent("FailureManager", string)
log += "\n$string"
log.trim()
}

/**
* Init sendable
*
* @param builder
*/
override fun initSendable(builder: SendableBuilder?) {
builder?.addStringProperty("Failures", { log }) {}
}
}
data class FailureSource(val failType: FailureManager.Failures, val latching: Boolean, val condition: () -> Boolean, val testOnly: Boolean)
Loading