class Robot(TimedRobot):
    def robotInit(self):
        # Right Motors
        self.RightMotor1 = WPI_TalonFX(1)
        self.RightSensor1 = SensorCollection(self.RightMotor1)
        self.RightMotor2 = WPI_TalonFX(2)
        self.RightMotor3 = WPI_TalonFX(3)
        self.rightDriveMotors = SpeedControllerGroup(self.RightMotor1,
                                                     self.RightMotor2,
                                                     self.RightMotor3)
        # Left Motors
        self.LeftMotor1 = WPI_TalonFX(4)
        self.LeftMotor2 = WPI_TalonFX(5)
        self.LeftMotor3 = WPI_TalonFX(6)
        self.leftDriveMotors = SpeedControllerGroup(self.LeftMotor1,
                                                    self.LeftMotor2,
                                                    self.LeftMotor3)
        
        # self.drive = DifferentialDrive(self.leftDriveMotors,
        #                               self.rightDriveMotors)

        self.testEncoder = Encoder(1, 2, 3, Encoder.EncodingType.k4X)

        self.dashboard = NetworkTables.getTable("SmartDashboard")

    def disabledInit(self):
        pass

    def autonomousInit(self):
        pass

    def teleopInit(self):
        pass

    def testInit(self):
        pass

    def robotPeriodic(self):
        self.dashboard.putNumber("Encoder", self.RightSensor1.getQuadratureVelocity()/2048*60)

    def disabledPeriodic(self):
        pass

    def autonomousPeriodic(self):
        speed = self.testEncoder.get() / 1028
        self.leftDriveMotors.set(speed)
        self.rightDriveMotors.set(speed)

    def teleopPeriodic(self):
        pass

    def testPeriodic(self):
        pass
示例#2
0
class Indexer():
    def __init__(self, operator: OperatorControl):
        self.operator = operator
        self.motor = WPI_VictorSPX(7)
        self.encoder = Encoder(0, 1, False, Encoder.EncodingType.k4X)
        self.encoder.setIndexSource(2)
        self.limit = DigitalInput(4)
        self.dashboard = NetworkTables.getTable("SmartDashboard")

        self.totalValues = 2048  # * self.encoder.getEncodingScale() - 1
        self.targetValue = 10
        self.realValue = 0
        self.allowedError = 10
        self.hole = 4
        self.holeOffset = 36 - 15
        self.maxspeed = .25
        self.minspeed = .1
        self.speedmult = 1/300
        self.speed = .1

    def update(self):
        self.realValue = self.encoder.get()

        offset = (self.targetValue - self.realValue) % self.totalValues - (self.totalValues / 2)

        self.speed = clamp(abs(offset) * self.speedmult, self.minspeed, self.maxspeed)
        self.dashboard.putString("Indexer", "{} offset".format(offset))

        if (offset > self.allowedError):
            self.motor.set(ControlMode.PercentOutput, -self.speed)
        elif (offset < -self.allowedError):
            self.motor.set(ControlMode.PercentOutput, self.speed)
        else:
            self.motor.set(ControlMode.PercentOutput, 0)

        if (abs(offset) < 15):
            if (self.operator.getIndexUp()):
                self.hole = (self.hole + 1) % 5
            elif (self.operator.getIndexDown()):
                self.hole = (self.hole + 4) % 5
            self.setRotation(self.hole * 72 + self.holeOffset)

    def getRotation(self) -> float:
        return self.realValue / self.totalValues * 360

    def setRotation(self, degrees):
        self.targetValue = clamp(degrees/360*self.totalValues,
                                 0, self.totalValues)
示例#3
0
class Turret(Subsystem):
    def __init__(self, robot):
        Subsystem.__init__(self, 'Turret')

        self.robot = robot
        self.tEncoder = Encoder(4, 5, False, Encoder.EncodingType.k4X)
        motors = {}

        self.map = self.robot.botMap
        self.tmotors = motors

        for name in self.map.motorMap.motors:
            motors[name] = robot.Creator.createMotor(
                self.map.motorMap.motors[name])

        for name in self.tmotors:
            self.tmotors[name].setInverted(
                self.map.motorMap.motors[name]['inverted'])
            self.tmotors[name].setNeutralMode(ctre.NeutralMode.Coast)

        self.kP = 0.05
        self.kI = 0.000
        self.kD = 0.002

        self.turretPID = PID(self.kP, self.kI, self.kD)

        self.turretPID.limitVal(0.3)

        self.setPow = 0

    def set(self, pw):
        self.tmotors['turret'].set(ctre.ControlMode.PercentOutput, pw)

    def setPower(self, pow):
        self.setPow = pow

    def getEnc(self):
        return self.tEncoder.get()

    def periodic(self):
        if self.robot.Limelight.isExisting():
            self.set(0)  # self.turretPID.outVal(self.robot.Limelight.getX()))
        else:
            self.set(self.setPow)
示例#4
0
class Flywheel(Subsystem):
    def __init__(self, robot):
        Subsystem.__init__(self, 'Flywheel')

        self.CurPos = 0
        self.PasPos = 0

        self.robot = robot
        self.Fenc = Encoder(6, 7, False, Encoder.EncodingType.k4X)
        self.map = self.robot.botMap
        motor = {}
        piston = {}

        for name in self.robot.botMap.motorMap.motors:
            motor[name] = self.robot.Creator.createMotor(
                self.robot.botMap.motorMap.motors[name])

        for name in self.robot.botMap.PneumaticMap.pistons:
            piston[name] = self.robot.Creator.createPistons(
                self.robot.botMap.PneumaticMap.pistons[name])

        self.fmotor = motor
        self.fpiston = piston

        for name in self.fmotor:
            self.fmotor[name].setInverted(
                self.robot.botMap.motorMap.motors[name]['inverted'])
            self.fmotor[name].setNeutralMode(ctre.NeutralMode.Coast)
            if self.map.motorMap.motors[name]['CurLimit'] is True:
                self.fmotor[name].configStatorCurrentLimit(
                    self.robot.Creator.createCurrentConfig(
                        self.robot.botMap.currentConfig['Fly']), 40)

        self.kP = 0.008
        self.kI = 0.00002
        self.kD = 0.00018
        self.kF = 0.0  # tune me when testing

        self.flywheelPID = PID(self.kP, self.kI, self.kD, self.kF)

        self.flywheelPID.MaxIn(680)
        self.flywheelPID.MaxOut(1)
        self.flywheelPID.limitVal(0.95)  # Limit PID output power to 50%

        self.feetToRPS = 51.111

    def log(self):
        wpilib.SmartDashboard.putNumber('Flywheel Enc', self.Fenc.get())
        wpilib.SmartDashboard.putNumber('Flywheel Vel',
                                        self.getVelocity(self.Fenc.get()))

    def init(self):
        self.Fenc.reset()

    def set(self, pow):
        self.fmotor['RFly'].set(ctre.ControlMode.PercentOutput, pow)
        self.fmotor['LFly'].set(ctre.ControlMode.PercentOutput, pow)

    def setVelocityPID(self, rps):
        self.flywheelPID.setPoint(rps)
        if rps == 0:
            pow = 0
        else:
            pow = self.flywheelPID.outVel(self.getVelocity(self.get()))
        return pow

    def get(self):
        return self.Fenc.get()

    def getVelocity(self, input):
        self.CurPos = -(input / 1025) * (2 * math.pi)
        vel = (self.CurPos - self.PasPos) / 0.02
        self.PasPos = self.CurPos
        return vel
class Arm(Subsystem):
    def __init__(self, robot):
        super().__init__("Arm")
        self.robot = robot

        self.peakCurrentLimit = 30
        self.PeaKDuration = 50
        self.continuousLimit = 15

        motor = {}

        for name in self.robot.RobotMap.motorMap.motors:
            motor[name] = self.robot.Creator.createMotor(self.robot.RobotMap.motorMap.motors[name])

        self.motors = motor

        for name in self.motors:
            self.motors[name].setInverted(self.robot.RobotMap.motorMap.motors[name]['inverted'])
            # drive current limit
            self.motors[name].configPeakCurrentLimit(self.peakCurrentLimit, 10)
            self.motors[name].configPeakCurrentDuration(self.PeaKDuration, 10)
            self.motors[name].configContinuousCurrentLimit(self.continuousLimit, 10)
            self.motors[name].enableCurrentLimit(True)

        self.AEnc = Encoder(4, 5, False, Encoder.EncodingType.k4X)
        self.Zero = DigitalInput(6)

        self.kp = 0.00035
        self.ki = 0.00000000001
        self.kd = 0.0000001

        self.ArmPID = PID(self.kp, self.ki, self.kd)

    def log(self):
        wpilib.SmartDashboard.putNumber('armEnc', self.getHeight())
        wpilib.SmartDashboard.putNumber('Zero', self.getZeroPos())

    """
    Get Functions
    """

    def getHeight(self):
        # get encoder values
        return self.AEnc.get()

    def getZeroPos(self):
        # get zero position of arm
        return self.Zero.get()

    """
    set functions
    """
    def set(self, power):
        self.motors['RTArm'].set(ctre.ControlMode.PercentOutput, power)
        self.motors['LTArm'].set(ctre.ControlMode.PercentOutput, power)

    def stop(self):
        self.set(0)

    def resetHeight(self):
        self.AEnc.reset()
示例#6
0
class Drive(Subsystem):
    distPID = 0
    anglePID = 0

    prevDist = [0, 0]

    maxSpeed = 0.85

    yaw = 0
    pitch = 0
    roll = 0

    leftVal = 0
    rightVal = 0

    leftConv = 6 / 12 * math.pi / 256
    rightConv = -6 / 12 * math.pi / 256

    def __init__(self, robot):
        super().__init__('Drive')

        SmartDashboard.putNumber("DriveStraight_P", 0.075)
        SmartDashboard.putNumber("DriveStraight_I", 0.0)
        SmartDashboard.putNumber("DriveStraight_D", 0.42)
        # OLD GAINS 0.075, 0, 0.42

        SmartDashboard.putNumber("DriveAngle_P", 0.009)
        SmartDashboard.putNumber("DriveAngle_I", 0.0)
        SmartDashboard.putNumber("DriveAngle_D", 0.025)

        SmartDashboard.putNumber("DriveStraightAngle_P", 0.025)
        SmartDashboard.putNumber("DriveStraightAngle_I", 0.0)
        SmartDashboard.putNumber("DriveStraightAngle_D", 0.01)

        self.driveStyle = "Tank"
        SmartDashboard.putString("DriveStyle", self.driveStyle)
        #SmartDashboard.putData("Mode", self.mode)

        self.robot = robot
        self.lime = self.robot.limelight
        self.nominalPID = 0.15
        self.nominalPIDAngle = 0.22  # 0.11 - v2

        self.preferences = Preferences.getInstance()
        timeout = 0

        TalonLeft = Talon(map.driveLeft1)
        TalonRight = Talon(map.driveRight1)

        leftInverted = True
        rightInverted = False

        TalonLeft.setInverted(leftInverted)
        TalonRight.setInverted(rightInverted)

        VictorLeft1 = Victor(map.driveLeft2)
        VictorLeft2 = Victor(map.driveLeft3)
        VictorLeft1.follow(TalonLeft)
        VictorLeft2.follow(TalonLeft)

        VictorRight1 = Victor(map.driveRight2)
        VictorRight2 = Victor(map.driveRight3)
        VictorRight1.follow(TalonRight)
        VictorRight2.follow(TalonRight)

        for motor in [VictorLeft1, VictorLeft2]:
            motor.clearStickyFaults(timeout)
            motor.setSafetyEnabled(False)
            #motor.setExpiration(2 * self.robot.period)
            motor.setInverted(leftInverted)

        for motor in [VictorRight1, VictorRight2]:
            motor.clearStickyFaults(timeout)
            motor.setSafetyEnabled(False)
            #motor.setExpiration(2 * self.robot.period)
            motor.setInverted(rightInverted)

        for motor in [TalonLeft, TalonRight]:
            motor.setSafetyEnabled(False)
            #motor.setExpiration(2 * self.robot.period)
            motor.clearStickyFaults(timeout)  #Clears sticky faults

            motor.configContinuousCurrentLimit(40, timeout)  #15 Amps per motor
            motor.configPeakCurrentLimit(
                70, timeout)  #20 Amps during Peak Duration
            motor.configPeakCurrentDuration(
                300, timeout)  #Peak Current for max 100 ms
            motor.enableCurrentLimit(True)

            motor.configVoltageCompSaturation(12,
                                              timeout)  #Sets saturation value
            motor.enableVoltageCompensation(
                True)  #Compensates for lower voltages

            motor.configOpenLoopRamp(0.2,
                                     timeout)  #number of seconds from 0 to 1

        self.left = TalonLeft
        self.right = TalonRight

        self.navx = navx.AHRS.create_spi()

        self.leftEncoder = Encoder(map.leftEncoder[0], map.leftEncoder[1])
        self.leftEncoder.setDistancePerPulse(self.leftConv)
        self.leftEncoder.setSamplesToAverage(10)

        self.rightEncoder = Encoder(map.rightEncoder[0], map.rightEncoder[1])
        self.rightEncoder.setDistancePerPulse(self.rightConv)
        self.rightEncoder.setSamplesToAverage(10)

        self.zero()

        #PID for Drive
        self.TolDist = 0.1  #feet
        [kP, kI, kD, kF] = [0.027, 0.00, 0.20, 0.00]
        if wpilib.RobotBase.isSimulation():
            [kP, kI, kD, kF] = [0.25, 0.00, 1.00, 0.00]
        distController = PIDController(kP,
                                       kI,
                                       kD,
                                       kF,
                                       source=self.__getDistance__,
                                       output=self.__setDistance__)
        distController.setInputRange(0, 50)  #feet
        distController.setOutputRange(-0.6, 0.6)
        distController.setAbsoluteTolerance(self.TolDist)
        distController.setContinuous(False)
        self.distController = distController
        self.distController.disable()
        '''PID for Angle'''
        self.TolAngle = 2  #degrees
        [kP, kI, kD, kF] = [0.025, 0.00, 0.01, 0.00]
        if RobotBase.isSimulation():
            [kP, kI, kD, kF] = [0.005, 0.0, 0.01, 0.00]
        angleController = PIDController(kP,
                                        kI,
                                        kD,
                                        kF,
                                        source=self.__getAngle__,
                                        output=self.__setAngle__)
        angleController.setInputRange(-180, 180)  #degrees
        angleController.setOutputRange(-0.5, 0.5)
        angleController.setAbsoluteTolerance(self.TolAngle)
        angleController.setContinuous(True)
        self.angleController = angleController
        self.angleController.disable()

        self.k = 1
        self.sensitivity = 1

        SmartDashboard.putNumber("K Value", self.k)
        SmartDashboard.putNumber("sensitivity", self.sensitivity)

        self.prevLeft = 0
        self.prevRight = 0

    def setGains(self, p, i, d, f):
        self.distController.setPID(p, i, d, f)

    def setGainsAngle(self, p, i, d, f):
        self.angleController.setPID(p, i, d, f)

    def periodic(self):
        self.updateSensors()

    def __getDistance__(self):
        return self.getAvgDistance()

    def __setDistance__(self, output):
        self.distPID = output

    def __getAngle__(self):
        return self.getAngle()

    def __setAngle__(self, output):
        self.anglePID = output

    def setMode(self, mode, name=None, distance=0, angle=0):
        self.distPID = 0
        self.anglePID = 0

        if (mode == "Angle"):
            self.angleController.setSetpoint(angle)
            self.distController.disable()
            self.angleController.enable()
        elif (mode == "Combined"):
            self.distController.setSetpoint(distance)
            self.angleController.setSetpoint(angle)
            self.distController.enable()
            self.angleController.enable()
            self.prevLeft = 0
            self.prevRight = 0
        elif (mode == "Direct"):
            self.distController.disable()
            self.angleController.disable()
        self.mode = mode

    def setAngle(self, angle):
        self.setMode("Angle", angle=angle)

    def setCombined(self, distance, angle):
        self.setMode("Combined", distance=distance, angle=angle)

    def setDirect(self):
        self.setMode("Direct")

    def sign(self, num):
        if (num > 0): return 1
        if (num == 0): return 0
        return -1

    def tankDrive(self, left=0, right=0):
        if (self.mode == "Angle"):
            nom = self.nominalPIDAngle
            if self.anglePID < 0:
                nom = -nom
            left = self.getMaximum(self.anglePID, nom)
            right = self.getMaximum(-self.anglePID, -nom)
        elif (self.mode == "Combined"):
            nom = self.nominalPID
            if self.distPID < 0:
                nom = -nom

            left = self.getMaximum(self.distPID + self.anglePID, nom)
            right = self.getMaximum(self.distPID - self.anglePID, nom)

            left = self.getMinimum3(left, 0.30, self.prevLeft + 0.01)
            right = self.getMinimum3(right, 0.30, self.prevRight + 0.01)

            self.prevLeft = left
            self.prevRight = right

        elif (self.mode == "Direct"):
            [left, right] = [left, right]
        else:
            [left, right] = [0, 0]

        left = min(abs(left), self.maxSpeed) * self.sign(left)
        right = min(abs(right), self.maxSpeed) * self.sign(right)
        self.__tankDrive__(left, right)

    def __tankDrive__(self, left, right):
        deadband = 0.1

        if (abs(left) > abs(deadband)): self.left.set(left)
        else: self.left.set(0)

        if (abs(right) > abs(deadband)): self.right.set(right)
        else: self.right.set(0)

    def getOutputCurrent(self):
        return (self.right.getOutputCurrent() +
                self.left.getOutputCurrent()) * 3

    def updateSensors(self):
        if self.navx == None:
            self.yaw = 0
            self.pitch = 0
            self.roll = 0
        else:
            self.yaw = self.navx.getYaw()
            self.pitch = self.navx.getPitch()
            self.roll = self.navx.getRoll()

        self.leftVal = self.leftEncoder.get()
        self.rightVal = self.rightEncoder.get()

    def getAngle(self):
        angle = self.yaw
        if RobotBase.isSimulation(): return -angle
        if self.robot.teleop:
            if angle == 0:
                angle = 0
            elif angle < 0:
                angle = angle + 180
            else:
                angle = angle - 180
        return angle

    def getRoll(self):
        return self.roll

    def getPitch(self):
        return self.pitch

    def getRaw(self):
        return [self.leftVal, self.rightVal]

    def getDistance(self):
        return [self.leftVal * self.leftConv, self.rightVal * self.rightConv]

    def getAvgDistance(self):
        return (self.getDistance()[0] + self.getDistance()[1]) / 2

    def getVelocity(self):
        dist = self.getDistance()
        velocity = [
            self.robot.frequency * (dist[0] - self.prevDist[0]),
            self.robot.frequency * (dist[1] - self.prevDist[1])
        ]
        self.prevDist = dist
        return velocity

    def getAvgVelocity(self):
        return (self.getVelocity()[0] + self.getVelocity()[1]) / 2

    def getAvgAbsVelocity(self):
        return (abs(self.getVelocity()[0]) + abs(self.getVelocity()[1])) / 2

    def zeroEncoders(self):
        self.leftEncoder.reset()
        self.rightEncoder.reset()
        simComms.resetEncoders()

    def zeroNavx(self):
        if self.navx == None: pass
        else: self.navx.zeroYaw()

    def zero(self):
        self.zeroEncoders()
        self.zeroNavx()

    def disable(self):
        self.__tankDrive__(0, 0)

    def initDefaultCommand(self):
        self.setDefaultCommand(SetSpeedDT(timeout=300))

    def dashboardInit(self):
        SmartDashboard.putData("Turn Angle", TurnAngle())
        SmartDashboard.putData("Drive Combined", DriveStraight())

    def getMaximum(self, number, comparison):
        if math.fabs(number) > math.fabs(comparison): return number
        else: return comparison

    def getMinimum3(self, val1, val2, val3):
        return self.getMinimum(self.getMinimum(val1, val2), val3)

    def getMinimum(self, number, comparison):
        if math.fabs(number) < math.fabs(comparison): return number
        else: return comparison

    def isCargoPassed(self):
        if self.getAvgDistance() > 16.1: return True
        else: return False

    def dashboardPeriodic(self):
        #commented out some values. DON'T DELETE THESE VALUES
        SmartDashboard.putNumber("Left Counts", self.leftEncoder.get())
        SmartDashboard.putNumber("Left Distance",
                                 self.leftEncoder.getDistance())
        SmartDashboard.putNumber("Right Counts", self.rightEncoder.get())
        #SmartDashboard.putNumber("Right Distance", self.rightEncoder.getDistance())
        SmartDashboard.putNumber("DT_DistanceAvg", self.getAvgDistance())
        SmartDashboard.putNumber("DT_DistanceLeft", self.getDistance()[0])
        SmartDashboard.putNumber("DT_DistanceRight", self.getDistance()[1])
        SmartDashboard.putNumber("DT_Angle", self.getAngle())
        #SmartDashboard.putNumber("DT_PowerLeft", self.left.get())
        #SmartDashboard.putNumber("DT_PowerRight", self.right.get())
        #SmartDashboard.putNumber("DT_VelocityLeft", self.getVelocity()[0])
        #SmartDashboard.putNumber("DT_VelocityRight", self.getVelocity()[1])
        #SmartDashboard.putNumber("DT_CounLeft", self.getRaw()[0])
        #SmartDashboard.putNumber("DT_CountRight", self.getRaw()[1])
        #SmartDashboard.putNumber("angle correction", self.anglePID)
        #SmartDashboard.putNumber("DriveAmps",self.getOutputCurrent())

        #self.mode = SmartDashboard.getData("Mode", "Tank")
        self.k = SmartDashboard.getNumber("K Value", 1)
        self.sensitivity = SmartDashboard.getNumber("sensitivity", 1)
        self.driveStyle = SmartDashboard.getString("DriveStyle", "Tank")
class Drive(Subsystem):
    def __init__(self, robot):
        Subsystem.__init__(self, 'Drive')

        self.robot = robot

        motors = {}
        pistons = {}

        self.map = self.robot.botMap
        self.rEnc = Encoder(0, 1, False, Encoder.EncodingType.k4X)
        self.lEnc = Encoder(2, 3, False, Encoder.EncodingType.k4X)
        self.Gyro = ADXRS450_Gyro()

        for name in self.map.motorMap.motors:
            motors[name] = robot.Creator.createMotor(
                self.map.motorMap.motors[name])

        for name in self.robot.botMap.PneumaticMap.pistons:
            if name == 'Shifter':
                pistons[name] = self.robot.Creator.createPistons(
                    self.robot.botMap.PneumaticMap.pistons[name])

        self.dMotors = motors
        self.dPistons = pistons

        for name in self.dMotors:
            self.dMotors[name].setInverted(
                self.robot.botMap.motorMap.motors[name]['inverted'])
            self.dMotors[name].setNeutralMode(ctre.NeutralMode.Coast)
            if self.map.motorMap.motors[name]['CurLimit'] is True:
                self.dMotors[name].configStatorCurrentLimit(
                    self.robot.Creator.createCurrentConfig(
                        self.robot.botMap.currentConfig['Drive']), 40)

        self.kP = 0.0
        self.kI = 0.0
        self.kD = 0.0

        self.DrivePID = PID(self.kP, self.kI, self.kD)

    def log(self):
        wpilib.SmartDashboard.putNumber('RDrive Enc', self.rEnc.get())
        wpilib.SmartDashboard.putNumber('LDrive Enc', self.lEnc.get())
        wpilib.SmartDashboard.putNumber('Gyro Val', self.Gyro.getAngle())

    def set(self, rgt, lft):
        self.dMotors['RFDrive'].set(ctre.ControlMode.PercentOutput, rgt)
        self.dMotors['LFDrive'].set(ctre.ControlMode.PercentOutput, lft)

    def stop(self):
        self.set(0, 0)

    def resetGryo(self):
        self.Gyro.reset()

    def resetEnc(self):
        self.rEnc.reset()
        self.lEnc.reset()

    def setSpeed(self, mode):
        self.dPistons['shifter'].set(mode)

    def getAngle(self):
        x = self.Gyro.getAngle()
        if x > 360 or x < -360:
            self.Gyro.reset()
        return x

    def getEnc(self):
        l = self.lEnc.get()
        r = self.rEnc.get()

        return (l + r) / 2
class Drive(Subsystem):
    def __init__(self, robot):
        super().__init__("Drive")
        self.robot = robot

        self.peakCurrentLimit = 25
        self.PeaKDuration = 50
        self.continuousLimit = 15

        self.map = robot.RobotMap

        # drive motor, sensors, and pistons
        motor = {}
        pistons = {}

        # create all drive motors, Sensors, and pistons
        for name in self.map.motorMap.motors:
            motor[name] = robot.Creator.createMotor(self.map.motorMap.motors[name])

        for name in self.map.PneumaticMap.pistons:
            if name == 'Shifter':
                pistons[name] = robot.Creator.createPistons(self.map.PneumaticMap.pistons[name])

        self.REnc = Encoder(0, 1, True, Encoder.EncodingType.k4X)
        self.LEnc = Encoder(2, 3, False, Encoder.EncodingType.k4X)

        self.Gyro = ADXRS450_Gyro()

        # make motors, Sensors, and pistons local to subsystem
        self.Dmotor = motor
        self.Dpiston = pistons

        for name in self.Dmotor:
            self.Dmotor[name].setInverted(self.robot.RobotMap.motorMap.motors[name]['inverted'])

            # drive current limit
            self.Dmotor[name].configPeakCurrentLimit(self.peakCurrentLimit, 10)
            self.Dmotor[name].configPeakCurrentDuration(self.PeaKDuration, 10)
            self.Dmotor[name].configContinuousCurrentLimit(self.continuousLimit, 10)
            self.Dmotor[name].enableCurrentLimit(True)

        self.KtorqueMode = DoubleSolenoid.Value.kReverse
        self.KspeedMode = DoubleSolenoid.Value.kForward

        if wpilib.RobotBase.isSimulation():
            self.kp = 0.001
            self.ki = 0.00001
            self.kd = 0.000000001
        else:
            self.kp = 0.001
            self.ki = 0.00001
            self.kd = 0.000000001

        self.DrivePID = PID(self.kp, self.ki, self.kd)

    def Log(self):
        wpilib.SmartDashboard.putNumber('rgt enc', self.REnc.get())
        wpilib.SmartDashboard.putNumber('lft enc', self.LEnc.get())

        wpilib.SmartDashboard.putNumber('drive rgt frt', self.Dmotor['RFDrive'].getOutputCurrent())
        wpilib.SmartDashboard.putNumber('drive lft frt', self.Dmotor['LFDrive'].getOutputCurrent())

    """
    Get Functions
    """
    def getEncoderVal(self):
        # get encoder values from both sides
        rgt = self.REnc.get()
        lft = self.LEnc.get()
        avg = (rgt+lft)/2   # find average
        return avg

    def getGyroVal(self):
        # get gyro values
        x = self.Gyro.getAngle()
        # reset gyro if it passes 360 deg
        if x > 360 or x < -360:
            self.resetGyro()
        return self.Gyro.getAngle()

    """
    Set Functions
    """
    def set(self, rgt, lft):
        self.Dmotor['RFDrive'].set(ctre.ControlMode.PercentOutput, rgt)
        self.Dmotor['LFDrive'].set(ctre.ControlMode.PercentOutput, lft)

        # uncomment when all motors are master
        """self.Dmotor['RMDrive'].set(self.Dmotor['RMDrive'].ControlMode.PercentOutput, rgt)
        self.Dmotor['RBDrive'].set(self.Dmotor['RBDrive'].ControlMode.PercentOutput, rgt)"""

        """self.Dmotor['LMDrive'].set(self.Dmotor['LMDrive'].ControlMode.PercentOutput, lft)
        self.Dmotor['LBDrive'].set(self.Dmotor['LBDrive'].ControlMode.PercentOutput, lft)"""

    def stop(self):
        self.set(0, 0)

    def ShiftGear(self, GearMode):
        self.Dpiston['Shifter'].set(GearMode)

    def resetEnc(self):
        self.REnc.reset()
        self.LEnc.reset()

    def resetGyro(self):
        self.Gyro.reset()