Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions PythonClient/tests/smoke_annotation_lifecycle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Regression for dynamic annotation cleanup. Use a disposable simulator."""
import argparse
import time
import uuid
import cosysairsim as airsim


def main():
parser = argparse.ArgumentParser()
parser.add_argument('--port', type=int, required=True)
args = parser.parse_args()
client = airsim.VehicleClient(port=args.port, timeout_value=15)
assert client.ping()
assert 'Cube' in client.simListAssets(), 'Test level must include a Cube asset'
prefix = 'AnnotationAudit_' + uuid.uuid4().hex[:8]
for cycle in range(2):
name = client.simSpawnObject(prefix, 'Cube', airsim.Pose(airsim.Vector3r(10, 0, -10)),
airsim.Vector3r(1, 1, 1), False, False)
try:
names = [key for key in client.simListInstanceSegmentationObjects() if prefix in key]
assert len(names) == 1, names
key = names[0]
# The render proxy is created after the initial spawn registration.
time.sleep(1)
assert client.simSetSegmentationObjectID(key, 1000 + cycle)
assert client.simGetSegmentationObjectID(key) == 1000 + cycle
finally:
assert client.simDestroyObject(name), name
time.sleep(0.5)
assert not any(prefix in key for key in client.simListInstanceSegmentationObjects())
assert client.simGetSegmentationObjectID(key) == -1
print('PASS: two spawn/render/update/destroy cycles, no stale annotation names or IDs')


if __name__ == '__main__':
main()
67 changes: 22 additions & 45 deletions Unreal/Plugins/AirSim/Source/Annotation/ObjectAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
// Licensed under the MIT License.
#include "ObjectAnnotator.h"
#include "Runtime/Engine/Public/EngineUtils.h"
#include "SceneInterface.h"
#include "../Private/ScenePrivate.h"
#include "Runtime/Launch/Resources/Version.h"
#include "AnnotationComponent.h"
#include "AirBlueprintLib.h"
Expand Down Expand Up @@ -74,16 +72,8 @@ void FObjectAnnotator::getPaintableComponentMeshes(AActor* actor, TMap<FString,
int index = 0;
for (auto component : paintable_components)
{
int32 PersistentPrimitiveIndex = component->GetUniqueID();
if (const UPrimitiveComponent* PrimitiveComp = Cast<UPrimitiveComponent>(component))
{
if (const FPrimitiveSceneProxy* SceneProxy = PrimitiveComp->SceneProxy)
{
int32 PersistentPrimitiveIndexTemp = SceneProxy->GetPrimitiveSceneInfo()->GetPersistentIndex().Index;
if (PersistentPrimitiveIndexTemp != -1)
PersistentPrimitiveIndex = PersistentPrimitiveIndexTemp;
}
}
// UObject identity remains stable when the render state is recreated.
const uint32 PersistentPrimitiveIndex = component->GetUniqueID();
if (paintable_components.Num() == 1) {
if (UStaticMeshComponent* staticmesh_component = Cast<UStaticMeshComponent>(component)) {
if (actor->GetParentActor()) {
Expand Down Expand Up @@ -174,16 +164,8 @@ void FObjectAnnotator::getPaintableComponentMeshesAndTags(AActor* actor, TMap<FS
int index = 0;
for (auto component : paintable_components)
{
int32 PersistentPrimitiveIndex = component->GetUniqueID();
if (const UPrimitiveComponent* PrimitiveComp = Cast<UPrimitiveComponent>(component))
{
if (const FPrimitiveSceneProxy* SceneProxy = PrimitiveComp->SceneProxy)
{
int32 PersistentPrimitiveIndexTemp = SceneProxy->GetPrimitiveSceneInfo()->GetPersistentIndex().Index;
if (PersistentPrimitiveIndexTemp != -1)
PersistentPrimitiveIndex = PersistentPrimitiveIndexTemp;
}
}
// UObject identity remains stable when the render state is recreated.
const uint32 PersistentPrimitiveIndex = component->GetUniqueID();
if (paintable_components.Num() == 1) {
if (UStaticMeshComponent* staticmesh_component = Cast<UStaticMeshComponent>(component)) {
if (actor->GetParentActor()) {
Expand Down Expand Up @@ -712,28 +694,23 @@ bool FObjectAnnotator::AnnotateNewActorTexture(AActor* actor) {

bool FObjectAnnotator::DeleteActor(AActor* actor)
{
if (actor && IsPaintable(actor)) {
TMap<FString, UMeshComponent*> paintable_components_meshes;
getPaintableComponentMeshes(actor, &paintable_components_meshes);
for (auto it = paintable_components_meshes.CreateConstIterator(); it; ++it)
{
if (name_to_component_map_.Contains(it.Key())) {
component_to_name_map_.Remove(it.Value());
check(DeleteComponent(it.Value()));
name_to_component_map_.Remove(it.Key());
//UE_LOG(LogTemp, Log, TEXT("AirSim Annotation [%s]: Deleted object %s."), *name_, *it.Key());

}
else {
UE_LOG(LogTemp, Log, TEXT("AirSim Annotation [%s]: could not delete object %s."), *name_, *it.Key());
return false;
}
}
return true;
}
else {
return false;
}
if (!IsValid(actor)) return false;
TArray<UMeshComponent*> components;
actor->GetComponents<UMeshComponent>(components);
for (UMeshComponent* component : components) {
// Resolve the original registration, not a freshly generated render index.
const FString* registered_name = component_to_name_map_.Find(component);
if (registered_name == nullptr) continue;
const FString component_name = *registered_name;
verify(DeleteComponent(component));
component_to_name_map_.Remove(component);
name_to_component_map_.Remove(component_name);
name_to_color_index_map_.Remove(component_name);
name_to_gammacorrected_color_map_.Remove(component_name);
name_to_value_map_.Remove(component_name);
name_to_texture_path_map_.Remove(component_name);
}
return true;
}

uint32 FObjectAnnotator::GetComponentIndex(FString component_id)
Expand Down Expand Up @@ -1216,7 +1193,7 @@ TArray<TWeakObjectPtr<UPrimitiveComponent>> FObjectAnnotator::GetAnnotationComp

std::vector<std::string> FObjectAnnotator::GetAllComponentNames() {
std::vector<std::string> retval;
TMap<FString, uint32> nameToColorIndexMapTemp = name_to_color_index_map_;
TMap<FString, UMeshComponent*> nameToColorIndexMapTemp = name_to_component_map_;
for (auto const& element : nameToColorIndexMapTemp) {
retval.emplace_back(std::string(TCHAR_TO_UTF8(*element.Key)));
}
Expand Down
1 change: 1 addition & 0 deletions Unreal/Plugins/AirSim/Source/WorldSimApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ bool WorldSimApi::destroyObject(const std::string& object_name)
UAirBlueprintLib::RunCommandOnGameThread([this, &object_name, &result]() {
AActor* actor = UAirBlueprintLib::FindActor<AActor>(simmode_, FString(object_name.c_str()));
if (actor) {
simmode_->DeleteActorFromInstanceSegmentation(actor, true);
actor->Destroy();
result = !IsValid(actor);
}
Expand Down