예제 #1
0
/**
 * Append actuators from an actuator set to this set.  Copies of the actuators are not made.
 *
 * This method overrides the method in Set<Force> so that several
 * internal variables of the actuator set can be updated.
 *
 * @param aForceSet The set of actuators to be appended.
 * @param aAllowDuplicateNames If true, all actuators will be appended; If false, don't append actuators whose
 * name already exists in this model's actuator set.
 * @return True if successful; false otherwise.
 */
bool ForceSet::append(ForceSet &aForceSet, bool aAllowDuplicateNames)
{
    bool success = true;
    for(int i=0;i<aForceSet.getSize() && success;i++) {
        bool nameExists = false;
        if(!aAllowDuplicateNames) {
            std::string name = aForceSet.get(i).getName();
            for(int j=0;j<getSize();j++) {
                if(get(j).getName() == name) {
                    nameExists = true;
                    break;
                }
            }
        }
        if(!nameExists) {
            if(!ModelComponentSet<Force>::adoptAndAppend(&aForceSet.get(i))) 
                success = false;
        }
    }

    if(success) {
        updateActuators();
        updateMuscles();
    }

    return(success);
}
/**
 * This method is called at the beginning of an analysis so that any
 * necessary initializations may be performed.
 *
 * This method should be overridden in the child class.  It is
 * included here so that the child class will not have to implement it if it
 * is not necessary.
 *
 * @param s state of system
 *
 * @return -1 on error, 0 otherwise.
 */
int InverseDynamics::begin(const SimTK::State& s )
{
    if(!proceed()) return(0);

    SimTK::Matrix massMatrix;
    _model->getMatterSubsystem().calcM(s, massMatrix);

    //massMatrix.dump("mass matrix is:");
    // Check that m is full rank
    try {
        SimTK::FactorLU lu(massMatrix);
    } catch (const SimTK::Exception::Base&) {
        throw Exception("InverseDynamics: ERROR- mass matrix is singular  ",__FILE__,__LINE__);
    }
    // enable the line below when simmath is fixed
    //bool singularMassMatrix = lu.isSingular();

    //cout << "Mass matrix is " << (singularMassMatrix?"singular":"Non-singular");

    // Make a working copy of the model
    delete _modelWorkingCopy;
    _modelWorkingCopy = _model->clone();
    _modelWorkingCopy->updAnalysisSet().setSize(0);

    // Replace model force set with only generalized forces
    if(_model) {
        SimTK::State& sWorkingCopyTemp = _modelWorkingCopy->initSystem();
        // Update the _forceSet we'll be computing inverse dynamics for
        if(_ownsForceSet) delete _forceSet;
        if(_useModelForceSet) {
            // Set pointer to model's internal force set
            _forceSet = &_modelWorkingCopy->updForceSet();
            _numCoordinateActuators = _modelWorkingCopy->getActuators().getSize();
        } else {
            ForceSet& as = _modelWorkingCopy->updForceSet();
            // Keep a copy of forces that are not muscles to restore them back.
            ForceSet* saveForces = as.clone();
            // Generate an force set consisting of a coordinate actuator for every unconstrained degree of freedom
            _forceSet = CoordinateActuator::CreateForceSetOfCoordinateActuatorsForModel(sWorkingCopyTemp,*_modelWorkingCopy,1,false);
            _numCoordinateActuators = _forceSet->getSize();
            // Copy whatever forces that are not muscles back into the model
            
            for(int i=0; i<saveForces->getSize(); i++){
                // const Force& f=saveForces->get(i);
                if ((dynamic_cast<const Muscle*>(&saveForces->get(i)))==NULL)
                    as.append(saveForces->get(i).clone());
            }
        }
        _modelWorkingCopy->setAllControllersEnabled(false);
        _ownsForceSet = false;

        SimTK::State& sWorkingCopy = _modelWorkingCopy->initSystem();

        // Gather indices into speed set corresponding to the unconstrained degrees of freedom (for which we will set acceleration constraints)
        _accelerationIndices.setSize(0);
        auto coordinates = _modelWorkingCopy->getCoordinatesInMultibodyTreeOrder();
        for(size_t i=0u; i<coordinates.size(); ++i) {
            const Coordinate& coord = *coordinates[i];
            if(!coord.isConstrained(sWorkingCopy)) {
                _accelerationIndices.append(static_cast<int>(i));
            }
        }

        _dydt.setSize(_modelWorkingCopy->getNumCoordinates() + _modelWorkingCopy->getNumSpeeds());

        int nf = _numCoordinateActuators;
        int nacc = _accelerationIndices.getSize();

        if(nf < nacc) 
            throw(Exception("InverseDynamics: ERROR- over-constrained system -- need at least as many forces as there are degrees of freedom.\n"));

        // Realize to velocity in case there are any velocity dependent forces
        _modelWorkingCopy->getMultibodySystem().realize(sWorkingCopy, SimTK::Stage::Velocity);

        _constraintMatrix.resize(nacc,nf);
        _constraintVector.resize(nacc);

        _performanceMatrix.resize(nf,nf);
        _performanceMatrix = 0;
        for(int i=0,j=0; i<nf; i++) {
            ScalarActuator* act = dynamic_cast<ScalarActuator*>(&_forceSet->get(i));
            if( act ) {
                act->setActuation(sWorkingCopy, 1);
                _performanceMatrix(j,j) = act->getStress(sWorkingCopy);
                j++;
             }
        }

        _performanceVector.resize(nf);
        _performanceVector = 0;

        int lwork = nf + nf + nacc;
        _lapackWork.resize(lwork);
    }

    _statesSplineSet=GCVSplineSet(5,_statesStore);

    // DESCRIPTION AND LABELS
    constructDescription();
    constructColumnLabels();

    deleteStorage();
    allocateStorage();

    // RESET STORAGE
    _storage->reset(s.getTime());

    // RECORD
    int status = 0;
    if(_storage->getSize()<=0) {
        status = record(s);
    }

    return(status);
}
/**
 * This method is called at the beginning of an analysis so that any
 * necessary initializations may be performed.
 *
 * This method is meant to be called at the beginning of an integration 
 *
 * @param s Current state .
 *
 * @return -1 on error, 0 otherwise.
 */
int StaticOptimization::
begin(SimTK::State& s )
{
    if(!proceed()) return(0);

    // Make a working copy of the model
    delete _modelWorkingCopy;
    _modelWorkingCopy = _model->clone();
    _modelWorkingCopy->initSystem();

    // Replace model force set with only generalized forces
    if(_model) {
        SimTK::State& sWorkingCopyTemp = _modelWorkingCopy->updWorkingState();
        // Update the _forceSet we'll be computing inverse dynamics for
        if(_ownsForceSet) delete _forceSet;
        if(_useModelForceSet) {
            // Set pointer to model's internal force set
            _forceSet = &_modelWorkingCopy->updForceSet();
            _ownsForceSet = false;
        } else {
            ForceSet& as = _modelWorkingCopy->updForceSet();
            // Keep a copy of forces that are not muscles to restore them back.
            ForceSet* saveForces = as.clone();
            // Generate an force set consisting of a coordinate actuator for every unconstrained degree of freedom
            _forceSet = CoordinateActuator::CreateForceSetOfCoordinateActuatorsForModel(sWorkingCopyTemp,*_modelWorkingCopy,1,false);
            _ownsForceSet = false;
            _modelWorkingCopy->setAllControllersEnabled(false);
            _numCoordinateActuators = _forceSet->getSize();
            // Copy whatever forces that are not muscles back into the model
            
            for(int i=0; i<saveForces->getSize(); i++){
                const Force& f=saveForces->get(i);
                if ((dynamic_cast<const Muscle*>(&saveForces->get(i)))==NULL)
                    as.append(saveForces->get(i).clone());
            }
        }

        SimTK::State& sWorkingCopy = _modelWorkingCopy->initSystem();
        // Set modeling options for Actuators to be overriden
        for(int i=0; i<_forceSet->getSize(); i++) {
            ScalarActuator* act = dynamic_cast<ScalarActuator*>(&_forceSet->get(i));
            if( act ) {
                act->overrideActuation(sWorkingCopy, true);
            }
        }

        sWorkingCopy.setTime(s.getTime());
        sWorkingCopy.setQ(s.getQ());
        sWorkingCopy.setU(s.getU());
        sWorkingCopy.setZ(s.getZ());
        _modelWorkingCopy->getMultibodySystem().realize(s,SimTK::Stage::Velocity);
        _modelWorkingCopy->equilibrateMuscles(sWorkingCopy);
        // Gather indices into speed set corresponding to the unconstrained degrees of freedom 
        // (for which we will set acceleration constraints)
        _accelerationIndices.setSize(0);
        const CoordinateSet& coordSet = _model->getCoordinateSet();
        for(int i=0; i<coordSet.getSize(); i++) {
            const Coordinate& coord = coordSet.get(i);
            if(!coord.isConstrained(sWorkingCopy)) {
                Array<int> inds = _statesStore->
                    getColumnIndicesForIdentifier(coord.getName()) ;
                _accelerationIndices.append(inds[0]);
            }
        }

        int na = _forceSet->getSize();
        int nacc = _accelerationIndices.getSize();

        if(na < nacc) 
            throw(Exception("StaticOptimization: ERROR- over-constrained "
                "system -- need at least as many forces as there are degrees of freedom.\n") );

        _forceReporter.reset(new ForceReporter(_modelWorkingCopy));
        _forceReporter->begin(sWorkingCopy);
        _forceReporter->updForceStorage().reset();

        _parameters.resize(_modelWorkingCopy->getNumControls());
        _parameters = 0;
    }

    _statesSplineSet=GCVSplineSet(5,_statesStore);

    // DESCRIPTION AND LABELS
    constructDescription();
    constructColumnLabels();

    deleteStorage();
    allocateStorage();

    // RESET STORAGE
    _activationStorage->reset(s.getTime());
    _forceReporter->updForceStorage().reset(s.getTime());

    // RECORD
    int status = 0;
    if(_activationStorage->getSize()<=0) {
        status = record(s);
        const Set<Actuator>& fs = _modelWorkingCopy->getActuators();
        for(int k=0;k<fs.getSize();k++) {
            ScalarActuator* act = dynamic_cast<ScalarActuator *>(&fs[k]);
            if (act){
                cout << "Bounds for " << act->getName() << ": "
                    << act->getMinControl() << " to "
                    << act->getMaxControl() << endl;
            }
            else{
                std::string msg = getConcreteClassName();
                msg += "::can only process scalar Actuator types.";
                throw Exception(msg);
            }
        }
    }

    return(status);
}