| 1333 | } |
| 1334 | |
| 1335 | void FURLabRpcDispatcher::ApplyStepCtrl(AAMjManager* Manager, const FMjStepRequest& Req, |
| 1336 | mjModel* m, mjData* d) |
| 1337 | { |
| 1338 | if (!Manager) |
| 1339 | return; |
| 1340 | for (auto& Pair : Req.PerArticulationCtrl) |
| 1341 | { |
| 1342 | AMjArticulation* Art = Manager->GetArticulation(Pair.Key); |
| 1343 | if (!Art) |
| 1344 | continue; |
| 1345 | |
| 1346 | const FString Prefix = Art->GetName() + TEXT("_"); |
| 1347 | TMap<FString, UMjActuator*> ByName; |
| 1348 | ByName.Reserve(Art->GetActuators().Num() * 2); |
| 1349 | for (UMjActuator* A : Art->GetActuators()) |
| 1350 | { |
| 1351 | if (!A) |
| 1352 | continue; |
| 1353 | FString FullName = A->GetMjName(); |
| 1354 | FString Local = FullName.StartsWith(Prefix) ? FullName.Mid(Prefix.Len()) : FullName; |
| 1355 | ByName.Add(Local, A); |
| 1356 | ByName.Add(FullName, A); |
| 1357 | } |
| 1358 | |
| 1359 | // Stage to actuator NetworkValue; AMjArticulation::ApplyControls |
| 1360 | // copies it into d->ctrl every sub-step. Writing d->ctrl directly |
| 1361 | // would be overwritten on the next sub-step. |
| 1362 | for (const TPair<FString, float>& KV : Pair.Value) |
| 1363 | { |
| 1364 | UMjActuator** Found = ByName.Find(KV.Key); |
| 1365 | if (!Found || !*Found) |
| 1366 | continue; |
| 1367 | (*Found)->SetNetworkControl(KV.Value); |
| 1368 | } |
| 1369 | } |
| 1370 | |
| 1371 | // xfrc_applied writes: per_articulation -> body_name -> 6-vec. |
| 1372 | // MuJoCo clears d->xfrc_applied on every mj_step, so this is a one-shot |
| 1373 | // impulse for the next mj_step n_steps loop. Body name lookup tries both |
| 1374 | // the local (no-prefix) form and the prefixed full name. |
| 1375 | if (m && d) |
| 1376 | { |
| 1377 | for (auto& APair : Req.PerArticulationXfrc) |
| 1378 | { |
| 1379 | FString ArtPrefix = APair.Key + TEXT("_"); |
| 1380 | for (auto& BPair : APair.Value) |
| 1381 | { |
| 1382 | if (BPair.Value.Num() != 6) |
| 1383 | continue; |
| 1384 | FString FullName = ArtPrefix + BPair.Key; |
| 1385 | int Bid = mj_name2id(m, mjOBJ_BODY, TCHAR_TO_UTF8(*FullName)); |
| 1386 | if (Bid < 0) |
| 1387 | Bid = mj_name2id(m, mjOBJ_BODY, TCHAR_TO_UTF8(*BPair.Key)); |
| 1388 | if (Bid < 0 || Bid >= m->nbody) |
| 1389 | continue; |
| 1390 | for (int i = 0; i < 6; ++i) |
| 1391 | d->xfrc_applied[6 * Bid + i] = (mjtNum)BPair.Value[i]; |
| 1392 | } |
nothing calls this directly
no test coverage detected