Отображение движения с использованием результатов обратной динамикиC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Отображение движения с использованием результатов обратной динамики

Сообщение Anonymous »

Я новичок в 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]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»