CTRE simulation discussion

Hi all, just wanted to open a thread for general discussion on the new CTRE simulation support.

I want to be able to teach my students how to implement the new Talon’s simulation support easily.
I will put here my understanding of it here and hopefully, we (I) could understand how to integrate it into the java/c++ command base framework while supporting real code execution when the time comes.

New release info:

The example that I will analyze here (motion magic)

My understanding - points:

  1. Creating a SimProfile class, all motor’s profiles will extend this class which includes run
    method (should be abstract prob) that will update the SimCollection about the motor’s current state based on specific physic’s profile implementation
    Example

  2. Creating a class that represents the specific motor physic’s profile which extends the SimProfile class for each motor (unless they are in follower more) in each system in our robot (different physics for each system so different profile)
    Example

  3. PhysicsSim class, manager class, creates and holds all of our motors profiles, will be updated (run) in Robot.java simulationPeriodic method.
    Example

  4. Initializing PhysicsSim: pushing talons so PhysicsSim will create and hold the appropriate profile in simulationInit at Robot.java
    Exmaple

  5. Updating PhysicsSim: in simulationPeriodic at Robot.java update (run) PhysicsSim to update all active profiles
    Example

Physics dive in: (I will add a dive in on how to tweak the physics params if this thread will be active)
TBC

Conclusion:

From my understanding, the main changes are:

  1. TalonSRXSimCollection - through this collection teams will update the motors about their current state
  2. Phoenix Tuner simulation support which includes Plotter, Self Test Snapshot, Control, and Configs
  3. Support for simulated device-to-device features, such as follower mode and remote sensors/limit-switches
  4. Integration with WPILib’s simulation GUI when using WPI_* classes

Full list of features

So the provided example shows a way to update the TalonSRXSimCollection, which is all we need to run a close loop control in simulation mode (?) :slight_smile:

@ozrien Any input will be more than welcome :smile:

1 Like

Thanks for this thread, the links were helpful. I was going to try to simulate our Falcon 500s but then I saw this:


I guess I’ll try to see if I can adapt their TalonSRX simulation code example to work for a TalonFX but I’m not sure how much of it is in common.

So the provided example shows a way to update the TalonSRXSimCollection , which is all we need to run a close loop control in simulation mode (?) :slight_smile:

That is correct. In order for closed loop control, soft limits, current limiting, etc. to work in simulation, users need to call into the SimCollection during simulationPeriodic() and update the appropriate values. The provided example simply demonstrates how users can do that.

Users that are simulating a robot remotely using the WebSocket interface, such as in Unity, should not call into the SimCollection, as values sent through the WebSocket interface are handled in our WPI_* classes.

1 Like

Nice! happy to see someone found this helpful, I would suggest looking at WPI own physics implementation

The idea is: activate the talon with closed-loop as usual, get the desired output, push it into the WPILIB physics obj (i.e ElevatorSim) and push the result into the SimCollection.

1 Like

Thanks. I think I’m going to have to wait until CTRE implements sim support for TalonFX or try to use some WPI_TalonSRX objects purely for simulation.

Yeah well, no reason to wait for TalonFX unless you really want to fine-tune the values so they will match your real robot, which I guess you don’t…

Just to let folks know, there’s a basic Java example for using TalonSRX simulation with WPI’s DifferentialDrivetrainSim:

2 Likes

Here’s my workaround code for TalonFX not supporting simulation yet. I just store the simulated encoder velocity and position in variables instead :slight_smile: .

How are the TalonFX close-loop works then? the close-loop isn’t being updated with the encoder values…

It doesn’t work :stuck_out_tongue:. It’s basically open-loop in the simulator. Idk of a good way of doing it and am just waiting for a CTRE update.

I’ve been thinking about throwing this in an example but you could do something like the following:

BaseTalon m_myTalon;

TalonSRXSimCollection m_myTalonSim;

robotInit() {
    if(IsReal()){
        m_myTalon = TalonFX(ID);
    } else {
        m_myTalon = new TalonSRX(ID);
        m_myTalonSim = ((TalonSRX)m_myTalon).getSimCollection();
    }
}

This would treat your FX like an SRX during simulation, and most of the methods are common.
You just wouldn’t be able to use anything that’s device specific, like stator current limiting or anything API calls that directly reference the integrated sensor (though selected sensor would be fine) - except within the IsReal() check. Also make sure you null check the SimCollection object just in case.

1 Like

I went this route in my SimulationPeriodic I do this:
m_talon->GetSimCollection().SetQuadratureRawPosition( sim_position);

for my encoder reading I tried these:
m_talon->GetSensorCollection().GetQuadraturePosition()
m_talon->GetSelectedSensorPosition()

when I test this… the GetSelectedSensorPosition() updates every 20ms, and for GetQuadraturePosition() it only updates every 100-200ms. I have not yet tested this on a real motor, but want to know how to set in simulation and get updates every 10ms if possible, without having to resort to simulation read variables. Thanks.

This matches what I expect - the update rates for signals match the update rates from CAN data on real devices. You can use the SetStatusFramePeriod function as normal if you want to change this update rate.

2 Likes

For a TalonFX, does changing the frame period for Status 2 mean that if the selected sensor is the integrated encoder, it will update quicker too or does the period for Status 21 also need to be set?

If the integrated sensor is the selected sensor, then changing the update rate of Status 2 will change the update rate of the value returned by the getSelectedSensorPosition/Velocity functions (which in this case will the the values for integrated sensor).

Changing the update rate of Status 2 will not change the update rate of any other signal groups, however, so the update rate of values returned by SensorCollection’s specific getter for integrated sensor will not change.

Keep in mind these are two completely separate functions - the Selected Sensor value is what you should use most of the time; that’s the value being used by your closed loop and reflects any inverts or phasing. The sensor collection methods exist to verify the raw value of the sensor and as a method to get raw sensor data when a given sensor is not the selected sensor.

1 Like