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

Adding Vision to robot #53

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
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
23 changes: 23 additions & 0 deletions src/main/kotlin/org/team5499/frc2019/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,29 @@ public object Constants {
public var HOLD_POSITION by DashboardVar(170)
}

object Vision {
public var CAMERA_HEIGHT by DashboardVar(33.0)
public var CAMERA_VERTICAL_ANGLE by DashboardVar(0.0)
public var CAMERA_HORIZONTAL_ANGLE by DashboardVar(7.0)
public var HATCH_TARGET_HEIGHT by DashboardVar(29.0)
public var BALL_TARGET_HEIGHT by DashboardVar(36.0)

public var TARGET_DISTANCE by DashboardVar(24.0) // inches

public var ACCEPTABLE_ANGLE_ERROR by DashboardVar(3.0) // degrees(?)
public var ACCEPTABLE_DISTANCE_ERROR by DashboardVar(2.0) // inches (?)

public var ANGLE_KP by DashboardVar(1.0)
public var ANGLE_KI by DashboardVar(0.0)
public var ANGLE_KD by DashboardVar(0.1)
public var ANGLE_KF by DashboardVar(0.0)

public var DISTANCE_KP by DashboardVar(0.35)
public var DISTANCE_KI by DashboardVar(0.0)
public var DISTANCE_KD by DashboardVar(0.0)
public var DISTANCE_KF by DashboardVar(0.0)
}

object Auto {
fun initProps() {
println("init Auto")
Expand Down
19 changes: 17 additions & 2 deletions src/main/kotlin/org/team5499/frc2019/Robot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import org.team5499.frc2019.subsystems.Drivetrain
import org.team5499.frc2019.subsystems.Lift
import org.team5499.frc2019.subsystems.Intake
import org.team5499.frc2019.subsystems.Vision
import org.team5499.frc2019.subsystems.Vision.LEDState
import org.team5499.frc2019.subsystems.Vision.VisionMode
import org.team5499.frc2019.subsystems.HatchMech
import org.team5499.frc2019.controllers.SandstormController
import org.team5499.frc2019.controllers.TeleopController
Expand Down Expand Up @@ -174,6 +176,8 @@ class Robot : TimedRobot(Constants.ROBOT_UPDATE_PERIOD) {

override fun robotInit() {
Logger.warn("Robot initializing" as Any)
mVision.ledState = Vision.LEDState.OFF
mVision.visionMode = Vision.VisionMode.VISION
}

override fun robotPeriodic() {
Expand All @@ -196,11 +200,13 @@ class Robot : TimedRobot(Constants.ROBOT_UPDATE_PERIOD) {
override fun disabledInit() {
Logger.warn("Robot disabling" as Any)
mLift.zeroed = false
mVision.initialize()
mVision.ledState = Vision.LEDState.OFF
mVision.visionMode = Vision.VisionMode.VISION
mSubsystemsManager.resetAll()
}

override fun disabledPeriodic() {
}
override fun disabledPeriodic() {}

override fun autonomousInit() {
Logger.warn("Robot going autonomous" as Any)
Expand All @@ -224,4 +230,13 @@ class Robot : TimedRobot(Constants.ROBOT_UPDATE_PERIOD) {
mTeleopController.update()
mSubsystemsManager.updateAll()
}

override fun testInit() {
mVision.ledState = LEDState.ON
mVision.visionMode = VisionMode.VISION
}

override fun testPeriodic() {
println("distance to target ${mVision.distanceToTarget}")
}
}
14 changes: 10 additions & 4 deletions src/main/kotlin/org/team5499/frc2019/auto/Routines.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import org.team5499.frc2019.auto.actions.LiftAction
import org.team5499.frc2019.auto.actions.HatchMechAction
import org.team5499.frc2019.auto.actions.WaitForLiftZeroAction
import org.team5499.frc2019.auto.actions.CrossedXBoundaryAction
import org.team5499.frc2019.auto.actions.VisionGoalAction
import org.team5499.frc2019.auto.actions.VisionGoalAction.VisionGoal

import java.util.HashMap

Expand Down Expand Up @@ -182,13 +184,17 @@ public class Routines(paths: Paths, subsystems: SubsystemsManager) {
private fun createTuning() = Routine(
"Tuning",
Pose2d(Vector2(0, 0), Rotation2d.fromDegrees(0)),
PathAction(15.0, mPaths.tuning, mSubsystems.drivetrain)
PathAction(120.0, mPaths.tuning, mSubsystems.drivetrain)
)

private fun createTest() = Routine(
"Test",
Pose2d(Vector2(0, 0), Rotation2d.fromDegrees(0.0)),
DriveStraightAction(10.0, 12.0, mSubsystems.drivetrain)
"test",
Pose2d(Vector2(0, 0), Rotation2d.fromDegrees(0)),
WaitForLiftZeroAction(mSubsystems.lift),
LiftAction(LiftHeight.HATCH_LOW, mSubsystems.lift),
HatchMechAction(HatchMechPosition.HOLD, mSubsystems.hatchMech),
VisionGoalAction(120.0, VisionGoal.HATCH_TARGET, mSubsystems.vision, mSubsystems.drivetrain),
HatchMechAction(HatchMechPosition.DEPLOYED, mSubsystems.hatchMech)
)

private fun createNothing() = Routine(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package org.team5499.frc2019.auto.actions

import org.team5499.monkeyLib.auto.Action
import org.team5499.monkeyLib.math.pid.PIDF

import org.team5499.frc2019.subsystems.Vision
import org.team5499.frc2019.subsystems.Drivetrain
import org.team5499.frc2019.Constants

public class VisionGoalAction(
timeout: Double,
val goal: VisionGoal,
val vision: Vision,
val drivetrain: Drivetrain
) : Action(timeout) {

public enum class VisionGoal { HATCH_TARGET, BALL_TARGET }

private val mAnglePID: PIDF
private val mDistancePID: PIDF

init {
mAnglePID = PIDF(
Constants.Vision.ANGLE_KP,
Constants.Vision.ANGLE_KI,
Constants.Vision.ANGLE_KI,
Constants.Vision.ANGLE_KD,
false
)
mDistancePID = PIDF(
Constants.Vision.DISTANCE_KP,
Constants.Vision.DISTANCE_KI,
Constants.Vision.DISTANCE_KD,
Constants.Vision.DISTANCE_KF,
false
)
}

public override fun start() {

// reset pid for dashboard
mAnglePID.reset()
mDistancePID.reset()

mAnglePID.kP = Constants.Vision.ANGLE_KP
mAnglePID.kI = Constants.Vision.ANGLE_KI
mAnglePID.kD = Constants.Vision.ANGLE_KD
mAnglePID.kF = Constants.Vision.ANGLE_KF

mDistancePID.kP = Constants.Vision.DISTANCE_KP
mDistancePID.kI = Constants.Vision.DISTANCE_KI
mDistancePID.kD = Constants.Vision.DISTANCE_KD
mDistancePID.kF = Constants.Vision.DISTANCE_KF

mAnglePID.setpoint = -Constants.Vision.CAMERA_HORIZONTAL_ANGLE
mDistancePID.setpoint = Constants.Vision.TARGET_DISTANCE

// turn on leds
// vision.ledState = Vision.LEDState.ON
}

public override fun update() {

if (!vision.hasValidTarget) {
drivetrain.setVelocity(0.0, 0.0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe coast here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will check this.

} else {
mAnglePID.processVariable = -vision.targetXOffset
var steer = mAnglePID.calculate()

// mDistancePID.processVariable = when (goal) {
// VisionGoal.BALL_TARGET -> vision.distanceToBallTarget
// VisionGoal.HATCH_TARGET -> vision.distanceToHatchTarget
// }
mDistancePID.processVariable = -vision.distanceToTarget
val drive = mDistancePID.calculate()

val left = drive + steer
val right = drive - steer

drivetrain.setVelocity(left, right)
}
}

public override fun next(): Boolean {
return super.timedOut() || (
vision.distanceToTarget < Constants.Vision.TARGET_DISTANCE // &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work? I'm concerned that this condition wont ever be satisfied

// abs(mAnglePID.error) < Constants.Vision.ACCEPTABLE_ANGLE_ERROR &&
// abs(mDistancePID.error) < Constants.Vision.ACCEPTABLE_DISTANCE_ERROR
)
}

public override fun finish() {
drivetrain.setVelocity(0.0, 0.0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import org.team5499.monkeyLib.math.geometry.Rotation2d

import org.team5499.frc2019.subsystems.SubsystemsManager
import org.team5499.frc2019.auto.Routines
import org.team5499.frc2019.subsystems.Vision.LEDState
import org.team5499.frc2019.subsystems.Vision.VisionMode

import org.team5499.dashboard.StringChooser

Expand Down Expand Up @@ -48,6 +50,8 @@ public class AutoController(subsystems: SubsystemsManager, routines: Routines) :
currentRoutine = if (routine == null) mRoutines.baseline else routine
// currentRoutine = mRoutines.rocketRight
mSubsystems.drivetrain.brakeMode = true
mSubsystems.vision.ledState = LEDState.ON
mSubsystems.vision.visionMode = VisionMode.VISION
mSubsystems.drivetrain.heading = Rotation2d(currentRoutine.startPose.rotation)
mSubsystems.drivetrain.setPosition(currentRoutine.startPose.translation)
currentAction = currentRoutine.getCurrentAction()
Expand Down
100 changes: 89 additions & 11 deletions src/main/kotlin/org/team5499/frc2019/controllers/TeleopController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ import org.team5499.frc2019.subsystems.SubsystemsManager
import org.team5499.frc2019.input.ControlBoard
import org.team5499.frc2019.subsystems.Lift.LiftHeight
import org.team5499.frc2019.subsystems.HatchMech
import org.team5499.frc2019.subsystems.Vision.VisionMode
import org.team5499.frc2019.subsystems.Vision.LEDState

import org.team5499.frc2019.Constants

import org.team5499.monkeyLib.Controller
import org.team5499.monkeyLib.input.DriveHelper
import org.team5499.monkeyLib.math.pid.PIDF

@Suppress("LargeClass")
public class TeleopController(
subsystems: SubsystemsManager,
controlBoard: ControlBoard,
Expand All @@ -22,11 +27,15 @@ public class TeleopController(

private val mDriveHelper: DriveHelper

private val mDistancePID: PIDF
private val mAnglePID: PIDF

private var mLockHatchMech: Boolean
private var mLockElevator: Boolean
private var mLastLoopManualUsed: Boolean
private var mAutoAlign: Boolean

private var started = false
private var mStarted: Boolean

init {
mSubsystems = subsystems
Expand All @@ -35,26 +44,94 @@ public class TeleopController(
mLockHatchMech = false
mLockElevator = false
mLastLoopManualUsed = false
mStarted = false
mAutoAlign = false

mAnglePID = PIDF(
Constants.Vision.ANGLE_KP,
Constants.Vision.ANGLE_KI,
Constants.Vision.ANGLE_KI,
Constants.Vision.ANGLE_KD,
false
)
mDistancePID = PIDF(
Constants.Vision.DISTANCE_KP,
Constants.Vision.DISTANCE_KI,
Constants.Vision.DISTANCE_KD,
Constants.Vision.DISTANCE_KF,
false
)
}

public override fun start() {
if (!started) {
if (!mStarted) {
mSubsystems.drivetrain.brakeMode = false
mLockHatchMech = false
mLockElevator = false
started = true
mStarted = true
mSubsystems.vision.ledState = LEDState.OFF
mSubsystems.vision.visionMode = VisionMode.DRIVER

mAnglePID.reset()
mDistancePID.reset()

mAnglePID.kP = Constants.Vision.ANGLE_KP
mAnglePID.kI = Constants.Vision.ANGLE_KI
mAnglePID.kD = Constants.Vision.ANGLE_KD
mAnglePID.kF = Constants.Vision.ANGLE_KF

mDistancePID.kP = Constants.Vision.DISTANCE_KP
mDistancePID.kI = Constants.Vision.DISTANCE_KI
mDistancePID.kD = Constants.Vision.DISTANCE_KD
mDistancePID.kF = Constants.Vision.DISTANCE_KF
}
}

@Suppress("ComplexMethod")
public override fun update() {
val driveSignal = mDriveHelper.calculateOutput(
-mControlBoard.driverControls.getThrottle(),
mControlBoard.driverControls.getTurn(),
mControlBoard.driverControls.getQuickTurn(),
mControlBoard.driverControls.getCreep()
)
mSubsystems.drivetrain.setPercent(driveSignal.left, driveSignal.right)
val isAutoAlign = mControlBoard.driverControls.getAutoAlign()
if (!mAutoAlign && isAutoAlign) {
mAutoAlign = true
mDistancePID.reset()
mAnglePID.reset()
mDistancePID.setpoint = Constants.Vision.TARGET_DISTANCE
mAnglePID.setpoint = -Constants.Vision.CAMERA_HORIZONTAL_ANGLE
mSubsystems.vision.ledState = LEDState.ON
mSubsystems.vision.visionMode = VisionMode.VISION
} else if (mAutoAlign && !isAutoAlign) {
mAutoAlign = false
mSubsystems.vision.ledState = LEDState.OFF
mSubsystems.vision.visionMode = VisionMode.DRIVER
}

if (!mAutoAlign) {
// driver can control
val driveSignal = mDriveHelper.calculateOutput(
-mControlBoard.driverControls.getThrottle(),
mControlBoard.driverControls.getTurn(),
mControlBoard.driverControls.getQuickTurn(),
mControlBoard.driverControls.getCreep()
)
mSubsystems.drivetrain.setPercent(driveSignal.left, driveSignal.right)
} else {
// vision system can control
if (mSubsystems.vision.hasValidTarget) {
// mSubsystems.vision.ledState = LEDState.ON

mAnglePID.processVariable = -mSubsystems.vision.targetXOffset
mDistancePID.processVariable = -mSubsystems.vision.distanceToTarget

val drive = mDistancePID.calculate()
val steer = mAnglePID.calculate()
val left = drive + steer
val right = drive - steer
mSubsystems.drivetrain.setVelocity(left, right)
} else {
// if not target, stop and blink
mSubsystems.drivetrain.setVelocity(0.0, 0.0)
// mSubsystems.vision.ledState = LEDState.BLINK
}
}

if (mControlBoard.codriverControls.getExaust()) {
mSubsystems.intake.outtake()
Expand Down Expand Up @@ -135,6 +212,7 @@ public class TeleopController(
public override fun reset() {
mLockHatchMech = false
mLockElevator = false
started = false
mStarted = false
mAutoAlign = false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ public interface IDriverControls {

public fun getStow(): Boolean

public fun getAutoAlign(): Boolean
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add this function to the getState function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.


public fun getState(): String {
@Suppress("MaxLineLength")
return "${getThrottle()} : ${getTurn()} : ${getLeft()} : ${getRight()} : ${getQuickTurn()} : ${getCreep()} : ${getExitAuto()} : ${getStow()}"
return "${getThrottle()} : ${getTurn()} : ${getLeft()} : ${getRight()} : ${getQuickTurn()} : ${getCreep()} : ${getExitAuto()} : ${getStow()} : ${getAutoAlign()}"
}
}
2 changes: 2 additions & 0 deletions src/main/kotlin/org/team5499/frc2019/input/WheelDriver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ public class WheelDriver(wheel: Joystick, throttle: Joystick) : IDriverControls
public override fun getExitAuto() = mWheel.getRawButton(1) // paddle

public override fun getStow() = false // change this later

public override fun getAutoAlign() = false
}
3 changes: 3 additions & 0 deletions src/main/kotlin/org/team5499/frc2019/input/XboxDriver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,7 @@ public class XboxDriver(xbox: XboxController) : IDriverControls {
public override fun getExitAuto() = mXbox.getAButtonPressed()

public override fun getStow() = mXbox.getBButtonPressed()

@Suppress("MagicNumber")
public override fun getAutoAlign() = (mXbox.getTriggerAxis(Hand.kLeft) > 0.15)
}
Loading