wpilibsuite / allwpilib

Official Repository of WPILibJ and WPILibC
https://wpilib.org/
Other
1.05k stars 612 forks source link

Simulator: Why is my Field2d object not updating based on a swerve robot code sample? #3219

Closed reteps closed 1 year ago

reteps commented 3 years ago

Describe the question you have. Hello, is there any way to use a swerve bot with the simulator Field2d object?

Describe the reason for your confusion.

The online tutorial, https://docs.wpilib.org/en/stable/docs/software/examples-tutorials/drivesim-tutorial/index.html, uses a class DifferentialDrivetrainSim, that would not make sense in the context of a swerve bot (I think?).

Is your question related to a problem? Please describe.

Using the SwerveDrivePoseEstimator example c++ project, I have not been able to get my robot to move inside of the Field2d screen on the simulator.

image Additional context (Modifications made to the example project)

Added the Field2d instance and updated call.

// private member variable of Drivetrain
frc::Field2d m_field;
// ....
void Drivetrain::UpdateOdometry() {
  m_poseEstimator.Update(m_gyro.GetRotation2d(), m_frontLeft.GetState(),
                         m_frontRight.GetState(), m_backLeft.GetState(),
                         m_backRight.GetState());

    m_field.SetRobotPose(m_poseEstimator.GetEstimatedPosition());
}
// ...
  Drivetrain() {
      m_gyro.Reset();
      frc::SmartDashboard::PutData("Field", &m_field);
    }

Added encoders to prevent overlap inside SwerveModule.

SwerveModule::SwerveModule(const int driveMotorChannel,
                           const int turningMotorChannel,
                           const int encoderChannel)
    : m_driveMotor(driveMotorChannel), m_turningMotor(turningMotorChannel), 
    m_driveEncoder(encoderChannel, encoderChannel + 1),
     m_turningEncoder(encoderChannel + 2, encoderChannel + 3) {

}
// header of SwerveModule.h
  frc::Encoder m_driveEncoder;
  frc::Encoder m_turningEncoder;
  // Drivetrain.h
  SwerveModule m_frontLeft{1, 2, 0};
  SwerveModule m_frontRight{2, 3, 4};
  SwerveModule m_backLeft{5, 6, 8};
  SwerveModule m_backRight{7, 8, 12};

Updated Odometry in TeleopPeriodic call

  void TeleopPeriodic() override { DriveWithJoystick(true); m_swerve.UpdateOdometry(); }

I would appreciate some guidance or resources, I am not sure where to go from here.

prateekma commented 3 years ago

Are you sending the Field2d instance over SmartDashboard? You'll need the following call (in the Drivetrain constructor would make the most sense):

frc::SmartDashboard::PutData("Field", &m_field);
reteps commented 3 years ago

Oops! I also had that in the constructor, ~I will edit the details~ updated.

  Drivetrain() {
      m_gyro.Reset();
      frc::SmartDashboard::PutData("Field", &m_field);
    }
PeterJohnson commented 3 years ago

Where are you calling UpdateOdometry() from?

reteps commented 3 years ago

I have been updating it inside TeleopPeriodic.

  // Robot.cpp
  void TeleopPeriodic() override { DriveWithJoystick(true); m_swerve.UpdateOdometry(); }
prateekma commented 3 years ago

If you print the pose going into m_field to cout, does it change as you provide motor inputs? What about the pose in the NetworkTables view of the GUI under /SmartDashboard/Field?

prateekma commented 3 years ago

Oh, that particular example isn't meant to work in simulation at all. Unfortunately, we weren't able to come up with a stable swerve model (the API would be similar to DifferentialDriveSim) in time for the season.

For example, it does not use EncoderSim et al. to set encoder positions and velocities in the individual swerve module states. These will always stay at zero so there's nothing in the odometry to update.

reteps commented 3 years ago

@prateekma Is there any alternatives? Since we are digital so far this season, it has been hard to teach the new students about Swerve Drive. I would also be wiling to help add simulation support to swerve drive.

reteps commented 3 years ago

@prateekma Would I have any better luck using just the base SwerveDrive class and adding the normal Odometry object instead?

prateekma commented 3 years ago

No, that would have the same issue. One thing you could try is to model each swerve module as a single jointed arm (without gravity) for the rotation portion and the driving part as a simple flywheel. Then you can use their associated classes to get reasonable speeds and angles which you feed into the pose estimator/odometry.

I can try to setup something like this tonight and post it here.

reteps commented 3 years ago

That would be incredibly useful, thank you for your help.

prateekma commented 3 years ago

I started to work on some of the changes here: https://github.com/wpilibsuite/allwpilib/compare/main...prateekma:swerve-sim-test.

There are still a few bugs to work out but I don't think I can work on it more tonight; hopefully I can finish it up this week. It should give you an idea of the direction this is going however.