opensim-org / opensim-core

SimTK OpenSim C++ libraries and command-line applications, and Java/Python wrapping.
https://opensim.stanford.edu
Apache License 2.0
794 stars 318 forks source link

getActivation for muscles that do not "apply_force" are inconsistent between muscle models #2521

Open aymanhab opened 5 years ago

aymanhab commented 5 years ago

What is the expected behavior when you ask a disabled muscle for its Activation (or Color). I'm trying code examples and I'm always getting an activation value between 0.0 and 1.0

aseth1 commented 5 years ago

Muscles are not disabled. A Force component that "appliesForce" is obvious that it has to compute whatever it needs (including internal states) to compute and apply a force. What should happen if a Muscle does not apply force? It seems you would prefer that the muscle states are not computed. But then, should you be able to ask a disabled muscle how long its fiber is? AFAICT Muscles handle the ambiguity by going ahead and computing internal states (including activation). So they are not really bogus. The Millard muscles does check if it appliesForce, but it just sets the activation rate to zero in that case, which means it will just return the default_activation value and the state variable/allocation is just a wasted resource.

I am not in favor of these behavior-based disable options because they require the derived class to implement the logic to figure out what to do with these flags, and it is not at all surprising they create inconsistencies. There was an alternative proposal (#1382) to exclude components altogether instead of being in this gray zone. IMHO complete exclusion is favorable over selectively trying to turn on/off one aspect/behavior of a complex component.

aymanhab commented 5 years ago

Thanks for the feedback @aseth1 I guess bogus was an overstatement, inconsistent is a more accurate word. I'll update accordingly. The main issue that I'm trying to address though is how to show/color muscles that do not "apply_force" when applying a state either live or in playback. Are you suggesting the answer depends on the muscle model? Would the user want to draw distinction between muscles that are not-activated due to algorithms and those due to "apply_force" being false?

aymanhab commented 5 years ago

@tkuchida would love to hear your thoughts as well.

aseth1 commented 5 years ago

Are you suggesting the answer depends on the muscle model? Would the user want to draw distinction between muscles that are not-activated due to algorithms and those due to "apply_force" being false?

I am not suggesting, I am simply stating that Muscles do compute an activation state independent of whether or not they apply force. Furthermore, in one case (Millard) the calculation is different whether the flag is true or not (activation rate = 0). Now, whether this is the correct thing to do or not is up for debate. I think it is poorly defined and more problematic than useful.

We have to ask ourselves and users when appliesForce == false for a given muscle is it necessary/desired to:

  1. visualize the muscle
  2. compute activation
  3. compute fiber length
  4. compute the force that would have been applied if the flag were true (but not applied)
  5. compute other muscle related outputs

If the answer is No for all or most of these then the user is really expecting the muscle to NOT be present in the simulation. That is excluded from the system altogether and has zero overhead/impact on computations. For most use cases of "disabling" exclusion is the desired/expected behavior.

From a software point of view it is going to be very difficult to manage any partial set of computations when the Muscle (Force) does not apply force but is still present in the System. We either compute everything or we don't and effectively exclude it. Anything in the middle is going to be problematic.

aymanhab commented 5 years ago

Thanks @aseth1 for the very informative answer. Would be great to hear what other developers/users answer the 5 questions above as well as your answers Ajay 😃 @jimmyDunne @chrisdembia @tkuchida @jenhicks @nickbianco

tkuchida commented 5 years ago

I don't think it should matter too much what activation or fiber length is reported by a disabled muscle since one should not expect these values to be meaningful anyway. Ideally, NaNs would be reported since numbers (even zeros) could be misinterpreted as being meaningful (by users, the GUI, etc.). IMHO, disabling a muscle should remove its states from the system (like removing the battery :battery: or pulling the +5V wire on a breadboard). Presumably, one might want to enable/disable muscles to speed up a simulation or to isolate a bug/bottleneck. If the user is trying to perform some subset of the muscle calculations, they could set max. activation to zero, max. isometric force to zero, etc.

However, the flag is appliesForce, not enabled. In an inverse simulation, for example, it's unclear what it would mean if a muscle in which appliesForce == false reported a nonzero force value. If the muscle were to apply this force, then the forces from the other muscles would be different, too. If two muscles were set to appliesForce == false, it would be unclear whether the hypothetical forces were computed in isolation or whether they were computed consistently (as part of a separate hypothetical model in which all muscles apply force).

If there are going to be conditions on what a Component reports in special cases, these conditions should be defined and enforced in testComponents. Aside from that, I don't think the Component designer can be expected to adhere to a set of conditions/rules associated with Tool- or Study-level considerations: that's the job of the Tool or Study designer.

IMHO:

  1. I wouldn't expect a disabled muscle to show up when animating results.
  2. A disabled muscle should not be activated.
  3. Fiber length (and equilibrium with tendon, for example) should not be computed.
  4. Force should not be computed.
  5. No outputs should be computed.