Я новичок в OpenSim, поэтому это может быть тривиальная проблема, но я не смог найти ответ на форуме или в Интернете.
Я использую 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]
Я новичок в OpenSim, поэтому это может быть тривиальная проблема, но я не смог найти ответ на форуме или в Интернете. Я использую OpenSim4.5 и хочу визуализировать движение на основе результат обратной динамики (что означает использование сил и моментов). Я вижу всплывающее окно, но отображаемое движение даже близко не похоже на исходное. Мое первоначальное движение длится 15 секунд, но симуляция часто вылетает примерно через 5 секунд. Более того, я получаю разные движения, когда запускаю один и тот же код несколько раз, даже не меняя файл движения. Я опубликую свой код и надеюсь, что кто-то более опытный, чем я, сможет взглянуть, потому что я чувствую, что есть что-то простое, что я просто упускаю из виду 🙏. Вот краткое изложение кода: функция имеет модель, исходный файл движения .sto (для начальной позиции) и силы, создаваемые моделированием обратной динамики (также .sto). [list] [*]Во-первых, недостающие в модели исполнительные механизмы (6 сил и моментов, действующих на таз). [*]Затем я устанавливаю верхний и нижний пределы координат. [*]Я перебираю координаты, указанные в списке «coordinateNames». " и я использую сплайн GCV по каждой координате, чтобы установить prescribeControlForActuator. [*]В конце я использую менеджер для интеграции до последнего момента движения. [/list] [code]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 */
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