Exemplo n.º 1
0
class DriveTrain(Subsystem):
    """
    This subsystem controls the drivetrain for the robot.
    """
    def __init__(self):
        super().__init__()
        self.logger = logging.getLogger(self.getName())

        # Configure motors
        self.leftMasterTalon = WPI_TalonSRX(RobotMap.LEFT_MASTER_TALON)
        self.leftSlaveTalon = WPI_TalonSRX(RobotMap.LEFT_SLAVE_TALON)
        self.rightMasterTalon = WPI_TalonSRX(RobotMap.RIGHT_MASTER_TALON)
        self.rightSlaveTalon = WPI_TalonSRX(RobotMap.RIGHT_SLAVE_TALON)

        self.leftSlaveTalon.follow(self.leftMasterTalon)
        self.rightSlaveTalon.follow(self.rightMasterTalon)

        self.leftMasterTalon.configSelectedFeedbackSensor(
            FeedbackDevice.CTRE_MagEncoder_Relative, 0, Constants.TIMEOUT_MS)
        self.rightMasterTalon.configSelectedFeedbackSensor(
            FeedbackDevice.CTRE_MagEncoder_Relative, 0, Constants.TIMEOUT_MS)
        self.leftMasterTalon.setInverted(True)
        self.leftSlaveTalon.setInverted(True)

        self.configureDrivePID()

        # Configure shift solenoid
        self.shiftSolenoid = DoubleSolenoid(RobotMap.SHIFT_IN_SOLENOID,
                                            RobotMap.SHIFT_OUT_SOLENOID)

    def configureDrivePID(self):
        # Slot 0 = Distance PID
        # Slot 1 = Velocity PID
        self.leftMasterTalon.config_kF(0, Constants.LEFT_DISTANCE_F,
                                       Constants.TIMEOUT_MS)
        self.leftMasterTalon.config_kP(0, Constants.LEFT_DISTANCE_P,
                                       Constants.TIMEOUT_MS)
        self.leftMasterTalon.config_kI(0, Constants.LEFT_DISTANCE_I,
                                       Constants.TIMEOUT_MS)
        self.leftMasterTalon.config_kD(0, Constants.LEFT_DISTANCE_D,
                                       Constants.TIMEOUT_MS)

        self.leftMasterTalon.config_kF(1, Constants.LEFT_VELOCITY_F,
                                       Constants.TIMEOUT_MS)
        self.leftMasterTalon.config_kP(1, Constants.LEFT_VELOCITY_P,
                                       Constants.TIMEOUT_MS)
        self.leftMasterTalon.config_kI(1, Constants.LEFT_VELOCITY_I,
                                       Constants.TIMEOUT_MS)
        self.leftMasterTalon.config_kD(1, Constants.LEFT_VELOCITY_D,
                                       Constants.TIMEOUT_MS)

        self.rightMasterTalon.config_kF(0, Constants.RIGHT_DISTANCE_F,
                                        Constants.TIMEOUT_MS)
        self.rightMasterTalon.config_kP(0, Constants.RIGHT_DISTANCE_P,
                                        Constants.TIMEOUT_MS)
        self.rightMasterTalon.config_kI(0, Constants.RIGHT_DISTANCE_I,
                                        Constants.TIMEOUT_MS)
        self.rightMasterTalon.config_kD(0, Constants.RIGHT_DISTANCE_D,
                                        Constants.TIMEOUT_MS)

        self.rightMasterTalon.config_kF(1, Constants.RIGHT_VELOCITY_F,
                                        Constants.TIMEOUT_MS)
        self.rightMasterTalon.config_kP(1, Constants.RIGHT_VELOCITY_P,
                                        Constants.TIMEOUT_MS)
        self.rightMasterTalon.config_kI(1, Constants.RIGHT_VELOCITY_I,
                                        Constants.TIMEOUT_MS)
        self.rightMasterTalon.config_kD(1, Constants.RIGHT_VELOCITY_D,
                                        Constants.TIMEOUT_MS)

        self.leftMasterTalon.configMotionAcceleration(6385)
        self.rightMasterTalon.configMotionAcceleration(6385)

        self.leftMasterTalon.configMotionCruiseVelocity(6385)
        self.rightMasterTalon.configMotionCruiseVelocity(6385)

    def initDefaultCommand(self):
        self.setDefaultCommand(JoystickDrive())

    def zeroEncoders(self):
        self.leftMasterTalon.setSelectedSensorPosition(0)
        self.rightMasterTalon.setSelectedSensorPosition(0)

    def set(self, type, leftMagnitude, rightMagnitude):
        assert (isinstance(type, ControlMode))

        if type == ControlMode.PercentOutput:
            self.leftMasterTalon.set(ControlMode.PercentOutput, leftMagnitude)
            self.rightMasterTalon.set(ControlMode.PercentOutput,
                                      rightMagnitude)
        elif type == ControlMode.Velocity:
            self.leftMasterTalon.set(ControlMode.Velocity, leftMagnitude)
            self.rightMasterTalon.set(ControlMode.Velocity, rightMagnitude)
        elif type == ControlMode.MotionMagic:
            self.leftMasterTalon.set(ControlMode.MotionMagic, leftMagnitude)
            self.rightMasterTalon.set(ControlMode.MotionMagic, rightMagnitude)

    def setPIDSlot(self, slot):
        self.leftMasterTalon.selectProfileSlot(slot, 0)
        self.rightMasterTalon.selectProfileSlot(slot, 0)

    def getPositions(self):
        return self.leftMasterTalon.getSelectedSensorPosition(
        ), self.rightMasterTalon.getSelectedSensorPosition()

    def getVelocities(self):
        return self.leftMasterTalon.getSelectedSensorVelocity(
        ), self.rightMasterTalon.getSelectedSensorVelocity()

    def customArcadeDrive(self, xSpeed, zRotation, squareInputs):
        deadband = 0.1
        xSpeed, zRotation = self.limit(xSpeed, zRotation)

        xSpeed, zRotation = self.applyDeadband(deadband, xSpeed, zRotation)

        if squareInputs:
            xSpeed = math.copysign(xSpeed * xSpeed, xSpeed)
            zRotation = math.copysign(zRotation * zRotation, zRotation)

        maxInput = math.copysign(max(abs(xSpeed), abs(zRotation)), xSpeed)

        if xSpeed >= 0:
            if zRotation >= 0:
                leftMotorOutput = maxInput
                rightMotorOutput = xSpeed - zRotation
            else:
                leftMotorOutput = xSpeed + zRotation
                rightMotorOutput = maxInput
        else:
            if zRotation >= 0:
                leftMotorOutput = xSpeed + zRotation
                rightMotorOutput = maxInput
            else:
                leftMotorOutput = maxInput
                rightMotorOutput = xSpeed - zRotation

        # Fine tune control
        if abs(xSpeed) > abs(zRotation):
            self.leftMasterTalon.set(ControlMode.PercentOutput,
                                     self.limit(leftMotorOutput) * 0.55)
            self.rightMasterTalon.set(ControlMode.PercentOutput,
                                      self.limit(rightMotorOutput) * -0.55)
        else:
            self.leftMasterTalon.set(ControlMode.PercentOutput,
                                     self.limit(leftMotorOutput) * 0.55)
            self.rightMasterTalon.set(ControlMode.PercentOutput,
                                      self.limit(rightMotorOutput) * -0.55)

    def limit(self, *args):
        return_list = []
        for arg in args:
            if arg > 1.0:
                return_list.append(1.0)
            elif arg < -1.0:
                return_list.append(1.0)
            else:
                return_list.append(arg)

        return return_list[0] if len(return_list) == 1 else return_list

    def applyDeadband(self, deadband, *args):
        return_list = []
        for arg in args:
            if abs(arg) < deadband:
                return_list.append(0.0)
            else:
                return_list.append(arg)

        return return_list[0] if len(return_list) == 1 else return_list
Exemplo n.º 2
0
class Robot(magicbot.MagicRobot):
    # Automations
    # TODO: bad name
    seek_target: seek_target.SeekTarget

    # Controllers
    # recorder: recorder.Recorder

    # Components
    follower: trajectory_follower.TrajectoryFollower

    drive: drive.Drive
    lift: lift.Lift
    hatch_manipulator: hatch_manipulator.HatchManipulator
    cargo_manipulator: cargo_manipulator.CargoManipulator
    climber: climber.Climber

    ENCODER_PULSE_PER_REV = 1024
    WHEEL_DIAMETER = 0.5
    """
    manual_lift_control = tunable(True)
    stabilize = tunable(False)
    stabilizer_threshold = tunable(30)
    stabilizer_aggression = tunable(5)
    """
    """
    time = tunable(0)
    voltage = tunable(0)
    yaw = tunable(0)
    """
    def createObjects(self):
        """
        Initialize robot components.
        """
        # For using teleop in autonomous
        self.robot = self

        # Joysticks
        self.joystick_left = wpilib.Joystick(0)
        self.joystick_right = wpilib.Joystick(1)
        self.joystick_alt = wpilib.Joystick(2)

        # Buttons
        self.button_strafe_left = JoystickButton(self.joystick_left, 4)
        self.button_strafe_right = JoystickButton(self.joystick_left, 5)
        self.button_strafe_forward = JoystickButton(self.joystick_left, 3)
        self.button_strafe_backward = JoystickButton(self.joystick_left, 2)
        self.button_slow_rotation = JoystickButton(self.joystick_right, 4)

        self.button_lift_actuate = ButtonDebouncer(self.joystick_alt, 2)
        self.button_manual_lift_control = ButtonDebouncer(self.joystick_alt, 6)
        self.button_hatch_kick = JoystickButton(self.joystick_alt, 1)
        self.button_cargo_push = JoystickButton(self.joystick_alt, 5)
        self.button_cargo_pull = JoystickButton(self.joystick_alt, 3)
        self.button_cargo_pull_lightly = JoystickButton(self.joystick_alt, 4)
        self.button_climb_front = JoystickButton(self.joystick_right, 3)
        self.button_climb_back = JoystickButton(self.joystick_right, 2)

        self.button_target = JoystickButton(self.joystick_right, 8)

        # Drive motor controllers
        # ID SCHEME:
        #   10^1: 1 = left, 2 = right
        #   10^0: 0 = front, 5 = rear
        self.lf_motor = WPI_TalonSRX(10)
        self.lr_motor = WPI_TalonSRX(15)
        self.rf_motor = WPI_TalonSRX(20)
        self.rr_motor = WPI_TalonSRX(25)

        encoder_constant = ((1 / self.ENCODER_PULSE_PER_REV) *
                            self.WHEEL_DIAMETER * math.pi)

        self.r_encoder = wpilib.Encoder(0, 1)
        self.r_encoder.setDistancePerPulse(encoder_constant)
        self.l_encoder = wpilib.Encoder(2, 3)
        self.l_encoder.setDistancePerPulse(encoder_constant)
        self.l_encoder.setReverseDirection(True)

        # Drivetrain
        self.train = wpilib.drive.MecanumDrive(self.lf_motor, self.lr_motor,
                                               self.rf_motor, self.rr_motor)

        # Functional motors
        self.lift_motor = WPI_TalonSRX(40)
        self.lift_motor.setSensorPhase(True)
        self.lift_switch = wpilib.DigitalInput(4)
        self.lift_solenoid = wpilib.DoubleSolenoid(2, 3)
        self.hatch_solenoid = wpilib.DoubleSolenoid(0, 1)
        self.left_cargo_intake_motor = WPI_TalonSRX(35)
        # TODO: electricians soldered one motor in reverse.
        # self.left_cargo_intake_motor.setInverted(True)
        self.right_cargo_intake_motor = WPI_TalonSRX(30)
        """
        self.cargo_intake_motors = wpilib.SpeedControllerGroup(self.left_cargo_intake_motor,
                                                               self.right_cargo_intake_motor)
        """
        self.right_cargo_intake_motor.follow(self.left_cargo_intake_motor)
        self.front_climb_piston = wpilib.DoubleSolenoid(4, 5)
        self.back_climb_piston = wpilib.DoubleSolenoid(6, 7)

        # Tank Drivetrain
        """
        self.tank_train = wpilib.drive.DifferentialDrive(wpilib.SpeedControllerGroup(self.lf_motor, self.lr_motor),
                                                         wpilib.SpeedControllerGroup(self.rf_motor, self.rr_motor))
        """

        # Load trajectories
        self.generated_trajectories = load_trajectories()

        # NavX
        self.navx = navx.AHRS.create_spi()
        self.navx.reset()

        # Utility
        # self.ds = wpilib.DriverStation.getInstance()
        # self.timer = wpilib.Timer()
        self.pdp = wpilib.PowerDistributionPanel(0)
        self.compressor = wpilib.Compressor()

        # Camera server
        wpilib.CameraServer.launch('camera/camera.py:main')
        wpilib.LiveWindow.disableAllTelemetry()

    def robotPeriodic(self):
        """
        Executed periodically regardless of mode.
        """
        # self.time = int(self.timer.getMatchTime())
        # self.voltage = self.pdp.getVoltage()
        # self.yaw = self.navx.getAngle() % 360
        pass

    def autonomous(self):
        """
        Prepare for and start autonomous mode.
        """
        # Call autonomous
        super().autonomous()

    def disabledInit(self):
        """
        Executed once right away when robot is disabled.
        """
        # Reset Gyro to 0
        self.navx.reset()

    def disabledPeriodic(self):
        """
        Executed periodically while robot is disabled.
        Useful for testing.
        """
        pass

    def teleopInit(self):
        """
        Executed when teleoperated mode begins.
        """
        self.lift.zero = self.lift_motor.getSelectedSensorPosition()
        self.lift.current_position = 5000000
        self.compressor.start()

    def teleopPeriodic(self):
        """
        Executed periodically while robot is in teleoperated mode.
        """
        # Read from joysticks and move drivetrain accordingly
        self.drive.move(x=-self.joystick_left.getY(),
                        y=self.joystick_left.getX(),
                        rot=self.joystick_right.getX(),
                        real=True,
                        slow_rot=self.button_slow_rotation.get())
        """
        self.drive.strafe(self.button_strafe_left.get(),
                          self.button_strafe_right.get(),
                          self.button_strafe_forward.get(),
                          self.button_strafe_backward.get())
        """
        """
        for button in range(7, 12 + 1):
            if self.joystick_alt.getRawButton(button):
                self.lift.target(button)
        """
        # if self.manual_lift_control:
        self.lift.move(-self.joystick_alt.getY())
        """
        else:
            # self.lift.correct(-self.joystick_alt.getY())
            # self.lift.approach()
            pass
        """
        """
        if self.button_manual_lift_control:
            # self.manual_lift_control = not self.manual_lift_control
            pass
        """

        if self.button_hatch_kick.get():
            self.hatch_manipulator.extend()
        else:
            self.hatch_manipulator.retract()

        if self.button_target.get():
            self.seek_target.seek()

        if self.button_lift_actuate.get():
            self.lift.actuate()

        if self.button_cargo_push.get():
            self.cargo_manipulator.push()
        elif self.button_cargo_pull.get():
            self.cargo_manipulator.pull()
        elif self.button_cargo_pull_lightly.get():
            self.cargo_manipulator.pull_lightly()

        if self.button_climb_front.get():
            self.climber.extend_front()
        else:
            self.climber.retract_front()
        if self.button_climb_back.get():
            self.climber.extend_back()
        else:
            self.climber.retract_back()
        """