Resetting a User Limit's Configuration

[RMP 10.4.3]

I recently learned that if a user limit configured with an output is re-used, i.e. UserLimitConfigSet(…) is called for it, if no call to UserLimitOutputSet(…) is made, the previous output will still be configured for that user limit (and will get set when the user limit fires).

How do I clear the configuration for a given user limit?

My application re-uses user limits, meaning that I don’t have hardcoded user limit indices. Rather, when one is needed, it “checks out” a user limit, does what it wants, and may return it to be used by some other part of the application when it’s needed.

In this scenario, I need to be able to start with a user limit of unknown configuration and clear out any configuration it currently has so that I can configure it to do what is needed.

How do I clear/drop all existing configuration for a user limit?

Is there a single API call that will accomplish this, or do I need to call the basic config API functions with NONE/null/empty values to de-configure it?

I tried using UserLimitDisable(…) to accomplish this, but it doesn’t seem to work as I’d expect. Here’s a illustration of the current behavior [RMP 10.4.3]. (This is using my own SWIG interface to RapidCode, but the differences between it and yours are superficial.)

def TestUserLimitDisable():
    ul_index = 1
    # void UserLimitConditionSet(int32_t number, int32_t conditionNumber, RSIUserLimitLogic logic, uint64_t addressOfUInt32, uint32_t userLimitMask, uint32_t limitValueUInt32)
    mc.UserLimitConditionSet(ul_index,
                             0,
                             pyrmp.Enums.RSIUserLimitLogic.EQ,
                             mc.AddressGet(pyrmp.Enums.RSIControllerAddressType.SAMPLE_COUNTER),
                             0xFFFFFFFF,
                             1)
    # void UserLimitConfigSet(int32_t number, RSIUserLimitTriggerType triggerType, RSIAction action, int32_t actionAxis, double duration)
    mc.UserLimitConfigSet(ul_index,
                          pyrmp.Enums.RSIUserLimitTriggerType.SINGLE_CONDITION,
                          pyrmp.Enums.RSIAction.NONE,
                          0,
                          0.0)
    # void UserLimitOutputSet(int32_t number, uint32_t andMask, uint32_t orMask, uint64_t outputPtr, bool enabled)
    mc.UserLimitOutputSet(ul_index,
                          0x0,
                          0x1,
                          mc.AddressGet(pyrmp.Enums.RSIControllerAddressType.USER_BUFFER,1),
                          True)

    input(f'User Limit #{ul_index} Configured (Stage 1)')

    mc.UserLimitDisable(ul_index)
    
    input(f'User Limit #{ul_index} Disabled (Stage 2)')

                          
    mc.UserLimitConditionSet(ul_index,
                             0,
                             pyrmp.Enums.RSIUserLimitLogic.EQ,
                             mc.AddressGet(pyrmp.Enums.RSIControllerAddressType.SAMPLE_COUNTER),
                             0xFFFFFFFF,
                             10000)
    mc.UserLimitConfigSet(ul_index,
                          pyrmp.Enums.RSIUserLimitTriggerType.SINGLE_CONDITION,
                          pyrmp.Enums.RSIAction.E_STOP,
                          0,
                          0.0)

    input(f'User Limit #{ul_index} Reconfigured (Stage 3)')

When I run this, after stage 3 (as well as stage 2), the user limit still has an output set.

Hi Todd,

UserLimitDisable(…) only sets Enabled to false, preventing the UserLimit from being processed, but it does not clear any of the configuration. In general, we will not clear any UserLimit configuration unless it is explicitly overwritten. This has to be done separately for each part of the configuration using UserLimitConfigSet(…), UserLimitConditionSet(…), and UserLimitOutputSet(…). If you are just interested in disabling the output, then you can use UserLimitOutputSet(…, false) whenever you return a UserLimit to the pool.

Future Updates: If there is enough demand for this sort of feature, then we can add something like UserLimitReset(<user_limit_index>) or UserLimitOutputDisable(<user_limit_index>).

The fact that there’s nothing for this suggests that nobody else needs something special.

It would be sufficient for me to have a RSI Recommended® set of calls.

Here’s what I’m currently using.

		mc->UserLimitConfigSet(ul_index,
							   RSIUserLimitTriggerType::RSIUserLimitTriggerTypeNONE,
							   RSIAction::RSIActionNONE,
							   0,
							   0.0);
		mc->UserLimitOutputSet(ul_index,
							   static_cast<uint32_t>(0x0), // and mask
							   static_cast<uint32_t>(0x0), // or mask
							   static_cast<uint32_t>(0x0), // output pointer
							   false); // DISABLED

		mc->UserLimitEnableSet(ul_index, false); // DISABLED

Is this enough? Do I need to call UserLimitConditionSet(...) if I’m using a trigger type of NONE?

The problem that I had was really about outputs, since not all of my uses of user limits do not need/use outputs. I didn’t think to unconfigure them. I imagined that calling UserLimitConfigSet(...) would discard some of that configuration.

Hi Todd,

What you are currently using looks good. You are correct in your assumption that you don’t need to call UserLimitConditionSet(...). As long as the trigger type is RSIUserLimitTriggerTypeNONE the condition won’t be evaluated at all.

This could run into issues if you set the trigger type to something other than NONE without setting the condition, but I can’t think of a good reason to do that. The intended way to use UserLimits is to always call UserLimitConditionSet(...) before calling UserLimitConfigSet(...). If you do it in the other order, then RMP will be evaluating a condition before it is configured, which is likely to lead to unexpected behavior.