Page 1 of 1

Help Needed: Convergence Issues in Muscle-Driven Simulations

Posted: Wed Jun 05, 2024 11:19 am
by alexandrebperes
Hello everyone,
I've reached a frustrating point in my research where I can't get my muscle-driven simulations to converge due to a restoration phase error. Currently, I can only get my simulations to converge by increasing the max isometric force of the muscles or the tolerances to absurdly high values.

Context:
I'm running fully predictive cycling simulations with a 2D torque-driven model. The goal is to complete a full crank cycle in the least amount of time (weight 1) and the least amount of effort (weight 3). The problem specifications are that it starts at rest and has to be completed within 5 seconds, there are ideal torques added to the joints of 40Nm, allowing for hip and knee flexion.
Afterward, results from the torque-driven simulation are filtered using the TabOpLowPassFilter function and used as a reference for a muscle-driven simulation via the MocoInverse function while a static optimization result is used as the initial guess.

Some useful information:
  • The gait10dof18musc model was used and all the muscles were activated.
  • Only the crank joint is not free to satisfy constraints.
  • The torso movements were disabled by turning it into a WeldJoint, so only hip and knee movements are possible.
  • The model takes around 2 seconds to complete the movement, and the number of meshes was set to 300.
Hypotheses and Questions:
  • Crank Resistance Implementation
    • Hypotheses: I'm using ExpressionBasedCoordinateForce() to implement crank resistance in the torque-driven simulations. Setting it to 4N in the center of the crank, considering a crank arm of 17cm, might require very strong muscles to follow the reference.
    • Question: Is my implementation of crank resistance the best way to do this and is this force going to result in too much torque for muscles to solve? Do I need to add the resistance again when running the MocoInverse for the muscle-driven simulation?
  • Starting from Absolute Rest
    • Hypotheses: Starting the movement from rest might cause muscles to contract too intensely initially, violating activation times.
    • Question: Should I start the movement with some initial velocity to avoid intense initial contractions?
  • Filtering Process
    • Hypotheses: The filtering process might not be smoothing the raw data the way I think it is, leading to abrupt changes and muscle behavior violations.
    • Question: How does TabOpLowPassFilter work? Does it filter all the data from the .sto file? Is there a better way to avoid sudden changes in torque value? I even filtered the data myself to better understand what was going on and then used it as a reference, but I had no success with avoiding restauration phase errors, even though it seemed a very smooth and feasible trajectory.
  • Reserve Actuators
    • Hypotheses: To try and help with the convergence, there are coordinate actuators, but with only 0.1Nm in each joint.
    • Question: Should I add more reserve actuators to the leg joints? What would be a recommended setup for reserve actuators in this context? What is the difference between coordinate actuators and reserve actuators?
Any insights or suggestions you can provide would be greatly appreciated. Thank you for your time and assistance!

Best regards,
Alexandre Peres

Re: Help Needed: Convergence Issues in Muscle-Driven Simulations

Posted: Thu Jun 13, 2024 1:28 pm
by nbianco
Hi Alexandre,

Thank you for the detailed illustration of your problem. My first recommendation for issues like this are to start with a simpler problem/model that does converge and build up complexity from there. If it is not possible to simplify much, then I would recommend making temporary model adjustments to help with convergence (e.g., add strong CoordinateActuators at every joint. My last piece of general advice is to plot the failed solution and look at what the states and controls are doing to get a sense of why the problem is not converging (failed MocoSolutions can be accessed with the "unseal()" command).

All the hypothesis you posit seem like reasonable explanations, but rather than speculate, it will be much quicker to take a look at your most recent solution and work backwards from there.

Best,
Nick