FRC Simulator Issue

I am working with the simulation and I have an auto routine which drives forward a distance, stops, rotates 180 degrees, then drives back the way it came. The rotation is to the left 180 degrees with the same power level on each wheel, negative on left positive on right, which causes our robot to rotate left. Now with the same power on each motor the robot should rotate pretty much around the center point of the robot, with little translation in any direction (which the real robot does). One would expect the encoder counts of each wheel to change a similar amount, left down and right up.

However, in simulation the encoder counts of each wheel are not similar as one would expect. The right encoder reports twice the counts of the left motor. This results in a position translation in the Y direction because the rotation is in effect not around the center but more around the left wheel. If one observes the test, the real robot drives forward, stops, rotates 180 degrees, then drives back over the same path. These two paths should be very close to the same. But in the sim, the path driven back is translated upwards in the Y direction, so the path back is offset from the path out.

The question is why, with equal power but opposite sign on the motors, do the l/r encoder counts returned by DifferentialDrivetrainSim show dissimilar changes, 50% off?

The left encoder is dropping counts. Is this in one specific direction?

Good question. I will test that report back.

So switching power signs to rotate right 180, the encoder counts are again off by 50% ish but on opposite encoders, more counts on left than on right. So it would appear that the problem is related to the inside wheel…?.. This causes translation in the -Y direction.

Is your code posted publicly on GitHub somewhere? It can also be helpful to print the numbers going directly into your setInputs() call to make sure something isn’t being added by accident in the middle.

The code is extensively instrumented and I am watching the power setting pulled from the motor controller and sent into the DifferentialDrivetrainSim and the power is constant at each simulationPeriodic call. The code is a full command based control program for 2020 robot with simulation grafted into it. It uses NavX and SRXMagenetic Encoders read through the TalonSRX interface. We have our own wrapper classes for those components so it was somewhat easy to plug the simulated encoders and gyro into those wrappers and get the complete sim working. NavX and SRX encoder sims are working fine. Note that the encoder counts are being traced from the analog gyros passed to EncoderSim, not our SRXencoder sim. Given all that, its not a trivial read. This code is a conversion of our previous SampleRobot based code. If you want to wade through all the code you can find it here GitHub - ORF-4450/Robot21C: Command based robot code for FRC Team 4450 (ORF) 2021 robot.

While we are at it, I am also observing that when I turn motors off, with brakes ON, the robot will still coast quite a ways before stopping. A related issue is that I had to set the MOI to 1.0 to get sim behavior to come close to actual robot behavior. I had real problems with over rotations because the sim bot would not stop turning even though my pid controlled turn had ramped the power down to zero. Now I am doing an arc drive and I ramp the power down to zero as new heading is reached but robot runs on after power = 0 with brakes on.

    sim.setInputs(4, -4);

    // 10 seconds should be enough time to verify stability
    for (int i = 0; i < 500; i++) {
      sim.update(0.020);
    }

    System.out.println(sim.getLeftPositionMeters() + ", " + sim.getRightPositionMeters());
20.216779418064753, -20.220588342829487

A quick check shows that the encoder distances produced by the sim are correct and as expected (the slight deviation of ~4mm is from measurement noise added via the constructor), so I suspect this has to do with a resetting issue somewhere in your code. I’ll have a look into your setup tomorrow morning as it is currently pretty late here.

Edit: with no noise, the results are 20.216430007914674, -20.216430007914674

Your test code has given me a couple of ideas on things to check. I will do that in the morning and get back to you. Save you digging through our code if I can find it.

So after more investigation I found nothing that changes the result. When I rotate by setting same power with dissimilar sign, the distance traveled values returned by the sim are off by 50%, with the inside, or backwards travelling wheel reporting the lower distance. Note that there is no reset in my code after the drive forward stops as encoder counts are not used in rotation function. I did try resetting the encoder counts as a test but same result. Note that in my code I “reset” the sim (to get reset encoder counts) by calling sim.setPose with the current pose of the robot. This is the only way I could get it to work. Is interesting that resetting the encoders passed to EncoderSim has no effect because the next pass through simPeriodic will just stuff the sim distance into EncoderSim. You have to reset the sim to get reset encoders (unless I just don’t understand this stuff). In any case resetting does not appear to be a factor in the problem I am observing.

I would also like your take on the issue with the sim continuing to report substantial movement after I have set power to zero (with pid driven ramp down to reduce momentum) and with brakes on. I don’t see where the sim takes motor braking into account.

Can you go into more detail about this? If your program involves moving forward in a straight line first, both your encoders will report the same value (e.g. 10 m). Then when you spin counter-clockwise without resetting, your encoders will report e.g. 7 m and 13 m (delta of 3 m for the spin).

I don’t understand whether you are talking about this discrepancy (which is expected) or something else. I tried to run your code but I ran into several issues with your library not finding a properties file (I suspect this has to do with using backslashes in looking for the file) and certain vendor libraries not being available on macOS.

We have noticed that the simulator’s brake mode modeling is not super accurate compared to the real-world. If you set motor power to 0 from a relatively large value, coasting behavior is expected; ramping this should help. We have several examples that use differential drive simulation to follow trajectories and they don’t have significant coasting behavior because the trajectory ramps down the velocity setpoint.

Can you provide some data on how much the robot coasts, the previous voltage, etc. when you set the voltage to 0?

After looking into this a little more, I believe I may have something. To test, I wrote a simple program to drive forward for one meter and then turn left counterclockwise 90 degrees. Both of these commands are hardcoded to take 2 seconds to complete.

I then plotted the encoder value and motor % on the simulator GUI:

You can see that when the motor percent is set to 0 (red line), the encoder position continues to increase due to the robot’s inertia. You are correct in that brake mode would cause different behavior on the real robot; however this is a limitation of the current physics simulator (in that it doesn’t simulate the effects of brake mode accurately).

Because of the 2 second delay, the robot mostly comes to a stop (as evidenced by the flattening encoder position) before rotating. In this case, the encoder position behavior is as expected (see prints in the bottom left). If however, you start rotating immediately, some of that forward momentum will cause your inner wheel to keep moving forward for a while before that velocity eventually becomes negative – I strongly suspect this is the cause of the discrepancy you observed earlier.

Code: https://gist.github.com/prateekma/bcbb9da68b70e892c6f435c0683f0331

We will look into simulating brake mode when motor output is zero to more closely match the behavior on real robots when brake mode is set. I opened a tracking issue here: [wpimath] Add brake mode physics · Issue #3056 · wpilibsuite/allwpilib · GitHub

1 Like

Thanks for that feedback. I will investigate the effect of a delay between stopping forward movement and rotating.

But this and the braking issue speaks to a problem I have been having all along, momentum. Note in the case of forward then rotate, my code uses a PID control on the forward driving to ramp down motor power as target distance is approached. In my trace I can see motor power going very low to zero as bot approaches distance target. However the sim bot continues to travel forward quite a bit. In testing before this post, I had to reduce the MOI value to 1.0 to get the sim bot to behave anything like the real robot. I may not know what I am doing but this seems incorrect. Note that the sim bot continues to move with low power inputs, inputs that on the real robot don’t overcome resistance of the drive train, or when power levels are low, the real robot stops.

The upshot of this is that the sim bot and real bot are quite different. Now I would expect some difference but what I am seeing seems out of line. Again, I reduce power to quite low values trying to stop robot momentum overrun and reduced the MOI value which should help but the sim bot drives on…

So I will do more testing and see if I can characterized this with measurements that would give you something better to respond to.

I had big problems with over rotation on my turns that (again pid controlled) which led to reducing the MOI until behavior approached something like the real robot. I still had to tweak the P factor on my rotation pid to get a clean sim turn.

1 Like

Ok. So you are correct. If I put a 10 second wait between the drive forward and rotate commands, the turn is correct, same encoder counts added to one side subtracted from the other. So that solves the cause of the translation on rotate issue, coasting still happening as the rotation command starts.

As I look at the traces from this test I find that after the end of the drive forward the sim bot continues to move forward for 2.84 seconds and travels .3317 meters before stopping movement. Now if I was at full requested power (50%) then went immediately to zero then I would expect a coast forward and the values are not outside what the real robot does. BUT, I use a PID controller to reduce power smoothly to reach zero power as target drive distance is reached. The trace bears this out as you can see lowering power levels. The forward “coast” of the sim seems to be too much and is not what the real robot does (it slows to a smooth stop without coast). Note that the pid reduced power levels reach a level that would not cause the real robot to move but the sim bot moves at any power level. Increasing MOI might help ignore low power as power is increased from zero. But higher MOI then makes the sim bot coast way too much. In the real robot a lot of the relationship between power and movement is not just inertia but the mechanical resistance in the drive train.

Now .3317 meters is not the end of the world but does hamper simulating precise autonomous movements. I also have another test where the coast is more severe, I will get the numbers for that and pass them along if they are out of line with the numbers mentioned here.

Of more concern might be having to wait almost 3 seconds to get rid of coasting effects if a precise turn is needed. Again, maybe the coast effect on the turn can be ignored for many cases.

What are your thoughts on this? This seems problematic especially if braking is not supported.

So one more test. This is driving in a curve at 25% power and 15% rotation factor. Again a pid controller is used to reduce power as curve reaches target heading. In this case after power has been ramped down to zero and the curve command has ended as its target has been reached, the sim bot continues to accrue movement for 3.25 seconds(!) and travels and additional .47 meters. This is way off.

Here is a plot of motor power level 0-1 against distance meters from the sim on the simple drive forward and stop. May this will help decide if the coast is reasonable or not. I am thinking there needs to be some aspect of the sim that represents resistance in the drive train separate from MOI, but I am hardly an expert on any of this.

A related question: in doing the plots, the encoders appear in the DIO device list but do not show a drop down for their properties and can’t be added to the plot. I had to put the encoder distance value into an NT variable to plot it. I expected I could just plot the encoder right from the sim like I did with the talon motor controller.

You should be able to go to Hardware | Encoders to show the Encoders window and expand the encoder detail from there.

Whoops…my bad.

So, I have been doing all this sim testing without access to our real robot. I guessed at the overall gearing reduction. Yesterday I finally got access and measured the reduction and the real robot was quite a bit different than my guess. So fixed that and tested the sim alongside the machine and after some tweaking they are behaving close enough that I will end this thread and move on to the next project. It makes sense that the reduction would have an effect on the coast after power off.

Thanks for all the feedback.

1 Like