Я использую OpenSim4.5 и хочу визуализировать движение на основе результат обратной динамики (что означает использование сил и моментов).
Я вижу всплывающее окно, но отображаемое движение даже близко не похоже на исходное. Мое первоначальное движение длится 15 секунд, но симуляция часто вылетает примерно через 5 секунд. Более того, я получаю разные движения, когда запускаю один и тот же код несколько раз, даже не меняя файл движения.
Я опубликую свой код и надеюсь, что кто-то более опытный, чем я, сможет взглянуть, потому что я чувствую, что есть что-то простое, что я просто упускаю из виду
Вот краткое изложение кода: функция имеет модель, исходный файл движения .sto (для начальной позиции) и силы, создаваемые моделированием обратной динамики (также .sto).
- Во-первых, недостающие в модели исполнительные механизмы (6 сил и моментов, действующих на таз).
- Затем я устанавливаю верхний и нижний пределы координат.
- Я перебираю координаты, указанные в списке «coordinateNames». " и я использую сплайн GCV по каждой координате, чтобы установить prescribeControlForActuator.
- В конце я использую менеджер для интеграции до последнего момента движения.
Код: Выделить всё
void forwardForInverseResult(OpenSim::Model model, const std::string& inputSTOfn, const std::string& inputForceSTOfn) {
std::cout getFirstTime();
const double lastTime = inputSTO->getLastTime();
/* Adding the controller actuators */
/* This section adds the missing actuators acting on the pelvis: yaw/roll/pitch/longitudinal/vertical/lateral */
auto controller = new OpenSim::PrescribedController();
model.addController(controller);
for (int i = 0; i < model.getNumCoordinates(); ++i) {
const auto& c = model.getCoordinateSet().get(i);
OpenSim::CoordinateActuator* ca;
if (model.getActuators().contains(c.getName() + "_ca")) {
std::cout getName(), new OpenSim::Constant(0.));
}
/* END Adding the controller actuators */
model.setUseVisualizer(true);
auto state = model.initSystem();
/* Setting the model's initial position from coordinates file. */
for (int i = 0; i < model.getNumCoordinates(); ++i) {
const auto& coord = model.getCoordinateSet().get(i);
double initialValue = inputSTOposition->getStateVector(0)->getData()[i];
coord.setValue(state, initialValue);
}
model.realizePosition(state);
/* End setting the model's initial position. */
/* Setting the times column */
OpenSim::Array times;
inputSTO->getTimeColumn(times);
std::vector timesVec(times.getSize());
// set the times vetor only once at the beginning
for (int p = 0; p < times.getSize(); p++) {
timesVec[p] = times[p];
}
/* End Setting the times column */
// Define the coordinate names
static const std::unordered_set coordinateNames = {
"Hip_RR_r", "Hip_DB_r", "Knee_FE_r", "Hip_EF_r",
"Hip_EF_l", "Hip_RR_l", "Hip_BD_l", "Knee_FE_l",
"Shoulder_BD_r", "Shoulder_EF_r", "Elbow_EF_r",
"Shoulder_DB_l", "Shoulder_EF_l", "Shoulder_RR_l", "Elbow_EF_l",
"Neck_LL", "Neck_RR", "Neck_FE", "Shoulder_RR_r", "SpineL_LL", "SpineL_RR", "SpineL_FE", "SpineU_FE",
};
state.setTime(firstTime);
for (int i = 0; i < model.getNumCoordinates(); ++i) {
auto& c = model.updCoordinateSet().get(i);
// If coordinate is excluded, skip the rest of the loop
// (Here if the "find" function returns the end iterator, it means the coordinate is not found)
if (coordinateNames.find(c.getName()) != coordinateNames.end()) {
continue;
}
// Iterate through CoordinateLimitForce components to apply limits
for (const auto& x : model.getComponentList()) {
if (x.get_coordinate() == c.getName()) {
double upperLimitRad = SimTK::convertDegreesToRadians(x.getUpperLimit());
double lowerLimitRad = SimTK::convertDegreesToRadians(x.getLowerLimit());
// Adjust the coordinate value to be within the limits
double currentValue = c.getValue(state);
if (currentValue > upperLimitRad) {
c.setValue(state, upperLimitRad);
}
else if (currentValue < lowerLimitRad) {
c.setValue(state, lowerLimitRad);
}
// Break out of the loop once the match is found
break;
}
}
}
// Start simulation
auto manager = std::make_unique(model, state);
// Loop over coordinates
for (int k = 0; k < model.getNumCoordinates(); ++k) {
const auto& c = model.getCoordinateSet().get(k);
cout
Подробнее здесь: [url]https://stackoverflow.com/questions/79139910/displaying-motion-using-inverse-dynamics-results[/url]