acmerobotics / road-runner-quickstart

FTC quickstart for https://github.com/acmerobotics/road-runner
BSD 3-Clause Clear License
188 stars 1.01k forks source link

How to use StandardTrackingWheelLocalizer? #25

Closed EddieDL closed 4 years ago

EddieDL commented 4 years ago

It isn't 100% clear how to use the StandardTrackingWheelLocalizer. I have read issue #24 and I have gone through the examples and the documentation. However, I am still not sure on a few things.

Also, in my situation we are not able to install our lateral odometery wheels inline. In our case they are offset from the center line of the robot. What measurements should I use to utilize this configuration?

Thank you for any help you can provide.

rbrott commented 4 years ago

Is it feasible to use dead tracking wheels AND encoders on your DC motors? This seems like it would require 7 DC motor ports on REV Expansion Hubs.

Yes, seven quadrature encoder ports are required for the seven quadrature encoders required by three tracking wheels and 4WD with feedback. You can still use three of those motor ports for other mechanisms, but you will have to use current monitoring, I2C encoders, or another sensor for feedback. This is entirely possible with road runner; however, whether it is feasible for your team depends on the design of your robot.

Assuming it isn't feasible to have both dead tracking wheels AND encoders on your DC motors, what parts of the quickstart code should be removed/changed? For example, getWheelPositions, DriveConstants.TICKS_PER_REV, DriveConstants.WHEEL_RADIUS, etc.

The localization method doesn't really affect the tuning procedure. If you haven't tested your localizer, you should use LocalizationTest or a similar test routine to make sure the positional data is correct. After that, complete the listed steps as detailed in the guide.

Also, in my situation we are not able to install our lateral odometery wheels inline. In our case they are offset from the center line of the robot. What measurements should I use to utilize this configuration?

In that case, StandardTrackingWheelLocalizer may not work for you out-of-the-box, but you can modify the wheel poses passed to the ThreeTrackingWheelLocalizer ctor here. The origin of these coordinates is the center of the robot, and the heading is measured counter-clockwise from the x-axis.

EddieDL commented 4 years ago

Thank you so much for your quick responses. I think this makes sense.

Is it feasible to use dead tracking wheels AND encoders on your DC motors? This seems like it would require 7 DC motor ports on REV Expansion Hubs.

Based on your feedback I will change my question to, is it recommended/required to have encoders for the dead tracking wheels and the DC motors?

While we have the ability to operate other motors with alternate feedback, we would like to not have to tackle this right now. However, if it is the only way to get sufficiently accurate motions with Mechanum wheels, we will need to figure it out. This is our first season using Mechanum wheels so it is a bit of a learning experience :)

EddieDL commented 4 years ago

@rbrott I messed up my last comment, it is now updated correctly.

rbrott commented 4 years ago

is it recommended/required to have encoders for the dead tracking wheels and the DC motors?

Neither is required per se. Since you have the tracking wheels already, I would stick with those and try without drive motor feedback.

EddieDL commented 4 years ago

Note to others that might want to do something similar. If you don't plan on using the built-in PID, you need to remove / rpmToVelocity(getMaxRpm())) from the kV configuration in DriveConstraints.java. The value provided from DriveFeedForwardTuner should be used directly.

@rbrott Thanks again, we are getting really close to having something working. Our problem now is turning. It seems like the StandardTrackingWheelLocalizer doesn't use the internal IMU and it seems like our settings for track width are not right. However, when we run the TrackWidthTuner we get a silly number like .35 back.

I am not sure if we should be working to correct our track width or converting the localizer to use the IMU. It seems like if we convert to using the internal IMU there is no point in having the third wheel?

If we should convert to using the IMU, where might we start this process. In the TrackWidthTuner it references we should change the localizer, but it really isn't clear.

PS: When we are all done, we would be happy to create a PR with some updates to the comments. Let me know if you would be interested in that.

rbrott commented 4 years ago

Our problem now is turning. It seems like the StandardTrackingWheelLocalizer doesn't use the internal IMU and it seems like our settings for track width are not right.

Have you tried validating that the localizer works correctly with LocalizationTest? Also make sure that DriveConstants.TRACK_WIDTH has a reasonable (i.e., physical) value.

It seems like if we convert to using the internal IMU there is no point in having the third wheel?

Yes, three tracking wheels and an IMU usually results in an overdetermined system. You could use least squares or a more advanced technique to utilize the information (of course you'd have to write your own localizer). Alternatively, you can just drop a wheel.

If we should convert to using the IMU, where might we start this process. In the TrackWidthTuner it references we should change the localizer, but it really isn't clear.

If you're just dropping a wheel, take a look at TwoTrackingWheelLocalizer. Otherwise you'll have to write your own implementation of Localizer.

PS: When we are all done, we would be happy to create a PR with some updates to the comments. Let me know if you would be interested in that.

Sure, I'd be happy to hear any feedback on the tuning instructions and/or general documentation. You can also PR https://github.com/acmerobotics/road-runner-docs.

EddieDL commented 4 years ago

As we understand it, using the 3 wheel localizer is more consistent than using the IMU, for mechanum drivetrains. So we are planning to get the three wheel localizer working. Is our understanding correct that the 3 wheel localizer is better than just an IMU and 2 wheel localizer?

Have you tried validating that the localizer works correctly with LocalizationTest? Also make sure that DriveConstants.TRACK_WIDTH has a reasonable (i.e., physical) value.

We have run LocalizationTest and we have verified the values for X and Y, but I don't think we paid much attention to the heading. We will need to check that out.

Our initial value for DriveConstants.TRACK_WIDTH seemed reasonable to us (we used the measurement between the left and right dead wheels). However, the result from the TrackWidthTunder opmode was very weird. We were also confused by the comment TODO: if you haven't already, set the localizer to something that doesn't depend on drive encoders for computing the heading. Perhaps we are supposed to temporarily set the localizer to the TwoTrackingWheelLocalizer while we are tuning the track width?

Again thanks for all your help!

rbrott commented 4 years ago

As we understand it, using the 3 wheel localizer is more consistent than using the IMU, for mechanum drivetrains. So we are planning to get the three wheel localizer working. Is our understanding correct that the 3 wheel localizer is better than just an IMU and 2 wheel localizer?

Unfortunately, I have no personal experience with tracking wheel localizer (only drive wheel localizers). Anecdotally, some prefer 3 wheel localizers because the IMU has additional latency and only updates at 100Hz anyway.

We were also confused by the comment TODO: if you haven't already, set the localizer to something that doesn't depend on drive encoders for computing the heading. Perhaps we are supposed to temporarily set the localizer to the TwoTrackingWheelLocalizer while we are tuning the track width?

That comment cautions against using drive encoders for computing the heading. Neither tracking wheel localizer falls into this camp nor does the default drive encoder localizer (it uses the IMU). The pure drive encoder localizer depends on the value of the track width hence the prohibition.

EddieDL commented 4 years ago

We are generally good on how to use the sample now. I am going to leave the issue open so I can remember to send you a pull request with updated comments/documentation.

I do have a few other questions/issues. I am going to open other issues for those.

Below are the things we think should be address (just so I have it somewhere).

rbrott commented 4 years ago

OK most of those sound like reasonable additions/clarifications to the documentation.

Change StandardTrackingWheelLocalizer to use DriveConstants instead of duplicating values.

StandardTrackingWheelLocalizer deliberately has a separate set of parameters. Are you suggesting moving them to DriveConstants?

EddieDL commented 4 years ago

What is the reason for the StandardTrackignWheelLocalizer to have a separate set of parameters? Perhaps that is causing some of our issues. Is it for the scenario where you have encoders on all of the drive wheels and dead trailing wheels?

In our scenario we configured all of them the same, which is why I thought they should be the same.

rbrott commented 4 years ago

What is the reason for the StandardTrackignWheelLocalizer to have a separate set of parameters?

"Tracking wheels" are dead wheels, not driven wheels (there's no reason to use a tracking wheel localizer for drive encoder localization; that functionality is built into the drive classes). Teams regularly have different encoders, gear ratios, and wheel radii for their dead wheels. I'd be surprised if your driven wheels have exactly the same parameters as your dead wheels.

Is it for the scenario where you have encoders on all of the drive wheels and dead trailing wheels?

Not necessarily. Drive wheel parameters are still required for proper open-loop/feedforward control even if you only use dead wheels for feedback.

EddieDL commented 4 years ago

So in our configuration, we don't have any encoders on the drive wheels. Given this, we configured the TRACK_WIDTH, kV, kA, kStatic, WHEEL_RADIUS, etc. in `DriveConstants' based on our dead wheels. Perhaps this was wrong thinking on our part?

rbrott commented 4 years ago

Yes, that's incorrect. Those parameters should always refer to the drive wheels; many are used for feedforward.

EddieDL commented 4 years ago

I guess it is confusing to me. How those would work if we aren't getting feedback from the encoders. How would you even calculate them since here is no feedback?

rbrott commented 4 years ago

You'll want to tune the feedback with the drive encoders plugged in. If your motors do not have encoders, you'll have to tune it manually with the dashboard with TurnTest (adjust until the robot turns the proper angle).

EddieDL commented 4 years ago

Ahh... So does the following sound like a reasonable sequence of actions?

  1. Plug in all of the drive wheel encoders.
  2. Remove the custom localizer.
  3. Tune the kV, kA, kStatic and ensure all settings in DriveConstants apply to the drive wheels.
  4. Disconnect the drive encoders and connect the dead wheel encoders.
  5. Ensure your localizer configuration matches your dead wheels.
  6. Configure your custom localizer.
  7. Tune your PID.
rbrott commented 4 years ago

That seems more-or-less reasonable. Have you checked out this list?

EddieDL commented 4 years ago

Yup. That is the process we have been using.

It seems like our main remaining issue is that we were not tuning the kV, kA, kStatic, and TRACK_WIDTH for the driven wheels. We did it based on the Localizer data or something (we haven't had the drive encoders plugged in).

Though, with all of the issues we are considering just using the encoder ports so we can just use the built in velocity PID. Our first competition is next weekend :)

EddieDL commented 4 years ago

@rbrott two more questions.

rbrott commented 4 years ago

What are the units on Max Velocity, Max Acceleration, and Jerk. My assumption is Inches per second, and Inches per second per second for Max Velocity and Max Acceleration, but Jerk I have no idea.

The units of velocity, acceleration and jerk are in/sec, in/sec^2, and in/sec^3, respectively (keep in mind you can substitute any distance unit you like; the quickstart tacitly assumes inches).

If we choose to not use the encoders from the drive wheels what should getWheelPositions return?

getWheelPositions() should always return the positions of the drive wheels. If you don't have drive encoders/don't plan to use them, you can return a list of zeroes with the proper length.

Calvin-Xu commented 4 years ago

is it recommended/required to have encoders for the dead tracking wheels and the DC motors?

Neither is required per se. Since you have the tracking wheels already, I would stick with those and try without drive motor feedback.

So is it that when an alternate localizer (i.e. StandardTrackingWheelLocalizer) is set, the error in the drivetrain PID loop is then derived from the position the localizer returns instead of the drive wheel positions, which renders encoders on the drive motors unnecessary (or are there still velocity control benefits)? We are just recently beginning to understand the process (related); it would be great that we do not need seven encoder ports just for the drivetrain.

rbrott commented 4 years ago

The localizer determines how the robot's position is computed. The default localizers use the drive wheel encoders. This position is used by the various followers, including the PIDVA follower.

This is independent of the onboard/built-in motor velocity PID that is recommended for drive encoders if available.

If you need to reclaim encoder ports, it's probably better to sacrifice velocity control (i.e., remove the drive wheel encoders). That said, velocity control is useful in addition to just position control; in essence, it helps prevent velocity error from "spilling"/"transforming" into position error.

Calvin-Xu commented 4 years ago

So if I understand correctly, the goal of both drive characterization with DriveFeedforwardTuner and drive wheel encoders + tuning with DriveVelocityPIDTuner is to establish a relationship between power set to the motor and velocity of the drive, and the latter is preferable to the former?

That said, velocity control is useful in addition to just position control;

Would you elaborate in the distinctions between position control and velocity control in the context of roadrunner? We have been visualizing PID in 1D scenarios, and imagine that the controller makes changes to the velocity based on the error computed from position—how are the two quantities controlled separately? We are probably not familiar with how the followers work, and how they use position—some explanation would be very helpful!

rbrott commented 4 years ago

So if I understand correctly, the goal of both drive characterization with DriveFeedforwardTuner and drive wheel encoders + tuning with DriveVelocityPIDTuner is to establish a relationship between power set to the motor and velocity of the drive, and the latter is preferable to the former?

Yes, that's the essence of their function. The goal is to translate wheel/shaft velocities into motor voltages. This can be accomplished with feedforward/open-loop control based on the (idealized) linear relationship between voltage and velocity (this can be augmented by considering acceleration and static friction through kA and kStatic), or it can be accomplished with feedback/closed-loop control by manipulating the voltage to achieve the desired velocity. The later feedback mechanism is preferable due to its robustness to changes in input voltages, friction, and other unmodeled effects/dynamics.

Would you elaborate in the distinctions between position control and velocity control in the context of roadrunner? We have been visualizing PID in 1D scenarios, and imagine that the controller makes changes to the velocity based on the error computed from position—how are the two quantities controlled separately? We are probably not familiar with how the followers work, and how they use position—some explanation would be very helpful!

The position and velocity controllers form a cascade where the output of the position controller becomes the input for the velocity controller. In this case, the position controller manipulates velocity to affect position error, and the velocity controller manipulates applied voltage to affect velocity error.

The trajectory followers are controllers that compute the robot's velocity and acceleration from the current trajectory and current position (they fall into the category of reference trackers). Some of the followers in Road Runner use PID with VA feedforward terms (the holonomic PIDVA trajectory follower source is pretty readable and understandable at a high level) while others use more sophisticated techniques.

EddieDL commented 4 years ago

@rbrott thanks again for all of your help. I am going to continue to keep this open so it reminds me to work on some suggested improvements to the docs (not sure if there is a better way to manage that).

We still have problems with the tuning, but I am going to open a separate issue about that.

@Calvin-Xu thank you for your addition to this thread, you asked some great questions that helped me understand this from a different perspective.

shishghate commented 4 years ago

Ahh... So does the following sound like a reasonable sequence of actions?

  1. Plug in all of the drive wheel encoders.
  2. Remove the custom localizer.
  3. Tune the kV, kA, kStatic and ensure all settings in DriveConstants apply to the drive wheels.
  4. Disconnect the drive encoders and connect the dead wheel encoders.
  5. Ensure your localizer configuration matches your dead wheels.
  6. Configure your custom localizer.
  7. Tune your PID.

@EddieDL , We are also embarking down this path, and did these steps work for you? You also mentioned that your encoders were not on center. Were you able to get them to work with a non 0 x position?