Beispiel #1
0
    def update_outputs(self, l_enc: int, r_enc: int, angle: float):
        self.l_output = -self.left_follower.calculate(l_enc)
        self.r_output = self.right_follower.calculate(r_enc)

        if self.reverse:
            self.l_output = self.left_follower.calculate(-l_enc)
            self.r_output = -self.right_follower.calculate(-r_enc)
        if self.reverse:
            angle *= -1

        desired_heading = pathfinder.r2d(self.left_follower.getHeading())

        angle_diff = pathfinder.boundHalfDegrees(desired_heading - angle)
        angle_diff = angle_diff % 360
        if abs(angle_diff) > 180:
            if angle_diff > 0:
                angle_diff = angle_diff - 360
            else:
                angle_diff = angle_diff + 360

        turn = 0.8 * (1.0 / 80.0) * angle_diff
        if not self.reverse:
            self.l_output -= turn
            self.r_output -= turn
        else:
            self.l_output += turn
            self.r_output += turn
Beispiel #2
0
    def autonomousPeriodic(self):

        l = self.leftFollower.calculate(
            self.l_motor_master.getSelectedSensorPosition(0))
        r = self.rightFollower.calculate(
            self.r_motor_master.getSelectedSensorPosition(0))

        gyro_heading = (-self.navx.getAngle()
                        )  # Assuming the gyro is giving a value in degrees
        desired_heading = pf.r2d(
            self.leftFollower.getHeading())  # Should also be in degrees

        # This is a poor man's P controller
        angleDifference = pf.boundHalfDegrees(desired_heading - gyro_heading)
        turn = 5 * (-1.0 / 80.0) * angleDifference

        if self.timer.hasPeriodPassed(0.5):
            print("l: " + str(l) + ", r: " + str(r) + ", turn: " + str(turn))
            #print("current segment: " + str(self.leftFollower.getSegment().position))

        l = l + turn
        r = r - turn

        if self.leftFollower.isFinished() or self.rightFollower.isFinished():
            self.robot_drive.tankDrive(0, 0)
        else:
            # -1 is forward, so invert both values
            self.robot_drive.tankDrive(-l, -r)
Beispiel #3
0
 def execute(self):
     if self.enabled:
         angle_speed = self.config[
             "navx_p"] / 180 * pathfinder.boundHalfDegrees(
                 pathfinder.r2d(self.left.getHeading()) -
                 self.drive.getNavx())
         self.drive.setSpeeds(
             self.left.calculate(self.drive.getEncLeft()) +
             (angle_speed if angle_speed < 0 else 0),
             self.right.calculate(self.drive.getEncRight()) -
             (angle_speed if angle_speed > 0 else 0))
Beispiel #4
0
    def autonomousPeriodic(self):

        l = self.leftFollower.calculate(self.l_encoder.get())
        r = self.rightFollower.calculate(self.r_encoder.get())

        gyro_heading = (-self.gyro.getAngle()
                        )  # Assuming the gyro is giving a value in degrees
        desired_heading = pf.r2d(
            self.leftFollower.getHeading())  # Should also be in degrees

        # This is a poor man's P controller
        angleDifference = pf.boundHalfDegrees(desired_heading - gyro_heading)
        turn = 5 * (-1.0 / 80.0) * angleDifference

        l = l + turn
        r = r - turn

        # -1 is forward, so invert both values
        self.robot_drive.tankDrive(-l, -r)
Beispiel #5
0
    def charge(self, initial_call):
        left_speed = self.leftFollower.calculate(self.drive.leftDistance())
        right_speed = self.rightFollower.calculate(self.drive.rightDistance())

        gyro_heading = (-self.drive.gyro.getAngle()
                        )  # Assuming the gyro is giving a value in degrees
        desired_heading = pf.r2d(
            self.leftFollower.getHeading())  # Should also be in degrees

        # This is a poor man's P controller
        angleDifference = pf.boundHalfDegrees(desired_heading - gyro_heading)
        turn = 1.2 * (-1.0 / 80.0) * angleDifference

        left_speed += turn
        right_speed -= turn
        print(left_speed, right_speed)

        # -1 is forward, so invert both values
        self.drive.tank(left_speed, right_speed)
Beispiel #6
0
    def run(self):

        l = self.leftFollower.calculate(sself.sensors.getLeftDistance())
        r = self.rightFollower.calculate(self.sensors.getRightDistance())

        # REPLACE THIS WITH NAVX
        gyro_heading = -self.sensors.getCurrentAngle(
        )  # Assuming the gyro is giving a value in degrees
        desired_heading = pf.r2d(
            self.leftFollower.getHeading())  # Should also be in degrees

        # This is a poor man's P controller
        angleDifference = pf.boundHalfDegrees(desired_heading - gyro_heading)
        turn = 5 * (-1.0 / 80.0) * angleDifference

        l = l + turn
        r = r - turn

        # -1 is forward, so invert both values
        self.drivetrain().moveRobot(-l, -r)
Beispiel #7
0
    def autonomousPeriodic(self):

        l = self.leftFollower.calculate(self.l_encoder.get())
        r = self.rightFollower.calculate(self.r_encoder.get())

        gyro_heading = (
            -self.gyro.getAngle()
        )  # Assuming the gyro is giving a value in degrees
        desired_heading = pf.r2d(
            self.leftFollower.getHeading()
        )  # Should also be in degrees

        # This is a poor man's P controller
        angleDifference = pf.boundHalfDegrees(desired_heading - gyro_heading)
        turn = .8 * (-1.0 / 80.0) * angleDifference

        l = l + turn
        r = r - turn

        # -1 is forward, so invert both values
        self.robot_drive.tankDrive(-l, -r)
Beispiel #8
0
def GeneratePath(path_name, file_name, waypoints, settings, reverse=False, heading_overide=False, headingValue=0.0):
    """
    This function will take a set of pathfinder waypoints and create the trajectories to follow a path going through the waypoints.  This path is
    specific for the drivetrain controllers, so the position will use the CTRE quadrature encoders and the velocity will use the feed-forward in
    units of Volts.
    """
    # Generate the path using pathfinder.
    info, trajectory = pf.generate(waypoints, settings.order, settings.samples, settings.period,
                                   settings.maxVelocity, settings.maxAcceleration, settings.maxJerk)

    # Modify the path for the differential drive based on the calibrated wheelbase
    modifier = pf.modifiers.TankModifier(trajectory).modify(ROBOT_WHEELBASE_FT)

    # Ge the left and right trajectories...left and right are reversed
    rightTrajectory = modifier.getLeftTrajectory()
    leftTrajectory = modifier.getRightTrajectory()

    # Grab the position, velocity + acceleration for feed-forward, heading, and duration
    path = {"left": [], "right": []}
    headingOut = []
    for i in range(len(leftTrajectory)):
        if not reverse:
            if heading_overide:
                heading = headingValue
            elif abs(pf.r2d(leftTrajectory[i].heading)) > 180:
                heading = -(pf.r2d(leftTrajectory[i].heading) - 360)
            else:
                heading = -pf.r2d(leftTrajectory[i].heading)
        else:
            if heading_overide:
                heading = headingValue
            else:
                heading = pf.r2d(leftTrajectory[i].heading) - 180

        headingOut.append(heading)
        path["left"].append([leftTrajectory[i].position * 4096 /                            # Position: CTRE SRX Mag encoder: 4096 units per rotation
                             (ROBOT_WHEEL_DIAMETER_FT * math.pi),                           # Voltage / Feed-Forward
                             CalculateFeedForwardVoltage(True,
                                                         leftTrajectory[i].velocity,
                                                         leftTrajectory[i].acceleration),
                             heading / 360,                                                 # Pigeon IMU setup for 3600 units per rotation
                             int(leftTrajectory[i].dt * 1000)])                             # Duration
        path["right"].append([rightTrajectory[i].position * 4096 /
                              (ROBOT_WHEEL_DIAMETER_FT * math.pi),
                              CalculateFeedForwardVoltage(False,
                                                          rightTrajectory[i].velocity,
                                                          rightTrajectory[i].acceleration),
                              heading / 360,
                              int(rightTrajectory[i].dt * 1000)])

    # Dump the path into a pickle file which will be read up later by the RoboRIO robot code
    with open(os.path.join(path_name, file_name+".pickle"), "wb") as fp:
        pickle.dump(path, fp)

    # Plot the data for review
    x = list(i * (settings.period) for i, _ in enumerate(leftTrajectory))

    plt.figure()
    # plt.plot(aspect=0.5)
    plt.title("Trajectory")
    drawField(plt)
    plt.plot([segment.y for segment in leftTrajectory],
             [segment.x for segment in leftTrajectory],
             marker='.', color='b')
    plt.plot([segment.y for segment in rightTrajectory],
             [segment.x for segment in rightTrajectory],
             marker='.', color='r')
    plt.gca().set_yticks(np.arange(0, 30.1, 1.0), minor=True)
    plt.gca().set_yticks(np.arange(0, 30.1, 3))
    plt.gca().set_xticks(np.arange(0, 27.1, 1.0), minor=True)
    plt.gca().set_xticks(np.arange(0, 27.1, 3))
    plt.grid(which='minor', color='grey', linestyle='--', alpha=0.25)
    plt.grid(which='major', color='grey', linestyle='-', alpha=0.75)

    # Plot the heading
    plt.figure()
    plt.title("Heading")
    plt.plot(x, headingOut, marker='.')

    # Plot the velocity and acceleration and look for any discontinuities
    plt.figure()
    plt.subplot(2, 1, 1)
    plt.title("Velocity")
    plt.plot(x, [segment.velocity for segment in leftTrajectory], marker='.', color='b')
    plt.plot(x, [segment.velocity for segment in rightTrajectory], marker='.', color='r')
    plt.yticks(np.arange(0, DRIVETRAIN_MAX_VELOCITY + 0.1, 1.0))
    plt.grid()
    plt.subplot(2, 1, 2)
    plt.title("Acceleration")
    plt.plot(x, [segment.acceleration for segment in leftTrajectory], marker='.', color='b')
    plt.plot(x, [segment.acceleration for segment in rightTrajectory], marker='.', color='r')
    plt.yticks(np.arange(-DRIVETRAIN_MAX_ACCELERATION, DRIVETRAIN_MAX_ACCELERATION + 1.1, 2.0))
    plt.grid()
    plt.tight_layout()
    plt.show()
Beispiel #9
0
    def exec_path(self):
        if self.finished:
            return

        print('[path controller] [current] L: %s; R: %s' %
        (self.drivetrain.get_left_encoder_meters(),
         self.drivetrain.get_right_encoder_meters()))

        l_dist = self.drivetrain.get_left_encoder_meters() \
            - self.position_offset[0]
        r_dist = self.drivetrain.get_right_encoder_meters() \
            - self.position_offset[1]

        if self.reverse:
            l_dist *= -1
            r_dist *= -1

        try:
            l_o = self.left.calculate(l_dist)
            r_o = self.right.calculate(r_dist)
        except Exception:
            return

        print('[path controller] [calculated] L: %s; R: %s' % (l_o, r_o))

        gyro_heading = self.angle_controller.get_angle() - self.angle_offset
        desired_heading = -pf.r2d(self.left.getHeading())

        if self.reverse:
            desired_heading += 180

        print('[path controller] [heading] curr: %s, desired: %s' %
              (gyro_heading, desired_heading))

        if not self.initial_desired_heading:
            self.initial_desired_heading = desired_heading

        angleDifference = pf.boundHalfDegrees(desired_heading - gyro_heading -
                                              self.initial_desired_heading)
        # TURN_FACTOR = 0.025
        TURN_FACTOR = 0.01
        turn = TURN_FACTOR * angleDifference

        if self.reverse:
            turn *= -1

        # print('[path controller] [angle diff] %s [desired] %s [gyro] ' +
        #       '%s [init desire] %s' % (angleDifference, desired_heading,
        #       gyro_heading))

        print('[path controller] [calculated w turn] L: %s; R: %s' %
              (l_o + turn, r_o - turn))

        l_speed = l_o + turn
        r_speed = r_o - turn

        if self.reverse:
            l_speed *= -1
            r_speed *= -1

        self.drivetrain.manual_drive(l_speed, r_speed)

        if self.left.isFinished() and self.right.isFinished():
            self.stop()
            self.finished = True