Configuration ============= Devices support persistent settings through the use of "configs". .. tip:: Configs can also be configured using Phoenix Tuner X. See :ref:`docs/tuner/configs:tuner configs` for more information. Configuration Objects --------------------- There are device-specific ``Configuration`` classes that group configuration data of devices in a meaningful way. These classes are `Passive Data Structures `__. One example is ``TalonFXConfiguration``, which has subgroups of configs such as ``MotorOutputConfigs``. The configs can be modified through public member variables of the ``Configuration`` object. The complete list of configuration objects can be found in the API documentation (`Java `__, `C++ `__, `Python `__). .. note:: Phoenix 6 utilizes the `C++ units library `__ and, optionally, the `Java units library `__ when applicable. Using the Java units library may increase GC overhead. .. tab-set:: .. tab-item:: Java :sync: Java .. code-block:: Java var talonFXConfigs = new TalonFXConfiguration(); .. tab-item:: C++ :sync: C++ .. code-block:: c++ configs::TalonFXConfiguration talonFXConfigs{}; .. tab-item:: Python :sync: python .. code-block:: python talonfx_configs = configs.TalonFXConfiguration() Modifying Configurations ^^^^^^^^^^^^^^^^^^^^^^^^ Configuration objects are mutable, so they can be saved in a member variable and reused. Additionally, configuration objects support modification using method chaining. This can be useful for constructing them as a class member variable or at compile time. In Java, this can also be used to provide unit types. Configuration and config group objects can also be cloned, making it easy to share common configs across device configurations. .. tab-set:: .. tab-item:: Java :sync: Java .. code-block:: Java final TalonFXConfiguration commonConfigs = new TalonFXConfiguration() .withMotorOutput( new MotorOutputConfigs() .withNeutralMode(NeutralModeValue.Brake) ) .withCurrentLimits( new CurrentLimitsConfigs() .withStatorCurrentLimit(Amps.of(120)) .withStatorCurrentLimitEnable(true) ); /* create a copy with a different invert */ final TalonFXConfiguration leaderConfigs = commonConfigs.clone() .withMotorOutput( commonConfigs.MotorOutput.clone() .withInverted(InvertedValue.Clockwise_Positive) ); .. tab-item:: C++ :sync: C++ .. code-block:: c++ static constexpr configs::TalonFXConfiguration commonConfigs = configs::TalonFXConfiguration{} .WithMotorOutput( configs::MotorOutputConfigs{} .WithNeutralMode(signals::NeutralModeValue::Brake) ) .WithCurrentLimits( configs::CurrentLimitsConfigs{} .WithStatorCurrentLimit(120_A) .WithStatorCurrentLimitEnable(true) ); /* create a copy with a different invert */ configs::TalonFXConfiguration leaderConfigs = configs::TalonFXConfiguration{commonConfigs} .WithMotorOutput( configs::MotorOutputConfigs{commonConfigs.MotorOutput} .WithInverted(signals::InvertedValue::Clockwise_Positive) ); .. tab-item:: Python :sync: python .. code-block:: python self._common_configs = ( configs.TalonFXConfiguration() .with_motor_output( configs.MotorOutputConfigs() .with_neutral_mode(signals.NeutralModeValue.BRAKE) ) .with_current_limits( configs.CurrentLimitsConfigs() .with_stator_current_limit(120.0) .with_stator_current_limit_enable(True) ) ) # create a copy with a different invert self._leader_configs = ( copy.deepcopy(self._common_configs) .with_motor_output( copy.deepcopy(self._common_configs.motor_output) .with_inverted(signals.InvertedValue.CLOCKWISE_POSITIVE) ) ) Future Proofing Configs ^^^^^^^^^^^^^^^^^^^^^^^ There is a corner case with configs where the device may have firmware with newer configs that didn't exist when the version of the API was built. To account for this problem, device ``Configuration`` objects have a ``FutureProofConfigs`` (`Java `__, `C++ `__, `Python `__) field. Configurator API ---------------- Device objects have a ``getConfigurator()`` method that returns a device-specific ``Configurator`` object. The ``Configurator`` is used to retrieve, apply, and factory default the configs of a device. .. note:: The ``getConfigurator()`` routine can be called frequently without any performance implications. The device-specific configurators have type-specific overloads that allow for the widest variety of device-compatible configs. As a result, the caller can pass the entire device ``Configuration`` object or just the relevant subgroup of configs to the ``Configurator`` API. .. tab-set:: .. tab-item:: Java :sync: Java .. code-block:: Java var talonFXConfigurator = m_talonFX.getConfigurator(); .. tab-item:: C++ :sync: C++ .. code-block:: c++ auto& talonFXConfigurator = m_talonFX.GetConfigurator(); .. tab-item:: Python :sync: python .. code-block:: python talonfx_configurator = self.talonfx.configurator Reading Configs ^^^^^^^^^^^^^^^ To read configs stored in a device, use the ``refresh()`` method to update a ``Configuration`` object. The example below demonstrates retrieving a full ``TalonFXConfiguration`` (`Java `__, `C++ `__, `Python `__) object from a ``TalonFX`` device. .. warning:: ``refresh()`` is a blocking API call that waits on the device to respond. Calling ``refresh()`` periodically may slow down the execution time of the periodic function, as it will always wait up to ``DefaultTimeoutSeconds`` (`Java `__, `C++ `__, `Python `__) for the response when no timeout parameter is specified. .. tab-set:: .. tab-item:: Java :sync: Java .. code-block:: Java var talonFXConfigurator = m_talonFX.getConfigurator(); var talonFXConfigs = new TalonFXConfiguration(); // optional timeout (in seconds) as a second optional parameter talonFXConfigurator.refresh(talonFXConfigs); .. tab-item:: C++ :sync: C++ .. code-block:: c++ auto& talonFXConfigurator = m_talonFX.GetConfigurator(); configs::TalonFXConfiguration talonFXConfigs{}; // optional timeout (in seconds) as a second optional parameter talonFXConfigurator.Refresh(talonFXConfigs); .. tab-item:: Python :sync: python .. code-block:: python talonfx_configurator = self.talonfx.configurator talonfx_configs = configs.TalonFXConfiguration() # optional timeout (in seconds) as a second optional parameter talonfx_configurator.refresh(talonfx_configs) Applying Configs ^^^^^^^^^^^^^^^^ Configs can be applied to a device by calling ``apply()`` on the ``Configurator`` with a ``Configuration`` object. .. warning:: ``apply()`` is a blocking API call that waits on the device to respond. Calling ``apply()`` periodically may slow down the execution time of the periodic function, as it will always wait up to ``DefaultTimeoutSeconds`` (`Java `__, `C++ `__, `Python `__) for the response when no timeout parameter is specified. .. tab-set:: .. tab-item:: Java :sync: Java .. code-block:: Java var talonFXConfigurator = m_talonFX.getConfigurator(); var motorConfigs = new MotorOutputConfigs(); // set invert to CW+ and apply config change motorConfigs.Inverted = InvertedValue.Clockwise_Positive; talonFXConfigurator.apply(motorConfigs); .. tab-item:: C++ :sync: C++ .. code-block:: c++ auto& talonFXConfigurator = m_talonFX.GetConfigurator(); configs::MotorOutputConfigs motorConfigs{}; // set invert to CW+ and apply config change motorConfigs.Inverted = signals::InvertedValue::Clockwise_Positive; talonFXConfigurator.Apply(motorConfigs); .. tab-item:: Python :sync: python .. code-block:: python talonfx_configurator = self.talonfx.configurator motor_configs = configs.MotorOutputConfigs() # set invert to CW+ and apply config change motor_configs.inverted = signals.InvertValue.CLOCKWISE_POSITIVE talonfx_configurator.apply(motor_configs) .. tip:: To modify a single configuration value without affecting the other configs, users can call ``refresh()`` after constructing the config object, or users can cache the config object and reuse it for future calls to ``apply()``. Factory Default ~~~~~~~~~~~~~~~ A newly-created ``Configuration`` object contains the default configuration values of a device. As a result, it is **unnecessary** to factory default a device before applying a modified device ``Configuration`` object. A device's configs can be explicitly restored to the factory defaults by passing a newly-created ``Configuration`` object to the device ``Configurator``. .. tab-set:: .. tab-item:: Java :sync: Java .. code-block:: Java m_talonFX.getConfigurator().apply(new TalonFXConfiguration()); .. tab-item:: C++ :sync: C++ .. code-block:: c++ m_talonFX.GetConfigurator().Apply(configs::TalonFXConfiguration{}); .. tab-item:: Python :sync: python .. code-block:: Python self.talonfx.configurator.apply(configs.TalonFXConfiguration())