opensim-org / opensim-gui

SimTK OpenSim graphical user interface and distribution.
Apache License 2.0
62 stars 33 forks source link

Changing motions from one with muscle states to without: color of muscles is carried over #279

Open jenhicks opened 7 years ago

jenhicks commented 7 years ago

This happened for me in the tutorial when I switched from the SO results to IK results

tkuchida commented 7 years ago

Related: Muscles are red when model is first opened. If IK is run on newly opened model, muscles remain red while IK is solving but then (correctly) become blue in playback mode. opensim4.0PreviewWin64_0719.zip

aymanhab commented 7 years ago

@tkuchida While running an analysis or playing back a motion, the muscles are colored by the state, otherwise the colors use their default colors from the file. This seems reasonable and allows for a mode where you can use display options to show various muscle groups etc. IK produces only coordinates so there's no specific color to apply to muscles. From there on we're using states hence the blue color. Does that make sense? Confusing? Open to suggestions.

tkuchida commented 7 years ago

I've never used the "mode where you can use display options to show various muscle groups etc." I think the playback should play back whatever was displayed during the computation. Presumably, the muscles should be blue during IK computation if the muscles are inactive.

aymanhab commented 6 years ago

This was folded into #283 where loading any motion now, we convert into States using formStateStorage. Please verify and close or report unexpected behavior. Thanks

jimmyDunne commented 6 years ago

I opened a model and two motions; one a states file from CMC, and the other is an RRA sto file from RRA. When I switch from the CMC states to the RRA kinematics, whatever the current muscle colors were during the CMC playback are persistent.

opensim 4 0 4_11_2018 2_03_10 pm

jenhicks commented 6 years ago

When you load coordinates, make full state with muscles to blue. @aymanhab will investigate

aymanhab commented 6 years ago

This actually is exactly how Model.formStateStorage() works which is correctly invoked in this case. For unspecifed states (e.g. muscle states) it keeps them at current value. If this is unexpected or a different behavior is expected pleaseopen an issue for opensim-core and when a solution is available at the API level we can wire it from the GUI. @chrisdembia please let me know if this is different from your expectations. Thanks.

jimmyDunne commented 6 years ago

Ayman, it would be great if you could pass on more details on how this feature works. It feels like the rest of the team aren't sure of how this is implemented and it would be awesome to get some further insight. What class/component draws the colors? What class/component holds/computes the data? It sounds like Model.formStateStorage() will compute some data that then gets passed to something that draws it on the screen, correct? When we have multiple loaded motions or states, does Model.formStateStorage() get computed each time you change the current motion or state or does it call it once when the data is loaded then store it somewhere for recall when a user changes the current motion or state? It would be really helpful for us to know the design.

We had discussed that when we switch between a loaded state with muscle activations to a motion with only coordinate values, the muscles should become blue— the recognized color for zero activation. Sorry if that was unclear from the meeting?

If this is an improvement that should be made to OpenSim-core to help the visualizer, it would be most helpful for you to create and write the issue. You are by far the most familiar with the GUI and the communication between the GUI and the API. I would find it daunting to write an issue on the this that captures the nuance of the problem.

aymanhab commented 6 years ago

@jimmyDunne nice writeup ;) My note was mainly intended for @jenhicks and @aseth1 since we had extended discussions in the past regarding display of motions and colors. Let me explain how this works for the benefit of everybody.

Hope this helps.

tkuchida commented 6 years ago

if your preference is for muscles to be colored blue if activations are unspecified

Yes, I think this is essential. From the user's perspective, it would be very confusing for muscles to be colorful when playing a motion that is devoid of activation data (the colors would be conveying information that isn't there). Also, the color of a muscle when playing an animation of IK results, for example, should not depend on the arbitrary color of that muscle when some previously selected motion was paused. I would expect the internal state and external appearance of the visualizer to be identical when playing the same IK result, regardless of what else has been loaded or played previously.

aymanhab commented 6 years ago

I totally agree @tkuchida 👍 you make a very strong case. I just pointed out that the functionality is implemented in a different repository 😄

tkuchida commented 6 years ago

Ah, ok thanks @aymanhab. According to the doxygen for Model::formStateStorage(), it should "Use the default state value if a state is unspecified in the originalStorage." Perhaps this isn't happening when the original Storage is missing activations (e.g., IK results) and the GUI isn't given zeros to turn the muscles blue? I'll open an Issue on opensim-core :apple:

jenhicks commented 6 years ago

Thanks @tkuchida. I'm leaving this issue open on the GUI side and under Needs Verifying so that we don't forget to test.

tkuchida commented 6 years ago

@aymanhab: Please see @aseth1's analysis at https://github.com/opensim-org/opensim-core/issues/2152.

aseth1 commented 6 years ago

I tracked it down further and it comes down to the following in MotionDisplayer.java on lines 813 and 823:

model.setStateVariableValues(context.getCurrentStateRef(), states.getAsVector());

where we (thanks to Java we can ignore the constness of the OpenSim::getCurrentStateRef()) write values to the internal working state of the Model. We should be providing the State to be rendered, not overwriting the internal state of the model! The const SimTK::State& signature of getCurrentStateRef() indicates that using the state for writing was never its intention.

This is not an API issue AFAICT.

jimmyDunne commented 6 years ago

Issue is still present

aymanhab commented 6 years ago

Trying to keep a copy of the state is doable but have wide ranging implications. since we need to explicitly Realize our copy to proper stage. E.g. testContext fail for this reason, and trying to load a model in the GUI with this change results in Error detected by Simbody method getCacheEntry: State Cache entry was out of date with respect to one of its explicit prerequisites. And this is just scratching the surface without knowing for sure that it fixes the issue in question.

I'll keep the branch for a future, cleaner fix, but suggest we use the more surgical fix in PR #804 for 4.0 purposes.

aymanhab commented 6 years ago

Thoughts @aseth1 @tkuchida @jenhicks

aseth1 commented 6 years ago

'll keep the branch for a future, cleaner fix, but suggest we use the more surgical fix in PR #804 for 4.0 purposes.

I have to disagree. This will only perpetuate a bad design and make it harder to fix down the road. The issue here is twofold:

  1. there is a flagrant violation of coding practices changing the value of a const method that is also a data member of a const object.
  2. the argument of maintaining a copy of the State as being arduous is false. You are relying on the internal copy of the Model (which IMHO should not exist). That State is not magically realized to the correct stage. It follows a logical process. You are likely getting the error because you are trying to get positions to draw when the State has not been realized to the Position stage.
jenhicks commented 6 years ago

@aymanhab I will stop by your office this morning to discuss what we should do for the 4.0 beta we are finalizing today. @aseth1 If you have suggestions about what to do given that we need to post a beta today, please let me know.

aseth1 commented 6 years ago

It should not be challenge to realize to the correct stage. I am not sure what is holding up the change.

jenhicks commented 6 years ago

@aseth1 We are not making the change at this point because the Model's internal copy of the state is used widely in the GUI. It seems too late in the game to change this over now.

aymanhab commented 6 years ago

Based on discussion with @jenhicks and considering the potential scope of the change, we agreed to merge the one-line surgical fix to MotionDisplayer and to leave the issue and the branch with the stateCopy intact for later consideration. This fix is easily rolled back if needed.

If you prefer to deprecate the get/updWorkingState methods you can start there and we'll adjust or we can discuss when you have a chance.

aseth1 commented 6 years ago

This fix is easily rolled back if needed

I disagree. The Tools and GUI are filled with hacks that have never been rolled back because no-one can comprehend what they are doing. It will be the same in this case. The fact that a const method is being used to change a data member was difficult for me to track down. I doubt it will ever be fixed. It was not addressed almost three months ago when it was raised.

If you prefer to deprecate the get/updWorkingState methods you can start there and we'll adjust or we can discuss when you have a chance.

I'm not a fan of these methods, but that is not the issue here. You are using the working state as your internal data member when it is just a pointer to the model's. That is plain wrong.

aymanhab commented 6 years ago

I fixed the opensim-core branch with the copied state so that core test cases pass, and the models load in the GUI but other functionality broke (e.g. live playback while running tools). Will hold until I investigate these issues and we have cycles to test the far reaching effects of this change.