Differential Swerve - "the math"

There has been discussion thrown around CD, and to a small extent, our team, about the necessity of differential swerve.

Generally, I agree with this step, but as a programmer I have yet to find any real documentation of the math going on behind differential swerve. Looking at code hasn’t helped because it seems that teams use completely different math from each other, abstracted behind several layers of functions that make it hard to follow.

All in all, I’m looking to understand the math that goes on behind the scenes, including:

  • Determining a module’s angle (using integrated encoders, NOT the CAN-connected absolute encoder)
  • Converting a SwerveModuleState (target speed & angle = velocity) into target velocities for each motor

What I do understand is how to determine the module’s position and speed - simply averaging the position/velocity of each motor.

Given the lack of any real documentation I’ve found, I’d like to hear an explanation for the math necessary to control these aspects of a differential swerve module.

4 Likes

Don’t have an answer for you, I’m just curious why you don’t want to use the CAN connected absolute encoder for determining the module’s current angle.

I don’t believe that it is possible to know the wheel’s heading without an encoder measuring only that.

The reason for this is that the rotation of the module is directly related to the translation of the wheel. As such, if the wheel were to slip or skid, you lose your heading if only measuring using the motor built in encoders.

Alternatively, if you can somehow directly measure the wheels translation, you can figure out the heading based on the three encoder values you do have. It is vastly simpler mechanically to measure heading and deduce translation.

1 Like

Unless you set the status period really low and eat up CAN bus, there’s going to be delay between the actual heading of the wheel and the reading from the encoder, resulting in lower-accuracy odometry and PID. Integrated encoders are more reliable and faster acting.

Unless there’s something with differential swerve itself that negates this?

The absolute encoder would still be used to “seed” the angle of the modules like a traditional swerve (unless this isn’t possible with diffswerve).

Thinking about it now though, I suppose wheel skips do pose a greater problem for diffswerve.

I’m still interested in knowing the math behind converting target velocity to motor velocities. I’ve heard some people use DifferentialDrive but have no clue if this really “works”/how to implement it

1 Like

Plenty of teams in FRC control their swerve modules using only the CANcoder. It is really not that bad. Not sure where you got the idea that “delay” is really a problem. I guess CAN bus utilisation could be a problem, but that could be mitigated by putting the CANcoder on the high speed CANivore bus. CANcoders are pretty close to the lowest contributing device to CAN bus utilisation.

1 Like

We had our CANCoder set to 100ms status frame period. When driving straight and rotating fast (such as in an auton), we noticed significant drift (edging near a foot of lateral drift when driving 10ft forward while rotating).

We also would absolutely prefer to not use the CANivore if possible.

In that regard, I’m curious what “the” way for determining the module angle from each motor is. Similarly, I’m looking for the opposite: transforming a desired state into motor velocities.

As others have said, you want to control the position (rotation) for steering – use an absolute encoder here. These are cheap (in the context of swerve), easy to use, and work well. I don’t see any reason one would try to keep up with the steering angle using built-in motor encoders, and I expect any attempt to do so is just going to make this harder (and, in the end, work less well). I don’t think using the built-in encoder on a dedicated single steering motor is best-practice.

As for the math, this is where I’d focus. This, and worrying about the control loop latency. I’ve seen at least one paper that goes into this, here on CD…

EDIT: If you don’t want to use a CANcoder, don’t. There are multiple other options for absolute position sensing for steerng angle at this point.

2 Likes

This is bringing up more questions… Why don’t you want to use a CANivore?
I haven’t seen a rash of other teams who use the CANcoder for swerve report issues like this for odometry.
Also, you can use other absolute encoders that aren’t the CANcoder, and just connect them to the RIO.

Wheel skipping won’t affect module rotation. The difference between motor encoders should always be able to derive the heading of the module, unless a gear/belt slips.

I think you need to run cascaded PID loops. First, a loop on heading whose input is heading and output is desired motor velocity. Add/subtract that to the result of your desired forward velocity to get commands for each motor. Then run a tight loop on the motors to reach those velocities. There’s probably a much better ideal solution to this that takes advantage of characterization, but that’s the first thing that comes to mind. Feedforwards could be applied separately to the rotation component and translation component of the command.

2 Likes

I am not a programmer so don’t fully understand the nuances of PID loops, but (im fairly certain) the question of wheel skipping/module rotation is a mechanical question, not a programming one.

The best way that I can describe this is if you put both motors in brake mode, you could still turn the wheel (and the heading would change) or change the heading (and the wheel would turn).

We had pretty debilitating issues with it last season that took an extremely long time to solve, and spending $300 for an alternate solution when one already presumably exists is not a good decision.

1 Like

Using the built-in encoder lets us use the much more reliable 1000Hz PID control loops versus 50Hz loops for the RIO.

This is turning into nonsense ideological debate over a nonissue. I’m curious about the implementation, not the encoder…

The output, i assume, is thus half the differential between each motor?

What I don’t really understand is how exactly this is calculated. At this point though I assume it’s mainly a mechanical thing, I’m unfamiliar with the inner workings of differential swerve and am not entirely sure of what this looks like.

Sorry – I was tight for time and a little terse, which may have come across as a bit harsh and judgmental. I’m still short for time, but here’s a longer answer…

I don’t recall you explicitly saying, but it seems we are talking about using Falcons here. I’ll assume this in order to hold down the number of variables and keep things at least a little more focused. I’ll try not to make unstated assumptions.

The 10,000 ft. description of the problem is you need to control two motors. In the context of diff swerve, the control function for each motor will need input from at least one external sensor, whether this is something like a CANcoder, or the other (CAN-connected) motor. If you are not doing the math on the motor controller, things are a little different, but let’s start here, since this seems to be what you are thinking.

If you are going to do the math on the motor controller, the motors will also need the desired module state (typically, position for the steering angle and power/velocity/position for driving the wheel). And, the motor controllers will have to expose some means of running the desired math. This last point is important, it’s not as if you can legally change the motor controller firmware – even if you chose to go there.

For the moment, let’s not worry about the latency or update frequency of the desired module state – as a simplifying assumption, we can just say this is known everywhere and then come back to this assumption later, as needed. At this point, the control for motor A is going to be a function of the sensor for motor A and the sensor for motor B (no absolute encoder). Or, it is going to be a function of an external/absolute steering angle sensor. In the latter case, it might also need the sensor for the local motor, depending on what kind of control is desired for driving the wheel.

Now that there’s a general outline, we can turn to response/latency in the control loop. With an absolute position sensor on the turn angle, the mechanical side of things is pretty optimal. When using the built-in motor encoders, there’s backlash. The resolution of these encoders also differs, so there’s going to be a different quantization error. And, you still have to get the sensor data from one motor to the other, across CAN (and not CANivore-rate CAN, based on info in this thread). The 1000Hz (1 ms) PID loop is starting to be suspect…

Importantly, it isn’t the frequency you really care about, it’s the latency. Sure, a higher frequency can help average and worst-case latency, but it doesn’t get around the CAN transfer (there are other sources of latency as well). Running a really fast control loop that has stale feedback data isn’t really where you want to be. And now, we come to the question of what math can the motor controller actually do with the two inputs (there’s no provision for working with three on the Talon FX, AFAIK).

I have no expertise with Talon FX and can’t even claim to have used one. There’s also the two-API (Pro) thing. But, the most recent thing I recall in this area is Auxiliary Closed Loop PID[1]. This does let you use two sensors to control a Falcon. The question then becomes: “Can Talon FX do the necessary math with the two sensors?” I don’t know the answer, and until the math is set out, it’s impossible to know. But, what can be done here is limited – you don’t get to run arbitrary math on the motor controller. Is this a problem? Maybe; it’s certainly a risk.

So this is what was behind my earlier comment on not being so quick to jump to running diff swerve control on the motor controllers. Let’s briefly turn to the alternative of running on the RIO. To start, one can get way more than 50Hz (20 ms) if needed/desired, you just have to do a little more work. I’m not going to go into this here, but it’s been done and written up on CD.

In this scenario, you can use something like an SRX Mag Encoder – no CAN from here to the RIO. The sensor data is processed by the FPGA, which is going to be very low latency. The RIO can do arbitrary math. And, the RIO can send CAN messages to the motors with good latency, with CAN accounting for the bulk of this. This does not seem like an option to write off and not consider so early in any analysis.

Don’t want to run the control on the RIO? Want an advanced project – or maybe something to request of a vendor? Run the control on a CAN-attached absolute encoder and have the two motors “follow” a pair of outputs it publishes. Send the module state info to the encoder, have it do the computations, and send the follower data. You can legally change firmware on a sensor, and the devices these use have firmware development toolchains you can download. At this point, you can do what you want. I actually think the RIO would be the thing to do right now, but this might be a cool offseason project for a team looking for a high ceiling for S/W, given the interest and people.

I hope this helps. I still think you do not want to rule out using an external absolute encoder, and I hope this explains why a little more clearly.

3 Likes

I’ve done a bit more research on existing code and understand a bit more what @asid61 was talking about regarding the PID loop. That is, you run each motor at a specified velocity (based on the requested meters per second) and add or subtract a PID-calculated differential, where you subtract the differential from one motor and add it to the other.

So now I understand this part–but the PID calculation does require knowing the difference between the requested angle and the current angle. After closely reviewing existing code I understand more the rationale behind using the absolute encoder. I’ll probably do some testing to determine if the CAN usage of a CANCoder is as big a deal as I think it is.

At this point I have one question:

What goes behind the actual PID calculation for heading-to-differential calculations? All I’ve really found is team code with seemingly arbitrary PID loops running a P of 5.0 or something and responding to the difference between desired and actual heading in degrees.

I’m not sure how to make this more clear, I’m just confused on how to actually determine the necessary PID values, either empirically or through theoretical calculations.

@nuttle - thanks for the long-form explanation, I understand things much better now. I’ve realized both through this comment and looking at team code that maybe a CANcoder as the sensor maybe is “the way” :smiley:

Also, I assure you i did not assume malice or harshness from your comment! (The only reason I got a little harsh was because I’ve witnessed so much stupid, nonsensical ideology debates within code that I’ve come to be quite sensitive to what I deem as ideology pushing…)

1 Like
4 Likes

I’m not sure this is true. If you know the starting angle of the module, then the rotation angle of the module at any given time is based on the difference in total motor rotations between the two motors (accounting for gear ratios, of course).

Think of the case where the module is sitting on the bench not touching the ground at all. In a sense this is a case where you are constantly slipping or skidding. You can still determine (and control) the module rotation angle for this case.

You still need an absolute encoder to determine the starting angle. And since you have it, you could use it for control from that point on. But, you might find that the control loop is more stable if you are using motor encoders. We have found that to be true for traditional swerve allowing us to use faster rotational speeds. It would not surprise me that it was also more stable to use the motor encoders for diff swerve to get a more stable control loop.

1 Like

Thank you for this reply. After looking at it this way, I see that the absolute encoder is not necessary for anything other than zeroing, which could be done in another way.

2 Likes

Note that zeroing sometimes does need to happen mid-match and having the absolute sensor available to make it a sub-20ms process has value.

(192 had a automated mechanical zero on custom swerve in ~2018(?)… That took about six seconds and so was extremely noticable when they needed to do it. Mechanical issues lead to rezeroing frequently… Perhaps not as much a concern in 2023)

1 Like