| 967 | // ============================================================================= |
| 968 | |
| 969 | TSharedPtr<FJsonObject> FURLabRpcDispatcher::HandleStep(const TSharedPtr<FJsonObject>& Req) |
| 970 | { |
| 971 | AAMjManager* Mgr = OwnerMgr.Get(); |
| 972 | if (!Mgr || !Mgr->PhysicsEngine || !Mgr->PhysicsEngine->m_model) |
| 973 | { |
| 974 | return MakeError(TEXT("not_ready"), TEXT("PhysicsEngine not initialised")); |
| 975 | } |
| 976 | |
| 977 | if (ActiveStepMode == EStepMode::Live) |
| 978 | { |
| 979 | // Live mode: UE drives its own physics. step() applies ctrl and |
| 980 | // returns current state. n_steps is ignored (UE steps at its own |
| 981 | // rate). Same per_articulation shape as direct mode. |
| 982 | mjModel* m = Mgr->PhysicsEngine->GetModel(); |
| 983 | mjData* d = Mgr->PhysicsEngine->GetData(); |
| 984 | |
| 985 | FMjStepRequest TmpReq; |
| 986 | const TSharedPtr<FJsonObject>* PerArt = nullptr; |
| 987 | if (Req->TryGetObjectField(TEXT("per_articulation"), PerArt) && PerArt && PerArt->IsValid()) |
| 988 | { |
| 989 | for (auto& Pair : (*PerArt)->Values) |
| 990 | { |
| 991 | const TSharedPtr<FJsonObject>* ArtObj = nullptr; |
| 992 | if (!Pair.Value->TryGetObject(ArtObj) || !ArtObj || !ArtObj->IsValid()) |
| 993 | continue; |
| 994 | |
| 995 | FString CtlMode; |
| 996 | if ((*ArtObj)->TryGetStringField(TEXT("control_mode"), CtlMode)) |
| 997 | TmpReq.PerArticulationControlMode.Add(Pair.Key, CtlMode); |
| 998 | |
| 999 | const TArray<TSharedPtr<FJsonValue>>* CtrlList = nullptr; |
| 1000 | if ((*ArtObj)->TryGetArrayField(TEXT("ctrl"), CtrlList) && CtrlList) |
| 1001 | { |
| 1002 | if (AMjArticulation* Art = Cast<AMjArticulation>(Mgr->GetArticulation(Pair.Key))) |
| 1003 | { |
| 1004 | TArray<UMjActuator*> Acts = Art->GetActuators(); |
| 1005 | for (int32 i = 0; i < CtrlList->Num() && i < Acts.Num(); ++i) |
| 1006 | { |
| 1007 | UMjActuator* A = Acts[i]; |
| 1008 | if (!A) |
| 1009 | continue; |
| 1010 | FString Local = A->GetMjName(); |
| 1011 | FString Prefix = Art->GetName() + TEXT("_"); |
| 1012 | if (Local.StartsWith(Prefix)) |
| 1013 | Local = Local.Mid(Prefix.Len()); |
| 1014 | TmpReq.PerArticulationCtrl.FindOrAdd(Pair.Key).Add( |
| 1015 | {Local, (float)(*CtrlList)[i]->AsNumber()}); |
| 1016 | } |
| 1017 | } |
| 1018 | } |
| 1019 | } |
| 1020 | } |
| 1021 | |
| 1022 | TSharedPtr<FJsonObject> Reply = MakeShared<FJsonObject>(); |
| 1023 | { |
| 1024 | FScopeLock Lock(&Mgr->PhysicsEngine->CallbackMutex); |
| 1025 | ApplyStepCtrl(Mgr, TmpReq, m, d); |
| 1026 | Reply->SetStringField(TEXT("op"), TEXT("step_ok")); |
nothing calls this directly
no test coverage detected