autonomous_routine_path_planning
Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| autonomous_routine_path_planning [2022/08/15 00:05] – created rfhuang | autonomous_routine_path_planning [2022/09/13 21:51] (current) – rfhuang | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ===== Autonomous Routines ===== | ===== Autonomous Routines ===== | ||
| + | |||
| + | __Encoder Based Odometric Path Planning__ | ||
| + | |||
| + | **Github** \\ | ||
| + | [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ==== Goals and Tooling==== | ||
| One of the goals we set during the offseason was to upgrade our current autonomous pathing through the use of motion profiling. We had tried this in 2020, but had great difficulty in getting off the ground. This year, we did more research and we were able to get ahead of the curve before we started development. We used the WPILib toolsuite for designing and running autonomous paths with trajectories using Ramsete controllers, | One of the goals we set during the offseason was to upgrade our current autonomous pathing through the use of motion profiling. We had tried this in 2020, but had great difficulty in getting off the ground. This year, we did more research and we were able to get ahead of the curve before we started development. We used the WPILib toolsuite for designing and running autonomous paths with trajectories using Ramsete controllers, | ||
| - | {{ :: | + | {{ : |
| + | |||
| + | //Fig 4.6: One of our three-ball autonomous routines. We designed this path with high velocities and high angle turns which was made possible by our highly refined PID loops. This was to make // | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ==== Computer Vision Integration ==== | ||
| + | Given the modularity of the Command Based architecture, | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Architecture (Sequential) ===== | ||
| + | |||
| + | 1. Using PathWeaver with path + splines as inputs, the desired path is turned into JSON which is machine readable to become a RamseteCommand. | ||
| + | {{ :: | ||
| + | 2. TrajectorySequence.java takes in those generated path files, combines it with our drivebase PID constants into a completed RamseteCommand. | ||
| + | <code java> public TrajectorySequence(Drivebase drivetrain, String ... paths) { | ||
| + | drivebase = drivetrain; | ||
| + | |||
| + | for (String pathLocation : paths) { | ||
| + | Command path = generatePath(pathLocation); | ||
| + | if (path == null) return; | ||
| + | } | ||
| + | |||
| + | for (String pathLocation : paths) { | ||
| + | Command path = generatePath(pathLocation); | ||
| + | addCommands(path); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | private Command generatePath(String pathName) { | ||
| + | try { | ||
| + | Path trajectoryPath = Filesystem.getDeployDirectory().toPath().resolve(pathName); | ||
| + | Trajectory trajectory = TrajectoryUtil.fromPathweaverJson(trajectoryPath); | ||
| + | RamseteCommand ramseteCommand = new RamseteCommand( | ||
| + | trajectory, | ||
| + | drivebase:: | ||
| + | new RamseteController(AutoConstants.kRamseteB, | ||
| + | new SimpleMotorFeedforward( | ||
| + | DrivebaseConstants.ksVolts, | ||
| + | DrivebaseConstants.kvVoltSecondsPerMeter, | ||
| + | DrivebaseConstants.kaVoltSecondsSquaredPerMeter), | ||
| + | DrivebaseConstants.kDriveKinematics, | ||
| + | drivebase:: | ||
| + | new PIDController(DrivebaseConstants.kPDriveVel, | ||
| + | new PIDController(DrivebaseConstants.kPDriveVel, | ||
| + | // RamseteCommand passes volts to the callback | ||
| + | drivebase:: | ||
| + | drivebase); | ||
| + | |||
| + | // Reset odometry to the starting pose of the trajectory. | ||
| + | drivebase.resetOdometry(trajectory.getInitialPose()); | ||
| + | // Set up a sequence of commands | ||
| + | // First, we want to reset the drivetrain odometry | ||
| + | return new InstantCommand(() -> drivebase.resetOdometry(trajectory.getInitialPose()), | ||
| + | .andThen(new InstantCommand(() -> drivebase.enableBrakeMode(), | ||
| + | // next, we run the actual ramsete command | ||
| + | .andThen(ramseteCommand) | ||
| + | // Finally, we make sure that the robot stops | ||
| + | .andThen(new InstantCommand(() -> drivebase.tankDriveVolts(0, | ||
| + | } catch (IOException ex) { | ||
| + | DriverStation.reportError(" | ||
| + | } | ||
| + | return null; | ||
| + | }</ | ||
| + | 3. Using a pre-generated GUI in SmartDashbaord the desired path is chosen, this happens in AutoSelector.java. The selected path is able to be read by our code when the match begins. | ||
| + | <code java> | ||
| + | chooser.setDefaultOption(" | ||
| + | new InstantCommand(superstructure.intake:: | ||
| + | new ParallelRaceGroup( | ||
| + | new BallManager(superstructure, | ||
| + | new TrajectorySequence(drivebase, | ||
| + | ), | ||
| + | new ParallelCommandGroup( | ||
| + | new Shoot(drivebase, | ||
| + | new SequentialCommandGroup( | ||
| + | new WaitCommand(0.75), | ||
| + | new InstantCommand(superstructure.intake:: | ||
| + | ) | ||
| + | ), | ||
| + | new ParallelRaceGroup( | ||
| + | new BallManager(superstructure, | ||
| + | new SequentialCommandGroup( | ||
| + | new TrajectorySequence(drivebase, | ||
| + | new WaitCommand(0.75), | ||
| + | new TrajectorySequence(drivebase, | ||
| + | ) | ||
| + | ), | ||
| + | new Shoot(drivebase, | ||
| + | )); | ||
| + | |||
| + | chooser.addOption(" | ||
| + | new InstantCommand(superstructure.intake:: | ||
| + | new ParallelCommandGroup( | ||
| + | new BallManager(superstructure).withInterrupt(() -> { | ||
| + | return superstructure.indexer.hasLowerBall() && superstructure.indexer.hasUpperBall(); | ||
| + | }).withTimeout(4), | ||
| + | new TrajectorySequence(drivebase, | ||
| + | ), | ||
| + | new Shoot(drivebase, | ||
| + | new InstantCommand(superstructure.intake:: | ||
| + | new ParallelRaceGroup( | ||
| + | new BallManager(superstructure), | ||
| + | new SequentialCommandGroup( | ||
| + | new TrajectorySequence(drivebase, | ||
| + | new WaitCommand(1), | ||
| + | new TrajectorySequence(drivebase, | ||
| + | ) | ||
| + | ), | ||
| + | new Shoot(drivebase, | ||
| + | )); | ||
| + | |||
| + | SmartDashboard.putData(chooser); | ||
| + | | ||
| - | //Fig 4.5: Romi robot - primary test board for our autonomous routines and runs the same code as the main robot and comes with a Raspberry Pi for additional communication// | + | public Command getSelected() { |
| + | return chooser.getSelected(); | ||
| + | }</code> | ||
| + | 4. The selected path is taken from the GUI at game start. After that, the RamseteCommand is generated | ||
autonomous_routine_path_planning.1660536303.txt.gz · Last modified: 2022/08/15 00:05 by rfhuang
