How to check if CTRE Phoenix library has finished initialization?

Shortly after starting my robot program (in the simulator) I see this log message:

[phoenix] Library initialization is complete.

Using the Phoenix SDK for Java, how can I tell whether this initialization has occurred? I need to know if the TalonFX controller is ready to handle voltages, accept new sensor positions, etc. before running the control loop on the roboRIO.

All that stuff should be happening at process startup before any of your code is really running, though I don’t know the exact timing.

I’m curious why you ask though. Are you running into specific issues? Or is this a solution in search of a problem?

1 Like

The Phoenix library seems to initialize asynchronously in a separate thread.

Some of our controller code runs in Subsystem#periodic() and we’ve noticed problems occurring when reset a sensor position, but don’t see its new value until after Phoenix init.
As a temporary fix, we wrapped our controller code to only run while the robot is enabled which is fine as long as the driver doesn’t enable before Phoenix init.

1 Like

Well one way to do it is to set the sensor position to a specific value, and then call the sensor value. If it changed, the library has been initialized, and if not, keep waiting.

Will the sensor value only start to update once the library has initialized? If so, this is probably what we’ll do if there’s no more direct way to check Phoenix init status.

Ideally, the CTRE motor controller and sensor constructors should be waiting until the backend thread is done initializing. At the moment, Resource acquisition is initialization - Wikipedia is being violated (RAII is the idea that after a class’s constructor has finished, the class is ready to use).

I suggest filing a bug report with them.

1 Like

FYI this initialization message is not required to use any of the CAN device classes in Phoenix - what this message is indicating is the initialization of Phoenix background tasks & management has been verified to be complete.

Setting, configuring, or receiving CAN data using class functions is not affected by when this message happens. Once you’ve instantiated the device object, it’s ready to use.

You’re not the first person to have this interpretation of the message, however, so there’s definitely some room for improvement in the message text to make it less confusing.

1 Like

This is not quite what we’ve experienced.

Here’s a video demonstrating the problematic behavior prior to the init message being logged.

Here’s what’s happening

  1. The simulated robot program starts
  2. As part of a subsystem constructor, the sensor position of a Falcon 500 is set to 0.
  3. I connect the dashboard (the graph on the right) to the simulator and we can see the currently read position of ~1.2 radians.
  4. At the exact moment the Phoenix library prints its “Library initialization complete” message we see the graph suddenly change, as the simulated Falcon 500 acknowledges the .setSelectedSensorPosition() call.

I expected that .setSelectedSensorPosition() would immediately set the sensor position, not queue it up to be applied once the Phoenix library has finished init.

Have you seen this same behavior on the roboRIO?

I have not had a chance to attempt reproducing this on actual hardware yet.

That should not be happening, even in sim. I mocked up a minimal test to check if it was the case and wasn’t able to reproduce the problem.
For reference, I created a new timed skeleton java project, added the CTRE vendor library, and added/modified the following code in Robot.java, then proceeded to simulate:

  WPI_TalonFX _1 = new WPI_TalonFX(1);
  int time = 0;

  @Override
  public void robotInit() {
    System.out.println("Set position error code: " + _1.setSelectedSensorPosition(452));
  }

  @Override
  public void robotPeriodic() {
    System.out.println("Position is " + _1.getSelectedSensorPosition() + " @ " + time++);
  }

This produces a stream of text to the terminal, so I’ll focus on the bits that matter

********** Robot program starting **********
Set position error code: OK
********** Robot program startup complete **********
Position is 0.0 @ 0
Position is 0.0 @ 1
Position is 0.0 @ 2
Position is 0.0 @ 3
Position is 452.0 @ 4
Position is 452.0 @ 5
Position is 452.0 @ 157
Position is 452.0 @ 158
[phoenix] Library initialization is complete.

Position is 452.0 @ 159
Position is 452.0 @ 160

You should be able to reproduce my test and get similar results.

The test indicates that position is not “gotten” until 4 loops have passed, about 80ms. While this is longer than I’d normally expect (we simulate the can frame latency, so I’d expect an update 20ms after setting), I’m willing to believe part of it is due to the simulation library initializing. Regardless, the setter goes out well before the print and we see the feedback well before the print, indicating no relation to the feature and the print.

I went back and modified the example to verify the 80ms latency was related to initialization

By changing the position on teleop init and printing the time I changed position

  @Override
  public void teleopInit() {
    System.out.println("Changing position @ " + time);
    _1.setSelectedSensorPosition(5489);
  }

Giving me the following text

Position is 452.0 @ 103
Position is 452.0 @ 104
Changing position @ 105
Position is 452.0 @ 105
Position is 5489.0 @ 106
Position is 5489.0 @ 107

I suspect you’re seeing this behavior due to something you’re doing in your code. Would you mind sharing your code so that I can attempt to reproduce what you’re doing and possibly find the source of the problem?

1 Like

Thanks for testing this! I ran your project locally and same as you, I could not reproduce my issue. I also observed a delay of 80-100ms before the program began printing 452.0.

We’ve also noticed 60-100ms latency with all Talon FX operations while testing in the simulator (haven’t had a chance to test on actual hardware yet). I’ve tried a bunch of stuff to reduce it without any success: decreasing robot period, decreasing status frame periods, etc. I wonder if that latency issue is related to this one.

Absolutely! Our code is on GitHub here on the lifter-sim branch. We instantiate the TalonFX instance here and we set the sensor position here.
You should be enable to simulate the project locally without any issue. Printing the current encoder position to the console in the subsystem’s periodic function should be fine for debugging, but you can also use the Advantage Scope log viewer if you’d like to take advantage of our existing log calls.

Thanks again for helping us out with this!

1 Like

Sorry for the wait, I got caught up with releasing 5.21.2, but I have some answers for you.
There were two things going on that half canceled each other out.

The first thing was how you were setting sensor position, it’s an order of operations thing.
You set sensor position on subsystem construction, but you update the simulated integrate sensor position on subsystem periodic.
This meant you were setting the sensor position before the device knew where it was, so you were setting it to the wrong value.
I copy-pasted your io.updateInputs(inputs) call just before seedSensorPosition() and that seemed to fix your issue.

The second thing was a bug in our API that caused configs to get re-sent around the time the Phoenix-Initialization message went out.
Setting the sensor position is done in the same manner as configuring a parameter on our motor controllers.
This meant the setSelectedSensorPosition frame went out a second time around when the Phoenix-Initialization message printed, which happened to “fix” your bug and obscured the real problem.
This bug has been fixed and is available in our 5.21.2 release that’s just released.

Hope this helps!

1 Like

Wow, what a good observation, thanks so much for your help in this!

While I still have your attention, do you think you could confirm if the 80ms latency with the TalonFX (ex. .setVoltage(12), 80ms elapse, .getMotorOutputVoltage() == 12) is expected behavior during simulation?


Edit: It looks like the latency is only an issue shortly after starting the robot simulation, which lines up with what you were saying. I haven’t done any thorough testing of this, but it seems like there’s only 20ms latency after giving the robot a few seconds to ““warm up””. Was this latency issue possibly fixed from updating the vendordep?

Correct, I can look further into why the startup is taking that long, but I don’t think it’s necessarily an issue since it’s still relatively fast and only happens on startup.

That is the desired behavior, as that is what you’d see on an actual robot due to status 2 going out at 20ms intervals. If you need it sped up you’ll have to increase the status frame period, just like you’d have to on a real robot.

1 Like

Thanks for the info! 20ms is definitely enough for us to work with.