コード例 #1
0
    def end(self, message='Ended'):
        """Called once after isFinished returns true"""
        end_time = round(Timer.getFPGATimestamp() - self.robot.enabled_time, 1)
        print(f"** {message} {self.getName()} at {end_time} s after {round(end_time-self.start_time,1)} s **")
        SmartDashboard.putString("alert", f"** Ended {self.getName()} at {end_time} s after {round(end_time-self.start_time,1)} s **")
        self.robot.drivetrain.stop()

        self.write_telemetry = SmartDashboard.getBoolean("ramsete_write", self.write_telemetry)
        if self.write_telemetry:
            location = Path.cwd() if self.robot.isSimulation() else Path('/home/lvuser/py/')  # it's not called robot on the robot
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            file_name = timestamp + '_'+ self.course + f'_kpv_{self.kp_vel:2.1f}'.replace('.','p') + f'_vel_{str(self.velocity).replace(".","p")}'   +'.pkl'
            pickle_file = location / 'sim' / 'data' / file_name
            with open(pickle_file.absolute(), 'wb') as fp:
                out_dict = {'TIMESTAMP':timestamp,'DATA':self.telemetry, 'COURSE':self.course, 'VELOCITY':self.velocity,
                            'KP_VEL':self.kp_vel, 'KD_VEL':self.kd_vel, 'BETA':self.beta, 'ZETA':self.zeta}
                pickle.dump(out_dict, fp)
            print(f'*** Wrote ramsete command data to {file_name} ***')
        else:
            print(f'*** Skipping saving of telemetry to disk ***')
コード例 #2
0
 def end(self, message='Ended'):
     """Called once after isFinished returns true"""
     end_time = round(Timer.getFPGATimestamp() - self.robot.enabled_time, 1)
     elapsed_time = end_time - self.start_time + self.time_offset
     print(
         f"** {message} {self.getName()} at {end_time} s after {round(elapsed_time,1)} s **"
     )
     SmartDashboard.putString(
         "alert",
         f"** Ended {self.getName()} at {end_time} s after {round(end_time-self.start_time,1)} s **"
     )
     self.robot.drivetrain.stop()
     AutonomousRamseteSimple.time_offset += end_time - self.start_time  # maintain running time in string of commands BUT don't reassign or it makes an instance
     # ToDo: update this so it only happens at the end of a list of commands.  May need a new variable.
     self.write_telemetry = SmartDashboard.getBoolean(
         "ramsete_write", self.write_telemetry)
     if self.write_telemetry:
         timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
         file_name = timestamp + '_' + self.course + f'_kpv_{self.kp_vel:2.1f}'.replace(
             '.',
             'p') + f'_vel_{str(self.velocity).replace(".","p")}' + '.pkl'
         pickle_file = Path.cwd() / 'sim' / 'data' / file_name
         with open(pickle_file.absolute(), 'wb') as fp:
             out_dict = {
                 'TIMESTAMP': timestamp,
                 'DATA': self.telemetry,
                 'COURSE': self.course,
                 'VELOCITY': self.velocity,
                 'KP_VEL': self.kp_vel,
                 'KD_VEL': self.kd_vel,
                 'BETA': self.beta,
                 'ZETA': self.zeta
             }
             pickle.dump(out_dict, fp)
         print(f'*** Wrote ramsete command data to {file_name} ***')
     else:
         print(
             f'*** Skipping saving of {len(self.telemetry)} telemetry points to disk  ***'
         )
コード例 #3
0
    def initialize(self):
        """Called just before this Command runs the first time."""

        self.previous_time = -1

        self.init_time = round(
            Timer.getFPGATimestamp() - self.robot.enabled_time, 1)

        self.robot.drivetrain.drive.feed(
        )  # this initialization is taking some time now
        # update gains from dash if desired
        if self.dash is True:
            self.kp_vel = SmartDashboard.getNumber("ramsete_kpvel",
                                                   self.kp_vel)
            self.beta = SmartDashboard.getNumber("ramsete_B", self.beta)
            self.zeta = SmartDashboard.getNumber("ramsete_Z", self.zeta)
            self.write_telemetry = SmartDashboard.getBoolean(
                "ramsete_write", self.write_telemetry)

        # create controllers
        self.follower = wpilib.controller.RamseteController(
            self.beta, self.zeta)
        self.left_controller = wpilib.controller.PIDController(
            self.kp_vel, 0, self.kd_vel)
        self.right_controller = wpilib.controller.PIDController(
            self.kp_vel, 0, self.kd_vel)
        self.left_controller.reset()
        self.right_controller.reset()

        #ToDo - make this selectable, probably from the dash, add the other trajectories (done)
        trajectory_choice = self.path  # path is passed in on constructor this time
        self.velocity = float(self.robot.oi.velocity_chooser.getSelected()
                              )  # get the velocity from the GUI
        self.trajectory = drive_constants.generate_trajectory(
            trajectory_choice,
            self.velocity,
            simulation=self.robot.isSimulation(),
            save=False)
        self.course = trajectory_choice
        # Note - we are setting to pose to have the robot physically in the start position - usually absolute matters
        if self.relative:  # figure out if we want to start where we are or where the trajectory says we should be
            self.start_pose = geo.Pose2d(
                self.trajectory.sample(0).pose.X(),
                self.trajectory.sample(0).pose.Y(),
                self.robot.drivetrain.get_rotation2d())
        else:
            #self.start_pose = self.robot.drivetrain.get_pose()
            field_x = SmartDashboard.getNumber(
                'field_x',
                self.trajectory.sample(0).pose.X())
            field_y = SmartDashboard.getNumber(
                'field_y',
                self.trajectory.sample(0).pose.Y())
            self.start_pose = geo.Pose2d(
                field_x, field_y, self.robot.drivetrain.get_rotation2d())
        self.robot.drivetrain.reset_odometry(self.start_pose)

        self.robot.drivetrain.drive.feed(
        )  # this initialization is taking some time now

        initial_state = self.trajectory.sample(0)
        # these are all meters in 2021
        self.previous_speeds = self.kinematics.toWheelSpeeds(
            wpimath.kinematics.ChassisSpeeds(
                initial_state.velocity, 0,
                initial_state.curvature * initial_state.velocity))

        self.start_time = round(
            Timer.getFPGATimestamp() - self.robot.enabled_time, 1)
        print(
            "\n" +
            f"** Started {self.getName()} on {self.course} with load time {self.start_time-self.init_time:2.2f}s"
            f" (b={self.beta}, z={self.zeta}, kp_vel={self.kp_vel}) at {self.start_time} s **"
        )
        SmartDashboard.putString(
            "alert", f"** Started {self.getName()} at {self.start_time} s **")

        if self.reset_telemetry:  # don't reset telemetry if we want to chain trajectories together
            print(
                'Time\tTrVel\tTrRot\tlspd\trspd\tram an\tram vx\tram vy\tlffw\trffw\tlpid\trpid'
            )
            self.telemetry.clear(
            )  # Aha.  important not to set it to a new value (=[]) , because then it makes an instance
            AutonomousRamseteSimple.time_offset = 0  # seems like an easier way to do it, but man.  Globals are always ugly.
        else:
            pass
コード例 #4
0
    def initialize(self):
        """Called just before this Command runs the first time."""

        self.previous_time = -1
        self.telemetry = []
        self.init_time = round(Timer.getFPGATimestamp() - self.robot.enabled_time, 1)

        self.robot.drivetrain.drive.feed() # this initialization is taking some time now
        # update gains from dash if desired
        if self.dash is True:
            self.kp_vel = SmartDashboard.getNumber("ramsete_kpvel", self.kp_vel)
            self.beta = SmartDashboard.getNumber("ramsete_B", self.beta)
            self.zeta = SmartDashboard.getNumber("ramsete_Z", self.zeta)
            self.write_telemetry = SmartDashboard.getBoolean("ramsete_write", self.write_telemetry)

        # create controllers
        self.follower = wpilib.controller.RamseteController(self.beta, self.zeta)
        self.left_controller = wpilib.controller.PIDController(self.kp_vel, 0 , self.kd_vel)
        self.right_controller = wpilib.controller.PIDController(self.kp_vel, 0 , self.kd_vel)
        self.left_controller.reset()
        self.right_controller.reset()


        #ToDo - test for real robot -
        trajectory_choice = self.robot.oi.path_chooser.getSelected()  # get path from the GUI
        self.velocity = float(self.robot.oi.velocity_chooser.getSelected())  # get the velocity from the GUI
        if 'z_' not in trajectory_choice:  # let me try a few of the other methods if the path starts with z_
            self.trajectory = drive_constants.generate_trajectory(trajectory_choice, self.velocity, simulation=self.robot.isSimulation(), save=False)
            self.course = trajectory_choice
            if self.robot.isReal():
                self.start_pose = geo.Pose2d(self.trajectory.sample(0).pose.X(), self.trajectory.sample(0).pose.Y(),
                                                 self.robot.drivetrain.get_rotation2d())
            else:
                field_x = SmartDashboard.getNumber('field_x', self.trajectory.sample(0).pose.X())
                field_y = SmartDashboard.getNumber('field_y', self.trajectory.sample(0).pose.Y())
                self.start_pose = geo.Pose2d(field_x, field_y, self.robot.drivetrain.get_rotation2d())
        self.robot.drivetrain.drive.feed()  # this initialization is taking some time now

        # Note - we are setting to pose to have the robot physically in the start position - usually absolute matters

        if 'slalom' in trajectory_choice:
            pass
            #self.start_pose = geo.Pose2d(1.3, 0.66, geo.Rotation2d(0))
        elif 'barrel' in trajectory_choice:
            pass
            # self.start_pose = geo.Pose2d(1.3, 2.40, geo.Rotation2d(0))  # may want to rotate this
        elif 'bounce' in trajectory_choice:
            pass
            # self.start_pose = geo.Pose2d(1.3, 2.62, geo.Rotation2d(0))
        elif 'student' in trajectory_choice:
            pass
            # self.start_pose = geo.Pose2d(0, 0, geo.Rotation2d(0))  # student should put barrel, slalom or bounce in name
        elif 'loop' in trajectory_choice:
            self.course = 'loop'
            self.trajectory = drive_constants.get_loop_trajectory(self.velocity)
            self.start_pose = geo.Pose2d(0, 0, geo.Rotation2d(0))
        elif 'poses' in trajectory_choice:
            self.course = 'slalom_poses'
            self.trajectory = drive_constants.get_pose_trajectory(self.velocity)
            self.start_pose = geo.Pose2d(0, 0, geo.Rotation2d(0))
        elif 'points' in trajectory_choice:
            self.course = 'slalom_points'
            self.trajectory = drive_constants.get_point_trajectory(self.velocity)
            self.start_pose = geo.Pose2d(0, 0, geo.Rotation2d(0))
        elif 'z_test' in trajectory_choice:
            self.course = 'test'
            self.trajectory = drive_constants.get_test_trajectory(self.velocity)
            self.start_pose = geo.Pose2d(0, 0, geo.Rotation2d(0))
        else:
            pass
            #self.start_pose = geo.Pose2d(0, 0, geo.Rotation2d(0))

        self.robot.drivetrain.reset_odometry(self.start_pose)
        initial_state = self.trajectory.sample(0)
        # these are all meters in 2021
        self.previous_speeds = self.kinematics.toWheelSpeeds(wpimath.kinematics.ChassisSpeeds(
            initial_state.velocity, 0, initial_state.curvature*initial_state.velocity))

        self.start_time = round(Timer.getFPGATimestamp() - self.robot.enabled_time, 1)
        print("\n" + f"** Started {self.getName()} on {self.course} with load time {self.start_time-self.init_time:2.2f}s"
                     f" (b={self.beta}, z={self.zeta}, kp_vel={self.kp_vel}) at {self.start_time} s **")
        SmartDashboard.putString("alert", f"** Started {self.getName()} at {self.start_time} s **")

        print('Time\tTr Vel\tTr Rot\tlspd\trspd\tram ang\tram vx\tram vy\tlffw\trffw\tlpid\trpid')
コード例 #5
0
 def initializeBoolean(label: str, defaultValue: bool) -> bool:
     value: bool = SmartDashboard.getBoolean(label, defaultValue)
     SmartDashboard.putBoolean(label, value)
     return value
コード例 #6
0
    def teleopPeriodic(self):
        try:
            if self.robot_mode == RobotModes.MANUAL_DRIVE:
                if robotmap.drivetrain_enabled:
                    if self.subsystem_drivetrain.drive_mode == drivetrain.DrivetrainMode.MANUAL_DRIVE_CURVATURE:
                        self.subsystem_drivetrain.curvature_drive(
                            self.oi.controller_driver.getY()**3,
                            -self.oi.controller_driver.getX()**3)
                    if self.subsystem_drivetrain.drive_mode == drivetrain.DrivetrainMode.MANUAL_DRIVE_ARCADE:
                        self.subsystem_drivetrain.arcade_drive(
                            self.oi.controller_driver.getY()**3,
                            -self.oi.controller_driver.getX()**3)

                    if self.navx.isConnected(
                    ) and self.oi.check_drivetrain_straight(
                            self.oi.controller_driver.getX(),
                            self.oi.controller_driver.getY()):
                        self.subsystem_drivetrain.drive_to_angle(
                            self.oi.controller_driver.getY()**3)
                    elif self.subsystem_drivetrain.drive_mode == drivetrain.DrivetrainMode.ASSIST_DRIVE_ARCADE:
                        self.subsystem_drivetrain.drive_mode = drivetrain.DrivetrainMode.MANUAL_DRIVE_CURVATURE

                if robotmap.shooter_enabled:
                    target_shooter_speed = dash.getNumber(
                        "target shooter velocity", 0)
                    shooter_enabled = dash.getBoolean("shooter enabled", False)

                    if shooter_enabled:
                        self.subsystem_shooter.enable_at_speed(
                            self.oi.controller_driver.getY(
                                wpilib.XboxController.Hand.kLeft))
                    else:
                        self.subsystem_shooter.disable()

                    dash.putNumber("shooter speed error",
                                   self.subsystem_shooter.get_error())

                if robotmap.loader_enabled:
                    if self.oi.controller_driver.getPOV() == 0:  # up on dpad
                        self.subsystem_loader.position = LoaderPosition.UP
                    if self.oi.controller_driver.getPOV(
                    ) == 180:  # down on dpad
                        self.subsystem_loader.position = LoaderPosition.DOWN
                    if self.oi.controller_driver.getXButtonPressed():
                        self.subsystem_loader.enabled = not self.subsystem_loader.enabled

                if self.oi.controller_driver.getBButtonPressed():
                    self.robot_mode = RobotModes.AUTO_TARGETTING

            elif self.robot_mode == RobotModes.AUTO_TARGETTING:
                # this is the control loop that will deal with automatically shooting into a target
                # inputs: distance from target, horizontal offset from target
                # outputs: speed of shooter, turning speed of robot, linear speed of robot
                # the speed of the shooter is controlled by the distance
                # the linear speed of the robot is controlled by the distance
                # the turning speed of the robot is controlled by the horizontal offset of the robot

                if not robotmap.limelight_enabled:
                    # we can't do anything in this case.
                    self.robot_mode = RobotModes.MANUAL_DRIVE

                distance_to_target = self.limelight.get_distance_trig()
                x_offset = self.limelight.get_horizontal_angle_offset()

                drivetrain_on_target = True

                if robotmap.drivetrain_enabled:
                    # use proportional techniques to make the robot drive into a good position to shoot
                    angular_error = 0
                    distance_error = 0

                    if abs(x_offset
                           ) > robotmap.auto_targetting_alignment_tolerance:
                        drivetrain_on_target = False
                        angular_error = 0 - x_offset

                    if distance_to_target > robotmap.auto_targetting_max_distance:
                        drivetrain_on_target = False
                        distance_error = distance_to_target - robotmap.auto_targetting_max_distance

                    if distance_to_target < robotmap.auto_targetting_min_distance:
                        drivetrain_on_target = False
                        distance_to_target = distance_to_target - robotmap.auto_targetting_min_distance

                    drivetrain_rotation = drivetrain.DrivetrainConstants.K_PROPORTIONAL_TURNING * angular_error
                    drivetrain_power = drivetrain.DrivetrainConstants.K_PROPORTIONAL_DRIVING * distance_error

                    self.subsystem_drivetrain.arcade_drive(
                        drivetrain_power, drivetrain_rotation)

                if robotmap.shooter_enabled:
                    # set the shooter to an appropriate speed if the drivetrain is on target
                    if drivetrain_on_target:
                        self.subsystem_shooter.enabled = True
                        self.subsystem_shooter.shoot_from_distance(
                            distance_to_target, angle=45)
                    else:
                        self.subsystem_shooter.enabled = False

                if robotmap.loader_enabled:
                    # TODO: we don't have a working loader right now so (logically) there's no code here
                    pass

                if self.oi.controller_driver.getBButtonPressed():
                    self.robot_mode = RobotModes.MANUAL_DRIVE

            if robotmap.limelight_enabled:
                dash.putString("distance to target",
                               self.limelight.get_distance_trig())
                dash.putString("horizontal angle to target",
                               self.limelight.get_horizontal_angle_offset())
                dash.putString("vertical angle to target",
                               self.limelight.get_vertical_angle_offset())

            dash.putNumber("PID Output",
                           self.subsystem_drivetrain.turn_pid.get())

        except:
            self.onException()