Two trajectory Questions

I have two trajectory questions.

  1. Now that we are getting into commands, trajectories, and the like, we are wondering if there are any examples anyone can share or docs to help us figure out the syntax of creating a Generate Ramsete command as a stand-alone command rather than inline in Robot Container. I understand why the examples do this, but I feel we will have more success training the programmers on our team who have not been part of the online trainings we have done to get to this point if RobotContainer is as clean as possible.
    When I go to create a new command in VSCode, Generate Ramsete is not a template. So, I am wondering, if we created a new Generate Ramsete command, how do we set it up. I tried copying the Ramsete Command into a new Instant command, but I am getting many errors. See my code and errors below.

  2. In setting up the trajectories (we are using pathweaver), how would one go about having the robot spin in place (or as it is moving from one waypoint to another. This is on a Romi,so it has a differential drive)?

// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

package frc.robot.commands;

import java.nio.file.Path;
import java.util.List;

import edu.wpi.first.wpilibj.Filesystem;
import edu.wpi.first.wpilibj.controller.PIDController;
import edu.wpi.first.wpilibj.controller.RamseteController;
import edu.wpi.first.wpilibj.geometry.Translation2d;
import edu.wpi.first.wpilibj.trajectory.Trajectory;
import edu.wpi.first.wpilibj.trajectory.TrajectoryConfig;
import edu.wpi.first.wpilibj.trajectory.TrajectoryGenerator;
import edu.wpi.first.wpilibj.trajectory.TrajectoryUtil;
import edu.wpi.first.wpilibj.trajectory.constraint.DifferentialDriveVoltageConstraint;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.InstantCommand;
import edu.wpi.first.wpilibj2.command.PrintCommand;
import edu.wpi.first.wpilibj2.command.RamseteCommand;
import frc.robot.Constants;
import frc.robot.Waypoints;
import frc.robot.subsystems.DriveSubsystem;

// NOTE:  Consider using this command inline, rather than writing a subclass.  For more
// information, see:
public class testRamsete extends InstantCommand {
  DriveSubsystem m_drivetrain;
  public testRamsete(DriveSubsystem drivetrain) {
    m_drivetrain = drivetrain;
    // Use addRequirements() here to declare subsystem dependencies.

  Trajectory pathtraj (){  //I know I need to move this into a class that triggers on startup; I put it here for simplicity's sake.
    String trajectoryJSON = "paths/Unnamed.wpilib.json";
    Trajectory trajectory = new Trajectory();

    try {
      Path trajectoryPath = Filesystem.getDeployDirectory().toPath().resolve(trajectoryJSON);
      trajectory = TrajectoryUtil.fromPathweaverJson(trajectoryPath);
   } catch (IOException ex) {
      new PrintCommand("Unable to open trajectory: " ); //+ trajectoryJSON, ex.getStackTrace()
   return trajectory;


  // Called when the command is initially scheduled.
  public void initialize() {
    RamseteCommand ramseteCommand =
    new RamseteCommand( //Wants a different constructor.
        new RamseteController(
            Constants.AutoConstants.kRamseteB, Constants.AutoConstants.kRamseteZeta),
        new SimpleMotorFeedforward( //Wants a different constructor.
        m_drivetrain::getWheelSpeeds,//Wants this expression to be a functional interface; it seems as though it is.
        new PIDController(Constants.DriveConstants.kPDriveVel, 0, 0),
        new PIDController(Constants.DriveConstants.kPDriveVel, 0, 0),
        // RamseteCommand passes volts to the callback
        m_drivetrain::tankDriveVolts, //Wants this expression to be a functional interface; it seems as though it is.

m_drivetrain.resetOdometry(pathtraj.getInitialPose() ) //Cannot find the trajectory
        .andThen(() -> m_drivetrain.tankDriveVolts(0, 0));

Not sure how “nice” the code is, but we have been using standalone Ramsete commands for the past ~2 years. Most of them end up being SequentialCommandGroups, but generally you want to drive-shoot-drive or something like that. For IRH it was driving N trajectories in order.

Take a look at InfiniteRecharge2021/ at main · ligerbots/InfiniteRecharge2021 · GitHub
One change that I would now make for my team is to add a utility method to our DriveTrain to create the Ramsete command from a passed-in trajectory, since it is so repetitive. OTOH, you might end up with half a dozen parameters passed in. For IRH, we had different speeds and constraints depending on the path.


I’ve actually written a full example of trajectory following for non-commandbased, with integration with CTRE motor controllers, PathWeaver, and NavX.

I’ll share a gif later

1 Like


1 Like

Thank you both. This helps a lot (I was wondering about the offboard PID as well). Both projects are incredible. Do any of you have any insight about turning in place (or while moving)?

1 Like

Our 2021 code (linked previously) does have a “TurnAndShoot” command, which starts with turning to point to the target. We don’t use a PID; instead we use a simple if-then-else to set the turn speed based on how far off target we are (ie off by 60deg, turn fast; off by 5 deg, turn slow). This is not the most accurate, but at least it does not oscillate. For our shooting, we don’t need to be too accurate, since our shooter can adjust a few degrees.

1 Like

Thanks. I missed that, but I am on my phone currently. I will check it out. I was just thinking about trying something exactly like that. I will definitely check that out.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.