SysID of Falcon with Negative Ks

I have captured SysId information for a Falcon 500 using .hoot and wpilog information. When the data is analyzed it results in a negative Ks value.

  1. Is this an issue? Does it mean my captures are not good?

  2. Since it is negative, do I still use it in the SimpleMotorFeedforward object or ignore?

Log Files
falconID.zip (185.5 KB)

SysID results

Your data are fine, kS is too small to measure.

Are you using Phoenix 5 or Phoenix 6?

Phoenix 6

so just call it zero?

Yep. I’m a little concerned about the signal timing, though - on phoenix 6 there should be no appreciable velocity measurement delay, but yours is reporting ~160ms. The timestep versus time graph is very funky, too - what are your CAN frame timings?

Interesting. I havent changed anything from the default values.

I basically downloaded the SysId template and changed the code to work with falcon using voltage controlled output with no FOC.

This is all I am doing to configure the Falcon

   configs::TalonFXConfiguration falconTalonFXConfigs{};

   /* Configure the leader motor with the parameters stored in          */
   /* constants.                                                        */
   falconTalonFXConfigs.CurrentLimits.StatorCurrentLimit       = 40.0;
   falconTalonFXConfigs.CurrentLimits.StatorCurrentLimitEnable = true;

   falconTalonFXConfigs.MotorOutput.NeutralMode = ctre::phoenix6::signals::NeutralModeValue::Brake;

   /* Apply the configuration changes to the motor under test           */
   /* controllers.                                                      */
   m_motorUnderTest.GetConfigurator().Apply(falconTalonFXConfigs);

And this is the initialization of the sysid

    /* Initialize the Falcons as the motor under test on the RoboRio's  */
    /* CAN bus.                                                         */
    ctre::phoenix6::hardware::TalonFX m_motorUnderTest{kFalconMotorCanId, kFalconBusName};

    /* SysId standard routine.                                           */
    frc2::sysid::SysIdRoutine m_sysIdRoutine{
        frc2::sysid::Config{std::nullopt, std::nullopt, std::nullopt, std::nullopt},  // use default configuration
        frc2::sysid::Mechanism{
            [this](units::volt_t falconVoltage){ m_motorUnderTest.setControl(VoltageOut{falconVoltage, false}; },
            [this](frc::sysid::SysIdRoutineLog *log){},  // log nothing, should be logged using URCL
            this}};

Here is the source files if you want to take a closer look anything specifically:

src.zip (6.0 KB)

My process for gathering data was:

  1. I ran the tests (using joystick A,B,X,Y).
  2. Log was saved to flash drive (which was kind of an old flash drive if you think that could cause an issue).
  3. I opened log in tuner X
  4. regexprs for keys I need
  5. exported out of .hoot to wpilog
  6. Opened in advantage kit (to combine Wpilog with Hoot export so I could get the system base string and 1 file), which was my best guess of how to get it.
  7. Opened in SysId, selected base string added MotorVoltage, Position, and Velocity then ran analysis. (also using SimpleMotorModel and Rotation units)

Also of note, this test was ran on an old RoboRio 1 we had available for testing off robot.

Just so you have more of the data…

-R

You should probably use the alternate test state callback in SysIdRoutine.Config to declare the SysId test state directly to hoot.

First I would like to say THANK YOU! for the time you are spending looking at this and your advice! :slight_smile:

Do you know if there is a specific way that the state needs to be written to the .hoot log?

Looks like the log Record State is passed in as a frc::sysid::State

I can’t find any documentation on what the SysId parser might be expecting for this to be turned into so that my SignalLogger::WriteXXXX() can output the correct format for the state.

It doesn’t really say explicitly in the API documentation or the SysID page for FRC.

I took a peek at the wpilog file and it looks like maybe this needs to be a string written to the .hoot based on state. Something like “quasistatic-forward” etc.?

-R

1 Like

The state is an enum whose value is provided by the SysIdRoutine. There should be a Hoot function that just accepts the enum as-is.

@TytanRock can confirm?

1 Like

The suggested way to setup the CTRE phoenix6 SignalLogger to work with SysId in java is here.

There isn’t a C++ example (it would be nice if there was one, really, I don’t think it would be a huge effort to write) but I assume the process is the same, convert the enum to a string (using its name) and then write the string to the SignalLogger.

I don’t believe there is a specific SignalLogger function that accepts the enum directly, but WriteString does exist in C++ here.

1 Like

We do not have a function that accepts the State enum as-is, but it should be as simple as calling frc::sysid::SysIdRoutineLog::StateEnumToString and passing that string to SignalLogger::WriteString.

3 Likes

Thank You! This is super helpful.

using setUpdateFrequencyForAll(250Hz) will also probably be a good thing to add.

Ill convert this over to C++ and post it back up here and you can use if you want.

-R

2 Likes

All updated.

My Ks is no longer negative, but my Acceleration R^2 went down quite a bit but still looks like it is in the acceptable range?

Here is the SysID Output:

Here is the log file .hoot and converted to .wpilog (which I dumped directly into SysID now that is has built in state information).
LogFiles.zip (684.6 KB)

@HarryXChen and @bhall-ctre

Here is a C++ version of your Java code (hopefully it can be useful to the community).

PhoenixSysId.zip (57.8 KB)

2 Likes

This looks like much more accurate data. The “sim velocity r^2” term is the real metric of overall fit quality to look at.

The decrease in the acceleration r^2 might be because the more-accurate sampling captures more high-frequency system noise that the model doesn’t account for, but i’m merely spitballing here.

1 Like

Great, once again I really appreciate your help on improving my capture!!

1 Like

I have a new flywheel mechanism today to characterize. This one is geared up 2:1 in attempt to get more speed. This one take a lot longer to spin up to full speed and I am back to having a negative Ks. (NOTE: I am using the same C++ software as I used to characterize the previous version).

I have attached the log files below:

rio_2024-02-12_10-47-22.zip (785.2 KB)

And a screen shot of the SysId output.

The R^2 values seem to be in line, but it seemed like you also looked at some other numbers to evaluated how well it worked? I am curious which other values are most relevant to making sure the capture was successful.

Also when I used the Kp that was calculated for CTRE, it doesn’t like it at all. It oscillates wildly with that value (105.08) and any value over about 0.35. After further investigation, I am using VelocityVoltage type control, and I think when it is set to CTRE it is assuming DutyCycle units. Looks like (Pro) is using Voltage, so I will use that instead.

I would love your opinion on this data. Thanks Again!

-R

1 Like

Do not use the “CTRE” preset for Phoenix 6, those are the values used for Phoenix 5. Instead, you can use the default preset and change the “Controller Period (ms)” to 1.

2 Likes

Got it. That number looks a lot better. Thanks for you help!

The dynamic test looks a bit strange - are you running any current limits?

Overall, the fit looks to be good, so I wouldn’t be overly worried.

1 Like

Yes, I have a 35 A stator current limit. I can see that it does hit that limit as it spins up (thru telemetry on advantage scope). It is on a 40A fuse, is it ok to push that number up to a higher current limit? I wasn’t sure how much I could push the fuse before it turned off.

-R

40A breakers can sustain much more than 40A for short periods of time. See this post for more details.