From ea6c14b6c59600b5113f5b33d3f511f99bc2e7c5 Mon Sep 17 00:00:00 2001 From: doterop Date: Wed, 5 Aug 2020 09:42:01 +0200 Subject: [PATCH 001/179] Fix wrong condition on empty atlas --- .../Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp index 908425cf42a..44c1b720d1d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp @@ -567,7 +567,7 @@ bool ASceneCaptureSensor::CopyTextureFromAtlas( // and our image has been initialized uint32 ExpectedSize = (uint32)(PositionInAtlas.Y * AtlasTextureWidth + ImageWidth * ImageHeight); uint32 TotalSize = (uint32)AtlasImage.Num(); - if(AtlasImage.GetData() && TotalSize < ExpectedSize) + if(!AtlasImage.GetData() || TotalSize == 0 || TotalSize < ExpectedSize) { return false; } From 7bf2b87356c4b9a1b655f188d766c86f37474949 Mon Sep 17 00:00:00 2001 From: doterop Date: Wed, 5 Aug 2020 15:49:30 +0200 Subject: [PATCH 002/179] Avoided atlas and added checks to avoid invalid resources --- .../Carla/Source/Carla/Game/CarlaGameModeBase.cpp | 5 +++-- .../Carla/Source/Carla/Sensor/DepthCamera.cpp | 4 +++- .../Carla/Source/Carla/Sensor/PixelReader.cpp | 12 ++++++++++-- .../Plugins/Carla/Source/Carla/Sensor/PixelReader.h | 6 ++++++ .../Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp | 4 +++- .../Carla/Sensor/SemanticSegmentationCamera.cpp | 4 +++- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp index 9c615b3d65c..b11a99891f3 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp @@ -205,7 +205,8 @@ void ACarlaGameModeBase::BeginPlay() Recorder->GetReplayer()->CheckPlayAfterMapLoaded(); } - CaptureAtlasDelegate = FCoreDelegates::OnEndFrame.AddUObject(this, &ACarlaGameModeBase::CaptureAtlas); + // CaptureAtlasDelegate = FCoreDelegates::OnEndFrameRT.AddUObject(this, &ACarlaGameModeBase::CaptureAtlas); + CaptureAtlasDelegate = FCoreDelegates::OnEndFrameRT.AddUObject(this, &ACarlaGameModeBase::SendAtlas); } @@ -219,7 +220,7 @@ void ACarlaGameModeBase::Tick(float DeltaSeconds) Recorder->Tick(DeltaSeconds); } - SendAtlas(); + //SendAtlas(); } void ACarlaGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.cpp index c60abf9911e..e4ca1341ea8 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.cpp @@ -37,5 +37,7 @@ void ADepthCamera::SendPixels(const TArray& AtlasImage, uint32 AtlasText if(!GameMode->IsCameraStreamEnabled()) return; #endif - SendPixelsInStream(*this, AtlasImage, AtlasTextureWidth); + // SendPixelsInStream(*this, AtlasImage, AtlasTextureWidth); + + FPixelReader::SendPixelsInRenderThread(*this); } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp index 18ecb5792e1..4c7aa397ee0 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp @@ -151,7 +151,12 @@ void FPixelReader::WritePixelsToBuffer( } #endif // CARLA_WITH_VULKAN_SUPPORT - FRHITexture2D *Texture = RenderTarget.GetRenderTargetResource()->GetRenderTargetTexture(); + FTextureRenderTargetResource* RenderTargetResource = RenderTarget.GetRenderTargetResource(); + if(!RenderTargetResource) + { + return; + } + FRHITexture2D *Texture = RenderTargetResource->GetRenderTargetTexture(); checkf(Texture != nullptr, TEXT("FPixelReader: UTextureRenderTarget2D missing render target texture")); const uint32 BytesPerPixel = 4u; // PF_R8G8B8A8 @@ -182,7 +187,10 @@ void FPixelReader::WritePixelsToBuffer( { check(ExpectedStride == SrcStride); const uint8 *Source = Lock.Source; - Buffer.copy_from(Offset, Source, ExpectedStride * Height); + if(Source) + { + Buffer.copy_from(Offset, Source, ExpectedStride * Height); + } } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.h index e640caff4fd..e7045220d29 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.h @@ -91,6 +91,11 @@ void FPixelReader::SendPixelsInRenderThread(TSensor &Sensor) { check(Sensor.CaptureRenderTarget != nullptr); + if (!Sensor.HasActorBegunPlay() || Sensor.IsPendingKill()) + { + return; + } + // Enqueue a command in the render-thread that will write the image buffer to // the data stream. The stream is created in the capture thus executed in the // game-thread. @@ -108,6 +113,7 @@ void FPixelReader::SendPixelsInRenderThread(TSensor &Sensor) carla::sensor::SensorRegistry::get::type::header_offset, InRHICmdList); + if(Buffer.data()) { SCOPE_CYCLE_COUNTER(STAT_CarlaSensorStreamSend); Stream.Send(Sensor, std::move(Buffer)); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp index c86d2271414..7e480606d2f 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp @@ -31,5 +31,7 @@ void ASceneCaptureCamera::SendPixels(const TArray& AtlasImage, uint32 At if(!GameMode->IsCameraStreamEnabled()) return; #endif - SendPixelsInStream(*this, AtlasImage, AtlasTextureWidth); + //SendPixelsInStream(*this, AtlasImage, AtlasTextureWidth); + + FPixelReader::SendPixelsInRenderThread(*this); } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.cpp index df085db7bcc..8f6e6497395 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.cpp @@ -33,5 +33,7 @@ void ASemanticSegmentationCamera::SendPixels(const TArray& AtlasImage, u if(!GameMode->IsCameraStreamEnabled()) return; #endif - SendPixelsInStream(*this, AtlasImage, AtlasTextureWidth); + //SendPixelsInStream(*this, AtlasImage, AtlasTextureWidth); + + FPixelReader::SendPixelsInRenderThread(*this); } From 33508ad1be9c41bf0926d0ceef818f4afd077853 Mon Sep 17 00:00:00 2001 From: erdnaxe Date: Wed, 2 Sep 2020 12:08:46 +0200 Subject: [PATCH 003/179] Upgrade carla Docker image to Ubuntu 18.04 (#3054) Co-authored-by: bernat --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25900160e7f..09212aa1e7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## CARLA 0.9.10 + + * Upgraded carla Docker image to Ubuntu 18.04 * Added PythonAPI `carla.Osm2Odr.convert()` function and `calra.Osm2OdrSettings` class to support Open Street Maps to OpenDRIVE conversions * Upgraded to AD RSS v4.0.1 supporting unstructured scenes and pedestrians, and fixed spdlog to v1.7.0 * Fixed a bug in `spawn_npc_sumo` script computing not allowed routes for a given vehicle class From fc2b3627eaa836293aac41e846375280f18c1114 Mon Sep 17 00:00:00 2001 From: Simran Verma <36468747+simmranvermaa@users.noreply.github.com> Date: Wed, 2 Sep 2020 15:45:55 +0530 Subject: [PATCH 004/179] Update start_introduction.md (#3201) Co-authored-by: bernat --- Docs/start_introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/start_introduction.md b/Docs/start_introduction.md index bf8d1771910..753b021d4de 100644 --- a/Docs/start_introduction.md +++ b/Docs/start_introduction.md @@ -14,7 +14,7 @@ In order to smooth the process of developing, training and validating driving sy ## The simulator The CARLA simulator consists of a scalable client-server architecture. -The server is responsible of everything related with the simulation itself: sensor rendering, computation of physics, updates on the world-state and its actors and much more. As it aims for realistic results, the best fit would be running the server with a dedicated GPU, especially when dealing with machine learning. +The server is responsible for everything related with the simulation itself: sensor rendering, computation of physics, updates on the world-state and its actors and much more. As it aims for realistic results, the best fit would be running the server with a dedicated GPU, especially when dealing with machine learning. The client side consists of a sum of client modules controlling the logic of actors on scene and setting world conditions. This is achieved by leveraging the CARLA API (in Python or C++), a layer that mediates between server and client that is constantly evolving to provide new functionalities. ![CARLA Modules](img/carla_modules.png) From 5a6e41d45703080c3c3c9de251c54bb278596d36 Mon Sep 17 00:00:00 2001 From: Simran Verma <36468747+simmranvermaa@users.noreply.github.com> Date: Wed, 2 Sep 2020 15:47:12 +0530 Subject: [PATCH 005/179] Update CHANGELOG.md (#3202) Co-authored-by: bernat --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09212aa1e7e..8377998dfc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ * Added configurable noise to Lidar sensor * Replace deprectated `platform.dist()` with recommended `distro.linux_distribution()` * Improved the performance on capture sensors. + * Fixed minor typo in the introduction section of documentation. ## CARLA 0.9.9 From 8cff64fd00b0a0fadcaee2c8277c468a1f0a0a69 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Tue, 25 Aug 2020 16:31:53 +0200 Subject: [PATCH 006/179] Added new semantic tags --- .../source/carla/image/CityScapesPalette.h | 13 +++--- .../Carla/Source/Carla/Game/Tagger.cpp | 42 ++++++++++++------- .../Plugins/Carla/Source/Carla/Game/Tagger.h | 5 +++ 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/LibCarla/source/carla/image/CityScapesPalette.h b/LibCarla/source/carla/image/CityScapesPalette.h index 28f39351425..44724b454ff 100644 --- a/LibCarla/source/carla/image/CityScapesPalette.h +++ b/LibCarla/source/carla/image/CityScapesPalette.h @@ -20,8 +20,8 @@ namespace detail { uint8_t CITYSCAPES_PALETTE_MAP[][3u] = { { 0u, 0u, 0u}, // unlabeled = 0u, { 70u, 70u, 70u}, // building = 1u, - {190u, 153u, 153u}, // fence = 2u, - {250u, 170u, 160u}, // other = 3u, + {100u, 40u, 40u}, // fence = 2u, + { 55u, 90u, 80u}, // other = 3u, {220u, 20u, 60u}, // pedestrian = 4u, {153u, 153u, 153u}, // pole = 5u, {157u, 234u, 50u}, // road line = 6u, @@ -34,6 +34,11 @@ namespace detail { { 70u, 130u, 180u}, // sky = 13u, { 81u, 0u, 81u}, // ground = 14u, {150u, 100u, 100u}, // bridge = 15u, + {230u, 150u, 140u}, // rail track = 16u, + {180u, 165u, 180u}, // guard rail = 17u, + {110u, 190u, 160u}, // traffic light = 18u, + { 45u, 60u, 150u}, // static = 19u, + {250u, 170u, 30u}, // dynamic = 20u, // { 0u, 0u, 70u}, // truck // { 0u, 0u, 90u}, // caravan // { 0u, 0u, 110u}, // trailer @@ -41,14 +46,10 @@ namespace detail { // { 0u, 0u, 230u}, // motorcycle // { 0u, 60u, 100u}, // bus // { 0u, 80u, 100u}, // train - // {111u, 74u, 0u}, // dynamic // {119u, 11u, 32u}, // bicycle // {150u, 120u, 90u}, // tunnel // {152u, 251u, 152u}, // terrain // {153u, 153u, 153u}, // polegroup - // {180u, 165u, 180u}, // guard rail - // {230u, 150u, 140u}, // rail track - // {250u, 170u, 30u}, // traffic light // {250u, 170u, 160u}, // parking // {255u, 0u, 0u}, // rider }; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp index 89b8b4a491d..766dda5b884 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp @@ -21,22 +21,27 @@ static auto CastEnum(T label) } ECityObjectLabel ATagger::GetLabelByFolderName(const FString &String) { - if (String == "Buildings") return ECityObjectLabel::Buildings; - else if (String == "Fences") return ECityObjectLabel::Fences; - else if (String == "Pedestrians") return ECityObjectLabel::Pedestrians; - else if (String == "Pole") return ECityObjectLabel::Poles; - else if (String == "Props") return ECityObjectLabel::Other; - else if (String == "Road") return ECityObjectLabel::Roads; - else if (String == "RoadLines") return ECityObjectLabel::RoadLines; - else if (String == "SideWalk") return ECityObjectLabel::Sidewalks; - else if (String == "TrafficSigns") return ECityObjectLabel::TrafficSigns; - else if (String == "Vegetation") return ECityObjectLabel::Vegetation; - else if (String == "Vehicles") return ECityObjectLabel::Vehicles; - else if (String == "Walls") return ECityObjectLabel::Walls; - else if (String == "Sky") return ECityObjectLabel::Sky; - else if (String == "Ground") return ECityObjectLabel::Ground; - else if (String == "Bridge") return ECityObjectLabel::Bridge; - else return ECityObjectLabel::None; + if (String == "Building") return ECityObjectLabel::Buildings; + else if (String == "Fence") return ECityObjectLabel::Fences; + else if (String == "Pedestrian") return ECityObjectLabel::Pedestrians; + else if (String == "Pole") return ECityObjectLabel::Poles; + else if (String == "Other") return ECityObjectLabel::Other; + else if (String == "Road") return ECityObjectLabel::Roads; + else if (String == "RoadLine") return ECityObjectLabel::RoadLines; + else if (String == "SideWalk") return ECityObjectLabel::Sidewalks; + else if (String == "TrafficSign") return ECityObjectLabel::TrafficSigns; + else if (String == "Vegetation") return ECityObjectLabel::Vegetation; + else if (String == "Vehicle") return ECityObjectLabel::Vehicles; + else if (String == "Wall") return ECityObjectLabel::Walls; + else if (String == "Sky") return ECityObjectLabel::Sky; + else if (String == "Ground") return ECityObjectLabel::Ground; + else if (String == "Bridge") return ECityObjectLabel::Bridge; + else if (String == "RailTrack") return ECityObjectLabel::RailTrack; + else if (String == "GuardRail") return ECityObjectLabel::GuardRail; + else if (String == "TrafficLight") return ECityObjectLabel::TrafficLight; + else if (String == "Static") return ECityObjectLabel::Static; + else if (String == "Dynamic") return ECityObjectLabel::Dynamic; + else return ECityObjectLabel::None; } void ATagger::SetStencilValue( @@ -126,6 +131,11 @@ FString ATagger::GetTagAsString(const ECityObjectLabel Label) CARLA_GET_LABEL_STR(Sky) CARLA_GET_LABEL_STR(Ground) CARLA_GET_LABEL_STR(Bridge) + CARLA_GET_LABEL_STR(RailTrack) + CARLA_GET_LABEL_STR(GuardRail) + CARLA_GET_LABEL_STR(TrafficLight) + CARLA_GET_LABEL_STR(Static) + CARLA_GET_LABEL_STR(Dynamic) #undef CARLA_GET_LABEL_STR } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h index a15e188ac60..a8142ac0bbc 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h @@ -28,6 +28,11 @@ enum class ECityObjectLabel : uint8 Sky = 13u, Ground = 14u, Bridge = 15u, + RailTrack = 16u, + GuardRail = 17u, + TrafficLight = 18u, + Static = 19u, + Dynamic = 20u, }; /// Sets actors' custom depth stencil value for semantic segmentation according From c6b6fe6d718877b818f5dc04e3194c9c2fa81914 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Tue, 25 Aug 2020 16:33:56 +0200 Subject: [PATCH 007/179] Added color tags in opend3d.py --- PythonAPI/examples/opend3d.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/PythonAPI/examples/opend3d.py b/PythonAPI/examples/opend3d.py index 2c191e6c209..3f4eadc4e30 100644 --- a/PythonAPI/examples/opend3d.py +++ b/PythonAPI/examples/opend3d.py @@ -34,8 +34,8 @@ LABEL_COLORS = np.array([ (255, 255, 255), # None (70, 70, 70), # Buildings - (190, 153, 153), # Fences - (250, 170, 160), # Other + (100, 40, 40), # Fences + (55, 90, 80), # Other (220, 20, 60), # Pedestrians (153, 153, 153), # Poles (157, 234, 50), # RoadLines @@ -47,7 +47,12 @@ (220, 220, 0), # TrafficSign (70, 130, 180), # Sky (81, 0, 81), # Ground - (150, 100, 100) # Bridge + (150, 100, 100), # Bridge + (230, 150, 140), # RailTrack + (180, 165, 180), # GuardRail + (110, 190, 160), # TrafficLight + (45, 60, 150), # Static + (250, 170, 30), # Dynamic ]) / 255.0 # normalize each channel [0-1] since is what Open3D uses From 564a15989b63a0dfee9d153dcb9e8707b8bb7d94 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Wed, 26 Aug 2020 12:26:14 +0200 Subject: [PATCH 008/179] Added sem seg water and changed Dynamic color --- LibCarla/source/carla/image/CityScapesPalette.h | 5 +++-- PythonAPI/examples/opend3d.py | 17 +++++++++-------- .../Plugins/Carla/Source/Carla/Game/Tagger.cpp | 2 ++ .../Plugins/Carla/Source/Carla/Game/Tagger.h | 1 + 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/LibCarla/source/carla/image/CityScapesPalette.h b/LibCarla/source/carla/image/CityScapesPalette.h index 44724b454ff..d5d894a6cb8 100644 --- a/LibCarla/source/carla/image/CityScapesPalette.h +++ b/LibCarla/source/carla/image/CityScapesPalette.h @@ -28,7 +28,7 @@ namespace detail { {128u, 64u, 128u}, // road = 7u, {244u, 35u, 232u}, // sidewalk = 8u, {107u, 142u, 35u}, // vegetation = 9u, - { 0u, 0u, 142u}, // car = 10u, + { 0u, 0u, 142u}, // vehicle = 10u, {102u, 102u, 156u}, // wall = 11u, {220u, 220u, 0u}, // traffic sign = 12u, { 70u, 130u, 180u}, // sky = 13u, @@ -38,7 +38,8 @@ namespace detail { {180u, 165u, 180u}, // guard rail = 17u, {110u, 190u, 160u}, // traffic light = 18u, { 45u, 60u, 150u}, // static = 19u, - {250u, 170u, 30u}, // dynamic = 20u, + {170u, 120u, 50u}, // dynamic = 20u, + { 45u, 60u, 150u}, // water = 21u, // { 0u, 0u, 70u}, // truck // { 0u, 0u, 90u}, // caravan // { 0u, 0u, 110u}, // trailer diff --git a/PythonAPI/examples/opend3d.py b/PythonAPI/examples/opend3d.py index 3f4eadc4e30..1001e51144c 100644 --- a/PythonAPI/examples/opend3d.py +++ b/PythonAPI/examples/opend3d.py @@ -33,17 +33,17 @@ VID_RANGE = np.linspace(0.0, 1.0, VIRIDIS.shape[0]) LABEL_COLORS = np.array([ (255, 255, 255), # None - (70, 70, 70), # Buildings + (70, 70, 70), # Building (100, 40, 40), # Fences (55, 90, 80), # Other - (220, 20, 60), # Pedestrians - (153, 153, 153), # Poles + (220, 20, 60), # Pedestrian + (153, 153, 153), # Pole (157, 234, 50), # RoadLines - (128, 64, 128), # Roads - (244, 35, 232), # Sidewalks + (128, 64, 128), # Road + (244, 35, 232), # Sidewalk (107, 142, 35), # Vegetation - (0, 0, 142), # Car - (102, 102, 156), # Walls + (0, 0, 142), # Vehicle + (102, 102, 156), # Wall (220, 220, 0), # TrafficSign (70, 130, 180), # Sky (81, 0, 81), # Ground @@ -52,7 +52,8 @@ (180, 165, 180), # GuardRail (110, 190, 160), # TrafficLight (45, 60, 150), # Static - (250, 170, 30), # Dynamic + (170, 120, 50), # Dynamic + (45, 60, 150), # Water ]) / 255.0 # normalize each channel [0-1] since is what Open3D uses diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp index 766dda5b884..9a9eacf5566 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp @@ -41,6 +41,7 @@ ECityObjectLabel ATagger::GetLabelByFolderName(const FString &String) { else if (String == "TrafficLight") return ECityObjectLabel::TrafficLight; else if (String == "Static") return ECityObjectLabel::Static; else if (String == "Dynamic") return ECityObjectLabel::Dynamic; + else if (String == "Water") return ECityObjectLabel::Water; else return ECityObjectLabel::None; } @@ -136,6 +137,7 @@ FString ATagger::GetTagAsString(const ECityObjectLabel Label) CARLA_GET_LABEL_STR(TrafficLight) CARLA_GET_LABEL_STR(Static) CARLA_GET_LABEL_STR(Dynamic) + CARLA_GET_LABEL_STR(Water) #undef CARLA_GET_LABEL_STR } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h index a8142ac0bbc..a4631785371 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h @@ -33,6 +33,7 @@ enum class ECityObjectLabel : uint8 TrafficLight = 18u, Static = 19u, Dynamic = 20u, + Water = 21u, }; /// Sets actors' custom depth stencil value for semantic segmentation according From 3918ce2d6d7dd1856f490f796979c8e93de6d753 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Wed, 26 Aug 2020 12:40:31 +0200 Subject: [PATCH 009/179] Fixed name for new paths --- Unreal/CarlaUE4/Source/CarlaUE4/CarlaMapGenerator.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Unreal/CarlaUE4/Source/CarlaUE4/CarlaMapGenerator.cpp b/Unreal/CarlaUE4/Source/CarlaUE4/CarlaMapGenerator.cpp index a322704eef8..3592b499be0 100644 --- a/Unreal/CarlaUE4/Source/CarlaUE4/CarlaMapGenerator.cpp +++ b/Unreal/CarlaUE4/Source/CarlaUE4/CarlaMapGenerator.cpp @@ -23,8 +23,8 @@ ACarlaMapGenerator::ACarlaMapGenerator(const FObjectInitializer& ObjectInitializ SET_STATIC_MESH(RoadTwoLanes_LaneRight, PREFIX_FOLDER "Road", "St_Road_TileRoad_RoadR"); SET_STATIC_MESH(RoadTwoLanes_SidewalkLeft, PREFIX_FOLDER "SideWalk", "St_Road_TileRoad_SidewalkL"); SET_STATIC_MESH(RoadTwoLanes_SidewalkRight, PREFIX_FOLDER "SideWalk", "St_Road_TileRoad_SidewalkR"); - SET_STATIC_MESH(RoadTwoLanes_LaneMarkingSolid, PREFIX_FOLDER "RoadLines", "St_Road_TileRoad_LaneMarkingSolid"); - SET_STATIC_MESH(RoadTwoLanes_LaneMarkingBroken, PREFIX_FOLDER "RoadLines", "St_Road_TileRoad_LaneMarkingBroken"); + SET_STATIC_MESH(RoadTwoLanes_LaneMarkingSolid, PREFIX_FOLDER "RoadLine", "St_Road_TileRoad_LaneMarkingSolid"); + SET_STATIC_MESH(RoadTwoLanes_LaneMarkingBroken, PREFIX_FOLDER "RoadLine", "St_Road_TileRoad_LaneMarkingBroken"); SET_STATIC_MESH(Road90DegTurn_Lane0, PREFIX_FOLDER "Road", "St_Road_Curve_Road0"); SET_STATIC_MESH(Road90DegTurn_Lane1, PREFIX_FOLDER "Road", "St_Road_Curve_Road1"); @@ -40,7 +40,7 @@ ACarlaMapGenerator::ACarlaMapGenerator(const FObjectInitializer& ObjectInitializ SET_STATIC_MESH(Road90DegTurn_Sidewalk1, PREFIX_FOLDER "SideWalk", "St_Road_Curve_Sidewalk2"); SET_STATIC_MESH(Road90DegTurn_Sidewalk2, PREFIX_FOLDER "SideWalk", "St_Road_Curve_Sidewalk3"); SET_STATIC_MESH(Road90DegTurn_Sidewalk3, PREFIX_FOLDER "SideWalk", "St_Road_Curve_Sidewalk4"); - SET_STATIC_MESH(Road90DegTurn_LaneMarking, PREFIX_FOLDER "RoadLines", "St_Road_Curve_LaneMarking"); + SET_STATIC_MESH(Road90DegTurn_LaneMarking, PREFIX_FOLDER "RoadLine", "St_Road_Curve_LaneMarking"); SET_STATIC_MESH(RoadTIntersection_Lane0, PREFIX_FOLDER "Road", "St_Road_TCross_Road0"); SET_STATIC_MESH(RoadTIntersection_Lane1, PREFIX_FOLDER "Road", "St_Road_TCross_Road1"); @@ -56,7 +56,7 @@ ACarlaMapGenerator::ACarlaMapGenerator(const FObjectInitializer& ObjectInitializ SET_STATIC_MESH(RoadTIntersection_Sidewalk1, PREFIX_FOLDER "SideWalk", "St_Road_TCross_Sidewalk2"); SET_STATIC_MESH(RoadTIntersection_Sidewalk2, PREFIX_FOLDER "SideWalk", "St_Road_TCross_Sidewalk3"); SET_STATIC_MESH(RoadTIntersection_Sidewalk3, PREFIX_FOLDER "SideWalk", "St_Road_TCross_Sidewalk4"); - SET_STATIC_MESH(RoadTIntersection_LaneMarking, PREFIX_FOLDER "RoadLines", "St_Road_TCross_LaneMarking"); + SET_STATIC_MESH(RoadTIntersection_LaneMarking, PREFIX_FOLDER "RoadLine", "St_Road_TCross_LaneMarking"); SET_STATIC_MESH(RoadXIntersection_Lane0, PREFIX_FOLDER "Road", "St_Road_XCross_Road0"); SET_STATIC_MESH(RoadXIntersection_Lane1, PREFIX_FOLDER "Road", "St_Road_XCross_Road1"); @@ -72,7 +72,7 @@ ACarlaMapGenerator::ACarlaMapGenerator(const FObjectInitializer& ObjectInitializ SET_STATIC_MESH(RoadXIntersection_Sidewalk1, PREFIX_FOLDER "SideWalk", "St_Road_XCross_Sidewalk2"); SET_STATIC_MESH(RoadXIntersection_Sidewalk2, PREFIX_FOLDER "SideWalk", "St_Road_XCross_Sidewalk3"); SET_STATIC_MESH(RoadXIntersection_Sidewalk3, PREFIX_FOLDER "SideWalk", "St_Road_XCross_Sidewalk4"); - SET_STATIC_MESH(RoadXIntersection_LaneMarking, PREFIX_FOLDER "RoadLines", "St_Road_XCross_LaneMarking"); + SET_STATIC_MESH(RoadXIntersection_LaneMarking, PREFIX_FOLDER "RoadLine", "St_Road_XCross_LaneMarking"); #undef PREFIX_FOLDER #undef SET_STATIC_MESH From 36ba6216c9630577b72258628ac56e69dd332bf2 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Wed, 26 Aug 2020 12:49:13 +0200 Subject: [PATCH 010/179] Fixed TrafficLight name --- .../Carla/Source/Carla/Traffic/TrafficLightManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightManager.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightManager.cpp index 07a4bc38384..e5222d6c39d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightManager.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightManager.cpp @@ -33,7 +33,7 @@ ATrafficLightManager::ATrafficLightManager() } // Default traffic signs models static ConstructorHelpers::FClassFinder StopFinder( - TEXT( "/Game/Carla/Static/TrafficSigns/BP_Stop" ) ); + TEXT( "/Game/Carla/Static/TrafficSign/BP_Stop" ) ); if (StopFinder.Succeeded()) { TSubclassOf StopSignModel = StopFinder.Class; @@ -41,7 +41,7 @@ ATrafficLightManager::ATrafficLightManager() SignComponentModels.Add(carla::road::SignalType::StopSign().c_str(), UStopSignComponent::StaticClass()); } static ConstructorHelpers::FClassFinder YieldFinder( - TEXT( "/Game/Carla/Static/TrafficSigns/BP_Yield" ) ); + TEXT( "/Game/Carla/Static/TrafficSign/BP_Yield" ) ); if (YieldFinder.Succeeded()) { TSubclassOf YieldSignModel = YieldFinder.Class; From 1726e88192219b64f2cb2b3afe6a12cb3fc412cd Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Fri, 28 Aug 2020 15:29:58 +0200 Subject: [PATCH 011/179] Added fix to OS dependant exposure compensation --- .../Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp index 44c1b720d1d..11d0308a8a8 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp @@ -110,7 +110,13 @@ EAutoExposureMethod ASceneCaptureSensor::GetExposureMethod() const void ASceneCaptureSensor::SetExposureCompensation(float Compensation) { check(CaptureComponent2D != nullptr); + // Looks like windows and linux have different outputs with the + // same exposure compensation +#ifdef PLATFORM_WINDOWS + CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation + 2.2; +#else CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation; +#endif } float ASceneCaptureSensor::GetExposureCompensation() const From 44225dabb45ce4348e58a9f00b2e1b80e04dd231 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Fri, 28 Aug 2020 15:47:37 +0200 Subject: [PATCH 012/179] Added and extra s to the Vehicles folder --- Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp index 9a9eacf5566..29af25b3c88 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp @@ -31,7 +31,7 @@ ECityObjectLabel ATagger::GetLabelByFolderName(const FString &String) { else if (String == "SideWalk") return ECityObjectLabel::Sidewalks; else if (String == "TrafficSign") return ECityObjectLabel::TrafficSigns; else if (String == "Vegetation") return ECityObjectLabel::Vegetation; - else if (String == "Vehicle") return ECityObjectLabel::Vehicles; + else if (String == "Vehicles") return ECityObjectLabel::Vehicles; else if (String == "Wall") return ECityObjectLabel::Walls; else if (String == "Sky") return ECityObjectLabel::Sky; else if (String == "Ground") return ECityObjectLabel::Ground; From 8a02d7aa7b12d001da22f96731907b2094686bc5 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Fri, 28 Aug 2020 17:20:21 +0200 Subject: [PATCH 013/179] Fixed Linux detection in exposure compensation --- .../Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp index 11d0308a8a8..5b300fec7a2 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp @@ -112,10 +112,10 @@ void ASceneCaptureSensor::SetExposureCompensation(float Compensation) check(CaptureComponent2D != nullptr); // Looks like windows and linux have different outputs with the // same exposure compensation -#ifdef PLATFORM_WINDOWS - CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation + 2.2; -#else +#if PLATFORM_LINUX CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation; +#else + CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation + 2.2f; #endif } From aabde2182baa6ad6a9640719c21fc7a4cbb94fc0 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Mon, 31 Aug 2020 10:59:14 +0200 Subject: [PATCH 014/179] Small color fix --- LibCarla/source/carla/image/CityScapesPalette.h | 4 ++-- PythonAPI/examples/opend3d.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/LibCarla/source/carla/image/CityScapesPalette.h b/LibCarla/source/carla/image/CityScapesPalette.h index d5d894a6cb8..1499b9760d9 100644 --- a/LibCarla/source/carla/image/CityScapesPalette.h +++ b/LibCarla/source/carla/image/CityScapesPalette.h @@ -36,8 +36,8 @@ namespace detail { {150u, 100u, 100u}, // bridge = 15u, {230u, 150u, 140u}, // rail track = 16u, {180u, 165u, 180u}, // guard rail = 17u, - {110u, 190u, 160u}, // traffic light = 18u, - { 45u, 60u, 150u}, // static = 19u, + {250u, 170u, 30u}, // traffic light = 18u, + {110u, 190u, 160u}, // static = 19u, {170u, 120u, 50u}, // dynamic = 20u, { 45u, 60u, 150u}, // water = 21u, // { 0u, 0u, 70u}, // truck diff --git a/PythonAPI/examples/opend3d.py b/PythonAPI/examples/opend3d.py index 1001e51144c..55cdd14873e 100644 --- a/PythonAPI/examples/opend3d.py +++ b/PythonAPI/examples/opend3d.py @@ -50,8 +50,8 @@ (150, 100, 100), # Bridge (230, 150, 140), # RailTrack (180, 165, 180), # GuardRail - (110, 190, 160), # TrafficLight - (45, 60, 150), # Static + (250, 170, 30), # TrafficLight + (110, 190, 160), # Static (170, 120, 50), # Dynamic (45, 60, 150), # Water ]) / 255.0 # normalize each channel [0-1] since is what Open3D uses From d75e1516b31f1fdf468f46a231d649319138c74b Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Tue, 1 Sep 2020 13:03:00 +0200 Subject: [PATCH 015/179] Fixed open3d name --- PythonAPI/examples/{opend3d.py => open3d.py} | 1 + 1 file changed, 1 insertion(+) rename PythonAPI/examples/{opend3d.py => open3d.py} (99%) diff --git a/PythonAPI/examples/opend3d.py b/PythonAPI/examples/open3d.py similarity index 99% rename from PythonAPI/examples/opend3d.py rename to PythonAPI/examples/open3d.py index 55cdd14873e..f3fbe4418d2 100644 --- a/PythonAPI/examples/opend3d.py +++ b/PythonAPI/examples/open3d.py @@ -54,6 +54,7 @@ (110, 190, 160), # Static (170, 120, 50), # Dynamic (45, 60, 150), # Water + (145, 170, 100), # Terrain ]) / 255.0 # normalize each channel [0-1] since is what Open3D uses From b15f0d2d50a9d81fa97668118e071cf3e4eff3c1 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Tue, 1 Sep 2020 13:03:27 +0200 Subject: [PATCH 016/179] Added Terrain sem seg label --- LibCarla/source/carla/image/CityScapesPalette.h | 2 +- Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp | 2 ++ Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/LibCarla/source/carla/image/CityScapesPalette.h b/LibCarla/source/carla/image/CityScapesPalette.h index 1499b9760d9..2be428e31bb 100644 --- a/LibCarla/source/carla/image/CityScapesPalette.h +++ b/LibCarla/source/carla/image/CityScapesPalette.h @@ -40,6 +40,7 @@ namespace detail { {110u, 190u, 160u}, // static = 19u, {170u, 120u, 50u}, // dynamic = 20u, { 45u, 60u, 150u}, // water = 21u, + {145u, 170u, 100u}, // terrain = 22u, // { 0u, 0u, 70u}, // truck // { 0u, 0u, 90u}, // caravan // { 0u, 0u, 110u}, // trailer @@ -49,7 +50,6 @@ namespace detail { // { 0u, 80u, 100u}, // train // {119u, 11u, 32u}, // bicycle // {150u, 120u, 90u}, // tunnel - // {152u, 251u, 152u}, // terrain // {153u, 153u, 153u}, // polegroup // {250u, 170u, 160u}, // parking // {255u, 0u, 0u}, // rider diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp index 29af25b3c88..b5011fc66a2 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp @@ -42,6 +42,7 @@ ECityObjectLabel ATagger::GetLabelByFolderName(const FString &String) { else if (String == "Static") return ECityObjectLabel::Static; else if (String == "Dynamic") return ECityObjectLabel::Dynamic; else if (String == "Water") return ECityObjectLabel::Water; + else if (String == "Terrain") return ECityObjectLabel::Terrain; else return ECityObjectLabel::None; } @@ -138,6 +139,7 @@ FString ATagger::GetTagAsString(const ECityObjectLabel Label) CARLA_GET_LABEL_STR(Static) CARLA_GET_LABEL_STR(Dynamic) CARLA_GET_LABEL_STR(Water) + CARLA_GET_LABEL_STR(Terrain) #undef CARLA_GET_LABEL_STR } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h index a4631785371..7237bcaaf10 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h @@ -34,6 +34,7 @@ enum class ECityObjectLabel : uint8 Static = 19u, Dynamic = 20u, Water = 21u, + Terrain = 22u, }; /// Sets actors' custom depth stencil value for semantic segmentation according From 537409d91edf06c8ae044f4e977b0b7b045b6cfc Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Wed, 2 Sep 2020 13:05:40 +0200 Subject: [PATCH 017/179] Updated ContentVersions and CHANGELOG --- CHANGELOG.md | 2 ++ Util/ContentVersions.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8377998dfc5..6a8afa71f22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ * Fixed recorder determinism problems * Added function to stop the replayer * Added Light ids + * Added new semantic segmenation tags: `RailTrack`, `GuardRail`, `TrafficLight`, `Static`, `Dynamic`, `Water` and `Terrain` + * Fixed several untagged and mistagged objects * Added vehicle light and street light data to recorder * Added API function `add_angular_impulse()` to add angular impulse to any actor * Fixed rain drop spawn issues when spawning camera sensors diff --git a/Util/ContentVersions.txt b/Util/ContentVersions.txt index 511a3a5f249..846181d6c35 100644 --- a/Util/ContentVersions.txt +++ b/Util/ContentVersions.txt @@ -32,4 +32,4 @@ 0.9.7: 20191221_c88604b 0.9.8: 20200306_06b6cb1 0.9.9: 20200422_ea5179a -0.9.10: 20200731_3e91044 +Latest: 20200902_8d5419c From 5f67e28821b02f999a654642de41e0a2fc63416d Mon Sep 17 00:00:00 2001 From: "Pasch, Frederik" Date: Tue, 1 Sep 2020 14:51:41 +0200 Subject: [PATCH 018/179] Update RSS library to 4.1.0 Add setMapLogLevel() to rss sensor API --- LibCarla/source/carla/rss/RssCheck.cpp | 19 ++++++++++++------- LibCarla/source/carla/rss/RssCheck.h | 3 +++ LibCarla/source/carla/rss/RssSensor.cpp | 11 +++++++++++ LibCarla/source/carla/rss/RssSensor.h | 3 +++ PythonAPI/carla/source/libcarla/AdRss.cpp | 1 + Util/BuildTools/Ad-rss.sh | 2 +- 6 files changed, 31 insertions(+), 8 deletions(-) diff --git a/LibCarla/source/carla/rss/RssCheck.cpp b/LibCarla/source/carla/rss/RssCheck.cpp index 15dfe3b354f..713cf9a62e2 100644 --- a/LibCarla/source/carla/rss/RssCheck.cpp +++ b/LibCarla/source/carla/rss/RssCheck.cpp @@ -131,6 +131,7 @@ RssCheck::RssCheck(float maximum_steering_angle) _timing_logger->set_level(spdlog::level::off); SetLogLevel(spdlog::level::warn); + SetMapLogLevel(spdlog::level::warn); _default_actor_constellation_callback_ego_vehicle_dynamics = GetDefaultVehicleDynamics(); _default_actor_constellation_callback_other_vehicle_dynamics = GetDefaultVehicleDynamics(); @@ -208,6 +209,7 @@ RssCheck::RssCheck(float maximum_steering_angle, _timing_logger->set_level(spdlog::level::off); SetLogLevel(spdlog::level::warn); + SetMapLogLevel(spdlog::level::warn); _carla_rss_state.ego_match_object = GetMatchObject(carla_ego_actor, ::ad::physics::Distance(2.0)); UpdateDefaultRssDynamics(_carla_rss_state); @@ -220,8 +222,11 @@ RssCheck::~RssCheck() {} void RssCheck::SetLogLevel(const spdlog::level::level_enum &log_level) { spdlog::set_level(log_level); _logger->set_level(log_level); - ::ad::map::access::getLogger()->set_level(log_level); - ::ad::rss::map::getLogger()->set_level(log_level); +} + +void RssCheck::SetMapLogLevel(const spdlog::level::level_enum &map_log_level) { + ::ad::map::access::getLogger()->set_level(map_log_level); + ::ad::rss::map::getLogger()->set_level(map_log_level); } const ::ad::rss::world::RssDynamics &RssCheck::GetDefaultActorConstellationCallbackEgoVehicleDynamics() const { @@ -337,7 +342,7 @@ bool RssCheck::CheckObjects(carla::client::Timestamp const ×tamp, _carla_rss_state.ego_match_object = ego_match_object; - _logger->debug("MapMatch:: {}", _carla_rss_state.ego_match_object); + _logger->trace("MapMatch:: {}", _carla_rss_state.ego_match_object); #if DEBUG_TIMING t_end = std::chrono::high_resolution_clock::now(); @@ -471,7 +476,7 @@ ::ad::physics::Angle RssCheck::GetSteeringAngle(carla::client::Vehicle const &ac } void RssCheck::UpdateRoute(CarlaRssState &carla_rss_state) { - _logger->debug("Update route start: {}", carla_rss_state.ego_route); + _logger->trace("Update route start: {}", carla_rss_state.ego_route); // remove the parts of the route already taken, try to prepend route sections // (i.e. when driving backwards) @@ -588,7 +593,7 @@ void RssCheck::UpdateRoute(CarlaRssState &carla_rss_state) { } } - _logger->debug("Update route result: {}", carla_rss_state.ego_route); + _logger->trace("Update route result: {}", carla_rss_state.ego_route); } EgoDynamicsOnRoute RssCheck::CalculateEgoDynamicsOnRoute( @@ -819,7 +824,7 @@ void RssCheck::RssObjectChecker::operator()( try { auto other_match_object = _rss_check.GetMatchObject(other_traffic_participant, ::ad::physics::Distance(2.0)); - _rss_check._logger->debug("OtherVehicleMapMatching: {} {}", other_traffic_participant->GetId(), + _rss_check._logger->trace("OtherVehicleMapMatching: {} {}", other_traffic_participant->GetId(), other_match_object.mapMatchedBoundingBox); carla::SharedPtr actor_constellation_data{new ActorConstellationData{ @@ -1005,7 +1010,7 @@ void RssCheck::AnalyseCheckResults(CarlaRssState &carla_rss_state) const { carla_rss_state.ego_dynamics_on_route.crossing_border = true; } - _logger->debug("RouteResponse: {}", carla_rss_state.proper_response); + _logger->trace("RouteResponse: {}", carla_rss_state.proper_response); } } // namespace rss diff --git a/LibCarla/source/carla/rss/RssCheck.h b/LibCarla/source/carla/rss/RssCheck.h index 3a7b13e5874..b24ae3c70ff 100644 --- a/LibCarla/source/carla/rss/RssCheck.h +++ b/LibCarla/source/carla/rss/RssCheck.h @@ -175,6 +175,9 @@ class RssCheck { /// @brief sets the current log level void SetLogLevel(const spdlog::level::level_enum &log_level); + /// @brief sets the current log level + void SetMapLogLevel(const spdlog::level::level_enum &map_log_level); + /// @returns the current mode for respecting the road boundaries (@see also /// RssSensor::GetRoadBoundariesMode()) const ::carla::rss::RoadBoundariesMode &GetRoadBoundariesMode() const; diff --git a/LibCarla/source/carla/rss/RssSensor.cpp b/LibCarla/source/carla/rss/RssSensor.cpp index 81b2e27e151..c7018161659 100644 --- a/LibCarla/source/carla/rss/RssSensor.cpp +++ b/LibCarla/source/carla/rss/RssSensor.cpp @@ -119,6 +119,17 @@ void RssSensor::SetLogLevel(const uint8_t &log_level) { } } +void RssSensor::SetMapLogLevel(const uint8_t &map_log_level) { + if (!bool(_rss_check)) { + log_error(GetDisplayId(), ": not yet listening. SetMapLogLevel has no effect."); + return; + } + + if (map_log_level < spdlog::level::n_levels) { + _rss_check->SetMapLogLevel(spdlog::level::level_enum(map_log_level)); + } +} + const ::ad::rss::world::RssDynamics &RssSensor::GetEgoVehicleDynamics() const { static auto default_vehicle_dynamics = rss::RssCheck::GetDefaultVehicleDynamics(); if (!bool(_rss_check)) { diff --git a/LibCarla/source/carla/rss/RssSensor.h b/LibCarla/source/carla/rss/RssSensor.h index 37bb7ffcc89..89833a9fd68 100644 --- a/LibCarla/source/carla/rss/RssSensor.h +++ b/LibCarla/source/carla/rss/RssSensor.h @@ -77,6 +77,9 @@ class RssSensor : public Sensor { /// @brief sets the current log level void SetLogLevel(const uint8_t &log_level); + /// @brief sets the current map log level + void SetMapLogLevel(const uint8_t &map_log_level); + /// @returns the currently used dynamics of the ego vehicle (@see also /// RssCheck::GetEgoVehicleDynamics()) const ::ad::rss::world::RssDynamics &GetEgoVehicleDynamics() const; diff --git a/PythonAPI/carla/source/libcarla/AdRss.cpp b/PythonAPI/carla/source/libcarla/AdRss.cpp index e095063e2f1..d18ff1b5354 100644 --- a/PythonAPI/carla/source/libcarla/AdRss.cpp +++ b/PythonAPI/carla/source/libcarla/AdRss.cpp @@ -200,6 +200,7 @@ void export_ad_rss() { .def("reset_routing_targets", &cc::RssSensor::ResetRoutingTargets) .def("drop_route", &cc::RssSensor::DropRoute) .def("set_log_level", &cc::RssSensor::SetLogLevel, (arg("log_level"))) + .def("set_map_log_level", &cc::RssSensor::SetMapLogLevel, (arg("map_log_level"))) .def(self_ns::str(self_ns::self)); class_>("RssRestrictor", diff --git a/Util/BuildTools/Ad-rss.sh b/Util/BuildTools/Ad-rss.sh index 15e06576de9..2be72ae0ddb 100755 --- a/Util/BuildTools/Ad-rss.sh +++ b/Util/BuildTools/Ad-rss.sh @@ -31,7 +31,7 @@ else git clone --depth=1 -b v1.7.0 https://github.com/gabime/spdlog.git git clone --depth=1 -b 4.9.3 https://github.com/OSGeo/PROJ.git git clone --depth=1 -b v2.1.0 https://github.com/carla-simulator/map.git - git clone --depth=1 -b v4.0.1 https://github.com/intel/ad-rss-lib.git + git clone --depth=1 -b v4.1.0 https://github.com/intel/ad-rss-lib.git popd cat >"${CARLA_BUILD_FOLDER}/${ADRSS_BASENAME}/colcon.meta" < Date: Tue, 1 Sep 2020 14:55:27 +0200 Subject: [PATCH 019/179] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a8afa71f22..70c1dec1959 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ * Upgraded carla Docker image to Ubuntu 18.04 * Added PythonAPI `carla.Osm2Odr.convert()` function and `calra.Osm2OdrSettings` class to support Open Street Maps to OpenDRIVE conversions - * Upgraded to AD RSS v4.0.1 supporting unstructured scenes and pedestrians, and fixed spdlog to v1.7.0 + * Upgraded to AD RSS v4.1.0 supporting unstructured scenes and pedestrians, and fixed spdlog to v1.7.0 * Fixed a bug in `spawn_npc_sumo` script computing not allowed routes for a given vehicle class * Fixed a bug where `get_traffic_light` would always return `None` * Changed frozen behavior for traffic lights. It now affects to all traffic lights at the same time From 251d2bbbb751bb3e3f881b4093acb8e89e6f680f Mon Sep 17 00:00:00 2001 From: "Pasch, Frederik" Date: Wed, 2 Sep 2020 15:54:46 +0200 Subject: [PATCH 020/179] Remove switch to different default rss parameter, add new members --- PythonAPI/examples/rss/manual_control_rss.py | 7 ---- PythonAPI/examples/rss/rss_sensor.py | 38 ++++++++------------ 2 files changed, 14 insertions(+), 31 deletions(-) diff --git a/PythonAPI/examples/rss/manual_control_rss.py b/PythonAPI/examples/rss/manual_control_rss.py index 74008b6e352..a5ad1147c7f 100755 --- a/PythonAPI/examples/rss/manual_control_rss.py +++ b/PythonAPI/examples/rss/manual_control_rss.py @@ -102,7 +102,6 @@ from pygame.locals import K_q from pygame.locals import K_r from pygame.locals import K_s - from pygame.locals import K_t from pygame.locals import K_w from pygame.locals import K_l from pygame.locals import K_i @@ -420,12 +419,6 @@ def parse_events(self, world, clock): elif event.key == K_g: if self._world and self._world.rss_sensor: self._world.rss_sensor.drop_route() - elif event.key == K_t: - if self._world and self._world.rss_sensor: - if self._world.rss_sensor.assertive_parameters: - self._world.rss_sensor.set_default_parameters() - else: - self._world.rss_sensor.set_assertive_parameters() if isinstance(self._control, carla.VehicleControl): if event.key == K_q: self._control.gear = 1 if self._control.reverse else -1 diff --git a/PythonAPI/examples/rss/rss_sensor.py b/PythonAPI/examples/rss/rss_sensor.py index 187795f3aaf..de8897785d9 100644 --- a/PythonAPI/examples/rss/rss_sensor.py +++ b/PythonAPI/examples/rss/rss_sensor.py @@ -298,29 +298,6 @@ def destroy(self): def toggle_debug_visualization_mode(self): self.debug_visualizer.toggleMode() - @staticmethod - def get_assertive_parameters(): - ego_dynamics = rss.RssDynamics() - ego_dynamics.alphaLon.accelMax = 4.1 - ego_dynamics.alphaLon.brakeMax = -8.03 - ego_dynamics.alphaLon.brakeMin = -4.64 - ego_dynamics.alphaLon.brakeMinCorrect = -1.76 - ego_dynamics.alphaLat.accelMax = 0.43 - ego_dynamics.alphaLat.brakeMin = -0.96 - ego_dynamics.lateralFluctuationMargin = 0.07 - ego_dynamics.responseTime = 0.25 # paper: 0.53 - ego_dynamics.maxSpeedOnAcceleration = 100 - ego_dynamics.unstructuredSettings.pedestrianTurningRadius = 2.0 - ego_dynamics.unstructuredSettings.driveAwayMaxAngle = 2.4 - ego_dynamics.unstructuredSettings.vehicleYawRateChange = 0.3 - ego_dynamics.unstructuredSettings.vehicleMinRadius = 3.5 - ego_dynamics.unstructuredSettings.vehicleTrajectoryCalculationStep = 0.2 - return ego_dynamics - - def set_assertive_parameters(self): - print("Use 'assertive' RSS Parameters") - self.current_vehicle_parameters = self.get_assertive_parameters() - @staticmethod def get_default_parameters(): ego_dynamics = rss.RssDynamics() @@ -331,13 +308,18 @@ def get_default_parameters(): ego_dynamics.alphaLat.accelMax = 0.2 ego_dynamics.alphaLat.brakeMin = -0.8 ego_dynamics.lateralFluctuationMargin = 0.1 - ego_dynamics.responseTime = 1.0 + ego_dynamics.responseTime = 0.5 ego_dynamics.maxSpeedOnAcceleration = 100 ego_dynamics.unstructuredSettings.pedestrianTurningRadius = 2.0 ego_dynamics.unstructuredSettings.driveAwayMaxAngle = 2.4 ego_dynamics.unstructuredSettings.vehicleYawRateChange = 0.3 ego_dynamics.unstructuredSettings.vehicleMinRadius = 3.5 ego_dynamics.unstructuredSettings.vehicleTrajectoryCalculationStep = 0.2 + ego_dynamics.unstructuredSettings.vehicleFrontIntermediateRatioSteps = 4 + ego_dynamics.unstructuredSettings.vehicleBackIntermediateRatioSteps = 0 + ego_dynamics.unstructuredSettings.vehicleContinueForwardIntermediateAccelerationSteps = 0 + ego_dynamics.unstructuredSettings.vehicleBrakeIntermediateAccelerationSteps = 0 + ego_dynamics.unstructuredSettings.vehicleResponseTimeIntermediateAccelerationSteps = 4 return ego_dynamics def set_default_parameters(self): @@ -358,9 +340,17 @@ def get_pedestrian_parameters(): pedestrian_dynamics.maxSpeedOnAcceleration = 10 pedestrian_dynamics.unstructuredSettings.pedestrianTurningRadius = 2.0 pedestrian_dynamics.unstructuredSettings.driveAwayMaxAngle = 2.4 + + #not used: pedestrian_dynamics.unstructuredSettings.vehicleYawRateChange = 0.3 pedestrian_dynamics.unstructuredSettings.vehicleMinRadius = 3.5 pedestrian_dynamics.unstructuredSettings.vehicleTrajectoryCalculationStep = 0.2 + pedestrian_dynamics.unstructuredSettings.vehicleTrajectoryCalculationStep = 0.2 + pedestrian_dynamics.unstructuredSettings.vehicleFrontIntermediateRatioSteps = 4 + pedestrian_dynamics.unstructuredSettings.vehicleBackIntermediateRatioSteps = 0 + pedestrian_dynamics.unstructuredSettings.vehicleContinueForwardIntermediateAccelerationSteps = 0 + pedestrian_dynamics.unstructuredSettings.vehicleBrakeIntermediateAccelerationSteps = 0 + pedestrian_dynamics.unstructuredSettings.vehicleResponseTimeIntermediateAccelerationSteps = 4 return pedestrian_dynamics def get_steering_ranges(self): From 8e4eabb7b8aaa14205bf03affca5c2fe4b2594f9 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 2 Sep 2020 12:32:00 +0200 Subject: [PATCH 021/179] First draft --- Docs/cont_contribution_guidelines.md | 155 ++++++++++++++------------- Docs/cont_doc_standard.md | 29 ++--- 2 files changed, 96 insertions(+), 88 deletions(-) diff --git a/Docs/cont_contribution_guidelines.md b/Docs/cont_contribution_guidelines.md index 71c80bd01ff..9ad168b083e 100644 --- a/Docs/cont_contribution_guidelines.md +++ b/Docs/cont_contribution_guidelines.md @@ -1,20 +1,23 @@ # Contributing to CARLA -We are more than happy to accept contributions! +The CARLA team is glad to accept contributions from anybody willing to collaborate. There are different ways to contribute to the project, depending on the capabilities of the contributor. The team will work as much as possible so that contributions are successfully integrated in CARLA. -How can I contribute? +Take a look and don't hesitate! -* Reporting bugs -* Feature requests -* Improving documentation -* Code contributions +* [__Report bugs__](#report-bugs) +* [__Request features__](#request-features) +* [__Art contributions__](#art-contributions) +* [__Docs contributions__](#docs-contributions) +* [__Code contributions__](#code-contributions) --- -## Reporting bugs +## Report bugs -Use our [issue section][issueslink] on GitHub. Please check before that the -issue is not already reported, and make sure you have read our -[Documentation][docslink] and [FAQ][faqlink]. +Issues can be reported in the [issue section][issueslink] on GitHub. Before reporting a new bug, make sure to do some checkups. + +__1. Check if the bug has been reported.__ Look it up in that same issue section on GitHub. + +__2. Read the docs.__ Make sure that the issue is a bug, not a misunderstanding on how is CARLA supposed to work. Read the pages related to the issue in the [Documentation][docslink] and take a look at the [FAQ][faqlink] page. [issueslink]: https://github.com/carla-simulator/carla/issues [docslink]: http://carla.readthedocs.io @@ -23,102 +26,104 @@ issue is not already reported, and make sure you have read our --- ## Feature requests -Please check first the list of [feature requests][frlink]. If it is not there -and you think is a feature that might be interesting for users, please submit -your request as a new issue. +Ideas for new features are also a great way to contribute. Any suggestion that could improve the users' experience can be submitted in the corresponding GitHub section [here][frlink]. [frlink]: https://github.com/carla-simulator/carla/issues?q=is%3Aissue+is%3Aopen+label%3A%22feature+request%22+sort%3Acomments-desc --- -## Improving documentation +## Art contributions + +Art contributions include vehicles, walkers, maps or any other type of assets to be used in CARLA. These are stored in a BitBucket repository, which has some account space limitations. For said reason, the contributor will have to get in touch with the CARLA team, and ask them to create a branch on the content repository for the contributions. + +__1. Create a BitBucket account.__ Visit the [Bitbucket page](https://bitbucket.org). + +__2. Contact the art team to get access to the content repository.__ Join the [Discord server](https://discord.com/invite/8kqACuC). Go to the __Contributors__ channel and request for access to the content repostory. + +__3. A branch will be created for each contributor.__ The branch will be named as `contributors/contributor_name`. All the contributions made by said user should be made in that corresponding branch. + +__4. Build CARLA.__ In order to contribute, a CARLA build is necessary. Follow the instructions to build either in [Linux](https://carla.readthedocs.io/en/latest/build_linux/) or [Windows](https://carla.readthedocs.io/en/latest/build_windows/). + +__5. Download the content repository.__ Follow the instructions to update the content in [here](https://carla.readthedocs.io/en/latest/build_update/#get-development-assets). + +__6. Update the branch to be in sync with master.__ The branch should always be updated with the latest changes in master. + +__7. Upload the contribution.__ Do the corresponding changes and push the branch to origin. + +__8. Wait for the art team to check it up.__ Once the contribution is uploaded, the team will check that everything is prepared to be merged with master. + + +--- +## Docs contributions + +If some documentation is missing, vague or imprecise, it can be reported as with any other bug (read the previous section on [how to report bugs](#report-bugs)). However, users can contribute by writing documentation. -If you feel something is missing in the documentation, please don't hesitate to -open an issue to let us know. Even better, if you think you can improve it -yourself, it would be a great contribution to the community! +The documentation is written with a mix of [Markdown](https://www.markdownguide.org/) and HTML tags, with a some extra CSS code for features such as tables or the [town slider](https://carla.readthedocs.io/en/latest/core_map/#carla-maps). Follow the steps below to start writing documentation. -We build our documentation with [MkDocs](http://www.mkdocs.org/) based on the -Markdown files inside the `Docs` folder. You can either directly modify them on -GitHub or locally in your machine. +__1. Build CARLA from source.__ Follow the steps in the docs to build on [Linux](build_linux.md) or [Windows](build_windows.md). -To update Python API docs, instead of directly modifying the Markdown you need to edit the -corresponding YAML files inside [`carla/PythonAPI/docs/`][fileslink] and run [`doc_gen.py`][scriptlink] -or `make PythonAPI.docs`. -This will re-generate the respective Markdown files inside `carla/Docs/`, -which can then be fed into `mkdocs`. -[fileslink]: https://github.com/carla-simulator/carla/tree/master/PythonAPI/docs -[scriptlink]: https://github.com/carla-simulator/carla/blob/master/PythonAPI/docs/doc_gen.py +__2. Install [MkDocs](http://www.mkdocs.org/).__ MkDocs is a static site generator used to build documentation. -Once you are done with your changes, please submit a pull-request. +```sh +sudo pip install mkdocs +``` -!!! tip - You can build and serve it locally (at ) by running `mkdocs` - in the project's main folder. +__3. Visualize the docs.__ In the main CARLA folder, run the following command and click the link that appears in the terminal (http://127.0.0.1:8000) to open a local visualization of the documentation. + +```sh +mkdocs serve +``` +__4. Create a git branch.__ Make sure to be in the master branch (updated to latest changes) when creating a new one. ```sh - > sudo pip install mkdocs - > mkdocs serve +git checkout -b / ``` +__5. Write the docs.__ Edit the files following the guidelines in the [documentation standard](cont_doc_standard.md) page. + +__6. Submit the changes.__ Create a pull request in the GitHub repository, and add one of the suggested reviewers. Try to be as descriptive as possible when filling the pull-request description. + +__7. Wait for review.__ The team will check if everything is ready to be merged or any changes are needed. + +!!! Warning + The local repository must be updated with the latest updates in the master branch. + --- ## Code contributions -So you are considering making a code contribution, great! We love to have -contributions from the community. - -Before starting hands-on on coding, please check out our -[issue board][issueboard] to see if we are already working on that, it would -be a pity putting an effort into something just to discover that someone else -was already working on that. In case of doubt or to discuss how to proceed, -please contact one of us (or send an email to ). +Before starting hands-on on coding, please check out the [issue board][issueboard] to check what is the team already working on, to avoid overlapping. In case of doubt or to discuss how to proceed, please contact one of us (or send an email to ). [issueboard]: https://github.com/carla-simulator/carla/issues -#### Where can I learn more about Unreal Engine? +### Learn about Unreal Engine -A basic introduction to C++ programming with UE4 can be found at Unreal's -[C++ Programming Tutorials][ue4tutorials]. Then, if you want to dive into UE4 -C++ development there are few paying options online. The -[Unreal C++ Course at Udemy][ue4course] it's pretty complete and there are -usually offers that make it very affordable. +A basic introduction to C++ programming with UE4 can be found at Unreal's [C++ Programming Tutorials][ue4tutorials]. There are other options online, some of them not free of charge. The [Unreal C++ Course at Udemy][ue4course] it's pretty complete and there are usually offers that make it very affordable. [ue4tutorials]: https://docs.unrealengine.com/latest/INT/Programming/Tutorials/ [ue4course]: https://www.udemy.com/unrealcourse/ -#### What should I know before I get started? - -Check out the ["CARLA Design"](index.md) document to get an idea -on the different modules that compose CARLA, and chose the most appropriate one -to hold the new feature. We are aware the developers documentation is still -scarce, please ask us in case of doubt, and of course don't hesitate to improve -the current documentation if you feel confident enough. +### What should I know before I get started? -#### Coding standard +Check out the [CARLA Design](index.md) document to get an idea on the different modules that compose CARLA. Choose the most appropriate one +to hold the new feature. Feel free to contact the team in the [Discord server](https://discord.com/invite/8kqACuC) in case any doubt arises during the process. -Please follow the current [coding standard](cont_coding_standard.md) when submitting -new code. +### Coding standard -#### Pull-requests +Follow the current [coding standard](cont_coding_standard.md) when submitting new code. -Once you think your contribution is ready to be added to CARLA, please submit a -pull-request. +### Submission -Try to be as descriptive as possible when filling the pull-request description. -Adding images and gifs may help people to understand your changes or new -features. +Contributions and new features are not merged directly to the `master` branch, but to an intermediate branch named `dev`. This [Gitflow](https://nvie.com/posts/a-successful-git-branching-model/) branching model makes it easier to maintain a stable master branch. This model requires a specific workflow for contributions. -Please note that there are some checks that the new code is required to pass -before we can do the merge. The checks are automatically run by the continuous -integration system, you will see a green tick mark if all the checks succeeded. -If you see a red mark, please correct your code accordingly. +* Always keep your `dev` branch updated with the lastest changes. +* Develop the contribution in child branch from `dev` named as `username/name_of_the_contribution`. +* Once the contribution is ready, submit a pull-request from your branch to `dev`. Try to be as descriptive as possible when filling the description. Note that there are some checks that the new code is required to pass before merging. The checks are automatically run by the continuous integration system. A green tick mark will appear if the checks are successful. If a red mark, please correct the code accordingly. -###### Checklist +Once the contribution is merged in `dev`, it can be tested with the rest of new features. By the time of the next release, the `dev` branch will be merged to `master`, and the contribution will be available and announced. - +### Checklist - - [ ] Your branch is up-to-date with the `master` branch and tested with latest changes - - [ ] Extended the README / documentation, if necessary - - [ ] Code compiles correctly - - [ ] All tests passing with `make check` +* [ ] Your branch is up-to-date with the `dev` branch and tested with latest changes. +* [ ] Extended the README/documentation, if necessary. +* [ ] Code compiles correctly. +* [ ] All tests passing with `make check`. \ No newline at end of file diff --git a/Docs/cont_doc_standard.md b/Docs/cont_doc_standard.md index 84a58067861..69796623e9b 100644 --- a/Docs/cont_doc_standard.md +++ b/Docs/cont_doc_standard.md @@ -3,23 +3,26 @@ This document will serve as a guide and example of some rules that need to be followed in order to contribute to the documentation. -We use a mix of markdown and HTML tags to customize the documentation along with an -[`extra.css`](https://github.com/carla-simulator/carla/tree/master/Docs/extra.css) file. +--- +## Docs structure + +We use a mix of markdown and HTML tags to customize the documentation along with an [`extra.css`](https://github.com/carla-simulator/carla/tree/master/Docs/extra.css) file. +To update Python API docs, instead of directly modifying the Markdown you need to edit the corresponding YAML files inside [`carla/PythonAPI/docs/`][fileslink] and run [`doc_gen.py`][scriptlink] or `make PythonAPI.docs`. + +This will re-generate the respective Markdown files inside `carla/Docs/`, which can then be fed into `mkdocs`. + +[fileslink]: https://github.com/carla-simulator/carla/tree/master/PythonAPI/docs +[scriptlink]: https://github.com/carla-simulator/carla/blob/master/PythonAPI/docs/doc_gen.py --- ## Rules - - * Leave always an empty line between sections and at the end of the document. - * Writting should not exceed `100` columns, except for HTML related content, markdown tables, - code snipets and referenced links. - * If an inline link exceeds the limit, use referenced `[name][reference_link]` markdown notation - `[reference_link]: https://` rather than `[name](https://)`. - * Use `
` to make inline jumps rather than leaving two spaces at the end of a line. - * Use `

Title

` at the beggining of a new page in order to make a Title or - `Heading` to make a heading that **won't show** on the navigation bar. - * Use `------` underlining a Heading or `#` hierarchy to make headings and show them in the - navigation bar. +* Leave always an empty line between sections and at the end of the document. +* Writting should not exceed `100` columns, except for HTML related content, markdown tables, code snipets and referenced links. +* If an inline link exceeds the limit, use referenced `[name][reference_link]` markdown notation `[reference_link]: https://` rather than `[name](https://)`. +* Use `
` to make inline jumps rather than leaving two spaces at the end of a line. +* Use `

Title

` at the beggining of a new page in order to make a Title or `Heading` to make a heading that **won't show** on the navigation bar. +* Use `------` underlining a Heading or `#` hierarchy to make headings and show them in the navigation bar. --- ## Exceptions From 787e3bc5c2f56523271dc3a28521b173a4ffbfc7 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 2 Sep 2020 12:43:49 +0200 Subject: [PATCH 022/179] Changed order and new note on docs contributions --- Docs/cont_contribution_guidelines.md | 89 ++++++++++++++-------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/Docs/cont_contribution_guidelines.md b/Docs/cont_contribution_guidelines.md index 9ad168b083e..d7a19299408 100644 --- a/Docs/cont_contribution_guidelines.md +++ b/Docs/cont_contribution_guidelines.md @@ -6,9 +6,9 @@ Take a look and don't hesitate! * [__Report bugs__](#report-bugs) * [__Request features__](#request-features) +* [__Code contributions__](#code-contributions) * [__Art contributions__](#art-contributions) * [__Docs contributions__](#docs-contributions) -* [__Code contributions__](#code-contributions) --- ## Report bugs @@ -30,6 +30,46 @@ Ideas for new features are also a great way to contribute. Any suggestion that c [frlink]: https://github.com/carla-simulator/carla/issues?q=is%3Aissue+is%3Aopen+label%3A%22feature+request%22+sort%3Acomments-desc +--- +## Code contributions + +Before starting hands-on on coding, please check out the [issue board][issueboard] to check what is the team already working on, to avoid overlapping. In case of doubt or to discuss how to proceed, please contact one of us (or send an email to ). + +[issueboard]: https://github.com/carla-simulator/carla/issues + +### Learn about Unreal Engine + +A basic introduction to C++ programming with UE4 can be found at Unreal's [C++ Programming Tutorials][ue4tutorials]. There are other options online, some of them not free of charge. The [Unreal C++ Course at Udemy][ue4course] it's pretty complete and there are usually offers that make it very affordable. + +[ue4tutorials]: https://docs.unrealengine.com/latest/INT/Programming/Tutorials/ +[ue4course]: https://www.udemy.com/unrealcourse/ + +### What should I know before I get started? + +Check out the [CARLA Design](index.md) document to get an idea on the different modules that compose CARLA. Choose the most appropriate one +to hold the new feature. Feel free to contact the team in the [Discord server](https://discord.com/invite/8kqACuC) in case any doubt arises during the process. + +### Coding standard + +Follow the current [coding standard](cont_coding_standard.md) when submitting new code. + +### Submission + +Contributions and new features are not merged directly to the `master` branch, but to an intermediate branch named `dev`. This [Gitflow](https://nvie.com/posts/a-successful-git-branching-model/) branching model makes it easier to maintain a stable master branch. This model requires a specific workflow for contributions. + +* Always keep your `dev` branch updated with the lastest changes. +* Develop the contribution in child branch from `dev` named as `username/name_of_the_contribution`. +* Once the contribution is ready, submit a pull-request from your branch to `dev`. Try to be as descriptive as possible when filling the description. Note that there are some checks that the new code is required to pass before merging. The checks are automatically run by the continuous integration system. A green tick mark will appear if the checks are successful. If a red mark, please correct the code accordingly. + +Once the contribution is merged in `dev`, it can be tested with the rest of new features. By the time of the next release, the `dev` branch will be merged to `master`, and the contribution will be available and announced. + +### Checklist + +* [ ] Your branch is up-to-date with the `dev` branch and tested with latest changes. +* [ ] Extended the README/documentation, if necessary. +* [ ] Code compiles correctly. +* [ ] All tests passing with `make check`. + --- ## Art contributions @@ -59,6 +99,9 @@ If some documentation is missing, vague or imprecise, it can be reported as with The documentation is written with a mix of [Markdown](https://www.markdownguide.org/) and HTML tags, with a some extra CSS code for features such as tables or the [town slider](https://carla.readthedocs.io/en/latest/core_map/#carla-maps). Follow the steps below to start writing documentation. +!!! Important + To submit docs contributions, follow the same workflow explained right above in [code contributions](#submission). To sum up, contributions are made in a child branch from `dev` and merged to said branch. + __1. Build CARLA from source.__ Follow the steps in the docs to build on [Linux](build_linux.md) or [Windows](build_windows.md). @@ -73,7 +116,7 @@ __3. Visualize the docs.__ In the main CARLA folder, run the following command a ```sh mkdocs serve ``` -__4. Create a git branch.__ Make sure to be in the master branch (updated to latest changes) when creating a new one. +__4. Create a git branch.__ Make sure to be in the `dev` branch (updated to latest changes) when creating a new one. ```sh git checkout -b / @@ -86,44 +129,4 @@ __6. Submit the changes.__ Create a pull request in the GitHub repository, and a __7. Wait for review.__ The team will check if everything is ready to be merged or any changes are needed. !!! Warning - The local repository must be updated with the latest updates in the master branch. - ---- -## Code contributions - -Before starting hands-on on coding, please check out the [issue board][issueboard] to check what is the team already working on, to avoid overlapping. In case of doubt or to discuss how to proceed, please contact one of us (or send an email to ). - -[issueboard]: https://github.com/carla-simulator/carla/issues - -### Learn about Unreal Engine - -A basic introduction to C++ programming with UE4 can be found at Unreal's [C++ Programming Tutorials][ue4tutorials]. There are other options online, some of them not free of charge. The [Unreal C++ Course at Udemy][ue4course] it's pretty complete and there are usually offers that make it very affordable. - -[ue4tutorials]: https://docs.unrealengine.com/latest/INT/Programming/Tutorials/ -[ue4course]: https://www.udemy.com/unrealcourse/ - -### What should I know before I get started? - -Check out the [CARLA Design](index.md) document to get an idea on the different modules that compose CARLA. Choose the most appropriate one -to hold the new feature. Feel free to contact the team in the [Discord server](https://discord.com/invite/8kqACuC) in case any doubt arises during the process. - -### Coding standard - -Follow the current [coding standard](cont_coding_standard.md) when submitting new code. - -### Submission - -Contributions and new features are not merged directly to the `master` branch, but to an intermediate branch named `dev`. This [Gitflow](https://nvie.com/posts/a-successful-git-branching-model/) branching model makes it easier to maintain a stable master branch. This model requires a specific workflow for contributions. - -* Always keep your `dev` branch updated with the lastest changes. -* Develop the contribution in child branch from `dev` named as `username/name_of_the_contribution`. -* Once the contribution is ready, submit a pull-request from your branch to `dev`. Try to be as descriptive as possible when filling the description. Note that there are some checks that the new code is required to pass before merging. The checks are automatically run by the continuous integration system. A green tick mark will appear if the checks are successful. If a red mark, please correct the code accordingly. - -Once the contribution is merged in `dev`, it can be tested with the rest of new features. By the time of the next release, the `dev` branch will be merged to `master`, and the contribution will be available and announced. - -### Checklist - -* [ ] Your branch is up-to-date with the `dev` branch and tested with latest changes. -* [ ] Extended the README/documentation, if necessary. -* [ ] Code compiles correctly. -* [ ] All tests passing with `make check`. \ No newline at end of file + The local repository must be updated with the latest updates in the `dev` branch. \ No newline at end of file From 15f93a68623509dd5ae6ead674f0d63389a72912 Mon Sep 17 00:00:00 2001 From: Axel Date: Thu, 3 Sep 2020 15:28:16 +0200 Subject: [PATCH 023/179] Added libpng to linux setup. --- LibCarla/cmake/client/CMakeLists.txt | 11 +++++++-- Util/BuildTools/Setup.sh | 36 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/LibCarla/cmake/client/CMakeLists.txt b/LibCarla/cmake/client/CMakeLists.txt index c0b9de355f2..ee7fabf2c7e 100644 --- a/LibCarla/cmake/client/CMakeLists.txt +++ b/LibCarla/cmake/client/CMakeLists.txt @@ -75,6 +75,11 @@ if (WIN32) # Install zlib lib. file(GLOB libpng_libraries "${LIBPNG_LIB_PATH}/*") install(FILES ${libpng_libraries} DESTINATION lib) +else () + # Install libpng library + install(DIRECTORY "${LIBPNG_INCLUDE_PATH}" DESTINATION include/system) + file(GLOB libcarla_carla_libpnglib "${LIBPNG_LIB_PATH}/*.*") + install(FILES ${libcarla_carla_libpnglib} DESTINATION lib) endif (WIN32) # Add sources. @@ -257,7 +262,8 @@ if (LIBCARLA_BUILD_RELEASE) target_include_directories(carla_client${carla_target_postfix} SYSTEM PRIVATE "${BOOST_INCLUDE_PATH}" "${RPCLIB_INCLUDE_PATH}" - "${RECAST_INCLUDE_PATH}") + "${RECAST_INCLUDE_PATH}" + "${LIBPNG_INCLUDE_PATH}") if (BUILD_RSS_VARIANT) target_compile_definitions(carla_client${carla_target_postfix} PRIVATE RSS_ENABLED RSS_USE_TBB) @@ -296,7 +302,8 @@ if (LIBCARLA_BUILD_DEBUG) target_include_directories(carla_client${carla_target_postfix}_debug SYSTEM PRIVATE "${BOOST_INCLUDE_PATH}" "${RPCLIB_INCLUDE_PATH}" - "${RECAST_INCLUDE_PATH}") + "${RECAST_INCLUDE_PATH}" + "${LIBPNG_INCLUDE_PATH}") if (BUILD_RSS_VARIANT) target_compile_definitions(carla_client${carla_target_postfix}_debug PRIVATE RSS_ENABLED RSS_USE_TBB) diff --git a/Util/BuildTools/Setup.sh b/Util/BuildTools/Setup.sh index a96e74b2646..c7e12d540a8 100755 --- a/Util/BuildTools/Setup.sh +++ b/Util/BuildTools/Setup.sh @@ -399,6 +399,40 @@ fi unset RECAST_BASENAME +# ============================================================================== +# -- Get and compile libpng 1.6.37 ------------------------------ +# ============================================================================== + +LIBPNG_VERSION=1.6.37 +LIBPNG_REPO=https://sourceforge.net/projects/libpng/files/libpng16/${LIBPNG_VERSION}/libpng-${LIBPNG_VERSION}.tar.xz +LIBPNG_BASENAME=libpng-${LIBPNG_VERSION} +LIBPNG_INSTALL=${LIBPNG_BASENAME}-install + +LIBPNG_INCLUDE=${PWD}/${LIBPNG_BASENAME}-install/include/libpng16 +LIBPNG_LIBPATH=${PWD}/${LIBPNG_BASENAME}-install/lib + +if [[ -d ${LIBPNG_INSTALL} ]] ; then + log "Libpng already installed." +else + log "Retrieving libpng." + wget ${LIBPNG_REPO} + + log "Extracting libpng." + tar -xf libpng-${LIBPNG_VERSION}.tar.xz + mv ${LIBPNG_BASENAME} ${LIBPNG_BASENAME}-source + + pushd ${LIBPNG_BASENAME}-source >/dev/null + + ./configure --prefix=${CARLA_BUILD_FOLDER}/${LIBPNG_INSTALL} + make install + + popd >/dev/null + + rm -Rf libpng-${LIBPNG_VERSION}.tar.xz + rm -Rf ${LIBPNG_BASENAME}-source +fi + + # ============================================================================== # -- Generate Version.h -------------------------------------------------------- # ============================================================================== @@ -495,6 +529,8 @@ elseif (CMAKE_BUILD_TYPE STREQUAL "Client") set(BOOST_LIB_PATH "${BOOST_LIBPATH}") set(RECAST_INCLUDE_PATH "${RECAST_INCLUDE}") set(RECAST_LIB_PATH "${RECAST_LIBPATH}") + set(LIBPNG_INCLUDE_PATH "${LIBPNG_INCLUDE}") + set(LIBPNG_LIB_PATH "${LIBPNG_LIBPATH}") endif () EOL From 63ad110bf52698c5e323bd235c4923dd6a8d0974 Mon Sep 17 00:00:00 2001 From: Axel Date: Thu, 3 Sep 2020 16:32:46 +0200 Subject: [PATCH 024/179] Fixed test compilation. --- LibCarla/cmake/test/CMakeLists.txt | 3 ++- Util/BuildTools/Setup.sh | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/LibCarla/cmake/test/CMakeLists.txt b/LibCarla/cmake/test/CMakeLists.txt index d2ac1ddf1b2..432f509e726 100644 --- a/LibCarla/cmake/test/CMakeLists.txt +++ b/LibCarla/cmake/test/CMakeLists.txt @@ -48,7 +48,8 @@ foreach(target ${build_targets}) target_include_directories(${target} SYSTEM PRIVATE "${BOOST_INCLUDE_PATH}" "${RPCLIB_INCLUDE_PATH}" - "${GTEST_INCLUDE_PATH}") + "${GTEST_INCLUDE_PATH}" + "${LIBPNG_INCLUDE_PATH}") target_include_directories(${target} PRIVATE "${libcarla_source_path}/test") diff --git a/Util/BuildTools/Setup.sh b/Util/BuildTools/Setup.sh index c7e12d540a8..a5a82eb1247 100755 --- a/Util/BuildTools/Setup.sh +++ b/Util/BuildTools/Setup.sh @@ -408,7 +408,7 @@ LIBPNG_REPO=https://sourceforge.net/projects/libpng/files/libpng16/${LIBPNG_VERS LIBPNG_BASENAME=libpng-${LIBPNG_VERSION} LIBPNG_INSTALL=${LIBPNG_BASENAME}-install -LIBPNG_INCLUDE=${PWD}/${LIBPNG_BASENAME}-install/include/libpng16 +LIBPNG_INCLUDE=${PWD}/${LIBPNG_BASENAME}-install/include/ LIBPNG_LIBPATH=${PWD}/${LIBPNG_BASENAME}-install/lib if [[ -d ${LIBPNG_INSTALL} ]] ; then From 53c6051091678da8d658fb7bb580f4acb945037a Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 2 Sep 2020 16:06:33 +0200 Subject: [PATCH 025/179] First draft --- Docs/ref_sensors.md | 68 +++++++++++++++++++++++++++++++--------- Docs/tuto_A_add_props.md | 29 +++++++++++------ 2 files changed, 73 insertions(+), 24 deletions(-) diff --git a/Docs/ref_sensors.md b/Docs/ref_sensors.md index 883a0f9687e..5366a3e235d 100644 --- a/Docs/ref_sensors.md +++ b/Docs/ref_sensors.md @@ -1448,55 +1448,95 @@ The following tags are currently available: 0 Unlabeled -( 0, 0, 0) +(0, 0, 0) 1 Building -( 70, 70, 70) +(70, 70, 70) 2 Fence -(190, 153, 153) +(100, 40, 40) 3 Other -(250, 170, 160) +(55, 90, 80) 4 Pedestrian -(220, 20, 60) +(220, 20, 60) 5 Pole -(153, 153, 153) +(153, 153, 153) 6 Road line -(157, 234, 50) +(157, 234, 50) 7 Road -(128, 64, 128) +(128, 64, 128) 8 Sidewalk -(244, 35, 232) +(244, 35, 232) 9 Vegetation -(107, 142, 35) +(107, 142, 35) 10 -Car -( 0, 0, 142) +Vehicle +(0, 0, 142) 11 Wall -(102, 102, 156) +(102, 102, 156) 12 Traffic sign -(220, 220, 0) +(220, 220, 0) + +13 +Sky +(70, 130, 180) + +14 +Ground +(81, 0, 81) + +15 +Bridge +(150, 100, 100) + +16 +Rail track +(230, 150, 140) + +17 +Guard rail +(180, 165, 180) + +18 +Traffic +(250, 170, 30) + +19 +Static +(110, 190, 160) + +20 +Dynamic +(170, 120, 50) + +21 +Water +(45, 60, 150) + +22 +Terrain +(145, 170, 100)
diff --git a/Docs/tuto_A_add_props.md b/Docs/tuto_A_add_props.md index a7716dceb73..ebcfbf66a50 100644 --- a/Docs/tuto_A_add_props.md +++ b/Docs/tuto_A_add_props.md @@ -57,22 +57,31 @@ __Props__ need the following parameters. * `medium` * `big` * `huge` -* __tag__ value for the semantic segmentation. If the tag is misspelled, it will be read as `None`. - * `None` - * `Buildings` - * `Fences` - * `Pedestrians` +* __tag__ value for the semantic segmentation. If the tag is misspelled, it will be read as `Unlabeled`. + * `Bridge` + * `Building` + * `Dynamic` + * `Fence` + * `Ground` + * `Guard rail` + * `Other` + * `Pedestrian` * `Pole` * `Props` - * `RailTrack` + * `Rail track` * `Road` - * `RoadLines` + * `Road line` * `Sidewalk` + * `Sky` + * `Static` * `Terrain` - * `TrafficSigns` + * `Traffic` + * `Traffic sign` + * `Unlabeled` * `Vegetation` - * `Vehicles` - * `Walls` + * `Vehicle` + * `Wall` + * `Water` In the end, the `.json` should look similar to the one below. From 140bb675d1d2f75e29dd995c60c9c008c1c279fd Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 2 Sep 2020 16:15:58 +0200 Subject: [PATCH 026/179] Minor fix in Python API --- Docs/python_api.md | 24 ++++++++++++++---------- PythonAPI/docs/sensor_data.yml | 20 ++++++++++---------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index 6ea8a7afda6..8cd7732b15c 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -377,6 +377,10 @@ Load a new world with default settings using `map_name` map. All actors present - `start` (_float_) – Time in seconds where to start playing the simulation. Negative is read as beginning from the end, being -10 just 10 seconds before the recording finished. - `duration` (_float_) – Time in seconds that will be reenacted using the information `name` file. If the end is reached, the simulation will continue. - `follow_id` (_int_) – ID of the actor to follow. If this is 0 then camera is disabled. +- **stop_replayer**(**self**, **keep_actors**) +Stop current replayer. + - **Parameters:** + - `keep_actors` (_bool_) – True if you want autoremove all actors from the replayer, or False to keep them. - **show_recorder_actors_blocked**(**self**, **filename**, **min_time**, **min_distance**) The terminal will show the information registered for actors considered blocked. An actor is considered blocked when it does not move a minimum distance in a period of time, being these `min_distance` and `min_time`. - **Parameters:** @@ -1804,16 +1808,16 @@ Commands the sensor to stop listening for data. --- ## carla.SensorData -Base class for all the objects containing data generated by a [carla.Sensor](#carla.Sensor). This objects should be the argument of the function said sensor is listening to, in order to work with them. Each of these sensors needs for a specific type of sensor data. Hereunder is a list of the sensors and their corresponding data. - - Cameras (RGB, depth and semantic segmentation): [carla.Image](#carla.Image). - - Collision detector: [carla.CollisionEvent](#carla.CollisionEvent). - - GNSS sensor: [carla.GnssMeasurement](#carla.GnssMeasurement). - - IMU sensor: [carla.IMUMeasurement](#carla.IMUMeasurement). - - Lane invasion detector: [carla.LaneInvasionEvent](#carla.LaneInvasionEvent). - - LIDAR sensor: [carla.LidarMeasurement](#carla.LidarMeasurement). - - Obstacle detector: [carla.ObstacleDetectionEvent](#carla.ObstacleDetectionEvent). - - Radar sensor: [carla.RadarMeasurement](#carla.RadarMeasurement). - - RSS sensor: [carla.RssResponse](#carla.RssResponse). +Base class for all the objects containing data generated by a [carla.Sensor](#carla.Sensor). This objects should be the argument of the function said sensor is listening to, in order to work with them. Each of these sensors needs for a specific type of sensor data. Hereunder is a list of the sensors and their corresponding data.
+ - Cameras (RGB, depth and semantic segmentation): [carla.Image](#carla.Image).
+ - Collision detector: [carla.CollisionEvent](#carla.CollisionEvent).
+ - GNSS sensor: [carla.GnssMeasurement](#carla.GnssMeasurement).
+ - IMU sensor: [carla.IMUMeasurement](#carla.IMUMeasurement).
+ - Lane invasion detector: [carla.LaneInvasionEvent](#carla.LaneInvasionEvent).
+ - LIDAR sensor: [carla.LidarMeasurement](#carla.LidarMeasurement).
+ - Obstacle detector: [carla.ObstacleDetectionEvent](#carla.ObstacleDetectionEvent).
+ - Radar sensor: [carla.RadarMeasurement](#carla.RadarMeasurement).
+ - RSS sensor: [carla.RssResponse](#carla.RssResponse).
- Semantic LIDAR sensor: [carla.SemanticLidarMeasurement](#carla.SemanticLidarMeasurement).

Instance Variables

diff --git a/PythonAPI/docs/sensor_data.yml b/PythonAPI/docs/sensor_data.yml index 890326abe93..8ba111626b1 100644 --- a/PythonAPI/docs/sensor_data.yml +++ b/PythonAPI/docs/sensor_data.yml @@ -5,16 +5,16 @@ - class_name: SensorData # - DESCRIPTION ------------------------ doc: > - Base class for all the objects containing data generated by a carla.Sensor. This objects should be the argument of the function said sensor is listening to, in order to work with them. Each of these sensors needs for a specific type of sensor data. Hereunder is a list of the sensors and their corresponding data. - - Cameras (RGB, depth and semantic segmentation): carla.Image. - - Collision detector: carla.CollisionEvent. - - GNSS sensor: carla.GnssMeasurement. - - IMU sensor: carla.IMUMeasurement. - - Lane invasion detector: carla.LaneInvasionEvent. - - LIDAR sensor: carla.LidarMeasurement. - - Obstacle detector: carla.ObstacleDetectionEvent. - - Radar sensor: carla.RadarMeasurement. - - RSS sensor: carla.RssResponse. + Base class for all the objects containing data generated by a carla.Sensor. This objects should be the argument of the function said sensor is listening to, in order to work with them. Each of these sensors needs for a specific type of sensor data. Hereunder is a list of the sensors and their corresponding data.
+ - Cameras (RGB, depth and semantic segmentation): carla.Image.
+ - Collision detector: carla.CollisionEvent.
+ - GNSS sensor: carla.GnssMeasurement.
+ - IMU sensor: carla.IMUMeasurement.
+ - Lane invasion detector: carla.LaneInvasionEvent.
+ - LIDAR sensor: carla.LidarMeasurement.
+ - Obstacle detector: carla.ObstacleDetectionEvent.
+ - Radar sensor: carla.RadarMeasurement.
+ - RSS sensor: carla.RssResponse.
- Semantic LIDAR sensor: carla.SemanticLidarMeasurement. # - PROPERTIES ------------------------- instance_variables: From 00fd4df4a8d26eb9653a20858b3f661b218876ad Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 2 Sep 2020 17:07:11 +0200 Subject: [PATCH 027/179] Fixed names to match tag folders --- Docs/ref_sensors.md | 14 +++++++------- Docs/tuto_A_add_props.md | 15 +++++++-------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/Docs/ref_sensors.md b/Docs/ref_sensors.md index 5366a3e235d..89cfbad6668 100644 --- a/Docs/ref_sensors.md +++ b/Docs/ref_sensors.md @@ -1471,7 +1471,7 @@ The following tags are currently available: (153, 153, 153) 6 -Road line +RoadLine (157, 234, 50) 7 @@ -1479,7 +1479,7 @@ The following tags are currently available: (128, 64, 128) 8 -Sidewalk +SideWalk (244, 35, 232) 9 @@ -1487,7 +1487,7 @@ The following tags are currently available: (107, 142, 35) 10 -Vehicle +Vehicles (0, 0, 142) 11 @@ -1495,7 +1495,7 @@ The following tags are currently available: (102, 102, 156) 12 -Traffic sign +TrafficSign (220, 220, 0) 13 @@ -1511,15 +1511,15 @@ The following tags are currently available: (150, 100, 100) 16 -Rail track +RailTrack (230, 150, 140) 17 -Guard rail +GuardRail (180, 165, 180) 18 -Traffic +TrafficLight (250, 170, 30) 19 diff --git a/Docs/tuto_A_add_props.md b/Docs/tuto_A_add_props.md index ebcfbf66a50..88ec4103dba 100644 --- a/Docs/tuto_A_add_props.md +++ b/Docs/tuto_A_add_props.md @@ -63,23 +63,22 @@ __Props__ need the following parameters. * `Dynamic` * `Fence` * `Ground` - * `Guard rail` + * `GuardRail` * `Other` * `Pedestrian` * `Pole` - * `Props` - * `Rail track` + * `RailTrack` * `Road` - * `Road line` - * `Sidewalk` + * `RoadLine` + * `SideWalk` * `Sky` * `Static` * `Terrain` - * `Traffic` - * `Traffic sign` + * `TrafficLight` + * `TrafficSign` * `Unlabeled` * `Vegetation` - * `Vehicle` + * `Vehicles` * `Wall` * `Water` From 2829e63f1b77c142fca8c554fa28745e8b15032b Mon Sep 17 00:00:00 2001 From: Axel Date: Thu, 27 Aug 2020 16:31:02 +0200 Subject: [PATCH 028/179] Added libxerces-c and setuptools version --- Util/Docker/Prerequisites.Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Util/Docker/Prerequisites.Dockerfile b/Util/Docker/Prerequisites.Dockerfile index 7d193163e3a..9c8a232330c 100644 --- a/Util/Docker/Prerequisites.Dockerfile +++ b/Util/Docker/Prerequisites.Dockerfile @@ -34,9 +34,10 @@ RUN apt-get update ; \ libtool \ rsync \ libxml2-dev \ - aria2 && \ + aria2 \ + libxerces-c-dev && \ pip2 install setuptools && \ - pip3 install setuptools && \ + pip3 install -Iv setuptools==47.3.1 && \ pip2 install distro && \ pip3 install distro && \ update-alternatives --install /usr/bin/clang++ clang++ /usr/lib/llvm-8/bin/clang++ 180 && \ From 172d947ed859e471a270b6dabcc14f1aa84199d9 Mon Sep 17 00:00:00 2001 From: Axel Date: Wed, 2 Sep 2020 15:19:07 +0200 Subject: [PATCH 029/179] Removed Python 2 from default builds. --- Jenkinsfile | 10 ++--- Util/BuildTools/BuildPythonAPI.sh | 37 +++++----------- Util/BuildTools/Check.sh | 68 +++++++--------------------- Util/BuildTools/Linux.mk | 22 +++++----- Util/BuildTools/Setup.sh | 73 ++++++++++++------------------- 5 files changed, 71 insertions(+), 139 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 0c4c788b8c7..599a87e8ff0 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -43,7 +43,7 @@ pipeline { steps { - sh 'make setup ARGS="--python3-version=3.7"' + sh 'make setup ARGS="--python-version=3.7"' } } stage('ubuntu build') @@ -51,7 +51,7 @@ pipeline steps { sh 'make LibCarla' - sh 'make PythonAPI ARGS="--python3-version=3.7"' + sh 'make PythonAPI ARGS="--python-version=3.7"' sh 'make CarlaUE4Editor' sh 'make examples' } @@ -68,7 +68,7 @@ pipeline { steps { - sh 'make check ARGS="--all --xml --python3-version=3.7"' + sh 'make check ARGS="--all --xml --python-version=3.7"' } post { @@ -90,8 +90,8 @@ pipeline { steps { - sh 'make package ARGS="--python3-version=3.7"' - sh 'make package ARGS="--packages=AdditionalMaps --clean-intermediate --python3-version=3.7"' + sh 'make package ARGS="--python-version=3.7"' + sh 'make package ARGS="--packages=AdditionalMaps --clean-intermediate --python-version=3.7"' sh 'make examples ARGS="localhost 3654"' } post diff --git a/Util/BuildTools/BuildPythonAPI.sh b/Util/BuildTools/BuildPythonAPI.sh index faabbd26d19..080cee909dd 100755 --- a/Util/BuildTools/BuildPythonAPI.sh +++ b/Util/BuildTools/BuildPythonAPI.sh @@ -11,42 +11,35 @@ export CXX=clang++-8 DOC_STRING="Build and package CARLA Python API." -USAGE_STRING="Usage: $0 [-h|--help] [--rebuild] [--py2] [--py3] [--clean] [--python3-version=VERSION]" +USAGE_STRING="Usage: $0 [-h|--help] [--rebuild] [--clean] [--python-version=VERSION]" REMOVE_INTERMEDIATE=false -BUILD_FOR_PYTHON2=false -BUILD_FOR_PYTHON3=false BUILD_RSS_VARIANT=false +BUILD_PYTHONAPI=true -OPTS=`getopt -o h --long help,rebuild,py2,py3,clean,rss,python3-version:,packages:,clean-intermediate,all,xml, -n 'parse-options' -- "$@"` +OPTS=`getopt -o h --long help,rebuild,clean,rss,python-version:,packages:,clean-intermediate,all,xml, -n 'parse-options' -- "$@"` if [ $? != 0 ] ; then echo "$USAGE_STRING" ; exit 2 ; fi eval set -- "$OPTS" -PY3_VERSION=3 +PY_VERSION=3 while [[ $# -gt 0 ]]; do case "$1" in --rebuild ) REMOVE_INTERMEDIATE=true; - BUILD_FOR_PYTHON2=true; - BUILD_FOR_PYTHON3=true; + BUILD_PYTHONAPI=true; shift ;; - --py2 ) - BUILD_FOR_PYTHON2=true; - shift ;; - --py3 ) - BUILD_FOR_PYTHON3=true; - shift ;; - --python3-version ) - PY3_VERSION="$2" + --python-version ) + PY_VERSION="$2" shift 2 ;; --rss ) BUILD_RSS_VARIANT=true; shift ;; --clean ) REMOVE_INTERMEDIATE=true; + BUILD_PYTHONAPI=false; shift ;; -h | --help ) echo "$DOC_STRING" @@ -58,7 +51,7 @@ while [[ $# -gt 0 ]]; do esac done -if ! { ${REMOVE_INTERMEDIATE} || ${BUILD_FOR_PYTHON2} || ${BUILD_FOR_PYTHON3} ; }; then +if ! { ${REMOVE_INTERMEDIATE} || ${BUILD_PYTHONAPI} ; }; then fatal_error "Nothing selected to be done." fi @@ -87,19 +80,11 @@ if ${BUILD_RSS_VARIANT} ; then export BUILD_RSS_VARIANT=${BUILD_RSS_VARIANT} fi -if ${BUILD_FOR_PYTHON2} ; then - - log "Building Python API for Python 2." - - /usr/bin/env python2 setup.py bdist_egg - -fi - -if ${BUILD_FOR_PYTHON3} ; then +if ${BUILD_PYTHONAPI} ; then log "Building Python API for Python 3." - /usr/bin/env python${PY3_VERSION} setup.py bdist_egg + /usr/bin/env python${PY_VERSION} setup.py bdist_egg fi diff --git a/Util/BuildTools/Check.sh b/Util/BuildTools/Check.sh index 55abfc3253f..a9660aa16fa 100755 --- a/Util/BuildTools/Check.sh +++ b/Util/BuildTools/Check.sh @@ -9,7 +9,7 @@ source $(dirname "$0")/Environment.sh DOC_STRING="Run unit tests." USAGE_STRING=$(cat <<- END -Usage: $0 [-h|--help] [--gdb] [--xml] [--gtest_args=ARGS] +Usage: $0 [-h|--help] [--gdb] [--xml] [--gtest_args=ARGS] [--python-version=VERSION] Then either ran all the tests @@ -18,7 +18,6 @@ Then either ran all the tests Or choose one or more of the following [--libcarla-release] [--libcarla-debug] - [--python-api-2] [--python-api-3] [--benchmark] You can also set the command-line arguments passed to GTest on a ".gtest" @@ -35,19 +34,17 @@ XML_OUTPUT=false GTEST_ARGS=`sed -e 's/#.*$//g' ${CARLA_ROOT_FOLDER}/.gtest | sed -e '/^[[:space:]]*$/!s/^/--/g' | sed -e ':a;N;$!ba;s/\n/ /g'` LIBCARLA_RELEASE=false LIBCARLA_DEBUG=false -PYTHON_API_2=false -PYTHON_API_3=false -SMOKE_TESTS_2=false -SMOKE_TESTS_3=false +SMOKE_TESTS=false +PYTHON_API=false RUN_BENCHMARK=false -OPTS=`getopt -o h --long help,gdb,xml,gtest_args:,all,libcarla-release,libcarla-debug,python-api-2,python-api-3,smoke-2,smoke-3,benchmark,python3-version:, -n 'parse-options' -- "$@"` +OPTS=`getopt -o h --long help,gdb,xml,gtest_args:,all,libcarla-release,libcarla-debug,python-api,smoke,benchmark,python-version:, -n 'parse-options' -- "$@"` if [ $? != 0 ] ; then echo "$USAGE_STRING" ; exit 2 ; fi eval set -- "$OPTS" -PY3_VERSION=3 +PY_VERSION=3 while [[ $# -gt 0 ]]; do case "$1" in @@ -65,8 +62,7 @@ while [[ $# -gt 0 ]]; do --all ) LIBCARLA_RELEASE=true; LIBCARLA_DEBUG=true; - PYTHON_API_2=true; - PYTHON_API_3=true; + PYTHON_API=true; shift ;; --libcarla-release ) LIBCARLA_RELEASE=true; @@ -74,25 +70,19 @@ while [[ $# -gt 0 ]]; do --libcarla-debug ) LIBCARLA_DEBUG=true; shift ;; - --python-api-2 ) - PYTHON_API_2=true; + --smoke ) + SMOKE_TESTS=true; shift ;; - --python-api-3 ) - PYTHON_API_3=true; - shift ;; - --smoke-2 ) - SMOKE_TESTS_2=true; - shift ;; - --smoke-3 ) - SMOKE_TESTS_3=true; + --python-api ) + PYTHON_API=true; shift ;; --benchmark ) LIBCARLA_RELEASE=true; RUN_BENCHMARK=true; GTEST_ARGS="--gtest_filter=benchmark*"; shift ;; - --python3-version ) - PY3_VERSION="$2" + --python-version ) + PY_VERSION="$2" shift 2 ;; -h | --help ) echo "$DOC_STRING" @@ -104,7 +94,7 @@ while [[ $# -gt 0 ]]; do esac done -if ! { ${LIBCARLA_RELEASE} || ${LIBCARLA_DEBUG} || ${PYTHON_API_2} || ${PYTHON_API_3} || ${SMOKE_TESTS_2} || ${SMOKE_TESTS_3}; }; then +if ! { ${LIBCARLA_RELEASE} || ${LIBCARLA_DEBUG} || ${PYTHON_API} || ${SMOKE_TESTS}; }; then fatal_error "Nothing selected to be done." fi @@ -186,23 +176,11 @@ else EXTRA_ARGS= fi -if ${PYTHON_API_2} ; then - - log "Running Python API for Python 2 unit tests." - - /usr/bin/env python2 -m nose2 ${EXTRA_ARGS} - - if ${XML_OUTPUT} ; then - mv test-results.xml ${CARLA_TEST_RESULTS_FOLDER}/python-api-2.xml - fi - -fi - -if ${PYTHON_API_3} ; then +if ${PYTHON_API} ; then log "Running Python API for Python 3 unit tests." - /usr/bin/env python${PY3_VERSION} -m nose2 ${EXTRA_ARGS} + /usr/bin/env python${PY_VERSION} -m nose2 ${EXTRA_ARGS} if ${XML_OUTPUT} ; then mv test-results.xml ${CARLA_TEST_RESULTS_FOLDER}/python-api-3.xml @@ -231,23 +209,11 @@ else EXTRA_ARGS= fi -if ${SMOKE_TESTS_2} ; then - - log "Running smoke tests for Python 2." - - /usr/bin/env python2 -m nose2 ${EXTRA_ARGS} - - if ${XML_OUTPUT} ; then - mv test-results.xml ${CARLA_TEST_RESULTS_FOLDER}/smoke-tests-2.xml - fi - -fi - -if ${SMOKE_TESTS_3} ; then +if ${SMOKE_TESTS} ; then log "Running smoke tests for Python 3." - /usr/bin/env python${PY3_VERSION} -m nose2 ${EXTRA_ARGS} + /usr/bin/env python${PY_VERSION} -m nose2 ${EXTRA_ARGS} if ${XML_OUTPUT} ; then mv test-results.xml ${CARLA_TEST_RESULTS_FOLDER}/smoke-tests-3.xml diff --git a/Util/BuildTools/Linux.mk b/Util/BuildTools/Linux.mk index 4a4ede69d45..dedf211e99d 100644 --- a/Util/BuildTools/Linux.mk +++ b/Util/BuildTools/Linux.mk @@ -58,20 +58,20 @@ check.LibCarla.release: LibCarla.release @${CARLA_BUILD_TOOLS_FOLDER}/Check.sh --libcarla-release $(ARGS) check.PythonAPI: PythonAPI - @${CARLA_BUILD_TOOLS_FOLDER}/Check.sh --python-api-2 --python-api-3 $(ARGS) + @${CARLA_BUILD_TOOLS_FOLDER}/Check.sh --python-api $(ARGS) check.PythonAPI.2: PythonAPI.2 - @${CARLA_BUILD_TOOLS_FOLDER}/Check.sh --python-api-2 $(ARGS) + @${CARLA_BUILD_TOOLS_FOLDER}/Check.sh --python-api --python-version=2 $(ARGS) check.PythonAPI.3: PythonAPI.3 - @${CARLA_BUILD_TOOLS_FOLDER}/Check.sh --python-api-3 $(ARGS) + @${CARLA_BUILD_TOOLS_FOLDER}/Check.sh --python-api --python-version=3 $(ARGS) benchmark: LibCarla.release @${CARLA_BUILD_TOOLS_FOLDER}/Check.sh --benchmark $(ARGS) @cat profiler.csv smoke_tests: - @${CARLA_BUILD_TOOLS_FOLDER}/Check.sh --smoke-2 --smoke-3 $(ARGS) + @${CARLA_BUILD_TOOLS_FOLDER}/Check.sh --smoke $(ARGS) examples: @for D in ${CARLA_EXAMPLES_FOLDER}/*; do [ -d "$${D}" ] && make -C $${D} build; done @@ -84,28 +84,28 @@ CarlaUE4Editor: LibCarla.server.release .PHONY: PythonAPI PythonAPI: LibCarla.client.release osm2odr - @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --py2 --py3 $(ARGS) + @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh $(ARGS) PythonAPI.2: LibCarla.client.release osm2odr - @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --py2 + @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --python-version=2 PythonAPI.3: LibCarla.client.release osm2odr - @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --py3 $(ARGS) + @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --python-version=3 PythonAPI.rebuild: LibCarla.client.release osm2odr @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --rebuild $(ARGS) PythonAPI.rss: LibCarla.client.rss.release osm2odr - @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --py2 --py3 --rss $(ARGS) + @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --rss $(ARGS) PythonAPI.rss.2: LibCarla.client.rss.release osm2odr - @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --py2 --rss + @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --python-version=2 --rss PythonAPI.rss.3: LibCarla.client.rss.release osm2odr - @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --py3 --rss $(ARGS) + @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --python-version=3 --rss PythonAPI.rss.rebuild: LibCarla.client.rss.release osm2odr - @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --rebuild --rss + @${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.sh --rebuild --rss $(ARGS) PythonAPI.docs: @python PythonAPI/docs/doc_gen.py diff --git a/Util/BuildTools/Setup.sh b/Util/BuildTools/Setup.sh index a5a82eb1247..bc7e082a892 100755 --- a/Util/BuildTools/Setup.sh +++ b/Util/BuildTools/Setup.sh @@ -6,20 +6,20 @@ DOC_STRING="Download and install the required libraries for carla." -USAGE_STRING="Usage: $0 [--python3-version=VERSION]" +USAGE_STRING="Usage: $0 [--python-version=VERSION]" -OPTS=`getopt -o h --long help,rebuild,py2,py3,clean,rss,python3-version:,packages:,clean-intermediate,all,xml -n 'parse-options' -- "$@"` +OPTS=`getopt -o h --long help,rebuild,clean,rss,python-version:,packages:,clean-intermediate,all,xml -n 'parse-options' -- "$@"` if [ $? != 0 ] ; then echo "$USAGE_STRING" ; exit 2 ; fi eval set -- "$OPTS" -PY3_VERSION=3 +PY_VERSION=3 while [[ $# -gt 0 ]]; do case "$1" in - --python3-version ) - PY3_VERSION="$2"; + --python-version ) + PY_VERSION="$2"; shift 2 ;; -h | --help ) echo "$DOC_STRING" @@ -106,10 +106,19 @@ BOOST_BASENAME="boost-${BOOST_VERSION}-${CXX_TAG}" BOOST_INCLUDE=${PWD}/${BOOST_BASENAME}-install/include BOOST_LIBPATH=${PWD}/${BOOST_BASENAME}-install/lib +SHOULD_BUILD_BOOST=true + +PYTHON_VERSION=$(/usr/bin/env python${PY_VERSION} -V) +LIB_NAME=${PYTHON_VERSION:7:3} +LIB_NAME=${LIB_NAME//.} if [[ -d "${BOOST_BASENAME}-install" ]] ; then - log "${BOOST_BASENAME} already installed." -else + if [ -f "${BOOST_BASENAME}-install/lib/libboost_python${LIB_NAME}.a" ] ; then + SHOULD_BUILD_BOOST=false + log "${BOOST_BASENAME} already installed." + fi +fi +if { ${SHOULD_BUILD_BOOST} ; } ; then rm -Rf ${BOOST_BASENAME}-source BOOST_PACKAGE_BASENAME=boost_${BOOST_VERSION//./_} @@ -122,7 +131,7 @@ else wget "https://carla-releases.s3.eu-west-3.amazonaws.com/Backup/${BOOST_PACKAGE_BASENAME}.tar.gz" || true fi - log "Extracting boost for Python 2." + log "Extracting boost for Python ${PY_VERSION}." tar -xzf ${BOOST_PACKAGE_BASENAME}.tar.gz mkdir -p ${BOOST_BASENAME}-install/include mv ${BOOST_PACKAGE_BASENAME} ${BOOST_BASENAME}-source @@ -136,53 +145,19 @@ else BOOST_TOOLSET="clang-8.0" BOOST_CFLAGS="-fPIC -std=c++14 -DBOOST_ERROR_CODE_HEADER_ONLY" - py2="/usr/bin/env python2" - py2_root=`${py2} -c "import sys; print(sys.prefix)"` - pyv=`$py2 -c "import sys;x='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));sys.stdout.write(x)";` - ./bootstrap.sh \ - --with-toolset=clang \ - --prefix=../boost-install \ - --with-libraries=python,filesystem,system,program_options \ - --with-python=${py2} --with-python-root=${py2_root} - - if ${TRAVIS} ; then - echo "using python : ${pyv} : ${py2_root}/bin/python2 ;" > ${HOME}/user-config.jam - else - echo "using python : ${pyv} : ${py2_root}/bin/python2 ;" > project-config.jam - fi - - ./b2 toolset="${BOOST_TOOLSET}" cxxflags="${BOOST_CFLAGS}" --prefix="../${BOOST_BASENAME}-install" -j ${CARLA_BUILD_CONCURRENCY} stage release - ./b2 toolset="${BOOST_TOOLSET}" cxxflags="${BOOST_CFLAGS}" --prefix="../${BOOST_BASENAME}-install" -j ${CARLA_BUILD_CONCURRENCY} install - ./b2 toolset="${BOOST_TOOLSET}" cxxflags="${BOOST_CFLAGS}" --prefix="../${BOOST_BASENAME}-install" -j ${CARLA_BUILD_CONCURRENCY} --clean-all - - # Get rid of python2 build artifacts completely & do a clean build for python3 - popd >/dev/null - rm -Rf ${BOOST_BASENAME}-source - - log "Extracting boost for Python 3." - tar -xzf ${BOOST_PACKAGE_BASENAME}.tar.gz - mkdir -p ${BOOST_BASENAME}-install/include - mv ${BOOST_PACKAGE_BASENAME} ${BOOST_BASENAME}-source - # Boost patch for exception handling - cp "${CARLA_BUILD_FOLDER}/../Util/BoostFiles/rational.hpp" "${BOOST_BASENAME}-source/boost/rational.hpp" - cp "${CARLA_BUILD_FOLDER}/../Util/BoostFiles/read.hpp" "${BOOST_BASENAME}-source/boost/geometry/io/wkt/read.hpp" - # --- - - pushd ${BOOST_BASENAME}-source >/dev/null - - py3="/usr/bin/env python${PY3_VERSION}" + py3="/usr/bin/env python${PY_VERSION}" py3_root=`${py3} -c "import sys; print(sys.prefix)"` pyv=`$py3 -c "import sys;x='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));sys.stdout.write(x)";` ./bootstrap.sh \ --with-toolset=clang \ --prefix=../boost-install \ - --with-libraries=python \ + --with-libraries=python,filesystem,system,program_options \ --with-python=${py3} --with-python-root=${py3_root} if ${TRAVIS} ; then - echo "using python : ${pyv} : ${py3_root}/bin/python${PY3_VERSION} ;" > ${HOME}/user-config.jam + echo "using python : ${pyv} : ${py3_root}/bin/python${PY_VERSION} ;" > ${HOME}/user-config.jam else - echo "using python : ${pyv} : ${py3_root}/bin/python${PY3_VERSION} ;" > project-config.jam + echo "using python : ${pyv} : ${py3_root}/bin/python${PY_VERSION} ;" > project-config.jam fi ./b2 toolset="${BOOST_TOOLSET}" cxxflags="${BOOST_CFLAGS}" --prefix="../${BOOST_BASENAME}-install" -j ${CARLA_BUILD_CONCURRENCY} stage release @@ -198,6 +173,12 @@ else cp "${CARLA_BUILD_FOLDER}/../Util/BoostFiles/read.hpp" "${BOOST_BASENAME}-install/include/boost/geometry/io/wkt/read.hpp" # --- + # Install boost dependencies + mkdir -p "${LIBCARLA_INSTALL_CLIENT_FOLDER}/include/system" + mkdir -p "${LIBCARLA_INSTALL_CLIENT_FOLDER}/lib" + cp -rf ${BOOST_BASENAME}-install/include/* ${LIBCARLA_INSTALL_CLIENT_FOLDER}/include/system + cp -rf ${BOOST_BASENAME}-install/lib/* ${LIBCARLA_INSTALL_CLIENT_FOLDER}/lib + fi unset BOOST_BASENAME From 658a7fb3702bd3f108a4a12d8517ac8c29ac6325 Mon Sep 17 00:00:00 2001 From: Axel Date: Thu, 3 Sep 2020 16:56:21 +0200 Subject: [PATCH 030/179] Fixed smoke test. --- Util/BuildTools/Check.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Util/BuildTools/Check.sh b/Util/BuildTools/Check.sh index a9660aa16fa..c8553894e0d 100755 --- a/Util/BuildTools/Check.sh +++ b/Util/BuildTools/Check.sh @@ -194,10 +194,10 @@ popd >/dev/null # -- Run smoke tests ----------------------------------------------------------- # ============================================================================== -if ${SMOKE_TESTS_2} || ${SMOKE_TESTS_3} ; then +if ${SMOKE_TESTS} ; then pushd "${CARLA_PYTHONAPI_ROOT_FOLDER}/util" >/dev/null log "Checking connection with the simulator." - ./test_connection.py -p 3654 --timeout=60.0 + python${PY_VERSION} test_connection.py -p 3654 --timeout=60.0 popd >/dev/null fi From 443113c8905e59ab5f66859cd3b88ab1cd4213d1 Mon Sep 17 00:00:00 2001 From: Axel Date: Thu, 3 Sep 2020 16:59:09 +0200 Subject: [PATCH 031/179] Removed python 2 prerequisites. --- Util/Docker/Prerequisites.Dockerfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Util/Docker/Prerequisites.Dockerfile b/Util/Docker/Prerequisites.Dockerfile index 9c8a232330c..b6db6c97603 100644 --- a/Util/Docker/Prerequisites.Dockerfile +++ b/Util/Docker/Prerequisites.Dockerfile @@ -36,9 +36,7 @@ RUN apt-get update ; \ libxml2-dev \ aria2 \ libxerces-c-dev && \ - pip2 install setuptools && \ pip3 install -Iv setuptools==47.3.1 && \ - pip2 install distro && \ pip3 install distro && \ update-alternatives --install /usr/bin/clang++ clang++ /usr/lib/llvm-8/bin/clang++ 180 && \ update-alternatives --install /usr/bin/clang clang /usr/lib/llvm-8/bin/clang 180 From 40296dfa9090cd6a3402fd98634421174fca602c Mon Sep 17 00:00:00 2001 From: Axel Date: Thu, 3 Sep 2020 18:21:28 +0200 Subject: [PATCH 032/179] Fixed python version argument string. --- Util/BuildTools/Package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Util/BuildTools/Package.sh b/Util/BuildTools/Package.sh index 9efb09a3be7..a16ecd82220 100755 --- a/Util/BuildTools/Package.sh +++ b/Util/BuildTools/Package.sh @@ -16,7 +16,7 @@ DO_CLEAN_INTERMEDIATE=false PROPS_MAP_NAME=PropsMap PACKAGE_CONFIG=Shipping -OPTS=`getopt -o h --long help,config:,no-zip,clean-intermediate,packages:,python3-version: -n 'parse-options' -- "$@"` +OPTS=`getopt -o h --long help,config:,no-zip,clean-intermediate,packages:,python-version: -n 'parse-options' -- "$@"` if [ $? != 0 ] ; then echo "$USAGE_STRING" ; exit 2 ; fi From 201bc254a7e82e4d076165dd35b0c8b927d5937a Mon Sep 17 00:00:00 2001 From: bernat Date: Tue, 1 Sep 2020 12:00:23 +0200 Subject: [PATCH 033/179] Changing Jenkinsfile for Doxygen --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index 599a87e8ff0..4d0a5ffa553 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -121,6 +121,7 @@ pipeline sh 'rm -rf ~/carla-simulator.github.io/Doxygen' sh ''' cd ~/carla-simulator.github.io + git remote set-url origin git@github.com:carla-simulator/carla-simulator.github.io.git git fetch git checkout -B master origin/master ''' From 63e7c765a8b383c5d3e605aa2097ba7959b82562 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Mon, 7 Sep 2020 11:15:55 +0200 Subject: [PATCH 034/179] Update pull_request_template.md --- .github/pull_request_template.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 20309c23d75..fcf482fb780 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -5,10 +5,10 @@ view the contribution guidelines, then fill out the blanks below. Checklist: - - [ ] Your branch is up-to-date with the `master` branch and tested with latest changes + - [ ] Your branch is up-to-date with the `dev` branch and tested with latest changes - [ ] Extended the README / documentation, if necessary - [ ] Code compiles correctly - - [ ] All tests passing with `make check` + - [ ] All tests passing with `make check` (only Linux) - [ ] If relevant, update CHANGELOG.md with your changes --> From 808755ad3f21157293ccf9509d7d7016b71c16df Mon Sep 17 00:00:00 2001 From: bernat Date: Mon, 7 Sep 2020 14:43:37 +0200 Subject: [PATCH 035/179] Update build_windows.md --- Docs/build_windows.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Docs/build_windows.md b/Docs/build_windows.md index 15eeb006ba3..cae564269ab 100644 --- a/Docs/build_windows.md +++ b/Docs/build_windows.md @@ -28,6 +28,9 @@ CARLA forum
Show command lines to build on Windows +!!! Important + To execute the ```make``` commands below, you **must** use the Visual Studio 2017 native console x64 **with** administrator rights, otherwise you may be getting permission errors. + ```sh # Make sure to meet the minimum requirements. From f287a1e7c0f579373d4e120cd9eea2b63b556d02 Mon Sep 17 00:00:00 2001 From: doterop Date: Wed, 9 Sep 2020 14:29:31 +0200 Subject: [PATCH 036/179] Automatic calculation of vehicle's BB (#3267) * Added BB calculation * Updated changelog * Removed logs * Improved BB calculation * Added BB calculation * Updated changelog * Removed logs * Improved BB calculation * Updating content version Co-authored-by: bernat --- CHANGELOG.md | 1 + .../Carla/Vehicle/CarlaWheeledVehicle.cpp | 51 +++++++++++++++++++ .../Carla/Vehicle/CarlaWheeledVehicle.h | 3 ++ Util/ContentVersions.txt | 2 +- 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70c1dec1959..9dd0d5557d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ * Replace deprectated `platform.dist()` with recommended `distro.linux_distribution()` * Improved the performance on capture sensors. * Fixed minor typo in the introduction section of documentation. + * Added automatic calculation of vehicle's BB ## CARLA 0.9.9 diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.cpp index 5c8a1ea9bc8..310d39e3f12 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.cpp @@ -16,6 +16,8 @@ #include "TireConfig.h" #include "VehicleWheel.h" +#include "Rendering/SkeletalMeshRenderData.h" + // ============================================================================= // -- Constructor and destructor ----------------------------------------------- // ============================================================================= @@ -81,6 +83,55 @@ void ACarlaWheeledVehicle::BeginPlay() Vehicle4W->WheelSetups = NewWheelSetups; } +void ACarlaWheeledVehicle::AdjustVehicleBounds() +{ + USkeletalMeshComponent *SkMeshComp = GetMesh(); + USkeletalMesh* SkeletalMesh = SkMeshComp->SkeletalMesh; + if(!SkeletalMesh) + { + UE_LOG(LogCarla, Error, TEXT("AdjustVehicleBounds no SkeletalMesh")); + return; + } + + // Get Vertex postion information from LOD 0 of the Skeletal Mesh + FPositionVertexBuffer& FPositionVertexBuffer = SkeletalMesh->GetResourceForRendering()->LODRenderData[0].StaticVertexBuffers.PositionVertexBuffer; + uint32 NumVertices = FPositionVertexBuffer.GetNumVertices(); + + // Look for Skeletal Mesh bounds (vertex perfect) + FVector MaxVertex(TNumericLimits::Min()); + FVector MinVertex(TNumericLimits::Max()); + for(uint32 i = 0; i < NumVertices; i++) + { + FVector& Pos = FPositionVertexBuffer.VertexPosition(i); + MaxVertex.X = (Pos.X > MaxVertex.X) ? Pos.X : MaxVertex.X; + MaxVertex.Y = (Pos.Y > MaxVertex.Y) ? Pos.Y : MaxVertex.Y; + MaxVertex.Z = (Pos.Z > MaxVertex.Z) ? Pos.Z : MaxVertex.Z; + MinVertex.X = (Pos.X < MinVertex.X) ? Pos.X : MinVertex.X; + MinVertex.Y = (Pos.Y < MinVertex.Y) ? Pos.Y : MinVertex.Y; + MinVertex.Z = (Pos.Z < MinVertex.Z) ? Pos.Z : MinVertex.Z; + } + + // Calculate box extent + FVector Extent ( + (MaxVertex.X - MinVertex.X) * 0.5f, + (MaxVertex.Y - MinVertex.Y) * 0.5f, + (MaxVertex.Z - MinVertex.Z) * 0.5f + ); + + // Calculate middle point + FVector Origin ( + (MinVertex.X + Extent.X), + (MinVertex.Y + Extent.Y), + (MinVertex.Z + Extent.Z) + ); + + // Prepare Box Collisions + FTransform Transform; + Transform.SetTranslation(Origin); + VehicleBounds->SetRelativeTransform(Transform); + VehicleBounds->SetBoxExtent(Extent); +} + // ============================================================================= // -- Get functions ------------------------------------------------------------ // ============================================================================= diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.h index 385999a3945..93a75da4587 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.h @@ -196,6 +196,9 @@ class CARLA_API ACarlaWheeledVehicle : public AWheeledVehicle UFUNCTION(BlueprintImplementableEvent) void RefreshLightState(const FVehicleLightState &VehicleLightState); + UFUNCTION(BlueprintCallable, CallInEditor) + void AdjustVehicleBounds(); + private: /// Current state of the vehicle controller (for debugging purposes). diff --git a/Util/ContentVersions.txt b/Util/ContentVersions.txt index 846181d6c35..ded7f7fca44 100644 --- a/Util/ContentVersions.txt +++ b/Util/ContentVersions.txt @@ -32,4 +32,4 @@ 0.9.7: 20191221_c88604b 0.9.8: 20200306_06b6cb1 0.9.9: 20200422_ea5179a -Latest: 20200902_8d5419c +Latest: 20200908_3f92e51 From 18ae3b3acc75b38b1613e061142f9f62e5c356ff Mon Sep 17 00:00:00 2001 From: Aniol Marti Date: Fri, 4 Sep 2020 11:05:34 +0200 Subject: [PATCH 037/179] Fix typo: liston -> listen in Co-Simulation/Sumo/run_synchronization.py --- Co-Simulation/Sumo/run_synchronization.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Co-Simulation/Sumo/run_synchronization.py b/Co-Simulation/Sumo/run_synchronization.py index b5b28d9afda..1ded6887286 100644 --- a/Co-Simulation/Sumo/run_synchronization.py +++ b/Co-Simulation/Sumo/run_synchronization.py @@ -276,7 +276,7 @@ def synchronization_loop(args): metavar='P', default=None, type=int, - help='TCP port to liston to (default: 8813)') + help='TCP port to listen to (default: 8813)') argparser.add_argument('--sumo-gui', action='store_true', help='run the gui version of sumo') argparser.add_argument('--step-length', default=0.05, From a33855ba25c705e2c784bc7dd48b9daa2d92289e Mon Sep 17 00:00:00 2001 From: Aniol Marti Date: Fri, 4 Sep 2020 11:08:04 +0200 Subject: [PATCH 038/179] New feature: allow remote sumo instance in spawn_npc_sumo.py * New arguments: --sumo-host, --sumo-port. --- Co-Simulation/Sumo/spawn_npc_sumo.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Co-Simulation/Sumo/spawn_npc_sumo.py b/Co-Simulation/Sumo/spawn_npc_sumo.py index 9448bb9acf0..1dd28d94700 100644 --- a/Co-Simulation/Sumo/spawn_npc_sumo.py +++ b/Co-Simulation/Sumo/spawn_npc_sumo.py @@ -116,8 +116,8 @@ def main(args): sumo_net = sumolib.net.readNet(net_file) sumo_simulation = SumoSimulation(cfg_file, args.step_length, - host=None, - port=None, + host=args.sumo_host, + port=args.sumo_port, sumo_gui=args.sumo_gui, client_order=args.client_order) @@ -218,6 +218,13 @@ def main(args): default=2000, type=int, help='TCP port to listen to (default: 2000)') + argparser.add_argument('--sumo-host', + default=None, + help='IP of the sumo host server (default: None)') + argparser.add_argument('--sumo-port', + default=None, + type=int, + help='TCP port to listen to (default: None)') argparser.add_argument('-n', '--number-of-vehicles', metavar='N', From 6de460466e0d6729dd7498362cd53a2ed414d28a Mon Sep 17 00:00:00 2001 From: bernat Date: Tue, 8 Sep 2020 12:49:09 +0200 Subject: [PATCH 039/179] Fix manual_control.py memory leak --- PythonAPI/examples/manual_control.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/PythonAPI/examples/manual_control.py b/PythonAPI/examples/manual_control.py index a379eb4f4eb..f6e7b3b0e90 100755 --- a/PythonAPI/examples/manual_control.py +++ b/PythonAPI/examples/manual_control.py @@ -261,16 +261,18 @@ def destroy_sensors(self): def destroy(self): if self.radar_sensor is not None: self.toggle_radar() - actors = [ + sensors = [ self.camera_manager.sensor, self.collision_sensor.sensor, self.lane_invasion_sensor.sensor, self.gnss_sensor.sensor, - self.imu_sensor.sensor, - self.player] - for actor in actors: - if actor is not None: - actor.destroy() + self.imu_sensor.sensor] + for sensor in sensors: + if sensor is not None: + sensor.stop() + sensor.destroy() + if self.player is not None: + self.player.destroy() # ============================================================================== From e8f103c786314ca21731ed644291787077626244 Mon Sep 17 00:00:00 2001 From: bernat Date: Tue, 8 Sep 2020 12:49:42 +0200 Subject: [PATCH 040/179] Remove unused .xodr parsing call --- LibCarla/source/carla/client/LaneInvasionSensor.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/LibCarla/source/carla/client/LaneInvasionSensor.cpp b/LibCarla/source/carla/client/LaneInvasionSensor.cpp index ffff730b219..30c48f8b6e7 100644 --- a/LibCarla/source/carla/client/LaneInvasionSensor.cpp +++ b/LibCarla/source/carla/client/LaneInvasionSensor.cpp @@ -151,8 +151,7 @@ namespace client { } auto episode = GetEpisode().Lock(); - SharedPtr map = episode->GetCurrentMap(); - + auto cb = std::make_shared( *vehicle, episode->GetCurrentMap(), From b574ca57e80fc8033a95eb20c80722495f669fe1 Mon Sep 17 00:00:00 2001 From: bernat Date: Tue, 8 Sep 2020 13:38:59 +0200 Subject: [PATCH 041/179] Fix manual_control_steeringwheel.py memory leak --- .../examples/manual_control_steeringwheel.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/PythonAPI/examples/manual_control_steeringwheel.py b/PythonAPI/examples/manual_control_steeringwheel.py index 7c98d3bb211..cdd551db0f5 100755 --- a/PythonAPI/examples/manual_control_steeringwheel.py +++ b/PythonAPI/examples/manual_control_steeringwheel.py @@ -187,16 +187,17 @@ def render(self, display): self.hud.render(display) def destroy(self): - actors = [ + sensors = [ self.camera_manager.sensor, self.collision_sensor.sensor, self.lane_invasion_sensor.sensor, - self.gnss_sensor.sensor, - self.player] - for actor in actors: - if actor is not None: - actor.destroy() - + self.gnss_sensor.sensor] + for sensor in sensors: + if sensor is not None: + sensor.stop() + sensor.destroy() + if self.player is not None: + self.player.destroy() # ============================================================================== # -- DualControl ----------------------------------------------------------- From 131764de0c9d125351dd3e9aa6e654eff066f362 Mon Sep 17 00:00:00 2001 From: bernat Date: Tue, 8 Sep 2020 13:45:39 +0200 Subject: [PATCH 042/179] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dd0d5557d9..b65970dc1f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * Upgraded carla Docker image to Ubuntu 18.04 + * Fixed memory leak on manual_control scripts (sensor listenning was not stoped before destroying) * Added PythonAPI `carla.Osm2Odr.convert()` function and `calra.Osm2OdrSettings` class to support Open Street Maps to OpenDRIVE conversions * Upgraded to AD RSS v4.1.0 supporting unstructured scenes and pedestrians, and fixed spdlog to v1.7.0 * Fixed a bug in `spawn_npc_sumo` script computing not allowed routes for a given vehicle class From 03bcce63298f99467bf3bf4f3f7c582e1be432b1 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 9 Sep 2020 13:50:56 +0200 Subject: [PATCH 043/179] First iteration --- Docs/build_faq.md | 53 +++++++++++++++++++++++++++++++++++++ Docs/img/faq_rpc_error.jpg | Bin 0 -> 654877 bytes 2 files changed, 53 insertions(+) create mode 100644 Docs/img/faq_rpc_error.jpg diff --git a/Docs/build_faq.md b/Docs/build_faq.md index 160cf499184..a99af7658f4 100644 --- a/Docs/build_faq.md +++ b/Docs/build_faq.md @@ -104,6 +104,59 @@ make PythonAPI.docs
+ +
+
+ Cannot run example scripts or "RuntimeError: rpc::rpc_error during call in function version" +
+ +![faq_rpc_error](img/faq_rpc_error.jpg) + +If running a script returns an output similar to this, there is a problem with the `.egg` file in the PythonAPI. + +First of all, open `/PythonAPI/carla/dist`. There should be an `.egg` file for the corresponding CARLA and Python version you are using (similar to `carla-0.X.X-pyX.X-linux-x86_64.egg`). Make sure the file matches the Python version you are using. To check your Python version use the following command. + +```sh +python3 --version # CARLA no longer provides support for Python2, so we are dismissing it here +``` + +If either the file is missing or you think it could be corrupted, try rebuilding again. +```sh +make clean +make PythonAPI +make launch +``` +Now try one of the example scripts again. + +```sh +cd PythonAPI/examples +python3 dynamic_weather.py +``` + +If the error persists, the problem is probably related with your PythonPATH. These scripts automatically look for the `.egg` file associated with the build, so maybe there is any other `.egg` file in your PythonPATH interfering with the process. Show the content of the PythonPATH with the following command. + +```sh +python -c "import sys; print('\n'.join(sys.path))" +``` +Look up in the output for other instances of `.egg` files in a route similar to `PythonAPI/carla/dist`, and get rid of these. They probably belong to other instances of CARLA installations. + +Ultimately there is the option to add the `.egg` file of your build to the PythonPATH using the `~/.bashrc`. This is not the recommended way, as the path will need an update for every new release. + +First, open the `~/.bashrc`. +```sh +gedit ~/.bashrc +``` +Edit the following line to match your CARLA and Python version. In other words, change `carla-0.9.10-py3.6-linux-x86_64.egg` for the name of your `.egg` file. +``` +export PYTHONPATH=$PYTHONPATH:${CARLA_ROOT}/PythonAPI/carla/dist/carla-0.9.10-py3.6-linux-x86_64.egg:${CARLA_ROOT}/PythonAPI/carla/agents:${CARLA_ROOT}/PythonAPI/carla +``` +Add the line to the `~/.bashrc`, save the file, and reset the terminal for changes to be effective. + +After cleaning the PythonPATH or adding the path to the new `.egg` file, all the example scripts should work properly. + +
+ + --- ## Windows build diff --git a/Docs/img/faq_rpc_error.jpg b/Docs/img/faq_rpc_error.jpg new file mode 100644 index 0000000000000000000000000000000000000000..55233715edded1f0673ad3ced1517de0e67b4cfa GIT binary patch literal 654877 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

SvCw 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

a3k9SzDAel3msF23v}*8tx(%m&eqkh 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 {{l@`eMu6Ww`(dc>s%2h9j1vum`lNMikL zEP4p);FQ8Wio90zp$OQ2W|U)U5%iBjX((KJp#+WVTdy~sivN)tZ)n36KKt#Z)MYB7kNLl{sFL0v=uNPt=9L2Ya7hyOZV+dOc{V> zT4p202wALpdqND_0C|IaWB*s;8M@q52KqVo5`QEWbzfkRi%OR+m1JL`JnkUwoc%-& zk^C?Ge~h~(`{fU~CcD>8{B~XU`Zm4+bt;`jdxbW_PGyy;YLWGxF} z0O4C3b&DLGIo(L1DmuD*)#}>%*F7vw@m0f{*>#h$GurfaxnL6``&*;nFT>hzUF29| zp*NEZLmSN3uddBFK~7MYlG{p`CyV>y|2<^bQ#Ins-?ebwvu+P^Kul0oimM7k_f5tH zf8#L0yv>yH{p@+GIcQkYYNst^%JNX-Si8hej=l!g;&p~tDutt^seaNIsE}Y;3uQXk z&jOPihDtb#;tE(w{@Z+a7s{gilL0inms488LtVuD_J>yg((8J^;xHW3&3PDfjZc+BE_aC({LXMmmG^-`GAM8V6aX7UB55f;#_cb ztGv8;aw{Kvv+2I*;J(<$5SH-)c->}49&@R-&?WLi?;ndn92BE+qI%-^>pcC)|KYX- zL_0UAQZTPkwW5EeZ(~kk;QN5g`Iy|O3{CqNmw?bGX1Rk|laPr)AZr|aEnq+6+`h&C zf-E_*X4!h#{6{U}uQ9S6c|I_WoK{u(G+Z*MCU)NJE?3JTg`Nx2BMY6lr=!UuA zp1FA*6ph8lm0p>#I%bW!C3~U%#A)yy3Un%?V)v=G!A4ue_lL!DM(ki zI+5=7z5a6vesE(-51Ou=T&5k8AeQT%q|NIt?6DNO;K*_n)DkDM9A=5LbUWsZx=Ey) zEiw8^7OL=E2jV{NVOR!R;coSqpWXT--;I;Um z+fCHFaU+W0=tAo$lbL7gve4tq$(VHn8?evyh0?Lw*W>fsfb!^uFrL}fG%!SkRc2LoDM&3QXR39`Qa5V+sNxzqNBI5rA4SAJiW3y!KS`0@ zxqY6`#ev$Iaoc5!@9g%K`kvgq>fz-2dCM`LHXjfQ*Ponf?va`Gt%&Bh195d{adV;hIDj3%@BKqN%S24^v%Iw%C@=oi%O7rf2-{E7K2IFC=LQz)1Ko^0 zFBl6X2J7${W0`i~Rwr}k&D*Tpn$2R(zaMJn>Lp;ZE>!Dn4BrqD=dtXDjX}~uXRFjs z=yc`Tv=}W}u`Pg*k&$4aO~U(3Vr{SKn?q<_zu)^QXnbG@4(E^11Up<)emlhb{2#?q zoDeeCnR(@+4H|DdP$OBKo}ji(|ExLP#pa26j$3G&g0Y#+br{M8Vpm$$?^ZK}c>1C~ z1hM{7?8~(%CFGqoa>f+NaFS7jB)nz#em;)eA!kd{fjfue$>*EMFLBoOD}Md*bMFtK zfZCy;_u~rTaNCc2U&ylqB4;1E*ljrkY{gZw)rWpd{Kf{*$@L|8$$u}k{e{~Ahb2ka z-epeB_|ys_CTJbB)Eq>AJ$1uByiOtvt^`AIjR3^%mp-Vq*W9=HsU(rc)ke=w<1z#c z6#{f=7LD@-LOK-8Ru$L>G_QCE%ANV_r5Jl?d&5oiCIVE7@t-F`1=EM+)n{I98xnUr zIoP2J?ufdGrJb-7a#1p0QHOF@rV`~-3WiqnH!pzny`nx}!jyq%*&(@Jc1>qL~-^{}_=HqOp5cXNg@1n7Ia&!LNzZ!kS zJd+ty4@ntJPOu|_Tz zH&#spanf^V9afiooaQ%hL@j&jBz;$g3FbP{R(WDnIV2r_w>}K!CY1eUvwRSHFSY=P zcP!T#;=>M>R1eM%%Q^zX2K0a)mU=~!vDNoqlz;wwd28_nm7Cjs)v0aGD%;ClF)zVf z&joyn46a65Vpv+pCMU?XUhUVRQ+(m{QB-WLzzAt&Qf_+mwpc|h;?;iZ|1`@pwS*nA z2vN#;KlvImZLA{h?w!7uW;{iR^15XYscA{hHdoM@Ce1fOMhB~Da$#dov@dsgki!HF$yLctfiuc?&7 zQJ6C&Vg=y%P`1g{b`J-WCi>(Ze!cn;H?9Wbc{}Ae!IBBZLWk@ZOtdT z>Di)HFXhYfxOznuGU~c#J`mM`tp;45N*{B`mBpvjvyy(wOXPZVcj;~3{a|x6L2f0z zzhu8Llf(nhI4@tRG&-)|jc87?_bQF}W;iHZGR!xKbMPJ!p#R+G5yE1Zt&>kwDD6Vj zoi~JqGSz;v|NnEM1q0;zVdG9Dbaf!k!DBy|E!tnw12H-7wgs-1DAH+OzoF?K3~;mX z@~GGQ_8uM1y{K_s@Izg?QQU%Xfc1;ruqNu%Q zp3I(OADEMBr4UW-WF8YAoC6Wx0-}LmGhj*`gIG>~u`plbh`d?>9dL=RFjj^(e2Kcg z`23udnW_9_u2aR1)hHxvXt04rHZ#qPXQJ9g)hox+`I)J6Zh^qjeNx)Q%1O5oz1Ov7 zdM6g5fuJHR5!wB>qGM6_(z)^<#TMocL)jL&F5aHad)DRgpC7oVer9MidzQ_}%fH)u zL4!?_Ce~~q*CrFHLI9yyhdYd zy)Cm$pX`ys$MF!<78+j%JbyjU)$DhOp5=SeF7_nU=&8LxY; zyQq>CYW0L*B#)4*S9VrmVZeZpvKyuB3ykI0%-O}*7= z6WUnzX_E7nW{v98trm-NGLcmBeWg8D*Cbpv+&f>N1^y6H^AueD#*+J`yN$nRAFDwg zM5D~Mdh#1Cp0&~zWsGO5DyTX!&MUz1j_H35@C~sFsiE2=r^K$~MX!4hSQ0^`PMr39z*LBf3&k zD<^ko;iqZt14hjCAe4ucc7r$6Yf!qsL_|6}Oc!PJ*e|$myKVSl&<}dFuu=1w%lkCO z&8AViY(RV%KXvQbmI+?&`s!3Aer%#*y!4=-zL_ZyNmGQqS*jfbKJ3q>p;=LiGnw;2 z(KKV1Fa&*}A(0pt7L62s8z4Lv9zV$Zp2k{cQd~MIXWC*-A;iKCEP{iIF~#Nm*mg$ zh1K!49PZ={6vi2%h5_N3l~MWL?yW72#z@m`vLHl>e7(OVY+{gJyUo4fA~1(wQeh^M zm(H1dP_ZGIoJAe=w3)Gu|pw;&9ZgLuZaw0 zNal>4i&8u!X7hz??l%hvFz2PkxRtt!MmLk2)%_)pW2XLs_&yQ>M3*f^Y`z+>!(!dopfR59SPFL#LQMFrPz2d-s*kPda< zEYQk8f{vvK!-9{=)k@LK4xKpYx$rQPe3Ko~Do^*3rqTjEy)G}?Onh@FLVTg{RrF0` zy=ka)b7=ikBrQn{dl)a?L9Qm~_=ui1Vl6zmWor;gD=ijmfDQwgd{B-}sW{@i?YBqP za)s7wL#<5<`jGuCNXx2xu2GS~`;JMUfe?+C^2yLndtC!=*?`ExJOwyH`uCL8ge$cj zEu9X0y~A7~@pc-Y>4rk66T&L#!0nIm`Ar*P|C=S-bw^PVHB!SK{t>;(+fR(-=v3s? zT=8{1h8c2wIRA)GVwd#epXJR|xJ7$ySD%&~^e>bp44dpmz>$9^kvVg({~MutvdIz3 z>LjTNNzMmuPpH0`i+_!ib`NI#M}cRFRK4suQ698l63tR-;gvxtdFNxrHqd^beNdpu z4V`MaP#9{p6-FpVa8Av8P&e%8WwUHXypmQJ_xO5hq?F64X^g+qJ@-(16Izde2DV_}c>^#I-(Qc7Lb#BKzJR6)cchAzP$-Kwf2ZI(VlBnb(mv$XoeyOs*=CZx zYuWZlIGX{A_QwNRg&M>qq5wCG7J+O^=Y`nIhkVK270%ct`c-zzarx=;*C@kIRfr@5 zkkznHZ1gj-JoS}q=2P7oy*70FP`s`9>V=B8!jEZ9}6ba zXd-!9EMpGphmpyNl+))_wqC!(lTlB~x3|9T>O`g3iNan;?AtFDzsy#9UYRt+NKIMt z5PSc=Ppp6Mlji)D4|}mPSHnRLcLu8{675^<)fHc~7>Sv?$M!~Cv_b1xP zz}S41*g`0@1;h~#UzZNqd|F6g%bUFE_nTYPJnaJ^9=BYW{LV;M_LhaN9jl~=!7=mY z4V#Q3qrHftRZ7J{B{!?LpI2s%>}I+8>w>ZUe!muF@*&!waU%;>7ggO{+Pa9k><7_J zAL@F(XN3R-e=zI@Z!r8__(zc=T67V#R92)*K%o%^5!1(SZYoAfmsI^|XpphC2*_|y)prQUVRYadhlTXCMoqGF7+ zP+-z9_eBfjPFczj$y+w@0u>vK^Pk2FKsILNm{ z{xPq5$wNNg(6$@v-}V1I>QMvQwO;ZF{G)JnUM!M$wB9j0dwz#p3~qgbJeM3&lXYTx zcfpfqs&@1X)J~}(p?rR^wIHy&^q<{8U=w*Qrb03df8`E4aL%iH`$a}$p;Vz@5gD8t z+y41y_wZ7zzhiRhv{r4~>pvyt4{hY~4Cg+>z7z*CVa`CUz4g3%9=TORdE7>! zJLCtE3g$iC`fw@fC3bnbvww#SXA|D*d*8URRW>)eynlJCA352iHaquUb12zeK5|uC zbCf05ni{f@k-;YkP2_vslN-C?aJRqH$ehZAi@@&&&mN^r>oyimQX-@GOb%V|UsQK| zL>@DcI)22uTzU)G?}lwy{r!r}$xpcmB(lJO0Am+RYOQ5K^h6FHlgpE$OaAZ8B@y z()b0tiAk+xrGMFnST_2mG6JJvID-jyI3Bbs#|=) zW!EF$@gTCO*f%5DH|rbW^-iyQ(z7dHzeW~uIxf|z3LHFp)cE4l0PfqOH@oiySz{q3 z<>l5MU9eRtLGXK^a#FKzj$8qa z!AuAIo>@%3rFBw?yE`t1gPTi3G9Nu2LFVZz6^Tzo)D|urH{|#=niY-cM!ZO5yfXh& z>BOsfF{So9Ym(v9V58p>MxAtjmA+mat){GrW72Kd9K$y)d!}kFd{>`&9R@V;zOtt) zr~Ea%M48GXAaL!kz|&_pHb&;5m&JuCL7X>~ZhuFKD*d4JYKy2%dUu2FyZDdaC?lRf zmXFu@?m78U<_a|57%V@0>R@Yb^gin|i%T*}w46$iHBeMAyv^pL-sT*(Jm#u&MvqkN zo0lHUUc>h2wj!jIucs%at7F&KE9I9nj4E3&kHy8o@Pv6Mx*01ubUmNDrUT7Q5M!P0 zngd9|c=M6o0?g^k{RpKz-^kHo*v^>KH~^d%=-ChNF~#I1h&9YAa>L)nh%|fkh&RQk z(&!zfse}doKdNnu`lQaIM2EzuIf?N8o1rRf7?GDZ(LwI^}EHq zh9rw`4WdqS5VCC$d3QVDp-OTb!)O|iQ#cgc?bYq@H{wqEdHJj3Zya}C%X808vzaM7PDJPvYY<Xv^tAl(-=gKFKS3B_4_%Lc?o5j+RM4c1^(dS7JU z=AZXk)la@()%<%$=Om}e4g7>ijM}d1dSO)cP4W}^4Jo^HHh=>>SJ7ySr%|-Yir1EY zan)%Y=+LAd`(CzWZB0Lx+YuiSA9#E2=N%?iv#h?vaRxwl|3?khrKXvUXJ`H5j6n*4 zq9Bb-p=t5AU+r4xjHiNr$*FR_Xb%-Tsq%BavMKCO1XvNQpKV79OJd({K7Rxby9ucqSa%JGE; z-Zz(@O6a+Wn3szj09N`q0{{A&Rw6ApKuSL*E3j>IKqMH=KvT5 z3S47+Blhsh6xdetjk<}w$av^g&uW#I=4B5R*2*P{_yshwITSz7_Y?IQGt*FWdQZ0g#sMjWJ~k&T`r{x5_e@6;!M1WQ)E#Gu3tsgy!W$!V z6k>aG%)i->ZhfW=BLnIPl=dl6u}acAEZ54H)Mcp8N=2MlDysYnK2U!lF!NTmht!=u z`fBb?i@VW>mISkvsx}_!CF9WYjyrVCfE*rPD2wg-n_~lqPuZ!R`YIkwJb@DKXauli zPBC9SkrT{8$_LuL-@6-BWLj!x=B*SKR-vBF?L%+~i=&BD`3iDL&2m#xkj|5$^pOi{ zFK*WMF5)|O%{6OY-(4R8Ip1sgwfyXZ`Ojl&Urc@&_*!2Ye`$HOeh@TW(ODcbjY$zg zxmKds+1u{jjtc~RIL}85CQp8(U!Cgm z?#!@VnyOIomQondc4gj}6iK^_?ZW9rImdDwtr?8q7U>Q4@(p}$vnMz3J~2z5b#g|_ zxz0n2TP+*m&}md8o0EsdB-9WzsX<5LlPvNu&Fm_pr+E?dFdiCNsvK~pVakYB%|!2L z)l5jd0y>gODfs}s*ZiU`UFxs-L5osDjsn-U{O@5`Vp;Bd9v_$~hYQyujxs|JXO-R+ zG9tV`2;#3CvA*XHQN?Ctvh|y4SO?Ox*8RZ!h&0gW(5eN6l*5CPs`-1i z!liG}4m=iQv`&~$@CG?qV(7oHGjXlgI$oi3D(76(zZR@7koL2I3uZYK_7{T}c<7$u zKhA9q54wOb+r&44fT_(=o4@;+e&GDMZ}}GYt$5kb~qsyGjtt(;`{1>wO$ ziq8dKiO!5_N`g$+=~^(5v001d6c+I^6u-t|hEVtztEuKkxJ5s+G9*w~;fLaWOr*QX zW4)W!*1fYt=3T*NexWD74Dof9+2ekWV%MC534xC$Y~sI0uSw}LZ(KoJnvRtz>1?uC zGcLVLWtN-mcWJWYUxuk_HH}3}&(j#$>E&pJ_T^djnrE6~@_qj@ubWSi>ee;m%s;^N zxQ(I#LIyj!CB4#6sIB?bE7c7zI)H--cSnZvJ?8K8e_@~&P;~P33PCrh?}U*r)6|*X zpC8I!o;~6guLh`|GJa!L2hK&js&vWZtN;UL|DqonV?h;dBH8>UOxy<45iTNu%taQ% zCD@IpeHJysnH1!nV)SIwB>0}AoLy}6NHM-osfC+hTvseC!G#@n)LHUaiS%QoG%Sxc zir<>io48(}9Ym>LTYG(qhO32@TmIJoxMklAL2P!J%Fm@bTG2#!r0ugy+aATtDc+>->ySM*3;OhyvgEU^nTx0fI59?KsKl!>iAp^d zimPraR-FZb!#;hlzT(_M6jYc}r~6TI=vjwW%;YHz>6fnbplP7doA}^=MS|)>)5D)m z%kMfDa=}v1WE;g{R~3#=6886%W&_;~Z@K1Lc>ir&_w%4GAC5#__!_)W~<(WHyXF(U8dj$zf~>R(TE1W4LNF&J5|)dFy~vi$I#t(7%?y zh&r#0;oa3@16L*LE`|zklygG@MGW zi1U_C;M23!$>1jUge5knZwi9!3`#d(vQ2Uv?gkI39%;n+Yla1E=8soAhDjk<4*K!| zbz_3HLYm7@1$E)Cq+XIo4d(2z>aM5#{5{k67TAPbQm+ohgP-3Nqw))^w`wdNXO))iKS&5P zYWA<&A7I{;%9gjUli*-1-Z!B(D<%GNp`^pUFu$96T2EIfuEg#o(wqKW5I{pk#0lT% z9DPMBx>hb*Gb++Ie;}@|&ySct4aLMaxLN__(XJU+Yef2poS()k4D+?%eN}_LIb+N( z4?RXI3M;70ntn_Fa5rG4Onl89=nLJ6(S?8YHY>_n3Hjq73o9IbDUyy&JTozODsL!t z4p+Zr@P=Oj?xATyo~k?L>>#o#B`Q<3BNqJ|pf|hO4QcJBlzEO@fZTG{=5(^KyU+AJ zC|Oon?#ibPIIAbt#)!lzv6ql7Ca07trtveRRi$B06aRb&2-|WFsT2#3rmt` z%mpAKwKGHPw1J*DA|OK0F7?NT*5m!HIPPhe2mQb!%ZWek`jOOuA2==gz0eBF6d2}l z2V`FK9Z_s)4Jb?Spq`J`;%S#JNil2ejahDd-8$43wgvNwd1T&R{QY!%tnhug1=oem zBO2M)S>wMR;5$9i@5Y+ayoDQ;q>dLD@i`wSJ8-t1l-wP}JazF!r_kb)KHp-*#5q2m zv&`_m?D-gXt>Wsf_M_j0&cCUWl4_deNk=RClvF@H2X709@il{-SUy=nyv8lF+zh^H zv=R@cw=k}0m|BEhWF$sSxGyymKo7XtZm_N8&?GgaV9Y0+it|m3)+o~S7DtOu&6pQF zeLkC>S)D1|1hWyWiHW|gj-T7(8{ZgPoA_GU6UW+jNnOBytK>V(E2~UNLJK2!te^b7 z#R>PWAwm5^<|{iyj7{T;99xY(ZmbPWuSPqG+q4h>7)bqBFlTYt{-5keH&8~pj)z8z%h@AdN4mubAu=Wp8CFov}`T1jBAjrmTPsNa!GQsW-Dm4FM*j&2H0gQ z?SCJ5FKRZII;`I$p@ULzm`%hb>%DRbJmXNwm0If3x)uVSLPV+-c-#E>RsxK>Hz7(p zK&Tqh>IYs|N|IAM(G{s_zGCjwG>`Y+qL)79g!yv8wV}83C+;zFh~S*l;SjBqTY9y8 zuE~)iA^-q2QJ(-|77qD*T|m(je|Mt-3p&QrN@*>Z>1)~AK;_cu{In!?*-au}`6?tu z>vd-q@IHX_3vpjB6qL_eFkeyblu7vA$glKZ##7%J1;DU_rZN@5F{nEl@2U#fTSf3? z5P43TNSqZDSeQ`#r&fF;sio`LtCFtvT%OOH;OwrPng_ed`+j_iu$-af3b=L#HWP%% z2%a!{{0Jgcm6O=#vdXIbn)2C`G&T)TX4V8+g%4q#XZ{IB??89GaVFDFgkTPDScsDQ zD3=Fj-{%3#!({uv@fRepX=*qhW$yjBxi@GaBI0rcKDB(!@=DD0v(?CiuS~V`z};9h zPRsbN_9Q{?lQ1n6N#*O;E4b&~2sYwkdX%?0_6r?Srb|hVGPGEprfB()dRCRsZqjR&a9aYE8XJqznX~b z@~7IyX;%3*anJ;-M(6G{0G{RHeG8YKNK|U4Ut6s~rW5f;I?T&=9#)MuW*hqgG3S@k zA?~{h5AB-A3946!+_fH<*Tk`@Fe?e0uV57mtZr4I!7-TUdXA!;)Gka(=BPIfnWhcq zc7=~76E-NgUvkO$RyXgKO|G=h?U)Owu*uXsP?o=ZSJ=53$87#t^NVe0gS~~XGeG1S z0AvAI0(`DpvIB!)FK6&+B9i@@Qm13j2fo3)CV98{eI=HSG5WvpR!FMA4)kpa6BG{KZHrd9Dp0TQFip4UvY^1@pl(IW8 z%+B1vuRyDuug`nnDWIzNv7T?tJ^4WoegAz1li0x*qEEol!AS+FdLRKY*Y7L9>xxxZ zD0b<7B_7d09#1CP65#w*$-0?%S!cGfE*!AT!raE4ZX&{lV<*O{@U=FNqa_!WD;yc;3JPG%Q z=uw2_7RzRmJQW61EL3r^Xw0flm=rPAb1co`>r67O5CRh?aNg2~>Z|W3PMC52XdD@N z%Fl-m+^i!t|;+$j)_Qc9ab zcZD5J=h8!dw?e&CXObZA3$f!{j2nUdELqi)utQ+Jg!#C+9Q&>S_^pk!8J|%XCU&CV zrQZbIGkJHHgi;u?DHpP>DEq=R!;Ztm>!Fk3a-xNTR|K5B9_n1zzCx4=(!YW3z3-;R zI8o`!$T7vFNP=*KRFu1v;?})3b-!U=xl!@yxFPF_?9!(r{i~sCxWX3jkG)W)0s5n@0X1H;X zX9%yy1^jg*j^D=n3G`?%jt@Fula%D98Da3I;X5zAdNr&X>-}@$hk3>e=kr)LJtQol zuJ|t*PcqmD%Qhh;bj!zslpn5WcRe6aZWl)%M|dpVQ^TOPV$*`>Cup{t>9B`kO6^>a zSg%9m1;7W|q0tksHN_QkUfp5)?gG4>EJN35Eu(bztpRu5&33@NGiMhDP zY)<#2ImR~Nw2L~(KOGvB_eA?cUirozor96pv~&i2277FoYOG_;EMFhD@KEW>Y!YZ1 zUkyd!0_Kd?51P^{%r*yb5UWzfsGU@QuI?OI@P+AJ5H#<*y7 zfoc1eEYv$w$Yt9Ukpgp^51WswkrVH$Y>G4Ig}5{>e<_JwwOB%F`YHL&(+!2)PeN~V zUwM6hh=;vAS~t+w{0+2Jgq_$eXkdsPyCPcpEC;tN+hS+;(h2ix$~E1s*$j)RD7^bS z$w1~oc>!x+Ki9CC=rdAJOw$`{UoE>HQ+0oDJN8=1(ZT%dFM<4SW2E?8!=eB%tfu3T ziX+8!K+6({0)6824ty|;g;Y2Zuvk<}OQ$_lm6Y|?t!R1@ZA?N#M24oV2@~WtF*8Tm z`CtK!EK0=FKIT;eM@=IGmm|C6g9GJdfQEV6J@KB?HcX~Cu*UlIqXUd1*A63R-clVt z)%Z;KoqghAeD_p0u#%mh`;lQ;wglV+{5J8dtm`!>74SHXPaKoWvFbI)hHNk)lBhV! zJyO7qA+eDgR5L;aX@1uVC(yDETUMKWOE7AJ#{UX3eZlmmj$JGy5ls`^6UKb5 zyTYoR`h!r3<92Dt%uEFE;Lr9JTxD^7w?ObW`?hb^y}Um;_xir^k}ZG5swHf#F%P`u z>j8~!$+FcovHd96bQEEp`W%HVe4h3>lcH45JS_6F-{X%8BkDnRH$z0mzH#x1nzy`p z+()Hb0yLxGT`Najd7l0(V^RBRDPaKS7?40`dq~xKYjJ2kA#ISyPTVl@SD?b=JNntA z1~ze*Ca&j=fkrX0$7v6_IgAQ4NtL74(<&uGZ9qB1i%_F9U?4xqePV+pNT39}_4=2w z$nB?=z$B44_so^B0o;}}2Sx)+D~w{>nxvtsn}mw@>Jt{&h(ViXBK?@UJ!c6qIcZ3_1D^;5`H<^ zMpeBP3dS;SF~i~y#umi+j1@l~Wo6og)NX<|3j~jo##RW1>{3G1Nzzz6EJ=mOaYfb^ zEK8c0yHqfNaRY61p?XU%_)$=e;sHvXdPQjkySRIL*Wyd2R;^QM(y6ci_{`8Xw`9fEq{&x2;M6_n*9|$&?1bt~4`!TR?k{OdlCa4z?tX6?W2eDZ zMb{t01_xp$TOPW@l%eH&bYevYZ%I3=l)}?yPE6kX=CFcBzPHK$!`WNLHTnMG--v=R z1qA^G1Zmj_0SOs`O0!WL8!<|n4Th2`3KoqtY;>+EiIIXqN;5`>B0WN-RE+PR`{Dh& zAN*gh`}y_YIm_}#ZWHB&Sp^@9OiJo~aE7T~_vwB`L-lk6yE zGc;HZnOt4!j=f;+(z@8=wXVvle_V=-^LzE1M?db#rCP|%8w2Vmg9PS6H1#udIha78 z1|>}+%sJ1#adzd0wfx>1B;d^0mvPeEYX;8Srq30l3rY~id9@6Xm?W~cn4Y2?BdWv# zcG-^~}QKbw`Q{Y>V-U!(c=qteP zp`zr3yvAkk5XVM3UcD8^3C!zX_EmAo>LbzW+-#LEO_0jw(wtMHNBz`IRX=wpL=81A zku;1KTE`42OkrwY`7J&{h~b;DaY&x(x}JbfhPdwruEl8v%|Dq`4n7AWdQF98hV68{ zdk)HFQ8oO$&BM)S$m3l7{rsS_2wG;3a~yF95oLQyRnyGF>~B_;!;G{45MIBoY}||K zsh>qwC;1`5ON!s8Ucm<41iYfCPpdg6UHpYs99vNeoR&ZLdTtdH`BX6MDYOcNrUYM* zeWGIHmqkmbNp|HoEt+my?eV1)c%qklb2T$YuLG(&)%VZao*f1jefLdElPbKp z-z-$%^Qw1K8uGe1&1&oMjcA6p2X5UV`$+-DoO@!f6_*rbBM;9f_cYCutQ@KmLe_(Q zE{*6GX6aIcu)Ud#F378By<>N6$IFY;<5#*PoqLzbh8QL!8ZtxMEZ{e9%A|bH%?Ap0 zJF17}2fP((7E-E&My$yVk_nEAs@idV?qD!(ccer}6jOae?LfT9i_=H_mZi@2Lo)7B&@c1X+*_Ec)iS;u>^@qnF< zBBC;ZyPG?uY2uY|%59=irpTio(~*b+sq1Euj}?$wU0I7&j#=D0{a#+z{5?sfl%z#6 zTKpkPNaK}~+U@icGTjcCrF8A-7(CSMRABd}s3|)s(lP%@-kY2_^#hHOF`Ey}BwdT! z=~a(d5@E@FR#uSp{gFs546l*Hnc=KjUPoPTIi70%UQHDU(XxT#qRA%r+j?9E_O3?}zHO#SU4Dcb)9q5wP6u)ufftS)TEiP0mIj`0&eC4Rr1yyj*>qNL zG%&2`#W!M5Xl}y?EgQ^ULE!lfwKVX}5EBTop=N96*4BpO`(nI{8F!!|zmqK&{62e7 zgq`v$T6a3tK}h92CrO_Tq38-JzxPY>Hs>-M*QIa%eTZ}i!t?42eMis-PC)ndQ(grV z$2YI7>5AN%?bkct`~49}>|0>Y*;H?Z5;_l0o1`hCtERc~$} zw~Y!Ub1zsR@@d-q1*!=}bmPa<=0`7FymoM2O~3tkde)Vc%wI=?vzl;@kSOmw1ymV= zIFun?WJ(^FvqgV}Ej4NiXDj z*k+d=OiPO=xYJ0n8ImLtoX+Bt<@}Tc57!BDCDt=<%c#o%o;(UFZLgz4coL)<%)_*cWZigD@cf~VaaTj<{-ys0T4FLGIP6ZCCQs~Iqq5oh;uOs&fyJE za_41SG*`&Y?;;xo2^u@|jy223z3TF=h?biQaLjOhQ4b0#?RQVl>N}^o*@qDg=>O)x zdt)hWPuH&hstSUNKZ&bqauD>iL1(TR@C_uC9~ia%EirTFQEgFw!9-Q~?r8H9syWrW z)cO`A>8di#rj@1(Sin&L3b?%bVUk|qpM^!eajM_VLV`RCW%hwF@mx^ z>|=7-rBr!`YdS)pFTavQmAz$hpR|KD&e+%q8v_ZZFO<97tjPyVJ<(_X1hhVV0m`GqggMmkP5&5&m$5)|}uVeRm>Zaw2>0 zG%1Y3$_8_Bo`@hYaK|#Twek&qOw}!G{?d*dWkr#oDYN6G4GvDfd3h-4PLN_`yVRMR zqZpl6btV)$8WQ(K>4JUGTM?x&-$$}!NJMFHP-axgz65UJwhbC+qjnq0ZH3%C|CPoJ zkI=-*O;KQ9=7bLHri|o2gqwp9y?$xJKg6CZpQ$wzFi$!$N!=+05kSzVvmDBjzlwMN ze&mkx8S{7csKqeSot0HhYBobbHrp*7uc~z2)xGBfEh>QsSJ%*pd#vGTU}19UA>r5- zpRDbfb~TsLEtYeG|Ms`2w%d=ppQfs#rXeZVw^Mp3WS zu`_Ttmt?9bnoX_ma`H1=8YB5R<7Hg%{XfS0;n}4)J713ssmg0-&F>(5%r4i-uf9M3 zDN^Le^Bw{4DG0}@+6we#hH``QKl2sj{Dr?y`(iqbQ*Lnll!31!QRSD27GqaNCTONI<&?5jtZ?tOM z?#l`?dJhPfSIw}`u?%d6ZJZklJgOi#rCl)0zJ#{POL9=(xZwD2A~{3S*PcaSiD#D_ zlnVYf59CIl!ER{sbX-=fd$>j9wO>!{ifYnFL_c-(X72=#trhL{Kp0w4eYo<7@;v4H@iaOMdb%i8RforD8mF2?~y)3 zxUKuCp>y&pm9s@mVG)f28YGdX;gw*hOln$PiVm2SZ3^}I4V;wX2 z*>Uxw=yCOuBRglMJ1TEwL0pM&v+ycLzSBKynhfY(ebZh@_zO3d>_mI&MqK(|<@Xa0 z1){nDam;Y%F+P%{vLP4c!+e-dUHX~Pmy`(Q(wk_0nUbc_^W?Jr@K>8bnT?KlK^v@3 z5Y^9GE>xQp&P+@884BE;Dv7}waX%=&Au7XuzEpaF;`g_Wv|Bnhod_tG^Hatd$*r9$ zA)kjgz5mXWqkwJ9zefdeZR$Hhw>5W7*Rhfs=^z^hj5#oH+W^n(*5I%M*_v^FcCN4* zz01?X$n6QY@670OFyk`9dZ;;QNXni(ZK%um4D@O`TkX#Cp)2Y3>S>4dkfYG%N`Kd3 zq##%chDcm3bBg9^3KWhA`5=G6y`f*SH>Hnnr9FoqiX8ynSBsU_oamT5Tt%>eIb_SK z3(yFcVV;#Y(vn@(Q&Na!UFiMaYSP8^)DzqhT^vmS9KWOU{GT2>KMQ7=yyO1I6H{9v z=Hc2Ehy_o!<3X=S70jkAl}bh-F)tPL)1)P7xt2OoJr@N6HTt#)1UL7LxAQ5XH+l=8c=aCS zMJu01juYMG<|b)+kU3zeEYG`;u{ZL(Bv7L1A>ktgEZzE9QFi2rC0+{`Ht*d*k1q`G z28oa$Nvgj%V$%0$$vKgu7G5Qp?O&W9D(&JJ7yh*5ZHhw0LuNch%FNB+Qg6ZVPYIoI z+YJr+lF1E>MHqCLJ@YjG6tAqjzEE-WLz_wcdLQJ0`+SB?jS^J@ECb|$$wW=aW3oF5 zr{389c@+Gm7n{}aO+M8Ts=N<|C8rl&u?N<+NW0qQrq?udpxM#d|k4- z2NrO#gh4z{hbvH=qBgN32``a@LW-jTlQmKp z@D8eOtMWyxrxAhS4bLU^`LerPLg{EeLgSK3=J^rZGYV<6%A|X(7DGxQKPcc3R*5Lkr+_^`kW}en=h!V=L>H zBG3RY8;PvAEhDq9Q0e;J(@ob*Op|PO)vA zsjP&-9|eryX?_-!bym|@DJ#`Zfk&*GdgjwN!c~Dr6Kf6y`5oc_h zbl`vFRF$9|U%kb81IRPE!1XCkSc$sQ|028Z^jXb}V~(M-?rNb$?NCuy7+I|x*?2ig z_C7V8e2c9E2Y$n0>b72v-Ix5R;1-kpV49%2q)<#}WGNlnQhhZb~KG7$pR=+Zjib37CS!I^`tn7hK0o!MGgC+F;LlTu=C6J<=Q zoQ6Ax>J1EpWlkDcg30;ETercxHu9=MRAMeLF^OuVQyFDy^po+7JCwntPCbKZ zDzUqS4N66ZyV4fUnP#Y7FLZW4!D z4DLSihWOs4UC;&$*v56vug0(N8z4b_+;%7Ma7azFg%KqA`EQ=Q3OO>PcKVBH$+7I6 zZ=$By4Lfy>$JWMjq(*&5*mJbZ$=C!D8VsblnywNoO6P=@(t!u^TJnTOsS;4jGVuJ| z;i~=>5+vRh4VyrGfmxqZYmD-q+qjzvbka_3Py7Aav}MhRa!kU>)bhi9aE&*i>FtN> z1O2rvc}8J!t;!OyN_?V7i!NXeC`abT>g{DIl5k{kd|nE9XPqv?|mIpr#yV@Trk`CV%n7W zL4d6!UGtTiM1nV3L-lQ-J=#vzM9%q|yN(%ZWDww`B+#Dx#lX>83|^XxqAW)$T|%5W zYn0=Vl~yQw3$i(yYsKJsFckETLd^|@%Tnzsn)a%kcT^O53kQ0!`joC09qrQUE0nfN zK+EH^Ucx*SdvKFMnpi7sw4jd#j4NzfEiWOD#sk^_ZTv(eE?zC7=Gh-qDlDEiwf7r% zOm(8=iCVpEYJ0Np2gbZ?-M#hu86o2$(4CgQlE`ok7jx9SroSPR>KEFL9*J(>hGgy| zyWJak6*j{4%b+PDgt!rsUW-qe2p@GaD>AnLa;S+;f<{Y8m01xZTy352G{GeFwlO)v zv@*EkcY?B!2Hw3*EVkoJ;BEEL+Ev)5N(bKV4W~Tu0@OrNUZd9oX&fZ!+aX4r_>Q@$ zIVMFDg-!!E?qXVUw}=nnHv?XKs~~g)iI4`#lfnaUg!nH-`ALxxrg;Vul-YqsQtb zHS|m;Vv_%6c%r<}9F0)Je>0?>_UZxXtkC623c0lFMcTN;R({rGCLHt~Ha-N0|g@ph;SJ4^)HS5?3g zPnezz>2GNCb!iNJ%Wm=BCZO$LuKCq)3@If^5ne1HWqwirO0>Mt7Y$%vka+%pk8ImZ zW%9nyz{YhhX$=d(o2AEZm75)(|4ojZO$gZ$d*=WRoKUy3#VYiFNmfM!QP){wcT*UA z8-ABlWs|;Kxg{_flm2kOM3y}cTE||xmo?#MwsP zTM+is3t&1u-UlrKZk{BXf+}1*wmCrF~PNkZ+Y1E zMhA3l6!Db&iG2O_H!-O1vCQ*yZ~t6fkfVltsUa7DB)oVW*N`U!PRK`e&!8ACJeoU~ z?BX^fC6!uK9;r0AP=_d}mRj_f-)IiGMs39%*D^02F4f5A=avQDdZ==d`wmwm5bdMQ zeeR*3KG~cKGGVV)EBHtY>N}`Nn1h5nn3s5t-%Y*%$M`T1-`SAeL&CuxR^hof8#s(e zTqFR(2X=W}_5Q~c%N=4|Du)H?SrT1SMqfMsb(V7^QSacy%7-w})sJ;#x$9f%`W@J= zB&)~o@5{P5qZ4lyrj(Q$j3{SWOJ?_aRNoN9kT4Dm(K) ziWr~dt+*P`*B`$z`DZR$2Pe1g{n|I$KtfIS56^*|8fNS0VJ@Z90t$t6z(EVv+ieOv z<|nsN-J2xE5_nK_*ig)YU$Vq8WPq!u@TCnIb^U4y{++{ig2w3g36N*bD+M>wEhLg} zQ>DwUv*PeyE6e0%A9$Z_c{Qv@>9^1oGg7v#?HAKV*x$V=Uy|ZvK9DBJmz5bM>1v~( z4i&M#$(vZI8PXb4qWDQj;VUrOm>(||gI2R11$F73?!a0mv+iF#b>8gXgNrb__$=NE ztNy#+BF}J!639gxN1G2h?ldz_>#xb~>!Xt4U^d_>PjZ0vy^1I43%T+w=4XzwBGH1| zQpATu+f6Md;EU|&2J#0LLEE>J?hG^M#8{lpLzAx#LDOcjdQ(f=1A(wZAv|IXrf<(| z{gne3PZ-;YxW5?TmL-&T1|PgyWJO=+v_Qrj2r})pNn6;~sB$AL525&(Q@MqO=((T)Mzz%itIA2fZIL5$uNt z&^yP3HTc>El<(viE~&?!#+022iK$$NZzNA#amxv7Gp?eIBtgB^y+P(W4>VWqtdDsa zrI~sM^GW<#Xsn-DYxO~QLT#K4#w$&z3rxQ-ULv~7T~HNy1|*qdgS}2YU!A_JtyEo- za~xP=wrT%pYBRt<(KoM_9epQ5jeMfeENz8Qkh6GycN1qnHPiRXgip$2|IxH+dI7}< zEt8y3=3rX-aIuiB2J+^{2cyf4%ro{5B1U5i5({hefc}Ou1r}i;nM7!n z6GzL8cws!SH#tk@W>r!Pzyv1kMt7DIS?+d%3}8CG8moDhDwvwoR)VYyFs=z@zlsko zysS-Doqd^x`SWo!v%g}X&Z|lb;XUo8{xUEdt_(Mn0^)rN= z*VG5dI_uJ8yhvr&J(ZQ}=|6VUXmLqEC_q9!dJ9||+E?;vOb#?svihQobeq?i&=%n#k|94+zw=ab#Z(hr6* zvl`(}p}6BCf7O@}j-ZKn;e>If6bo(oa))rp26$9{+2{pNwF>7!FK#^qddv4+>asb( z-B4QfCIHm1jF!J7R&n~FPa|eGGi(Xbe<=jZ3DGvtZaR?_Wh_maI9r9xoR7!W%;g$Y z&}xnh!7a>b>EC%HnXp67yVJ^H>c=r;&J{B%qh=VxhF4U5 z5GX}5Kwc_)YD4)(JwZ_N23y71yWe}c-kKUteS0ZrQdLWeHGrk@GV{)}XUTRmH@VBe zG5CorH+h&IfNcX13OX*)@kuIk_RhzQI;VjOgT+Fjme>2D>Sc97yf!<$WCNOsW8qi0 zZB$6 z2w8RRF$%kjNt8N{(2Z2kFiD>yHbpfoBGi@YzPh1dcK40Bmhut*9#%RW$hjJM&tNRA z+neiKNqC+!(7THJ?Oyd^KajSLo$0-{4$${<*&+z z^4zj|G$&;JtQO7+Pl*DgScd+`M%~)*H27Idb+^F9Fy#cWpaIdRU0Goye<2}V}Df*nUSk?LOfou^_?2cd#_c6a}$s-eblv( zmOoNy&r;3+VW-LRz#9_Zr-l#|K?vu|S-vl0zDeABEI7&7m)Lk_S6MiSpLk#=WGYgB`Hcno@TSu#pi%lB7XZjB`{6>qCM5Yn{@v2vU@)5ITPI&e=B{Sc&V(`G ze3zWnH~6gtKm3(y+xgC%>>kP*RXge}E$?4IB`I8rRmloHsl_+#Vv<#I|5EZgwyGF4 z^<;^uNY`*wlh^PugG59#Zz~*n5uq~LQHzqdWfVZVH*Af$JNz&R`MPqX`dsCBhCVg| z_Ky}5E9ODmk3J1Rq4NIS){f3xs<>J{Clg5U%YFzeL2O{>g@UDm603tD7q0h}0Y!xKYY^$OVHYS9w@)PrvAN#vC^qvT4WtgdFqCR-fB%Hm<2z^`1@nj+}pxwiWgv-?j)P@^jnPUDefkBi&IFfU+i3 z7gGeX^7njz|xH?9#Z9s7Z=S>E0R9zP8D9x>o+yEPEqQQkhUdy<`3_? zzsE}?(Gr5VJG7km3R;TTAFHd*@Ln`1IH zA@|j!dpY~J-l6~4exG9^-oBQ9zI!u3jTMMg45{ccGE5u83$?^McqpEj%Hp|y(;vJv ztYeX9mik^Z;;b1=+2qV>%~;<+&9JglY1Iu+&sGp*Br42hx13+A&)l8-GXD> zp_XjGTuni|`N&a0#lic)u}V}Oa~c*fEz|*m@{I3*Pz91a&ei=Usz2H|6GNt-yxqip z@^=d8b6;rMjsUhFGpzPT46`h~6YU5iUSq7}j`J%y7VlG!mf~um?@z>rM>M#6K)$NQ zOZ)D$Ux;Knyt+Qtlf8nh88)+V zhRhp~F%8G1LmYn0JPt0yUK(oh;p|5U96y2}$}?|6;3s6#+1Szp-xbkjoEk@9R87FM zSW7eD8|(@j!RAW|S_Wat(q|A9A3)OKwqC8pm5zgum!XP)z|dYx175AVYmkG8ZzT9`rzx61@vKU zx$zKPVNzo#?S%7%1d4$D1x(o#eg`^Wwe9t|Iz+5#CAPQF*2A9jK{o%VS_A+SG${Ov zPr~{^95Mff2;}SIdnpmOwkTnLgE!rO;m38_QIF64scw9`x6~seJcc#O2(Pv%o6;&jN|;-t z2G}dk&?oQNvI0lQGB$WWDfV(oeuuAPiXq~JBta75h&~=d0?BsG$>dMC$m~h=iw@hf zNB?XR>b8y!ajqe)h0F1mfFBP4g00HW#xZpEJTdYLQ-<-mA0uP`_04W-49?JKR~R=i zBIB@dcN?(?+_r+E^IyC(?t0M}A|xZq!4VJO7Ebxs_a9r|DR=LT<+2(YaO9)zUd8UW z(mbJ5-xjvVjdykC7rdu7?tLSZZv8ZQef;R}$H&#}H_t6vnLquO;&x2zJpA$R$-@`m z?;mfe+-zk%o_RpYefkiFRtr6krdQIC<>H5p>fJvov=xn0G?^_5xIZ_>X(2IvYxOPn z@xYMPg3P#n2;d>Apt<2vfHwA%2%g};C>1W)gTLp(FGP4}>RAvK{i~r~MeD_aazvn+TuEQ(8 zT<<+y>q&;qh-j71ywq<}&N~gEOZ{lTYBIOS180OZhJ!{bNvR)G8lZRc7rOLe%3qM{=%id3c+qmyX$fBaE(BVrgKBkU+1b1-sPUZTNLxr8x~t^RoC! zd04-WwkqMi-|+bkOuyz0n@pC^4t-8V~Jsa;0H zWQ_yOdz0jJJ{k;|x-B0&g+sXl$>#}5K)9*k6)9~qt`5Cw1u0z8@r=M*W--mB=_SHg z3E-qRe?4;yxUFs6jX6X8CAW3ox7Y48c=&`d7KMBdrGmxZO%?FmE5%L^|Ig66@}cmU z_^~M7@gJMQ_SZi@zjt$9inQ74e$`(q(;M0#-Qz}o^ZV+R6$_SrF(~=iAv_+H!?B|m|%;tw`{j?do@<)2==}JV~e{4nKr~h{_1$9`5Ty@;X z@yJnWxmvUqAMpk7g^}#|MYdgymffsHGT?yNuuLPjzr{#*Zd7A8a+!J}zfI%brOOo-)!2R>27w?A! zZ%GN8p6$`C2Ba%mTIi~rQ8+IoCo}EoejB0bZpwD~k~4l;qXdi8sDbim8|&YHYg7^Cn0C@giBv{bL?SGZC< zYavxk!YNrdKEm1)L(ZYMH5jUf)=KuPf*{E-H`M75aV>l`Y|)aN7;r(lx^@zkH0 zx#tgFH;aCDJ+zCo&NjANE~=@J#qtRb)z!*IwAQ2+9L_zkT?=dgH~#@{r2OOCy0zQB z@E_Z7%E|xfF$v9QyFS%V`W$jApKQ1kx!`p#LX}2s14GUT?KOAJyB_V#5@{dku8s1c zH!{B3Qh!L>U1!Sb#aGT|{yI?m=vGgKE$q})ZQp8QHH7}c%!OIZ>qqeUg;mZQP-h>A zi9laz$Tl6I#Jm+j1=xZ<^ktY{e7+Q%XZu#ryeu znkQQUv$ja3QZ$v{e!BBNHm~3nfawh4*VQdQ;|vX*rsGDItH}hZd#NViCEzo}R7aNMRm(t*XCeTL+R~=iAcYlk;kU@P;~P{wQhcL%y9FsS`+A4y zBDg%O!TsG8r+Du8h>=P4RzEE_Tx#_U6k;u&1jmv~-;P~f)=}VLzx-A8nspYxeraw& z&Js~YaR+H8pD@lxyB_UuToCRwhPYq+^#7R#ZN2|ubc9Kq&t*Ld)-bdKDeq`yYff)_ zu^dFrt4pt*pZXREF8ROouC_;*uW^&TD@=6Fn2s8_XoNCipZ-%Z*55M!r?jdoU9zuq zq`j%E<7lB$1eGCV1TNaXAe>&@@ruZ}(5-7YvhBwZLc>FSOb(#XrAhrkzQ2ZJzia!v zUyGPJ#$;~yo06o8MfKC^zoiP-%>cG1PAB}U)wWFil;XFKU*y~m$I3w!?!RxNZ+L;P z(FRBpQiuPsVehT*9z8_`^kBF=6@G5sY=7neoi*C$w1v+-x4qb;dEgoxaV?xD6#aKk zJR-}|!-0M>3;Hy(Z+zoI9>DdR0q;-)rNQg1Rnzugt{n27Sn=c>*`A5_HX^ZJs-Fg> z(+)I&s)dx6XSUr(s9*QX25Sz$e;DOzyQ?0S^~z<%0%ESkds@)iZOj2Fq^hw@bKb`~ zq!yX>AkumsH~!K-AQhA;x-gt*ub%6lo1_a*-TV5;y4-i6+S(suOP*9Ohs)3SIR}y` zxv{o2RpFsY4x#_5Ia-jjYPdo6;-z`ew>19Z-TV!^+c$13{QutrXwh%US;3UNjO@^U z;`%M1>D~MiTh0qU8s1p;9FMYc{=*cVj4>&D%)0@WiD=BCNqX1Mu+g5|L48kC3kSPQ z9D7n?t#;#gvjpe@$VZ`a7O)JWxx>u(EgzcNpV}A6E`vQ(1JZ^wFOdD1=ld3Bj6&Kj zc|tVv4?a+~{6$%P){F22Z~~a9ZEJIR7ru%}@YC6_to5rPR>SOUL;>;UeOI&lik00X zuiQ=8So+1gHJzwF1t4<)^~kiO{c_!AUs@ZWMEdbnlt1f4oU6F6lq@Y zxcx=`Y~)x-^~R|cQJea{oI7vnYgvxQEQ;^Hbl>F04K0m|O)SzwnZ}z%gjYc(eVBCP1~-BL-#oHIrus z{r$p2FW`kI|B5e+>$=r!_wm&DvJl;L)^gtCl0;Oj5$5=WyU9s1C zNcSrjpgAj8e}2_h$};{Mj*AdAVhBuhOQ`2uWBpIQBGkx0{OfI+m!+YtxMP4M*%jL` zhZ4$^&!n71{JlC3rXN*;h#SY`L-_cqfh1h1pqDES>|9*6A{j31sWhhIVY zW0t_!%kN9|OG70*B@p4zTXMs255(~121u47oLM`{=n=FCbrOynH1equ;HYXC z8*65PTHN^j-2J&UbLCd7=P%30HZ!MxNo@_GMS2`8%raJ|4*Do6J5WBiw8&7BnAd z`lb*Nn+tVUXUiW%w3UvFs)gF-97G#^%*epDm0z!1R~`t=zK@C<P6oa(W)vC6)}W-^>IT(Ex%9}EG8~E2L_2G8I(l8 zJ5k4;_r1u&=bIH+{S-pFx}&WJtDa<@-QszezrceL$X<-~y0|p$S0=aoC`~YS8ShA< zo``XNT;74joT{!An$W!#Z9&DjWMI4t#>y}FjG+b3usU0?@<>z?@WZ$zhbA&I%gQ}u zCYWjy{G}^!a^0tElOm?g`)r#Y6UC56wl+oyGWH+N_RS;Rg#3qhiWEo_tQ3T(shE-50V z%LwKAr46BF{a!|!KZ9EYXcz6bsaZ0n49eVAUyB^BsY>}g^NH}@dw#SPx6~YR8qTt_ zpaM3GEPv3lcN|l9MD}w*v=C&YAFS`@TNm)P3RI|miL=N{!V%tm*3J}CnV0arMmfpojxukzv!hYdLH^5-5Q_tD(WItn2ezQjorhkozUpS4JENj^36YwSGeWL-ERi zuSsiae_e8VtI!|JGOtsn;%{Edx6pKiLO|E;@G5!n4l)^9)FjR$e z!snV$RrPJA?_9Ii;2E>h3GDh0F}-S=x+=_yNYR~Qs1@3kKiqd z`8ZM)Ehf3PRl8ruarS1cMula+PwlXUWA8qJ!<&^FKTjtQ zQILWdgP^pKPK4imBxoE=lds6M$vwswAyCQjwPF!YVO2rRm8zjnZPYD$>J*NqAEGrn zP>sqx^~O_g=zz>Q+NrgTEbST#y&3l^pyF^M2y~SxzkfIvq(kJE=SJaMg!?R(szf{n zh+&fr8d6`zb10%aGXiJA3w)f;dj@k?XWe)Z8hN>e zF4w3jKszk5ueVUIp~WHaUJQkO@PQi2K6{|SAlmT=`3OVtYl|OTQ7{WRj310Xjo4~) zXul`3cg3oxY;t?>9>m>i5UiQhOXstz$Jh-tSQwY62~nAgqnKJ5s}hDgf4}0R>XCo; z2h#Q$6Zn$dZ82CQD9}%}lm*Rn7G)|Kx2iWRSm=xC)dbI>e9(-7Hy4HCwtmKC3Brmg zy%|E+)1|8nFpEWPN>{OtM_V;+t=1K{0-O)}Efsc^j@sIgG#%55K7z{TVWk_cydE4i z-UFF0Ml3bjl0JqaHY!LS$`aUHsCAEuWLm~8+Dk^=$viJrWmnwz5nv^Klqe9wKPLKf`9ytKV}mwuVEEo1 zpkk9Al2f1wb2PAW#;<87SUBjx?CF^ylIRy*ytD`S36A&suY+bqfAYqXYz-z3u9*FL zL)d%l>H+`NQOf#@`POomey=A7&Da5oIQ#U`DZw5iBHz}SOAB;cFVirm9$G-CZ0{cN zttoGsJ-BS3ZPOX^p|w)a$6w5OY_@99$KDsW0*{6=f9G;60YdqAFnLHUQUUe3bkvoF z_iq+z1gQ5~c9Dg9(=I$i&Yu_;Q^)%tLO0Dri;NXTNj02TRcm{$_b%D#?^OtMWBMKVhKPx9n$%sryR$EG=V^NZ@>863Egs`y70E?=ZRk zrJP%ag!x+~gz;djhDpZ6NZU=-Q!(Je!NVY2nvgw1CgJ%^HW5+xrdjyGZ;1l|^+z!d zCcBc;$vjv9!nVySp!KPpBMf@lcPLN{35F8|W-FNK6`|@USM$OZEiOIxwFU|y8!ehCN3w|5MMgCaNWETy zF3ivZk%*NmldH3{&=gr~=TBVq$ZumGbHV-!k0pVrgrfrD&3J~oT34M6YUY@WKgkTQ z!jG3=@1!gN}4&iCn8dyu{sEWlMX<%r#c5$?i#lP1ruM_kPT@f#5{})-co!GW+r zVw2B^xBf(>x(8Cpo5G;+%ieAzIOCD|aSzz9!Z!wuDiR9H;1RHm;qkk1=iY}Pkdo7U z9zM(`dBRs;v;>S!y!wy_E~X~G_WI>-CGKTBUos>wx$j$&Tm+*G{x--N%IJ_9|ETt+ z&q)2GNJaIxAGAIUbH!C!7at4s&$vaRe3adO>c0ojUK*sf-kRA9*RP;N5rMIv}W>V*vYx#bk=no5JKDtIGg-jWrTZ|%hzqD*e8_dbZML8)&4HrYMg z#>0}VXfAj$%XlM_H6?*28UKUFLLGweg*j8r0}2FrWef9zE%wu=4>?7w8Gj zmJ|pb^Lm!7oCBlif@zB?_HGjOn?fheGz>#COut^|E;E(0C%hnDK^H!)16K70xt1UI;(+$p8ahG$vT5`}GCyo=-2 zzS>=mUhLC$ivXeQFjFm7gdbujEvh3F>A!-Q%BawQv7Aao-_0bO`mY7SO`)qC9rq?S z_Pb2S9IFOeFzSM{d#@hPfQXLeS$ZXn|w!8AZIXFt1+lw#d0VWKxPkABVz9a`2;>9CQ;q4#M6>8cg?8rQc$2rV_`2^kp5(<=E$=&e0k%tLsO`Eci0ucUnF z$8g-G5vU1;?eS#;R3NQnKM8VVTaOxI4xXfKbQRs50n7GB#8%=W3(=P=pAhD>WRBY3 z%;23lf3{ca!mt=GWP;$0ZBIR4M^qxl=jVpo0GRlvP2E>BCRkQ_+QF6~+v#!F7X)M3x zRQx}*z13ILQ6KiLCGeftapd#H24BaqH&@nWqbSvE` zU1AUhi1)+UyVm_4+|SAL5A1{e+v~UXzP{IWePD>j=LCaFa^4^I*tCUc)xg&r6ebGr zrj&jfzyA5e&7s7JGQy#OvzB8btcsEG#$BD7q8bf6-EFQ&lG|?muTpF};;}7Qn%THh zp21X&AWBS>f8Vv3AJRftTSV5+ax*q2WQoq2F-zH6)gQ6elZ)ew_iR! z9$@(xEgTrbdrt%R1mAQtJ;pJc&$8`eyK@Zm+}DRpWZLUbd%U#AOKDR$M%wI6NSRwr zIp4M(X5>U(T}t}cB5IshR9&TC!+&a$Wi62*B$>D5*JtO4sGjR@fVLgdKW1D$y*h7# zIIGcWTVGm_MSrY{ECK8H?}~SbTt1%wVB@FHM9dS^w@UfHs`}j;{3L1BPzR_ZTA+xd z<~56fj048g?0cPmpmju);!(7Ig^cqo1hdjKRi%Q16oP~>#6;iF0O zoPTc)5=oBmQ`y~#eAA|r)t2eoyKQf5r`o%c9Zl|#Wuwu_@UO#(yfQRJGnxeE&D#Qo z!K_Obx4BzzRF@oiT|;y3R8(N0WIkU3$b1nNBI}3H2V1%D&(|oL_y0g@!_4k zcUJb$#7S^9^xt5omy49nalwbbum2Wqp3boS!D%XNEeyDlM6rcR_%9v7WsSi~;@Q^s z%2gM5$GI}_#gQ91QRbG>DBB!m+e%%_!o%y8d%T2$h)(s%yZ4Zd@mS^io3}Nqv;#^; zD^?#_+n=BU7pC)_N9oUhoych%^tsYj6kv_ zPMRe6)Z=W6h|O#|Q|67M8)N#qs+D6en;T6{An~53Rm(M&>RywZ}5Jya+;Uxkm8tmRcmNkQKXV_Rn0m;KUzavqeYyt7VMz2NHYWCi3E66-JqTV~o|k z9b6!v(JWU;L3}XRS9+ks(7N&h_oJ4eS@vv?v?1y$$g(H;c7bZNw4}29W$M4t531Qa z=3y>a$`iM9r%Y4F!dS_cdXV^Aq4A^r{TD~H_5tIVLM?kClIO&Z@snGSQ42a{8P|cy zLV{J>)ZJ3oO-A|B$**HpHLD889EY<2_T7Lv9TC+`FU#dt>zhMm2-|o9vcjT0NV}%v z7?&O7F=O>QxRWp>2d^t2f@n%0#K#l_s%w_MrN($;EoF zKGkiHw;B@%VlsZ*an^SzUV9KUu=zO-b7Jdc9o!~%dDXZmhn8oC5)l~TI+p$i;f0&S zFuFZCWnvAqXk<^QY$jvNZ?`C^E!%bY$5R}b!)f6eS-`ZT&g4DHhU!Dk?6j$t)9)7p z`65o>pg~h7e41p9S3jjL@Y@zm{KKjmLUEO5NM3icZ271Nwovp?-xH-ThGc&uSS?R2 zRc@-wL;ZxX6u-wcWf|9-?5xyIB{k-Ue|G%p5LIPS1a9VTCuLkHhrC#kN4_gJrbY^! zLGVakWW)$VZa^A$$GwGsCPPBC zMts}R=)NA6p!D45X`MmMEH&cBg8O5y9Y#uZYdv$}r3Qoxr?R=j%EM+aJxx^RHw*WD zyvz^;e&@|&6gUhj$L*wlRA);ZB8L+_UVt)HH5PV3RVdpPh+`W8`hlyvN3S*z8{B&K;(x$ zu4J-F)ggfVWv528t!p)I&`uu~wT_M{dN;LbSXcbkBiZy8M>F)&DzbOK8S*cv__z~B zay_LvEWQ8AD)*Q_DYKSw*_k4n%Gh+|dMcd{Z;6&8-6&^~7Hw1h z3-Bd%UVAxihk+wwZm`zJpGi#|BL_=TWe=Se9F;)FPs#w{0+H7%vDD0!-8!Em1q@J|*vMrW%_n!HlO#!RPYe%ja6QCOW@8>lpobNMJ zxu}V!(yStkTFjOPC|1`WI&WsnP(w}rleqTqhE}QT1t3g5$C=}1gN01OF z%ipx`a`rDWVkYIL8c|SgNyN}~-So|M&`Zs~sGhh2e*GRoxligARXLVDDWld%1+TCqYOQy_F1g9I|leY_CpqED0Aq=4< zYf}F8Y@LMWk2NrS6DYwS-bAmL4mWU5Cd(96hk!IQCyL55G8M-J^;+%!S{uwH%g6{x zmBF=lOHqGDrg#h|dCmPR4wjgrFOo83{y1HP{uN%Dc`|ZuB-E_^^vS^k@?XHq&0jNx zxR=J~_hw~2c>KIsc|pEU3AN=?{%@6)N9MNYq8If;Xq$NPKli?P$VlV;KP{sD`)45{ria%Q(~5bxF3lhkME7d~fySQ`pU)b74j=tDZQ#>@olJC+qP3 z|FQ|Jf4bz;BoDuhmb&>Z#Ov*ibGNsmPi712-mX=C`#bu7^%dTq4Q$!=WJmw%eDvwf z1?5xvy#vGfPv2*Q{y8f`|HsH)uK5z{<8V~7HrjK(n)~hjzr}CEH%|#)yneeW{^yDm zPuYLDxL*I)dfb+uy~FDMn10{3yZEO6>yjz-|M(27EltEvj<kN1kt^UQdOur<$9w}d*V@I#1x1fb>)1!c_ z7r8$zfhC6?R_6K!4%#`}Q!{XFe#z{jxBwQ#H_TTZ72FLJcf5XjZN5}ln|Kw-`DE-~ z%)QF*vr8AbH(Ct-bH(*vH4m-rB~cSw_)+dJA}4Gy^zGl4i`0dUW0sKU>C^9tJKQv^4Uj4_3+)A^OI}eexI&|8?wCg z+8s#h>q(l@MR=Ch6hBjY@f6RSAB9{r4#!rFknW7@3=SJy-NhpE9Dz4#`E~@i5`v$e zdAC|~6i=3z2VcEH()38bas?oC>i>mi=gHWR;Fa&;+DCrP*RTBeR`)CR&iflY{WSl% zQj=T<8lG#271tblFR<~{{YJF$i&iV26UfOmZE*K=}{%981tJ{SjBiy8zD()~(Txx=?6$GOb%rXQpa(NqOT zDHrc>ltgXxI}NPB!-qqs1z+R|3G)kKwXWRF438{QDD)|YOnuQ!+(wpN6?h>txlze| z<(5Esi(a~@C~xiht2@duG&%g&mw8M#A8ggOUP*?S{<1qn7~=zAF&WkiuUfeD$6oX0 zTKO)`Lb|7gAsXhS0Knxq+*R{;cb-}I-H>F1Eylnm)Ua~}6 z&?*BC5{mXyj6QqwH?~|6l~Ydk=}o~6EBEN(M~OC%z_G59(?EJlnY*!+>9z=$IHM&U zwWlp>0eI?U&---V)B$Be>d*BJa&p~ewGolfYk1hNIOG+e;fu|yE9U)j#u`|8LB2>w z(UBI}r&l?;=H{6_o`0jfC*~*o7_Jv^rR zq?p=U)G(%^_Rn;XXP?|88O9qVg2MG?F|I86Eh5imX=j)R*aft0@0B%tAA#-14SsR5 zzvvs-4eJTaNdu1nQQA%=Byw8#kg2ggkK@rbv5tjEO%nuYYAPxqPCBDf%Ylx~m4)ED zbo_SgHux9HPQhWgKgBWw6{%AoG+m>$p(GaM|9d~(6p%^HYD1U=+y8wd*w3H{Cq3>p zwFqILU1j^N?JC9k)$&J?B2ytkmr0p7DXM%Vq`V2+SlMrB^p~SR8xFXr+J?U>1Jesu zKB_8)6&ds9WLE7-V!+u9+Svk*@()cmJlXJ=fJk9yNi6d^gMVA5b_*M8XwkRQxg5#d zY>C0Tdsq9zKMS99O$k$bTxU~v;vFw(rnw&3B83ySc7ulkq7t0^CE&(*t8Ussi@3JT z%a+?g1{+nuhKEA&0_hq&gSgvvTYvH`c4R1=1unLl*C~?XX~s@}%yjJHz*w%JC@`K@ z+^j6hrQw56vc12w0ux@HsEe|}DNys4&A49*{z_3F%SwbI+NMqOJ(?7rLIjMC4T|xP zgrTO!7P)K9&e?uB7s~y3B)yM_sy75VGiYq_S5VlUUkCk|_3Y(IelMOMWMp_5{}Z}+ zVvLy}oen=oVIu9*PeE2L7DP4H^~qdfZ(x=%|IDL9mSr`3Q*S_I>PE{V>oyy0VkYB- zh>X1)K{8Up5XMYc{26@CwrNEt9)zKRgF!C?0lrJT6NWPR}HW57_vZV-?3Jz>~JY}I?z-%`p0GtUwI4;-LPOWdF?0PwiHCZ#7f3;OWu*fs|$fIy3#{w4od0SY?ug6tX;=sS*F?)Gv(tKVL7(- z8&UNjbTow#%cu$QZ41t=aF~#I74rC8~Vl()VkUKI*PPR3$#Hf^?A`AOIXj*a8ff9-?j`#vDuX zHGeVA3kG-njbX9P{36MV)Ev!rn4nr7ip7Hgk+g5sR@0`dR6hu zi@^u_VtP1l0wp-+DlIv;!BNE z=@70@S))&9D_-xSP-T37l`&1J=vIZL*W4@<)L} z_1ZhaAVd3yO230V<2iGr#2cvatTl85C6}$90PP+oBAyYC4-k~|>Vs3|!F9_b4{=S8 zS%sk9Or#`*Obc2c{ejD^ijZuqnkLoXnxr#?A*Q|-GMb6TEK9MAswMr#qB`y5$q$NMR62_h#`Xf3GYXe8E%=s^y#W#hd}^G3$h7 zXHw&sx1-2%n8Y#yqmgIUSA;<~8!e0gzuqBq2RR&PoZ-;BRRy!RcZjctyO%6`n6{-0 z+1@%wCoY#px_JB(&612V(o%zTudj?%wozM70GJ_3(k-Sb-p>*&({fLYS(z6S2=Dh@r7MPckQEdGK<DxvxL?w)Cnb7ZB5ongl4u~L^4cdI< z>#IaQEy?EJqjmCZ0;VYW(uDqRP@R-yvpU+zPcN;$1 z%r+|2gM9~|VXObc)MV1~RX7i!XzVSwW>Z40R`7o)PArYD6T$=? zH`*`tFhHLvhY= z@FPJ52h0iR&R8gMPX+~LT+QSmo>f3|3XA7Pg$mmA0rp1J__z@;fJ4)QOf`j8lrfpEXnQhrQ%;C!GFYLuvDdNR?L|Fc5mfU z?P^>P^A1_;J!K?}LB4(;zReFJi4Wn{m1>+InhzK4R@?S|mJGLv%F?!yCg(V2OFonj z=R@%bH05r2vxwie##!zpgP$a_5osWi-=Rnvp2V{)8Mx`rG>aiiN&nNkJKlKBZ&vIIzFR^6Xt1t_EV_POyz+Ak!Aogw0K8aQ#(o~CJVnLeqj=KVzMMVEh94m-^u>ade4{Gig=Wxs{kR|$i6QgPi1oA$_KVZD%3jktC5a32R!O{ z<{vMANU*h6*QnABaGI8*V(wmMX)*-f&XHQstVNsCjXerPR9wzC)4m zilIdI*H@~|fl2m_<;&Q67K02?Db3c13V3u>+Vp-K77)_3=B2xpi>&@R@0(A^q&SJ0 znZ@fiRyfUF^%4D^fa_tzL!QO_@O#C~T3kDL!Z>&v(ouLehOXNp@36;#P-wGE}KEgbuBZ)JmAk|QJzBqFejGKJ=+l+*11SR zUwp|VEG5XMx0;s;dv)uc?D;yD_GjwG{p~N+%;ndg-XmFlbaVBY7t8ziPwApOU0dyB zjd6y2KNZXF+PAq(!^hv^+=kny={@QJ6|*gpIZTtN`C0k!*~rK%_4QQm!1G_5XSxQs zLnBW@jujzPx3s68hjZVl2LE(0t)}-)UAxD6Ytn%v1IRN6-(c=>R%(=)ESamv;iy@{ zn}-U>dw3kYgQ7aDm*e=d(iDlG+JBi&0l_2g&%k`pcp685d+S$8Z!LizQVh`wS}z; z)l<`~U{YK4L3M-Ip0G&S-Rk8Tas+{^0{B2S`y@xrHfyPV70jMpfAmz1Hdr$MXYwZZ zO1-o3)R`tK&?8`=yRkCmwKMTJ^N_`G z>HW%MhyHryjhu?w(Lv}H-^p78x|+kWN5J$&uojsIF==L6|6Ki_LjF&ervn}_Uk5=J zf|((&&5aCbg+aR~w?=7l-Zxdn*%YJun!P@y-!&#q0QUk@bxDuZlUWrd1nPt%5G(3v zUun_0EHY)Sv3`X4)AxHUOKJ2k6Qtmx-|yik4i(iF(pc!7Tq9u&&m>vbV*`w^QCSBD zsCsXXW*#3Qpei)ZYDA&}-ZPUuKwzApM!7r7cQ+w4MD0?F>;Br(;)$j`zt2B?dE0g5c<;?sl)vd zWVsbzkA05NIh|hAY!R)K z#B?)?T_5~`u~9Cikx%q~75@8KP4>7`K>26=T=cnS2*q#EO7w(2ENbKfl3|il@1={S zA$G}=BgSGjf|@~rB7HpQN9GDTdAh9NQbGai&c%maJ3VN_K|E%3n&a@ON(ConZ@j9+ra5#VUK0|}Dqj3+*b4E}C!|O`gdSjF+y3_3eM0U=!ev zidY5iC4m z9VhZIWt}Qx2`oQ5ifXB$^R8HLiv6pIR-}I?pW(NN?=VF9?dvZz4s;& zuU9zvT#7U~M!iPNKc?bh$EzaaDt(Af%NC!ny3rG_rP9@HAV1GwjLED00{+cZxw3-) zrVycj-0PbhqPk0alR4>APFh(vg_0sf6rAJ;@$h6-3U!h#+Lz2``44*mUq{YAvZjWR zSOgGOQ89y&4lE|>i_X1Uth=`M`8TlfX1r65R<80AW3c7_|+XEcBH{~b#E0>fc)iWYvXmh znIaFX+T)Z7#O6@7Unv`22uMz(${cI-B7mXcao(7upqGkYG2`I(5T^lmyk5tP2Xs0m zHAPixZCf*OlY5dNRU-o|lUz*fWrtr38=?ExyHjbObtR$NObAnVj zi(HwAPH4Y-rCTvv{p5ZIrOg8^QM!x*xet0*ci(}beuLx*{|r>S3w2~<=`iVU}2f4aKmVjwcTka{>1GMS39NzBFml7yx4LUr^?Y-=a^-Vy0vPf)=&K9fl327o+q0^3BT^mY zRw|EFC`BxWSkH-L>#;JWV`V-|S==$Uw%2!xk&cSU(b%IY)k8S7+Hi)kS-j|{R=uJK zE>AUx**79c-4Paj?kEg9c~tZZk~VVpURcf5;>Qh&n4}B&e%Z#XN^?kHKWS^?A(@Pv_&od~w%yXcNIxSMEtDi!k*sfHmDyO;*XOxw3=h8VRR?*Qv?k zAR?a{Zma zQkiUq+9(Yd){mA(Gn~KfU|``+UD5O@GiUWfE!0fe4V9fBxh9M`E5?=F`xj%Wa z>2BGDCe5~Whgl>BANZH{2&eYLCf)$0RBdJ1go1|;#xI4bmA#W-xpGZvC zPv0!Dnwe!>}TEX4wa!`j>H^(Vp zLjWgxepx-BMuL(h08$bey>jj-qx2#5)RM;i%idx=(ftrhO&)rug2vCIy4gK~5~Emn z^oDrOS_WQ-WW&$*vUMYamn-VexNN~5cXim~WMQ zkv(aAg{MX_m9MIr;YD+74+jrV75_J-`0Z4Nj?X)H!tnsE8GHcXMGyW>OFvVE1k-ls1cqAgEI zkV!GrHKQoRUv?y?qJZk7AwsW$WCgu{(fTsmVGgILvkBhCcXUve+0OTk7D^NK33x)`eUyrqaWbI78U-#Vxv4NQtfzva-e4}aE($I(5j3v7$C;nB?BDo$mYF}!A6F;YoR^c2I%*401cc-I*d zW$qwh`qLo9Pgo*F`GzanktH*E3UKGZ;vwwDiR;3zKyK)jN8B5P0~hh5+KVS9TMtJP z@$>N&t{0b<)}$}Ee)V@6-ccyxN>Ew1MY=(XCq*Ku;E!izZ#4yx(lokXH9B0RC$CVtd3$ z=P8gC{AX1HT+5oyMpDVEJRdeTMlUCj^xtykSWDs=ms`>w`CA@$hgj{?xmK&k(enLv z>4nek1F$88tNkyOYrjl^XvP&$46hv^ay*3rtar1oUWDJ(QA;S)%u4gIbBH&d=bGSm z&8@Avnqhaxed`SeAGBLVG65C6#SIxU4X%<->tIIK~o)1F^U)# z=uNT%squ!ad{1)RXRp+49z`~*;-?SXF|ybd{da`86lMxcT>}fsE-_dr9=97X>!1G3@vC^SPk7z556G)*<(^>4_c>No2 zf5&|V6Kt_?Uw}V5-V$Up5r_#%H&;~8F7uM4W|t4WwaUtR$RFh@7Z_^V)F~Q}N<{Zl z+uHfbk+RoH2JdI{1&Qe|+Ov&Suko9cgd|@KUdI4~RrNL9ck)li-M_*rogTSeTJwRl zNyqh0Gay#CnjVD8vwWkCI-NLcCx~o4qp=+buIlj))f?O@|E3e7weO9$ks0{pK!T{0 zYqD8{%%&{9@iA4^m3g$NYyf;OQr5Ut%fT_Lkg_|K(}2K}>m-pPTROpWeI`$%-dS`! zT<^?}ngFU=gHsk@SV~h@I`Pe$!*+tS&gp%9&BgV-e7bxt>>|Iq$DEbXs``QMq|_Sr zKUdV48;Muy*(?F4MAv%af-)lVpcj=oQ+9 zGRKB1+J4dWw|OQ=jIZad=>6SrT;<`Whr*D24GkWZayaS3%J{0`DB+0_Q4g_#F0YEK zb1vnKHuG<^vb)9QG!4?S@lNmm>R#n$6R>7bA!ACY{X1K#9k!Y%qPqo6$h^f{%+|;*7OyGNDqlCDMsd4!xaw_CAqccbyua0*nyc@ z9`x|=W1dit2Q43X()#TWW$f5jN?(g$P0TQ)9qD>rZYv!@tho`mU|n&_+&)PNN-Jtu z;vypwb}0*&{(S6k{h`)s!U-^I>a}#ayg6T){aNXhuvSj9a{+o$X9y}j*x+YAd#a^J zLppMr<}YSaTQGqH2U8~koM zWy}`0#9d<|2~=q$^XNX+XKN2DxqYWyR;(iF!a%yE@(CT#;ub3+oY2=6`ri5DzFT-q zeL0d-^k=$e6uygcBg>eobAF1}=3oCd7$ZV{m&t0i-oX~JJF@f_b0%}n!XS@EVVt&}YVl@MTZkopInmDI^94KRZs!QH5o?qnpvRGXY09jN{Y!ow1 zIMo^5)Z%uf8ezzORh!aT_P)sY+`USEAbEFQ8N8^(H!fzlO5h29)Fg@}9PFObG1F138$#hpCWB-n+qv6v=ZqslJ zNrvuB1=d2A?u_YS91 zBz0BP24@*(BRBIK3qr`T&q@@O+S=MJ77|WHTPwX>-UbFL6bv9Z=J!_c2s`G{XwTWQ z#^TvbbCNa~EZC|NKn=L!NK)bUH1K}bCamwn#whu%MKHjr;qwexk2xXS(jrY5WCWnQ zKgcYV81pXf=A;BIQEMAizH2vA%;Q?tagR~qvxng|jThJ3=E6%jkWhH|SsYS79TPoy z8**4a0Riijjy5@%5Z9|7>*E~Wa-l$KPumezUR+B|3gy`$NEdF$#<%Rse5Dn@p;jzJ zqWX)z#rFdH*g_N?mG(WB0UEu`z0`V<-sT`*Pnpt&neRyN+Yb)MI59D#-n2j;xJWQw z2i5Z3g-H(6D+P5n%JhhQ12Sv-dZ(E35^y`$&0YBFy$qS{T=bQc)JYJ3SHzWv;k1L- z?%Z|fo)&9uw0~S}U4>&8z3TtL2tNF32-33cGsy}FpQ*i$O^wMV=Nyk6rumqSUIjEQT{Ofi3g^V&5RSjG_#kdLGf)!2|3Yk&&5sgG%Pwvjxrv-?4Q? z3gF8GSF26FK$>uE;az+)SG?sbs&Fja^mC?R2c9Y2(Wx)(gAxm}+H_&TK0}nCmfd$n zNglgLG-TrleKZ@fujU@~=?=S^1uT|iEA^oygL8`zYA)-K)HPVUr>oY0v9_fQ(lI_& z<*pNF3Erog{H#SnIpa64lcYeg8EmTn80wJ4Y6;MP>y_V|)K9ubL~ESL3sB?;z=8JD zO_d_3JS;>Z?h~P^`>QO(iHV^C;+WR^G?~=)0V2su^linoaC_KXDHqr)C$3?j%32lo ziO=)FR1x8bX*SlXiP%}o37J;uxEe6KnPldA{gnSmf8)G*r6_Rf06ZEr#iAR#C1I)!07AIs+C$x(+Vr#>b|^LfhmVYc@jYz4H||6F~u_X(CcP` zHv&`siAlUNV>zjYt`4N<6SV?1fvxutIywNpl1t5@I$>uODJ}Kt(Qq4_PJSShrNO9j z1cc*{T#`0L5luCUVNK|tLCw9DGh*0j;%K$lL(70IrRCT`$Y9c9Ver6G%%p9|Q@fuv z2#O~RC}!V!Nl+^)$-D;VvpL=yliu(U-Vz$KPczKeQHNcA%iZhLud0)9-zQyZNSFjh z_o5jkTCn8Y3pULEO=XVM@VKkGbXgTIc zSIM7kfgL5}AwKP)^4hG?{rmNt?zMo)F%Wx80~MH(UXb^tHJLZS%unY)C~35z7n6|k z>(z9qKmjLneAG;xwQ9_Lhl$x%w>c?Zw)m1rltvKRFJr6o@qTf6hn=D8ZKF7MGS;b+ z5#&Zkn2wH$ypdxiF?}HBd8jC|HS4Bsma?*E-Lz-%ygYz@{e{9Z?9EBAB;WMz@S9un z<^gnsc9g|>+ht#tvyr95MRDVZxc{Twd*;D?TY={d2avuuVThU=k-$3r_D1^wTAwMC z7+!stzhyWg^{KXhF&&HNA>O@H5 zba*HST`j&oY6rgmqS!<@V=dLWtR&PrV$fOn!pN&I+m#h{7J5cnQ0J& zl)eC2$c!KdvNs8~Yf#{)KQf!G$TSp4C~X=Q3nSTL@Cvc0)+v=rl#71Wp$P#{}S zfW@=#)&BL;^4F`-v9O76CzvvS_9|LN-pwHx`IgDDbD4G_JaEmtW7;E7r1;9F8l z>l%erHp?7>l_Hq}SwT8|N)8(EB-TlQXtz(vm4CfTOn)Fo^`sld1DxLmyy6AAT7ypa zo>>He1M_*#s<^&2;%g5zOM1j5v-R4tF>XC9rJ~BzvkJ`TdctpAzQZG(^D)+Ix)zW- zrcS))p07m`_R+f(gz}=l;OVPWp37{hyxeIyCR@#s^m)m9$)n$*TjBXVe?QYKTQb;&@2{2VUuber(Wh{T)1omMZU;pZe9zfE#PTnQ zulax1Z9{+b2J~}nW%9+AN^Zdi`2FGb#^QmIYXOg#IcqriR(=^ptIL@Jb06C+at-c8 z>CI+b7E60bc5;hzmM~kPvmK0k613Qju7F9VmnsTJ)4^zw~>p&jU7E=Ay;tRsaJgO=w1z z>=|lnrU{T~{+nl06fQ~-!Yv)GS6;GZKM{JVHKE}aBshiv^q{%x)RWmNn#BGY{WQb^al%}9iG0UjuS0iBWY^2GWaKSH1m&QMDHMeMgh#7^3Gu7%Az}T zI;An{#&;%)7hTeI7FS+PqORE`QCgFymuAk}NNObYVu9<|m0aJvlURsK<&4w|C$AT# zZjjKXiC-}E5U9_)3@QhjwbUK>*<_Ul5tZG_+X0m68xCwxuha>2x{6q2)JCKj-)X#% zEJ|j4!*49~Fq@Y4=Cj!EONKh&f95CcmStLv51;|hAuoVpscQK&j&43;soCGE@^1&q82=HwJjf(BHXe`l=+mjfJyCYP z|1ySSHK2$NrApAz5gCs_>cyn&fsf0IoNo}egLc}j|-+#<-(LpDv^irB`sN{^n-%d?uLlR z$z2}#bF21^xw>CRj>aalGDk6uL#8;4c@agspjY9`86!u+=E9+Nnrzpp0wWEZd73Hc zGJPmTleaun@rH(UFqKR1l67I@r&fC8Q9T=0DC4A2&kTI8w`-8mJmu9wp&t zc<}hsCwSR+i`r@1nlI7urIyv5!0djBiP<&J{RG*O}awmhLhO zknFu|G$yJyiH;%cR&V<&j%pL$k%!_=Eeb%hW1T+T9v?Q%h*G?E0WFtpf}=sXi(|Nn zEk-4OV<9Nq?g1Wt+e6$b5ssp^hC0Lhl`rwBu;PhvSvT8Uu3#xZRQBGaN@O-(gMmYy zp5FuZ4%C#gU-oKCT^`)q^&IqfKrzsw(ZCH8Nb$1(pWk~|V*+-q`wTA#Z?En=z4w|+ zMi!ev_4yI^h=P}iwk=QNNwSLgc|i~eRe+YK=Ux@-z) zOo7c@66gzen4VX!7SJF{vYO|-+IaA)Cn@FB@1?VKNB|k7|71EJRah}MhW9W}$6TD7 zRSXh!t4(fsAa*{$t$d5Ys_CP-{DVK1jDG5Tt?!mh;r3A+#Jz>L{^|IL(PZ3@XU~)o zS;?g-hA}8B0QPPfqe4nKW2**ZzSY(-?s zWQ88oTvlj*MF&7TN!>I6Hbwirx*ROTlzgQITz3-Wm>9hBAi&RQ)yj8hvOWAui^rL`JWHBsntGEk66BB3#dqllQ&9 z+wYy}v>MEUmCKf-znWKv0%xEhcgZ2KWix=4I`_%Fz}(cT=VWEOeUA@@x`@x5D1hVq zcV`&`0+ih5(6$6_7wtE72`-$~tM+6P4H|6z6vqpE(!}%O` z#S$h-eI6bi>CLQ4_xVd4Abk(`2}@xQuFDMUJ+5z!odO$8Sr9;TG_m_zQfh*;f+k;| zj{M+Tyxr$K)wDga$I9Y9e zi83nv7(Lp^U3C?z8wXPF6vFpr-c?JVG>sIxPp9N>xZ6mYmmbH6!lsujYJ8SXVUEuQ zq|z_(>eRf2KA(PhG&mSJTGgE~N4c`ooz9YcFH2JxC<4zRa^b5X!5c{LVTks3vxrEc zbGZ=9EEpGKGyob$VXb+V(QWx5CIqhhamVRj1n>mp+_@t0^|_~$&hmHSY(SlfGaH5? zg7eXe_t{s{FyTR{o?!~&3BEhVm@t;O8T)*mx16!QPl4l83clIM4Y$FkaihAx^$!d| z_d{U;=9xYXw(fqxz8TdCi)$RF)S6k|>p`*{9Lh_id91eekLfPYR^Dyj^EpPfIsIGP z76F;)6)q=lqx~FPf%bq2@Ug9z;id%|_gIE|dN070f|}Zk$u*MRm06U06_Rzf@@gP< z{IPadqOMw9(e0ez*^lw^3hxbOh9d#FT&dnx-8jgQK6|zV$lLLK8@FebK55W$52IVw zwpjX`HOKjBsDS6?ZRy*jF#fdKRpxodic6x8#qCfIywCh16hh3fX5UYQ0z?&gwdbj040-N0!^KbonGp2H{%vccQt} zI3gNaW?W2Cn5zTd>h~lWv!v;@u})w!jc8t>C>->Bv=LWOjb^E>REnc#BCXe-ub4hS z+Ouxdq(ClIboL+r77{q1g{!5|s$nfZIDS<P*3R;;$v5o77$BgaAfTiYqlbbU zNGdtls1-3nN!bXgp`f6EbjRpsgKaQ!qYXqrQWzUZS(K!TfQs>Zc%HxEd2xU47x$~{ z&HcH~^ZcI2v2wRSx3)-Uh2j}pMV`B1$KDv@N|7fRQdut5*iSpL{H4ypzG%m@_nUo8 z&tq~xx}pIwaS*4=&4XPdF~lNCe#VhdQEyQy3qjSHRaC~GlkNssJ%*au4710WOS)c5MIh&gbXb!+5n)F#@`d4dyzjQ!?ZBG8pf8 z)aff#ha7b@y$b%Z_Uul^5j9Cis9^F8pFuFek_mm6|CX%-o-xSXhak6fTf8hlI-%_! znELU;sxvO`ZH!j%MwhDt*&?-Cw91KZ-_+g>|9<@iyE|&HlRmz_JY9@AYD|c-+zjd$ zC+60qNu2^meC5t#P?G*6bJN$|gb=DqX`lbTny)w4|H$R=x%YJFzj903#Ji^Tzy>a* zt1dV`{toJ*|BQRf^7<8;Vg>Xlc})6(WZN<_Cv(0mUCPvuKa< z5$cYgtVYzI@;35jpxl1x`x&c0&Id3eaqZ4Q?JeTQRxulyk2fFpwA*jWC%j&p6ej1; zuxAOlsPLwGclra|8p)R7lOZ7{|RF3~x!G`Neo@d%&1ei(DhDIr5%bD(mA z=DMD5(J=eX2X*~(?uLp=0>aB0EP24p;In}S>!$ZGljm>xYuk?BCeo2m!=;d)tbHVb(uF;%Q;LJXt4RsIZAgy%|G`b-Ljf~ z)l1N8KYT@B0-`87x_>q=d9cv$dmKU1B3>H~l)IDs`AlN{xK0=Ep9Y<+8eApZCjX6I zRWrFV4R>FKZ;O|rT4I;<9@;r^@rk!>oZ+MSxgj@{3=)6A7%#{Ub8$@eD>@pqbXUdN z6wCEsZk8W^0KeqfpDIUs&AeprX6DQNG*!(71sD1=-Sau{hHEev>1m}9$qs+sG2viR zPr`zsn{r~@^#~8(;JG;wal@lr?|q4PwSN;#XL0S^>=z5u^@ly@&}gg z8*Txtig#vQrw&wnZ?@FlJL`6i+#3~T*lUjnzY#T`l~gPzFUr*B_|W@PwzsKw_tGm& zdWp9}S>wch#$AjbuGA`ibs*#TYO!&hMXYVQd=qwp_i3ehp}>2blo&Kvg4f?m|DoD? zR|+{d!E>m6r*2wiO{Y?(64JFYZv0Yd9cU9evXS{v>lnv%Olst-6^&1zR7K&GSw&rJb4mJ{8ucCrv;)IU_#XdS2y zruy zncB<=w|gJgZRd)`e#=xFG&V-8*-@c6I<=^%u&8~WU@RzdEz9|UCz@dt*9op2E z#A{F7xb}5EwZ#2i``gBe>oLbx)la@X|1s?h@n3+$jlfy~=RUTERI9)} z_4}2_QBLNssYyn``kRrYi%1rOoH1%0@=x$U^jCUgxj>!E!Z*+el2EexvM1xM|6zvB zTdq^H17GBvyg~QgAGjQ;UVcyxJcbS6|8cwl9!xARH3~9Q=-p1`qEjhL6TmMN3ebpgOp24cGx8+h{TKfLT z0<;VPta2(Y_nqJE^@jA_Z?$cV2mtopj8dL!$s$rw?8%sR1T4g9VQsOi0VjOurA=8W z`kuEfCKO^x9%{!4__V8HCi9ksuZi3P90{3_Ahk9w;s)*j@9<20(} z&)_v-^%3-Ym zim;y0?AbfGU2T2&%4F5hK~;PiHTYb=s-PuJB0%s`B7x7wD*rVbNjx{XGMhZ&D61NT z9MlXt<+DPIjC^&Z5M^E!yk>+=Cieae*gcp+`JjQfnE$YK81;rCSZ(0qA*!+aYX>AF^MlaVZR-O!l3EJyMH4zNyhHWrKSn@ zs?MTnt!_fn*JRaFS`k~nF-t3Lt&UzI_~trcry80cB+e{LQYXtWTCKm>!TniLU_;Na zQtIo+ED)<-k|i{H_~ zUW7p$EiMat#S%gDTv_A!w?!zp5T%lH7*65B)w_jH)SI~+5vu)gU;go$X;)`x)UIeGAX_aNh2SNZ)J^ih@4HFngGa}lEmV&q1s)`e=9gV0cXk63!=`X?Y}r z*2?BnbaanV^aw8;@<@_J(iPOyDu8n8Uq`7peg1N_%3+!CaFJhB?l}v(sy|#V4t~sG zrqX#CvEKTtqjVH3?gYa9VWz=Xxw67BR+xxB+!3H&EE+>K=@8cW(p1g95RCmE>a!kP zZvUr_1h;ft|0;e~1J)a~m!ba<$GOtbo~x3PnfxwC!BNfkC9~mk|NM{!WB79gS}meP zJj?}QoyWeBpfWbpq~eF#xlX7?<$WKcJ`Zm3L`oEkmw*3dyP8MPn5<=M`_63m{r=~U zot6+i)Fx-Hy0SSg-qp z0SZe96+UwUsyTd*&^_}qyYeKu)pJjPH!t1PQ2{errW}DC@mWEsbnbo`&7MVPKxSj3BS>X0>Yo&jR*IvzL5gAwvA2u z{gA&Rar&w(9z(R$^(>&C%JnmzGzd?RYF?YtnsibV}8dKcoyomE9hLI7OhwlWk^d;?y6b|0-M6(FQXp;gUN9PzSEaPm)N~LB+&+Z zuJ;wyZIxQy^qR)jW~SHVYe7X>aOl^bF0^#PhSIul-y7b7zr5P1*=8}IRaVk(sX?NMvJAo{^M|g7Y5JaEaO)IYxBl+2%{*J<5kbsahkecS4|?{wtRwmz20>n za_a~E2|uHgt246I6{oprEv=^c2^B|Dwm5N0^hte8VQ$*hK^=-n;HK?_POkhPFr0r= z09A~jM;9r+4qmkU(Wy}s{7Au~b}ti;SulE+)tr6wx0jh3C`LV7)|gEr#~3nsx0yRNLvqq_Qom#YoN&RF3K zFIe%G+M#AVjH8N{#?`LJmgu0{Bf;+>_$nWe; zX|AlzF8_RI?*;PIjD3`3R;@~AQT5)hJyQE|-6Jn;Ti5Ii*V9N@R=+P_GiJ(ZEf)&b z8A`?<&w;n9&F{P;eFh~<8cfpiEuDMerHR)`M7tn0uAN3V&|G1=z9KvjQyYsGh-A=ZWc}GX9eAMY&sL}7`|KevXfH)Awba3b^9j|zFT_@C5g~n17>U0ysAZZA`TKe z@$GQFHqZGq13^nhTY-gh?$*cjHtc2y24_*ThnX3dFH~A7D@ulpUt5^FV(sZ9#+jpE zpAf5;1(A*yjjjL2CAN`3H1`SKNG_;6KRM-@`D)5kXum6X;klAbny35`+059|&fFvW zwhLu%$mZIs-6b=;tTp3=ok3<@z(mhBP_i=Qk|*w3#HBx%oxg(SM%;b7K6>N$xZaT$ z(2iGW^G2SV&?Ft8{zlJmB$xu!vJ4K9k~MT*V(DV4y7Ho3 zoi}ndtwPvgm0C-zEd!rqe3~*n{fcKgmAMgqf}A!t0UH)6_YKH;$8g-G&|$X_ThPBz zDAOCCWD?A}C}5pR;J`mSBLRNdhKuXa5z;YfUby)Z$#QBtQhx15K_o1nHYe;%XWX;Y z-s(^l&wDiuQ(p3ma$0YzQX8zb6Nc60Z~L~a6bDXWS>krBTlS#g=Sjzs?=k>HU5*BR z#INjj@G&vOzqEJkF$;91`E$t@KMW2pzZ8p|5pz5AccocQ%`}7yh3YJjlcNCWs~hLe zy!I&@MxQ>4vct<*)S413d zc~Z5~P#K^gy3fLA_4QIo6r#H6Tq>c=2as4_I3^KpeaHHfsSCL9;V+zkF#AK1SckHV z>Rm2ANwjKq5|)bHFkyy00-=+AmiY_OsLuFXIv~F}3hq;5Cg`!oh(s>4PbN+#pnv^8 z4v^5l+v|3zMSDL{;xxVGzY?G#&N#bg4jm1mtZkJkm1@g|?$sE%4Vz2rA`*s{b> z$t})~h9CIk=*KXO%lfVJwcc(Bth^v>wN@S3Ia{q#%*;4WEOBf8eF=cLCXRt(#RpOVygx>=ZYmVea}m-N0W+Y2`EAbT+7Qn=4BgNHmEF z-%zSk`Y3OBOR0oz<|9^9mD2);zsPc|&Wos?6)TEqiSw}lLd1LAF=jVC;x&okx^)(Y zl45ct+D}CB5FaU{9qyc1jyLPr@zSX5%Dk2%LpE}jhG4_AyXQ-2k0>F)n)WwWFh45p zxnvQ=BrRBGDq2$n-?9wjIFcRO-gshTV=nMr5~`A+J+~5^V_uDXu5f%iIn83Y>qL`y zft8K_Kj+R1jQVY3Vi&VN*oq&BEip>Kn~V zBl+e8LFl<K!;CMMesNBdC(xT;%3d_-k}v&tA?;ntw^(IVm?3y7*Ld>BUqBW zG;n4>=ukB16@48UiBnRDPf5kD7b)yn*qN8Bkz=wdbMuO><+l6Wj=;4={b5_6%Vv0! zh|J|FEY?ReZ&}-f|Ivu21SrQkUKL7BaM-rVZ z*&lWB@U@04kE1 z`-AZjgO%9*dHWv4%%U(A{?WR5)S*c-TT{ix>d8p9{7WyQu9^zY!8tx=H&U>{D~?kb zc4#?JLtvK9S)6o~zmwZp4HQaJ;JJ3f^`hJ)$x05WdRMHaJu>W5Az7gSJ*X_{L!27hg3Ulp&!-c=!%_~OJU}W}X)?yXY_rm#e z>sKHd8qJm!EGqs~d6L>K0RAile9yd$G{{a<6_ ztY-7G_ddKQk^bFRzElCo<_~5hSBk^H(>2ei9DQ)hhqQ2)?WYpvVgPVOA0sKt6u=(3d^?jBWMXC}`4_n|^|Z1{rRl+W%c;@;Aze_mx!obgkr*!LHSKzn*wiwlTFR6O_nEHz#A;hm;g z`+F)EL`rEGPWbeH99yZ4xcwE&RasZCR=&f96{)8Ia1W;+z!SFhrI^XzVVy2?m8J%c zzl?Bagq)%2z0G2G4KElaKS!%v9nr7}S-;x3<68@@ry*I;1mHPrC=I|m;rHM(5FF&g<`d41Gu|=a=7@b+zA8Q&L^u8`cc*i4ik+g zP8zbN^)1^!YVC;AQu!j5(@2r>2$#04!z%qeiTu(qf|##5b5c-*$$CO*nqbYau2vAq zh1FGYu0_c_fOEZuRs;l3-t}_@ABARJG*F-;$jx}6dz^dp1+c$9pRRr+O5F@cDrVN* zNx#fQ+oM-C4j%RZ8h%pU`FFJY%|XuoTh z{ZzbjZ{Bua%SCNo%QlqxqaEy3su%Xted~@DLvW`8)5yk!EswZ<>{7g-RE4f+4mL!K zgw{}^*fw5jyQ0&1BMllG5zg3t`ln!FW*ZAZUy&nzyqQYOd=O*y$MI!h-*8UaW7;;r zL7>_2#kSs86nd&(MnF!!fH_6uv{cJR#$~ZY#T4S=H8O`RXTI2ahMs+Ob5w5Yuj*dt zlwL3wWC>tpSYKNxrR^|~V2PCrf$q42`jGW+X)|BmxrG)xdCUYj@}~Zc9rbUmXD5C4 zG$Tll)YRUrvEQ(l;xVS>Hbuxj*)-NGapWl7Au@!IIKYsaDRUg z{mNvF_hwy1kux(ER09+f7POt5o~TC-x=Bn9*%YASkGb>y;Zv4Ls?7d!C(ltFy`iY0 zarn5!{4~VT-U7okmiAE9klPcQb1bt{I=X;3+By6^9%40$=dV0bppTlo{;+rUHqPUH{RgB~`cRN* zp!B0#p}sl1ZRHz-KtA!ad5UfN@6De6s#^Jv!)k}hIeFf0-}OU84xIjF(X_qc`j@}( zTf|X+YvhT$TIx;A=_X>0D6`Xpy-|B*=E}95Nh}>G*505KS;@QHxw)4TVfrO>Ja-{n zNK(6+wF05u0`tnM1Xl*iM2k3qiXJ+?vAD0z3j;#_f$8kd08f?M6%8@8-Be~-UKAe` zZQ$aPKe5_2;tK-D4qm{nQ1eb3Y7EKwE2-_~p@Ejcr|!$gdmT|jsHr+IL-roLF%0irIfx>yZztW`0H227x*p;Y|8Z2l6)|=B ztH)x^sNtL+JXvUmiSJkJ8tu#Pyf`ZM^H0haSSc7gl1;0e*0eQzv(Vc;7|a5|BYD$@;h?i=s}F zb8utQF`~qqP5CEN3W(70#yiX<>pCr04K+RhQ{`WyO?|6m!6@sq@L$8`fTERF^}OmP zOw=NoIXyKdW9+4IDrI1UCr?Z5W1@=DuJYsiZ0#^?zV}fyt7sD9*QMx{VKT>(Pqk0v==HMjCf}lMMtEJyU1J41}q3&XRSJQV!!`^ zj&PmB`FQ}83|IHX=BK6H_PN^XB4Q&qxoVsn7A}KeGW z=^}rP8qwM3#jbhX9SW!4?YlK_WQfpl%ZC?YS7}45L)Vl(SQrM<3j^E;FEcKxfKd4H zeU0jtT0x8%Pl!+vZMT{@_g+n}LI{#{z=^H-`IabHYEMI4%QwgoyulYLQgV(Zg zih1{Z48?Hf!_4|OH&JbLh`;$%$Dx(mqWzg2=a1iS-GKZ0J5T;X_0UxEh8ow4L$7Cl zc&A0W0i&{M@~wBD53`?(oDmn;e6*>9WCGB%f|klw;7)K*p00BCZ-I##+xB<)Ngr>dJ=^UVQNv@v7_E&fyw z=jBaMtJ?N~=bL0%Dv}}8r_<-WOYI)1b@^8PVL2Uo1%EbKlT4YV1i`u;+btefuRf(>GE$yFjfRe6}A471}V0y>Fx9#o&O zf$Aa!QGll)$r1#bHAb4JN{MysP8kBve2Dp$1wviraWNJVgaNKiiE@<@9D^LEqfEEP z!0q5_Xno2TDEJ3z=Xds7HqfO#v<+`G(6c3}8)rh9tJ$U^mKIaZ$aDDQhg9KXv-@PG zM5+_9gGIkiajS@!@wqW_Pq{giBvG$`(0)jMhrG)x^*lt0TGBP6II}Qv5IJSR^2Gs8 zIE5DVvWonJ-$$fam3)i~UThXNMnBb5O}^07Z^Lt6!q1Y{Uxt#`%(HB(6y+nvH>y@b zxrrA3jd61DB+n(PCe*9|PsgxjY2yFIZq(m4}mOtL_g?xB#eGvU$^c zflYb=X*Wb)v7A2D;c;PA@2y(R+o%^xXT$AqLcb+{!GUCK7Zoomj4?gtIwNC5%NH+~ zIb;3>mR%@BsLWr8WRNM{M_1T^c)6I1Za0q`o(a5syw@Wsw2Ca3Ssg60I-{Fyp?w}Y zWu-c9fhA?zs|LVc_ZKubb)O%7>$;Gj%75xabYEc4|Gs)-Pei}?5P19Oxh`?>>U9bJ zQ(R~Me?F97g4q0NUwHnrk@g?QT(?T%*;faLI^*DHOaF27r};cOu=fh;`$IZ?aGt*O zFE!^6@&5kv%*baB1~wT9KG^>_hOE+mPNbiBBz^cZ^ma+DRHW?JK|X)(W!aDIi)9i& z_5bxAp1K73?$whpSov?}uARZRutx_4+rJ5i1kPs$J&FSV7kc>g?`m5;$Jv5YHzfG~ zcrO*pyvjHerW|l8^TN;X>(SY|5=ZCeKjS3jXh3AFuiH;+ss2jFSfBJ69W*LcQ1WBw z(bS}|h+bnG0N}EU+=Ci@7k|UFKs}|+jr2y&7iBdpN85|46e|EXB0E=(05CX+XnuBr zxo9+%ihv+f%sF%_Btp0?cs4L1^;=ch=*+6X77Oh=jTE6@=wA5}Znw9o!s#WKggFPM z19=8J1hU?f1=<4)x~HsEM$wh(m58|~TwpoQCe=5xrH#H#%bd-BrlzNiCB*unV~Th& zK8R>cJM;3%B(sC%v}P^e9WR4aU$1^o$GWNsH>b&WX^7lUxcKx=aQn%L`OXNa=OFe) z9A0B2TRihz-mD){x|&s0w;5J(lo~D$o^id?_$sJls<;{)S7&gjXw|RAU%8WX_PRzU zhor+NwOR1NdNZlzyJEPS$R)o^=gER|6CZ|!uAYVAE}o3J_H04bxwAkCk;A=2y74VV zA41VLbd_PoDcwx}YfMbfjEFb&#^e>g9N3ns^wrOd;T($=-!atu)~O&;V@bN5w&JxH zf6Br0WF1a(p|05B#Hj1b7q|RL5ex*mKd(0^S6f3buiOEvocZm3y&J+aVHtm&bcI)q z1bOwN#|Dq}4*gfEQ~O|oyftQ*$tTiuT7SpyhDv%RH)8r| z6AsSvu`eq~pLH`iVz-62NsE`4Ls%1W)A2+|mmP8W0kLiRsk>G8!%5%z6$+{@z7*}- zcNy4T`NrEf^5k!dQV=nB*{?F2>x0lsPm5Tyl!dO-vB6;%+LnVkig(*#?u44GvVs@m zejoIA{GN_re%~r=zh!UGYPu|5IE%Hhij%&gM-(ZFK%T+>B*`hw3JQ(d9XAA+t}%(Z zW%LTE24T>xYLBAB`9#(A!}-)&N2B*>O#H{xOU5Z@&ApO~TP}J&2?hB2oRR`O$v7wU z?ejrd{<2y6u4JlHn63?ARfKYeq9&~joyQw2CECLgBK#sH0xb#RI{os(h_^Xb89{cm zbZsWYmvQQic|R@&M1tjiyEv6lZYWk zX8<2#V|Kz9(x2IFzL%-Bb%3E>9q$#IiuaF;TfSM5(*$_@P1j@m;eQ;}kXxTMi778v zVvlE;#~BiC6|~>c{Jw1xcWfhe43wx?GTOooWF$D1$*cWy?!n4zVq;}!kdV0fkXY!@;!YBb4V5ZPdBUSXb zO#urc7a~@~b%r|v>N8qb*{isKFXi?iYE%M!XJ4EwxgWd_i8rkhJ{Ik$^!)@}PEP%1 z%eUaQ$1XSJgmW7a#DL5H3W5nfc9@nrhQ1fGeQ)k5vKD?9o5oTTljvZ0F-d63Uc38r z4z}km?q(1#V~P{BAZxLJa26*WQZt zs0e+1WmXrs!{uG2PDVN=h)%zI(yNrgw`QB~VV3$fuI-ZITp@M;sTmEcZ#3D^+e&3C z8y!*7z}{X@)v9g0P^-?l{mMY~S=A|Jo)S~#-k?(UdQe3rBm#D+zER_VkS*hKKLTg=kGhC%b{>&({N2)wv$}8S0_Dp zOrp!hpACB|cTAM?T)Hi?M!;-})`|x2vWvaGOgEZj;oPb5 z9$(X=5|m_Bl~+*THW~stb^e2p!knZH19$`+a9HoYZ7 zGnpQ6%0vycXgvp=S!>T*YNH`%l?PKNTHv7%Cho{DWUQAx_SqU~b%9&A-yO3gAt`80 z-}tKwXf|UeH&w*QO~6@mWFLkgEIirZ?9;0>8d&dF6InQh+)8kNS^ltu1nr65+#RT83_{w)6l zO*01Zq(3CP>+d)f^fOc?crmChSWj#o45PLGO{a)hey%g()X-xZe;w5-c2bF~NaB{> z>-?lKN?dyb+i$m!e-3Z0V=D<&{$*H(rN2e_#>Yy#1$i6!Rbn-k;&M^4AWyyd*M=U0 ziSCvU(g>wqti$3FQ^a;BYUxfdk{`8Z>d(;BLB*MQ4LHG`)c!IR$tIEcTX!B`)A(XN zS`AIaQ3Oye8aGHND3Q$Rs_m`5emMqsd!WC;uuo-ucS92wQJ}o0Mjer%sS4;Uh{p!Aog13KQv=k5WP zD>9#fO1jtio4%`%g-%PoiF2&4=|mq%Xi$k4fm+(XW@A<7H^DUZO4DYwdiPW8`B z(fHqA3xQPBPl088UxBq5{d?Ze&Egw2RW1|D8inUnT<2ZGyJBR)pGI#tYlIHSzQMkL zepEc!HC!Ctt_RM{wHuy|gqmt%^>RksJ%}}=n~$568+M1UMZvkMC5>h{gz>KQ zVT5{U)_rkYI)xAMZtdsh$3mqTdI`si(^&Hw>vcjk09ueuq~YM%rU~y+fAfu?V_1~8 z1wv%UHsN>-?{02PMP|h3bl=dUQ3-r|Ot4MnP3opUNmx88TJlx=H2rnT5z^pwf$dzn zBa*V=|Kgaxu5{g6$nX0WiOWzxcfbUyX5Nh_ePq|8W!@KH0pmf1<;|z zQ=phCEg;8=Rn3#~UmwVcZYqC(1om2}HoXeq(0idUn)Qs+R0MIPm;U_eREbb-YfIW= zY0DO8L5S?@pJ#50T~LYWhZ|i=A>9iZ)8(^nmqCl+rEa9t6<(?YSMz9FT>m=3`w$|? zxK7l3XSXsLj$o(AlwLzNjtN-J-dvQsj8!HF}umbC_^AmaI0ePz@rd%_)Pl> z#h-F!!2f^%Hk`RErS%_2?*ZNFaJ)2dlkt@6T2?Wx@wn>X1~g81H?{50J<(cVRYo|F zvmG6T&|nrmv~ znFY|){i)IZTU3v+v$sj6#9m8M+pvU_-vdQ#G*`!I>iQ50Z5<1+;N``j#;%7}kOf%BFN)*Vs8c&{HP$Q+%s%$) z<}SS5?tgM&N{$=-Z6gR_!{!$ zuQVk_LbUY#i>iVo%GRZe|k z$zCoiAn-mEal*1%j-kSng3f~GH&bg${c~yax@h*;`I=ks;{){z*bXHb{VABL>R7<7 z0goul=P>^2D=~^A$s5>ZE0Nkn=qEHM?1~U4N807L#~$$Swux^;JGZ^D2j8b<36Q#P z<>fN%4w1G+F?qah4Tbxj*T+XOP}^FmfB4Q+O zz$Z8G0@881@+T8Y1ImRbsuWC(VLyufL{cdKEU!(vqvuE#szlx36eQ_c#^A9Kx;+v;+L zED!EvT*HDlwBM*~Zk3gL zR5ffod7T{cDtvl$KrmX>%=e^cxZHlBUwWKJOqtJ1lWZeErc9z-X*H9`Wv9}m?tR>7 zxZ;R#?q80W3`;9@^lT`^36p$k3Lh|evV@x5?+4`V%%UxB5}iliSD$qv7u7n=j0v+e zg}7)~f_1S;#~tGc&-?5~F;sF%62q=M#XzVq=Y2-7saw+|*`jJJd_AaUs|Z%~qei-Vwy2=f&;DjOSZPSCZCp4n@)x9Q-3YBSiI(Qg zw}Dc?qCt0V^6|5W|7CBK*4}g4=aRn0-_2L+T(H$f8A<_K8<#A66E*ZcpCvzJS&`fM zw}JE%D;JutRfqxdmfu5pA_MZ(G^xVA&pw3{*cZ^X@ca;KldjN<+3(z}H9yIk;!F(@ z&UoH@c^x;R(x6oCkD({pPamiS_1Z(6x?d!)5~AvFA8mkj+kBy_{yGlDoN6(I2&*Ib6e1ww)vFhbFkuQtR1b|e;tcG=f9zG-o?_qDbfANg|YQj zX^g%k>2{^cxwhO@R_~HP${V31?t3|?0U=3(Wof2ZrPx@4N4?_j7}(W1;`@KgEcn+H1nH~4 zyVaVc2$k^9vx{qb?^Fn9qCM$*8UwP41G&SpVj!ZI2ii&&%82nfK5gcGlKb1JDOyiS zj=YkhQ5Wyq%RAAcH70T&mN=?iKr+AoZnK#N6G|EUw?8 zrYMbvwGX7!n}lC!`&8!7xbEx_lzT2@$RKp@w+U$N$Tw1T1C}IWr6CzXxht69Tr(}N zt@W02Cf@V6Nx?A24dq0Fe)TK}snlZ2lx-e+J6K(^xKUH)BbO5JvJt(0!w!`tRwjzL zh0l{L6+;^qH0Vp&n&SzTz@D0Nl($28SvkLDE>(KNzVpykX=?Rck#5q_xDUfAppOb`pu)@Oy!>x#ixhyQB9&@)gB8zDS*vs|WTQ39M;?|J;F{sXdF zRkD0T#5YDi5q5u8rVG%XL}amqj5s>EUS&N{o7Ta+TKKYg_H*0B;`zxDnK<&dN}~o` z+;5{A)XD-wKCctSi-*cA*JRyQR|=3XpOmWD!;p+*gO*vDne+Wudo=m`3ax|oZD8Sp zNi{;^2l>B%7^@lgNy3Q=1j(0FO3^RB zl-}hwzW<)sWm6mM_j!`KM|BE4}%HL$HlZicBi8y~7;1K+2<;@nm z{BsOrm(b~9+R&Kk7=>o6kLO9rm~~sbCDF8!DMM4sCP(x8 z0x$0!Z+Ii!evKB*{^XFq@a1#Jy7VE)zdJtKbw*OOcA&zleLckYo)?XievL2jDkcnX z)@bBGse$wAc`ru!^GNcz<*~M<6^$&9t*(wSi{GQKbV-#v=H@tdsp-%oOo8!s@mXrH zU6U}@V5(F2>h9^0uSG|IZsW$TCmM4LHcc*StHY(^w}6MsRD9VA4W2?|4**P4g46?F zWdD5=;1Xy%W20!(fcd6`F~7| zK91w+d*I)8W>s;n5g2t*hO#Y3_G4D~aA+OM-)wPczTj4iPE?R8_{Dz+1Pv12f_{I8 zFCp;fF>*#mrKM`;HMZwX*|f9D;BGM|n4m&S&1BKknC4OdC%0AmL}9>dvB;?YwTJ|& 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
    -

    - Deprecated: emulate the virtual display -

    + + Show deprecated tutorial on how to emulate the virtual display + !!! Warning This tutorial is deprecated. To run headless CARLA, please [__run CARLA in a Docker__](build_docker.md). diff --git a/Docs/adv_rss.md b/Docs/adv_rss.md index 7ea7a0b25d6..07f19d41bcc 100644 --- a/Docs/adv_rss.md +++ b/Docs/adv_rss.md @@ -2,13 +2,13 @@ CARLA integrates the [C++ Library for Responsibility Sensitive Safety](https://github.com/intel/ad-rss-lib) in the client library. This feature allows users to investigate behaviours of RSS without having to implement anything. CARLA will take care of providing the input, and applying the output to the AD systems on the fly. -* [__Overview__](#overview) -* [__Compilation__](#compilation) - * [Dependencies](#dependencies) - * [Build](#build) +* [__Overview__](#overview) +* [__Compilation__](#compilation) + * [Dependencies](#dependencies) + * [Build](#build) * [__Current state__](#current-state) - * [RssSensor](#rsssensor) - * [RssRestrictor](#rssrestrictor) + * [RssSensor](#rsssensor) + * [RssRestrictor](#rssrestrictor) !!! Important This feature is a work in progress. Right now, it is only available for the Linux build. diff --git a/Docs/adv_sumo.md b/Docs/adv_sumo.md index 9f7485cf6d2..6b0c44dfd52 100644 --- a/Docs/adv_sumo.md +++ b/Docs/adv_sumo.md @@ -3,12 +3,12 @@ CARLA has developed a co-simulation feature with SUMO. This allows to distribute the tasks at will, and exploit the capabilities of each simulation in favour of the user. -* [__Requisites__](#requisites) -* [__Run a custom co-simulation__](#run-a-custom-co-simulation) - * [Create CARLA vtypes](#create-carla-vtypes) - * [Create the SUMO net](#create-the-sumo-net) - * [Run the synchronization](#run-the-synchronization) -* [__Spawn NPCs controlled by SUMO__](#spawn-npcs-controlled-by-sumo) +* [__Requisites__](#requisites) +* [__Run a custom co-simulation__](#run-a-custom-co-simulation) + * [Create CARLA vtypes](#create-carla-vtypes) + * [Create the SUMO net](#create-the-sumo-net) + * [Run the synchronization](#run-the-synchronization) +* [__Spawn NPCs controlled by SUMO__](#spawn-npcs-controlled-by-sumo) --- ## Requisites diff --git a/Docs/adv_synchrony_timestep.md b/Docs/adv_synchrony_timestep.md index b9df6b0f020..3ddb424dbfd 100644 --- a/Docs/adv_synchrony_timestep.md +++ b/Docs/adv_synchrony_timestep.md @@ -2,15 +2,15 @@ This section deals with two fundamental concepts in CARLA. Their configuration defines how does time go by in the simulation, and how does the server make the simulation move forward. -* [__Simulation time-step__](#simulation-time-step) - * Variable time-step - * Fixed time-step - * Tips when recording the simulation - * Time-step limitations -* [__Client-server synchrony__](#client-server-synchrony) - * Setting synchronous mode - * Using synchronous mode -* [__Possible configurations__](#possible-configurations) +* [__Simulation time-step__](#simulation-time-step) + * [Variable time-step](#variable-time-step) + * [Fixed time-step](#fixed-time-step) + * [Tips when recording the simulation](#tips-when-recording-the-simulation) + * [Time-step limitations](#time-step-limitations) +* [__Client-server synchrony__](#client-server-synchrony) + * [Setting synchronous mode](#setting-synchronous-mode) + * [Using synchronous mode](#using-synchronous-mode) +* [__Possible configurations__](#possible-configurations) --- ## Simulation time-step diff --git a/Docs/build_docker.md b/Docs/build_docker.md index 66d114ed0a9..90552d2cbec 100644 --- a/Docs/build_docker.md +++ b/Docs/build_docker.md @@ -1,9 +1,9 @@ # Running CARLA in a Docker -* [__Docker installation__](#docker-installation) - * Docker CE - * NVIDIA-Docker2 -* [__Running CARLA container__](#running-carla-container) +* [__Docker installation__](#docker-installation) + * [Docker CE](#docker-ce) + * [NVIDIA-Docker2](#nvidia-docker2) +* [__Running CARLA container__](#running-carla-container) This tutorial is designed for: diff --git a/Docs/build_linux.md b/Docs/build_linux.md index 7d3bd62a199..a0e666e1df5 100644 --- a/Docs/build_linux.md +++ b/Docs/build_linux.md @@ -1,16 +1,16 @@ # Linux build -* [__Linux build command summary__](#linux-build-command-summary) -* [__Requirements__](#requirements) - * [System specifics](#system-specifics) - * [Dependencies](#dependencies) -* [__GitHub__](#github) -* [__Unreal Engine__](#unreal-engine) -* [__CARLA build__](#carla-build) - * [Clone repository](#clone-repository) - * [Get assets](#get-assets) - * [Set the environment variable](#set-the-environment-variable) - * [make CARLA](#make-carla) +* [__Linux build command summary__](#linux-build-command-summary) +* [__Requirements__](#requirements) + * [System specifics](#system-specifics) + * [Dependencies](#dependencies) +* [__GitHub__](#github) +* [__Unreal Engine__](#unreal-engine) +* [__CARLA build__](#carla-build) + * [Clone repository](#clone-repository) + * [Get assets](#get-assets) + * [Set the environment variable](#set-the-environment-variable) + * [make CARLA](#make-carla) The build process can be quite long and tedious. The **[F.A.Q.](build_faq.md)** section contains the most common issues and solutions that appear during the installation. However, the CARLA forum is open for anybody to post unexpected issues, doubts or suggestions. There is a specific section for installation issues on Linux. Feel free to login and become part of the community. diff --git a/Docs/build_update.md b/Docs/build_update.md index 019b604b76c..01b367ae70f 100644 --- a/Docs/build_update.md +++ b/Docs/build_update.md @@ -1,13 +1,13 @@ # Update CARLA -* [__Update commands summary__](#update-commands-summary) -* [__Get the lastest binary release__](#get-latest-binary-release) -* [__Update Linux and Windows build__](#update-linux-and-windows-build) - * Clean the build - * Pull from origin - * Download the assets - * Launch the server -* [__Get development assets__](#get-development-assets) +* [__Update commands summary__](#update-commands-summary) +* [__Get the lastest binary release__](#get-latest-binary-release) +* [__Update Linux and Windows build__](#update-linux-and-windows-build) + * [Clean the build](#clean-the-build) + * [Pull from origin](#pull-from-origin) + * [Download the assets](#download-the-assets) + * [Launch the server](#launch-the-server) +* [__Get development assets__](#get-development-assets) To post unexpected issues, doubts or suggestions, feel free to login in the CARLA forum. diff --git a/Docs/build_windows.md b/Docs/build_windows.md index cae564269ab..331c34582ab 100644 --- a/Docs/build_windows.md +++ b/Docs/build_windows.md @@ -1,17 +1,17 @@ # Windows build -* [__Windows build command summary__](#windows-build-command-summary) -* [__Requirements__](#requirements) - * System specifics -* [__Necessary software__](#necessary-software) - * Minor installations: CMake, git, make, Python3 x64 - * Visual Studio 2017 - * Unreal Engine 4.24 -* [__CARLA build__](#carla-build) - * Clone repository - * Get assets - * Set the environment variable - * make CARLA +* [__Windows build command summary__](#windows-build-command-summary) +* [__Requirements__](#requirements) + * [System specifics](#system-specifics) +* [__Necessary software__](#necessary-software) + * [Minor installations (CMake, git, make, Python3 x64)](#minor-installations) + * [Visual Studio 2017](#visual-studio-2017) + * [Unreal Engine (4.24)](#unreal-engine) +* [__CARLA build__](#carla-build) + * [Clone repository](#clone-repository) + * [Get assets](#get-assets) + * [Set the environment variable](#set-the-environment-variable) + * [make CARLA](#make-carla) The build process can be quite long and tedious. The **[F.A.Q.](build_faq.md)** section contains the most common issues and solutions that appear during the installation. However, the CARLA forum is open for anybody to post unexpected issues, doubts or suggestions. There is a specific section for installation issues on Linux. Feel free to login and become part of the community. @@ -89,7 +89,7 @@ Get the 2017 version from [here](https://developerinsider.co/download-visual-stu !!! Important Other Visual Studio versions may cause conflict. Even if these have been uninstalled, some registers may persist. To completely clean Visual Studio from the computer, go to `Program Files (x86)\Microsoft Visual Studio\Installer\resources\app\layout` and run `.\InstallCleanup.exe -full` -### Unreal Engine 4.24 +### Unreal Engine Go to [Unreal Engine](https://www.unrealengine.com/download) and download the _Epic Games Launcher_. In `Engine versions/Library`, download __Unreal Engine 4.24.x__. Make sure to run it in order to check that everything was properly installed. diff --git a/Docs/cont_code_of_conduct.md b/Docs/cont_code_of_conduct.md index 30b75949077..ca505f82f06 100644 --- a/Docs/cont_code_of_conduct.md +++ b/Docs/cont_code_of_conduct.md @@ -1,5 +1,12 @@ # Contributor Covenant Code of Conduct +* [__Our pledge__](#our-pledge) +* [__Our standards__](#our-standards) +* [__Our responsibilities__](#our-responsibilities) +* [__Scope__](#scope) +* [__Enforcement__](#enforcement) +* [__Attribution__](#attribution) + --- ## Our Pledge diff --git a/Docs/cont_coding_standard.md b/Docs/cont_coding_standard.md index 1c49adaedee..5c6e04d1fb8 100644 --- a/Docs/cont_coding_standard.md +++ b/Docs/cont_coding_standard.md @@ -1,5 +1,9 @@ # Coding standard +* [__General__](#general) +* [__Python__](#python) +* [__C++__](#c++) + --- ## General diff --git a/Docs/cont_contribution_guidelines.md b/Docs/cont_contribution_guidelines.md index d7a19299408..b8f6efe9d04 100644 --- a/Docs/cont_contribution_guidelines.md +++ b/Docs/cont_contribution_guidelines.md @@ -7,6 +7,11 @@ Take a look and don't hesitate! * [__Report bugs__](#report-bugs) * [__Request features__](#request-features) * [__Code contributions__](#code-contributions) + * [Learn about Unreal Engine](#learn-about-unreal-engine) + * [Before getting started](#before-getting-started) + * [Coding standard](#coding-standard) + * [Submission](#submission) + * [Checklist](#checklist) * [__Art contributions__](#art-contributions) * [__Docs contributions__](#docs-contributions) @@ -24,7 +29,7 @@ __2. Read the docs.__ Make sure that the issue is a bug, not a misunderstanding [faqlink]: build_faq.md --- -## Feature requests +## Request features Ideas for new features are also a great way to contribute. Any suggestion that could improve the users' experience can be submitted in the corresponding GitHub section [here][frlink]. @@ -44,7 +49,7 @@ A basic introduction to C++ programming with UE4 can be found at Unreal's [C++ P [ue4tutorials]: https://docs.unrealengine.com/latest/INT/Programming/Tutorials/ [ue4course]: https://www.udemy.com/unrealcourse/ -### What should I know before I get started? +### Before getting started Check out the [CARLA Design](index.md) document to get an idea on the different modules that compose CARLA. Choose the most appropriate one to hold the new feature. Feel free to contact the team in the [Discord server](https://discord.com/invite/8kqACuC) in case any doubt arises during the process. diff --git a/Docs/cont_doc_standard.md b/Docs/cont_doc_standard.md index 69796623e9b..dd70797ceed 100644 --- a/Docs/cont_doc_standard.md +++ b/Docs/cont_doc_standard.md @@ -1,7 +1,10 @@ # Documentation Standard -This document will serve as a guide and example of some rules that need to be -followed in order to contribute to the documentation. +This document will serve as a guide and example of some rules that need to be followed in order to contribute to the documentation. + +* [__Docs structure__](#docs-structure) +* [__Rules__](#rules) +* [__Exceptions__](#exceptions) --- ## Docs structure diff --git a/Docs/core_concepts.md b/Docs/core_concepts.md index f6c6a4891f1..22e0c99e139 100644 --- a/Docs/core_concepts.md +++ b/Docs/core_concepts.md @@ -5,10 +5,10 @@ This page introduces the main features and modules in CARLA. Detailed explanatio In order to learn about the different classes and methods in the API, take a look at the [Python API reference](python_api.md). Besides, the [Code recipes](ref_code_recipes.md) reference contains some common code chunks, specially useful during these first steps. * [__First steps__](#first-steps) - * [1st- World and client](#1st-world-and-client) - * [2nd- Actors and blueprints](#2nd-actors-and-blueprints) - * [3rd- Maps and navigation](#3rd-maps-and-navigation) - * [4th- Sensors and data](#4th-sensors-and-data) + * [1st- World and client](#1st-world-and-client) + * [2nd- Actors and blueprints](#2nd-actors-and-blueprints) + * [3rd- Maps and navigation](#3rd-maps-and-navigation) + * [4th- Sensors and data](#4th-sensors-and-data) * [__Advanced steps__](#advanced-steps) !!! Important diff --git a/Docs/plugins_carlaviz.md b/Docs/plugins_carlaviz.md index 6f7772c38ef..4c2479f6841 100644 --- a/Docs/plugins_carlaviz.md +++ b/Docs/plugins_carlaviz.md @@ -2,12 +2,12 @@ The carlaviz plugin is used to visualize the simulation in a web browser. A windows with some basic representation of the scene is created. Actors are updated on-the-fly, sensor data can be retrieved, and additional text, lines and polylines can be drawn in the scene. -* [__General information__](#general-information) - * [Support](#support) -* [__Get carlaviz__](#get-carlaviz) - * [Prerequisites](#prerequisites) - * [Download the plugin](#download-the-plugin) -* [__Utilities__](#utilities) +* [__General information__](#general-information) + * [Support](#support) +* [__Get carlaviz__](#get-carlaviz) + * [Prerequisites](#prerequisites) + * [Download the plugin](#download-the-plugin) +* [__Utilities__](#utilities) --- ## General information diff --git a/Docs/ref_code_recipes.md b/Docs/ref_code_recipes.md index b38392438b0..03959b4ed3c 100644 --- a/Docs/ref_code_recipes.md +++ b/Docs/ref_code_recipes.md @@ -7,6 +7,17 @@ which is divided into those in which the recipe is centered, and those that need There are more recipes to come! +* [__Actor Spectator Recipe__](#actor-spectator-recipe) +* [__Attach Sensors Recipe__](#attach-sensors-recipe) +* [__Actor Attribute Recipe__](#actor-attribute-recipe) +* [__Converted Image Recipe__](#converted-image-recipe) +* [__Lanes Recipe__](#lanes-recipe) +* [__Debug Bounding Box Recipe__](#debug-bounding-box-recipe) +* [__Debug Vehicle Trail Recipe__](#debug-vehicle-trail-recipe) +* [__Parsing Client Arguments Recipe__](#parsing-client-arguments-recipe) +* [__Traffic Light Recipe__](#traffic-light-recipe) +* [__Walker Batch Recipe__](#walker-batch-recipe) + --- ## Actor Spectator Recipe @@ -222,7 +233,7 @@ path it was following and the speed at each waypoint. ![debug_trail_recipe](img/recipe_debug_trail.jpg) --- -## Parse client creation arguments +## Parsing Client Arguments Recipe This recipe shows in every script provided in `PythonAPI/Examples` and it is used to parse the client creation arguments when running the script. @@ -261,7 +272,7 @@ Used:
    ``` --- -## Traffic lights Recipe +## Traffic Light Recipe This recipe changes from red to green the traffic light that affects the vehicle. This is done by detecting if the vehicle actor is at a traffic light. @@ -286,7 +297,7 @@ if vehicle_actor.is_at_traffic_light(): ![tl_recipe](img/tl_recipe.gif) --- -## Walker batch recipe +## Walker Batch Recipe ```py # 0. Choose a blueprint fo the walkers diff --git a/Docs/ref_recorder_binary_file_format.md b/Docs/ref_recorder_binary_file_format.md index 6c3cf20a091..d1345999b92 100644 --- a/Docs/ref_recorder_binary_file_format.md +++ b/Docs/ref_recorder_binary_file_format.md @@ -2,6 +2,23 @@ The recorder system saves all the info needed to replay the simulation in a binary file, using little endian byte order for the multibyte values. + +* [__1- Strings in binary__](#1-strings-in-binary) +* [__2- Info header__](#2-info-header) +* [__3- Packets__](#3-packets) + * [Packet 0 - Frame Start](#packet-0-frame-start) + * [Packet 1 - Frame End](#packet-1-frame-end) + * [Packet 2 - Event Add](#packet-2-event-add) + * [Packet 3 - Event Del](#packet-3-event-del) + * [Packet 4 - Event Parent](#packet-4-event-parent) + * [Packet 5 - Event Collision](#packet-5-event-collision) + * [Packet 6 - Position](#packet-6-position) + * [Packet 7 - TrafficLight](#packet-7-trafficlight) + * [Packet 8 - Vehicle Animation](#packet-8-vehicle-animation) + * [Packet 9 - Walker Animation](#packet-9-walker-animation) +* [__4- Frame Layout__](#4-frame-layout) +* [__5- File Layout__](#5-file-layout) + In the next image representing the file format, we can get a quick view of all the detailed information. Each part that is visualized in the image will be explained in the following sections: @@ -14,7 +31,7 @@ In summary, the file format has a small header with general info ![global file format](img/RecorderFileFormat3.jpg) --- -## 1. Strings in binary +## 1- Strings in binary Strings are encoded first with the length of it, followed by its characters without null character ending. For example, the string 'Town06' will be saved @@ -23,7 +40,7 @@ as hex values: 06 00 54 6f 77 6e 30 36 ![binary dynamic string](img/RecorderString.jpg) --- -## 2. Info header +## 2- Info header The info header has general information about the recorded file. Basically, it contains the version and a magic string to identify the file as a recorder file. If the header changes then the version @@ -37,7 +54,7 @@ A sample info header is: ![info header sample](img/RecorderHeader.jpg) --- -## 3. Packets +## 3- Packets Each packet starts with a little header of two fields (5 bytes): @@ -64,7 +81,7 @@ The types of packets are: We suggest to use **id** over 100 for user custom packets, because this list will keep growing in the future. -### 3.1 Packet 0: Frame Start +### Packet 0 - Frame Start This packet marks the start of a new frame, and it will be the first one to start each frame. All packets need to be placed between a **Frame Start** and a **Frame End**. @@ -73,7 +90,7 @@ All packets need to be placed between a **Frame Start** and a **Frame End**. So, elapsed + durationThis = elapsed time for next frame -### 3.2 Packet 1: Frame End +### Packet 1 - Frame End This frame has no data and it only marks the end of the current frame. That helps the replayer to know the end of each frame just before the new one starts. @@ -81,7 +98,7 @@ Usually, the next frame should be a Frame Start packet to start a new frame. ![frame end](img/RecorderFrameEnd.jpg) -### 3.3 Packet 2: Event Add +### Packet 2 - Event Add This packet says how many actors we need to create at current frame. @@ -110,7 +127,7 @@ The number of attributes is variable and should look similar to this: * color = 79,33,85 * role_name = autopilot -### 3.4 Packet 3: Event Del +### Packet 3 - Event Del This packet says how many actors need to be destroyed this frame. @@ -128,7 +145,7 @@ the next 16 bytes and will be directly to the start of the next packet. The next 3 says the total records that follows, and each record is the id of the actor to remove. So, we need to remove at this frame the actors 100, 101 and 120. -### 3.5 Packet 4: Event Parent +### Packet 4 - Event Parent This packet says which actor is the child of another (the parent). @@ -136,7 +153,7 @@ This packet says which actor is the child of another (the parent). The first id is the child actor, and the second one will be the parent actor. -### 3.6 Packet 5: Event Collision +### Packet 5 - Event Collision If a collision happens between two actors, it will be registered in this packet. Currently only actors with a collision sensor will report collisions, so currently only hero vehicles have that @@ -148,28 +165,28 @@ The **id** is just a sequence to identify each collision internally. Several collisions between the same pair of actors can happen in the same frame, because physics frame rate is fixed and usually there are several physics substeps in the same rendered frame. -### 3.7 Packet 6: Position +### Packet 6 - Position This packet records the position and orientation of all actors of type **vehicle** and **walker** that exist in the scene. ![position](img/RecorderPosition.jpg) -### 3.8 Packet 7: TrafficLight +### Packet 7 - TrafficLight This packet records the state of all **traffic lights** in the scene. Which means that it stores the state (red, orange or green) and the time it is waiting to change to a new state. ![state](img/RecorderTrafficLight.jpg) -### 3.9 Packet 8: Vehicle animation +### Packet 8 - Vehicle animation This packet records the animation of the vehicles, bikes and cycles. This packet stores the **throttle**, **sterring**, **brake**, **handbrake** and **gear** inputs, and then set them at playback. ![state](img/RecorderVehicle.jpg) -### 3.10 Packet 9: Walker animation +### Packet 9 - Walker animation This packet records the animation of the walker. It just saves the **speed** of the walker that is used in the animation. @@ -177,7 +194,7 @@ that is used in the animation. ![state](img/RecorderWalker.jpg) --- -## 4. Frame Layout +## 4- Frame Layout A frame consists of several packets, where all of them are optional, except the ones that have the **start** and **end** in that frame, that must be there always. @@ -195,7 +212,7 @@ The **animation** packets are also optional, but by default they are recorded. T are animated and also the vehicle wheels follow the direction of the vehicles. --- -## 5. File Layout +## 5- File Layout The layout of the file starts with the **info header** and then follows a collection of packets in groups. The first in each group is the **Frame Start** packet, and the last in the group is diff --git a/Docs/ref_sensors.md b/Docs/ref_sensors.md index 89cfbad6668..fd6b71b3489 100644 --- a/Docs/ref_sensors.md +++ b/Docs/ref_sensors.md @@ -1,18 +1,18 @@ # Sensors reference -* [__Collision detector__](#collision-detector) -* [__Depth camera__](#depth-camera) -* [__GNSS sensor__](#gnss-sensor) -* [__IMU sensor__](#imu-sensor) -* [__Lane invasion detector__](#lane-invasion-detector) -* [__LIDAR sensor__](#lidar-sensor) +* [__Collision detector__](#collision-detector) +* [__Depth camera__](#depth-camera) +* [__GNSS sensor__](#gnss-sensor) +* [__IMU sensor__](#imu-sensor) +* [__Lane invasion detector__](#lane-invasion-detector) +* [__LIDAR sensor__](#lidar-sensor) * [__Obstacle detector__](#obstacle-detector) -* [__Radar sensor__](#radar-sensor) -* [__RGB camera__](#rgb-camera) -* [__RSS sensor__](#rss-sensor) -* [__Semantic LIDAR sensor__](#semantic-lidar-sensor) -* [__Semantic segmentation camera__](#semantic-segmentation-camera) -* [__DVS camera__](#dvs-camera) +* [__Radar sensor__](#radar-sensor) +* [__RGB camera__](#rgb-camera) +* [__RSS sensor__](#rss-sensor) +* [__Semantic LIDAR sensor__](#semantic-lidar-sensor) +* [__Semantic segmentation camera__](#semantic-segmentation-camera) +* [__DVS camera__](#dvs-camera) --- ## Collision detector diff --git a/Docs/tuto_A_create_standalone.md b/Docs/tuto_A_create_standalone.md index c60de808d8b..d4b8aca82d3 100644 --- a/Docs/tuto_A_create_standalone.md +++ b/Docs/tuto_A_create_standalone.md @@ -2,8 +2,8 @@ It is a common practice in CARLA to manage assets with standalone packages. Keeping them aside allows to reduce the size of the build. These asset packages can be easily imported into a CARLA package anytime. They also become really useful to easily distribute assets in an organized way. -* [__Export a package from the UE4 Editor__](#export-a-package-from-the-ue4-editor) -* [__Import assets into a CARLA package__](#import-assets-into-a-carla-package) +* [__Export a package from the UE4 Editor__](#export-a-package-from-the-ue4-editor) +* [__Import assets into a CARLA package__](#import-assets-into-a-carla-package) --- ## Export a package from the UE4 Editor diff --git a/Docs/tuto_A_vehicle_modelling.md b/Docs/tuto_A_vehicle_modelling.md index 6ba949ce809..06d536dcaae 100644 --- a/Docs/tuto_A_vehicle_modelling.md +++ b/Docs/tuto_A_vehicle_modelling.md @@ -1,9 +1,16 @@ # How to model vehicles +* [__4-wheeled Vehicles__](#4-wheeled-vehicles) + * [Modelling](#modelling) + * [Naming materials](#naming-materials) + * [Texturing](#texturing) + * [Rigging](#rigging) + * [LODs](#lods) + --- ## 4-Wheeled Vehicles -#### Modelling +### Modelling Vehicles must have a minimum of 10.000 and a maximum of 17.000 Tris approximately. We model the vehicles using the size and scale of actual cars. @@ -36,7 +43,7 @@ The vehicle must be divided in 6 materials: Put a rectangular plane with this size 29-12 cm, for the licence Plate. We assign the license plate texture. -#### Nomenclature of Material +### Naming materials * M(Material)_"CarName"_Bodywork(part of car) @@ -50,7 +57,7 @@ The vehicle must be divided in 6 materials: * M_"CarName"_LicencePlate -#### Textures +### Texturing The size of the textures is 2048x2048. @@ -71,7 +78,7 @@ TEXTURES MATERIAL * M_Tesla3_BodyWork -#### RIG +### Rigging The easiest way is to copy the "General4WheeledVehicleSkeleton" present in our project, either by exporting it and copying it to your model or by creating your skeleton diff --git a/Docs/tuto_D_create_sensor.md b/Docs/tuto_D_create_sensor.md index e28c395f61f..de49031d884 100644 --- a/Docs/tuto_D_create_sensor.md +++ b/Docs/tuto_D_create_sensor.md @@ -5,6 +5,19 @@ the necessary steps to implement a sensor in Unreal Engine 4 (UE4) and expose its data via CARLA's Python API. We'll follow all the steps by creating a new sensor as an example. +* [__Prerequisites__](#prerequisites) +* [__Introduction__](#introduction) +* [__Creating a new sensor__](#creating-a-new-sensor) + * [1- Sensor actor](#1-sensor-actor) + * [2- Sensor data serializer](#2-sensor-data-serializer) + * [3- Sensor data object](#3-sensor-data-object) + * [4- Register your sensor](#4-register-your-sensor) + * [5- Usage example](#5-usage-example) +* [__Appendix__](#appendix) + * [Reusing buffers](#reusing-buffers) + * [Sending data asynchronously](#sending-data-asynchronously) + * [Client-side sensors](#client-side-sensors) + --- ## Prerequisites @@ -71,8 +84,7 @@ _For the sake of simplicity we're not going to take into account all the edge cases, nor it will be implemented in the most efficient way. This is just an illustrative example._ ---- -### 1. The sensor actor +### 1- Sensor actor This is the most complicated class we're going to create. Here we're running inside Unreal Engine framework, knowledge of UE4 API will be very helpful but @@ -295,8 +307,7 @@ that, the data is going to travel through several layers. First of them will be the serializer that we have to create next. We'll fully understand this part once we have completed the `Serialize` function in the next section. ---- -### 2. The sensor data serializer +### 2- Sensor data serializer This class is actually rather simple, it's only required to have two static methods, `Serialize` and `Deserialize`. We'll add two files for it, this time to @@ -365,8 +376,8 @@ SharedPtr SafeDistanceSerializer::Deserialize(RawData &&data) { except for the fact that we haven't defined yet what's a `SafeDistanceEvent`. ---- -### 3. The sensor data object + +### 3- Sensor data object We need to create a data object for the users of this sensor, representing the data of a _safe distance event_. We'll add this file to @@ -431,8 +442,7 @@ What we're doing here is exposing some C++ methods in Python. Just with this, the Python API will be able to recognise our new event and it'll behave similar to an array in Python, except that cannot be modified. ---- -### 4. Register your sensor +### 4- Register your sensor Now that the pipeline is complete, we're ready to register our new sensor. We do so in _LibCarla/source/carla/sensor/SensorRegistry.h_. Follow the instruction in @@ -454,8 +464,7 @@ be a bit cryptic. make rebuild ``` ---- -### 5. Usage example +### 5- Usage example Finally, we have the sensor included and we have finished recompiling, our sensor by now should be available in Python. @@ -493,7 +502,9 @@ Vehicle too close: vehicle.mercedes-benz.coupe That's it, we have a new sensor working! --- -## Appendix: Reusing buffers +## Appendix + +### Reusing buffers In order to optimize memory usage, we can use the fact that each sensor sends buffers of similar size; in particularly, in the case of cameras, the size of @@ -530,8 +541,7 @@ buffer.reset(512u); // (size 512 bytes, capacity 1024 bytes) buffer.reset(2048u); // (size 2048 bytes, capacity 2048 bytes) -> allocates ``` ---- -## Appendix: Sending data asynchronously +### Sending data asynchronously Some sensors may require to send data asynchronously, either for performance or because the data is generated in a different thread, for instance, camera sensors send @@ -554,8 +564,7 @@ void MySensor::Tick(float DeltaSeconds) } ``` ---- -## Appendix: Client-side sensors +### Client-side sensors Some sensors do not require the simulator to do their measurements, those sensors may run completely in the client-side freeing the simulator from extra diff --git a/Docs/tuto_D_generate_pedestrian_navigation.md b/Docs/tuto_D_generate_pedestrian_navigation.md index 3b3b4591981..603f5edca7c 100644 --- a/Docs/tuto_D_generate_pedestrian_navigation.md +++ b/Docs/tuto_D_generate_pedestrian_navigation.md @@ -1,8 +1,5 @@ # How to generate the pedestrian navigation info ---- -## Introduction - The pedestrians to walk need information about the map in a specific format. That file that describes the map for navigation is a binary file with extension `.BIN`, and they are saved in the **Nav** folder of the map. Each map needs a `.BIN` file with the same name that the map, so automatically can be loaded with the map. This `.BIN` file is generated from the Recast & Detour library and has all the information that allows pathfinding and crow management. @@ -18,13 +15,34 @@ If we need to generate this `.BIN` file for a custom map, we need to follow this We have several types of meshes for navigation. The meshes need to be identified as one of those types, using specific nomenclature. -| Type | Start with | Description | -|-----------|------------|-------------| -| Ground | `Road_Sidewalk` | Pedestrians can walk over these meshes freely (sidewalks...). | -| Grass | `Road_Crosswalk` | Pedestrians can walk over these meshes but as a second option if no ground is found. | -| Road | `Road_Grass` | Pedestrians won't be allowed to walk on it unless we specify some percentage of pedestrians that will be allowed. | -| Crosswalk | `Road_Road`, `Road_Curb`, `Road_Gutter` or `Road_Marking` | Pedestrians can cross the roads only through these meshes. | -| Block | any other name | Pedestrians will avoid these meshes always (are obstacles like traffic lights, trees, houses...). | + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    TypeStart withDescription
    GroundRoad_SidewalkPedestrians can walk over these meshes freely (sidewalks...).
    GrassRoad_CrosswalkPedestrians can walk over these meshes but as a second option if no ground is found.
    RoadRoad_GrassPedestrians won't be allowed to walk on it unless we specify some percentage of pedestrians that will be allowed.
    CrosswalkRoad_Road, Road_Curb, Road_Gutter, Road_MarkingPedestrians can cross the roads only through these meshes.
    BlockAny other namePedestrians will avoid these meshes always (are obstacles like traffic lights, trees, houses...).

    diff --git a/Docs/tuto_G_control_walker_skeletons.md b/Docs/tuto_G_control_walker_skeletons.md index 39bc39a2dce..afa17bcc0d6 100644 --- a/Docs/tuto_G_control_walker_skeletons.md +++ b/Docs/tuto_G_control_walker_skeletons.md @@ -5,6 +5,12 @@ skeletons of walkers from the CARLA Python API. The reference of all classes and methods available can be found at [Python API reference](python_api.md). +* [__Walker skeleton structure__](#walker-skeleton-structure) +* [__Manually control walker bones__](#manually-control-walker-bones) + * [Connect to the simulator](#connect-to-the-simulator) + * [Spawn a walker](#spawn-a-walker) + * [Control walker skeletons](#control-walker-skeletons) + !!! note **This document assumes the user is familiar with the Python API**.
    The user should read the first steps tutorial before reading this document. @@ -86,12 +92,12 @@ crl_root ``` --- -## How to manually control a walker's bones +## Manually control walker bones Following is a detailed step-by-step example of how to change the bone transforms of a walker from the CARLA Python API -#### Connecting to the simulator +### Connect to the simulator Import neccessary libraries used in this example @@ -107,7 +113,7 @@ client = carla.Client('127.0.0.1', 2000) client.set_timeout(2.0) ``` -#### Spawning a walker +### Spawn a walker Spawn a random walker at one of the map's spawn points @@ -119,7 +125,7 @@ spawn_point = random.choice(spawn_points) if spawn_points else carla.Transform() world.try_spawn_actor(blueprint, spawn_point) ``` -#### Controlling a walker's skeleton +### Control walker skeletons A walker's skeleton can be modified by passing an instance of the WalkerBoneControl class to the walker's apply_control function. The WalkerBoneControl class contains the transforms diff --git a/Docs/tuto_G_retrieve_data.md b/Docs/tuto_G_retrieve_data.md index 95581fbefc6..a70262c0228 100644 --- a/Docs/tuto_G_retrieve_data.md +++ b/Docs/tuto_G_retrieve_data.md @@ -4,39 +4,39 @@ Learning an efficient way to retrieve simulation data is essential in CARLA. Thi First, the simulation is initialized with custom settings and traffic. An ego vehicle is set to roam around the city, optionally with some basic sensors. The simulation is recorded, so that later it can be queried to find the highlights. After that, the original simulation is played back, and exploited to the limit. New sensors can be added to retrieve consistent data. The weather conditions can be changed. The recorder can even be used to test specific scenarios with different outputs. -* [__Overview__](#overview) -* [__Set the simulation__](#set-the-simulation) - * [Map setting](#map-setting) - * [Weather setting](#weather-setting) -* [__Set traffic__](#set-traffic) - * [CARLA traffic and pedestrians](#carla-traffic-and-pedestrians) - * [SUMO co-simulation traffic](#sumo-co-simulation-traffic) -* [__Set the ego vehicle__](#set-the-ego-vehicle) - * [Spawn the ego vehicle](#spawn-the-ego-vehicle) - * [Place the spectator](#place-the-spectator) -* [__Set basic sensors__](#set-basic-sensors) - * [RGB camera](#rgb-camera) - * [Detectors](#detectors) - * [Other sensors](#other-sensors) -* [__Set advanced sensors__](#set-advanced-sensors) - * [Depth camera](#depth-camera) - * [Semantic segmentation camera](#semantic-segmentation-camera) - * [LIDAR raycast sensor](#lidar-raycast-sensor) - * [Radar sensor](#radar-sensor) -* [__No-rendering-mode__](#no-rendering-mode) - * [Simulate at a fast pace](#simulate-at-a-fast-pace) - * [Manual control without rendering](#manual-control-without-rendering) -* [__Record and retrieve data__](#record-and-retrieve-data) - * [Start recording](#start-recording) - * [Capture and record](#capture-and-record) - * [Stop recording](#stop-recording) -* [__Exploit the recording__](#exploit-the-recording) - * [Query the events](#query-the-events) - * [Choose a fragment](#choose-a-fragment) - * [Retrieve more data](#retrieve-more-data) - * [Change the weather](#change-the-weather) - * [Try new outcomes](#try-new-outcomes) -* [__Tutorial scripts__](#tutorial-scripts) +* [__Overview__](#overview) +* [__Set the simulation__](#set-the-simulation) + * [Map setting](#map-setting) + * [Weather setting](#weather-setting) +* [__Set traffic__](#set-traffic) + * [CARLA traffic and pedestrians](#carla-traffic-and-pedestrians) + * [SUMO co-simulation traffic](#sumo-co-simulation-traffic) +* [__Set the ego vehicle__](#set-the-ego-vehicle) + * [Spawn the ego vehicle](#spawn-the-ego-vehicle) + * [Place the spectator](#place-the-spectator) +* [__Set basic sensors__](#set-basic-sensors) + * [RGB camera](#rgb-camera) + * [Detectors](#detectors) + * [Other sensors](#other-sensors) +* [__Set advanced sensors__](#set-advanced-sensors) + * [Depth camera](#depth-camera) + * [Semantic segmentation camera](#semantic-segmentation-camera) + * [LIDAR raycast sensor](#lidar-raycast-sensor) + * [Radar sensor](#radar-sensor) +* [__No-rendering-mode__](#no-rendering-mode) + * [Simulate at a fast pace](#simulate-at-a-fast-pace) + * [Manual control without rendering](#manual-control-without-rendering) +* [__Record and retrieve data__](#record-and-retrieve-data) + * [Start recording](#start-recording) + * [Capture and record](#capture-and-record) + * [Stop recording](#stop-recording) +* [__Exploit the recording__](#exploit-the-recording) + * [Query the events](#query-the-events) + * [Choose a fragment](#choose-a-fragment) + * [Retrieve more data](#retrieve-more-data) + * [Change the weather](#change-the-weather) + * [Try new outcomes](#try-new-outcomes) +* [__Tutorial scripts__](#tutorial-scripts) --- ## Overview From 29cb90f8aa17fa083bc4ec8dc95cb4b6a6ff588c Mon Sep 17 00:00:00 2001 From: sergi-e Date: Tue, 1 Sep 2020 10:27:17 +0200 Subject: [PATCH 047/179] First draft --- Docs/ros_installation.md | 31 +++++++++---------- Docs/start_quickstart.md | 66 +++++++++++++++++++--------------------- 2 files changed, 47 insertions(+), 50 deletions(-) diff --git a/Docs/ros_installation.md b/Docs/ros_installation.md index d52e43a3ab7..116004cff34 100644 --- a/Docs/ros_installation.md +++ b/Docs/ros_installation.md @@ -2,8 +2,8 @@ * [__Requirements__](#requirements) * [__Bridge installation__](#bridge-installation) - * a) using apt repository - * b) using source repository + * [A. Using deb repository](#a-using-deb-repository) + * [B. Using source repository](#b-using-source-repository) * [__Run the ROS bridge__](#run-the-ros-bridge) * [__Setting CARLA__](#setting-carla) @@ -22,29 +22,28 @@ The ROS bridge enables two-way communication between ROS and CARLA. The informat --- ## Bridge installation -### a) Using apt repository +### A. Using deb repository -Add the apt repository. - -* __Bridge for ROS Melodic.__ +Set up the deb repository in the system. ```sh -sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 81061A1A042F527D && -sudo add-apt-repository "deb [arch=amd64 trusted=yes] http://dist.carla.org/carla-ros-bridge-melodic/ bionic main" +sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1AF1527DE64CB8D9 +sudo add-apt-repository "deb [arch=amd64] http://dist.carla.org/carla $(lsb_release -sc) main" ``` - -* __Bridge for ROS Kinetic.__ +Install CARLA and check for the installation in the `/opt/` folder. ```sh -sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 9BE2A0CDC0161D6C && -sudo add-apt-repository "deb [arch=amd64 trusted=yes] http://dist.carla.org/carla-ros-bridge-kinetic xenial main" +sudo apt-get update # Update the repository +sudo apt-get install carla-ros-bridge # Install the latest ROS bridge version, or update the current installation ``` -Install the ROS bridge. +This repository contains features from CARLA 0.9.10 and later versions. To install a specific version add the version tag to the installation command. ```sh -sudo apt update && -sudo apt install carla-ros-bridge- +sudo apt-get install carla-ros-bridge==0.9.10-1 # In this case, "0.9.10" refers to the ROS bridge version, and "-1" to a deb tag, which usually will always be the same. ``` -### b) Using source repository +!!! Important + To install ROS bridge versions prior to 0.9.10, change to a previous version of the documentation using the pannel in the bottom right corner of the window, and follow the old instructions. + +### B. Using source repository A catkin workspace is needed to use the ROS bridge. It should be cloned and built in there. The following code creates a new workspace, and clones the repository in there. diff --git a/Docs/start_quickstart.md b/Docs/start_quickstart.md index 1c2d86bf977..feb8daea5d4 100644 --- a/Docs/start_quickstart.md +++ b/Docs/start_quickstart.md @@ -3,11 +3,11 @@ * __[Installation summary](#installation-summary)__ * __[Requirements](#requirements)__ * __[CARLA installation](#carla-installation)__ - * a) deb CARLA installation - * b) GitHub repository installation + * [A. deb CARLA installation](#a-deb-carla-installation) + * [B. Package installation](#b-package-installation) * __[Import additional assets](#import-additional-assets)__ * __[Running CARLA](#running-carla)__ - * Command-line options + * [Command-line options](#command-line-options) * __[Updating CARLA](#updating-carla)__ * __[Follow-up](#follow-up)__ @@ -23,39 +23,29 @@ # Install required modules Pygame and Numpy. pip install --user pygame numpy -# Option A) deb package installation of CARLA 0.9.9 (only Linux) -sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 92635A407F7A020C -sudo add-apt-repository "deb [arch=amd64 trusted=yes] http://dist.carla.org/carla-0.9.9/ all main" -sudo apt-get update -sudo apt-get install carla-simulator -cd /opt/carla-simulator/bin -./CarlaUE4.sh -# To install CARLA 0.9.8 instead -sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 304F9BC29914A77D && -sudo add-apt-repository "deb [arch=amd64 trusted=yes] http://dist.carla.org/carla-0.9.8/ all main" -sudo apt-get update -sudo apt-get install carla-simulator -cd /opt/carla-simulator/bin -./CarlaUE4.sh -# To install CARLA 0.9.7 instead -sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys DB53A429E64554FC && -sudo add-apt-repository "deb [arch=amd64 trusted=yes] http://dist.carla.org/carla-0.9.7/ all main" +# There are two different ways to install CARLA. + +# Option A) deb package installation +# This repository contains CARLA 0.9.10 and later. To install previous CARLA versions, change to a previous version of the docs using the pannel in the bottom right part of the window. +sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1AF1527DE64CB8D9 +sudo add-apt-repository "deb [arch=amd64] http://dist.carla.org/carla $(lsb_release -sc) main" sudo apt-get update -sudo apt-get install carla-simulator +sudo apt-get install carla-simulator # Install the latest CARLA version or update the current installation. +sudo apt-get install carla-simulator==0.9.10-1 # install a specific CARLA version. cd /opt/carla-simulator/bin ./CarlaUE4.sh -# Option B) GitHub repository installation +# Option B) Package installation # Go to: https://github.com/carla-simulator/carla/blob/master/Docs/download.md # Download the desired package and additional assets. # Extract the package. -# Extract the additional assets in `/Import` -# Run CARLA (Linux) +# Extract the additional assets in `/Import`. +# Run CARLA (Linux). ./CarlaUE.sh -# Run CARLA (Windows) +# Run CARLA (Windows). > CarlaUE4.exe -# Run a script to test CARLA +# Run a script to test CARLA. cd PythonAPI/examples python3 spawn_npc.py @@ -83,21 +73,29 @@ To install both modules using [pip](https://pip.pypa.io/en/stable/installing/), The __deb installation__ is the easiest way to get the latest release in Linux. __Download the GitHub repository__ to get either a specific release or the Windows version of CARLA. -### a) deb CARLA installation +### A. deb CARLA installation -Add the CARLA 0.9.9 repository to the system. +Set up the deb repository in the system. ```sh -sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 92635A407F7A020C -sudo add-apt-repository "deb [arch=amd64 trusted=yes] http://dist.carla.org/carla-0.9.9/ all main" +sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1AF1527DE64CB8D9 +sudo add-apt-repository "deb [arch=amd64] http://dist.carla.org/carla $(lsb_release -sc) main" ``` Install CARLA and check for the installation in the `/opt/` folder. ```sh -sudo apt-get update -sudo apt-get install carla-simulator -cd /opt/carla-simulator +sudo apt-get update # Update the repository +sudo apt-get install carla-simulator # Install the latest CARLA version, or update the current installation +cd /opt/carla-simulator # Open the folder where CARLA is installed +``` + +This repository contains CARLA 0.9.10 and later versions. To install a specific version add the version tag to the installation command. +```sh +sudo apt-get install carla-simulator==0.9.10-1 # In this case, "0.9.10" refers to a CARLA version, and "-1" to a deb tag, which usually will always be the same. ``` -### b) Package installation +!!! Important + To install CARLA versions prior to 0.9.10, change to a previous version of the documentation using the pannel in the bottom right corner of the window, and follow the old instructions. + +### B. Package installation

    From 4c4ac269bb3b251c78515d596dc9370f379a4fcd Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 2 Sep 2020 11:14:55 +0200 Subject: [PATCH 048/179] First iteration on J comments --- Docs/ros_installation.md | 14 +++++++------- Docs/start_quickstart.md | 18 +++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Docs/ros_installation.md b/Docs/ros_installation.md index 116004cff34..52cce950448 100644 --- a/Docs/ros_installation.md +++ b/Docs/ros_installation.md @@ -2,7 +2,7 @@ * [__Requirements__](#requirements) * [__Bridge installation__](#bridge-installation) - * [A. Using deb repository](#a-using-deb-repository) + * [A. Using Debian repository](#a-using-debian-repository) * [B. Using source repository](#b-using-source-repository) * [__Run the ROS bridge__](#run-the-ros-bridge) * [__Setting CARLA__](#setting-carla) @@ -13,7 +13,7 @@ The ROS bridge enables two-way communication between ROS and CARLA. The informat ## Requirements ### ROS Kinetic/Melodic -* __ROS Kinetic/Melodic.__ Install ROS [Melodic](http://wiki.ros.org/melodic/Installation/Ubuntu), for Ubuntu 18.04, or [Kinetic](http://wiki.ros.org/kinetic/Installation), for Ubuntu 16.04. ROS packages may be required, depending on the user needs. [rviz](http://wiki.ros.org/rviz) to visualize ROS data. +* __ROS Kinetic/Melodic.__ Install ROS [Melodic](http://wiki.ros.org/melodic/Installation/Ubuntu), for Ubuntu 18.04, or [Kinetic](http://wiki.ros.org/kinetic/Installation), for Ubuntu 16.04. ROS packages may be required, depending on the user needs. [rviz](http://wiki.ros.org/rviz) to visualize ROS data.j * __CARLA 0.9.7 or later.__ Previous versions are not compatible with the ROS bridge. Follow the [quick start installation](start_quickstart.md) or make the build for the corresponding platform. !!! Important @@ -22,22 +22,22 @@ The ROS bridge enables two-way communication between ROS and CARLA. The informat --- ## Bridge installation -### A. Using deb repository +### A. Using Debian repository -Set up the deb repository in the system. +Set up the Debian repository in the system. ```sh sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1AF1527DE64CB8D9 sudo add-apt-repository "deb [arch=amd64] http://dist.carla.org/carla $(lsb_release -sc) main" ``` -Install CARLA and check for the installation in the `/opt/` folder. +Install the ROS bridge, and check for the installation in the `/opt/` folder. ```sh -sudo apt-get update # Update the repository +sudo apt-get update # Update the Debian package index sudo apt-get install carla-ros-bridge # Install the latest ROS bridge version, or update the current installation ``` This repository contains features from CARLA 0.9.10 and later versions. To install a specific version add the version tag to the installation command. ```sh -sudo apt-get install carla-ros-bridge==0.9.10-1 # In this case, "0.9.10" refers to the ROS bridge version, and "-1" to a deb tag, which usually will always be the same. +sudo apt-get install carla-ros-bridge=0.9.10-1 # In this case, "0.9.10" refers to the ROS bridge version, and "1" to the Debian revision. ``` !!! Important diff --git a/Docs/start_quickstart.md b/Docs/start_quickstart.md index feb8daea5d4..67f39fb98bd 100644 --- a/Docs/start_quickstart.md +++ b/Docs/start_quickstart.md @@ -3,7 +3,7 @@ * __[Installation summary](#installation-summary)__ * __[Requirements](#requirements)__ * __[CARLA installation](#carla-installation)__ - * [A. deb CARLA installation](#a-deb-carla-installation) + * [A. Debian CARLA installation](#a-debian-carla-installation) * [B. Package installation](#b-package-installation) * __[Import additional assets](#import-additional-assets)__ * __[Running CARLA](#running-carla)__ @@ -25,13 +25,13 @@ # There are two different ways to install CARLA. -# Option A) deb package installation +# Option A) Debian package installation # This repository contains CARLA 0.9.10 and later. To install previous CARLA versions, change to a previous version of the docs using the pannel in the bottom right part of the window. sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1AF1527DE64CB8D9 sudo add-apt-repository "deb [arch=amd64] http://dist.carla.org/carla $(lsb_release -sc) main" sudo apt-get update sudo apt-get install carla-simulator # Install the latest CARLA version or update the current installation. -sudo apt-get install carla-simulator==0.9.10-1 # install a specific CARLA version. +sudo apt-get install carla-simulator=0.9.10-1 # install a specific CARLA version. cd /opt/carla-simulator/bin ./CarlaUE4.sh @@ -70,26 +70,26 @@ To install both modules using [pip](https://pip.pypa.io/en/stable/installing/), --- ## CARLA installation -The __deb installation__ is the easiest way to get the latest release in Linux. +The __Debian installation__ is the easiest way to get the latest release in Linux. __Download the GitHub repository__ to get either a specific release or the Windows version of CARLA. -### A. deb CARLA installation +### A. Debian CARLA installation -Set up the deb repository in the system. +Set up the Debian repository in the system. ```sh sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1AF1527DE64CB8D9 sudo add-apt-repository "deb [arch=amd64] http://dist.carla.org/carla $(lsb_release -sc) main" ``` Install CARLA and check for the installation in the `/opt/` folder. ```sh -sudo apt-get update # Update the repository +sudo apt-get update # Update the Debian package index sudo apt-get install carla-simulator # Install the latest CARLA version, or update the current installation cd /opt/carla-simulator # Open the folder where CARLA is installed ``` This repository contains CARLA 0.9.10 and later versions. To install a specific version add the version tag to the installation command. ```sh -sudo apt-get install carla-simulator==0.9.10-1 # In this case, "0.9.10" refers to a CARLA version, and "-1" to a deb tag, which usually will always be the same. +sudo apt-get install carla-simulator=0.9.10-1 # In this case, "0.9.10" refers to a CARLA version, and "1" to the Debian revision. ``` !!! Important @@ -137,7 +137,7 @@ Open a terminal in the main CARLA folder. Run the following command to execute t > CarlaUE4.exe ``` !!! Important - In the __deb installation__, `CarlaUE4.sh` will be in `/opt/carla/bin/`, instead of the main `carla/` folder where it normally is. + In the __Debian installation__, `CarlaUE4.sh` will be in `/opt/carla-simulator`, instead of the main `carla/` folder where it normally is. A window containing a view over the city will pop up. This is the _spectator view_. To fly around the city use the mouse and `WASD` keys (while clicking). The server simulator is now running and waiting for a client to connect and interact with the world. Now it is time to start running scripts. The following example will spawn some life into the city: From b8128a9f044a7ec3e1e8c66ff7bacc3509a82308 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Mon, 7 Sep 2020 12:58:34 +0200 Subject: [PATCH 049/179] new iteration on J comments --- Docs/ros_installation.md | 2 +- Docs/start_quickstart.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Docs/ros_installation.md b/Docs/ros_installation.md index 52cce950448..6102ac91e2b 100644 --- a/Docs/ros_installation.md +++ b/Docs/ros_installation.md @@ -73,7 +73,7 @@ catkin_make __1) Run CARLA.__ The way to do so depends on the CARLA installation. * __Quick start/release package.__ `./CarlaUE4.sh` in `carla/`. -* __apt installation.__ `./CarlaUE4.sh` in `opt/carla/bin/`. +* __Debian installation.__ `./CarlaUE4.sh` in `opt/carla-simulator/`. * __Build installation.__ `make launch` in `carla/`. __2) Add the source path.__ The source path for the workspace has to be added, so that the ROS bridge can be used from a terminal. diff --git a/Docs/start_quickstart.md b/Docs/start_quickstart.md index 67f39fb98bd..11a939b51ce 100644 --- a/Docs/start_quickstart.md +++ b/Docs/start_quickstart.md @@ -32,7 +32,7 @@ sudo add-apt-repository "deb [arch=amd64] http://dist.carla.org/carla $(lsb_rele sudo apt-get update sudo apt-get install carla-simulator # Install the latest CARLA version or update the current installation. sudo apt-get install carla-simulator=0.9.10-1 # install a specific CARLA version. -cd /opt/carla-simulator/bin +cd /opt/carla-simulator ./CarlaUE4.sh # Option B) Package installation From 8c3f281b5199546c6a24ae24317c4585960c6128 Mon Sep 17 00:00:00 2001 From: bernat Date: Wed, 9 Sep 2020 23:27:54 +0200 Subject: [PATCH 050/179] Running Carla when choosing a) deb Carla install This fixes a minor error in the documentation regarding running carla, if the deb installation was choosen. --- Docs/start_quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/start_quickstart.md b/Docs/start_quickstart.md index 11a939b51ce..d121e1f4d73 100644 --- a/Docs/start_quickstart.md +++ b/Docs/start_quickstart.md @@ -137,7 +137,7 @@ Open a terminal in the main CARLA folder. Run the following command to execute t > CarlaUE4.exe ``` !!! Important - In the __Debian installation__, `CarlaUE4.sh` will be in `/opt/carla-simulator`, instead of the main `carla/` folder where it normally is. + In the __deb installation__, `CarlaUE4.sh` will be in `/opt/carla-simulator/bin/`, instead of the main `carla/` folder where it normally is. A window containing a view over the city will pop up. This is the _spectator view_. To fly around the city use the mouse and `WASD` keys (while clicking). The server simulator is now running and waiting for a client to connect and interact with the world. Now it is time to start running scripts. The following example will spawn some life into the city: From 2ca15c3bc53d26ac8c001c7891550793468a198e Mon Sep 17 00:00:00 2001 From: doterop Date: Mon, 7 Sep 2020 10:56:50 +0200 Subject: [PATCH 051/179] Added new function to calculate BBs on SKM and SM --- .../Carla/Util/BoundingBoxCalculator.cpp | 63 +++++++++++++++++++ .../Source/Carla/Util/BoundingBoxCalculator.h | 7 +++ 2 files changed, 70 insertions(+) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp index d0a296fba8c..43ab4a85f85 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp @@ -13,6 +13,8 @@ #include "Components/CapsuleComponent.h" #include "GameFramework/Character.h" +#include "Rendering/SkeletalMeshRenderData.h" + FBoundingBox UBoundingBoxCalculator::GetActorBoundingBox(const AActor *Actor) { if (Actor != nullptr) @@ -60,3 +62,64 @@ FBoundingBox UBoundingBoxCalculator::GetActorBoundingBox(const AActor *Actor) } return {}; } + +// TODO: update to calculate current animation pose +FBoundingBox UBoundingBoxCalculator::GetSkeletalMeshBoundingBox(USkeletalMesh* SkeletalMesh) +{ + if(!SkeletalMesh) + { + UE_LOG(LogCarla, Error, TEXT("GetSkeletalMeshBoundingBox no SkeletalMesh")); + return {}; + } + + // Get Vertex postion information from LOD 0 of the Skeletal Mesh + FPositionVertexBuffer& FPositionVertexBuffer = SkeletalMesh->GetResourceForRendering()->LODRenderData[0].StaticVertexBuffers.PositionVertexBuffer; + uint32 NumVertices = FPositionVertexBuffer.GetNumVertices(); + + // Look for Skeletal Mesh bounds (vertex perfect) + FVector MaxVertex(TNumericLimits::Min()); + FVector MinVertex(TNumericLimits::Max()); + for(uint32 i = 0; i < NumVertices; i++) + { + FVector& Pos = FPositionVertexBuffer.VertexPosition(i); + MaxVertex.X = (Pos.X > MaxVertex.X) ? Pos.X : MaxVertex.X; + MaxVertex.Y = (Pos.Y > MaxVertex.Y) ? Pos.Y : MaxVertex.Y; + MaxVertex.Z = (Pos.Z > MaxVertex.Z) ? Pos.Z : MaxVertex.Z; + MinVertex.X = (Pos.X < MinVertex.X) ? Pos.X : MinVertex.X; + MinVertex.Y = (Pos.Y < MinVertex.Y) ? Pos.Y : MinVertex.Y; + MinVertex.Z = (Pos.Z < MinVertex.Z) ? Pos.Z : MinVertex.Z; + } + + // Calculate middle point + FVector Origin ( + (MaxVertex.X + MinVertex.X) * 0.5f, + (MaxVertex.Y + MinVertex.Y) * 0.5f, + (MaxVertex.Z + MinVertex.Z) * 0.5f + ); + + // Calculate box extent + FVector Extent ( + (MaxVertex.X - MinVertex.X) * 0.5f, + (MaxVertex.Y - MinVertex.Y) * 0.5f, + (MaxVertex.Z - MinVertex.Z) * 0.5f + ); + + return {Origin, Extent}; +} + +FBoundingBox UBoundingBoxCalculator::GetStaticMeshBoundingBox(UStaticMesh* StaticMesh) +{ + if(!StaticMesh) + { + UE_LOG(LogCarla, Error, TEXT("GetStaticMeshBoundingBox no StaticMesh")); + return {}; + } + + FBox Box = StaticMesh->GetBoundingBox(); + + UE_LOG(LogCarla, Warning, TEXT("Origin %s"), *Box.GetCenter().ToString()); + UE_LOG(LogCarla, Warning, TEXT("Extent %s"), *Box.GetExtent().ToString()); + + return {Box.GetCenter(), Box.GetExtent()}; + +} \ No newline at end of file diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h index c1546bd09bf..80f7c9ed7d2 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h @@ -29,4 +29,11 @@ class CARLA_API UBoundingBoxCalculator : public UBlueprintFunctionLibrary /// @warning Traffic signs return its trigger box instead. UFUNCTION(Category = "Carla Actor", BlueprintCallable) static FBoundingBox GetActorBoundingBox(const AActor *Actor); + + UFUNCTION(Category = "Carla Actor", BlueprintCallable, CallInEditor) + static FBoundingBox GetSkeletalMeshBoundingBox(USkeletalMesh* SkeletalMesh); + + UFUNCTION(Category = "Carla Actor", BlueprintCallable, CallInEditor) + static FBoundingBox GetStaticMeshBoundingBox(UStaticMesh* StaticMesh); + }; From be1299f5c542b260e8b275dbe9b58099532e5a04 Mon Sep 17 00:00:00 2001 From: doterop Date: Mon, 7 Sep 2020 17:27:36 +0200 Subject: [PATCH 052/179] Added BB calculation for an array of actors --- .../Carla/Source/Carla/Util/BoundingBox.h | 4 ++ .../Carla/Util/BoundingBoxCalculator.cpp | 68 +++++++++++++++++-- .../Source/Carla/Util/BoundingBoxCalculator.h | 11 +-- 3 files changed, 74 insertions(+), 9 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBox.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBox.h index 60eb2221b04..5fa68707144 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBox.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBox.h @@ -20,4 +20,8 @@ struct CARLA_API FBoundingBox /// Radii extent of the bounding box. UPROPERTY(EditAnywhere, BlueprintReadWrite) FVector Extent = {0.0f, 0.0f, 0.0f}; + + /// Rotation of the bounding box. + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FRotator Rotation = {0.0f, 0.0f, 0.0f}; }; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp index 43ab4a85f85..5e0eff280f6 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp @@ -64,7 +64,7 @@ FBoundingBox UBoundingBoxCalculator::GetActorBoundingBox(const AActor *Actor) } // TODO: update to calculate current animation pose -FBoundingBox UBoundingBoxCalculator::GetSkeletalMeshBoundingBox(USkeletalMesh* SkeletalMesh) +FBoundingBox UBoundingBoxCalculator::GetSkeletalMeshBoundingBox(const USkeletalMesh* SkeletalMesh) { if(!SkeletalMesh) { @@ -107,7 +107,7 @@ FBoundingBox UBoundingBoxCalculator::GetSkeletalMeshBoundingBox(USkeletalMesh* S return {Origin, Extent}; } -FBoundingBox UBoundingBoxCalculator::GetStaticMeshBoundingBox(UStaticMesh* StaticMesh) +FBoundingBox UBoundingBoxCalculator::GetStaticMeshBoundingBox(const UStaticMesh* StaticMesh) { if(!StaticMesh) { @@ -117,9 +117,67 @@ FBoundingBox UBoundingBoxCalculator::GetStaticMeshBoundingBox(UStaticMesh* Stati FBox Box = StaticMesh->GetBoundingBox(); - UE_LOG(LogCarla, Warning, TEXT("Origin %s"), *Box.GetCenter().ToString()); - UE_LOG(LogCarla, Warning, TEXT("Extent %s"), *Box.GetExtent().ToString()); - return {Box.GetCenter(), Box.GetExtent()}; +} + +// TODO: can we convert it to list? makes sense? +// TODO: Dynamic vehicle, avoid SM of collision +// TODO: Folliage actors +TArray UBoundingBoxCalculator::GetBoundingBoxOfActors(TArray Actors) +{ + TArray Result; + + //TArray FoundActors; + //// Get all actors of the level + //UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass(), FoundActors); + + for(AActor* Actor : Actors) + { + + TArray MeshComps; + Actor->GetComponents(MeshComps); + + UE_LOG(LogCarla, Warning, TEXT("%s %d"), *Actor->GetName(), MeshComps.Num()); + if(MeshComps.Num() > 0) + { + UE_LOG(LogCarla, Warning, TEXT(" %s"), *MeshComps[0]->GetClass()->GetName()); + } + + FVector WorldLocation = Actor->GetActorLocation(); + FVector WorldScale = Actor->GetActorScale(); + FRotator WorldRotation = Actor->GetActorRotation(); + + // Find if there is some geometry component + TArray StaticMeshComps; + TArray SkeletalMeshComps; + Actor->GetComponents(StaticMeshComps); + Actor->GetComponents(SkeletalMeshComps); + + // Calculate FBoundingBox of SM + for(UStaticMeshComponent* StaticMeshComp : StaticMeshComps) + { + UStaticMesh* StaticMesh = StaticMeshComp->GetStaticMesh(); + FBoundingBox BoundingBox = GetStaticMeshBoundingBox(StaticMesh); + BoundingBox.Origin *= WorldScale; + BoundingBox.Origin = WorldRotation.RotateVector(BoundingBox.Origin) + WorldLocation; + BoundingBox.Extent *= WorldScale; + BoundingBox.Rotation = WorldRotation; + Result.Add(BoundingBox); + } + + // Calculate FBoundingBox of SK_M + for(USkeletalMeshComponent* SkeletalMeshComp : SkeletalMeshComps) + { + USkeletalMesh* SkeletalMesh = SkeletalMeshComp->SkeletalMesh; + FBoundingBox BoundingBox = GetSkeletalMeshBoundingBox(SkeletalMesh); + BoundingBox.Origin *= WorldScale; + BoundingBox.Origin = WorldRotation.RotateVector(BoundingBox.Origin) + WorldLocation; + BoundingBox.Extent *= WorldScale; + BoundingBox.Rotation = WorldRotation; + Result.Add(BoundingBox); + } + } + + return Result; } \ No newline at end of file diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h index 80f7c9ed7d2..d96a9ad9d8e 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h @@ -30,10 +30,13 @@ class CARLA_API UBoundingBoxCalculator : public UBlueprintFunctionLibrary UFUNCTION(Category = "Carla Actor", BlueprintCallable) static FBoundingBox GetActorBoundingBox(const AActor *Actor); - UFUNCTION(Category = "Carla Actor", BlueprintCallable, CallInEditor) - static FBoundingBox GetSkeletalMeshBoundingBox(USkeletalMesh* SkeletalMesh); + UFUNCTION(Category = "Carla Util", BlueprintCallable, CallInEditor) + static FBoundingBox GetSkeletalMeshBoundingBox(const USkeletalMesh* SkeletalMesh); - UFUNCTION(Category = "Carla Actor", BlueprintCallable, CallInEditor) - static FBoundingBox GetStaticMeshBoundingBox(UStaticMesh* StaticMesh); + UFUNCTION(Category = "Carla Util", BlueprintCallable, CallInEditor) + static FBoundingBox GetStaticMeshBoundingBox(const UStaticMesh* StaticMesh); + + UFUNCTION(Category = "Carla Util", BlueprintCallable, CallInEditor) + static TArray GetBoundingBoxOfActors(TArray Actors); }; From 3b6a6bbb24b8610692240f061c37f482cd3b0967 Mon Sep 17 00:00:00 2001 From: doterop Date: Tue, 8 Sep 2020 17:36:49 +0200 Subject: [PATCH 053/179] Added BB folliage calculation --- .../Carla/Util/BoundingBoxCalculator.cpp | 124 ++++++++++++------ .../Source/Carla/Util/BoundingBoxCalculator.h | 2 +- 2 files changed, 83 insertions(+), 43 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp index 5e0eff280f6..e29a63f5819 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp @@ -121,61 +121,101 @@ FBoundingBox UBoundingBoxCalculator::GetStaticMeshBoundingBox(const UStaticMesh* } -// TODO: can we convert it to list? makes sense? // TODO: Dynamic vehicle, avoid SM of collision -// TODO: Folliage actors -TArray UBoundingBoxCalculator::GetBoundingBoxOfActors(TArray Actors) +TArray UBoundingBoxCalculator::GetBoundingBoxOfActors(const TArray& Actors) { TArray Result; - //TArray FoundActors; - //// Get all actors of the level - //UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass(), FoundActors); - + int ActorIndex = 0; for(AActor* Actor : Actors) { + UE_LOG(LogCarla, Warning, TEXT(" %d / %d"), ActorIndex, Actors.Num()); + ActorIndex++; - TArray MeshComps; - Actor->GetComponents(MeshComps); - - UE_LOG(LogCarla, Warning, TEXT("%s %d"), *Actor->GetName(), MeshComps.Num()); - if(MeshComps.Num() > 0) + AInstancedFoliageActor* InstancedFolliageActor = Cast(Actor); + if(InstancedFolliageActor != nullptr) { - UE_LOG(LogCarla, Warning, TEXT(" %s"), *MeshComps[0]->GetClass()->GetName()); - } + TMap FoliageInstancesMap = InstancedFolliageActor->GetAllInstancesFoliageType(); - FVector WorldLocation = Actor->GetActorLocation(); - FVector WorldScale = Actor->GetActorScale(); - FRotator WorldRotation = Actor->GetActorRotation(); - // Find if there is some geometry component - TArray StaticMeshComps; - TArray SkeletalMeshComps; - Actor->GetComponents(StaticMeshComps); - Actor->GetComponents(SkeletalMeshComps); + UE_LOG(LogCarla, Warning, TEXT("FolliageActor with %d FoliageTypes"), FoliageInstancesMap.Num()); - // Calculate FBoundingBox of SM - for(UStaticMeshComponent* StaticMeshComp : StaticMeshComps) - { - UStaticMesh* StaticMesh = StaticMeshComp->GetStaticMesh(); - FBoundingBox BoundingBox = GetStaticMeshBoundingBox(StaticMesh); - BoundingBox.Origin *= WorldScale; - BoundingBox.Origin = WorldRotation.RotateVector(BoundingBox.Origin) + WorldLocation; - BoundingBox.Extent *= WorldScale; - BoundingBox.Rotation = WorldRotation; - Result.Add(BoundingBox); - } + int FoliageIndex = 0; + for(auto& FoliagePair: FoliageInstancesMap) + { + + const UFoliageType* FoliageType = FoliagePair.Key; + const UFoliageType_InstancedStaticMesh* FoliageType_ISM = Cast(FoliageType); + + const FFoliageInfo* FoliageInfo = FoliagePair.Value; + UHierarchicalInstancedStaticMeshComponent* HISMComp = FoliageInfo->GetComponent(); + + UStaticMesh *Mesh = FoliageType_ISM->GetStaticMesh(); + FBoundingBox SMBoundingBox = GetStaticMeshBoundingBox(Mesh); + + int32 NumHISMInstances = HISMComp->GetNumRenderInstances(); + + UE_LOG(LogCarla, Warning, TEXT(" %d/%d : NumHISMInstances = %d"), + FoliageIndex, FoliageInstancesMap.Num(), NumHISMInstances); + FoliageIndex++; + + const TArray& PerInstanceSMData = HISMComp->PerInstanceSMData; - // Calculate FBoundingBox of SK_M - for(USkeletalMeshComponent* SkeletalMeshComp : SkeletalMeshComps) + for(auto& InstSMIData : PerInstanceSMData) + { + FTransform Transform = FTransform(InstSMIData.Transform); + FRotator Rotation = Transform.GetRotation().Rotator(); + FVector Translation = Transform.GetLocation(); + FVector Scale = Transform.GetScale3D(); + + FBoundingBox BoundingBox = SMBoundingBox; + BoundingBox.Origin *= Scale; + BoundingBox.Origin = Rotation.RotateVector(BoundingBox.Origin) + Translation; + BoundingBox.Extent *= Scale; + BoundingBox.Rotation = Rotation; + Result.Add(BoundingBox); + } + } + + } + else { - USkeletalMesh* SkeletalMesh = SkeletalMeshComp->SkeletalMesh; - FBoundingBox BoundingBox = GetSkeletalMeshBoundingBox(SkeletalMesh); - BoundingBox.Origin *= WorldScale; - BoundingBox.Origin = WorldRotation.RotateVector(BoundingBox.Origin) + WorldLocation; - BoundingBox.Extent *= WorldScale; - BoundingBox.Rotation = WorldRotation; - Result.Add(BoundingBox); + TArray MeshComps; + Actor->GetComponents(MeshComps); + + FVector WorldLocation = Actor->GetActorLocation(); + FVector WorldScale = Actor->GetActorScale(); + FRotator WorldRotation = Actor->GetActorRotation(); + + // Find if there is some geometry component + TArray StaticMeshComps; + TArray SkeletalMeshComps; + Actor->GetComponents(StaticMeshComps); + Actor->GetComponents(SkeletalMeshComps); + + // Calculate FBoundingBox of SM + for(UStaticMeshComponent* StaticMeshComp : StaticMeshComps) + { + UStaticMesh* StaticMesh = StaticMeshComp->GetStaticMesh(); + FBoundingBox BoundingBox = GetStaticMeshBoundingBox(StaticMesh); + BoundingBox.Origin *= WorldScale; + BoundingBox.Origin = WorldRotation.RotateVector(BoundingBox.Origin) + WorldLocation; + BoundingBox.Extent *= WorldScale; + BoundingBox.Rotation = WorldRotation; + Result.Add(BoundingBox); + } + + // Calculate FBoundingBox of SK_M + for(USkeletalMeshComponent* SkeletalMeshComp : SkeletalMeshComps) + { + USkeletalMesh* SkeletalMesh = SkeletalMeshComp->SkeletalMesh; + FBoundingBox BoundingBox = GetSkeletalMeshBoundingBox(SkeletalMesh); + BoundingBox.Origin *= WorldScale; + BoundingBox.Origin = WorldRotation.RotateVector(BoundingBox.Origin) + WorldLocation; + BoundingBox.Extent *= WorldScale; + BoundingBox.Rotation = WorldRotation; + Result.Add(BoundingBox); + } } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h index d96a9ad9d8e..cb393bf4b9e 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h @@ -37,6 +37,6 @@ class CARLA_API UBoundingBoxCalculator : public UBlueprintFunctionLibrary static FBoundingBox GetStaticMeshBoundingBox(const UStaticMesh* StaticMesh); UFUNCTION(Category = "Carla Util", BlueprintCallable, CallInEditor) - static TArray GetBoundingBoxOfActors(TArray Actors); + static TArray GetBoundingBoxOfActors(const TArray& Actors); }; From abcc0f30d7b548f2230f697345b8d629cd7bf92d Mon Sep 17 00:00:00 2001 From: doterop Date: Tue, 8 Sep 2020 17:37:20 +0200 Subject: [PATCH 054/179] Added a call on the GM to get all the BBs of the level --- .../Source/Carla/Game/CarlaGameModeBase.cpp | 26 +++++++++++++++++++ .../Source/Carla/Game/CarlaGameModeBase.h | 3 +++ 2 files changed, 29 insertions(+) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp index b11a99891f3..e0d32b0a223 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp @@ -476,4 +476,30 @@ void ACarlaGameModeBase::SendAtlas() Sensor->SendPixels(AtlasImage, AtlasTextureWidth); } +} + + +void ACarlaGameModeBase::GetAllBBsOfLevel() +{ + + UWorld* World = GetWorld(); + + // Get all actors of the level + TArray FoundActors; + UGameplayStatics::GetAllActorsOfClass(World, AActor::StaticClass(), FoundActors); + + TArray BoundingBoxes; + BoundingBoxes = UBoundingBoxCalculator::GetBoundingBoxOfActors(FoundActors); + + for(FBoundingBox& Box : BoundingBoxes) + { + UKismetSystemLibrary::DrawDebugBox( + World, + Box.Origin, + Box.Extent, + FLinearColor::Red, + Box.Rotation, + 10.0f); + } + } \ No newline at end of file diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h index d87aa1dbe4a..8b81a834e6d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h @@ -52,6 +52,9 @@ class CARLA_API ACarlaGameModeBase : public AGameModeBase UFUNCTION(BlueprintCallable, Category = "CARLA Game Mode") ATrafficLightManager* GetTrafficLightManager(); + UFUNCTION(Category = "Carla Game Mode", BlueprintCallable, CallInEditor, Exec) + void GetAllBBsOfLevel(); + void AddSceneCaptureSensor(ASceneCaptureSensor* SceneCaptureSensor); void RemoveSceneCaptureSensor(ASceneCaptureSensor* SceneCaptureSensor); From af0d92676d9f06cbd87ce6ee1a317b1f2a534e79 Mon Sep 17 00:00:00 2001 From: doterop Date: Wed, 9 Sep 2020 14:27:54 +0200 Subject: [PATCH 055/179] Fixed Folliage BB calculation. --- .../Carla/Util/BoundingBoxCalculator.cpp | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp index e29a63f5819..e5d8e8e2b0d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp @@ -73,7 +73,10 @@ FBoundingBox UBoundingBoxCalculator::GetSkeletalMeshBoundingBox(const USkeletalM } // Get Vertex postion information from LOD 0 of the Skeletal Mesh - FPositionVertexBuffer& FPositionVertexBuffer = SkeletalMesh->GetResourceForRendering()->LODRenderData[0].StaticVertexBuffers.PositionVertexBuffer; + FSkeletalMeshRenderData* SkeletalMeshRenderData = SkeletalMesh->GetResourceForRendering(); + FSkeletalMeshLODRenderData& LODRenderData = SkeletalMeshRenderData->LODRenderData[0]; + FStaticMeshVertexBuffers& StaticMeshVertexBuffers = LODRenderData.StaticVertexBuffers; + FPositionVertexBuffer& FPositionVertexBuffer = StaticMeshVertexBuffers.PositionVertexBuffer; uint32 NumVertices = FPositionVertexBuffer.GetNumVertices(); // Look for Skeletal Mesh bounds (vertex perfect) @@ -129,13 +132,13 @@ TArray UBoundingBoxCalculator::GetBoundingBoxOfActors(const TArray int ActorIndex = 0; for(AActor* Actor : Actors) { - UE_LOG(LogCarla, Warning, TEXT(" %d / %d"), ActorIndex, Actors.Num()); + //UE_LOG(LogCarla, Warning, TEXT(" %d / %d"), ActorIndex, Actors.Num()); ActorIndex++; AInstancedFoliageActor* InstancedFolliageActor = Cast(Actor); if(InstancedFolliageActor != nullptr) { - TMap FoliageInstancesMap = InstancedFolliageActor->GetAllInstancesFoliageType(); + TMap>& FoliageInstancesMap = InstancedFolliageActor->FoliageInfos; UE_LOG(LogCarla, Warning, TEXT("FolliageActor with %d FoliageTypes"), FoliageInstancesMap.Num()); @@ -143,12 +146,11 @@ TArray UBoundingBoxCalculator::GetBoundingBoxOfActors(const TArray int FoliageIndex = 0; for(auto& FoliagePair: FoliageInstancesMap) { - const UFoliageType* FoliageType = FoliagePair.Key; + const FFoliageInfo& FoliageInfo = FoliagePair.Value.Get(); const UFoliageType_InstancedStaticMesh* FoliageType_ISM = Cast(FoliageType); - const FFoliageInfo* FoliageInfo = FoliagePair.Value; - UHierarchicalInstancedStaticMeshComponent* HISMComp = FoliageInfo->GetComponent(); + UHierarchicalInstancedStaticMeshComponent* HISMComp = FoliageInfo.GetComponent(); UStaticMesh *Mesh = FoliageType_ISM->GetStaticMesh(); FBoundingBox SMBoundingBox = GetStaticMeshBoundingBox(Mesh); @@ -198,11 +200,19 @@ TArray UBoundingBoxCalculator::GetBoundingBoxOfActors(const TArray { UStaticMesh* StaticMesh = StaticMeshComp->GetStaticMesh(); FBoundingBox BoundingBox = GetStaticMeshBoundingBox(StaticMesh); - BoundingBox.Origin *= WorldScale; - BoundingBox.Origin = WorldRotation.RotateVector(BoundingBox.Origin) + WorldLocation; - BoundingBox.Extent *= WorldScale; - BoundingBox.Rotation = WorldRotation; - Result.Add(BoundingBox); + + if(BoundingBox.Extent.IsZero()) + { + UE_LOG(LogCarla, Error, TEXT("%s has no SM assigned"), *Actor->GetName()); + } + else + { + BoundingBox.Origin *= WorldScale; + BoundingBox.Origin = WorldRotation.RotateVector(BoundingBox.Origin) + WorldLocation; + BoundingBox.Extent *= WorldScale; + BoundingBox.Rotation = WorldRotation; + Result.Add(BoundingBox); + } } // Calculate FBoundingBox of SK_M From 1855d34c5698839b3598e15a2e21afeb157cb44f Mon Sep 17 00:00:00 2001 From: doterop Date: Wed, 9 Sep 2020 15:47:03 +0200 Subject: [PATCH 056/179] GM::GetAllBBsOfLevel now returns the array of BBs --- .../Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp | 4 ++-- .../Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp index e0d32b0a223..6f7a752ac4c 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp @@ -479,9 +479,8 @@ void ACarlaGameModeBase::SendAtlas() } -void ACarlaGameModeBase::GetAllBBsOfLevel() +TArray ACarlaGameModeBase::GetAllBBsOfLevel() { - UWorld* World = GetWorld(); // Get all actors of the level @@ -502,4 +501,5 @@ void ACarlaGameModeBase::GetAllBBsOfLevel() 10.0f); } + return BoundingBoxes; } \ No newline at end of file diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h index 8b81a834e6d..223493b883b 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h @@ -53,7 +53,7 @@ class CARLA_API ACarlaGameModeBase : public AGameModeBase ATrafficLightManager* GetTrafficLightManager(); UFUNCTION(Category = "Carla Game Mode", BlueprintCallable, CallInEditor, Exec) - void GetAllBBsOfLevel(); + TArray GetAllBBsOfLevel(); void AddSceneCaptureSensor(ASceneCaptureSensor* SceneCaptureSensor); From 33700bd6e3ff1aeb21dc10294371560ae00a5496 Mon Sep 17 00:00:00 2001 From: doterop Date: Wed, 9 Sep 2020 15:47:36 +0200 Subject: [PATCH 057/179] Added call on the server side to retrieve the BBs --- .../Carla/Source/Carla/Server/CarlaServer.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp index 2e92a0f7c8f..60dedb32b91 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp @@ -275,7 +275,6 @@ void FCarlaServer::FPimpl::BindActions() return Result; }; - BIND_SYNC(get_episode_settings) << [this]() -> R { REQUIRE_CARLA_EPISODE(); @@ -307,6 +306,19 @@ void FCarlaServer::FPimpl::BindActions() return Episode->SerializeActor(ActorView); }; + BIND_SYNC(get_all_level_BBs) << [this]() -> R> + { + REQUIRE_CARLA_EPISODE(); + TArray Result; + ACarlaGameModeBase* GameMode = UCarlaStatics::GetGameMode(Episode->GetWorld()); + if (!GameMode) + { + RESPOND_ERROR("unable to find CARLA game mode"); + } + Result = GameMode->GetAllBBsOfLevel(); + return MakeVectorFromTArray(Result); + }; + // ~~ Weather ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BIND_SYNC(get_weather_parameters) << [this]() -> R From b753498ecb86e295872defee5e3e1025ace71e4e Mon Sep 17 00:00:00 2001 From: doterop Date: Wed, 9 Sep 2020 18:11:41 +0200 Subject: [PATCH 058/179] Removed debug draw calls --- .../Carla/Source/Carla/Game/CarlaGameModeBase.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp index 6f7a752ac4c..b0f8c35fa7f 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp @@ -490,16 +490,5 @@ TArray ACarlaGameModeBase::GetAllBBsOfLevel() TArray BoundingBoxes; BoundingBoxes = UBoundingBoxCalculator::GetBoundingBoxOfActors(FoundActors); - for(FBoundingBox& Box : BoundingBoxes) - { - UKismetSystemLibrary::DrawDebugBox( - World, - Box.Origin, - Box.Extent, - FLinearColor::Red, - Box.Rotation, - 10.0f); - } - return BoundingBoxes; } \ No newline at end of file From 5bdd65ca0e5613cf383eeb9b4f386ee22dd9945d Mon Sep 17 00:00:00 2001 From: doterop Date: Wed, 9 Sep 2020 18:12:56 +0200 Subject: [PATCH 059/179] Added call to the PythonAPI --- LibCarla/source/carla/client/World.cpp | 4 ++++ LibCarla/source/carla/client/World.h | 3 +++ LibCarla/source/carla/client/detail/Client.cpp | 5 +++++ LibCarla/source/carla/client/detail/Client.h | 3 +++ LibCarla/source/carla/client/detail/Simulator.h | 5 +++++ PythonAPI/carla/source/libcarla/World.cpp | 10 ++++++++++ 6 files changed, 30 insertions(+) diff --git a/LibCarla/source/carla/client/World.cpp b/LibCarla/source/carla/client/World.cpp index ae56742e54c..757bf5676d5 100644 --- a/LibCarla/source/carla/client/World.cpp +++ b/LibCarla/source/carla/client/World.cpp @@ -158,5 +158,9 @@ namespace client { _episode.Lock()->FreezeAllTrafficLights(frozen); } + std::vector World::GetLevelBBs() const { + return _episode.Lock()->GetLevelBBs(); + } + } // namespace client } // namespace carla diff --git a/LibCarla/source/carla/client/World.h b/LibCarla/source/carla/client/World.h index 2df6af200ae..5040b232235 100644 --- a/LibCarla/source/carla/client/World.h +++ b/LibCarla/source/carla/client/World.h @@ -150,6 +150,9 @@ namespace client { void FreezeAllTrafficLights(bool frozen); + /// Returns all the BBs of all the elements of the level + std::vector GetLevelBBs() const; + private: detail::EpisodeProxy _episode; diff --git a/LibCarla/source/carla/client/detail/Client.cpp b/LibCarla/source/carla/client/detail/Client.cpp index 46de297f47d..64c9edd6a54 100644 --- a/LibCarla/source/carla/client/detail/Client.cpp +++ b/LibCarla/source/carla/client/detail/Client.cpp @@ -413,6 +413,11 @@ namespace detail { _pimpl->AsyncCall("update_lights_state", _pimpl->endpoint, std::move(lights), discard_client); } + std::vector Client::GetLevelBBs() const { + using return_t = std::vector; + return _pimpl->CallAndWait("get_all_level_BBs"); + } + } // namespace detail } // namespace client } // namespace carla diff --git a/LibCarla/source/carla/client/detail/Client.h b/LibCarla/source/carla/client/detail/Client.h index 4a31b4e1a91..e941eaeed9a 100644 --- a/LibCarla/source/carla/client/detail/Client.h +++ b/LibCarla/source/carla/client/detail/Client.h @@ -256,6 +256,9 @@ namespace detail { std::vector& lights, bool discard_client = false) const; + /// Returns all the BBs of all the elements of the level + std::vector GetLevelBBs() const; + private: class Pimpl; diff --git a/LibCarla/source/carla/client/detail/Simulator.h b/LibCarla/source/carla/client/detail/Simulator.h index 9a7d8731bfe..f6605d765d0 100644 --- a/LibCarla/source/carla/client/detail/Simulator.h +++ b/LibCarla/source/carla/client/detail/Simulator.h @@ -226,6 +226,11 @@ namespace detail { return _client.GetVehicleLightState(vehicle.GetId()); } + /// Returns all the BBs of all the elements of the level + std::vector GetLevelBBs() const { + return _client.GetLevelBBs(); + } + /// @} // ========================================================================= /// @name AI diff --git a/PythonAPI/carla/source/libcarla/World.cpp b/PythonAPI/carla/source/libcarla/World.cpp index c5edf6d1b2a..0a1a3d971bf 100644 --- a/PythonAPI/carla/source/libcarla/World.cpp +++ b/PythonAPI/carla/source/libcarla/World.cpp @@ -70,6 +70,15 @@ static auto GetVehiclesLightStates(carla::client::World &self) { return dict; } +static auto GetLevelBBs(const carla::client::World &self) { + carla::PythonUtil::ReleaseGIL unlock; + boost::python::list result; + for (const auto &bb : self.GetLevelBBs()) { + result.append(bb); + } + return result; +} + void export_world() { using namespace boost::python; namespace cc = carla::client; @@ -168,6 +177,7 @@ void export_world() { .def("get_traffic_light", CONST_CALL_WITHOUT_GIL_1(cc::World, GetTrafficLight, cc::Landmark), arg("landmark")) .def("get_lightmanager", CONST_CALL_WITHOUT_GIL(cc::World, GetLightManager)) .def("freeze_all_traffic_lights", &cc::World::FreezeAllTrafficLights, (arg("frozen"))) + .def("get_level_bbs", &GetLevelBBs) .def(self_ns::str(self_ns::self)) ; From 4757ce4dcc79b969c737aeb59475b10f58fe45d1 Mon Sep 17 00:00:00 2001 From: Jacopo Bartiromo <32928804+jackbart94@users.noreply.github.com> Date: Wed, 16 Sep 2020 13:11:04 +0200 Subject: [PATCH 060/179] Fixes a map change error when TM is in synchronous mode (#3288) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update build_windows.md Added info about command execution that toke me many time to find out * Update build_windows.md Updated as requested in pull request review * Running Carla when choosing a) deb Carla install This fixes a minor error in the documentation regarding running carla, if the deb installation was choosen. * Fix for traffic manager freezing upon map change * Remove manual unlock of mutex Co-authored-by: Néstor Sabater Co-authored-by: ll7 <32880741+ll7@users.noreply.github.com> Co-authored-by: Praveen Kumar Co-authored-by: bernat --- LibCarla/source/carla/trafficmanager/TrafficManager.h | 1 - .../carla/trafficmanager/TrafficManagerLocal.cpp | 10 +++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/LibCarla/source/carla/trafficmanager/TrafficManager.h b/LibCarla/source/carla/trafficmanager/TrafficManager.h index 74c91a848f7..14e001340a6 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManager.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManager.h @@ -237,7 +237,6 @@ class TrafficManager { std::lock_guard lock(_mutex); auto it = _tm_map.find(port); if (it != _tm_map.end()) { - _mutex.unlock(); return it->second; } return nullptr; diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp index 58bbd3374e9..656fdb691b5 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp @@ -123,7 +123,7 @@ void TrafficManagerLocal::Run() { // Wait for external trigger to initiate cycle in synchronous mode. if (synchronous_mode) { std::unique_lock lock(step_execution_mutex); - step_begin_trigger.wait(lock, [this]() {return step_begin.load();}); + step_begin_trigger.wait(lock, [this]() {return step_begin.load() || !run_traffic_manger.load();}); step_begin.store(false); } @@ -218,6 +218,9 @@ bool TrafficManagerLocal::SynchronousTick() { void TrafficManagerLocal::Stop() { run_traffic_manger.store(false); + if (parameters.GetSynchronousMode()) { + step_begin_trigger.notify_one(); + } if (worker_thread) { if (worker_thread->joinable()) { @@ -382,7 +385,12 @@ void TrafficManagerLocal::ResetAllTrafficLights() { } void TrafficManagerLocal::SetSynchronousMode(bool mode) { + const bool previous_mode = parameters.GetSynchronousMode(); parameters.SetSynchronousMode(mode); + if (previous_mode && !mode) { + step_begin.store(true); + step_begin_trigger.notify_one(); + } } void TrafficManagerLocal::SetSynchronousModeTimeOutInMiliSecond(double time) { From 0a837ff1a042ea9829e2c213030e401967457883 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Tue, 15 Sep 2020 11:31:55 +0200 Subject: [PATCH 061/179] Fixed bad_weak_ptr + updated deprecated asio calls --- LibCarla/source/carla/ThreadPool.h | 3 ++- .../source/carla/client/ServerSideSensor.cpp | 2 -- LibCarla/source/carla/rpc/Server.h | 5 +++-- .../carla/streaming/detail/tcp/Client.cpp | 22 ++++++++++++------- .../carla/streaming/detail/tcp/Server.cpp | 4 +++- .../carla/streaming/detail/tcp/Server.h | 3 ++- .../streaming/detail/tcp/ServerSession.cpp | 16 ++++++++------ .../source/carla/streaming/low_level/Client.h | 19 +++++++--------- .../test/server/test_benchmark_streaming.cpp | 4 +++- 9 files changed, 44 insertions(+), 34 deletions(-) diff --git a/LibCarla/source/carla/ThreadPool.h b/LibCarla/source/carla/ThreadPool.h index c9cc38567a7..b807d4e24f3 100644 --- a/LibCarla/source/carla/ThreadPool.h +++ b/LibCarla/source/carla/ThreadPool.h @@ -12,6 +12,7 @@ #include "carla/Time.h" #include +#include #include #include @@ -40,7 +41,7 @@ namespace carla { std::future Post(FunctorT &&functor) { auto task = std::packaged_task(std::forward(functor)); auto future = task.get_future(); - _io_context.post(carla::MoveHandler(task)); + boost::asio::post(_io_context, carla::MoveHandler(task)); return future; } diff --git a/LibCarla/source/carla/client/ServerSideSensor.cpp b/LibCarla/source/carla/client/ServerSideSensor.cpp index 102407379e7..52ede64571b 100644 --- a/LibCarla/source/carla/client/ServerSideSensor.cpp +++ b/LibCarla/source/carla/client/ServerSideSensor.cpp @@ -11,8 +11,6 @@ #include -#include - namespace carla { namespace client { diff --git a/LibCarla/source/carla/rpc/Server.h b/LibCarla/source/carla/rpc/Server.h index baa50bab9c8..6b51e7c7c20 100644 --- a/LibCarla/source/carla/rpc/Server.h +++ b/LibCarla/source/carla/rpc/Server.h @@ -12,6 +12,7 @@ #include "carla/rpc/Response.h" #include +#include #include @@ -107,12 +108,12 @@ namespace detail { }); if (metadata.IsResponseIgnored()) { // Post task and ignore result. - io.post(MoveHandler(task)); + boost::asio::post(io, MoveHandler(task)); return R(); } else { // Post task and wait for result. auto result = task.get_future(); - io.post(MoveHandler(task)); + boost::asio::post(io, MoveHandler(task)); return result.get(); } }; diff --git a/LibCarla/source/carla/streaming/detail/tcp/Client.cpp b/LibCarla/source/carla/streaming/detail/tcp/Client.cpp index da6fd0ab30c..71789a08c7e 100644 --- a/LibCarla/source/carla/streaming/detail/tcp/Client.cpp +++ b/LibCarla/source/carla/streaming/detail/tcp/Client.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include @@ -84,7 +86,7 @@ namespace tcp { void Client::Connect() { auto self = shared_from_this(); - _strand.post([this, self]() { + boost::asio::post(_strand, [this, self]() { if (_done) { return; } @@ -111,7 +113,11 @@ namespace tcp { boost::asio::async_write( _socket, boost::asio::buffer(&stream_id, sizeof(stream_id)), - _strand.wrap([=](error_code ec, size_t DEBUG_ONLY(bytes)) { + boost::asio::bind_executor(_strand, [=](error_code ec, size_t DEBUG_ONLY(bytes)) { + // Ensures to stop the execution once the connection has been stopped. + if (_done) { + return; + } if (!ec) { DEBUG_ASSERT_EQ(bytes, sizeof(stream_id)); // If succeeded start reading data. @@ -129,14 +135,14 @@ namespace tcp { }; log_debug("streaming client: connecting to", ep); - _socket.async_connect(ep, _strand.wrap(handle_connect)); + _socket.async_connect(ep, boost::asio::bind_executor(_strand, handle_connect)); }); } void Client::Stop() { _connection_timer.cancel(); auto self = shared_from_this(); - _strand.post([this, self]() { + boost::asio::post(_strand, [this, self]() { _done = true; if (_socket.is_open()) { _socket.close(); @@ -156,7 +162,7 @@ namespace tcp { void Client::ReadData() { auto self = shared_from_this(); - _strand.post([this, self]() { + boost::asio::post(_strand, [this, self]() { if (_done) { return; } @@ -173,7 +179,7 @@ namespace tcp { // Move the buffer to the callback function and start reading the next // piece of data. // log_debug("streaming client: success reading data, calling the callback"); - _strand.context().post([self, message]() { self->_callback(message->pop()); }); + boost::asio::post(_strand, [self, message]() { self->_callback(message->pop()); }); ReadData(); } else { // As usual, if anything fails start over from the very top. @@ -196,7 +202,7 @@ namespace tcp { boost::asio::async_read( _socket, message->buffer(), - _strand.wrap(handle_read_data)); + boost::asio::bind_executor(_strand, handle_read_data)); } else { log_info("streaming client: failed to read header:", ec.message()); DEBUG_ONLY(log_debug("size = ", message->size())); @@ -209,7 +215,7 @@ namespace tcp { boost::asio::async_read( _socket, message->size_as_buffer(), - _strand.wrap(handle_read_header)); + boost::asio::bind_executor(_strand, handle_read_header)); }); } diff --git a/LibCarla/source/carla/streaming/detail/tcp/Server.cpp b/LibCarla/source/carla/streaming/detail/tcp/Server.cpp index e788b40cc34..3ee00575f38 100644 --- a/LibCarla/source/carla/streaming/detail/tcp/Server.cpp +++ b/LibCarla/source/carla/streaming/detail/tcp/Server.cpp @@ -6,6 +6,8 @@ #include "carla/streaming/detail/tcp/Server.h" +#include + #include "carla/Logging.h" #include @@ -38,7 +40,7 @@ namespace tcp { _acceptor.async_accept(session->_socket, [=](error_code ec) { // Handle query and open a new session immediately. - _io_context.post([=]() { handle_query(ec); }); + boost::asio::post(_io_context, [=]() { handle_query(ec); }); OpenSession(timeout, on_opened, on_closed); }); } diff --git a/LibCarla/source/carla/streaming/detail/tcp/Server.h b/LibCarla/source/carla/streaming/detail/tcp/Server.h index c38cfa63c75..72cf8fa2621 100644 --- a/LibCarla/source/carla/streaming/detail/tcp/Server.h +++ b/LibCarla/source/carla/streaming/detail/tcp/Server.h @@ -12,6 +12,7 @@ #include #include +#include #include @@ -45,7 +46,7 @@ namespace tcp { /// is closed. template void Listen(FunctorT1 on_session_opened, FunctorT2 on_session_closed) { - _io_context.post([=]() { + boost::asio::post(_io_context, [=]() { OpenSession( _timeout, std::move(on_session_opened), diff --git a/LibCarla/source/carla/streaming/detail/tcp/ServerSession.cpp b/LibCarla/source/carla/streaming/detail/tcp/ServerSession.cpp index 8556fdec33a..15f570de661 100644 --- a/LibCarla/source/carla/streaming/detail/tcp/ServerSession.cpp +++ b/LibCarla/source/carla/streaming/detail/tcp/ServerSession.cpp @@ -11,6 +11,8 @@ #include #include +#include +#include #include @@ -45,7 +47,7 @@ namespace tcp { StartTimer(); auto self = shared_from_this(); // To keep myself alive. - _strand.post([=]() { + boost::asio::post(_strand, [=]() { auto handle_query = [this, self, callback=std::move(on_opened)]( const boost::system::error_code &ec, @@ -53,7 +55,7 @@ namespace tcp { if (!ec) { DEBUG_ASSERT_EQ(bytes_received, sizeof(_stream_id)); log_debug("session", _session_id, "for stream", _stream_id, " started"); - _strand.context().post([=]() { callback(self); }); + boost::asio::post(_strand.context(), [=]() { callback(self); }); } else { log_error("session", _session_id, ": error retrieving stream id :", ec.message()); CloseNow(); @@ -65,7 +67,7 @@ namespace tcp { boost::asio::async_read( _socket, boost::asio::buffer(&_stream_id, sizeof(_stream_id)), - _strand.wrap(handle_query)); + boost::asio::bind_executor(_strand, handle_query)); }); } @@ -73,7 +75,7 @@ namespace tcp { DEBUG_ASSERT(message != nullptr); DEBUG_ASSERT(!message->empty()); auto self = shared_from_this(); - _strand.post([=]() { + boost::asio::post(_strand, [=]() { if (!_socket.is_open()) { return; } @@ -100,12 +102,12 @@ namespace tcp { boost::asio::async_write( _socket, message->GetBufferSequence(), - _strand.wrap(handle_sent)); + boost::asio::bind_executor(_strand, handle_sent)); }); } void ServerSession::Close() { - _strand.post([self=shared_from_this()]() { self->CloseNow(); }); + boost::asio::post(_strand, [self=shared_from_this()]() { self->CloseNow(); }); } void ServerSession::StartTimer() { @@ -129,7 +131,7 @@ namespace tcp { if (_socket.is_open()) { _socket.close(); } - _strand.context().post([self=shared_from_this()]() { + boost::asio::post(_strand.context(), [self=shared_from_this()]() { DEBUG_ASSERT(self->_on_closed); self->_on_closed(self); }); diff --git a/LibCarla/source/carla/streaming/low_level/Client.h b/LibCarla/source/carla/streaming/low_level/Client.h index 7db9a418067..aacc4ceba75 100644 --- a/LibCarla/source/carla/streaming/low_level/Client.h +++ b/LibCarla/source/carla/streaming/low_level/Client.h @@ -46,12 +46,14 @@ namespace low_level { } } + /// @warning cannot subscribe twice to the same stream (even if it's a + /// MultiStream). template void Subscribe( boost::asio::io_context &io_context, token_type token, Functor &&callback) { - + DEBUG_ASSERT_EQ(_clients.find(token.get_stream_id()), _clients.end()); if (!token.has_address()) { token.set_address(_fallback_address); } @@ -64,15 +66,10 @@ namespace low_level { } void UnSubscribe(token_type token) { - auto id = token.get_stream_id(); - for (auto it=_clients.begin(); it!=_clients.end(); ) { - if (it->first == id) { - log_info("Unsubscribing from stream:", id); - it->second->Stop(); - it = _clients.erase(it); - } else { - ++it; - } + auto it = _clients.find(token.get_stream_id()); + if (it != _clients.end()) { + it->second->Stop(); + _clients.erase(it); } } @@ -80,7 +77,7 @@ namespace low_level { boost::asio::ip::address _fallback_address; - std::unordered_multimap< + std::unordered_map< detail::stream_id_type, std::shared_ptr> _clients; }; diff --git a/LibCarla/source/test/server/test_benchmark_streaming.cpp b/LibCarla/source/test/server/test_benchmark_streaming.cpp index 1ca293767de..f1f55087d25 100644 --- a/LibCarla/source/test/server/test_benchmark_streaming.cpp +++ b/LibCarla/source/test/server/test_benchmark_streaming.cpp @@ -9,6 +9,8 @@ #include #include +#include + #include using namespace carla::streaming; @@ -38,7 +40,7 @@ class Benchmark { _client.Subscribe(stream.token(), [this](carla::Buffer DEBUG_ONLY(msg)) { DEBUG_ASSERT_EQ(msg.size(), _message.size()); DEBUG_ASSERT(msg == _message); - _client_callback.post([this]() { + boost::asio::post(_client_callback, [this]() { CARLA_PROFILE_FPS(client, listen_callback); ++_number_of_messages_received; }); From 2a2b7d9bc87aef78b9b7ec3dacfb8153e15b40b4 Mon Sep 17 00:00:00 2001 From: Axel Date: Mon, 14 Sep 2020 13:00:00 +0200 Subject: [PATCH 062/179] Added static mesh factory. --- .../Source/Carla/Actor/StaticMeshFactory.cpp | 64 +++++++++++++++++++ .../Source/Carla/Actor/StaticMeshFactory.h | 29 +++++++++ .../Carla/Source/Carla/Game/CarlaEpisode.cpp | 22 ++++++- .../Source/Carla/Recorder/CarlaReplayer.cpp | 3 + .../Carla/Recorder/CarlaReplayerHelper.cpp | 17 +++++ .../Carla/Recorder/CarlaReplayerHelper.h | 2 + 6 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/StaticMeshFactory.cpp create mode 100644 Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/StaticMeshFactory.h diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/StaticMeshFactory.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/StaticMeshFactory.cpp new file mode 100644 index 00000000000..89decab3379 --- /dev/null +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/StaticMeshFactory.cpp @@ -0,0 +1,64 @@ +// Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma +// de Barcelona (UAB). +// +// This work is licensed under the terms of the MIT license. +// For a copy, see . + +#include "StaticMeshFactory.h" +#include "Carla/Actor/ActorBlueprintFunctionLibrary.h" +#include "Engine/StaticMeshActor.h" +#include "Carla/Game/CarlaEpisode.h" + +TArray AStaticMeshFactory::GetDefinitions() +{ + using ABFL = UActorBlueprintFunctionLibrary; + auto StaticMeshDefinition = ABFL::MakeGenericDefinition( + TEXT("static"), + TEXT("prop"), + TEXT("mesh")); + StaticMeshDefinition.Class = AStaticMeshActor::StaticClass(); + return { StaticMeshDefinition }; +} + +FActorSpawnResult AStaticMeshFactory::SpawnActor( + const FTransform &SpawnAtTransform, + const FActorDescription &ActorDescription) +{ + using ABFL = UActorBlueprintFunctionLibrary; + auto *World = GetWorld(); + if (World == nullptr) + { + UE_LOG(LogCarla, Error, TEXT + ("AStaticMeshFactory: cannot spawn mesh into an empty world.")); + return {}; + } + + FActorSpawnParameters SpawnParameters; + SpawnParameters.SpawnCollisionHandlingOverride = + ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + auto *StaticMeshActor = World->SpawnActor( + ActorDescription.Class, SpawnAtTransform, SpawnParameters); + + auto *StaticMeshComponent = Cast( + StaticMeshActor->GetRootComponent()); + if (StaticMeshComponent) + { + if (ActorDescription.Variations.Contains("mesh_path") && + ActorDescription.Variations.Contains("mass")) + { + FString MeshPath = ABFL::ActorAttributeToString( + ActorDescription.Variations["mesh_path"], ""); + UObject* MeshObject = StaticLoadObject(UStaticMesh::StaticClass(), + nullptr, + *(MeshPath)); + UStaticMesh *Mesh = Cast(MeshObject); + StaticMeshComponent->SetMobility(EComponentMobility::Movable); + StaticMeshComponent->SetStaticMesh(Mesh); + StaticMeshComponent->SetSimulatePhysics(true); + StaticMeshComponent->SetCollisionProfileName("PhysicsActor"); + StaticMeshComponent->SetMassOverrideInKg("", + ABFL::ActorAttributeToFloat(ActorDescription.Variations["mass"], 1.0f)); + } + } + return FActorSpawnResult(StaticMeshActor); +} diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/StaticMeshFactory.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/StaticMeshFactory.h new file mode 100644 index 00000000000..97082807630 --- /dev/null +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/StaticMeshFactory.h @@ -0,0 +1,29 @@ +// Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma +// de Barcelona (UAB). +// +// This work is licensed under the terms of the MIT license. +// For a copy, see . + +#pragma once + +#include "Carla/Actor/ActorSpawnResult.h" +#include "Carla/Actor/CarlaActorFactory.h" + +#include "StaticMeshFactory.generated.h" + +/// Factory in charge of spawning sensors. This factory is able to spawn every +/// sensor registered in carla::sensor::SensorRegistry. +UCLASS() +class CARLA_API AStaticMeshFactory : public ACarlaActorFactory +{ + GENERATED_BODY() + + /// Retrieve the definitions of all the sensors registered in the + /// SensorRegistry. Sensors must implement a GetSensorDefinition() static + /// method. + TArray GetDefinitions() final; + + FActorSpawnResult SpawnActor( + const FTransform &SpawnAtTransform, + const FActorDescription &ActorDescription) final; +}; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp index 2a7f81da198..7c40769da54 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp @@ -299,6 +299,18 @@ void UCarlaEpisode::InitializeAtBeginPlay() ActorDispatcher->RegisterActor(*Actor, Description); } + // get the definition id for static.prop.mesh + auto Definitions = GetActorDefinitions(); + uint32 StaticMeshUId = 0; + for (auto& Definition : Definitions) + { + if (Definition.Id == "static.prop.mesh") + { + StaticMeshUId = Definition.UId; + break; + } + } + for (TActorIterator It(World); It; ++It) { auto Actor = *It; @@ -308,8 +320,16 @@ void UCarlaEpisode::InitializeAtBeginPlay() if (MeshComponent->Mobility == EComponentMobility::Movable) { FActorDescription Description; - Description.Id = TEXT("static.prop"); + Description.Id = TEXT("static.prop.mesh"); + Description.UId = StaticMeshUId; Description.Class = Actor->GetClass(); + Description.Variations.Add("mesh_path", + FActorAttribute{"mesh_path", EActorAttributeType::String, + MeshComponent->GetStaticMesh()->GetPathName()}); + Description.Variations.Add("mass", + FActorAttribute{"mass", EActorAttributeType::Float, + FString::SanitizeFloat(MeshComponent->GetMass())}); + carla::log_warning(carla::rpc::FromFString(MeshComponent->GetStaticMesh()->GetPathName())); ActorDispatcher->RegisterActor(*Actor, Description); } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayer.cpp index 6333aae50a6..145e9206837 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayer.cpp @@ -178,6 +178,7 @@ std::string CarlaReplayer::ReplayFile(std::string Filename, double TimeStart, do // if we don't need to load a new map, then start if (!Autoplay.Enabled) { + Helper.RemoveStaticProps(); // process all events until the time ProcessToTime(TimeStart, true); // mark as enabled @@ -237,6 +238,8 @@ void CarlaReplayer::CheckPlayAfterMapLoaded(void) // apply time factor TimeFactor = Autoplay.TimeFactor; + Helper.RemoveStaticProps(); + // process all events until the time ProcessToTime(TimeStart, true); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayerHelper.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayerHelper.cpp index c98852dc53b..11c1fcb0ea8 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayerHelper.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayerHelper.cpp @@ -463,3 +463,20 @@ void CarlaReplayerHelper::SetWalkerSpeed(uint32_t ActorId, float Speed) } } } + +void CarlaReplayerHelper::RemoveStaticProps() +{ + check(Episode != nullptr); + auto World = Episode->GetWorld(); + for (TActorIterator It(World); It; ++It) + { + auto Actor = *It; + check(Actor != nullptr); + auto MeshComponent = Actor->GetStaticMeshComponent(); + check(MeshComponent != nullptr); + if (MeshComponent->Mobility == EComponentMobility::Movable) + { + Actor->Destroy(); + } + } +} diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayerHelper.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayerHelper.h index 6ea341ea0b7..23e00490813 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayerHelper.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayerHelper.h @@ -65,6 +65,8 @@ class CarlaReplayerHelper // set the animation speed for walkers void SetWalkerSpeed(uint32_t ActorId, float Speed); + void RemoveStaticProps(); + private: UCarlaEpisode *Episode {nullptr}; From f008c922ba75b7bbe8dbfec888b2d4eea80b2c30 Mon Sep 17 00:00:00 2001 From: Axel Date: Mon, 14 Sep 2020 16:07:11 +0200 Subject: [PATCH 063/179] Updated changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b65970dc1f8..bbb1333f800 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ * Fixed rain drop spawn issues when spawning camera sensors * Fixed assets import pipeline * Fixed Update.sh from failing when the root folder contains a space on it + * Fixed dynamic meshes not moving to initial position when replaying * Fixed colors of lane markings when importing a map, they were reversed (white and yellow) * Fixed missing include directive in file **WheelPhysicsControl.h** * Fixed gravity measurement bug from IMU sensor From 58a070941693cd93e55b039b7600a4e8c5475fa5 Mon Sep 17 00:00:00 2001 From: Axel Date: Tue, 15 Sep 2020 17:10:43 +0200 Subject: [PATCH 064/179] Updated ContentVersions --- Util/ContentVersions.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Util/ContentVersions.txt b/Util/ContentVersions.txt index ded7f7fca44..6521f78d34a 100644 --- a/Util/ContentVersions.txt +++ b/Util/ContentVersions.txt @@ -32,4 +32,4 @@ 0.9.7: 20191221_c88604b 0.9.8: 20200306_06b6cb1 0.9.9: 20200422_ea5179a -Latest: 20200908_3f92e51 +Latest: 20200915_24120cd From 7b914bd13a4e8890f0887d54eacb3898cc6b1238 Mon Sep 17 00:00:00 2001 From: Axel Date: Wed, 16 Sep 2020 14:46:05 +0200 Subject: [PATCH 065/179] Updated comments. --- .../Plugins/Carla/Source/Carla/Actor/StaticMeshFactory.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/StaticMeshFactory.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/StaticMeshFactory.h index 97082807630..3d65fdf49b9 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/StaticMeshFactory.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/StaticMeshFactory.h @@ -11,16 +11,14 @@ #include "StaticMeshFactory.generated.h" -/// Factory in charge of spawning sensors. This factory is able to spawn every -/// sensor registered in carla::sensor::SensorRegistry. +/// Factory in charge of spawning static meshes. This factory is able to spawn +/// any mesh in content. UCLASS() class CARLA_API AStaticMeshFactory : public ACarlaActorFactory { GENERATED_BODY() - /// Retrieve the definitions of all the sensors registered in the - /// SensorRegistry. Sensors must implement a GetSensorDefinition() static - /// method. + /// Retrieve the definitions of the static mesh actor TArray GetDefinitions() final; FActorSpawnResult SpawnActor( From ec7b3b63fda968aa79ef7b75f340f52a4ec1cc72 Mon Sep 17 00:00:00 2001 From: Axel Date: Wed, 16 Sep 2020 13:09:18 +0200 Subject: [PATCH 066/179] Added off state to traffic lights. --- .../Carla/Traffic/TrafficLightComponent.cpp | 17 +++++++++++++++-- .../Source/Carla/Traffic/TrafficLightState.h | 8 +++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightComponent.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightComponent.cpp index baaea9ddc9c..9b05028751e 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightComponent.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightComponent.cpp @@ -97,9 +97,16 @@ void UTrafficLightComponent::SetLightState(ETrafficLightState NewState) { Controller->SetTrafficLight(nullptr); } + // workarround for tm not supporting off state + if (LightState == ETrafficLightState::Off) + { + Controller->SetTrafficLightState(ETrafficLightState::Green); + Controller->SetTrafficLight(nullptr); + } } } - if (LightState == ETrafficLightState::Green) + if (LightState == ETrafficLightState::Green || + LightState == ETrafficLightState::Off) { Vehicles.Empty(); } @@ -153,12 +160,18 @@ void UTrafficLightComponent::OnOverlapTriggerBox(UPrimitiveComponent *Overlapped if (VehicleController) { VehicleController->SetTrafficLightState(LightState); - if (LightState != ETrafficLightState::Green) + if (LightState != ETrafficLightState::Green && + LightState != ETrafficLightState::Off) { Vehicles.Add(VehicleController); VehicleController->SetTrafficLight( Cast(GetOwner())); } + // workarround for tm not supporting off state + if (LightState == ETrafficLightState::Off) + { + VehicleController->SetTrafficLightState(ETrafficLightState::Green); + } } } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightState.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightState.h index daba3d2e770..cc5b26fd70c 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightState.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightState.h @@ -6,11 +6,17 @@ #pragma once +#include +#include +#include + #include "TrafficLightState.generated.h" + UENUM(BlueprintType) enum class ETrafficLightState : uint8 { Red UMETA(DisplayName = "Red"), Yellow UMETA(DisplayName = "Yellow"), - Green UMETA(DisplayName = "Green") + Green UMETA(DisplayName = "Green"), + Off UMETA(DisplayName = "Off") }; From fd89ec4cd7bb55f57288e1275156832aec135f33 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Mon, 14 Sep 2020 13:13:32 +0200 Subject: [PATCH 067/179] Brief note on code contributions --- Docs/cont_contribution_guidelines.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Docs/cont_contribution_guidelines.md b/Docs/cont_contribution_guidelines.md index b8f6efe9d04..b130ff6c2b4 100644 --- a/Docs/cont_contribution_guidelines.md +++ b/Docs/cont_contribution_guidelines.md @@ -38,7 +38,9 @@ Ideas for new features are also a great way to contribute. Any suggestion that c --- ## Code contributions -Before starting hands-on on coding, please check out the [issue board][issueboard] to check what is the team already working on, to avoid overlapping. In case of doubt or to discuss how to proceed, please contact one of us (or send an email to ). +Before starting hands-on on coding, please check out the [issue board][issueboard] to check what is the team already working on, to avoid overlapping. In case of doubt or to discuss how to proceed, please contact one of us (or send an email to ). + +In order to start working, [fork the CARLA repository](https://docs.github.com/en/enterprise/2.13/user/articles/fork-a-repo), and clone said fork in your computer. Remember to [keep your fork in sync](https://docs.github.com/en/enterprise/2.13/user/articles/syncing-a-fork) with the original repository. [issueboard]: https://github.com/carla-simulator/carla/issues From d18a506edf898cbfc7e33c57d8c36f0f9ef54109 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 9 Sep 2020 16:48:04 +0200 Subject: [PATCH 068/179] First iteration --- Docs/adv_rendering_options.md | 6 +++--- Docs/adv_sumo.md | 8 ++++---- Docs/adv_synchrony_timestep.md | 6 +++--- Docs/build_faq.md | 2 +- Docs/build_linux.md | 4 ++-- Docs/build_windows.md | 4 ++-- Docs/cont_doc_standard.md | 2 +- Docs/ref_sensors.md | 4 ++-- Docs/ros_installation.md | 4 ++-- Docs/start_quickstart.md | 5 +++-- Docs/tuto_A_add_map.md | 2 +- Docs/tuto_A_add_props.md | 2 +- Docs/tuto_A_add_vehicle.md | 2 +- Docs/tuto_G_openstreetmap.md | 2 +- Docs/tuto_G_retrieve_data.md | 20 ++++++++++---------- 15 files changed, 37 insertions(+), 36 deletions(-) diff --git a/Docs/adv_rendering_options.md b/Docs/adv_rendering_options.md index 4272bc167a3..9dd27fa0cb1 100644 --- a/Docs/adv_rendering_options.md +++ b/Docs/adv_rendering_options.md @@ -76,15 +76,15 @@ world.apply_settings(settings) ``` And here is an example on how to disable and then enable rendering using the `config.py`. ```sh -cd PythonAPI/util && ./config.py --no-rendering +cd PythonAPI/util && python3 config.py --no-rendering ``` ```sh -cd PythonAPI/util && ./config.py --rendering +cd PythonAPI/util && python3 config.py --rendering ``` The script `PythonAPI/examples/no_rendering_mode.py` will enable no-rendering mode, and use __Pygame__ to create an aerial view using simple graphics. ```sh -cd PythonAPI/examples && ./no_rendering_mode.py +cd PythonAPI/examples && python3 no_rendering_mode.py ``` !!! Warning diff --git a/Docs/adv_sumo.md b/Docs/adv_sumo.md index 6b0c44dfd52..25a466c6941 100644 --- a/Docs/adv_sumo.md +++ b/Docs/adv_sumo.md @@ -27,13 +27,13 @@ Run a CARLA simulation with __Town04__. cd ~/carla ./CarlaUE4.sh cd PythonAPI/util -python config.py --map Town04 +python3 config.py --map Town04 ``` Then, run the SUMO co-simulation example. ```sh cd ~/carla/Co-Simulation/Sumo -python run_synchronization.py examples/Town04.sumocfg --sumo-gui +python3 run_synchronization.py examples/Town04.sumocfg --sumo-gui ``` !!! Important @@ -83,7 +83,7 @@ Once a simulation is ready and saved as a `.sumocfg`, it is ready to run. There * __`--tls-manager`__ *(default: none)* — Choose which simulator should manage the traffic lights. The other will update those accordingly. The options are `carla`, `sumo`, and `none`. If `none` is chosen, traffic lights will not be synchronized. Each vehicle would only obey the traffic lights in the simulator that spawn it. ```sh -python run_synchronization.py --tls-manager carla --sumo-gui +python3 run_synchronization.py --tls-manager carla --sumo-gui ``` !!! Warning @@ -114,7 +114,7 @@ As the script runs a synchronous simulation, and spawns vehicles in it, the argu # Spawn 10 vehicles, that will be managed by SUMO instead of Traffic Manager. # CARLA in charge of traffic lights. # Open a window for SUMO visualization. -python spawn_sumo_npc.py -n 10 --tls-manager carla --sumo-gui +python3 spawn_sumo_npc.py -n 10 --tls-manager carla --sumo-gui ``` --- diff --git a/Docs/adv_synchrony_timestep.md b/Docs/adv_synchrony_timestep.md index 3ddb424dbfd..4757484912a 100644 --- a/Docs/adv_synchrony_timestep.md +++ b/Docs/adv_synchrony_timestep.md @@ -35,7 +35,7 @@ world.apply_settings(settings) ``` `PythonAPI/util/config.py` sets the time-step using an argument. Zero equals variable time-step. ```sh -cd PythonAPI/util && ./config.py --delta-seconds 0 +cd PythonAPI/util && python3 config.py --delta-seconds 0 ``` ### Fixed time-step @@ -52,7 +52,7 @@ world.apply_settings(settings) This can also be set using the provided script `PythonAPI/util/config.py`. ```sh -cd PythonAPI/util && ./config.py --delta-seconds 0.05 +cd PythonAPI/util && python3 config.py --delta-seconds 0.05 ``` ### Tips when recording the simulation @@ -101,7 +101,7 @@ world.apply_settings(settings) To disable synchronous mode just set the variable to false or use the script `PythonAPI/util/config.py`. ```sh -cd PythonAPI/util && ./config.py --no-sync # Disables synchronous mode +cd PythonAPI/util && python3 config.py --no-sync # Disables synchronous mode ``` Synchronous mode cannot be enabled using the script, only disabled. Enabling the synchronous mode makes the server wait for a client tick. Using this script, the user cannot send ticks when desired. diff --git a/Docs/build_faq.md b/Docs/build_faq.md index 2d4b435ec83..ada389097b6 100644 --- a/Docs/build_faq.md +++ b/Docs/build_faq.md @@ -295,7 +295,7 @@ Go to `Edit/Editor Preferences/Performance` in the editor preferences, and disab Some scripts have requirements. These are listed in files named __Requirements.txt__, in the same path as the script itself. Be sure to check these in order to run the script. The majority of them can be installed with a simple `pip` command. -Sometimes on Windows, scripts cannot run with just `> script_name.py`. Try adding `> python script_name.py`, and make sure to be in the right directory. +Sometimes on Windows, scripts cannot run with just `> script_name.py`. Try adding `> python3 script_name.py`, and make sure to be in the right directory.

    diff --git a/Docs/build_linux.md b/Docs/build_linux.md index a0e666e1df5..79be3de58a9 100644 --- a/Docs/build_linux.md +++ b/Docs/build_linux.md @@ -87,7 +87,7 @@ make PythonAPI # Press play in the Editor to initialize the server, and run an example script to test CARLA. cd PythonAPI/examples -python3 spawn_npc.py +python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) ``` @@ -264,7 +264,7 @@ The project may ask to build other instances such as `UE4Editor-Carla.dll` the f * __make PythonAPI__ compiles the API client, necessary to grant control over the simulation. It is only needed the first time. Remember to run it again when updating CARLA. Scripts will be able to run after this command is executed. The following example will spawn some life into the town. ```sh -make PythonAPI && cd PythonAPI/examples && python3 spawn_npc.py +make PythonAPI && cd PythonAPI/examples && python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) ``` !!! Important If the simulation is running at very low FPS rates, go to `Edit/Editor preferences/Performance` in the UE editor and disable __Use less CPU when in background__. diff --git a/Docs/build_windows.md b/Docs/build_windows.md index 331c34582ab..b7f6fb25145 100644 --- a/Docs/build_windows.md +++ b/Docs/build_windows.md @@ -52,7 +52,7 @@ make launch make PythonAPI # Press play in the Editor to initialize the server, and run an example script to test CARLA. -cd PythonAPI/Examples && python3 spawn_npc.py +cd PythonAPI/Examples && python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) ``` @@ -154,7 +154,7 @@ The project may ask to build other instances such as `UE4Editor-Carla.dll` the f * __make PythonAPI__ compiles the API client, necessary to grant control over the simulation. It is only needed the first time. Remember to run it again when updating CARLA. Scripts will be able to run after this command is executed. The following example will spawn some life into the town. ```sh -make PythonAPI && cd PythonAPI/examples && python3 spawn_npc.py +make PythonAPI && cd PythonAPI/examples && python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) ``` !!! Important If the simulation is running at very low FPS rates, go to `Edit/Editor preferences/Performance` in the UE editor and disable __Use less CPU when in background__. diff --git a/Docs/cont_doc_standard.md b/Docs/cont_doc_standard.md index dd70797ceed..71d4a53574e 100644 --- a/Docs/cont_doc_standard.md +++ b/Docs/cont_doc_standard.md @@ -30,7 +30,7 @@ This will re-generate the respective Markdown files inside `carla/Docs/`, which --- ## Exceptions - * Documentation generated via python scripts like PythonAPI reference + * Documentation generated via Python scripts like PythonAPI reference Handy markdown [cheatsheet][cheatlink]. diff --git a/Docs/ref_sensors.md b/Docs/ref_sensors.md index fd6b71b3489..9be199a2a97 100644 --- a/Docs/ref_sensors.md +++ b/Docs/ref_sensors.md @@ -495,7 +495,7 @@ For a better realism, points in the cloud can be dropped off. This is an easy wa Additionally, the `noise_stddev` attribute makes for a noise model to simulate unexpected deviations that appear in real-life sensors. For positive values, each point is randomly perturbed along the vector of the laser ray. The result is a LIDAR sensor with perfect angular positioning, but noisy distance measurement. -The rotation of the LIDAR can be tuned to cover a specific angle on every simulation step (using a [fixed time-step](adv_synchrony_timestep.md)). For example, to rotate once per step (full circle output, as in the picture below), the rotation frequency and the simulated FPS should be equal.
    __1.__ Set the sensor's frequency `sensors_bp['lidar'][0].set_attribute('rotation_frequency','10')`.
    __2.__ Run the simulation using `python config.py --fps=10`. +The rotation of the LIDAR can be tuned to cover a specific angle on every simulation step (using a [fixed time-step](adv_synchrony_timestep.md)). For example, to rotate once per step (full circle output, as in the picture below), the rotation frequency and the simulated FPS should be equal.
    __1.__ Set the sensor's frequency `sensors_bp['lidar'][0].set_attribute('rotation_frequency','10')`.
    __2.__ Run the simulation using `python3 config.py --fps=10`. ![LidarPointCloud](img/lidar_point_cloud.jpg) @@ -1329,7 +1329,7 @@ for detection in semantic_lidar_measurement: The rotation of the LIDAR can be tuned to cover a specific angle on every simulation step (using a [fixed time-step](adv_synchrony_timestep.md)). For example, to rotate once per step (full circle output, as in the picture below), the rotation frequency and the simulated FPS should be equal.
    __1.__ Set the sensor's frequency `sensors_bp['lidar'][0].set_attribute('rotation_frequency','10')`.
    -__2.__ Run the simulation using `python config.py --fps=10`. +__2.__ Run the simulation using `python3 config.py --fps=10`. ![LidarPointCloud](img/semantic_lidar_point_cloud.jpg) diff --git a/Docs/ros_installation.md b/Docs/ros_installation.md index 6102ac91e2b..26f96ae6da2 100644 --- a/Docs/ros_installation.md +++ b/Docs/ros_installation.md @@ -110,7 +110,7 @@ roslaunch carla_ros_bridge carla_ros_bridge_with_example_ego_vehicle.launch The path to CARLA Python is missing. The apt installation does this automatically, but it may be missing for other installations. Execute the following command with the complete path to the .egg file (included). Use the one supported by the Python version installed. -
    +

    Note: .egg files may be either in `/PythonAPI/` or `/PythonAPI/dist/` depending on the CARLA installation. ```sh @@ -119,7 +119,7 @@ The path to CARLA Python is missing. The apt installation does this automaticall Import CARLA from Python and wait for a sucess message to check the installation. ```sh -python -c 'import carla;print("Success")' +python3 -c 'import carla;print("Success")' ``` diff --git a/Docs/start_quickstart.md b/Docs/start_quickstart.md index d121e1f4d73..2d9ee32404a 100644 --- a/Docs/start_quickstart.md +++ b/Docs/start_quickstart.md @@ -47,7 +47,7 @@ cd /opt/carla-simulator # Run a script to test CARLA. cd PythonAPI/examples -python3 spawn_npc.py +python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) ``` @@ -146,8 +146,9 @@ Now it is time to start running scripts. The following example will spawn some l # Go to the folder containing example scripts > cd PythonAPI/examples -> python3 spawn_npc.py +> python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) ``` + #### Command-line options There are some configuration options available when launching CARLA. diff --git a/Docs/tuto_A_add_map.md b/Docs/tuto_A_add_map.md index 387fac0f734..e9a54d0b346 100644 --- a/Docs/tuto_A_add_map.md +++ b/Docs/tuto_A_add_map.md @@ -85,7 +85,7 @@ chmod 777 input_folder __2. Run the script to cook the map.__ In the folder `~/carla/Util/Docker` there is a script that connects with the Docker image previously created, and makes the ingestion automatically. It only needs the path for the input and output files, and the name of the package to be ingested. If no `.json` is provided, the name must be `map_package`. ```sh -python docker_tools.py --input ~/path_to_input_folder --output ~/path_to_output_folder --packages map_package +python3 docker_tools.py --input ~/path_to_input_folder --output ~/path_to_output_folder --packages map_package ``` !!! Warning If the argument `--package ` is not provided, the Docker will make a package of CARLA. diff --git a/Docs/tuto_A_add_props.md b/Docs/tuto_A_add_props.md index 88ec4103dba..c3af52f4237 100644 --- a/Docs/tuto_A_add_props.md +++ b/Docs/tuto_A_add_props.md @@ -119,7 +119,7 @@ __1. Build a Docker image of Unreal Engine.__ Follow [these instructions](https: __2. Run the script to cook the props.__ In the folder `~/carla/Util/Docker` there is a script that connects with the Docker image previously created, and makes the ingestion automatically. It only needs the path for the input and output files, and the name of the package to be ingested. ```sh -python docker_tools.py --input ~/path_to_package --output ~/path_for_output_assets --package=Package01 +python3 docker_tools.py --input ~/path_to_package --output ~/path_for_output_assets --package=Package01 ``` __3. Locate the package__. The Docker should have generated the package `Package01.tar.gz` in the output path. This is the standalone package for the assets. diff --git a/Docs/tuto_A_add_vehicle.md b/Docs/tuto_A_add_vehicle.md index d8bad35064c..8c0d09e3958 100644 --- a/Docs/tuto_A_add_vehicle.md +++ b/Docs/tuto_A_add_vehicle.md @@ -111,7 +111,7 @@ __4. Export the result__. Select all the meshes and the base of the skeleton a * __11. Test the vehicle__. Launch CARLA, open a terminal in `PythonAPI/examples` and run the following command. ```sh -python manual_control.py --filter # The name used in step 10.2 +python3 manual_control.py --filter # The name used in step 10.2 ``` --- diff --git a/Docs/tuto_G_openstreetmap.md b/Docs/tuto_G_openstreetmap.md index ebfd494719c..c95a591a755 100644 --- a/Docs/tuto_G_openstreetmap.md +++ b/Docs/tuto_G_openstreetmap.md @@ -91,7 +91,7 @@ world = client.generate_opendrive_world( __b) Using `config.py`__ — The script can load an OpenStreetMap file directly into CARLA using a new argument. ``` -config.py --osm-file=/path/to/OSM/file +python3 config.py --osm-file=/path/to/OSM/file ``` !!! Warning [client.generate_opendrive_world()](python_api.md#carla.Client.generate_opendrive_world) requires the __content of the OpenDRIVE file parsed as string__, and allows parameterization. On the contrary, __`config.py`__ script needs __the path to the `.xodr` file__ and always uses default parameters. diff --git a/Docs/tuto_G_retrieve_data.md b/Docs/tuto_G_retrieve_data.md index a70262c0228..be168678b81 100644 --- a/Docs/tuto_G_retrieve_data.md +++ b/Docs/tuto_G_retrieve_data.md @@ -87,7 +87,7 @@ Open a new terminal. Change the map using the __config.py__ script. ``` cd /opt/carla/PythonAPI/utils -./config.py --map Town01 +python3 config.py --map Town01 ``` This script can enable different settings. Some of them will be mentioned during the tutorial, others will not. Hereunder there is a brief summary. @@ -133,14 +133,14 @@ Each town is loaded with a specific weather that fits it, however this can be se ```sh cd /opt/carla/PythonAPI/examples -python dynamic_weather.py --speed 1.0 +python3 dynamic_weather.py --speed 1.0 ``` * __To set custom conditions__. Use the script __environment.py__. There are quite a lot of possible settings. Take a look at the optional arguments, and the documentation for [carla.WeatherParameters](python_api.md#carla.WeatherParameters). ```sh cd /opt/carla/PythonAPI/util -python environment.py --clouds 100 --rain 80 --wetness 100 --puddles 60 --wind 80 --fog 50 +python3 environment.py --clouds 100 --rain 80 --wetness 100 --puddles 60 --wind 80 --fog 50 ```
    @@ -182,7 +182,7 @@ Open a new terminal, and run __spawn_npc.py__ to spawn vehicles and walkers. Let ```sh cd /opt/carla/PythonAPI/examples -python spawn_npc.py -n 50 -w 50 --safe +python3 spawn_npc.py -n 50 -w 50 --safe ```
    Optional arguments in spawn_npc.py @@ -228,7 +228,7 @@ echo "export SUMO_HOME=/usr/share/sumo" >> ~/.bashrc && source ~/.bashrc * With the CARLA server on, run the [SUMO-CARLA synchrony script](https://github.com/carla-simulator/carla/blob/master/Co-Simulation/Sumo/run_synchronization.py). ```sh cd ~/carla/Co-Simulation/Sumo -python run_synchronization.py examples/Town01.sumocfg --sumo-gui +python3 run_synchronization.py examples/Town01.sumocfg --sumo-gui ``` * A SUMO window should have opened. __Press Play__ in order to start traffic in both simulations. ``` @@ -632,7 +632,7 @@ The same `config.py` used to [set the map](#map-setting) can disable rendering, ``` cd /opt/carla/PythonAPI/utils -./config.py --no-rendering --delta-seconds 0.05 # Never greater than 0.1s +python3 config.py --no-rendering --delta-seconds 0.05 # Never greater than 0.1s ``` !!! Warning @@ -644,12 +644,12 @@ The script `PythonAPI/examples/no_rendering_mode.py` provides an overview of the ``` cd /opt/carla/PythonAPI/examples -python manual_control.py +python3 manual_control.py ``` ``` cd /opt/carla/PythonAPI/examples -python no_rendering_mode.py --no-rendering +python3 no_rendering_mode.py --no-rendering ```
    @@ -712,7 +712,7 @@ while True: ``` cd /opt/carla/PythonAPI/examples -python manual_control.py +python3 manual_control.py ``` !!! Note @@ -742,7 +742,7 @@ It is time to run a new simulation. To reenact the simulation, [choose a fragment](#choose-a-fragment) and run the script containing the code for the playback. ```sh -python tuto_replay.py +python3 tuto_replay.py ``` ### Query the events From 95f9c59e342154d81c57e4c4b8cc176e65598454 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Thu, 17 Sep 2020 12:10:51 +0200 Subject: [PATCH 069/179] First iteration --- Docs/build_linux.md | 165 +++++++++++++++++++++++++----------------- Docs/build_windows.md | 75 +++++++++++-------- 2 files changed, 142 insertions(+), 98 deletions(-) diff --git a/Docs/build_linux.md b/Docs/build_linux.md index 79be3de58a9..c0a3175b151 100644 --- a/Docs/build_linux.md +++ b/Docs/build_linux.md @@ -12,14 +12,7 @@ * [Set the environment variable](#set-the-environment-variable) * [make CARLA](#make-carla) -The build process can be quite long and tedious. The **[F.A.Q.](build_faq.md)** section contains the most common issues and solutions that appear during the installation. However, the CARLA forum is open for anybody to post unexpected issues, doubts or suggestions. There is a specific section for installation issues on Linux. Feel free to login and become part of the community. - - +The build process can be quite long and tedious. The **[F.A.Q.](build_faq.md)** page offers solution for the most common complications. Alternatively, use the [CARLA forum](https://forum.carla.org/c/installation-issues/linux) to post any unexpected issues that may occur. --- ## Linux build command summary @@ -28,9 +21,10 @@ CARLA forum Show command lines to build on Linux ```sh -# Make sure to meet the minimum requirements and read the documentation to understand each step. +# Make sure to meet the minimum requirements +# Read the complete documentation to understand each step -# Install dependencies. +# Install dependencies sudo apt-get update && sudo apt-get install wget software-properties-common && sudo add-apt-repository ppa:ubuntu-toolchain-r/test && @@ -38,56 +32,61 @@ wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - && sudo apt-add-repository "deb http://apt.llvm.org/$(lsb_release -c --short)/ llvm-toolchain-$(lsb_release -c --short)-8 main" && sudo apt-get update -# Additional dependencies for Ubuntu 18.04. +# Additional dependencies for Ubuntu 18.04 sudo apt-get install build-essential clang-8 lld-8 g++-7 cmake ninja-build libvulkan1 python python-pip python-dev python3-dev python3-pip libpng-dev libtiff5-dev libjpeg-dev tzdata sed curl unzip autoconf libtool rsync libxml2-dev libxerces-c-dev && pip2 install --user setuptools && pip3 install --user -Iv setuptools==47.3.1 -# Additional dependencies for previous Ubuntu versions. +# Additional dependencies for previous Ubuntu versions sudo apt-get install build-essential clang-8 lld-8 g++-7 cmake ninja-build libvulkan1 python python-pip python-dev python3-dev python3-pip libpng16-dev libtiff5-dev libjpeg-dev tzdata sed curl unzip autoconf libtool rsync libxml2-dev libxerces-c-dev && pip2 install --user setuptools && pip3 install --user -Iv setuptools==47.3.1 && pip2 install --user distro && pip3 install --user distro -# Change default clang version. +# Change default clang version sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/lib/llvm-8/bin/clang++ 180 && sudo update-alternatives --install /usr/bin/clang clang /usr/lib/llvm-8/bin/clang 180 -# Get a GitHub and a UE account, and link both. -# Install git. +# Get a GitHub and a UE account, and link both +# Install git -# Download Unreal Engine 4.24. +# Download Unreal Engine 4.24 git clone --depth=1 -b 4.24 https://github.com/EpicGames/UnrealEngine.git ~/UnrealEngine_4.24 cd ~/UnrealEngine_4.24 # Download and install the UE patch -wget https://carla-releases.s3.eu-west-3.amazonaws.com/Linux/UE_Patch/430667-13636743-patch.txt ~/430667-13636743-patch.txt -patch --strip=4 < ~/430667-13636743-patch.txt +wget https://carla-releases.s3.eu-west-3.amazonaws.com/Linux/UE_Patch/430667-13636743-patch.txt 430667-13636743-patch.txt +patch --strip=4 < 430667-13636743-patch.txt # Build UE ./Setup.sh && ./GenerateProjectFiles.sh && make -# Open the UE Editor to check everything works properly. +# Open the UE Editor to check everything works properly cd ~/UnrealEngine_4.24/Engine/Binaries/Linux && ./UE4Editor -# Clone the CARLA repository. +# Clone the CARLA repository git clone https://github.com/carla-simulator/carla -# Get the CARLA assets. +# Get the CARLA assets cd ~/carla ./Update.sh -# Set the environment variable. +# Set the environment variable export UE4_ROOT=~/UnrealEngine_4.24 -# make the CARLA server and the CARLA client. -make launch +# make the CARLA client and the CARLA server make PythonAPI +make launch -# Press play in the Editor to initialize the server, and run an example script to test CARLA. +# Press play in the Editor to initialize the server +# Run example scripts to test CARLA +# Terminal A +cd PythonAPI/examples +python3 spawn_npc.py +# Terminal B cd PythonAPI/examples -python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) +python3 dynamic_weather.py # Support for Python2 was provided until 0.9.10 (not included) ```
    @@ -96,8 +95,8 @@ python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not includ ### System specifics -* __Ubuntu 18.04.__ CARLA provides support for previous Ubuntu versions up to 16.04. **However** proper compilers are needed for UE to work properly. The required dependencies for both Ubuntu 18.04 and previous versions are listed below. Make sure to install the ones corresponding to the system. -* __30GB disk space.__ Installing all the software needed and CARLA itself will require quite a lot of space, especially Unreal Engine. Make sure to have around 30/50GB of free disk space. +* __Ubuntu 18.04.__ CARLA provides support for previous Ubuntu versions up to 16.04. **However** proper compilers are needed for UE to work properly. Dependencies for Ubuntu 18.04 and previous versions are listed separatedly below. Make sure to install the ones corresponding to your system. +* __30GB disk space.__ The complete build will require quite a lot of space, especially Unreal Engine. Make sure to have around 30/50GB of free disk space. * __An adequate GPU.__ CARLA aims for realistic simulations, so the server needs at least a 4GB GPU. A dedicated GPU is highly recommended for machine learning. * __Two TCP ports and good internet connection.__ 2000 and 2001 by default. Be sure neither the firewall nor any other application block these. @@ -115,8 +114,8 @@ sudo apt-add-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 sudo apt-get update ``` -!!! Important - The following commands differ depending on the Ubuntu version. While the only change is `libpng16-dev` becoming `libpng-dev`, the full set of commands is here twice to ease the copy. +!!! Warning + The following commands depend on your Ubuntu version. Make sure to choose accordingly. __Ubuntu 18.04__. ```sh @@ -135,7 +134,8 @@ pip2 install --user distro && pip3 install --user distro ``` -To avoid compatibility issues between Unreal Engine and the CARLA dependencies, it is recommended to use the same compiler version and C++ runtime library to compile everything. The CARLA team uses clang-8 and LLVM's libc++. Change the default clang version to compile Unreal Engine and the CARLA dependencies. +__All Ubuntu systems__. +To avoid compatibility issues between Unreal Engine and the CARLA dependencies, use the same compiler version and C++ runtime library to compile everything. The CARLA team uses clang-8 and LLVM's libc++. Change the default clang version to compile Unreal Engine and the CARLA dependencies. ```sh sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/lib/llvm-8/bin/clang++ 180 && @@ -145,9 +145,13 @@ sudo update-alternatives --install /usr/bin/clang clang /usr/lib/llvm-8/bin/clan --- ## GitHub -A [GitHub](https://github.com/) account will be needed, as CARLA content is organized in different repositories in there. Also, [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) will be used in this build guide when facilitating commands to be run in terminal. +__1.__ Create a [GitHub](https://github.com/) account. CARLA is organized in different GitHub repositories, so an account will be needed to clone said repositories. + +__2.__ Install [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) to manage the repositories via terminal. -In order to access the Unreal Engine repositories, which are set to private, create an [Unreal Engine](https://www.unrealengine.com/en-US/feed) account and connect it to a GitHub account. To do so, there is a section in Unreal Engine's profile settings under the name of __Connected accounts__. [Here](https://www.unrealengine.com/en-US/blog/updated-authentication-process-for-connecting-epic-github-accounts) is a brief explanation just in case. +__3.__ Create an [Unreal Engine](https://www.unrealengine.com/en-US/feed) account to access the Unreal Engine repositories, which are set to private. + +__4.__ Connect both your GitHub and Unreal Engine accounts. Go to your personal settings in there is a section in [Unreal Engine](https://www.unrealengine.com/en-US/)'s website. Click on `Connections > Accounts`, and link both accounts. [Here](https://www.unrealengine.com/en-US/blog/updated-authentication-process-for-connecting-epic-github-accounts) is a brief explanation just in case. !!! Warning New Unreal Engine accounts need activation. After creating the account, a verification mail will be sent. Check it out, or the UE repository will be shown as non-existent in the following steps. @@ -155,40 +159,41 @@ In order to access the Unreal Engine repositories, which are set to private, cre --- ## Unreal Engine -The current version of CARLA runs on __Unreal Engine 4.24__ only. The path is irrelevant, but for the sake of this tutorial, installation will be done under `~/UnrealEngine_4.24`. If the path chosen differs, remember to change it accordingly when running the commands on terminal. +The current version of CARLA runs on __Unreal Engine 4.24__ only. In this guide, the installation will be done in `~/UnrealEngine_4.24`, but the path can be changed. If your path is different, change the following commands accordingly. !!! Note - Alternatively, there is this [guide](https://docs.unrealengine.com/en-US/Platforms/Linux/BeginnerLinuxDeveloper/SettingUpAnUnrealWorkflow/index.html) to build UE on Linux. When consulting it, remember that CARLA will need the __4.24 release__, not the latest. + Alternatively to this section, there is another [guide](https://docs.unrealengine.com/en-US/Platforms/Linux/BeginnerLinuxDeveloper/SettingUpAnUnrealWorkflow/index.html) to build UE on Linux. When consulting it, remember that CARLA will need the __4.24 release__, not the latest. -Clone the content for Unreal Engine 4.24 in a local computer. +__1.__ Clone the content for Unreal Engine 4.24 in your local computer. ```sh git clone --depth=1 -b 4.24 https://github.com/EpicGames/UnrealEngine.git ~/UnrealEngine_4.24 ``` -Get into said folder. Remember, this is the path where UE4.24 has been cloned. +__2.__ Get into the directory where UE4.24 has been cloned. ```sh cd ~/UnrealEngine_4.24 ``` -Get a patch for Unreal Engine. The patch fixes some Vulkan visualization issues that may occur when changing the map. Download and install it with the following commands. +__3.__ Download a patch for Unreal Engine. This patch fixes some Vulkan visualization issues that may occur when changing the map. Download and install it with the following commands. ```sh -wget https://carla-releases.s3.eu-west-3.amazonaws.com/Linux/UE_Patch/430667-13636743-patch.txt ~/430667-13636743-patch.txt -patch --strip=4 < ~/430667-13636743-patch.txt +wget https://carla-releases.s3.eu-west-3.amazonaws.com/Linux/UE_Patch/430667-13636743-patch.txt 430667-13636743-patch.txt +patch --strip=4 < 430667-13636743-patch.txt ``` -Make the build. +!!! Warning + If UE has already been built, install the patch, and make the build again. + + +__4.__ Make the build. This may take an hour or two depending on your system. ```sh ./Setup.sh && ./GenerateProjectFiles.sh && make ``` -!!! Warning - If UE has already been built, install the patch and make the build again. - -Unreal Engine should be installed in the system. Run `Engine/Binaries/Linux/UE4Editor.sh` to open the Editor and check it out. +__5.__ Open the Editor to check that UE has been properly installed. ```sh cd ~/UnrealEngine_4.24/Engine/Binaries/Linux && ./UE4Editor ``` -In case something went wrong, it is related with Unreal Engine There is not much CARLA can do about it. However, the [build documentation](https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Build/BatchFiles/Linux/README.md) provided by Unreal Engine may be helpful. +Any issues this far are related with Unreal Engine. There is not much CARLA can do about it. However, the [build documentation](https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Build/BatchFiles/Linux/README.md) provided by Unreal Engine may be helpful. --- ## CARLA build @@ -210,31 +215,33 @@ The system should be ready to start building CARLA. Just for clarity, a brief su CARLA repository

    -The official repository of the project. Either download and extract it or clone it using the following command line. +The official repository of the project. Either download and extract it, or clone the repository with the following command line. ```sh git clone https://github.com/carla-simulator/carla ``` -Now the latest content for the project, known as `master` branch in the repository, has been copied in local. +Now the latest state of the simulator, known as `master` branch in the repository, has been copied in local. Here is brief introduction to the most relevant branches of the repository. Remember that you can change and check your branches with the command `git branch`. + +* __`master` branch__ — Latest fixes and features that have been tested. These will be featured in the next CARLA release. +* __`dev` branch__ — Latest fixes and features still in development and testing. This branch will be merged with `master` when the time for a new release comes. +* __`stable` branch__ — Latest version of CARLA tagged as stable. Previous CARLA versions also have their own branch. -!!! Note - The `master` branch contains the latest fixes and features. Stable code is inside the `stable` and previous CARLA versions have their own branch. Always remember to check the current branch in git with the command `git branch`. ### Get assets -Only the assets package is yet to be donwloaded. These are stored separately to make the repository a bit lighter. CARLA cannot be built without the assets. There is a script that downloads and extracts the latest content version. The package is >3GB, so downloading it may take some time. +Download the assets, as they are necessary to run CARLA. These are stored in a separated package to reduce the size of the build. A script downloads and extracts the latest stable assets automatically. The package is >3GB, so the download may take some time. -Get into the root carla folder. The path should correspond with the repository just cloned: +__1.__ Get into your root carla directory. The path should correspond with the repository just cloned. ```sh cd ~/carla ``` -Run the script to get the assets. +__2.__ Run the script to get the assets. ```sh ./Update.sh ``` !!! Important - To get the assets currently in development, visit [Update CARLA](build_update.md#get-development-assets) and read __Get development assets__. + To download the assets currently in development, visit [Update CARLA](build_update.md#get-development-assets) and read __Get development assets__. ### Set the environment variable @@ -245,26 +252,48 @@ This is necessary for CARLA to find the Unreal Engine 4.24 installation folder. export UE4_ROOT=~/UnrealEngine_4.24 ``` -The variable should be added to `~/.bashrc` or `~/.profile` to be set persistently session-wide. Otherwise, it will only be accessible from the current shell. +The variable should be added to `~/.bashrc` or `~/.profile` to be set persistently session-wide. Otherwise, it will only be accessible from the current shell. To do this, follow these steps. + +__1.__ Open `~/.bashrc`. +```sh +gedit ~/.bashrc +``` + +__2.__ Write the environment variable in the `~/.bashrc` file: `export UE4_ROOT=~/UnrealEngine_4.24` + + +__3.__ Save the file and reset the terminal. + + ### make CARLA The last step is to finally build CARLA. There are different `make` commands to build the different modules. All of them run in the root CARLA folder. !!! Warning - Make sure to run `make launch` to prepare the server and `make PythonAPI` for the client. + Make sure to run `make PythonAPI` to prepare the client and `make launch` for the server. Alternatively `make LibCarla` will prepare the CARLA library to be imported anywhere. -* __make launch__ compiles the server simulator and launches Unreal Engine. Press **Play** to start the spectator view and close the editor window to exit. Camera can be moved with `WASD` keys and rotated by clicking the scene while moving the mouse around. +* __make PythonAPI__ compiles the API client, necessary to grant control over the simulation. It is only needed the first time. Remember to run it again when updating CARLA. Scripts will be able to run after this command is executed. +```sh +make PythonAPI +``` + +* __make launch__ compiles the server simulator and launches Unreal Engine. Press **Play** to start the spectator view and close the editor window to exit. Camera can be moved with `WASD` keys and rotated by clicking the scene while moving the mouse around. ```sh make launch ``` The project may ask to build other instances such as `UE4Editor-Carla.dll` the first time. Agree in order to open the project. During the first launch, the editor may show warnings regarding shaders and mesh distance fields. These take some time to be loaded and the city will not show properly until then. -* __make PythonAPI__ compiles the API client, necessary to grant control over the simulation. It is only needed the first time. Remember to run it again when updating CARLA. Scripts will be able to run after this command is executed. The following example will spawn some life into the town. + +Finally, let's test the simulator. Inside `PythonAPI/examples` and `PythonAPI/util` there are some example scripts that may be especially useful for starteres. The following commands will spawn some life into the town, and create a weather cycle. Each script should be run in one terminal ```sh -make PythonAPI && cd PythonAPI/examples && python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) +# Support for Python2 was provided until 0.9.10 (not included) +# Terminal A +cd PythonAPI/examples && python3 spawn_npc.py +# Terminal B +cd ~/carla/PythonAPI/examples && python3 dynamic_weather.py ``` !!! Important If the simulation is running at very low FPS rates, go to `Edit/Editor preferences/Performance` in the UE editor and disable __Use less CPU when in background__. @@ -298,21 +327,25 @@ Now CARLA is ready to go. Here is a brief summary of the most useful `make` comm make rebuild -make clean and make launch both in one command. +make clean and make launch both in one command. --- -
    -Keep reading this section to learn how to update the build or take some first steps in CARLA. + +Read the **[F.A.Q.](build_faq.md)** page or post in the [CARLA forum](https://forum.carla.org/c/installation-issues/linux) for any issues regarding this guide. + +Some recommendations after finishing the build. Learn how to update the CARLA build or take your first steps in the simulation, and learn some core concepts. diff --git a/Docs/build_windows.md b/Docs/build_windows.md index b7f6fb25145..0a04e2ea92d 100644 --- a/Docs/build_windows.md +++ b/Docs/build_windows.md @@ -13,14 +13,7 @@ * [Set the environment variable](#set-the-environment-variable) * [make CARLA](#make-carla) -The build process can be quite long and tedious. The **[F.A.Q.](build_faq.md)** section contains the most common issues and solutions that appear during the installation. However, the CARLA forum is open for anybody to post unexpected issues, doubts or suggestions. There is a specific section for installation issues on Linux. Feel free to login and become part of the community. - - +The build process can be quite long and tedious. The **[F.A.Q.](build_faq.md)** page offers solution for the most common complications. Alternatively, use the [CARLA forum](https://forum.carla.org/c/installation-issues/linux) to post any unexpected issues that may occur. --- ## Windows build command summary @@ -47,12 +40,17 @@ CARLA forum # Clone the CARLA repository git clone https://github.com/carla-simulator/carla -# make the CARLA server and the CARLA client -make launch +# make the CARLA client and the CARLA server make PythonAPI +make launch -# Press play in the Editor to initialize the server, and run an example script to test CARLA. -cd PythonAPI/Examples && python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) +# Press play in the Editor to initialize the server, and run example scripts to test CARLA. +# Terminal A +cd PythonAPI/examples +python3 spawn_npc.py +# Terminal B +cd PythonAPI/examples +python3 dynamic_weather.py # Support for Python2 was provided until 0.9.10 (not included) ```
    @@ -137,29 +135,40 @@ __2. On the `Advanced` panel__ open `Environment Variables...`. __3. Click `New...`__ to create the variable. __4. Name the variable as `UE4_ROOT`__ and choose the path to the installation folder of the desire UE4 installation. + ### make CARLA -The last step is to finally build CARLA. There are different `make` commands to build the different modules. All of them run in the root CARLA folder. +The last step is to finally build CARLA. There are different `make` commands to build the different modules. All of them run in the root CARLA folder. !!! Warning - Make sure to run `make launch` to prepare the server and `make PythonAPI` for the client. - Alternatively `make LibCarla` will prepare the CARLA library to be imported anywhere. + Make sure to run `make PythonAPI` to prepare the client and `make launch` for the server. + Alternatively `make LibCarla` will prepare the CARLA library to be imported anywhere. + +* __make PythonAPI__ compiles the API client, necessary to grant control over the simulation. It is only needed the first time. Remember to run it again when updating CARLA. Scripts will be able to run after this command is executed. +```sh +make PythonAPI +``` * __make launch__ compiles the server simulator and launches Unreal Engine. Press **Play** to start the spectator view and close the editor window to exit. Camera can be moved with `WASD` keys and rotated by clicking the scene while moving the mouse around. ```sh make launch -``` -The project may ask to build other instances such as `UE4Editor-Carla.dll` the first time. Agree in order to open the project. During the first launch, the editor may show warnings regarding shaders and mesh distance fields. These take some time to be loaded and the city will not show properly until then. +``` +The project may ask to build other instances such as `UE4Editor-Carla.dll` the first time. Agree in order to open the project. During the first launch, the editor may show warnings regarding shaders and mesh distance fields. These take some time to be loaded and the city will not show properly until then. -* __make PythonAPI__ compiles the API client, necessary to grant control over the simulation. It is only needed the first time. Remember to run it again when updating CARLA. Scripts will be able to run after this command is executed. The following example will spawn some life into the town. + +Finally, let's test the simulator. Inside `PythonAPI/examples` and `PythonAPI/util` there are some example scripts that may be especially useful for starteres. The following commands will spawn some life into the town, and create a weather cycle. Each script should be run in one terminal ```sh -make PythonAPI && cd PythonAPI/examples && python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) -``` +# Support for Python2 was provided until 0.9.10 (not included) +# Terminal A +cd PythonAPI/examples && python3 spawn_npc.py +# Terminal B +cd ~/carla/PythonAPI/examples && python3 dynamic_weather.py +``` !!! Important - If the simulation is running at very low FPS rates, go to `Edit/Editor preferences/Performance` in the UE editor and disable __Use less CPU when in background__. + If the simulation is running at very low FPS rates, go to `Edit/Editor preferences/Performance` in the UE editor and disable __Use less CPU when in background__. -Now CARLA is ready to go. Here is a brief summary of the most useful `make` commands available. +Now CARLA is ready to go. Here is a brief summary of the most useful `make` commands available. @@ -167,8 +176,7 @@ Now CARLA is ready to go. Here is a brief summary of the most useful `make` comm - + @@ -189,25 +197,28 @@ Now CARLA is ready to go. Here is a brief summary of the most useful `make` comm - +
    Description
    -make help make help Prints all available commands.
    make rebuildmake clean and make launch both in one command.make clean and make launch both in one command.
    --- -
    -Keep reading this section to learn how to update the build or take some first steps in CARLA. + +Read the **[F.A.Q.](build_faq.md)** page or post in the [CARLA forum](https://forum.carla.org/c/installation-issues/linux) for any issues regarding this guide. + +Some recommendations after finishing the build. Learn how to update the CARLA build or take your first steps in the simulation, and learn some core concepts. +

    + +First steps +

    + + From 681d2adc000bab9574a2b14fc48ea5bf8da0abd4 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Thu, 17 Sep 2020 13:46:56 +0200 Subject: [PATCH 070/179] New iteration on B comments --- Docs/build_linux.md | 8 +++++--- Docs/build_windows.md | 13 +++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Docs/build_linux.md b/Docs/build_linux.md index c0a3175b151..60dd0573e85 100644 --- a/Docs/build_linux.md +++ b/Docs/build_linux.md @@ -286,14 +286,16 @@ make launch The project may ask to build other instances such as `UE4Editor-Carla.dll` the first time. Agree in order to open the project. During the first launch, the editor may show warnings regarding shaders and mesh distance fields. These take some time to be loaded and the city will not show properly until then. -Finally, let's test the simulator. Inside `PythonAPI/examples` and `PythonAPI/util` there are some example scripts that may be especially useful for starteres. The following commands will spawn some life into the town, and create a weather cycle. Each script should be run in one terminal +Finally, let's test the simulator. Inside `PythonAPI/examples` and `PythonAPI/util` there are some example scripts that may be especially useful for starters. The following commands will spawn some life into the town, and create a weather cycle. Each script should be run in one terminal ```sh # Support for Python2 was provided until 0.9.10 (not included) # Terminal A -cd PythonAPI/examples && python3 spawn_npc.py +cd PythonAPI/examples +python3 spawn_npc.py # Terminal B -cd ~/carla/PythonAPI/examples && python3 dynamic_weather.py +cd PythonAPI/examples +python3 dynamic_weather.py ``` !!! Important If the simulation is running at very low FPS rates, go to `Edit/Editor preferences/Performance` in the UE editor and disable __Use less CPU when in background__. diff --git a/Docs/build_windows.md b/Docs/build_windows.md index 0a04e2ea92d..f8f9ed470ab 100644 --- a/Docs/build_windows.md +++ b/Docs/build_windows.md @@ -20,10 +20,9 @@ The build process can be quite long and tedious. The **[F.A.Q.](build_faq.md)**
    Show command lines to build on Windows +
    +To execute the make commands below, you must use the Visual Studio 2017 native console x64 with administrator rights, otherwise you may be getting permission errors. -!!! Important - To execute the ```make``` commands below, you **must** use the Visual Studio 2017 native console x64 **with** administrator rights, otherwise you may be getting permission errors. - ```sh # Make sure to meet the minimum requirements. @@ -156,14 +155,16 @@ make launch The project may ask to build other instances such as `UE4Editor-Carla.dll` the first time. Agree in order to open the project. During the first launch, the editor may show warnings regarding shaders and mesh distance fields. These take some time to be loaded and the city will not show properly until then. -Finally, let's test the simulator. Inside `PythonAPI/examples` and `PythonAPI/util` there are some example scripts that may be especially useful for starteres. The following commands will spawn some life into the town, and create a weather cycle. Each script should be run in one terminal +Finally, let's test the simulator. Inside `PythonAPI/examples` and `PythonAPI/util` there are some example scripts that may be especially useful for starters. The following commands will spawn some life into the town, and create a weather cycle. Each script should be run in one terminal ```sh # Support for Python2 was provided until 0.9.10 (not included) # Terminal A -cd PythonAPI/examples && python3 spawn_npc.py +cd PythonAPI/examples +python3 spawn_npc.py # Terminal B -cd ~/carla/PythonAPI/examples && python3 dynamic_weather.py +cd PythonAPI/examples +python3 dynamic_weather.py ``` !!! Important If the simulation is running at very low FPS rates, go to `Edit/Editor preferences/Performance` in the UE editor and disable __Use less CPU when in background__. From fd0e3f00a7bfb1da0ea5767caffb1a32c36118be Mon Sep 17 00:00:00 2001 From: doterop Date: Wed, 16 Sep 2020 18:13:23 +0200 Subject: [PATCH 071/179] Cleaned atlas code and rolled back to OnEndFrameRT SendPixels --- .../Source/Carla/Game/CarlaGameInstance.h | 4 + .../Source/Carla/Game/CarlaGameModeBase.cpp | 147 ------------------ .../Source/Carla/Game/CarlaGameModeBase.h | 94 ----------- .../Carla/Source/Carla/Sensor/DepthCamera.cpp | 11 +- .../Carla/Source/Carla/Sensor/DepthCamera.h | 2 +- .../Carla/Source/Carla/Sensor/PixelReader.cpp | 61 +------- .../Carla/Source/Carla/Sensor/PixelReader.h | 5 - .../Carla/Sensor/SceneCaptureCamera.cpp | 11 +- .../Source/Carla/Sensor/SceneCaptureCamera.h | 2 +- .../Carla/Sensor/SceneCaptureSensor.cpp | 87 +---------- .../Source/Carla/Sensor/SceneCaptureSensor.h | 28 +--- .../Sensor/SemanticSegmentationCamera.cpp | 11 +- .../Carla/Sensor/SemanticSegmentationCamera.h | 2 +- 13 files changed, 23 insertions(+), 442 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameInstance.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameInstance.h index c8331b393ec..9069249d7ef 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameInstance.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameInstance.h @@ -11,6 +11,10 @@ #include "Carla/Game/CarlaEngine.h" #include "Carla/Server/CarlaServer.h" +#include +#include +#include + #include "CarlaGameInstance.generated.h" class UCarlaSettings; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp index b0f8c35fa7f..47a68e63468 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp @@ -42,57 +42,6 @@ ACarlaGameModeBase::ACarlaGameModeBase(const FObjectInitializer& ObjectInitializ CarlaSettingsDelegate = CreateDefaultSubobject(TEXT("CarlaSettingsDelegate")); } -void ACarlaGameModeBase::AddSceneCaptureSensor(ASceneCaptureSensor* SceneCaptureSensor) -{ - uint32 ImageWidth = SceneCaptureSensor->ImageWidth; - uint32 ImageHeight = SceneCaptureSensor->ImageHeight; - - if(AtlasTextureWidth < ImageWidth) - { - IsAtlasTextureValid = false; - AtlasTextureWidth = ImageWidth; - } - - if(AtlasTextureHeight < (CurrentAtlasTextureHeight + ImageHeight) ) - { - IsAtlasTextureValid = false; - AtlasTextureHeight = CurrentAtlasTextureHeight + ImageHeight; - } - - SceneCaptureSensor->PositionInAtlas = FIntVector(0, CurrentAtlasTextureHeight, 0); - CurrentAtlasTextureHeight += ImageHeight; - - SceneCaptureSensors.Add(SceneCaptureSensor); - - UE_LOG(LogCarla, Warning, TEXT("ACarlaGameModeBase::AddSceneCaptureSensor %d %dx%d"), SceneCaptureSensors.Num(), AtlasTextureWidth, AtlasTextureHeight); -} - -void ACarlaGameModeBase::RemoveSceneCaptureSensor(ASceneCaptureSensor* SceneCaptureSensor) -{ - FlushRenderingCommands(); - - // Remove camera - SceneCaptureSensors.Remove(SceneCaptureSensor); - - // Recalculate PositionInAtlas for each camera - AtlasTextureWidth = 0u; - CurrentAtlasTextureHeight = 0u; - for(ASceneCaptureSensor* Camera : SceneCaptureSensors) - { - Camera->PositionInAtlas = FIntVector(0, CurrentAtlasTextureHeight, 0); - CurrentAtlasTextureHeight += Camera->ImageHeight; - - if(AtlasTextureWidth < Camera->ImageWidth) - { - AtlasTextureWidth = Camera->ImageWidth; - } - - } - AtlasTextureHeight = CurrentAtlasTextureHeight; - - IsAtlasTextureValid = false; -} - void ACarlaGameModeBase::InitGame( const FString &MapName, const FString &Options, @@ -204,10 +153,6 @@ void ACarlaGameModeBase::BeginPlay() { Recorder->GetReplayer()->CheckPlayAfterMapLoaded(); } - - // CaptureAtlasDelegate = FCoreDelegates::OnEndFrameRT.AddUObject(this, &ACarlaGameModeBase::CaptureAtlas); - CaptureAtlasDelegate = FCoreDelegates::OnEndFrameRT.AddUObject(this, &ACarlaGameModeBase::SendAtlas); - } void ACarlaGameModeBase::Tick(float DeltaSeconds) @@ -219,8 +164,6 @@ void ACarlaGameModeBase::Tick(float DeltaSeconds) { Recorder->Tick(DeltaSeconds); } - - //SendAtlas(); } void ACarlaGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason) @@ -234,8 +177,6 @@ void ACarlaGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason) { CarlaSettingsDelegate->Reset(); } - - FCoreDelegates::OnEndFrame.Remove(CaptureAtlasDelegate); } void ACarlaGameModeBase::SpawnActorFactories() @@ -391,94 +332,6 @@ void ACarlaGameModeBase::DebugShowSignals(bool enable) } -void ACarlaGameModeBase::CreateAtlasTextures() -{ - if(AtlasTextureWidth > 0 && AtlasTextureHeight > 0) - { - FRHIResourceCreateInfo CreateInfo; - CamerasAtlasTexture = RHICreateTexture2D(AtlasTextureWidth, AtlasTextureHeight, PF_B8G8R8A8, 1, 1, TexCreate_CPUReadback, CreateInfo); - - AtlasImage.Init(FColor(), AtlasTextureWidth * AtlasTextureHeight); - - IsAtlasTextureValid = true; - } -} - -void ACarlaGameModeBase::CaptureAtlas() -{ - - ACarlaGameModeBase* This = this; - - if(!SceneCaptureSensors.Num()) return; - - // Be sure that the atlas texture is ready - if(!IsAtlasTextureValid) - { - CreateAtlasTextures(); - return; - } - - // Enqueue the commands to copy the captures to the atlas - for(ASceneCaptureSensor* Sensor : SceneCaptureSensors) - { - Sensor->CopyTextureToAtlas(); - } - - // Download Atlas texture - ENQUEUE_RENDER_COMMAND(ACarlaGameModeBase_CaptureAtlas) - ( - [This](FRHICommandListImmediate& RHICmdList) mutable - { - FTexture2DRHIRef AtlasTexture = This->CamerasAtlasTexture; - - if (!AtlasTexture) - { - UE_LOG(LogCarla, Error, TEXT("ACarlaGameModeBase::CaptureAtlas: Missing atlas texture")); - return; - } - - FIntRect Rect = FIntRect(0, 0, This->AtlasTextureWidth, This->AtlasTextureHeight); - -#if !UE_BUILD_SHIPPING - if(This->ReadSurfaceMode == 2) Rect = FIntRect(0, 0, This->SurfaceW, This->SurfaceH); -#endif - -#if !UE_BUILD_SHIPPING - if (This->ReadSurfaceMode == 0) return; -#endif - - SCOPE_CYCLE_COUNTER(STAT_CarlaSensorReadRT); - RHICmdList.ReadSurfaceData( - AtlasTexture, - Rect, - This->AtlasImage, - FReadSurfaceDataFlags(RCM_UNorm, CubeFace_MAX)); - - } - ); - - -} - -void ACarlaGameModeBase::SendAtlas() -{ - -#if !UE_BUILD_SHIPPING - if(!AtlasCopyToCamera) - { - return; - } -#endif - - for(int32 Index = 0; Index < SceneCaptureSensors.Num(); Index++) - { - ASceneCaptureSensor* Sensor = SceneCaptureSensors[Index]; - Sensor->SendPixels(AtlasImage, AtlasTextureWidth); - } - -} - - TArray ACarlaGameModeBase::GetAllBBsOfLevel() { UWorld* World = GetWorld(); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h index 223493b883b..5c1376f891b 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h @@ -55,75 +55,6 @@ class CARLA_API ACarlaGameModeBase : public AGameModeBase UFUNCTION(Category = "Carla Game Mode", BlueprintCallable, CallInEditor, Exec) TArray GetAllBBsOfLevel(); - void AddSceneCaptureSensor(ASceneCaptureSensor* SceneCaptureSensor); - - void RemoveSceneCaptureSensor(ASceneCaptureSensor* SceneCaptureSensor); - - bool IsCameraAtlasTextureValid() const - { - return IsAtlasTextureValid; - } - - FTexture2DRHIRef GetCurrentCamerasAtlasTexture() const{ - return CamerasAtlasTexture; - } - - uint32 GetAtlasTextureWidth() const { - return AtlasTextureWidth; - } - - uint32 GetAtlasTextureHeight() const { - return AtlasTextureHeight; - } - - UFUNCTION(Exec) - void SwitchReadSurfaceMode(uint32 Mode) { -#if !UE_BUILD_SHIPPING - ReadSurfaceMode = Mode; -#endif - } - - UFUNCTION(Exec) - void SetAtlasSurface(uint32 W, uint32 H) { -#if !UE_BUILD_SHIPPING - SurfaceW = W; - SurfaceH = H; -#endif - } - - UFUNCTION(Exec) - void EnableCameraCopyToAtlas(bool Enable) { -#if !UE_BUILD_SHIPPING - CameraCopyToAtlasEnable = Enable; -#endif - } - - UFUNCTION(Exec) - void EnableAtlasCopyToCamera(bool Enable) { -#if !UE_BUILD_SHIPPING - AtlasCopyToCamera = Enable; -#endif - } - - UFUNCTION(Exec) - void EnableCameraStream(bool Enable) { -#if !UE_BUILD_SHIPPING - CameraStreamEnable = Enable; -#endif - } - -#if !UE_BUILD_SHIPPING - - bool IsCameraCopyToAtlasEnabled() const { - return CameraCopyToAtlasEnable; - } - - bool IsCameraStreamEnabled() const { - return CameraStreamEnable; - } - -#endif - protected: void InitGame(const FString &MapName, const FString &Options, FString &ErrorMessage) override; @@ -142,12 +73,6 @@ class CARLA_API ACarlaGameModeBase : public AGameModeBase void ParseOpenDrive(const FString &MapName); - void CreateAtlasTextures(); - - void CaptureAtlas(); - - void SendAtlas(); - UPROPERTY() UCarlaGameInstance *GameInstance = nullptr; @@ -180,23 +105,4 @@ class CARLA_API ACarlaGameModeBase : public AGameModeBase boost::optional Map; - FDelegateHandle CaptureAtlasDelegate; - - TArray SceneCaptureSensors; - FTexture2DRHIRef CamerasAtlasTexture; - TArray AtlasImage; - uint32 AtlasTextureWidth = 0u; - uint32 AtlasTextureHeight = 0u; - uint32 CurrentAtlasTextureHeight = 0u; - bool IsAtlasTextureValid = false; - -#if !UE_BUILD_SHIPPING - uint32 ReadSurfaceMode = 1; - uint32 SurfaceW = 0; - uint32 SurfaceH = 0; - bool CameraCopyToAtlasEnable = true; - bool AtlasCopyToCamera = true; - bool CameraStreamEnable = true; -#endif - }; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.cpp index e4ca1341ea8..e86663db326 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.cpp @@ -26,18 +26,9 @@ ADepthCamera::ADepthCamera(const FObjectInitializer &ObjectInitializer) TEXT("Material'/Carla/PostProcessingMaterials/DepthEffectMaterial.DepthEffectMaterial'") #endif ); - - Offset = carla::sensor::SensorRegistry::get::type::header_offset; } -void ADepthCamera::SendPixels(const TArray& AtlasImage, uint32 AtlasTextureWidth) +void ADepthCamera::SendPixels() { -#if !UE_BUILD_SHIPPING - ACarlaGameModeBase* GameMode = Cast(GetWorld()->GetAuthGameMode()); - if(!GameMode->IsCameraStreamEnabled()) return; -#endif - - // SendPixelsInStream(*this, AtlasImage, AtlasTextureWidth); - FPixelReader::SendPixelsInRenderThread(*this); } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.h index f4bda659dcb..60c450fc2d3 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.h @@ -26,5 +26,5 @@ class CARLA_API ADepthCamera : public AShaderBasedSensor protected: - void SendPixels(const TArray& AtlasImage, uint32 AtlasTextureWidth) override; + void SendPixels() override; }; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp index 4c7aa397ee0..917af42ae76 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp @@ -45,6 +45,10 @@ struct LockTexture #if CARLA_WITH_VULKAN_SUPPORT == 1 +// Temporal; this avoid allocating the array each time and also avoids checking +// for a bigger texture, ReadSurfaceData will allocate the space needed. +TArray gPixels; + static void WritePixelsToBuffer_Vulkan( const UTextureRenderTarget2D &RenderTarget, carla::Buffer &Buffer, @@ -62,15 +66,15 @@ static void WritePixelsToBuffer_Vulkan( } FIntPoint Rect = RenderResource->GetSizeXY(); + // NS: Extra copy here, don't know how to avoid it. - TArray Pixels; InRHICmdList.ReadSurfaceData( Texture, FIntRect(0, 0, Rect.X, Rect.Y), - Pixels, + gPixels, FReadSurfaceDataFlags(RCM_UNorm, CubeFace_MAX)); - Buffer.copy_from(Offset, Pixels); + Buffer.copy_from(Offset, gPixels); } #endif // CARLA_WITH_VULKAN_SUPPORT @@ -193,54 +197,3 @@ void FPixelReader::WritePixelsToBuffer( } } } - -void FPixelReader::WritePixelsToArray( - UTextureRenderTarget2D &RenderTarget, - TArray& Pixels, - FRHICommandListImmediate& RHICmdList) -{ - - // check(IsInRenderingThread()); - - const FTextureRenderTarget2DResource* RenderResource = - static_cast(RenderTarget.Resource); - FTexture2DRHIRef Texture = RenderResource->GetRenderTargetTexture(); - if (!Texture /* || !Texture->GetTexture2D() */) - { - UE_LOG(LogCarla, Error, TEXT("FPixelReader: UTextureRenderTarget2D missing render target texture")); - return; - } - - FIntPoint Rect = RenderResource->GetSizeXY(); - - - { - SCOPE_CYCLE_COUNTER(STAT_CarlaSensorReadRT); - - RHICmdList.ReadSurfaceData( - Texture, - FIntRect(0, 0, Rect.X, Rect.Y), - Pixels, - FReadSurfaceDataFlags(RCM_UNorm, CubeFace_MAX)); - - /* - void* ColorDataBuffer = nullptr; - - int32 Width = 0, Height = 0; - RHICmdList.MapStagingSurface(Texture, ColorDataBuffer, Width, Height); - - FColor* ColorBuffer = (FColor*)ColorDataBuffer; - FColor* Dest = &Pixels[0]; - - for (int32 Row = 0; Row < Height; ++Row) - { - FMemory::Memcpy(Dest, ColorBuffer, sizeof(FColor)*Width); - ColorBuffer += Width; - Dest += Width; - } - - RHICmdList.UnmapStagingSurface(Texture); - */ - } - -} \ No newline at end of file diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.h index e7045220d29..05a933a4cc5 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.h @@ -64,11 +64,6 @@ class FPixelReader template static void SendPixelsInRenderThread(TSensor &Sensor); - static void WritePixelsToArray( - UTextureRenderTarget2D &RenderTarget, - TArray& Pixels, - FRHICommandListImmediate &InRHICmdList); - private: /// Copy the pixels in @a RenderTarget into @a Buffer. diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp index 7e480606d2f..dc29b9bd3ba 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp @@ -20,18 +20,9 @@ ASceneCaptureCamera::ASceneCaptureCamera(const FObjectInitializer &ObjectInitial { AddPostProcessingMaterial( TEXT("Material'/Carla/PostProcessingMaterials/PhysicLensDistortion.PhysicLensDistortion'")); - - Offset = carla::sensor::SensorRegistry::get::type::header_offset; } -void ASceneCaptureCamera::SendPixels(const TArray& AtlasImage, uint32 AtlasTextureWidth) +void ASceneCaptureCamera::SendPixels() { -#if !UE_BUILD_SHIPPING - ACarlaGameModeBase* GameMode = Cast(GetWorld()->GetAuthGameMode()); - if(!GameMode->IsCameraStreamEnabled()) return; -#endif - - //SendPixelsInStream(*this, AtlasImage, AtlasTextureWidth); - FPixelReader::SendPixelsInRenderThread(*this); } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.h index bdd2fdf2b6c..ee5d8a71953 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.h @@ -26,6 +26,6 @@ class CARLA_API ASceneCaptureCamera : public AShaderBasedSensor protected: - void SendPixels(const TArray& AtlasImage, uint32 AtlasTextureWidth) override; + void SendPixels() override; }; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp index 5b300fec7a2..5bdc9d6fc08 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp @@ -490,9 +490,7 @@ void ASceneCaptureSensor::BeginPlay() Super::BeginPlay(); - ACarlaGameModeBase* GameMode = Cast(GetWorld()->GetAuthGameMode()); - GameMode->AddSceneCaptureSensor(this); - + SendPixelsDelegate = FCoreDelegates::OnEndFrameRT.AddUObject(this, &ASceneCaptureSensor::SendPixels); } void ASceneCaptureSensor::Tick(float DeltaTime) @@ -513,88 +511,7 @@ void ASceneCaptureSensor::EndPlay(const EEndPlayReason::Type EndPlayReason) Super::EndPlay(EndPlayReason); SCENE_CAPTURE_COUNTER = 0u; - ACarlaGameModeBase* GameMode = Cast(GetWorld()->GetAuthGameMode()); - GameMode->RemoveSceneCaptureSensor(this); -} - -void ASceneCaptureSensor::CopyTextureToAtlas() -{ - - check(CaptureRenderTarget != nullptr); - - ASceneCaptureSensor* This = this; - - ACarlaGameModeBase* GameMode = Cast(GetWorld()->GetAuthGameMode()); - if(!GameMode->IsCameraAtlasTextureValid()) return; - -#if !UE_BUILD_SHIPPING - if(!GameMode->IsCameraCopyToAtlasEnabled()) return; -#endif - - ENQUEUE_RENDER_COMMAND(ASceneCaptureSensor_CopyTextureToAtlas) - ( - [This, GameMode](FRHICommandListImmediate& RHICmdList) mutable - { - FTexture2DRHIRef AtlasTexture = GameMode->GetCurrentCamerasAtlasTexture(); - - if (AtlasTexture.IsValid() && This && This->HasActorBegunPlay() && !This->IsPendingKill()) - { - SCOPE_CYCLE_COUNTER(STAT_CarlaSensorCopyText); - - const FTextureRenderTarget2DResource* RenderResource = - static_cast(This->CaptureRenderTarget->Resource); - FTexture2DRHIRef Texture = RenderResource->GetRenderTargetTexture(); - if (!Texture) - { - UE_LOG(LogCarla, Error, TEXT("ASceneCaptureSensor::Capture: UTextureRenderTarget2D missing render target texture")); - return; - } - - // Prepare copy information - FRHICopyTextureInfo CopyInfo; - CopyInfo.Size = FIntVector(This->ImageWidth, This->ImageHeight, 0); // Size of the camera - CopyInfo.DestPosition = This->PositionInAtlas; // Where to copy the texture - - RHICmdList.CopyTexture(Texture, AtlasTexture, CopyInfo); - } - } - ); -} - -bool ASceneCaptureSensor::CopyTextureFromAtlas( - carla::Buffer &Buffer, - const TArray& AtlasImage, - uint32 AtlasTextureWidth) -{ - - Buffer.reset(Offset + ImageWidth * ImageHeight * sizeof(FColor)); - - // Check that the atlas alreay contains our texture - // and our image has been initialized - uint32 ExpectedSize = (uint32)(PositionInAtlas.Y * AtlasTextureWidth + ImageWidth * ImageHeight); - uint32 TotalSize = (uint32)AtlasImage.Num(); - if(!AtlasImage.GetData() || TotalSize == 0 || TotalSize < ExpectedSize) - { - return false; - } - - SCOPE_CYCLE_COUNTER(STAT_CarlaSensorBufferCopy); - - const FColor* SourceFColor = AtlasImage.GetData() + PositionInAtlas.Y * AtlasTextureWidth; - const uint8* Source = (uint8*)SourceFColor; - uint32 Dest = Offset; - - const uint32 DstStride = ImageWidth * sizeof(FColor); - const uint32 SrcStride = AtlasTextureWidth * sizeof(FColor); - - for(uint32 i = 0; i < ImageHeight; i++) - { - Buffer.copy_from(Dest, Source, DstStride); - Source += SrcStride; - Dest += DstStride; - } - - return true; + FCoreDelegates::OnEndFrameRT.Remove(SendPixelsDelegate); } // ============================================================================= diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.h index 6294320b0e2..b712b2e247b 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.h @@ -270,26 +270,6 @@ class CARLA_API ASceneCaptureSensor : public ASensor FPixelReader::SavePixelsToDisk(*CaptureRenderTarget, FilePath); } - void CopyTextureToAtlas(); - - bool CopyTextureFromAtlas(carla::Buffer &Buffer, const TArray& AtlasImage, uint32 AtlasTextureWidth); - - virtual void SendPixels(const TArray& /* AtlasImage */, uint32 /* AtlasTextureWidth */) {} - - template - void SendPixelsInStream(TSensor &Sensor, const TArray& AtlasImage, uint32 AtlasTextureWidth) - { - auto Stream = GetDataStream(Sensor); - carla::Buffer Buffer = Stream.PopBufferFromPool(); - - CopyTextureFromAtlas(Buffer, AtlasImage, AtlasTextureWidth); - - { - SCOPE_CYCLE_COUNTER(STAT_CarlaSensorStreamSend); - Stream.Send(Sensor, std::move(Buffer)); - } - } - protected: virtual void BeginPlay() override; @@ -300,6 +280,10 @@ class CARLA_API ASceneCaptureSensor : public ASensor virtual void SetUpSceneCaptureComponent(USceneCaptureComponent2D &SceneCapture) {} + virtual void SendPixels() {} + + FDelegateHandle SendPixelsDelegate; + /// Render target necessary for scene capture. UPROPERTY(EditAnywhere) UTextureRenderTarget2D *CaptureRenderTarget = nullptr; @@ -308,8 +292,6 @@ class CARLA_API ASceneCaptureSensor : public ASensor UPROPERTY(EditAnywhere) USceneCaptureComponent2D *CaptureComponent2D = nullptr; - FIntVector PositionInAtlas; - UPROPERTY(EditAnywhere) float TargetGamma = 2.2f; @@ -321,8 +303,6 @@ class CARLA_API ASceneCaptureSensor : public ASensor UPROPERTY(EditAnywhere) uint32 ImageHeight = 600u; - uint32 Offset = 0u; - /// Whether to render the post-processing effects present in the scene. UPROPERTY(EditAnywhere) bool bEnablePostProcessingEffects = true; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.cpp index 8f6e6497395..d9fb5594e72 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.cpp @@ -22,18 +22,9 @@ ASemanticSegmentationCamera::ASemanticSegmentationCamera( TEXT("Material'/Carla/PostProcessingMaterials/PhysicLensDistortion.PhysicLensDistortion'")); AddPostProcessingMaterial( TEXT("Material'/Carla/PostProcessingMaterials/GTMaterial.GTMaterial'")); - - Offset = carla::sensor::SensorRegistry::get::type::header_offset; } -void ASemanticSegmentationCamera::SendPixels(const TArray& AtlasImage, uint32 AtlasTextureWidth) +void ASemanticSegmentationCamera::SendPixels() { -#if !UE_BUILD_SHIPPING - ACarlaGameModeBase* GameMode = Cast(GetWorld()->GetAuthGameMode()); - if(!GameMode->IsCameraStreamEnabled()) return; -#endif - - //SendPixelsInStream(*this, AtlasImage, AtlasTextureWidth); - FPixelReader::SendPixelsInRenderThread(*this); } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.h index d622b05fac3..dd531038555 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.h @@ -26,5 +26,5 @@ class CARLA_API ASemanticSegmentationCamera : public AShaderBasedSensor protected: - void SendPixels(const TArray& AtlasImage, uint32 AtlasTextureWidth) override; + void SendPixels() override; }; From 32721d951ffcc7c154ad3eee6d88d9b294325c0b Mon Sep 17 00:00:00 2001 From: glopezdiest <58212725+glopezdiest@users.noreply.github.com> Date: Thu, 17 Sep 2020 15:48:09 +0200 Subject: [PATCH 072/179] Waypoint buffer cleans on route reset (#3264) --- CHANGELOG.md | 2 ++ .../carla/agents/navigation/behavior_agent.py | 2 +- .../carla/agents/navigation/local_planner.py | 28 +++++++++++++++++-- .../navigation/local_planner_behavior.py | 12 +++++++- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbb1333f800..5da99195760 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,8 +53,10 @@ * Replace deprectated `platform.dist()` with recommended `distro.linux_distribution()` * Improved the performance on capture sensors. * Fixed minor typo in the introduction section of documentation. + * Fixed a bug at the local planner when changing the route, causing it to maintain the first part of the previous one. This was only relevant when using very large buffer sizes. * Added automatic calculation of vehicle's BB + ## CARLA 0.9.9 * Introduced hybrid mode for Traffic Manager diff --git a/PythonAPI/carla/agents/navigation/behavior_agent.py b/PythonAPI/carla/agents/navigation/behavior_agent.py index 8a5b1949011..0a26b4e1968 100644 --- a/PythonAPI/carla/agents/navigation/behavior_agent.py +++ b/PythonAPI/carla/agents/navigation/behavior_agent.py @@ -118,7 +118,7 @@ def set_destination(self, start_location, end_location, clean=False): route_trace = self._trace_route(self.start_waypoint, self.end_waypoint) - self._local_planner.set_global_plan(route_trace) + self._local_planner.set_global_plan(route_trace, clean) def reroute(self, spawn_points): """ diff --git a/PythonAPI/carla/agents/navigation/local_planner.py b/PythonAPI/carla/agents/navigation/local_planner.py index a02a2040c5b..101d382b60b 100644 --- a/PythonAPI/carla/agents/navigation/local_planner.py +++ b/PythonAPI/carla/agents/navigation/local_planner.py @@ -191,10 +191,29 @@ def _compute_next_waypoints(self, k=1): self._waypoints_queue.append((next_waypoint, road_option)) def set_global_plan(self, current_plan): + """ + Resets the waypoint queue and buffer to match the new plan. Also + sets the global_plan flag to avoid creating more waypoints + + :param current_plan: list of (carla.Waypoint, RoadOption) + :return: + """ + + # Reset the queue self._waypoints_queue.clear() for elem in current_plan: self._waypoints_queue.append(elem) self._target_road_option = RoadOption.LANEFOLLOW + + # and the buffer + self._waypoint_buffer.clear() + for _ in range(self._buffer_size): + if self._waypoints_queue: + self._waypoint_buffer.append( + self._waypoints_queue.popleft()) + else: + break + self._global_plan = True def run_step(self, debug=False): @@ -203,7 +222,7 @@ def run_step(self, debug=False): follow the waypoints trajectory. :param debug: boolean flag to activate waypoints debugging - :return: + :return: control to be applied """ # not enough waypoints in the horizon? => add more! @@ -222,7 +241,7 @@ def run_step(self, debug=False): # Buffering the waypoints if not self._waypoint_buffer: - for i in range(self._buffer_size): + for _ in range(self._buffer_size): if self._waypoints_queue: self._waypoint_buffer.append( self._waypoints_queue.popleft()) @@ -253,6 +272,11 @@ def run_step(self, debug=False): return control def done(self): + """ + Returns whether or not the planner has finished + + :return: boolean + """ return len(self._waypoints_queue) == 0 and len(self._waypoint_buffer) == 0 def _retrieve_options(list_waypoints, current_waypoint): diff --git a/PythonAPI/carla/agents/navigation/local_planner_behavior.py b/PythonAPI/carla/agents/navigation/local_planner_behavior.py index 85944825ee2..86a6d6b78ca 100644 --- a/PythonAPI/carla/agents/navigation/local_planner_behavior.py +++ b/PythonAPI/carla/agents/navigation/local_planner_behavior.py @@ -135,7 +135,7 @@ def set_speed(self, speed): self._target_speed = speed - def set_global_plan(self, current_plan): + def set_global_plan(self, current_plan, clean=False): """ Sets new global plan. @@ -143,6 +143,16 @@ def set_global_plan(self, current_plan): """ for elem in current_plan: self.waypoints_queue.append(elem) + + if clean: + self._waypoint_buffer.clear() + for _ in range(self._buffer_size): + if self.waypoints_queue: + self._waypoint_buffer.append( + self.waypoints_queue.popleft()) + else: + break + self._global_plan = True def get_incoming_waypoint_and_direction(self, steps=3): From 318681e276445c16f7bf31f0f702d4fd5de5503a Mon Sep 17 00:00:00 2001 From: Jacopo Bartiromo Date: Thu, 3 Sep 2020 16:46:54 +0200 Subject: [PATCH 073/179] fixes add entry issue --- LibCarla/source/carla/trafficmanager/AtomicMap.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/LibCarla/source/carla/trafficmanager/AtomicMap.h b/LibCarla/source/carla/trafficmanager/AtomicMap.h index e2c5a9f08e9..04d7a92228b 100644 --- a/LibCarla/source/carla/trafficmanager/AtomicMap.h +++ b/LibCarla/source/carla/trafficmanager/AtomicMap.h @@ -27,7 +27,12 @@ namespace traffic_manager { void AddEntry(const std::pair &entry) { std::lock_guard lock(map_mutex); - map.insert(entry); + const Key& key = entry.first; + if (map.find(key) != map.end()) { + map.at(key) = entry.second; + } else { + map.insert(entry); + } } bool Contains(const Key &key) const { From 14900e3bb76e6871aa77a192a17806a41350f7f1 Mon Sep 17 00:00:00 2001 From: Jacopo Bartiromo Date: Tue, 1 Sep 2020 17:08:28 +0200 Subject: [PATCH 074/179] fixes std::numeric_limits::epsilon error --- .../source/carla/trafficmanager/CollisionStage.cpp | 9 ++++----- LibCarla/source/carla/trafficmanager/Constants.h | 2 +- .../carla/trafficmanager/LocalizationUtils.cpp | 12 +++++++----- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/LibCarla/source/carla/trafficmanager/CollisionStage.cpp b/LibCarla/source/carla/trafficmanager/CollisionStage.cpp index 37cdc2b6934..8df2e02b526 100644 --- a/LibCarla/source/carla/trafficmanager/CollisionStage.cpp +++ b/LibCarla/source/carla/trafficmanager/CollisionStage.cpp @@ -143,7 +143,7 @@ LocationVector CollisionStage::GetBoundary(const ActorId actor_id) { float bbox_y = dimensions.y; const cg::Vector3D x_boundary_vector = heading_vector * (bbox_x + forward_extension); - const auto perpendicular_vector = cg::Vector3D(-heading_vector.y, heading_vector.x, 0.0f).MakeUnitVector(); + const auto perpendicular_vector = cg::Vector3D(-heading_vector.y, heading_vector.x, 0.0f).MakeSafeUnitVector(EPSILON); const cg::Vector3D y_boundary_vector = perpendicular_vector * (bbox_y + forward_extension); // Four corners of the vehicle in top view clockwise order (left-handed system). @@ -199,7 +199,7 @@ LocationVector CollisionStage::GetGeodesicBoundary(const ActorId actor_id) { const cg::Vector3D heading_vector = current_point->GetForwardVector(); const cg::Location location = current_point->GetLocation(); cg::Vector3D perpendicular_vector = cg::Vector3D(-heading_vector.y, heading_vector.x, 0.0f); - perpendicular_vector = perpendicular_vector.MakeUnitVector(); + perpendicular_vector = perpendicular_vector.MakeSafeUnitVector(EPSILON); // Direction determined for the left-handed system. const cg::Vector3D scaled_perpendicular = perpendicular_vector * width; left_boundary.push_back(location + cg::Location(scaled_perpendicular)); @@ -304,15 +304,14 @@ std::pair CollisionStage::NegotiateCollision(const ActorId referenc // Ego and other vehicle heading. const cg::Vector3D reference_heading = simulation_state.GetHeading(reference_vehicle_id); // Vector from ego position to position of the other vehicle. - const float vector_magnitude_epsilon = 2.0f * std::numeric_limits::epsilon(); cg::Vector3D reference_to_other = other_location - reference_location; - reference_to_other = reference_to_other.MakeSafeUnitVector(vector_magnitude_epsilon); + reference_to_other = reference_to_other.MakeSafeUnitVector(EPSILON); // Other vehicle heading. const cg::Vector3D other_heading = simulation_state.GetHeading(other_actor_id); // Vector from other vehicle position to ego position. cg::Vector3D other_to_reference = reference_location - other_location; - other_to_reference = other_to_reference.MakeSafeUnitVector(vector_magnitude_epsilon); + other_to_reference = other_to_reference.MakeSafeUnitVector(EPSILON); float reference_vehicle_length = simulation_state.GetDimensions(reference_vehicle_id).x * SQUARE_ROOT_OF_TWO; float other_vehicle_length = simulation_state.GetDimensions(other_actor_id).x * SQUARE_ROOT_OF_TWO; diff --git a/LibCarla/source/carla/trafficmanager/Constants.h b/LibCarla/source/carla/trafficmanager/Constants.h index 4e6fca74a33..58042ff6173 100644 --- a/LibCarla/source/carla/trafficmanager/Constants.h +++ b/LibCarla/source/carla/trafficmanager/Constants.h @@ -78,6 +78,7 @@ static const float MAX_LOCKING_EXTENSION = 10.0f; static const float WALKER_TIME_EXTENSION = 1.5f; static const float SQUARE_ROOT_OF_TWO = 1.414f; static const float VERTICAL_OVERLAP_THRESHOLD = 4.0f; +static const float EPSILON = 2.0f * std::numeric_limits::epsilon(); } // namespace Collision namespace FrameMemory { @@ -126,7 +127,6 @@ static const uint64_t BUFFER_STEP_THROUGH = 10; static const float INV_BUFFER_STEP_THROUGH = 0.1f; } // namespace TrackTraffic - } // namespace constants } // namespace traffic_manager } // namespace carla diff --git a/LibCarla/source/carla/trafficmanager/LocalizationUtils.cpp b/LibCarla/source/carla/trafficmanager/LocalizationUtils.cpp index cba56552a47..8ced5c7c6b7 100644 --- a/LibCarla/source/carla/trafficmanager/LocalizationUtils.cpp +++ b/LibCarla/source/carla/trafficmanager/LocalizationUtils.cpp @@ -5,16 +5,19 @@ // For a copy, see . #include "carla/trafficmanager/LocalizationUtils.h" +#include "carla/trafficmanager/Constants.h" + namespace carla { namespace traffic_manager { +using constants::Collision::EPSILON; + float DeviationCrossProduct(const cg::Location &reference_location, const cg::Vector3D &heading_vector, const cg::Location &target_location) { cg::Vector3D next_vector = target_location - reference_location; - float vector_magnitude_epsilon = 2.0f * std::numeric_limits::epsilon(); - next_vector = next_vector.MakeSafeUnitVector(vector_magnitude_epsilon); + next_vector = next_vector.MakeSafeUnitVector(EPSILON); const float cross_z = heading_vector.x * next_vector.y - heading_vector.y * next_vector.x; return cross_z; } @@ -23,11 +26,10 @@ float DeviationDotProduct(const cg::Location &reference_location, const cg::Vector3D &heading_vector, const cg::Location &target_location) { cg::Vector3D next_vector = target_location - reference_location; - float vector_magnitude_epsilon = 2.0f * std::numeric_limits::epsilon(); next_vector.z = 0.0f; - next_vector = next_vector.MakeSafeUnitVector(vector_magnitude_epsilon); + next_vector = next_vector.MakeSafeUnitVector(EPSILON); cg::Vector3D heading_vector_flat(heading_vector.x, heading_vector.y, 0); - heading_vector_flat = heading_vector_flat.MakeSafeUnitVector(vector_magnitude_epsilon); + heading_vector_flat = heading_vector_flat.MakeSafeUnitVector(EPSILON); const float dot_product = cg::Math::Dot(next_vector, heading_vector_flat); return dot_product; } From 7bbb7f9c54b2a7296d62a4fedea2aca490be0e4d Mon Sep 17 00:00:00 2001 From: Axel Date: Tue, 15 Sep 2020 16:52:32 +0200 Subject: [PATCH 075/179] Fixed ugly z-fighting issue with OSM maps. Added AProceduralMeshActor for easier actor inspection in the editor. --- LibCarla/source/carla/geom/Mesh.h | 6 ++++++ .../Carla/OpenDrive/OpenDriveGenerator.cpp | 19 ++++++++++++++----- .../Carla/OpenDrive/OpenDriveGenerator.h | 11 +++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/LibCarla/source/carla/geom/Mesh.h b/LibCarla/source/carla/geom/Mesh.h index be83758180c..307a7e1dfe9 100644 --- a/LibCarla/source/carla/geom/Mesh.h +++ b/LibCarla/source/carla/geom/Mesh.h @@ -193,6 +193,12 @@ namespace geom { Normal = Normal.GetSafeNormal(.0001f); if (Normal != FVector::ZeroVector) { + // fix to prevent ugly x-fighting in geometries with very large curvatures, + // ensures that all road geometry is facing upwards + if (FVector::DotProduct(Normal, FVector(0,0,1)) < 0) + { + Normal = -Normal; + } Mesh.Normals[Triangle.v0] = Normal; Mesh.Normals[Triangle.v1] = Normal; Mesh.Normals[Triangle.v2] = Normal; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/OpenDrive/OpenDriveGenerator.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/OpenDrive/OpenDriveGenerator.cpp index 9c376c1453d..0f5ddd2da67 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/OpenDrive/OpenDriveGenerator.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/OpenDrive/OpenDriveGenerator.cpp @@ -18,6 +18,13 @@ #include "Engine/Classes/Interfaces/Interface_CollisionDataProvider.h" #include "PhysicsEngine/BodySetupEnums.h" +AProceduralMeshActor::AProceduralMeshActor() +{ + PrimaryActorTick.bCanEverTick = false; + MeshComponent = CreateDefaultSubobject(TEXT("RootComponent")); + RootComponent = MeshComponent; +} + AOpenDriveGenerator::AOpenDriveGenerator(const FObjectInitializer &ObjectInitializer) : Super(ObjectInitializer) { @@ -77,11 +84,13 @@ void AOpenDriveGenerator::GenerateRoadMesh() { continue; } - AActor *TempActor = GetWorld()->SpawnActor(); - UProceduralMeshComponent *TempPMC = NewObject(TempActor); - TempPMC->RegisterComponent(); - TempPMC->AttachToComponent( - TempActor->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform); + // AActor *TempActor = GetWorld()->SpawnActor(); + // UProceduralMeshComponent *TempPMC = NewObject(TempActor); + AProceduralMeshActor* TempActor = GetWorld()->SpawnActor(); + UProceduralMeshComponent *TempPMC = TempActor->MeshComponent; + // TempPMC->RegisterComponent(); + // TempPMC->AttachToComponent( + // TempActor->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform); TempPMC->bUseAsyncCooking = true; TempPMC->bUseComplexAsSimpleCollision = true; TempPMC->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/OpenDrive/OpenDriveGenerator.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/OpenDrive/OpenDriveGenerator.h index 3d10c1f0e35..6654e5935e3 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/OpenDrive/OpenDriveGenerator.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/OpenDrive/OpenDriveGenerator.h @@ -18,6 +18,17 @@ #include "OpenDriveGenerator.generated.h" +UCLASS() +class CARLA_API AProceduralMeshActor : public AActor +{ + GENERATED_BODY() +public: + AProceduralMeshActor(); + + UPROPERTY(Category = "Procedural Mesh Actor", VisibleDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) + UProceduralMeshComponent* MeshComponent; +}; + UCLASS() class CARLA_API AOpenDriveGenerator : public AActor { From def0b38a9ab3c15b79c3f9cce8841c65080d9504 Mon Sep 17 00:00:00 2001 From: Axel Date: Thu, 17 Sep 2020 16:12:49 +0200 Subject: [PATCH 076/179] Removed comments. --- .../Carla/Source/Carla/OpenDrive/OpenDriveGenerator.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/OpenDrive/OpenDriveGenerator.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/OpenDrive/OpenDriveGenerator.cpp index 0f5ddd2da67..ddcebe60d1d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/OpenDrive/OpenDriveGenerator.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/OpenDrive/OpenDriveGenerator.cpp @@ -84,13 +84,8 @@ void AOpenDriveGenerator::GenerateRoadMesh() { continue; } - // AActor *TempActor = GetWorld()->SpawnActor(); - // UProceduralMeshComponent *TempPMC = NewObject(TempActor); AProceduralMeshActor* TempActor = GetWorld()->SpawnActor(); UProceduralMeshComponent *TempPMC = TempActor->MeshComponent; - // TempPMC->RegisterComponent(); - // TempPMC->AttachToComponent( - // TempActor->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform); TempPMC->bUseAsyncCooking = true; TempPMC->bUseComplexAsSimpleCollision = true; TempPMC->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); From 6ad3ff8d5c5ec99b2fb6a7738f49ffad0c109fd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Sabater?= Date: Mon, 13 Jul 2020 01:58:51 +0200 Subject: [PATCH 077/179] Update build_windows.md Added info about command execution that toke me many time to find out --- Docs/build_windows.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Docs/build_windows.md b/Docs/build_windows.md index f8f9ed470ab..3394de55b6d 100644 --- a/Docs/build_windows.md +++ b/Docs/build_windows.md @@ -23,6 +23,9 @@ The build process can be quite long and tedious. The **[F.A.Q.](build_faq.md)**
    To execute the make commands below, you must use the Visual Studio 2017 native console x64 with administrator rights, otherwise you may be getting permission errors. +!!! Important + To execute the "make" commands below, you MUST use the Visual Studio 2017 native console x64 WITH administrator rights, otherwise you may be getting permission errors. + ```sh # Make sure to meet the minimum requirements. From d240c8dca6e5971eddb46e3b96d231514a051230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Sabater?= Date: Tue, 4 Aug 2020 19:35:43 +0200 Subject: [PATCH 078/179] Update build_windows.md Updated as requested in pull request review --- Docs/build_windows.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/build_windows.md b/Docs/build_windows.md index 3394de55b6d..b855d384fea 100644 --- a/Docs/build_windows.md +++ b/Docs/build_windows.md @@ -24,7 +24,7 @@ The build process can be quite long and tedious. The **[F.A.Q.](build_faq.md)** To execute the make commands below, you must use the Visual Studio 2017 native console x64 with administrator rights, otherwise you may be getting permission errors. !!! Important - To execute the "make" commands below, you MUST use the Visual Studio 2017 native console x64 WITH administrator rights, otherwise you may be getting permission errors. + To execute the ```make``` commands below, you **must** use the Visual Studio 2017 native console x64 **with** administrator rights, otherwise you may be getting permission errors. ```sh # Make sure to meet the minimum requirements. From bc5871330aad5b9573d956110217d3b24f1a27b3 Mon Sep 17 00:00:00 2001 From: Praveen Kumar Date: Thu, 17 Sep 2020 19:47:05 +0530 Subject: [PATCH 079/179] Implemented parameter for OSM mode. --- LibCarla/source/carla/trafficmanager/Parameters.cpp | 9 +++++++++ LibCarla/source/carla/trafficmanager/Parameters.h | 8 ++++++++ LibCarla/source/carla/trafficmanager/TrafficManager.h | 8 ++++++++ .../source/carla/trafficmanager/TrafficManagerBase.h | 3 +++ .../source/carla/trafficmanager/TrafficManagerClient.h | 6 ++++++ .../source/carla/trafficmanager/TrafficManagerLocal.cpp | 4 ++++ .../source/carla/trafficmanager/TrafficManagerLocal.h | 3 +++ .../source/carla/trafficmanager/TrafficManagerRemote.cpp | 4 ++++ .../source/carla/trafficmanager/TrafficManagerRemote.h | 3 +++ .../source/carla/trafficmanager/TrafficManagerServer.h | 5 +++++ PythonAPI/carla/source/libcarla/TrafficManager.cpp | 3 ++- 11 files changed, 55 insertions(+), 1 deletion(-) diff --git a/LibCarla/source/carla/trafficmanager/Parameters.cpp b/LibCarla/source/carla/trafficmanager/Parameters.cpp index 397a22983a5..d8c271184f3 100644 --- a/LibCarla/source/carla/trafficmanager/Parameters.cpp +++ b/LibCarla/source/carla/trafficmanager/Parameters.cpp @@ -133,6 +133,10 @@ void Parameters::SetHybridPhysicsRadius(const float radius) { hybrid_physics_radius.store(new_radius); } +void Parameters::SetOSMMode(const bool mode_switch) { + osm_mode.store(mode_switch); +} + //////////////////////////////////// GETTERS ////////////////////////////////// float Parameters::GetHybridPhysicsRadius() const { @@ -269,5 +273,10 @@ bool Parameters::GetHybridPhysicsMode() const { return hybrid_physics_mode.load(); } +bool Parameters::GetOSMMode() { + + return osm_mode.load(); +} + } // namespace traffic_manager } // namespace carla diff --git a/LibCarla/source/carla/trafficmanager/Parameters.h b/LibCarla/source/carla/trafficmanager/Parameters.h index 7843bcba4fc..a1138e4d934 100644 --- a/LibCarla/source/carla/trafficmanager/Parameters.h +++ b/LibCarla/source/carla/trafficmanager/Parameters.h @@ -64,6 +64,8 @@ class Parameters { std::atomic hybrid_physics_mode{false}; /// Hybrid physics radius. std::atomic hybrid_physics_radius {70.0}; + /// Parameter specifying Open Street Map mode. + std::atomic osm_mode {false}; public: Parameters(); @@ -126,6 +128,9 @@ class Parameters { /// Method to set hybrid physics radius. void SetHybridPhysicsRadius(const float radius); + /// Method to set Open Street Map mode. + void SetOSMMode(const bool mode_switch); + ///////////////////////////////// GETTERS ///////////////////////////////////// /// Method to retrieve hybrid physics radius. @@ -170,6 +175,9 @@ class Parameters { /// Method to retrieve hybrid physics mode. bool GetHybridPhysicsMode() const; + /// Method to get Open Street Map mode. + bool GetOSMMode(); + /// Synchronous mode time out variable. std::chrono::duration synchronous_time_out; }; diff --git a/LibCarla/source/carla/trafficmanager/TrafficManager.h b/LibCarla/source/carla/trafficmanager/TrafficManager.h index 14e001340a6..562df505185 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManager.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManager.h @@ -57,6 +57,14 @@ class TrafficManager { return (_port > 1023); } + /// Method to set Open Street Map mode. + void SetOSMMode(const bool mode_switch) { + TrafficManagerBase* tm_ptr = GetTM(_port); + if (tm_ptr != nullptr) { + tm_ptr->SetOSMMode(mode_switch); + } + } + /// This method sets the hybrid physics mode. void SetHybridPhysicsMode(const bool mode_switch) { TrafficManagerBase* tm_ptr = GetTM(_port); diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerBase.h b/LibCarla/source/carla/trafficmanager/TrafficManagerBase.h index 587b226bbfe..a4012e91bd9 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerBase.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerBase.h @@ -104,6 +104,9 @@ class TrafficManagerBase { /// Method to set hybrid physics radius. virtual void SetHybridPhysicsRadius(const float radius) = 0; + /// Method to set Open Street Map mode. + virtual void SetOSMMode(const bool mode_switch) = 0; + protected: }; diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerClient.h b/LibCarla/source/carla/trafficmanager/TrafficManagerClient.h index bc161584bcd..d29f3a1bdfc 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerClient.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerClient.h @@ -193,6 +193,12 @@ class TrafficManagerClient { _client->call("set_hybrid_physics_radius", radius); } + /// Method to set Open Street Map mode. + void SetOSMMode(const bool mode_switch) { + DEBUG_ASSERT(_client != nullptr); + _client->call("set_osm_mode", mode_switch); + } + private: /// RPC client. diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp index 656fdb691b5..b91319fa651 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp @@ -338,6 +338,10 @@ void TrafficManagerLocal::SetHybridPhysicsRadius(const float radius) { parameters.SetHybridPhysicsRadius(radius); } +void TrafficManagerLocal::SetOSMMode(const bool mode_switch) { + parameters.SetOSMMode(mode_switch); +} + bool TrafficManagerLocal::CheckAllFrozen(TLGroup tl_to_freeze) { for (auto &elem : tl_to_freeze) { if (!elem->IsFrozen() || elem->GetState() != TLS::Red) { diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.h b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.h index 9f376b81acf..fb2153ca14e 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.h @@ -214,6 +214,9 @@ class TrafficManagerLocal : public TrafficManagerBase { /// Method to set hybrid physics radius. void SetHybridPhysicsRadius(const float radius); + + /// Method to set Open Street Map mode. + void SetOSMMode(const bool mode_switch); }; } // namespace traffic_manager diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.cpp b/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.cpp index ac3fad8a173..6a9e3b17eb4 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.cpp +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.cpp @@ -181,6 +181,10 @@ void TrafficManagerRemote::SetHybridPhysicsRadius(const float radius) { client.SetHybridPhysicsRadius(radius); } +void TrafficManagerRemote::SetOSMMode(const bool mode_switch) { + client.SetOSMMode(mode_switch); +} + void TrafficManagerRemote::ResetAllTrafficLights() { client.ResetAllTrafficLights(); } diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.h b/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.h index ac3023b91d9..82787f78d3d 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.h @@ -102,6 +102,9 @@ class TrafficManagerRemote : public TrafficManagerBase { /// Method to set hybrid physics radius. void SetHybridPhysicsRadius(const float radius); + /// Method to set Open Street Map mode. + void SetOSMMode(const bool mode_switch); + /// Method to provide synchronous tick bool SynchronousTick(); diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerServer.h b/LibCarla/source/carla/trafficmanager/TrafficManagerServer.h index 5f7ed1a0035..62b1374ae7e 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerServer.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerServer.h @@ -163,6 +163,11 @@ class TrafficManagerServer { tm->SetHybridPhysicsRadius(radius); }); + /// Method to set hybrid physics radius. + server->bind("set_osm_mode", [=](const bool mode_switch) { + tm->SetHybridPhysicsRadius(mode_switch); + }); + /// Method to set synchronous mode. server->bind("set_synchronous_mode", [=](const bool mode) { tm->SetSynchronousMode(mode); diff --git a/PythonAPI/carla/source/libcarla/TrafficManager.cpp b/PythonAPI/carla/source/libcarla/TrafficManager.cpp index 586211d948c..795c4b96db7 100644 --- a/PythonAPI/carla/source/libcarla/TrafficManager.cpp +++ b/PythonAPI/carla/source/libcarla/TrafficManager.cpp @@ -33,5 +33,6 @@ void export_trafficmanager() { .def("set_percentage_keep_right_rule", &carla::traffic_manager::TrafficManager::SetKeepRightPercentage) .def("set_synchronous_mode", &carla::traffic_manager::TrafficManager::SetSynchronousMode) .def("set_hybrid_physics_mode", &carla::traffic_manager::TrafficManager::SetHybridPhysicsMode) - .def("set_hybrid_physics_radius", &carla::traffic_manager::TrafficManager::SetHybridPhysicsRadius); + .def("set_hybrid_physics_radius", &carla::traffic_manager::TrafficManager::SetHybridPhysicsRadius) + .def("set_osm_mode", &carla::traffic_manager::TrafficManager::SetOSMMode); } From f3d357d7d07e5535a9bc4e2222f54c323f55bc8c Mon Sep 17 00:00:00 2001 From: Praveen Kumar Date: Thu, 17 Sep 2020 20:31:59 +0530 Subject: [PATCH 080/179] Implemented vehicle removal in OSM mode. --- LibCarla/source/carla/trafficmanager/ALSM.cpp | 11 +++++++++++ LibCarla/source/carla/trafficmanager/ALSM.h | 3 +++ .../source/carla/trafficmanager/LocalizationStage.cpp | 9 +++++++++ .../source/carla/trafficmanager/LocalizationStage.h | 3 +++ LibCarla/source/carla/trafficmanager/Parameters.cpp | 2 +- LibCarla/source/carla/trafficmanager/Parameters.h | 2 +- .../carla/trafficmanager/TrafficManagerLocal.cpp | 2 ++ .../source/carla/trafficmanager/TrafficManagerLocal.h | 1 + PythonAPI/examples/spawn_npc.py | 7 +++++++ 9 files changed, 38 insertions(+), 2 deletions(-) diff --git a/LibCarla/source/carla/trafficmanager/ALSM.cpp b/LibCarla/source/carla/trafficmanager/ALSM.cpp index af4021e812d..60abde31127 100644 --- a/LibCarla/source/carla/trafficmanager/ALSM.cpp +++ b/LibCarla/source/carla/trafficmanager/ALSM.cpp @@ -18,6 +18,7 @@ ALSM::ALSM( AtomicActorSet ®istered_vehicles, BufferMap &buffer_map, TrackTraffic &track_traffic, + std::vector& marked_for_removal, const Parameters ¶meters, const cc::World &world, const LocalMapPtr &local_map, @@ -29,6 +30,7 @@ ALSM::ALSM( : registered_vehicles(registered_vehicles), buffer_map(buffer_map), track_traffic(track_traffic), + marked_for_removal(marked_for_removal), parameters(parameters), world(world), local_map(local_map), @@ -106,6 +108,15 @@ void ALSM::Update() { elapsed_last_actor_destruction = current_timestamp.elapsed_seconds; } + // Destorying vehicles for marked for removal by stages. + if (parameters.GetOSMMode()) { + for (const ActorId& actor_id: marked_for_removal) { + registered_vehicles.Destroy(actor_id); + RemoveActor(actor_id, true); + } + marked_for_removal.clear(); + } + // Update dynamic state and static attributes for unregistered actors. UpdateUnregisteredActorsData(); } diff --git a/LibCarla/source/carla/trafficmanager/ALSM.h b/LibCarla/source/carla/trafficmanager/ALSM.h index 146831e34ba..87f01496e50 100644 --- a/LibCarla/source/carla/trafficmanager/ALSM.h +++ b/LibCarla/source/carla/trafficmanager/ALSM.h @@ -48,6 +48,8 @@ class ALSM { // Structure containing vehicles with attribute role_name with value hero. ActorMap hero_actors; TrackTraffic &track_traffic; + // Array of vehicles marked by stages for removal. + std::vector& marked_for_removal; const Parameters ¶meters; const cc::World &world; const LocalMapPtr &local_map; @@ -88,6 +90,7 @@ class ALSM { ALSM(AtomicActorSet ®istered_vehicles, BufferMap &buffer_map, TrackTraffic &track_traffic, + std::vector& marked_for_removal, const Parameters ¶meters, const cc::World &world, const LocalMapPtr &local_map, diff --git a/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp b/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp index ac01d67020c..9132eb8d0a6 100644 --- a/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp +++ b/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp @@ -17,6 +17,7 @@ LocalizationStage::LocalizationStage( TrackTraffic &track_traffic, const LocalMapPtr &local_map, Parameters ¶meters, + std::vector& marked_for_removal, LocalizationFrame &output_array, cc::DebugHelper &debug_helper) : vehicle_id_list(vehicle_id_list), @@ -25,6 +26,7 @@ LocalizationStage::LocalizationStage( track_traffic(track_traffic), local_map(local_map), parameters(parameters), + marked_for_removal(marked_for_removal), output_array(output_array), debug_helper(debug_helper) {} @@ -150,6 +152,13 @@ void LocalizationStage::Update(const unsigned long index) { // Pseudo-randomized path selection if found more than one choice. if (next_waypoints.size() > 1) { selection_index = static_cast(pgen.next()) % next_waypoints.size(); + } else if (next_waypoints.size() == 0) { + if (parameters.GetOSMMode()) { + marked_for_removal.push_back(actor_id); + break; + } else { + throw std::invalid_argument("This is an OSM, please activate the set_open_street_map parameter"); + } } SimpleWaypointPtr next_wp = next_waypoints.at(selection_index); if (next_wp == nullptr) { diff --git a/LibCarla/source/carla/trafficmanager/LocalizationStage.h b/LibCarla/source/carla/trafficmanager/LocalizationStage.h index e3ada46ea84..ba70b407ff8 100644 --- a/LibCarla/source/carla/trafficmanager/LocalizationStage.h +++ b/LibCarla/source/carla/trafficmanager/LocalizationStage.h @@ -34,6 +34,8 @@ class LocalizationStage : Stage { TrackTraffic &track_traffic; const LocalMapPtr &local_map; Parameters ¶meters; + // Array of vehicles marked by stages for removal. + std::vector& marked_for_removal; LocalizationFrame &output_array; cc::DebugHelper &debug_helper; LaneChangeLocationMap last_lane_change_location; @@ -60,6 +62,7 @@ class LocalizationStage : Stage { TrackTraffic &track_traffic, const LocalMapPtr &local_map, Parameters ¶meters, + std::vector& marked_for_removal, LocalizationFrame &output_array, cc::DebugHelper &debug_helper); diff --git a/LibCarla/source/carla/trafficmanager/Parameters.cpp b/LibCarla/source/carla/trafficmanager/Parameters.cpp index d8c271184f3..801ca6d91f7 100644 --- a/LibCarla/source/carla/trafficmanager/Parameters.cpp +++ b/LibCarla/source/carla/trafficmanager/Parameters.cpp @@ -273,7 +273,7 @@ bool Parameters::GetHybridPhysicsMode() const { return hybrid_physics_mode.load(); } -bool Parameters::GetOSMMode() { +bool Parameters::GetOSMMode() const { return osm_mode.load(); } diff --git a/LibCarla/source/carla/trafficmanager/Parameters.h b/LibCarla/source/carla/trafficmanager/Parameters.h index a1138e4d934..234062ddbc1 100644 --- a/LibCarla/source/carla/trafficmanager/Parameters.h +++ b/LibCarla/source/carla/trafficmanager/Parameters.h @@ -176,7 +176,7 @@ class Parameters { bool GetHybridPhysicsMode() const; /// Method to get Open Street Map mode. - bool GetOSMMode(); + bool GetOSMMode() const; /// Synchronous mode time out variable. std::chrono::duration synchronous_time_out; diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp index b91319fa651..f1a1b830c72 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp @@ -37,6 +37,7 @@ TrafficManagerLocal::TrafficManagerLocal( track_traffic, local_map, parameters, + marked_for_removal, localization_frame, debug_helper)), @@ -71,6 +72,7 @@ TrafficManagerLocal::TrafficManagerLocal( alsm(ALSM(registered_vehicles, buffer_map, track_traffic, + marked_for_removal, parameters, world, local_map, diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.h b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.h index fb2153ca14e..e5da564f50a 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.h @@ -109,6 +109,7 @@ class TrafficManagerLocal : public TrafficManagerBase { std::condition_variable step_end_trigger; /// Single worker thread for sequential execution of sub-components. std::unique_ptr worker_thread; + std::vector marked_for_removal; /// Method to check if all traffic lights are frozen in a group. bool CheckAllFrozen(TLGroup tl_to_freeze); diff --git a/PythonAPI/examples/spawn_npc.py b/PythonAPI/examples/spawn_npc.py index e3e9d0e8971..3442b8ded5d 100755 --- a/PythonAPI/examples/spawn_npc.py +++ b/PythonAPI/examples/spawn_npc.py @@ -84,6 +84,10 @@ def main(): '--hybrid', action='store_true', help='Enanble') + argparser.add_argument( + '--osm', + action='store_true', + help='Open Street Map mode') argparser.add_argument( '--car-lights-on', action='store_true', @@ -108,6 +112,9 @@ def main(): if args.hybrid: traffic_manager.set_hybrid_physics_mode(True) + if args.osm: + traffic_manager.set_osm_mode(True) + if args.sync: settings = world.get_settings() traffic_manager.set_synchronous_mode(True) From 1139d679b1b6babd322a34acecc1aa163295b9e7 Mon Sep 17 00:00:00 2001 From: Jacopo Bartiromo Date: Fri, 18 Sep 2020 12:47:57 +0200 Subject: [PATCH 081/179] changelog update --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5da99195760..f25d2968ff5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ ## CARLA 0.9.10 - + * Support for OSM in Traffic Manager + * Fixed a map change error when Traffic Manager is in synchronous mode + * Fixes add entry issue for applying parameters more than once in Traffic Manager + * Fixes std::numeric_limits::epsilon error in Traffic Manager * Upgraded carla Docker image to Ubuntu 18.04 * Fixed memory leak on manual_control scripts (sensor listenning was not stoped before destroying) * Added PythonAPI `carla.Osm2Odr.convert()` function and `calra.Osm2OdrSettings` class to support Open Street Maps to OpenDRIVE conversions From 788f9e33f7e9df5c4b971bbb9303630935d69c13 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Wed, 16 Sep 2020 15:43:15 +0200 Subject: [PATCH 082/179] Fixed histogram exposure mode --- Unreal/CarlaUE4/Config/DefaultEngine.ini | 1 + .../Actor/ActorBlueprintFunctionLibrary.cpp | 20 +++++++++---------- .../Carla/Sensor/SceneCaptureSensor.cpp | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Unreal/CarlaUE4/Config/DefaultEngine.ini b/Unreal/CarlaUE4/Config/DefaultEngine.ini index ffa00cc8006..f6064a6f368 100644 --- a/Unreal/CarlaUE4/Config/DefaultEngine.ini +++ b/Unreal/CarlaUE4/Config/DefaultEngine.ini @@ -33,6 +33,7 @@ r.DistanceFieldBuild.EightBit=False r.DistanceFieldBuild.Compress=False r.DistanceFields.AtlasSizeXY=1024 r.DistanceFields.AtlasSizeZ=2048 +r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True [/Script/AIModule.AISense_Sight] bAutoRegisterAllPawnsAsSources=False diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp index 776bf7ffdae..e5e0fa661bd 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp @@ -441,7 +441,7 @@ void UActorBlueprintFunctionLibrary::MakeCameraDefinition( FActorVariation ExposureCompensation; ExposureCompensation.Id = TEXT("exposure_compensation"); ExposureCompensation.Type = EActorAttributeType::Float; - ExposureCompensation.RecommendedValues = { TEXT("-2.2") }; + ExposureCompensation.RecommendedValues = { TEXT("-1.8") }; ExposureCompensation.bRestrictToRecommended = false; // - Manual ------------------------------------------------ @@ -468,7 +468,7 @@ void UActorBlueprintFunctionLibrary::MakeCameraDefinition( FActorVariation Aperture; // N Aperture.Id = TEXT("fstop"); Aperture.Type = EActorAttributeType::Float; - Aperture.RecommendedValues = { TEXT("8.0") }; + Aperture.RecommendedValues = { TEXT("1.4") }; Aperture.bRestrictToRecommended = false; // - Histogram --------------------------------------------- @@ -478,7 +478,7 @@ void UActorBlueprintFunctionLibrary::MakeCameraDefinition( FActorVariation ExposureMinBright; ExposureMinBright.Id = TEXT("exposure_min_bright"); ExposureMinBright.Type = EActorAttributeType::Float; - ExposureMinBright.RecommendedValues = { TEXT("0.1") }; + ExposureMinBright.RecommendedValues = { TEXT("7.0") }; ExposureMinBright.bRestrictToRecommended = false; // The maximum brightness for auto exposure that limits the upper @@ -486,7 +486,7 @@ void UActorBlueprintFunctionLibrary::MakeCameraDefinition( FActorVariation ExposureMaxBright; ExposureMaxBright.Id = TEXT("exposure_max_bright"); ExposureMaxBright.Type = EActorAttributeType::Float; - ExposureMaxBright.RecommendedValues = { TEXT("2.0") }; + ExposureMaxBright.RecommendedValues = { TEXT("20.0") }; ExposureMaxBright.bRestrictToRecommended = false; // The speed at which the adaptation occurs from a dark environment @@ -1389,8 +1389,8 @@ void UActorBlueprintFunctionLibrary::SetCamera( RetrieveActorAttributeToFloat("lens_flare_intensity", Description.Variations, 0.1f)); Camera->SetBloomIntensity( RetrieveActorAttributeToFloat("bloom_intensity", Description.Variations, 0.675f)); - // Exposure - if (RetrieveActorAttributeToString("exposure_mode", Description.Variations, "manual") == "histogram") + // Exposure, histogram mode by default + if (RetrieveActorAttributeToString("exposure_mode", Description.Variations, "histogram") == "histogram") { Camera->SetExposureMethod(EAutoExposureMethod::AEM_Histogram); } @@ -1399,18 +1399,18 @@ void UActorBlueprintFunctionLibrary::SetCamera( Camera->SetExposureMethod(EAutoExposureMethod::AEM_Manual); } Camera->SetExposureCompensation( - RetrieveActorAttributeToFloat("exposure_compensation", Description.Variations, -2.2f)); + RetrieveActorAttributeToFloat("exposure_compensation", Description.Variations, -1.8f)); Camera->SetShutterSpeed( RetrieveActorAttributeToFloat("shutter_speed", Description.Variations, 200.0f)); Camera->SetISO( RetrieveActorAttributeToFloat("iso", Description.Variations, 200.0f)); Camera->SetAperture( - RetrieveActorAttributeToFloat("fstop", Description.Variations, 8.0f)); + RetrieveActorAttributeToFloat("fstop", Description.Variations, 1.4f)); Camera->SetExposureMinBrightness( - RetrieveActorAttributeToFloat("exposure_min_bright", Description.Variations, 0.1f)); + RetrieveActorAttributeToFloat("exposure_min_bright", Description.Variations, 7.0f)); Camera->SetExposureMaxBrightness( - RetrieveActorAttributeToFloat("exposure_max_bright", Description.Variations, 2.0f)); + RetrieveActorAttributeToFloat("exposure_max_bright", Description.Variations, 20.0f)); Camera->SetExposureSpeedUp( RetrieveActorAttributeToFloat("exposure_speed_up", Description.Variations, 3.0f)); Camera->SetExposureSpeedDown( diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp index 5bdc9d6fc08..20aad523937 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp @@ -115,7 +115,7 @@ void ASceneCaptureSensor::SetExposureCompensation(float Compensation) #if PLATFORM_LINUX CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation; #else - CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation + 2.2f; + CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation + 1.8f; #endif } From 19af3a40c70799b3c02c37bad13dea181fb18429 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Wed, 16 Sep 2020 16:49:58 +0200 Subject: [PATCH 083/179] Default camera mode is now histogram --- .../Actor/ActorBlueprintFunctionLibrary.cpp | 4 +- .../Source/CarlaUE4/CarlaMapGenerator.cpp | 79 ------------------- .../Source/CarlaUE4/CarlaMapGenerator.h | 21 ----- 3 files changed, 2 insertions(+), 102 deletions(-) delete mode 100644 Unreal/CarlaUE4/Source/CarlaUE4/CarlaMapGenerator.cpp delete mode 100644 Unreal/CarlaUE4/Source/CarlaUE4/CarlaMapGenerator.h diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp index e5e0fa661bd..ab20878a235 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp @@ -428,7 +428,7 @@ void UActorBlueprintFunctionLibrary::MakeCameraDefinition( FActorVariation ExposureMode; ExposureMode.Id = TEXT("exposure_mode"); ExposureMode.Type = EActorAttributeType::String; - ExposureMode.RecommendedValues = { TEXT("manual"), TEXT("histogram") }; + ExposureMode.RecommendedValues = { TEXT("histogram"), TEXT("manual") }; ExposureMode.bRestrictToRecommended = true; // Logarithmic adjustment for the exposure. Only used if a tonemapper is @@ -1403,7 +1403,7 @@ void UActorBlueprintFunctionLibrary::SetCamera( Camera->SetShutterSpeed( RetrieveActorAttributeToFloat("shutter_speed", Description.Variations, 200.0f)); Camera->SetISO( - RetrieveActorAttributeToFloat("iso", Description.Variations, 200.0f)); + RetrieveActorAttributeToFloat("iso", Description.Variations, 100.0f)); Camera->SetAperture( RetrieveActorAttributeToFloat("fstop", Description.Variations, 1.4f)); diff --git a/Unreal/CarlaUE4/Source/CarlaUE4/CarlaMapGenerator.cpp b/Unreal/CarlaUE4/Source/CarlaUE4/CarlaMapGenerator.cpp deleted file mode 100644 index 3592b499be0..00000000000 --- a/Unreal/CarlaUE4/Source/CarlaUE4/CarlaMapGenerator.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma -// de Barcelona (UAB). -// -// This work is licensed under the terms of the MIT license. -// For a copy, see . - -#include "CarlaUE4.h" -#include "CarlaMapGenerator.h" - -ACarlaMapGenerator::ACarlaMapGenerator(const FObjectInitializer& ObjectInitializer) - : Super(ObjectInitializer) -{ -#define SET_STATIC_MESH(Tag, Folder, FileName) \ - { \ - static const ConstructorHelpers::FObjectFinder MeshObj( \ - TEXT("StaticMesh'" Folder "/" FileName "." FileName "'")); \ - SetStaticMesh(ECityMapMeshTag:: Tag, MeshObj.Object); \ - } - -#define PREFIX_FOLDER "/Game/Carla/Static/" - - SET_STATIC_MESH(RoadTwoLanes_LaneLeft, PREFIX_FOLDER "Road", "St_Road_TileRoad_RoadL"); - SET_STATIC_MESH(RoadTwoLanes_LaneRight, PREFIX_FOLDER "Road", "St_Road_TileRoad_RoadR"); - SET_STATIC_MESH(RoadTwoLanes_SidewalkLeft, PREFIX_FOLDER "SideWalk", "St_Road_TileRoad_SidewalkL"); - SET_STATIC_MESH(RoadTwoLanes_SidewalkRight, PREFIX_FOLDER "SideWalk", "St_Road_TileRoad_SidewalkR"); - SET_STATIC_MESH(RoadTwoLanes_LaneMarkingSolid, PREFIX_FOLDER "RoadLine", "St_Road_TileRoad_LaneMarkingSolid"); - SET_STATIC_MESH(RoadTwoLanes_LaneMarkingBroken, PREFIX_FOLDER "RoadLine", "St_Road_TileRoad_LaneMarkingBroken"); - - SET_STATIC_MESH(Road90DegTurn_Lane0, PREFIX_FOLDER "Road", "St_Road_Curve_Road0"); - SET_STATIC_MESH(Road90DegTurn_Lane1, PREFIX_FOLDER "Road", "St_Road_Curve_Road1"); - SET_STATIC_MESH(Road90DegTurn_Lane2, PREFIX_FOLDER "Road", "St_Road_Curve_Road2"); - SET_STATIC_MESH(Road90DegTurn_Lane3, PREFIX_FOLDER "Road", "St_Road_Curve_Road3"); - SET_STATIC_MESH(Road90DegTurn_Lane4, PREFIX_FOLDER "Road", "St_Road_Curve_Road4"); - SET_STATIC_MESH(Road90DegTurn_Lane5, PREFIX_FOLDER "Road", "St_Road_Curve_Road5"); - SET_STATIC_MESH(Road90DegTurn_Lane6, PREFIX_FOLDER "Road", "St_Road_Curve_Road6"); - SET_STATIC_MESH(Road90DegTurn_Lane7, PREFIX_FOLDER "Road", "St_Road_Curve_Road7"); - SET_STATIC_MESH(Road90DegTurn_Lane8, PREFIX_FOLDER "Road", "St_Road_Curve_Road8"); - SET_STATIC_MESH(Road90DegTurn_Lane9, PREFIX_FOLDER "Road", "St_Road_Curve_Road9"); - SET_STATIC_MESH(Road90DegTurn_Sidewalk0, PREFIX_FOLDER "SideWalk", "St_Road_Curve_Sidewalk1"); - SET_STATIC_MESH(Road90DegTurn_Sidewalk1, PREFIX_FOLDER "SideWalk", "St_Road_Curve_Sidewalk2"); - SET_STATIC_MESH(Road90DegTurn_Sidewalk2, PREFIX_FOLDER "SideWalk", "St_Road_Curve_Sidewalk3"); - SET_STATIC_MESH(Road90DegTurn_Sidewalk3, PREFIX_FOLDER "SideWalk", "St_Road_Curve_Sidewalk4"); - SET_STATIC_MESH(Road90DegTurn_LaneMarking, PREFIX_FOLDER "RoadLine", "St_Road_Curve_LaneMarking"); - - SET_STATIC_MESH(RoadTIntersection_Lane0, PREFIX_FOLDER "Road", "St_Road_TCross_Road0"); - SET_STATIC_MESH(RoadTIntersection_Lane1, PREFIX_FOLDER "Road", "St_Road_TCross_Road1"); - SET_STATIC_MESH(RoadTIntersection_Lane2, PREFIX_FOLDER "Road", "St_Road_TCross_Road2"); - SET_STATIC_MESH(RoadTIntersection_Lane3, PREFIX_FOLDER "Road", "St_Road_TCross_Road3"); - SET_STATIC_MESH(RoadTIntersection_Lane4, PREFIX_FOLDER "Road", "St_Road_TCross_Road4"); - SET_STATIC_MESH(RoadTIntersection_Lane5, PREFIX_FOLDER "Road", "St_Road_TCross_Road5"); - SET_STATIC_MESH(RoadTIntersection_Lane6, PREFIX_FOLDER "Road", "St_Road_TCross_Road6"); - SET_STATIC_MESH(RoadTIntersection_Lane7, PREFIX_FOLDER "Road", "St_Road_TCross_Road7"); - SET_STATIC_MESH(RoadTIntersection_Lane8, PREFIX_FOLDER "Road", "St_Road_TCross_Road8"); - SET_STATIC_MESH(RoadTIntersection_Lane9, PREFIX_FOLDER "Road", "St_Road_TCross_Road9"); - SET_STATIC_MESH(RoadTIntersection_Sidewalk0, PREFIX_FOLDER "SideWalk", "St_Road_TCross_Sidewalk1"); - SET_STATIC_MESH(RoadTIntersection_Sidewalk1, PREFIX_FOLDER "SideWalk", "St_Road_TCross_Sidewalk2"); - SET_STATIC_MESH(RoadTIntersection_Sidewalk2, PREFIX_FOLDER "SideWalk", "St_Road_TCross_Sidewalk3"); - SET_STATIC_MESH(RoadTIntersection_Sidewalk3, PREFIX_FOLDER "SideWalk", "St_Road_TCross_Sidewalk4"); - SET_STATIC_MESH(RoadTIntersection_LaneMarking, PREFIX_FOLDER "RoadLine", "St_Road_TCross_LaneMarking"); - - SET_STATIC_MESH(RoadXIntersection_Lane0, PREFIX_FOLDER "Road", "St_Road_XCross_Road0"); - SET_STATIC_MESH(RoadXIntersection_Lane1, PREFIX_FOLDER "Road", "St_Road_XCross_Road1"); - SET_STATIC_MESH(RoadXIntersection_Lane2, PREFIX_FOLDER "Road", "St_Road_XCross_Road2"); - SET_STATIC_MESH(RoadXIntersection_Lane3, PREFIX_FOLDER "Road", "St_Road_XCross_Road3"); - SET_STATIC_MESH(RoadXIntersection_Lane4, PREFIX_FOLDER "Road", "St_Road_XCross_Road4"); - SET_STATIC_MESH(RoadXIntersection_Lane5, PREFIX_FOLDER "Road", "St_Road_XCross_Road5"); - SET_STATIC_MESH(RoadXIntersection_Lane6, PREFIX_FOLDER "Road", "St_Road_XCross_Road6"); - SET_STATIC_MESH(RoadXIntersection_Lane7, PREFIX_FOLDER "Road", "St_Road_XCross_Road7"); - SET_STATIC_MESH(RoadXIntersection_Lane8, PREFIX_FOLDER "Road", "St_Road_XCross_Road8"); - SET_STATIC_MESH(RoadXIntersection_Lane9, PREFIX_FOLDER "Road", "St_Road_XCross_Road9"); - SET_STATIC_MESH(RoadXIntersection_Sidewalk0, PREFIX_FOLDER "SideWalk", "St_Road_XCross_Sidewalk1"); - SET_STATIC_MESH(RoadXIntersection_Sidewalk1, PREFIX_FOLDER "SideWalk", "St_Road_XCross_Sidewalk2"); - SET_STATIC_MESH(RoadXIntersection_Sidewalk2, PREFIX_FOLDER "SideWalk", "St_Road_XCross_Sidewalk3"); - SET_STATIC_MESH(RoadXIntersection_Sidewalk3, PREFIX_FOLDER "SideWalk", "St_Road_XCross_Sidewalk4"); - SET_STATIC_MESH(RoadXIntersection_LaneMarking, PREFIX_FOLDER "RoadLine", "St_Road_XCross_LaneMarking"); - -#undef PREFIX_FOLDER -#undef SET_STATIC_MESH -} diff --git a/Unreal/CarlaUE4/Source/CarlaUE4/CarlaMapGenerator.h b/Unreal/CarlaUE4/Source/CarlaUE4/CarlaMapGenerator.h deleted file mode 100644 index b3608a54669..00000000000 --- a/Unreal/CarlaUE4/Source/CarlaUE4/CarlaMapGenerator.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma -// de Barcelona (UAB). -// -// This work is licensed under the terms of the MIT license. -// For a copy, see . - -#pragma once - -#include "CityMapGenerator.h" -#include "CarlaMapGenerator.generated.h" - -/// Generates the city map using CARLA assets. -UCLASS() -class CARLAUE4_API ACarlaMapGenerator : public ACityMapGenerator -{ - GENERATED_BODY() - -public: - - ACarlaMapGenerator(const FObjectInitializer& ObjectInitializer); -}; From 16ae46e47dcccb853cbc4e8cb66d461b54baae2a Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Wed, 16 Sep 2020 17:40:27 +0200 Subject: [PATCH 084/179] Fixed ISO to 100 --- .../Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp index ab20878a235..5eaf607b80d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp @@ -460,7 +460,7 @@ void UActorBlueprintFunctionLibrary::MakeCameraDefinition( FActorVariation ISO; // S ISO.Id = TEXT("iso"); ISO.Type = EActorAttributeType::Float; - ISO.RecommendedValues = { TEXT("200.0") }; + ISO.RecommendedValues = { TEXT("100.0") }; ISO.bRestrictToRecommended = false; // Defines the size of the opening for the camera lens. From 3b81872f05fb098f94a931a56dc27c62625399be Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Wed, 16 Sep 2020 17:44:13 +0200 Subject: [PATCH 085/179] Updated content version --- Util/ContentVersions.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Util/ContentVersions.txt b/Util/ContentVersions.txt index 6521f78d34a..113e7ced66b 100644 --- a/Util/ContentVersions.txt +++ b/Util/ContentVersions.txt @@ -32,4 +32,4 @@ 0.9.7: 20191221_c88604b 0.9.8: 20200306_06b6cb1 0.9.9: 20200422_ea5179a -Latest: 20200915_24120cd +Latest: 20200916_5b00e8a From 7e0546f9c8b7493215aa1e8e99f8f0ca15db2811 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Thu, 17 Sep 2020 10:49:50 +0200 Subject: [PATCH 086/179] Fixed open3d example name --- PythonAPI/examples/{open3d.py => open3d_lidar.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename PythonAPI/examples/{open3d.py => open3d_lidar.py} (100%) diff --git a/PythonAPI/examples/open3d.py b/PythonAPI/examples/open3d_lidar.py similarity index 100% rename from PythonAPI/examples/open3d.py rename to PythonAPI/examples/open3d_lidar.py From 943b04a580f1331f65ea98bfc9fc7bae67520330 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Thu, 17 Sep 2020 15:28:53 +0200 Subject: [PATCH 087/179] Updated EV100 values --- .../Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp | 4 ++-- .../Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp index 5eaf607b80d..ffb89883004 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp @@ -486,7 +486,7 @@ void UActorBlueprintFunctionLibrary::MakeCameraDefinition( FActorVariation ExposureMaxBright; ExposureMaxBright.Id = TEXT("exposure_max_bright"); ExposureMaxBright.Type = EActorAttributeType::Float; - ExposureMaxBright.RecommendedValues = { TEXT("20.0") }; + ExposureMaxBright.RecommendedValues = { TEXT("9.0") }; ExposureMaxBright.bRestrictToRecommended = false; // The speed at which the adaptation occurs from a dark environment @@ -1410,7 +1410,7 @@ void UActorBlueprintFunctionLibrary::SetCamera( Camera->SetExposureMinBrightness( RetrieveActorAttributeToFloat("exposure_min_bright", Description.Variations, 7.0f)); Camera->SetExposureMaxBrightness( - RetrieveActorAttributeToFloat("exposure_max_bright", Description.Variations, 20.0f)); + RetrieveActorAttributeToFloat("exposure_max_bright", Description.Variations, 9.0f)); Camera->SetExposureSpeedUp( RetrieveActorAttributeToFloat("exposure_speed_up", Description.Variations, 3.0f)); Camera->SetExposureSpeedDown( diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp index 20aad523937..549511bba72 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp @@ -526,13 +526,17 @@ namespace SceneCaptureSensor_local_ns { // Exposure PostProcessSettings.bOverride_AutoExposureMethod = true; - PostProcessSettings.AutoExposureMethod = EAutoExposureMethod::AEM_Manual; + PostProcessSettings.AutoExposureMethod = EAutoExposureMethod::AEM_Histogram; PostProcessSettings.bOverride_AutoExposureBias = true; PostProcessSettings.bOverride_AutoExposureMinBrightness = true; PostProcessSettings.bOverride_AutoExposureMaxBrightness = true; PostProcessSettings.bOverride_AutoExposureSpeedUp = true; PostProcessSettings.bOverride_AutoExposureSpeedDown = true; PostProcessSettings.bOverride_AutoExposureCalibrationConstant = true; + PostProcessSettings.bOverride_HistogramLogMin = true; + PostProcessSettings.HistogramLogMin = 1.0f; + PostProcessSettings.bOverride_HistogramLogMax = true; + PostProcessSettings.HistogramLogMax = 12.0f; // Camera PostProcessSettings.bOverride_CameraShutterSpeed = true; From 78c75648356a4eae8fec2a842a48fb0f5255f3d2 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Thu, 17 Sep 2020 15:40:52 +0200 Subject: [PATCH 088/179] Updated ExposureCompensation --- .../Carla/Actor/ActorBlueprintFunctionLibrary.cpp | 4 ++-- .../Source/Carla/Sensor/SceneCaptureSensor.cpp | 14 ++++++++++---- Util/BuildTools/BuildCarlaUE4.sh | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp index ffb89883004..629e4591bf8 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorBlueprintFunctionLibrary.cpp @@ -441,7 +441,7 @@ void UActorBlueprintFunctionLibrary::MakeCameraDefinition( FActorVariation ExposureCompensation; ExposureCompensation.Id = TEXT("exposure_compensation"); ExposureCompensation.Type = EActorAttributeType::Float; - ExposureCompensation.RecommendedValues = { TEXT("-1.8") }; + ExposureCompensation.RecommendedValues = { TEXT("0.0") }; ExposureCompensation.bRestrictToRecommended = false; // - Manual ------------------------------------------------ @@ -1399,7 +1399,7 @@ void UActorBlueprintFunctionLibrary::SetCamera( Camera->SetExposureMethod(EAutoExposureMethod::AEM_Manual); } Camera->SetExposureCompensation( - RetrieveActorAttributeToFloat("exposure_compensation", Description.Variations, -1.8f)); + RetrieveActorAttributeToFloat("exposure_compensation", Description.Variations, 0.0f)); Camera->SetShutterSpeed( RetrieveActorAttributeToFloat("shutter_speed", Description.Variations, 200.0f)); Camera->SetISO( diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp index 549511bba72..798baf2280d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp @@ -110,12 +110,12 @@ EAutoExposureMethod ASceneCaptureSensor::GetExposureMethod() const void ASceneCaptureSensor::SetExposureCompensation(float Compensation) { check(CaptureComponent2D != nullptr); - // Looks like windows and linux have different outputs with the - // same exposure compensation #if PLATFORM_LINUX - CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation; + // Looks like Windows and Linux have different outputs with the + // same exposure compensation, this fixes it. + CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation - 1.5f; #else - CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation + 1.8f; + CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation; #endif } @@ -563,6 +563,12 @@ namespace SceneCaptureSensor_local_ns { // Color Grading PostProcessSettings.bOverride_WhiteTemp = true; PostProcessSettings.bOverride_WhiteTint = true; + PostProcessSettings.bOverride_ColorContrast = true; +#if PLATFORM_LINUX + // Looks like Windows and Linux have different outputs with the + // same exposure compensation, this fixes it. + PostProcessSettings.ColorContrast = FVector4(1.5f, 1.5f, 1.5f, 1.0f); +#endif // Chromatic Aberration PostProcessSettings.bOverride_SceneFringeIntensity = true; diff --git a/Util/BuildTools/BuildCarlaUE4.sh b/Util/BuildTools/BuildCarlaUE4.sh index 56a734ca3f5..fbf68299393 100755 --- a/Util/BuildTools/BuildCarlaUE4.sh +++ b/Util/BuildTools/BuildCarlaUE4.sh @@ -120,7 +120,7 @@ if ${BUILD_CARLAUE4} ; then # This command fails sometimes but normally we can continue anyway. set +e log "Generate Unreal project files." - ${UE4_ROOT}/GenerateProjectFiles.sh -project="${PWD}/CarlaUE4.uproject" -game -engine -makefiles + ${UE4_ROOT}/GenerateProjectFiles.sh -project="${PWD}/CarlaUE4.uproject" -game -engine -makefile set -e fi From df74d94a12739db8ee0e6f28b9515a1254b5ec69 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Thu, 17 Sep 2020 18:10:00 +0200 Subject: [PATCH 089/179] Updated CHANGELOG and content versions --- CHANGELOG.md | 2 ++ Util/ContentVersions.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f25d2968ff5..153257bfc72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ * All sensors are now multi-stream, that means that the same sensor can be listened from different clients * Fixed point cloud of LiDAR. Now the points are given correctly in the sensor's coordinate system * Fixed light intensity and camera parameters to match + * Fixed and improved auto exposure camera (`histogram` exposure mode) + * RGB cameras `exposure_mode` is now set to `histogram` by default * New Lidar sensor ('lidar.ray_cast_semantic') that returns the point cloud with information regarding to the object that have collided: incident angle, idx of collided actor and it semantic tag * Added `opend3D.py`, a more friendly LiDAR visualizer * Exposed matrix form of transformation to the client and Python API diff --git a/Util/ContentVersions.txt b/Util/ContentVersions.txt index 113e7ced66b..3f0247cffe6 100644 --- a/Util/ContentVersions.txt +++ b/Util/ContentVersions.txt @@ -32,4 +32,4 @@ 0.9.7: 20191221_c88604b 0.9.8: 20200306_06b6cb1 0.9.9: 20200422_ea5179a -Latest: 20200916_5b00e8a +Latest: 20200917_7b9254b From 6b9124f0135f71ceef7d6462a98b644a4b2b13a7 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Thu, 17 Sep 2020 18:16:50 +0200 Subject: [PATCH 090/179] Added an accidentally removed `s` --- Util/BuildTools/BuildCarlaUE4.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Util/BuildTools/BuildCarlaUE4.sh b/Util/BuildTools/BuildCarlaUE4.sh index fbf68299393..56a734ca3f5 100755 --- a/Util/BuildTools/BuildCarlaUE4.sh +++ b/Util/BuildTools/BuildCarlaUE4.sh @@ -120,7 +120,7 @@ if ${BUILD_CARLAUE4} ; then # This command fails sometimes but normally we can continue anyway. set +e log "Generate Unreal project files." - ${UE4_ROOT}/GenerateProjectFiles.sh -project="${PWD}/CarlaUE4.uproject" -game -engine -makefile + ${UE4_ROOT}/GenerateProjectFiles.sh -project="${PWD}/CarlaUE4.uproject" -game -engine -makefiles set -e fi From 33f39e30ee3fed8227ec03a1f5dcf67f8b5b03d9 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Fri, 18 Sep 2020 11:21:03 +0200 Subject: [PATCH 091/179] Changed Color Contrast from1.5 to 1.2 --- .../Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp index 798baf2280d..9b1df2c611e 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp @@ -567,7 +567,7 @@ namespace SceneCaptureSensor_local_ns { #if PLATFORM_LINUX // Looks like Windows and Linux have different outputs with the // same exposure compensation, this fixes it. - PostProcessSettings.ColorContrast = FVector4(1.5f, 1.5f, 1.5f, 1.0f); + PostProcessSettings.ColorContrast = FVector4(1.2f, 1.2f, 1.2f, 1.0f); #endif // Chromatic Aberration From fb96d7f6c79f1e5c615e041bdc1c180b64f0ee14 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Fri, 18 Sep 2020 13:27:27 +0200 Subject: [PATCH 092/179] Updated ContentVersions --- Util/ContentVersions.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Util/ContentVersions.txt b/Util/ContentVersions.txt index 3f0247cffe6..3e8371eea74 100644 --- a/Util/ContentVersions.txt +++ b/Util/ContentVersions.txt @@ -32,4 +32,4 @@ 0.9.7: 20191221_c88604b 0.9.8: 20200306_06b6cb1 0.9.9: 20200422_ea5179a -Latest: 20200917_7b9254b +Latest: 20200918_0931149 From 9586cd24d55c7d3231ec02eaf01ec75066eabfde Mon Sep 17 00:00:00 2001 From: Axel1092 <35765780+Axel1092@users.noreply.github.com> Date: Mon, 21 Sep 2020 14:42:18 +0200 Subject: [PATCH 093/179] Existing actors in replayer are positioned to the initial position. (#3328) --- .../Carla/Source/Carla/Recorder/CarlaReplayerHelper.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayerHelper.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayerHelper.cpp index 11c1fcb0ea8..01090ba5ea1 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayerHelper.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Recorder/CarlaReplayerHelper.cpp @@ -54,6 +54,10 @@ std::pairCarlaReplayerHelper::TryToCreateReplayerActor( if (desc->Id == ActorDesc.Id) { // we don't need to create, actor of same type already exist + // relocate + FRotator Rot = FRotator::MakeFromEuler(Rotation); + FTransform Trans2(Rot, Location, FVector(1, 1, 1)); + view.GetActor()->SetActorTransform(Trans2, false, nullptr, ETeleportType::TeleportPhysics); return std::pair(2, view); } } From cc7b1ea910612f81e526aa95c492141e49c98f32 Mon Sep 17 00:00:00 2001 From: doterop Date: Mon, 21 Sep 2020 18:22:03 +0200 Subject: [PATCH 094/179] Retrieve BBs of all the elements of the level (#3301) * Added new function to calculate BBs on SKM and SM * Added BB calculation for an array of actors * Added BB folliage calculation * Added a call on the GM to get all the BBs of the level * Fixed Folliage BB calculation. * GM::GetAllBBsOfLevel now returns the array of BBs * Added call on the server side to retrieve the BBs * Removed debug draw calls * Added call to the PythonAPI * Added check for empty folliage actors * Added missing EOF * Added new RotateVector function * Added rotation to the BBs * Update changelog * Split BB calculation on more functions * Add tag query and simplified Folliage actor BB calculation * Look for ISM instead of HISM * Cleaning comments * Fixed BB duplication on BP_Procedural_Buildings * Fixed BB duplication on vehicles BPs * Added pedestrians case * Added CityObjectLabel enum on PythonAPI * Splitted logic in small functions * Fixed uint8_t * Merged BB of the lights in a TL * Splitted work into more functions * Added missing BB and rotation to TL * Cleaned comments * Added missing include * Changed None to Any in PythonAPI * Fixed Any enum * Added check for empty folliage actors * Added missing EOF * Added new RotateVector function * Added rotation to the BBs * Update changelog * Split BB calculation on more functions * Add tag query and simplified Folliage actor BB calculation * Look for ISM instead of HISM * Cleaning comments * Fixed BB duplication on BP_Procedural_Buildings * Fixed BB duplication on vehicles BPs * Added pedestrians case * Added CityObjectLabel enum on PythonAPI * Splitted logic in small functions * Fixed uint8_t * Merged BB of the lights in a TL * Splitted work into more functions * Added missing BB and rotation to TL * Cleaned comments * Changed None to Any in PythonAPI * Fixed Any enum * Fixed rebase --- CHANGELOG.md | 1 + LibCarla/source/carla/client/World.cpp | 4 +- LibCarla/source/carla/client/World.h | 2 +- .../source/carla/client/detail/Client.cpp | 4 +- LibCarla/source/carla/client/detail/Client.h | 2 +- .../source/carla/client/detail/Simulator.h | 4 +- LibCarla/source/carla/geom/BoundingBox.h | 32 +- LibCarla/source/carla/geom/Rotation.h | 28 ++ LibCarla/source/carla/rpc/ObjectLabel.h | 45 ++ PythonAPI/carla/source/libcarla/Geom.cpp | 3 +- PythonAPI/carla/source/libcarla/World.cpp | 33 +- .../Carla/Source/Carla/Actor/ActorInfo.h | 7 +- .../Source/Carla/Actor/ActorRegistry.cpp | 6 +- .../Carla/Source/Carla/CityMapGenerator.cpp | 4 +- .../Source/Carla/Game/CarlaGameModeBase.cpp | 6 +- .../Source/Carla/Game/CarlaGameModeBase.h | 2 +- .../Carla/Source/Carla/Game/Tagger.cpp | 62 +-- .../Plugins/Carla/Source/Carla/Game/Tagger.h | 54 +-- .../Carla/Sensor/RayCastSemanticLidar.cpp | 4 +- .../Carla/Source/Carla/Server/CarlaServer.cpp | 4 +- .../Carla/Util/BoundingBoxCalculator.cpp | 410 ++++++++++++++---- .../Source/Carla/Util/BoundingBoxCalculator.h | 47 +- 22 files changed, 569 insertions(+), 195 deletions(-) create mode 100644 LibCarla/source/carla/rpc/ObjectLabel.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 153257bfc72..a1090b2b357 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ * Fixed minor typo in the introduction section of documentation. * Fixed a bug at the local planner when changing the route, causing it to maintain the first part of the previous one. This was only relevant when using very large buffer sizes. * Added automatic calculation of vehicle's BB + * Retrieve BBs of all the elements of the level ## CARLA 0.9.9 diff --git a/LibCarla/source/carla/client/World.cpp b/LibCarla/source/carla/client/World.cpp index 757bf5676d5..df477cbab38 100644 --- a/LibCarla/source/carla/client/World.cpp +++ b/LibCarla/source/carla/client/World.cpp @@ -158,8 +158,8 @@ namespace client { _episode.Lock()->FreezeAllTrafficLights(frozen); } - std::vector World::GetLevelBBs() const { - return _episode.Lock()->GetLevelBBs(); + std::vector World::GetLevelBBs(uint8_t queried_tag) const { + return _episode.Lock()->GetLevelBBs(queried_tag); } } // namespace client diff --git a/LibCarla/source/carla/client/World.h b/LibCarla/source/carla/client/World.h index 5040b232235..41086e19fd1 100644 --- a/LibCarla/source/carla/client/World.h +++ b/LibCarla/source/carla/client/World.h @@ -151,7 +151,7 @@ namespace client { void FreezeAllTrafficLights(bool frozen); /// Returns all the BBs of all the elements of the level - std::vector GetLevelBBs() const; + std::vector GetLevelBBs(uint8_t queried_tag) const; private: diff --git a/LibCarla/source/carla/client/detail/Client.cpp b/LibCarla/source/carla/client/detail/Client.cpp index 64c9edd6a54..e1933e9dfc7 100644 --- a/LibCarla/source/carla/client/detail/Client.cpp +++ b/LibCarla/source/carla/client/detail/Client.cpp @@ -413,9 +413,9 @@ namespace detail { _pimpl->AsyncCall("update_lights_state", _pimpl->endpoint, std::move(lights), discard_client); } - std::vector Client::GetLevelBBs() const { + std::vector Client::GetLevelBBs(uint8_t queried_tag) const { using return_t = std::vector; - return _pimpl->CallAndWait("get_all_level_BBs"); + return _pimpl->CallAndWait("get_all_level_BBs", queried_tag); } } // namespace detail diff --git a/LibCarla/source/carla/client/detail/Client.h b/LibCarla/source/carla/client/detail/Client.h index e941eaeed9a..5b1875c6404 100644 --- a/LibCarla/source/carla/client/detail/Client.h +++ b/LibCarla/source/carla/client/detail/Client.h @@ -257,7 +257,7 @@ namespace detail { bool discard_client = false) const; /// Returns all the BBs of all the elements of the level - std::vector GetLevelBBs() const; + std::vector GetLevelBBs(uint8_t queried_tag) const; private: diff --git a/LibCarla/source/carla/client/detail/Simulator.h b/LibCarla/source/carla/client/detail/Simulator.h index f6605d765d0..384feb38f07 100644 --- a/LibCarla/source/carla/client/detail/Simulator.h +++ b/LibCarla/source/carla/client/detail/Simulator.h @@ -227,8 +227,8 @@ namespace detail { } /// Returns all the BBs of all the elements of the level - std::vector GetLevelBBs() const { - return _client.GetLevelBBs(); + std::vector GetLevelBBs(uint8_t queried_tag) const { + return _client.GetLevelBBs(queried_tag); } /// @} diff --git a/LibCarla/source/carla/geom/BoundingBox.h b/LibCarla/source/carla/geom/BoundingBox.h index 726b90b5605..8790d78dcc2 100644 --- a/LibCarla/source/carla/geom/BoundingBox.h +++ b/LibCarla/source/carla/geom/BoundingBox.h @@ -30,6 +30,11 @@ namespace geom { // -- Constructors --------------------------------------------------------- // ========================================================================= + explicit BoundingBox(const Location &in_location, const Vector3D &in_extent, const Rotation &in_rotation) + : location(in_location), + extent(in_extent), + rotation(in_rotation) {} + explicit BoundingBox(const Location &in_location, const Vector3D &in_extent) : location(in_location), extent(in_extent) {} @@ -38,7 +43,8 @@ namespace geom { : extent(in_extent) {} Location location; ///< Center of the BoundingBox in local space - Vector3D extent; ///< Half the size of the BoundingBox in local space + Vector3D extent; ///< Half the size of the BoundingBox in local space + Rotation rotation; ///< Rotation of the BoundingBox in local space // ========================================================================= // -- Other methods -------------------------------------------------------- @@ -63,15 +69,16 @@ namespace geom { * Returns the positions of the 8 vertices of this BoundingBox in local space. */ std::array GetLocalVertices() const { + return {{ - location + Location(-extent.x,-extent.y,-extent.z), - location + Location(-extent.x,-extent.y, extent.z), - location + Location(-extent.x, extent.y,-extent.z), - location + Location(-extent.x, extent.y, extent.z), - location + Location( extent.x,-extent.y,-extent.z), - location + Location( extent.x,-extent.y, extent.z), - location + Location( extent.x, extent.y,-extent.z), - location + Location( extent.x, extent.y, extent.z) + location + Location(rotation.RotateVector({-extent.x,-extent.y,-extent.z})), + location + Location(rotation.RotateVector({-extent.x,-extent.y, extent.z})), + location + Location(rotation.RotateVector({-extent.x, extent.y,-extent.z})), + location + Location(rotation.RotateVector({-extent.x, extent.y, extent.z})), + location + Location(rotation.RotateVector({ extent.x,-extent.y,-extent.z})), + location + Location(rotation.RotateVector({ extent.x,-extent.y, extent.z})), + location + Location(rotation.RotateVector({ extent.x, extent.y,-extent.z})), + location + Location(rotation.RotateVector({ extent.x, extent.y, extent.z})) }}; } @@ -92,7 +99,7 @@ namespace geom { // ========================================================================= bool operator==(const BoundingBox &rhs) const { - return (location == rhs.location) && (extent == rhs.extent); + return (location == rhs.location) && (extent == rhs.extent) && (rotation == rhs.rotation); } bool operator!=(const BoundingBox &rhs) const { @@ -107,11 +114,12 @@ namespace geom { BoundingBox(const FBoundingBox &Box) : location(Box.Origin), - extent(1e-2f * Box.Extent.X, 1e-2f * Box.Extent.Y, 1e-2f * Box.Extent.Z) {} + extent(1e-2f * Box.Extent.X, 1e-2f * Box.Extent.Y, 1e-2f * Box.Extent.Z), + rotation(Box.Rotation) {} #endif // LIBCARLA_INCLUDED_FROM_UE4 - MSGPACK_DEFINE_ARRAY(location, extent); + MSGPACK_DEFINE_ARRAY(location, extent, rotation); }; } // namespace geom diff --git a/LibCarla/source/carla/geom/Rotation.h b/LibCarla/source/carla/geom/Rotation.h index 6afe21b083e..207f20b15a8 100644 --- a/LibCarla/source/carla/geom/Rotation.h +++ b/LibCarla/source/carla/geom/Rotation.h @@ -87,6 +87,34 @@ namespace geom { in_point = out_point; } + Vector3D RotateVector(const Vector3D& in_point) const { + // Rotates Rz(yaw) * Ry(pitch) * Rx(roll) = first x, then y, then z. + const float cy = std::cos(Math::ToRadians(yaw)); + const float sy = std::sin(Math::ToRadians(yaw)); + const float cr = std::cos(Math::ToRadians(roll)); + const float sr = std::sin(Math::ToRadians(roll)); + const float cp = std::cos(Math::ToRadians(pitch)); + const float sp = std::sin(Math::ToRadians(pitch)); + + Vector3D out_point; + out_point.x = + in_point.x * (cp * cy) + + in_point.y * (cy * sp * sr - sy * cr) + + in_point.z * (-cy * sp * cr - sy * sr); + + out_point.y = + in_point.x * (cp * sy) + + in_point.y * (sy * sp * sr + cy * cr) + + in_point.z * (-sy * sp * cr + cy * sr); + + out_point.z = + in_point.x * (sp) + + in_point.y * (-cp * sr) + + in_point.z * (cp * cr); + + return out_point; + } + void InverseRotateVector(Vector3D &in_point) const { // Applies the transposed of the matrix used in RotateVector function, // which is the rotation inverse. diff --git a/LibCarla/source/carla/rpc/ObjectLabel.h b/LibCarla/source/carla/rpc/ObjectLabel.h new file mode 100644 index 00000000000..5b7b5d30db2 --- /dev/null +++ b/LibCarla/source/carla/rpc/ObjectLabel.h @@ -0,0 +1,45 @@ +// Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma +// de Barcelona (UAB). +// +// This work is licensed under the terms of the MIT license. +// For a copy, see . + +#pragma once + +#include "carla/MsgPack.h" + +#include + +namespace carla { +namespace rpc { + + enum class CityObjectLabel : uint8_t { + None = 0u, + Buildings = 1u, + Fences = 2u, + Other = 3u, + Pedestrians = 4u, + Poles = 5u, + RoadLines = 6u, + Roads = 7u, + Sidewalks = 8u, + TrafficSigns = 12u, + Vegetation = 9u, + Vehicles = 10u, + Walls = 11u, + Sky = 13u, + Ground = 14u, + Bridge = 15u, + RailTrack = 16u, + GuardRail = 17u, + TrafficLight = 18u, + Static = 19u, + Dynamic = 20u, + Water = 21u, + Terrain = 22u, + }; + +} // namespace rpc +} // namespace carla + +MSGPACK_ADD_ENUM(carla::rpc::CityObjectLabel); diff --git a/PythonAPI/carla/source/libcarla/Geom.cpp b/PythonAPI/carla/source/libcarla/Geom.cpp index 333d98ed38b..c772176364e 100644 --- a/PythonAPI/carla/source/libcarla/Geom.cpp +++ b/PythonAPI/carla/source/libcarla/Geom.cpp @@ -205,9 +205,10 @@ void export_geom() { class_("BoundingBox") .def(init( - (arg("location")=cg::Location(), arg("extent")=cg::Vector3D()))) + (arg("location")=cg::Location(), arg("extent")=cg::Vector3D(), arg("rotation")=cg::Rotation()))) .def_readwrite("location", &cg::BoundingBox::location) .def_readwrite("extent", &cg::BoundingBox::extent) + .def_readwrite("rotation", &cg::BoundingBox::rotation) .def("contains", &cg::BoundingBox::Contains, arg("point"), arg("bbox_transform")) .def("get_local_vertices", CALL_RETURNING_LIST(cg::BoundingBox, GetLocalVertices)) .def("get_world_vertices", CALL_RETURNING_LIST_1(cg::BoundingBox, GetWorldVertices, const cg::Transform&), arg("bbox_transform")) diff --git a/PythonAPI/carla/source/libcarla/World.cpp b/PythonAPI/carla/source/libcarla/World.cpp index 0a1a3d971bf..387efb605d7 100644 --- a/PythonAPI/carla/source/libcarla/World.cpp +++ b/PythonAPI/carla/source/libcarla/World.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -70,10 +71,10 @@ static auto GetVehiclesLightStates(carla::client::World &self) { return dict; } -static auto GetLevelBBs(const carla::client::World &self) { +static auto GetLevelBBs(const carla::client::World &self, uint8_t queried_tag) { carla::PythonUtil::ReleaseGIL unlock; boost::python::list result; - for (const auto &bb : self.GetLevelBBs()) { + for (const auto &bb : self.GetLevelBBs(queried_tag)) { result.append(bb); } return result; @@ -135,6 +136,32 @@ void export_world() { .value("SpringArm", cr::AttachmentType::SpringArm) ; + enum_("CityObjectLabel") + .value("Any", cr::CityObjectLabel::None) + .value("Buildings", cr::CityObjectLabel::Buildings) + .value("Fences", cr::CityObjectLabel::Fences) + .value("Other", cr::CityObjectLabel::Other) + .value("Pedestrians", cr::CityObjectLabel::Pedestrians) + .value("Poles", cr::CityObjectLabel::Poles) + .value("RoadLines", cr::CityObjectLabel::RoadLines) + .value("Roads", cr::CityObjectLabel::Roads) + .value("Sidewalks", cr::CityObjectLabel::Sidewalks) + .value("TrafficSigns", cr::CityObjectLabel::TrafficSigns) + .value("Vegetation", cr::CityObjectLabel::Vegetation) + .value("Vehicles", cr::CityObjectLabel::Vehicles) + .value("Walls", cr::CityObjectLabel::Walls) + .value("Sky", cr::CityObjectLabel::Sky) + .value("Ground", cr::CityObjectLabel::Ground) + .value("Bridge", cr::CityObjectLabel::Bridge) + .value("RailTrack", cr::CityObjectLabel::RailTrack) + .value("GuardRail", cr::CityObjectLabel::GuardRail) + .value("TrafficLight", cr::CityObjectLabel::TrafficLight) + .value("Static", cr::CityObjectLabel::Static) + .value("Dynamic", cr::CityObjectLabel::Dynamic) + .value("Water", cr::CityObjectLabel::Water) + .value("Terrain", cr::CityObjectLabel::Terrain) + ; + #define SPAWN_ACTOR_WITHOUT_GIL(fn) +[]( \ cc::World &self, \ const cc::ActorBlueprint &blueprint, \ @@ -177,7 +204,7 @@ void export_world() { .def("get_traffic_light", CONST_CALL_WITHOUT_GIL_1(cc::World, GetTrafficLight, cc::Landmark), arg("landmark")) .def("get_lightmanager", CONST_CALL_WITHOUT_GIL(cc::World, GetLightManager)) .def("freeze_all_traffic_lights", &cc::World::FreezeAllTrafficLights, (arg("frozen"))) - .def("get_level_bbs", &GetLevelBBs) + .def("get_level_bbs", &GetLevelBBs, (arg("actor_type")=cr::CityObjectLabel::None)) .def(self_ns::str(self_ns::self)) ; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorInfo.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorInfo.h index 9f407ea59b1..8b0e9aac7a5 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorInfo.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorInfo.h @@ -11,8 +11,11 @@ #include #include +#include #include +namespace crp = carla::rpc; + /// A view over an actor and its properties. struct FActorInfo { @@ -20,11 +23,11 @@ struct FActorInfo FActorDescription Description; - TSet SemanticTags; + TSet SemanticTags; FBoundingBox BoundingBox; - carla::rpc::Actor SerializedData; + crp::Actor SerializedData; /// @todo To be used solely by the FWorldObserver. mutable FVector Velocity = {0.0f, 0.0f, 0.0f}; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorRegistry.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorRegistry.cpp index a62a6480681..953ef34474b 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorRegistry.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorRegistry.cpp @@ -13,6 +13,8 @@ #include "Carla/Traffic/TrafficLightBase.h" #include "Carla/Util/BoundingBoxCalculator.h" +namespace crp = carla::rpc; + static FActorView::ActorType FActorRegistry_GetActorType(const FActorView &View) { if (!View.IsValid()) @@ -41,11 +43,11 @@ static FActorView::ActorType FActorRegistry_GetActorType(const FActorView &View) } } -static FString GetRelevantTagAsString(const TSet &SemanticTags) +static FString GetRelevantTagAsString(const TSet &SemanticTags) { for (auto &&Tag : SemanticTags) { - if ((Tag != ECityObjectLabel::None) && (Tag != ECityObjectLabel::Other)) + if ((Tag != crp::CityObjectLabel::None) && (Tag != crp::CityObjectLabel::Other)) { auto Str = ATagger::GetTagAsString(Tag).ToLower(); return (Str.EndsWith(TEXT("s")) ? Str.LeftChop(1) : Str); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/CityMapGenerator.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/CityMapGenerator.cpp index d4cb13f85c1..1e92bcfc28a 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/CityMapGenerator.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/CityMapGenerator.cpp @@ -22,6 +22,8 @@ #include #endif // CARLA_ROAD_GENERATOR_EXTRA_LOG +namespace crp = carla::rpc; + // ============================================================================= // -- Private types ------------------------------------------------------------ // ============================================================================= @@ -248,7 +250,7 @@ static bool LineTrace( if (Success) { for (FHitResult &Item : OutHits) { - if (ATagger::MatchComponent(*Item.Component, ECityObjectLabel::Roads)) { + if (ATagger::MatchComponent(*Item.Component, crp::CityObjectLabel::Roads)) { HitResult = Item; return true; } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp index 47a68e63468..fba24c8ba74 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp @@ -332,7 +332,7 @@ void ACarlaGameModeBase::DebugShowSignals(bool enable) } -TArray ACarlaGameModeBase::GetAllBBsOfLevel() +TArray ACarlaGameModeBase::GetAllBBsOfLevel(uint8 TagQueried) { UWorld* World = GetWorld(); @@ -341,7 +341,7 @@ TArray ACarlaGameModeBase::GetAllBBsOfLevel() UGameplayStatics::GetAllActorsOfClass(World, AActor::StaticClass(), FoundActors); TArray BoundingBoxes; - BoundingBoxes = UBoundingBoxCalculator::GetBoundingBoxOfActors(FoundActors); + BoundingBoxes = UBoundingBoxCalculator::GetBoundingBoxOfActors(FoundActors, TagQueried); return BoundingBoxes; -} \ No newline at end of file +} diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h index 5c1376f891b..9abcc6ce995 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h @@ -53,7 +53,7 @@ class CARLA_API ACarlaGameModeBase : public AGameModeBase ATrafficLightManager* GetTrafficLightManager(); UFUNCTION(Category = "Carla Game Mode", BlueprintCallable, CallInEditor, Exec) - TArray GetAllBBsOfLevel(); + TArray GetAllBBsOfLevel(uint8 TagQueried = 0); protected: diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp index b5011fc66a2..e214af2e48d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp @@ -14,46 +14,48 @@ #include "EngineUtils.h" #include "PhysicsEngine/PhysicsAsset.h" +namespace crp = carla::rpc; + template static auto CastEnum(T label) { return static_cast::type>(label); } -ECityObjectLabel ATagger::GetLabelByFolderName(const FString &String) { - if (String == "Building") return ECityObjectLabel::Buildings; - else if (String == "Fence") return ECityObjectLabel::Fences; - else if (String == "Pedestrian") return ECityObjectLabel::Pedestrians; - else if (String == "Pole") return ECityObjectLabel::Poles; - else if (String == "Other") return ECityObjectLabel::Other; - else if (String == "Road") return ECityObjectLabel::Roads; - else if (String == "RoadLine") return ECityObjectLabel::RoadLines; - else if (String == "SideWalk") return ECityObjectLabel::Sidewalks; - else if (String == "TrafficSign") return ECityObjectLabel::TrafficSigns; - else if (String == "Vegetation") return ECityObjectLabel::Vegetation; - else if (String == "Vehicles") return ECityObjectLabel::Vehicles; - else if (String == "Wall") return ECityObjectLabel::Walls; - else if (String == "Sky") return ECityObjectLabel::Sky; - else if (String == "Ground") return ECityObjectLabel::Ground; - else if (String == "Bridge") return ECityObjectLabel::Bridge; - else if (String == "RailTrack") return ECityObjectLabel::RailTrack; - else if (String == "GuardRail") return ECityObjectLabel::GuardRail; - else if (String == "TrafficLight") return ECityObjectLabel::TrafficLight; - else if (String == "Static") return ECityObjectLabel::Static; - else if (String == "Dynamic") return ECityObjectLabel::Dynamic; - else if (String == "Water") return ECityObjectLabel::Water; - else if (String == "Terrain") return ECityObjectLabel::Terrain; - else return ECityObjectLabel::None; +crp::CityObjectLabel ATagger::GetLabelByFolderName(const FString &String) { + if (String == "Building") return crp::CityObjectLabel::Buildings; + else if (String == "Fence") return crp::CityObjectLabel::Fences; + else if (String == "Pedestrian") return crp::CityObjectLabel::Pedestrians; + else if (String == "Pole") return crp::CityObjectLabel::Poles; + else if (String == "Other") return crp::CityObjectLabel::Other; + else if (String == "Road") return crp::CityObjectLabel::Roads; + else if (String == "RoadLine") return crp::CityObjectLabel::RoadLines; + else if (String == "SideWalk") return crp::CityObjectLabel::Sidewalks; + else if (String == "TrafficSign") return crp::CityObjectLabel::TrafficSigns; + else if (String == "Vegetation") return crp::CityObjectLabel::Vegetation; + else if (String == "Vehicles") return crp::CityObjectLabel::Vehicles; + else if (String == "Wall") return crp::CityObjectLabel::Walls; + else if (String == "Sky") return crp::CityObjectLabel::Sky; + else if (String == "Ground") return crp::CityObjectLabel::Ground; + else if (String == "Bridge") return crp::CityObjectLabel::Bridge; + else if (String == "RailTrack") return crp::CityObjectLabel::RailTrack; + else if (String == "GuardRail") return crp::CityObjectLabel::GuardRail; + else if (String == "TrafficLight") return crp::CityObjectLabel::TrafficLight; + else if (String == "Static") return crp::CityObjectLabel::Static; + else if (String == "Dynamic") return crp::CityObjectLabel::Dynamic; + else if (String == "Water") return crp::CityObjectLabel::Water; + else if (String == "Terrain") return crp::CityObjectLabel::Terrain; + else return crp::CityObjectLabel::None; } void ATagger::SetStencilValue( UPrimitiveComponent &Component, - const ECityObjectLabel &Label, + const crp::CityObjectLabel &Label, const bool bSetRenderCustomDepth) { Component.SetCustomDepthStencilValue(CastEnum(Label)); Component.SetRenderCustomDepth( bSetRenderCustomDepth && - (Label != ECityObjectLabel::None)); + (Label != crp::CityObjectLabel::None)); } // ============================================================================= @@ -98,24 +100,24 @@ void ATagger::TagActorsInLevel(UWorld &World, bool bTagForSemanticSegmentation) } } -void ATagger::GetTagsOfTaggedActor(const AActor &Actor, TSet &Tags) +void ATagger::GetTagsOfTaggedActor(const AActor &Actor, TSet &Tags) { TArray Components; Actor.GetComponents(Components); for (auto *Component : Components) { if (Component != nullptr) { const auto Tag = GetTagOfTaggedComponent(*Component); - if (Tag != ECityObjectLabel::None) { + if (Tag != crp::CityObjectLabel::None) { Tags.Add(Tag); } } } } -FString ATagger::GetTagAsString(const ECityObjectLabel Label) +FString ATagger::GetTagAsString(const crp::CityObjectLabel Label) { switch (Label) { -#define CARLA_GET_LABEL_STR(lbl) case ECityObjectLabel:: lbl : return TEXT(#lbl); +#define CARLA_GET_LABEL_STR(lbl) case crp::CityObjectLabel:: lbl : return TEXT(#lbl); default: CARLA_GET_LABEL_STR(None) CARLA_GET_LABEL_STR(Buildings) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h index 7237bcaaf10..5c8e578c538 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h @@ -8,34 +8,14 @@ #include "GameFramework/Actor.h" #include "Components/PrimitiveComponent.h" + +#include +#include +#include + #include "Tagger.generated.h" -enum class ECityObjectLabel : uint8 -{ - None = 0u, - Buildings = 1u, - Fences = 2u, - Other = 3u, - Pedestrians = 4u, - Poles = 5u, - RoadLines = 6u, - Roads = 7u, - Sidewalks = 8u, - TrafficSigns = 12u, - Vegetation = 9u, - Vehicles = 10u, - Walls = 11u, - Sky = 13u, - Ground = 14u, - Bridge = 15u, - RailTrack = 16u, - GuardRail = 17u, - TrafficLight = 18u, - Static = 19u, - Dynamic = 20u, - Water = 21u, - Terrain = 22u, -}; +namespace crp = carla::rpc; /// Sets actors' custom depth stencil value for semantic segmentation according /// to their meshes. @@ -67,40 +47,40 @@ class CARLA_API ATagger : public AActor static void TagActorsInLevel(UWorld &World, bool bTagForSemanticSegmentation); /// Retrieve the tag of an already tagged component. - static ECityObjectLabel GetTagOfTaggedComponent(const UPrimitiveComponent &Component) + static crp::CityObjectLabel GetTagOfTaggedComponent(const UPrimitiveComponent &Component) { - return static_cast(Component.CustomDepthStencilValue); + return static_cast(Component.CustomDepthStencilValue); } - /// Retrieve the tags of an already tagged actor. ECityObjectLabel::None is + /// Retrieve the tags of an already tagged actor. CityObjectLabel::None is /// not added to the array. - static void GetTagsOfTaggedActor(const AActor &Actor, TSet &Tags); + static void GetTagsOfTaggedActor(const AActor &Actor, TSet &Tags); /// Return true if @a Component has been tagged with the given @a Tag. - static bool MatchComponent(const UPrimitiveComponent &Component, ECityObjectLabel Tag) + static bool MatchComponent(const UPrimitiveComponent &Component, crp::CityObjectLabel Tag) { return (Tag == GetTagOfTaggedComponent(Component)); } - /// Retrieve the tags of an already tagged actor. ECityObjectLabel::None is + /// Retrieve the tags of an already tagged actor. CityObjectLabel::None is /// not added to the array. - static FString GetTagAsString(ECityObjectLabel Tag); + static FString GetTagAsString(crp::CityObjectLabel Tag); /// Method that computes the label corresponding to a folder path - static ECityObjectLabel GetLabelByFolderName(const FString &String); + static crp::CityObjectLabel GetLabelByFolderName(const FString &String); /// Method that computes the label corresponding to an specific object /// using the folder path in which it is stored template - static ECityObjectLabel GetLabelByPath(const T *Object) { + static crp::CityObjectLabel GetLabelByPath(const T *Object) { const FString Path = Object->GetPathName(); TArray StringArray; Path.ParseIntoArray(StringArray, TEXT("/"), false); - return (StringArray.Num() > 4 ? GetLabelByFolderName(StringArray[4]) : ECityObjectLabel::None); + return (StringArray.Num() > 4 ? GetLabelByFolderName(StringArray[4]) : crp::CityObjectLabel::None); } static void SetStencilValue(UPrimitiveComponent &Component, - const ECityObjectLabel &Label, const bool bSetRenderCustomDepth); + const crp::CityObjectLabel &Label, const bool bSetRenderCustomDepth); ATagger(); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/RayCastSemanticLidar.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/RayCastSemanticLidar.cpp index 052dea24c2f..92b6a53323a 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/RayCastSemanticLidar.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/RayCastSemanticLidar.cpp @@ -19,6 +19,8 @@ #include "Runtime/Engine/Classes/Kismet/KismetMathLibrary.h" #include "Runtime/Core/Public/Async/ParallelFor.h" +namespace crp = carla::rpc; + FActorDefinition ARayCastSemanticLidar::GetSensorDefinition() { return UActorBlueprintFunctionLibrary::MakeLidarDefinition(TEXT("ray_cast_semantic")); @@ -160,7 +162,7 @@ void ARayCastSemanticLidar::ComputeRawDetection(const FHitResult& HitInfo, const AActor* actor = HitInfo.Actor.Get(); Detection.object_idx = 0; - Detection.object_tag = static_cast(ECityObjectLabel::None); + Detection.object_tag = static_cast(crp::CityObjectLabel::None); if (actor != nullptr) { FActorView view = Registry.Find(actor); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp index 60dedb32b91..121ec6c07d0 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp @@ -306,7 +306,7 @@ void FCarlaServer::FPimpl::BindActions() return Episode->SerializeActor(ActorView); }; - BIND_SYNC(get_all_level_BBs) << [this]() -> R> + BIND_SYNC(get_all_level_BBs) << [this](uint8 QueriedTag) -> R> { REQUIRE_CARLA_EPISODE(); TArray Result; @@ -315,7 +315,7 @@ void FCarlaServer::FPimpl::BindActions() { RESPOND_ERROR("unable to find CARLA game mode"); } - Result = GameMode->GetAllBBsOfLevel(); + Result = GameMode->GetAllBBsOfLevel(QueriedTag); return MakeVectorFromTArray(Result); }; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp index e5d8e8e2b0d..4f4c016c10b 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp @@ -15,7 +15,61 @@ #include "Rendering/SkeletalMeshRenderData.h" -FBoundingBox UBoundingBoxCalculator::GetActorBoundingBox(const AActor *Actor) + +namespace crp = carla::rpc; + +static FBoundingBox ApplyTransformToBB( + const FBoundingBox& InBoundingBox, + const FTransform& Transform) +{ + const FRotator Rotation = Transform.GetRotation().Rotator(); + const FVector Translation = Transform.GetLocation(); + const FVector Scale = Transform.GetScale3D(); + + FBoundingBox BoundingBox = InBoundingBox; + BoundingBox.Origin *= Scale; + BoundingBox.Origin = Rotation.RotateVector(BoundingBox.Origin) + Translation; + BoundingBox.Extent *= Scale; + BoundingBox.Rotation = Rotation; + + return BoundingBox; +} + +static FBoundingBox CombineBBs(const TArray& BBsToCombine) +{ + FVector MaxVertex(TNumericLimits::Lowest()); + FVector MinVertex(TNumericLimits::Max()); + + for(const FBoundingBox& BB : BBsToCombine) { + FVector MaxVertexOfBB = BB.Origin + BB.Extent; + FVector MinVertexOfBB = BB.Origin - BB.Extent; + + MaxVertex.X = (MaxVertexOfBB.X > MaxVertex.X) ? MaxVertexOfBB.X : MaxVertex.X; + MaxVertex.Y = (MaxVertexOfBB.Y > MaxVertex.Y) ? MaxVertexOfBB.Y : MaxVertex.Y; + MaxVertex.Z = (MaxVertexOfBB.Z > MaxVertex.Z) ? MaxVertexOfBB.Z : MaxVertex.Z; + MinVertex.X = (MinVertexOfBB.X < MinVertex.X) ? MinVertexOfBB.X : MinVertex.X; + MinVertex.Y = (MinVertexOfBB.Y < MinVertex.Y) ? MinVertexOfBB.Y : MinVertex.Y; + MinVertex.Z = (MinVertexOfBB.Z < MinVertex.Z) ? MinVertexOfBB.Z : MinVertex.Z; + } + + // Calculate box extent + FVector Extent ( + (MaxVertex.X - MinVertex.X) * 0.5f, + (MaxVertex.Y - MinVertex.Y) * 0.5f, + (MaxVertex.Z - MinVertex.Z) * 0.5f + ); + + // Calculate middle point + FVector Origin ( + (MinVertex.X + Extent.X), + (MinVertex.Y + Extent.Y), + (MinVertex.Z + Extent.Z) + ); + + return {Origin, Extent}; +} + +FBoundingBox UBoundingBoxCalculator::GetActorBoundingBox(const AActor *Actor, uint8 InTagQueried) { if (Actor != nullptr) { @@ -59,10 +113,132 @@ FBoundingBox UBoundingBoxCalculator::GetActorBoundingBox(const AActor *Actor) return {}; } } + + } return {}; } +FBoundingBox UBoundingBoxCalculator::GetVehicleBoundingBox( + const ACarlaWheeledVehicle* Vehicle, + uint8 InTagQueried) +{ + check(Vehicle); + + crp::CityObjectLabel TagQueried = (crp::CityObjectLabel)InTagQueried; + bool FilterByTagEnabled = (TagQueried != crp::CityObjectLabel::None); + + UActorComponent *ActorComp = Vehicle->GetComponentByClass(USkeletalMeshComponent::StaticClass()); + USkeletalMeshComponent* Comp = Cast(ActorComp); + + // Filter by tag + crp::CityObjectLabel Tag = ATagger::GetTagOfTaggedComponent(*Comp); + if(FilterByTagEnabled && Tag != TagQueried) return {}; + + USkeletalMesh* SkeletalMesh = Comp->SkeletalMesh; + FBoundingBox BoundingBox = GetSkeletalMeshBoundingBox(SkeletalMesh); + if(BoundingBox.Extent.IsZero()) + { + UE_LOG(LogCarla, Error, TEXT("%s has no SKM assigned"), *Vehicle->GetName()); + return {}; + } + + // Component-to-world transform for this component + const FTransform& CompToWorldTransform = Comp->GetComponentTransform(); + BoundingBox = ApplyTransformToBB(BoundingBox, CompToWorldTransform); + + return BoundingBox; +} + +FBoundingBox UBoundingBoxCalculator::GetCharacterBoundingBox( + const ACharacter* Character, + uint8 InTagQueried) +{ + check(Character); + + UCapsuleComponent* Capsule = Character->GetCapsuleComponent(); + if (Capsule) + { + const float Radius = Capsule->GetScaledCapsuleRadius(); + const float HalfHeight = Capsule->GetScaledCapsuleHalfHeight(); + FBoundingBox BoundingBox; + // Characters have the pivot point centered. + BoundingBox.Origin = {0.0f, 0.0f, 0.0f}; + BoundingBox.Extent = {Radius, Radius, HalfHeight}; + // Component-to-world transform for this component + const FTransform& CompToWorldTransform = Capsule->GetComponentTransform(); + BoundingBox = ApplyTransformToBB(BoundingBox, CompToWorldTransform); + + return BoundingBox; + } + + return {}; +} + +void UBoundingBoxCalculator::GetTrafficLightBoundingBox( + const ATrafficLightBase* TrafficLight, + TArray& OutBB, + uint8 InTagQueried) +{ + check(TrafficLight); + + TArray BBsOfTL; + TArray StaticMeshComps; + TrafficLight->GetComponents(StaticMeshComps); + GetBBsOfStaticMeshComponents(StaticMeshComps, BBsOfTL, InTagQueried); + + // This kind of a magic number relying that the lights of a TL are not bigger than 100. + // and we are gonna compare against a squared distance + const float DistanceThreshold = 100.0f * 100.0f; + + // The BBs of the TL are calculated per light, so we need to merge the full-box + TSet IndicesDiscarded; + for(int i = 0; i < BBsOfTL.Num(); i++) + { + // Check if the index was used to merge a previous BB + if(IndicesDiscarded.Contains(i)) continue; + + TArray BBsToCombine; + FBoundingBox& BB1 = BBsOfTL[i]; + + for(int j = i + 1; j < BBsOfTL.Num(); j++) + { + // Check if the index was used to merge a previous BB + if(IndicesDiscarded.Contains(j)) continue; + + FBoundingBox& BB2 = BBsOfTL[j]; + + float Distance = FVector::DistSquared(BB1.Origin, BB2.Origin); + + // If the lights are close enough, we merge it + if(Distance <= DistanceThreshold) + { + BBsToCombine.Emplace(BB2); + IndicesDiscarded.Emplace(j); + } + } + if(BBsToCombine.Num() > 0) + { + BBsToCombine.Emplace(BB1); + IndicesDiscarded.Emplace(i); + FBoundingBox MergedBB = CombineBBs(BBsToCombine); + MergedBB.Rotation = BB1.Rotation; + OutBB.Add(MergedBB); + } + } + + // Add the BB of the meshes that didn't need to combine (ie: poles) + for(int i = 0; i < BBsOfTL.Num(); i++) + { + // Check if the index was used to merge a previous BB + if(IndicesDiscarded.Contains(i)) continue; + FBoundingBox& BB = BBsOfTL[i]; + OutBB.Add(BB); + } + +} + + // TODO: update to calculate current animation pose FBoundingBox UBoundingBoxCalculator::GetSkeletalMeshBoundingBox(const USkeletalMesh* SkeletalMesh) { @@ -80,7 +256,7 @@ FBoundingBox UBoundingBoxCalculator::GetSkeletalMeshBoundingBox(const USkeletalM uint32 NumVertices = FPositionVertexBuffer.GetNumVertices(); // Look for Skeletal Mesh bounds (vertex perfect) - FVector MaxVertex(TNumericLimits::Min()); + FVector MaxVertex(TNumericLimits::Lowest()); FVector MinVertex(TNumericLimits::Max()); for(uint32 i = 0; i < NumVertices; i++) { @@ -93,13 +269,6 @@ FBoundingBox UBoundingBoxCalculator::GetSkeletalMeshBoundingBox(const USkeletalM MinVertex.Z = (Pos.Z < MinVertex.Z) ? Pos.Z : MinVertex.Z; } - // Calculate middle point - FVector Origin ( - (MaxVertex.X + MinVertex.X) * 0.5f, - (MaxVertex.Y + MinVertex.Y) * 0.5f, - (MaxVertex.Z + MinVertex.Z) * 0.5f - ); - // Calculate box extent FVector Extent ( (MaxVertex.X - MinVertex.X) * 0.5f, @@ -107,6 +276,13 @@ FBoundingBox UBoundingBoxCalculator::GetSkeletalMeshBoundingBox(const USkeletalM (MaxVertex.Z - MinVertex.Z) * 0.5f ); + // Calculate middle point + FVector Origin ( + (MinVertex.X + Extent.X), + (MinVertex.Y + Extent.Y), + (MinVertex.Z + Extent.Z) + ); + return {Origin, Extent}; } @@ -119,115 +295,175 @@ FBoundingBox UBoundingBoxCalculator::GetStaticMeshBoundingBox(const UStaticMesh* } FBox Box = StaticMesh->GetBoundingBox(); - return {Box.GetCenter(), Box.GetExtent()}; } -// TODO: Dynamic vehicle, avoid SM of collision -TArray UBoundingBoxCalculator::GetBoundingBoxOfActors(const TArray& Actors) +void UBoundingBoxCalculator::GetISMBoundingBox( + UInstancedStaticMeshComponent* ISMComp, + TArray& OutBoundingBox) { - TArray Result; - - int ActorIndex = 0; - for(AActor* Actor : Actors) + if(!ISMComp) { - //UE_LOG(LogCarla, Warning, TEXT(" %d / %d"), ActorIndex, Actors.Num()); - ActorIndex++; + UE_LOG(LogCarla, Error, TEXT("GetISMBoundingBox no ISMComp")); + return; + } - AInstancedFoliageActor* InstancedFolliageActor = Cast(Actor); - if(InstancedFolliageActor != nullptr) - { - TMap>& FoliageInstancesMap = InstancedFolliageActor->FoliageInfos; + const UStaticMesh *Mesh = ISMComp->GetStaticMesh(); + const FBoundingBox SMBoundingBox = GetStaticMeshBoundingBox(Mesh); + if(SMBoundingBox.Extent.IsZero()) + { + UE_LOG(LogCarla, Error, TEXT("%s has no SM assigned to the ISM"), *ISMComp->GetOwner()->GetName()); + return; + } - UE_LOG(LogCarla, Warning, TEXT("FolliageActor with %d FoliageTypes"), FoliageInstancesMap.Num()); + const TArray& PerInstanceSMData = ISMComp->PerInstanceSMData; - int FoliageIndex = 0; - for(auto& FoliagePair: FoliageInstancesMap) - { - const UFoliageType* FoliageType = FoliagePair.Key; - const FFoliageInfo& FoliageInfo = FoliagePair.Value.Get(); - const UFoliageType_InstancedStaticMesh* FoliageType_ISM = Cast(FoliageType); + for(auto& InstSMIData : PerInstanceSMData) + { + const FTransform Transform = FTransform(InstSMIData.Transform); + FBoundingBox BoundingBox = ApplyTransformToBB(SMBoundingBox, Transform); + OutBoundingBox.Add(BoundingBox); + } - UHierarchicalInstancedStaticMeshComponent* HISMComp = FoliageInfo.GetComponent(); +} - UStaticMesh *Mesh = FoliageType_ISM->GetStaticMesh(); - FBoundingBox SMBoundingBox = GetStaticMeshBoundingBox(Mesh); +void UBoundingBoxCalculator::GetBBsOfStaticMeshComponents( + const TArray& StaticMeshComps, + TArray& OutBB, + uint8 InTagQueried) +{ + crp::CityObjectLabel TagQueried = (crp::CityObjectLabel)InTagQueried; + bool FilterByTagEnabled = (TagQueried != crp::CityObjectLabel::None); - int32 NumHISMInstances = HISMComp->GetNumRenderInstances(); + for(UStaticMeshComponent* Comp : StaticMeshComps) + { + // Filter by tag + crp::CityObjectLabel Tag = ATagger::GetTagOfTaggedComponent(*Comp); + if(FilterByTagEnabled && Tag != TagQueried) continue; - UE_LOG(LogCarla, Warning, TEXT(" %d/%d : NumHISMInstances = %d"), - FoliageIndex, FoliageInstancesMap.Num(), NumHISMInstances); - FoliageIndex++; + UStaticMesh* StaticMesh = Comp->GetStaticMesh(); + FBoundingBox BoundingBox = GetStaticMeshBoundingBox(StaticMesh); - const TArray& PerInstanceSMData = HISMComp->PerInstanceSMData; + if(BoundingBox.Extent.IsZero()) + { + UE_LOG(LogCarla, Error, TEXT("%s has no SM assigned"), *Comp->GetOwner()->GetName()); + } + else + { + // Component-to-world transform for this component + const FTransform& CompToWorldTransform = Comp->GetComponentTransform(); + BoundingBox = ApplyTransformToBB(BoundingBox, CompToWorldTransform); + OutBB.Add(BoundingBox); + } + } +} - for(auto& InstSMIData : PerInstanceSMData) - { - FTransform Transform = FTransform(InstSMIData.Transform); - FRotator Rotation = Transform.GetRotation().Rotator(); - FVector Translation = Transform.GetLocation(); - FVector Scale = Transform.GetScale3D(); +void UBoundingBoxCalculator::GetBBsOfSkeletalMeshComponents( + const TArray& SkeletalMeshComps, + TArray& OutBB, + uint8 InTagQueried) +{ + crp::CityObjectLabel TagQueried = (crp::CityObjectLabel)InTagQueried; + bool FilterByTagEnabled = (TagQueried != crp::CityObjectLabel::None); - FBoundingBox BoundingBox = SMBoundingBox; - BoundingBox.Origin *= Scale; - BoundingBox.Origin = Rotation.RotateVector(BoundingBox.Origin) + Translation; - BoundingBox.Extent *= Scale; - BoundingBox.Rotation = Rotation; - Result.Add(BoundingBox); - } - } + for(USkeletalMeshComponent* Comp : SkeletalMeshComps) + { + // Filter by tag + crp::CityObjectLabel Tag = ATagger::GetTagOfTaggedComponent(*Comp); + if(FilterByTagEnabled && Tag != TagQueried) continue; + USkeletalMesh* SkeletalMesh = Comp->SkeletalMesh; + FBoundingBox BoundingBox = GetSkeletalMeshBoundingBox(SkeletalMesh); + if(BoundingBox.Extent.IsZero()) + { + UE_LOG(LogCarla, Error, TEXT("%s has no SKM assigned"), *Comp->GetOwner()->GetName()); } else { - TArray MeshComps; - Actor->GetComponents(MeshComps); + // Component-to-world transform for this component + const FTransform& CompToWorldTransform = Comp->GetComponentTransform(); + BoundingBox = ApplyTransformToBB(BoundingBox, CompToWorldTransform); + OutBB.Add(BoundingBox); + } + } +} + +TArray UBoundingBoxCalculator::GetBoundingBoxOfActors( + const TArray& Actors, + uint8 InTagQueried) +{ + TArray Result; + crp::CityObjectLabel TagQueried = (crp::CityObjectLabel)InTagQueried; + bool FilterByTagEnabled = (TagQueried != crp::CityObjectLabel::None); - FVector WorldLocation = Actor->GetActorLocation(); - FVector WorldScale = Actor->GetActorScale(); - FRotator WorldRotation = Actor->GetActorRotation(); + for(AActor* Actor : Actors) + { + FString ClassName = Actor->GetClass()->GetName(); - // Find if there is some geometry component - TArray StaticMeshComps; - TArray SkeletalMeshComps; - Actor->GetComponents(StaticMeshComps); - Actor->GetComponents(SkeletalMeshComps); + // Avoid the BP_Procedural_Building to avoid duplication with their child actors + // When improved the BP_Procedural_Building this maybe should be removed + // Note: We don't use casting here because the base class is a BP and is easier to do it this way, + // than getting the UClass of the BP to cast the actor. + if(ClassName.Contains("BP_Procedural_Bulding")) continue; - // Calculate FBoundingBox of SM - for(UStaticMeshComponent* StaticMeshComp : StaticMeshComps) + // The vehicle's BP has a low-polystatic mesh for collisions, we should avoid it + ACarlaWheeledVehicle* Vehicle = Cast(Actor); + if (Vehicle) + { + FBoundingBox BoundingBox = GetVehicleBoundingBox(Vehicle, InTagQueried); + if(!BoundingBox.Extent.IsZero()) { - UStaticMesh* StaticMesh = StaticMeshComp->GetStaticMesh(); - FBoundingBox BoundingBox = GetStaticMeshBoundingBox(StaticMesh); - - if(BoundingBox.Extent.IsZero()) - { - UE_LOG(LogCarla, Error, TEXT("%s has no SM assigned"), *Actor->GetName()); - } - else - { - BoundingBox.Origin *= WorldScale; - BoundingBox.Origin = WorldRotation.RotateVector(BoundingBox.Origin) + WorldLocation; - BoundingBox.Extent *= WorldScale; - BoundingBox.Rotation = WorldRotation; - Result.Add(BoundingBox); - } + Result.Add(BoundingBox); } + continue; + } + - // Calculate FBoundingBox of SK_M - for(USkeletalMeshComponent* SkeletalMeshComp : SkeletalMeshComps) + // Pedestrians, we just use the capsule component at the moment. + ACharacter* Character = Cast(Actor); + if (Character) + { + FBoundingBox BoundingBox = GetCharacterBoundingBox(Character, InTagQueried); + if(!BoundingBox.Extent.IsZero()) { - USkeletalMesh* SkeletalMesh = SkeletalMeshComp->SkeletalMesh; - FBoundingBox BoundingBox = GetSkeletalMeshBoundingBox(SkeletalMesh); - BoundingBox.Origin *= WorldScale; - BoundingBox.Origin = WorldRotation.RotateVector(BoundingBox.Origin) + WorldLocation; - BoundingBox.Extent *= WorldScale; - BoundingBox.Rotation = WorldRotation; Result.Add(BoundingBox); } + continue; + } + + // TrafficLight, we need to join all the BB of the lights in one + ATrafficLightBase* TrafficLight = Cast(Actor); + if(TrafficLight) + { + GetTrafficLightBoundingBox(TrafficLight, Result, InTagQueried); + continue; } + + // Calculate FBoundingBox of SM + TArray StaticMeshComps; + Actor->GetComponents(StaticMeshComps); + GetBBsOfStaticMeshComponents(StaticMeshComps, Result, InTagQueried); + + // Calculate FBoundingBox of SK_M + TArray SkeletalMeshComps; + Actor->GetComponents(SkeletalMeshComps); + GetBBsOfSkeletalMeshComponents(SkeletalMeshComps, Result, InTagQueried); + + // Calculate FBoundingBox of ISM + TArray ISMComps; + Actor->GetComponents(ISMComps); + for(UInstancedStaticMeshComponent* Comp: ISMComps) + { + // Filter by tag + crp::CityObjectLabel Tag = ATagger::GetTagOfTaggedComponent(*Comp); + if(FilterByTagEnabled && Tag != TagQueried) continue; + + GetISMBoundingBox(Comp, Result); + } + } return Result; -} \ No newline at end of file +} diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h index cb393bf4b9e..ed641bc69bd 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h @@ -28,15 +28,52 @@ class CARLA_API UBoundingBoxCalculator : public UBlueprintFunctionLibrary /// /// @warning Traffic signs return its trigger box instead. UFUNCTION(Category = "Carla Actor", BlueprintCallable) - static FBoundingBox GetActorBoundingBox(const AActor *Actor); + static FBoundingBox GetActorBoundingBox( + const AActor *Actor, + uint8 InTagQueried = 0); - UFUNCTION(Category = "Carla Util", BlueprintCallable, CallInEditor) + UFUNCTION(Category = "Carla Actor", BlueprintCallable) + static FBoundingBox GetVehicleBoundingBox( + const ACarlaWheeledVehicle* Vehicle, + uint8 InTagQueried = 0); + + UFUNCTION(Category = "Carla Actor", BlueprintCallable) + static FBoundingBox GetCharacterBoundingBox( + const ACharacter* Character, + uint8 InTagQueried = 0); + + UFUNCTION(Category = "Carla Actor", BlueprintCallable) + static void GetTrafficLightBoundingBox( + const ATrafficLightBase* TrafficLight, + TArray& OutBB, + uint8 InTagQueried = 0); + + UFUNCTION(Category = "Carla Util", BlueprintCallable) static FBoundingBox GetSkeletalMeshBoundingBox(const USkeletalMesh* SkeletalMesh); - UFUNCTION(Category = "Carla Util", BlueprintCallable, CallInEditor) + UFUNCTION(Category = "Carla Util", BlueprintCallable) static FBoundingBox GetStaticMeshBoundingBox(const UStaticMesh* StaticMesh); - UFUNCTION(Category = "Carla Util", BlueprintCallable, CallInEditor) - static TArray GetBoundingBoxOfActors(const TArray& Actors); + UFUNCTION(Category = "Carla Util", BlueprintCallable) + static void GetISMBoundingBox( + UInstancedStaticMeshComponent* HISMComp, + TArray& OutBoundingBox); + + UFUNCTION(Category = "Carla Util", BlueprintCallable) + static void GetBBsOfStaticMeshComponents( + const TArray& StaticMeshComps, + TArray& OutBB, + uint8 InTagQueried = 0); + + UFUNCTION(Category = "Carla Util", BlueprintCallable) + static void GetBBsOfSkeletalMeshComponents( + const TArray& SkeletalMeshComps, + TArray& OutBB, + uint8 InTagQueried = 0); + + UFUNCTION(Category = "Carla Util", BlueprintCallable) + static TArray GetBoundingBoxOfActors( + const TArray& Actors, + uint8 InTagQueried = 0); }; From 9f5758577dfdb582ef40b7995ca0f6d657838fe6 Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Mon, 21 Sep 2020 19:38:40 +0200 Subject: [PATCH 095/179] SetVelocity -> SetTargetVelocity Change the commands set_velocity to set_target_velocity for both linear and angular velocities. --- LibCarla/source/carla/client/Actor.cpp | 8 ++++---- LibCarla/source/carla/client/Actor.h | 8 ++++---- LibCarla/source/carla/client/detail/Client.cpp | 8 ++++---- LibCarla/source/carla/client/detail/Client.h | 4 ++-- LibCarla/source/carla/client/detail/Simulator.h | 8 ++++---- LibCarla/source/carla/rpc/Command.h | 16 ++++++++-------- PythonAPI/carla/source/libcarla/Actor.cpp | 4 ++-- .../Carla/Source/Carla/Server/CarlaServer.cpp | 17 +++++++++-------- 8 files changed, 37 insertions(+), 36 deletions(-) diff --git a/LibCarla/source/carla/client/Actor.cpp b/LibCarla/source/carla/client/Actor.cpp index aee967280ff..87999be39a4 100644 --- a/LibCarla/source/carla/client/Actor.cpp +++ b/LibCarla/source/carla/client/Actor.cpp @@ -40,12 +40,12 @@ namespace client { GetEpisode().Lock()->SetActorTransform(*this, transform); } - void Actor::SetVelocity(const geom::Vector3D &vector) { - GetEpisode().Lock()->SetActorVelocity(*this, vector); + void Actor::SetTargetVelocity(const geom::Vector3D &vector) { + GetEpisode().Lock()->SetActorTargetVelocity(*this, vector); } - void Actor::SetAngularVelocity(const geom::Vector3D &vector) { - GetEpisode().Lock()->SetActorAngularVelocity(*this, vector); + void Actor::SetTargetAngularVelocity(const geom::Vector3D &vector) { + GetEpisode().Lock()->SetActorTargetAngularVelocity(*this, vector); } void Actor::AddImpulse(const geom::Vector3D &vector) { diff --git a/LibCarla/source/carla/client/Actor.h b/LibCarla/source/carla/client/Actor.h index 03f66b71d2a..bdc6e3ee549 100644 --- a/LibCarla/source/carla/client/Actor.h +++ b/LibCarla/source/carla/client/Actor.h @@ -64,11 +64,11 @@ namespace client { /// Teleport and rotate the actor to @a transform. void SetTransform(const geom::Transform &transform); - /// Set the actor velocity. - void SetVelocity(const geom::Vector3D &vector); + /// Set the actor velocity before applying physics. + void SetTargetVelocity(const geom::Vector3D &vector); - /// Set the angular velocity of the actor - void SetAngularVelocity(const geom::Vector3D &vector); + /// Set the angular velocity of the actor before applying physics. + void SetTargetAngularVelocity(const geom::Vector3D &vector); /// Add impulse to the actor. void AddImpulse(const geom::Vector3D &vector); diff --git a/LibCarla/source/carla/client/detail/Client.cpp b/LibCarla/source/carla/client/detail/Client.cpp index e1933e9dfc7..5859cf87070 100644 --- a/LibCarla/source/carla/client/detail/Client.cpp +++ b/LibCarla/source/carla/client/detail/Client.cpp @@ -264,12 +264,12 @@ namespace detail { _pimpl->AsyncCall("set_actor_transform", actor, transform); } - void Client::SetActorVelocity(rpc::ActorId actor, const geom::Vector3D &vector) { - _pimpl->AsyncCall("set_actor_velocity", actor, vector); + void Client::SetActorTargetVelocity(rpc::ActorId actor, const geom::Vector3D &vector) { + _pimpl->AsyncCall("set_actor_target_velocity", actor, vector); } - void Client::SetActorAngularVelocity(rpc::ActorId actor, const geom::Vector3D &vector) { - _pimpl->AsyncCall("set_actor_angular_velocity", actor, vector); + void Client::SetActorTargetAngularVelocity(rpc::ActorId actor, const geom::Vector3D &vector) { + _pimpl->AsyncCall("set_actor_target_angular_velocity", actor, vector); } void Client::AddActorImpulse(rpc::ActorId actor, const geom::Vector3D &vector) { diff --git a/LibCarla/source/carla/client/detail/Client.h b/LibCarla/source/carla/client/detail/Client.h index 5b1875c6404..45d3d96ac43 100644 --- a/LibCarla/source/carla/client/detail/Client.h +++ b/LibCarla/source/carla/client/detail/Client.h @@ -146,11 +146,11 @@ namespace detail { rpc::ActorId actor, const geom::Transform &transform); - void SetActorVelocity( + void SetActorTargetVelocity( rpc::ActorId actor, const geom::Vector3D &vector); - void SetActorAngularVelocity( + void SetActorTargetAngularVelocity( rpc::ActorId actor, const geom::Vector3D &vector); diff --git a/LibCarla/source/carla/client/detail/Simulator.h b/LibCarla/source/carla/client/detail/Simulator.h index 384feb38f07..2243f421652 100644 --- a/LibCarla/source/carla/client/detail/Simulator.h +++ b/LibCarla/source/carla/client/detail/Simulator.h @@ -319,16 +319,16 @@ namespace detail { return GetActorSnapshot(actor).velocity; } - void SetActorVelocity(const Actor &actor, const geom::Vector3D &vector) { - _client.SetActorVelocity(actor.GetId(), vector); + void SetActorTargetVelocity(const Actor &actor, const geom::Vector3D &vector) { + _client.SetActorTargetVelocity(actor.GetId(), vector); } geom::Vector3D GetActorAngularVelocity(const Actor &actor) const { return GetActorSnapshot(actor).angular_velocity; } - void SetActorAngularVelocity(const Actor &actor, const geom::Vector3D &vector) { - _client.SetActorAngularVelocity(actor.GetId(), vector); + void SetActorTargetAngularVelocity(const Actor &actor, const geom::Vector3D &vector) { + _client.SetActorTargetAngularVelocity(actor.GetId(), vector); } void AddActorImpulse(const Actor &actor, const geom::Vector3D &vector) { diff --git a/LibCarla/source/carla/rpc/Command.h b/LibCarla/source/carla/rpc/Command.h index c4191e7777c..6e689a2be24 100644 --- a/LibCarla/source/carla/rpc/Command.h +++ b/LibCarla/source/carla/rpc/Command.h @@ -102,9 +102,9 @@ namespace rpc { MSGPACK_DEFINE_ARRAY(actor, transform, speed); }; - struct ApplyVelocity : CommandBase { - ApplyVelocity() = default; - ApplyVelocity(ActorId id, const geom::Vector3D &value) + struct ApplyTargetVelocity : CommandBase { + ApplyTargetVelocity() = default; + ApplyTargetVelocity(ActorId id, const geom::Vector3D &value) : actor(id), velocity(value) {} ActorId actor; @@ -112,9 +112,9 @@ namespace rpc { MSGPACK_DEFINE_ARRAY(actor, velocity); }; - struct ApplyAngularVelocity : CommandBase { - ApplyAngularVelocity() = default; - ApplyAngularVelocity(ActorId id, const geom::Vector3D &value) + struct ApplyTargetAngularVelocity : CommandBase { + ApplyTargetAngularVelocity() = default; + ApplyTargetAngularVelocity(ActorId id, const geom::Vector3D &value) : actor(id), angular_velocity(value) {} ActorId actor; @@ -186,8 +186,8 @@ namespace rpc { ApplyWalkerControl, ApplyTransform, ApplyWalkerState, - ApplyVelocity, - ApplyAngularVelocity, + ApplyTargetVelocity, + ApplyTargetAngularVelocity, ApplyImpulse, ApplyAngularImpulse, SetSimulatePhysics, diff --git a/PythonAPI/carla/source/libcarla/Actor.cpp b/PythonAPI/carla/source/libcarla/Actor.cpp index 8cbfe61d045..564a35663ea 100644 --- a/PythonAPI/carla/source/libcarla/Actor.cpp +++ b/PythonAPI/carla/source/libcarla/Actor.cpp @@ -85,8 +85,8 @@ void export_actor() { .def("get_acceleration", &cc::Actor::GetAcceleration) .def("set_location", &cc::Actor::SetLocation, (arg("location"))) .def("set_transform", &cc::Actor::SetTransform, (arg("transform"))) - .def("set_velocity", &cc::Actor::SetVelocity, (arg("vector"))) - .def("set_angular_velocity", &cc::Actor::SetAngularVelocity, (arg("vector"))) + .def("set_target_velocity", &cc::Actor::SetTargetVelocity, (arg("vector"))) + .def("set_target_angular_velocity", &cc::Actor::SetTargetAngularVelocity, (arg("vector"))) .def("add_impulse", &cc::Actor::AddImpulse, (arg("vector"))) .def("add_angular_impulse", &cc::Actor::AddAngularImpulse, (arg("vector"))) .def("set_simulate_physics", &cc::Actor::SetSimulatePhysics, (arg("enabled") = true)) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp index 121ec6c07d0..6ce07a0b9db 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp @@ -512,7 +512,8 @@ void FCarlaServer::FPimpl::BindActions() return R::Success(); }; - BIND_SYNC(set_actor_velocity) << [this]( + + BIND_SYNC(set_actor_target_velocity) << [this]( cr::ActorId ActorId, cr::Vector3D vector) -> R { @@ -520,12 +521,12 @@ void FCarlaServer::FPimpl::BindActions() auto ActorView = Episode->FindActor(ActorId); if (!ActorView.IsValid()) { - RESPOND_ERROR("unable to set actor velocity: actor not found"); + RESPOND_ERROR("unable to set actor target velocity: actor not found"); } auto RootComponent = Cast(ActorView.GetActor()->GetRootComponent()); if (RootComponent == nullptr) { - RESPOND_ERROR("unable to set actor velocity: not supported by actor"); + RESPOND_ERROR("unable to set actor target velocity: not supported by actor"); } RootComponent->SetPhysicsLinearVelocity( vector.ToCentimeters().ToFVector(), @@ -534,7 +535,7 @@ void FCarlaServer::FPimpl::BindActions() return R::Success(); }; - BIND_SYNC(set_actor_angular_velocity) << [this]( + BIND_SYNC(set_actor_target_angular_velocity) << [this]( cr::ActorId ActorId, cr::Vector3D vector) -> R { @@ -542,12 +543,12 @@ void FCarlaServer::FPimpl::BindActions() auto ActorView = Episode->FindActor(ActorId); if (!ActorView.IsValid()) { - RESPOND_ERROR("unable to set actor angular velocity: actor not found"); + RESPOND_ERROR("unable to set actor target angular velocity: actor not found"); } auto RootComponent = Cast(ActorView.GetActor()->GetRootComponent()); if (RootComponent == nullptr) { - RESPOND_ERROR("unable to set actor angular velocity: not supported by actor"); + RESPOND_ERROR("unable to set actor target angular velocity: not supported by actor"); } RootComponent->SetPhysicsAngularVelocityInDegrees( vector.ToFVector(), @@ -1102,8 +1103,8 @@ void FCarlaServer::FPimpl::BindActions() [=](auto, const C::ApplyVehicleControl &c) { MAKE_RESULT(apply_control_to_vehicle(c.actor, c.control)); }, [=](auto, const C::ApplyWalkerControl &c) { MAKE_RESULT(apply_control_to_walker(c.actor, c.control)); }, [=](auto, const C::ApplyTransform &c) { MAKE_RESULT(set_actor_transform(c.actor, c.transform)); }, - [=](auto, const C::ApplyVelocity &c) { MAKE_RESULT(set_actor_velocity(c.actor, c.velocity)); }, - [=](auto, const C::ApplyAngularVelocity &c) { MAKE_RESULT(set_actor_angular_velocity(c.actor, c.angular_velocity)); }, + [=](auto, const C::ApplyTargetVelocity &c) { MAKE_RESULT(set_actor_target_velocity(c.actor, c.velocity)); }, + [=](auto, const C::ApplyTargetAngularVelocity &c) { MAKE_RESULT(set_actor_target_angular_velocity(c.actor, c.angular_velocity)); }, [=](auto, const C::ApplyImpulse &c) { MAKE_RESULT(add_actor_impulse(c.actor, c.impulse)); }, [=](auto, const C::ApplyAngularImpulse &c) { MAKE_RESULT(add_actor_angular_impulse(c.actor, c.impulse)); }, [=](auto, const C::SetSimulatePhysics &c) { MAKE_RESULT(set_actor_simulate_physics(c.actor, c.enabled)); }, From 6478d03657bef99dcdf0d31f35e767c2c10f113a Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Mon, 21 Sep 2020 20:11:23 +0200 Subject: [PATCH 096/179] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1090b2b357..2c773e56ea2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ * Added new semantic segmenation tags: `RailTrack`, `GuardRail`, `TrafficLight`, `Static`, `Dynamic`, `Water` and `Terrain` * Fixed several untagged and mistagged objects * Added vehicle light and street light data to recorder + * Change API: set_velocity to set_target_velocity for linear and angular velocities * Added API function `add_angular_impulse()` to add angular impulse to any actor * Fixed rain drop spawn issues when spawning camera sensors * Fixed assets import pipeline From f1dd2d77fa908af76215ba7a640fa5543b42b64d Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Mon, 21 Sep 2020 20:15:04 +0200 Subject: [PATCH 097/179] Added the change of name also in Commands of PythonAPI --- PythonAPI/carla/source/libcarla/Commands.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/PythonAPI/carla/source/libcarla/Commands.cpp b/PythonAPI/carla/source/libcarla/Commands.cpp index d9662ade90d..1e1e8d93c86 100644 --- a/PythonAPI/carla/source/libcarla/Commands.cpp +++ b/PythonAPI/carla/source/libcarla/Commands.cpp @@ -123,18 +123,18 @@ void export_commands() { .def_readwrite("speed", &cr::Command::ApplyWalkerState::speed) ; - class_("ApplyVelocity") + class_("ApplyTargetVelocity") .def("__init__", &command_impl::CustomInit, (arg("actor"), arg("velocity"))) .def(init((arg("actor_id"), arg("velocity")))) - .def_readwrite("actor_id", &cr::Command::ApplyVelocity::actor) - .def_readwrite("velocity", &cr::Command::ApplyVelocity::velocity) + .def_readwrite("actor_id", &cr::Command::ApplyTargetVelocity::actor) + .def_readwrite("velocity", &cr::Command::ApplyTargetVelocity::velocity) ; - class_("ApplyAngularVelocity") + class_("ApplyTargetAngularVelocity") .def("__init__", &command_impl::CustomInit, (arg("actor"), arg("angular_velocity"))) .def(init((arg("actor_id"), arg("angular_velocity")))) - .def_readwrite("actor_id", &cr::Command::ApplyAngularVelocity::actor) - .def_readwrite("angular_velocity", &cr::Command::ApplyAngularVelocity::angular_velocity) + .def_readwrite("actor_id", &cr::Command::ApplyTargetAngularVelocity::actor) + .def_readwrite("angular_velocity", &cr::Command::ApplyTargetAngularVelocity::angular_velocity) ; class_("ApplyImpulse") @@ -179,8 +179,8 @@ void export_commands() { implicitly_convertible(); implicitly_convertible(); implicitly_convertible(); - implicitly_convertible(); - implicitly_convertible(); + implicitly_convertible(); + implicitly_convertible(); implicitly_convertible(); implicitly_convertible(); implicitly_convertible(); From a75fc59eb02c5323ef6437e947dd10a64967fb4c Mon Sep 17 00:00:00 2001 From: Axel Date: Mon, 21 Sep 2020 18:09:54 +0200 Subject: [PATCH 098/179] Added reset all traffic lights function. --- LibCarla/source/carla/client/World.cpp | 4 ++++ LibCarla/source/carla/client/World.h | 2 ++ LibCarla/source/carla/client/detail/Client.cpp | 4 ++++ LibCarla/source/carla/client/detail/Client.h | 2 ++ LibCarla/source/carla/client/detail/Simulator.h | 4 ++++ PythonAPI/carla/source/libcarla/World.cpp | 1 + .../Plugins/Carla/Source/Carla/Server/CarlaServer.cpp | 10 ++++++++++ 7 files changed, 27 insertions(+) diff --git a/LibCarla/source/carla/client/World.cpp b/LibCarla/source/carla/client/World.cpp index df477cbab38..bb11f89d289 100644 --- a/LibCarla/source/carla/client/World.cpp +++ b/LibCarla/source/carla/client/World.cpp @@ -150,6 +150,10 @@ namespace client { return nullptr; } + void World::ResetAllTrafficLights() { + _episode.Lock()->ResetAllTrafficLights(); + } + SharedPtr World::GetLightManager() const { return _episode.Lock()->GetLightManager(); } diff --git a/LibCarla/source/carla/client/World.h b/LibCarla/source/carla/client/World.h index 41086e19fd1..981598b37cf 100644 --- a/LibCarla/source/carla/client/World.h +++ b/LibCarla/source/carla/client/World.h @@ -138,6 +138,8 @@ namespace client { SharedPtr GetTrafficLight(const Landmark& landmark) const; + void ResetAllTrafficLights(); + SharedPtr GetLightManager() const; DebugHelper MakeDebugHelper() const { diff --git a/LibCarla/source/carla/client/detail/Client.cpp b/LibCarla/source/carla/client/detail/Client.cpp index 5859cf87070..a415ef04852 100644 --- a/LibCarla/source/carla/client/detail/Client.cpp +++ b/LibCarla/source/carla/client/detail/Client.cpp @@ -326,6 +326,10 @@ namespace detail { _pimpl->AsyncCall("reset_traffic_light_group", traffic_light); } + void Client::ResetAllTrafficLights() { + _pimpl->AsyncCall("reset_all_traffic_lights"); + } + void Client::FreezeAllTrafficLights(bool frozen) { _pimpl->AsyncCall("freeze_all_traffic_lights", frozen); } diff --git a/LibCarla/source/carla/client/detail/Client.h b/LibCarla/source/carla/client/detail/Client.h index 45d3d96ac43..b8ed9fb504f 100644 --- a/LibCarla/source/carla/client/detail/Client.h +++ b/LibCarla/source/carla/client/detail/Client.h @@ -205,6 +205,8 @@ namespace detail { void ResetTrafficLightGroup( rpc::ActorId traffic_light); + void ResetAllTrafficLights(); + void FreezeAllTrafficLights(bool frozen); /// Returns a list of pairs where the firts element is the vehicle ID diff --git a/LibCarla/source/carla/client/detail/Simulator.h b/LibCarla/source/carla/client/detail/Simulator.h index 2243f421652..36c14e0c658 100644 --- a/LibCarla/source/carla/client/detail/Simulator.h +++ b/LibCarla/source/carla/client/detail/Simulator.h @@ -473,6 +473,10 @@ namespace detail { _client.ResetTrafficLightGroup(trafficLight.GetId()); } + void ResetAllTrafficLights() { + _client.ResetAllTrafficLights(); + } + std::vector GetGroupTrafficLights(TrafficLight &trafficLight) { return _client.GetGroupTrafficLights(trafficLight.GetId()); } diff --git a/PythonAPI/carla/source/libcarla/World.cpp b/PythonAPI/carla/source/libcarla/World.cpp index 387efb605d7..d5ca4df28f0 100644 --- a/PythonAPI/carla/source/libcarla/World.cpp +++ b/PythonAPI/carla/source/libcarla/World.cpp @@ -202,6 +202,7 @@ void export_world() { .def("set_pedestrians_cross_factor", CALL_WITHOUT_GIL_1(cc::World, SetPedestriansCrossFactor, float), (arg("percentage"))) .def("get_traffic_sign", CONST_CALL_WITHOUT_GIL_1(cc::World, GetTrafficSign, cc::Landmark), arg("landmark")) .def("get_traffic_light", CONST_CALL_WITHOUT_GIL_1(cc::World, GetTrafficLight, cc::Landmark), arg("landmark")) + .def("reset_all_traffic_lights", &cc::World::ResetAllTrafficLights) .def("get_lightmanager", CONST_CALL_WITHOUT_GIL(cc::World, GetLightManager)) .def("freeze_all_traffic_lights", &cc::World::FreezeAllTrafficLights, (arg("frozen"))) .def("get_level_bbs", &GetLevelBBs, (arg("actor_type")=cr::CityObjectLabel::None)) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp index 6ce07a0b9db..a4ff229f694 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp @@ -906,6 +906,16 @@ void FCarlaServer::FPimpl::BindActions() return R::Success(); }; + BIND_SYNC(reset_all_traffic_lights) << [this]() -> R + { + REQUIRE_CARLA_EPISODE(); + for (TActorIterator It(Episode->GetWorld()); It; ++It) + { + It->ResetGroup(); + } + return R::Success(); + }; + BIND_SYNC(freeze_all_traffic_lights) << [this] (bool frozen) -> R { From b963a9e3677cbcc181af4b2c391dfa47f0b3b6c4 Mon Sep 17 00:00:00 2001 From: Axel Date: Mon, 21 Sep 2020 18:18:34 +0200 Subject: [PATCH 099/179] Updated docs. --- Docs/python_api.md | 2 ++ PythonAPI/docs/world.yml | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/Docs/python_api.md b/Docs/python_api.md index 8cd7732b15c..9eb1fb0dc20 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -2659,6 +2659,8 @@ Same as **spawn_actor()** but returns None o Freezes or unfreezes all traffic lights in the scene. Frozen traffic lights can be modified by the user but the time will not update them until unfrozen. - **Parameters:** - `frozen` (_bool_) +- **reset_all_traffic_lights**(**self**) +Resets the cycle of all traffic lights in the map to the initial state.
    Getters
    - **get_actor**(**self**, **actor_id**) diff --git a/PythonAPI/docs/world.yml b/PythonAPI/docs/world.yml index 18c51d1e68f..dcd374c68b8 100644 --- a/PythonAPI/docs/world.yml +++ b/PythonAPI/docs/world.yml @@ -331,6 +331,10 @@ doc: > Freezes or unfreezes all traffic lights in the scene. Frozen traffic lights can be modified by the user but the time will not update them until unfrozen. # -------------------------------------- + - def_name: reset_all_traffic_lights + doc: > + Resets the cycle of all traffic lights in the map to the initial state. + # -------------------------------------- - def_name: get_map return: carla.Map doc: > From 4f5b66b0a0822b1e3b5b31acfae4b361610623df Mon Sep 17 00:00:00 2001 From: Axel Date: Tue, 22 Sep 2020 10:17:19 +0200 Subject: [PATCH 100/179] Changed call type for traffic light syncronization. --- LibCarla/source/carla/client/detail/Client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibCarla/source/carla/client/detail/Client.cpp b/LibCarla/source/carla/client/detail/Client.cpp index a415ef04852..b528b2c618d 100644 --- a/LibCarla/source/carla/client/detail/Client.cpp +++ b/LibCarla/source/carla/client/detail/Client.cpp @@ -327,7 +327,7 @@ namespace detail { } void Client::ResetAllTrafficLights() { - _pimpl->AsyncCall("reset_all_traffic_lights"); + _pimpl->CallAndWait("reset_all_traffic_lights"); } void Client::FreezeAllTrafficLights(bool frozen) { From 7360436c9d9e59ef4530a78feac4bcaa3c64d9fe Mon Sep 17 00:00:00 2001 From: Jacopo Bartiromo <32928804+jackbart94@users.noreply.github.com> Date: Tue, 22 Sep 2020 15:20:52 +0200 Subject: [PATCH 101/179] Determinism for Traffic Manager (#3333) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Check for determinism * Per-vehicle random device * Parameterised random device seed. * Changing next waypoint selection logic to use bucketing random device sample. Arranging next waypoint selections right to left. * Change to numpy's random lib * Sorting blueprints to ensure determinism * New method for determinism * ResetAllTrafficLight now works in sync mode. * Moving recorder stuff to engine module * Fixed recorder for traffic lights in standalone mode. * Added check to prevent traffic light from updating during replay. * Updating old traffic lights to use the traffic light component. * Moved recorder to posttick. * Small fix to elapse time function. * Added reset group function to API. * Merge with traffic_manager/determinism_check * Changes in TL reset Option to save to file for recorder script * Added automatic signal match with OpenDRIVE. * Fixed error that caused traffic light actors to be missing in client side. * Added new frozen behavior. * Updated documentation and changelog * Updated ContentVersions.txt * Review changes. * fixes merge error * fixes merge * Update build_windows.md Added info about command execution that toke me many time to find out * Update build_windows.md Updated as requested in pull request review * Running Carla when choosing a) deb Carla install This fixes a minor error in the documentation regarding running carla, if the deb installation was choosen. * Fix for traffic manager freezing upon map change * attempt to change sys clock to sim clock * Remove manual unlock of mutex * fixing merge error * Changelog and review fixes Co-authored-by: Praveen Kumar Co-authored-by: bernat Co-authored-by: Axel1092 Co-authored-by: Axel1092 <35765780+Axel1092@users.noreply.github.com> Co-authored-by: Néstor Sabater Co-authored-by: ll7 <32880741+ll7@users.noreply.github.com> --- CHANGELOG.md | 1 + LibCarla/source/carla/trafficmanager/ALSM.cpp | 7 ++- LibCarla/source/carla/trafficmanager/ALSM.h | 14 +++-- .../carla/trafficmanager/CollisionStage.cpp | 10 ++-- .../carla/trafficmanager/CollisionStage.h | 5 +- .../source/carla/trafficmanager/Constants.h | 4 +- .../carla/trafficmanager/DataStructures.h | 2 +- .../trafficmanager/LocalizationStage.cpp | 38 +++++++------ .../carla/trafficmanager/LocalizationStage.h | 5 +- .../carla/trafficmanager/MotionPlanStage.cpp | 17 +++--- .../carla/trafficmanager/MotionPlanStage.h | 5 +- .../carla/trafficmanager/PIDController.h | 2 +- .../carla/trafficmanager/RandomGenerator.h | 16 +++--- .../trafficmanager/TrafficLightStage.cpp | 46 ++++++++-------- .../carla/trafficmanager/TrafficLightStage.h | 14 +++-- .../carla/trafficmanager/TrafficManager.h | 8 +++ .../carla/trafficmanager/TrafficManagerBase.h | 2 + .../trafficmanager/TrafficManagerClient.h | 6 +++ .../trafficmanager/TrafficManagerLocal.cpp | 53 +++++++++---------- .../trafficmanager/TrafficManagerLocal.h | 13 ++++- .../trafficmanager/TrafficManagerRemote.cpp | 4 ++ .../trafficmanager/TrafficManagerRemote.h | 3 ++ .../trafficmanager/TrafficManagerServer.h | 5 ++ .../carla/source/libcarla/TrafficManager.cpp | 44 +++++++-------- PythonAPI/examples/show_recorder_file_info.py | 12 ++++- PythonAPI/examples/spawn_npc.py | 15 ++++-- .../Carla/Source/Carla/Game/CarlaEngine.cpp | 10 ++++ .../Carla/Source/Carla/Game/CarlaEngine.h | 8 +++ .../Source/Carla/Game/CarlaGameInstance.cpp | 3 ++ .../Source/Carla/Game/CarlaGameInstance.h | 10 +++- .../Source/Carla/Game/CarlaGameModeBase.h | 2 +- 31 files changed, 252 insertions(+), 132 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c773e56ea2..a8eb96630ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## CARLA 0.9.10 + * Deterministic mode for Traffic Manager, limited by computational power * Support for OSM in Traffic Manager * Fixed a map change error when Traffic Manager is in synchronous mode * Fixes add entry issue for applying parameters more than once in Traffic Manager diff --git a/LibCarla/source/carla/trafficmanager/ALSM.cpp b/LibCarla/source/carla/trafficmanager/ALSM.cpp index 60abde31127..b96ae7ba42b 100644 --- a/LibCarla/source/carla/trafficmanager/ALSM.cpp +++ b/LibCarla/source/carla/trafficmanager/ALSM.cpp @@ -26,7 +26,8 @@ ALSM::ALSM( LocalizationStage &localization_stage, CollisionStage &collision_stage, TrafficLightStage &traffic_light_stage, - MotionPlanStage &motion_plan_stage) + MotionPlanStage &motion_plan_stage, + RandomGeneratorMap &random_devices) : registered_vehicles(registered_vehicles), buffer_map(buffer_map), track_traffic(track_traffic), @@ -38,7 +39,8 @@ ALSM::ALSM( localization_stage(localization_stage), collision_stage(collision_stage), traffic_light_stage(traffic_light_stage), - motion_plan_stage(motion_plan_stage) {} + motion_plan_stage(motion_plan_stage), + random_devices(random_devices) {} void ALSM::Update() { @@ -339,6 +341,7 @@ void ALSM::RemoveActor(const ActorId actor_id, const bool registered_actor) { registered_vehicles.Remove({actor_id}); buffer_map.erase(actor_id); idle_time.erase(actor_id); + random_devices.erase(actor_id); localization_stage.RemoveActor(actor_id); collision_stage.RemoveActor(actor_id); traffic_light_stage.RemoveActor(actor_id); diff --git a/LibCarla/source/carla/trafficmanager/ALSM.h b/LibCarla/source/carla/trafficmanager/ALSM.h index 87f01496e50..83b4f388bb9 100644 --- a/LibCarla/source/carla/trafficmanager/ALSM.h +++ b/LibCarla/source/carla/trafficmanager/ALSM.h @@ -15,6 +15,7 @@ #include "carla/trafficmanager/LocalizationStage.h" #include "carla/trafficmanager/MotionPlanStage.h" #include "carla/trafficmanager/Parameters.h" +#include "carla/trafficmanager/RandomGenerator.h" #include "carla/trafficmanager/SimulationState.h" #include "carla/trafficmanager/TrafficLightStage.h" @@ -61,6 +62,8 @@ class ALSM { // Time elapsed since last vehicle destruction due to being idle for too long. double elapsed_last_actor_destruction {0.0}; cc::Timestamp current_timestamp; + // Random devices. + RandomGeneratorMap &random_devices; // Updates the duration for which a registered vehicle is stuck at a location. void UpdateIdleTime(std::pair& max_idle_time, const ActorId& actor_id); @@ -68,10 +71,6 @@ class ALSM { // Method to determine if a vehicle is stuck at a place for too long. bool IsVehicleStuck(const ActorId& actor_id); - // Removes an actor from traffic manager and performs clean up of associated data - // from various stages tracking the said vehicle. - void RemoveActor(const ActorId actor_id, const bool registered_actor); - using ActorVector = std::vector; // Method to identify actors newly spawned in the simulation since last tick. ActorVector IdentifyNewActors(const ActorList &actor_list); @@ -98,10 +97,15 @@ class ALSM { LocalizationStage &localization_stage, CollisionStage &collision_stage, TrafficLightStage &traffic_light_stage, - MotionPlanStage &motion_plan_stage); + MotionPlanStage &motion_plan_stage, + RandomGeneratorMap &random_devices); void Update(); + // Removes an actor from traffic manager and performs clean up of associated data + // from various stages tracking the said vehicle. + void RemoveActor(const ActorId actor_id, const bool registered_actor); + void Reset(); }; diff --git a/LibCarla/source/carla/trafficmanager/CollisionStage.cpp b/LibCarla/source/carla/trafficmanager/CollisionStage.cpp index 8df2e02b526..330c9e65e7c 100644 --- a/LibCarla/source/carla/trafficmanager/CollisionStage.cpp +++ b/LibCarla/source/carla/trafficmanager/CollisionStage.cpp @@ -22,14 +22,16 @@ CollisionStage::CollisionStage( const TrackTraffic &track_traffic, const Parameters ¶meters, CollisionFrame &output_array, - cc::DebugHelper &debug_helper) + cc::DebugHelper &debug_helper, + RandomGeneratorMap &random_devices) : vehicle_id_list(vehicle_id_list), simulation_state(simulation_state), buffer_map(buffer_map), track_traffic(track_traffic), parameters(parameters), output_array(output_array), - debug_helper(debug_helper) {} + debug_helper(debug_helper), + random_devices(random_devices) {} void CollisionStage::Update(const unsigned long index) { ActorId obstacle_id = 0u; @@ -81,9 +83,9 @@ void CollisionStage::Update(const unsigned long index) { look_ahead_index); if (negotiation_result.first) { if ((other_actor_type == ActorType::Vehicle - && parameters.GetPercentageIgnoreVehicles(ego_actor_id) <= pgen.next()) + && parameters.GetPercentageIgnoreVehicles(ego_actor_id) <= random_devices.at(ego_actor_id).next()) || (other_actor_type == ActorType::Pedestrian - && parameters.GetPercentageIgnoreWalkers(ego_actor_id) <= pgen.next())) { + && parameters.GetPercentageIgnoreWalkers(ego_actor_id) <= random_devices.at(ego_actor_id).next())) { collision_hazard = true; obstacle_id = other_actor_id; available_distance_margin = negotiation_result.second; diff --git a/LibCarla/source/carla/trafficmanager/CollisionStage.h b/LibCarla/source/carla/trafficmanager/CollisionStage.h index f3c9b31d882..51180325942 100644 --- a/LibCarla/source/carla/trafficmanager/CollisionStage.h +++ b/LibCarla/source/carla/trafficmanager/CollisionStage.h @@ -60,7 +60,7 @@ class CollisionStage : Stage { // to avoid repeated computation within a cycle. GeometryComparisonMap geometry_cache; GeodesicBoundaryMap geodesic_boundary_map; - RandomGenerator<> pgen; + RandomGeneratorMap &random_devices; // Method to determine if a vehicle is on a collision path to another. std::pair NegotiateCollision(const ActorId reference_vehicle_id, @@ -93,7 +93,8 @@ class CollisionStage : Stage { const TrackTraffic &track_traffic, const Parameters ¶meters, CollisionFrame &output_array, - cc::DebugHelper& debug_helper); + cc::DebugHelper& debug_helper, + RandomGeneratorMap &random_devices); void Update (const unsigned long index) override; diff --git a/LibCarla/source/carla/trafficmanager/Constants.h b/LibCarla/source/carla/trafficmanager/Constants.h index 58042ff6173..5d3e611f654 100644 --- a/LibCarla/source/carla/trafficmanager/Constants.h +++ b/LibCarla/source/carla/trafficmanager/Constants.h @@ -28,8 +28,8 @@ static const double DELTA_TIME_BETWEEN_DESTRUCTIONS = 10.0; } // namespace VehicleRemoval namespace HybridMode { -static const float HYBRID_MODE_DT = 0.05f; -static const float INV_HYBRID_DT = 1.0f / HYBRID_MODE_DT; +static const double HYBRID_MODE_DT = 0.05; +static const double INV_HYBRID_DT = 1.0 / HYBRID_MODE_DT; static const float PHYSICS_RADIUS = 50.0f; } // namespace HybridMode diff --git a/LibCarla/source/carla/trafficmanager/DataStructures.h b/LibCarla/source/carla/trafficmanager/DataStructures.h index 9e11d6635bb..5f604ff4269 100644 --- a/LibCarla/source/carla/trafficmanager/DataStructures.h +++ b/LibCarla/source/carla/trafficmanager/DataStructures.h @@ -60,7 +60,7 @@ struct ActuationSignal { /// Structure to hold the controller state. struct StateEntry { - TimeInstance time_instance; + cc::Timestamp time_instance; float deviation; float velocity; float deviation_integral; diff --git a/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp b/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp index 9132eb8d0a6..c2d98a29e12 100644 --- a/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp +++ b/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp @@ -19,7 +19,8 @@ LocalizationStage::LocalizationStage( Parameters ¶meters, std::vector& marked_for_removal, LocalizationFrame &output_array, - cc::DebugHelper &debug_helper) + cc::DebugHelper &debug_helper, + RandomGeneratorMap &random_devices) : vehicle_id_list(vehicle_id_list), buffer_map(buffer_map), simulation_state(simulation_state), @@ -28,7 +29,8 @@ LocalizationStage::LocalizationStage( parameters(parameters), marked_for_removal(marked_for_removal), output_array(output_array), - debug_helper(debug_helper) {} + debug_helper(debug_helper), + random_devices(random_devices) {} void LocalizationStage::Update(const unsigned long index) { @@ -105,7 +107,7 @@ void LocalizationStage::Update(const unsigned long index) { if (!force_lane_change) { float perc_keep_right = parameters.GetKeepRightPercentage(actor_id); - if (perc_keep_right >= 0.0f && perc_keep_right >= pgen.next()) { + if (perc_keep_right >= 0.0f && perc_keep_right >= random_devices.at(actor_id).next()) { force_lane_change = true; lane_change_direction = true; } @@ -147,11 +149,25 @@ void LocalizationStage::Update(const unsigned long index) { // Populating the buffer. while (waypoint_buffer.back()->DistanceSquared(waypoint_buffer.front()) <= horizon_square) { - std::vector next_waypoints = waypoint_buffer.back()->GetNextWaypoint(); + SimpleWaypointPtr furthest_waypoint = waypoint_buffer.back(); + std::vector next_waypoints = furthest_waypoint->GetNextWaypoint(); uint64_t selection_index = 0u; // Pseudo-randomized path selection if found more than one choice. if (next_waypoints.size() > 1) { - selection_index = static_cast(pgen.next()) % next_waypoints.size(); + // Arranging selection points from right to left. + std::sort(next_waypoints.begin(), next_waypoints.end(), + [&furthest_waypoint](const SimpleWaypointPtr &a, const SimpleWaypointPtr &b) { + float a_x_product = DeviationCrossProduct(furthest_waypoint->GetLocation(), + furthest_waypoint->GetForwardVector(), + a->GetLocation()); + float b_x_product = DeviationCrossProduct(furthest_waypoint->GetLocation(), + furthest_waypoint->GetForwardVector(), + b->GetLocation()); + return a_x_product < b_x_product; + }); + double r_sample = random_devices.at(actor_id).next(); + double s_bucket = 100.0 / next_waypoints.size(); + selection_index = static_cast(std::floor(r_sample/s_bucket)); } else if (next_waypoints.size() == 0) { if (parameters.GetOSMMode()) { marked_for_removal.push_back(actor_id); @@ -160,16 +176,8 @@ void LocalizationStage::Update(const unsigned long index) { throw std::invalid_argument("This is an OSM, please activate the set_open_street_map parameter"); } } - SimpleWaypointPtr next_wp = next_waypoints.at(selection_index); - if (next_wp == nullptr) { - for (auto &wp : next_waypoints) { - if (wp != nullptr) { - next_wp = wp; - break; - } - } - } - PushWaypoint(actor_id, track_traffic, waypoint_buffer, next_wp); + SimpleWaypointPtr next_wp_selection = next_waypoints.at(selection_index); + PushWaypoint(actor_id, track_traffic, waypoint_buffer, next_wp_selection); } ExtendAndFindSafeSpace(actor_id, is_at_junction_entrance, waypoint_buffer); diff --git a/LibCarla/source/carla/trafficmanager/LocalizationStage.h b/LibCarla/source/carla/trafficmanager/LocalizationStage.h index ba70b407ff8..042f7218e8e 100644 --- a/LibCarla/source/carla/trafficmanager/LocalizationStage.h +++ b/LibCarla/source/carla/trafficmanager/LocalizationStage.h @@ -42,7 +42,7 @@ class LocalizationStage : Stage { ActorIdSet vehicles_at_junction; using SimpleWaypointPair = std::pair; std::unordered_map vehicles_at_junction_entrance; - RandomGenerator<> pgen; + RandomGeneratorMap &random_devices; SimpleWaypointPtr AssignLaneChange(const ActorId actor_id, const cg::Location vehicle_location, @@ -64,7 +64,8 @@ class LocalizationStage : Stage { Parameters ¶meters, std::vector& marked_for_removal, LocalizationFrame &output_array, - cc::DebugHelper &debug_helper); + cc::DebugHelper &debug_helper, + RandomGeneratorMap &random_devices); void Update(const unsigned long index) override; diff --git a/LibCarla/source/carla/trafficmanager/MotionPlanStage.cpp b/LibCarla/source/carla/trafficmanager/MotionPlanStage.cpp index bcb99d4336c..f39961892ff 100644 --- a/LibCarla/source/carla/trafficmanager/MotionPlanStage.cpp +++ b/LibCarla/source/carla/trafficmanager/MotionPlanStage.cpp @@ -26,6 +26,7 @@ MotionPlanStage::MotionPlanStage( const LocalizationFrame &localization_frame, const CollisionFrame&collision_frame, const TLFrame &tl_frame, + const cc::World &world, ControlFrame &output_array) : vehicle_id_list(vehicle_id_list), simulation_state(simulation_state), @@ -39,6 +40,7 @@ MotionPlanStage::MotionPlanStage( localization_frame(localization_frame), collision_frame(collision_frame), tl_frame(tl_frame), + world(world), output_array(output_array) {} void MotionPlanStage::Update(const unsigned long index) { @@ -64,10 +66,11 @@ void MotionPlanStage::Update(const unsigned long index) { dot_product *= -1.0f; } const float current_deviation = dot_product; + current_timestamp = world.GetSnapshot().GetTimestamp(); // If previous state for vehicle not found, initialize state entry. if (pid_state_map.find(actor_id) == pid_state_map.end()) { - const auto initial_state = StateEntry{chr::system_clock::now(), 0.0f, 0.0f, 0.0f, 0.0f}; + const auto initial_state = StateEntry{current_timestamp, 0.0f, 0.0f, 0.0f, 0.0f}; pid_state_map.insert({actor_id, initial_state}); } @@ -96,7 +99,6 @@ void MotionPlanStage::Update(const unsigned long index) { bool collision_emergency_stop = collision_response.first; float dynamic_target_velocity = collision_response.second; - // Don't enter junction if there isn't enough free space after the junction. bool safe_after_junction = SafeAfterJunction(localization, tl_hazard, collision_emergency_stop); @@ -107,13 +109,12 @@ void MotionPlanStage::Update(const unsigned long index) { cg::Transform teleportation_transform; // If physics is enabled for the vehicle, use PID controller. - const auto current_time = chr::system_clock::now(); StateEntry current_state; if (ego_physics_enabled) { // State update for vehicle. current_state = PID::StateUpdate(previous_state, ego_speed, dynamic_target_velocity, - current_deviation, current_time); + current_deviation, current_timestamp); // Controller actuation. actuation_signal = PID::RunStep(current_state, previous_state, @@ -130,20 +131,20 @@ void MotionPlanStage::Update(const unsigned long index) { // For physics-less vehicles, determine position and orientation for teleportation. else { // Flushing controller state for vehicle. - current_state = {chr::system_clock::now(), + current_state = {current_timestamp, 0.0f, 0.0f, 0.0f, 0.0f}; // Add entry to teleportation duration clock table if not present. if (teleportation_instance.find(actor_id) == teleportation_instance.end()) { - teleportation_instance.insert({actor_id, chr::system_clock::now()}); + teleportation_instance.insert({actor_id, current_timestamp}); } // Measuring time elapsed since last teleportation for the vehicle. - chr::duration elapsed_time = current_time - teleportation_instance.at(actor_id); + double elapsed_time = current_timestamp.elapsed_seconds - teleportation_instance.at(actor_id).elapsed_seconds; // Find a location ahead of the vehicle for teleportation to achieve intended velocity. - if (!emergency_stop && (parameters.GetSynchronousMode() || elapsed_time.count() > HYBRID_MODE_DT)) { + if (!emergency_stop && (parameters.GetSynchronousMode() || elapsed_time > HYBRID_MODE_DT)) { // Target displacement magnitude to achieve target velocity. const float target_displacement = dynamic_target_velocity * HYBRID_MODE_DT; diff --git a/LibCarla/source/carla/trafficmanager/MotionPlanStage.h b/LibCarla/source/carla/trafficmanager/MotionPlanStage.h index ace2de47e3d..9d6bb8fa11b 100644 --- a/LibCarla/source/carla/trafficmanager/MotionPlanStage.h +++ b/LibCarla/source/carla/trafficmanager/MotionPlanStage.h @@ -29,12 +29,14 @@ class MotionPlanStage: Stage { const LocalizationFrame &localization_frame; const CollisionFrame &collision_frame; const TLFrame &tl_frame; + const cc::World &world; // Structure holding the controller state for registered vehicles. std::unordered_map pid_state_map; // Structure to keep track of duration between teleportation // in hybrid physics mode. - std::unordered_map teleportation_instance; + std::unordered_map teleportation_instance; ControlFrame &output_array; + cc::Timestamp current_timestamp; std::pair CollisionHandling(const CollisionHazardData &collision_hazard, const bool tl_hazard, @@ -59,6 +61,7 @@ bool SafeAfterJunction(const LocalizationData &localization, const LocalizationFrame &localization_frame, const CollisionFrame &collision_frame, const TLFrame &tl_frame, + const cc::World &world, ControlFrame &output_array); void Update(const unsigned long index); diff --git a/LibCarla/source/carla/trafficmanager/PIDController.h b/LibCarla/source/carla/trafficmanager/PIDController.h index 20079dea784..1217cbfaff2 100644 --- a/LibCarla/source/carla/trafficmanager/PIDController.h +++ b/LibCarla/source/carla/trafficmanager/PIDController.h @@ -28,7 +28,7 @@ StateEntry StateUpdate(StateEntry previous_state, float current_velocity, float target_velocity, float angular_deviation, - TimeInstance current_time) { + cc::Timestamp current_time) { StateEntry current_state = { current_time, angular_deviation, diff --git a/LibCarla/source/carla/trafficmanager/RandomGenerator.h b/LibCarla/source/carla/trafficmanager/RandomGenerator.h index a01d9389109..c3b23e3fb77 100644 --- a/LibCarla/source/carla/trafficmanager/RandomGenerator.h +++ b/LibCarla/source/carla/trafficmanager/RandomGenerator.h @@ -1,20 +1,24 @@ + #pragma once #include +#include + +#include "carla/rpc/ActorId.h" namespace carla { namespace traffic_manager { -template::value> -> class RandomGenerator { +class RandomGenerator { public: - RandomGenerator(): mt{std::random_device{}()}, dist(0.0, 100.0) {} - T next() { return dist(mt); } + RandomGenerator(const uint64_t seed): mt(std::mt19937(seed)), dist(0.0, 100.0) {} + double next() { return dist(mt); } private: std::mt19937 mt; - std::uniform_real_distribution dist; + std::uniform_real_distribution dist; }; +using RandomGeneratorMap = std::unordered_map; + } // namespace traffic_manager } // namespace carla diff --git a/LibCarla/source/carla/trafficmanager/TrafficLightStage.cpp b/LibCarla/source/carla/trafficmanager/TrafficLightStage.cpp index d778f9a03ce..026decbe65d 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficLightStage.cpp +++ b/LibCarla/source/carla/trafficmanager/TrafficLightStage.cpp @@ -7,7 +7,6 @@ namespace carla { namespace traffic_manager { -using constants::TrafficLight::NO_SIGNAL_PASSTHROUGH_INTERVAL; using constants::TrafficLight::DOUBLE_NO_SIGNAL_PASSTHROUGH_INTERVAL; using constants::WaypointSelection::JUNCTION_LOOK_AHEAD; @@ -16,12 +15,16 @@ TrafficLightStage::TrafficLightStage( const SimulationState &simulation_state, const BufferMap &buffer_map, const Parameters ¶meters, - TLFrame &output_array) + const cc::World &world, + TLFrame &output_array, + RandomGeneratorMap &random_devices) : vehicle_id_list(vehicle_id_list), simulation_state(simulation_state), buffer_map(buffer_map), parameters(parameters), - output_array(output_array) {} + world(world), + output_array(output_array), + random_devices(random_devices) {} void TrafficLightStage::Update(const unsigned long index) { bool traffic_light_hazard = false; @@ -31,7 +34,7 @@ void TrafficLightStage::Update(const unsigned long index) { const SimpleWaypointPtr look_ahead_point = GetTargetWaypoint(waypoint_buffer, JUNCTION_LOOK_AHEAD).first; const JunctionID junction_id = look_ahead_point->GetWaypoint()->GetJunctionId(); - const TimeInstance current_time = chr::system_clock::now(); + current_timestamp = world.GetSnapshot().GetTimestamp(); const TrafficLightState tl_state = simulation_state.GetTLS(ego_actor_id); const TLS traffic_light_state = tl_state.tl_state; @@ -41,7 +44,7 @@ void TrafficLightStage::Update(const unsigned long index) { // junction and there is a red or yellow light. if (is_at_traffic_light && traffic_light_state != TLS::Green && - parameters.GetPercentageRunningLight(ego_actor_id) <= pgen.next()) { + parameters.GetPercentageRunningLight(ego_actor_id) <= random_devices.at(ego_actor_id).next()) { traffic_light_hazard = true; } @@ -49,16 +52,16 @@ void TrafficLightStage::Update(const unsigned long index) { else if (look_ahead_point->CheckJunction() && !is_at_traffic_light && traffic_light_state != TLS::Green - && parameters.GetPercentageRunningSign(ego_actor_id) <= pgen.next()) { + && parameters.GetPercentageRunningSign(ego_actor_id) <= random_devices.at(ego_actor_id).next()) { - traffic_light_hazard = HandleNonSignalisedJunction(ego_actor_id, junction_id, current_time); + traffic_light_hazard = HandleNonSignalisedJunction(ego_actor_id, junction_id, current_timestamp); } output_array.at(index) = traffic_light_hazard; } bool TrafficLightStage::HandleNonSignalisedJunction(const ActorId ego_actor_id, const JunctionID junction_id, - const TimeInstance current_time) { + cc::Timestamp timestamp) { bool traffic_light_hazard = false; @@ -78,9 +81,9 @@ bool TrafficLightStage::HandleNonSignalisedJunction(const ActorId ego_actor_id, need_to_issue_new_ticket = true; } else { - const TimeInstance &previous_ticket = vehicle_last_ticket.at(ego_actor_id); - const chr::duration diff = current_time - previous_ticket; - if (diff.count() > DOUBLE_NO_SIGNAL_PASSTHROUGH_INTERVAL) { + const cc::Timestamp &previous_ticket = vehicle_last_ticket.at(ego_actor_id); + const double diff = timestamp.elapsed_seconds - previous_ticket.elapsed_seconds; + if (diff > DOUBLE_NO_SIGNAL_PASSTHROUGH_INTERVAL) { need_to_issue_new_ticket = true; } } @@ -91,16 +94,17 @@ bool TrafficLightStage::HandleNonSignalisedJunction(const ActorId ego_actor_id, if (need_to_issue_new_ticket) { if (junction_last_ticket.find(junction_id) != junction_last_ticket.end()) { - TimeInstance &last_ticket = junction_last_ticket.at(junction_id); - const chr::duration diff = current_time - last_ticket; - if (diff.count() > 0.0) { - last_ticket = current_time + chr::seconds(NO_SIGNAL_PASSTHROUGH_INTERVAL); + cc::Timestamp &last_ticket = junction_last_ticket.at(junction_id); + const double diff = timestamp.elapsed_seconds - last_ticket.elapsed_seconds; + if (diff > 0.0) { + last_ticket.elapsed_seconds = timestamp.elapsed_seconds + DOUBLE_NO_SIGNAL_PASSTHROUGH_INTERVAL; } else { - last_ticket += chr::seconds(NO_SIGNAL_PASSTHROUGH_INTERVAL); + last_ticket.elapsed_seconds += DOUBLE_NO_SIGNAL_PASSTHROUGH_INTERVAL; } } else { - junction_last_ticket.insert({junction_id, current_time + - chr::seconds(NO_SIGNAL_PASSTHROUGH_INTERVAL)}); + cc::Timestamp &new_ticket = timestamp; + new_ticket.elapsed_seconds += DOUBLE_NO_SIGNAL_PASSTHROUGH_INTERVAL; + junction_last_ticket.insert({junction_id, new_ticket}); } if (vehicle_last_ticket.find(ego_actor_id) != vehicle_last_ticket.end()) { vehicle_last_ticket.at(ego_actor_id) = junction_last_ticket.at(junction_id); @@ -111,9 +115,9 @@ bool TrafficLightStage::HandleNonSignalisedJunction(const ActorId ego_actor_id, } // If current time is behind ticket time, then do not enter junction. - const TimeInstance ¤t_ticket = vehicle_last_ticket.at(ego_actor_id); - const chr::duration diff = current_ticket - current_time; - if (diff.count() > 0.0) { + const cc::Timestamp current_ticket = vehicle_last_ticket.at(ego_actor_id); + const double diff = current_ticket.elapsed_seconds - timestamp.elapsed_seconds; + if (diff > 0.0) { traffic_light_hazard = true; } diff --git a/LibCarla/source/carla/trafficmanager/TrafficLightStage.h b/LibCarla/source/carla/trafficmanager/TrafficLightStage.h index 6f74a9e8075..f3c19311def 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficLightStage.h +++ b/LibCarla/source/carla/trafficmanager/TrafficLightStage.h @@ -18,24 +18,28 @@ class TrafficLightStage: Stage { const SimulationState &simulation_state; const BufferMap &buffer_map; const Parameters ¶meters; + const cc::World &world; /// Map containing the time ticket issued for vehicles. - std::unordered_map vehicle_last_ticket; + std::unordered_map vehicle_last_ticket; /// Map containing the previous time ticket issued for junctions. - std::unordered_map junction_last_ticket; + std::unordered_map junction_last_ticket; /// Map containing the previous junction visited by a vehicle. std::unordered_map vehicle_last_junction; TLFrame &output_array; - RandomGenerator<> pgen; + RandomGeneratorMap &random_devices; + cc::Timestamp current_timestamp; bool HandleNonSignalisedJunction(const ActorId ego_actor_id, const JunctionID junction_id, - const TimeInstance current_time); + cc::Timestamp timestamp); public: TrafficLightStage(const std::vector &vehicle_id_list, const SimulationState &Simulation_state, const BufferMap &buffer_map, const Parameters ¶meters, - TLFrame &output_array); + const cc::World &world, + TLFrame &output_array, + RandomGeneratorMap &random_devices); void Update(const unsigned long index) override; diff --git a/LibCarla/source/carla/trafficmanager/TrafficManager.h b/LibCarla/source/carla/trafficmanager/TrafficManager.h index 562df505185..601f4883eb8 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManager.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManager.h @@ -230,6 +230,14 @@ class TrafficManager { } } + /// Method to set randomization seed. + void SetRandomDeviceSeed(const uint64_t seed) { + TrafficManagerBase* tm_ptr = GetTM(_port); + if(tm_ptr != nullptr){ + tm_ptr->SetRandomDeviceSeed(seed); + } + } + private: void CreateTrafficManagerServer( diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerBase.h b/LibCarla/source/carla/trafficmanager/TrafficManagerBase.h index a4012e91bd9..cfabfb27536 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerBase.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerBase.h @@ -104,6 +104,8 @@ class TrafficManagerBase { /// Method to set hybrid physics radius. virtual void SetHybridPhysicsRadius(const float radius) = 0; + /// Method to set randomization seed. + virtual void SetRandomDeviceSeed(const uint64_t seed) = 0; /// Method to set Open Street Map mode. virtual void SetOSMMode(const bool mode_switch) = 0; diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerClient.h b/LibCarla/source/carla/trafficmanager/TrafficManagerClient.h index d29f3a1bdfc..0c38a323bed 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerClient.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerClient.h @@ -193,6 +193,12 @@ class TrafficManagerClient { _client->call("set_hybrid_physics_radius", radius); } + /// Method to set randomization seed. + void SetRandomDeviceSeed(const uint64_t seed) { + DEBUG_ASSERT(_client != nullptr); + _client->call("set_random_device_seed", seed); + } + /// Method to set Open Street Map mode. void SetOSMMode(const bool mode_switch) { DEBUG_ASSERT(_client != nullptr); diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp index f1a1b830c72..d7bb1401e39 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.cpp @@ -39,7 +39,8 @@ TrafficManagerLocal::TrafficManagerLocal( parameters, marked_for_removal, localization_frame, - debug_helper)), + debug_helper, + random_devices)), collision_stage(CollisionStage(vehicle_id_list, simulation_state, @@ -47,13 +48,16 @@ TrafficManagerLocal::TrafficManagerLocal( track_traffic, parameters, collision_frame, - debug_helper)), + debug_helper, + random_devices)), traffic_light_stage(TrafficLightStage(vehicle_id_list, simulation_state, buffer_map, parameters, - tl_frame)), + world, + tl_frame, + random_devices)), motion_plan_stage(MotionPlanStage(vehicle_id_list, simulation_state, @@ -67,6 +71,7 @@ TrafficManagerLocal::TrafficManagerLocal( localization_frame, collision_frame, tl_frame, + world, control_frame)), alsm(ALSM(registered_vehicles, @@ -80,7 +85,8 @@ TrafficManagerLocal::TrafficManagerLocal( localization_stage, collision_stage, traffic_light_stage, - motion_plan_stage)), + motion_plan_stage, + random_devices)), server(TrafficManagerServer(RPCportTM, static_cast(this))) { @@ -133,9 +139,9 @@ void TrafficManagerLocal::Run() { if (!synchronous_mode && hybrid_physics_mode) { TimePoint current_instance = chr::system_clock::now(); chr::duration elapsed_time = current_instance - previous_update_instance; - float time_to_wait = HYBRID_MODE_DT - elapsed_time.count(); - if (time_to_wait > 0.0f) { - std::this_thread::sleep_for(chr::duration(time_to_wait)); + chr::duration time_to_wait = chr::duration(HYBRID_MODE_DT) - elapsed_time; + if (time_to_wait > chr::duration(0.0f)) { + std::this_thread::sleep_for(time_to_wait); } previous_update_instance = current_instance; } @@ -237,6 +243,7 @@ void TrafficManagerLocal::Stop() { track_traffic.Clear(); previous_update_instance = chr::system_clock::now(); current_reserved_capacity = 0u; + random_devices.clear(); simulation_state.Reset(); localization_stage.Reset(); @@ -273,15 +280,17 @@ void TrafficManagerLocal::Reset() { void TrafficManagerLocal::RegisterVehicles(const std::vector &vehicle_list) { registered_vehicles.Insert(vehicle_list); + for (const ActorPtr &vehicle: vehicle_list) { + random_devices.insert({vehicle->GetId(), RandomGenerator(seed)}); + } } void TrafficManagerLocal::UnregisterVehicles(const std::vector &actor_list) { std::vector actor_id_list; for (auto &actor : actor_list) { - actor_id_list.push_back(actor->GetId()); + alsm.RemoveActor(actor->GetId(), true); } - registered_vehicles.Remove(actor_id_list); } void TrafficManagerLocal::SetPercentageSpeedDifference(const ActorPtr &actor, const float percentage) { @@ -354,39 +363,22 @@ bool TrafficManagerLocal::CheckAllFrozen(TLGroup tl_to_freeze) { } void TrafficManagerLocal::ResetAllTrafficLights() { - // Filter based on wildcard pattern. const auto world_traffic_lights = world.GetActors()->Filter("*traffic_light*"); std::vector list_of_all_groups; - TLGroup tl_to_freeze; std::vector list_of_ids; + for (auto iter = world_traffic_lights->begin(); iter != world_traffic_lights->end(); iter++) { auto tl = *iter; if (!(std::find(list_of_ids.begin(), list_of_ids.end(), tl->GetId()) != list_of_ids.end())) { const TLGroup tl_group = boost::static_pointer_cast(tl)->GetGroupTrafficLights(); list_of_all_groups.push_back(tl_group); - for (uint64_t i = 0u; i < tl_group.size(); i++) { - list_of_ids.push_back(tl_group.at(i).get()->GetId()); - if (i != 0u) { - tl_to_freeze.push_back(tl_group.at(i)); - } - } } } for (TLGroup &tl_group : list_of_all_groups) { - tl_group.front()->SetState(TLS::Green); - std::for_each( - tl_group.begin() + 1, tl_group.end(), - [](auto &tl) { tl->SetState(TLS::Red); }); - } - - while (!CheckAllFrozen(tl_to_freeze)) { - for (auto &tln : tl_to_freeze) { - tln->SetState(TLS::Red); - tln->Freeze(true); - } + tl_group.front()->ResetGroup(); } } @@ -411,5 +403,10 @@ std::vector TrafficManagerLocal::GetRegisteredVehiclesIDs() { return registered_vehicles.GetIDList(); } +void TrafficManagerLocal::SetRandomDeviceSeed(const uint64_t _seed) { + seed = _seed; + ResetAllTrafficLights(); +} + } // namespace traffic_manager } // namespace carla diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.h b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.h index e5da564f50a..65324e0f85a 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerLocal.h @@ -21,6 +21,7 @@ #include "carla/trafficmanager/AtomicActorSet.h" #include "carla/trafficmanager/InMemoryMap.h" #include "carla/trafficmanager/Parameters.h" +#include "carla/trafficmanager/RandomGenerator.h" #include "carla/trafficmanager/SimulationState.h" #include "carla/trafficmanager/TrackTraffic.h" #include "carla/trafficmanager/TrafficManagerBase.h" @@ -109,6 +110,10 @@ class TrafficManagerLocal : public TrafficManagerBase { std::condition_variable step_end_trigger; /// Single worker thread for sequential execution of sub-components. std::unique_ptr worker_thread; + /// Structure holding random devices per vehicle. + RandomGeneratorMap random_devices; + /// Randomization seed. + uint64_t seed {static_cast(time(NULL))}; std::vector marked_for_removal; /// Method to check if all traffic lights are frozen in a group. @@ -149,7 +154,7 @@ class TrafficManagerLocal : public TrafficManagerBase { void RegisterVehicles(const std::vector &actor_list); /// This method unregisters a vehicle from traffic manager. - void UnregisterVehicles(const std::vector &actor_list); + void UnregisterVehicles(const std::vector &actor_list); /// Method to set a vehicle's % decrease in velocity with respect to the speed limit. /// If less than 0, it's a % increase. @@ -197,6 +202,9 @@ class TrafficManagerLocal : public TrafficManagerBase { /// Method to reset all traffic light groups to the initial stage. void ResetAllTrafficLights(); + /// Method to start all traffic light groups to the initial stage. + void StartAllTrafficLights(); + /// Get CARLA episode information. carla::client::detail::EpisodeProxy &GetEpisodeProxy(); @@ -216,6 +224,9 @@ class TrafficManagerLocal : public TrafficManagerBase { /// Method to set hybrid physics radius. void SetHybridPhysicsRadius(const float radius); + /// Method to set randomization seed. + void SetRandomDeviceSeed(const uint64_t _seed); + /// Method to set Open Street Map mode. void SetOSMMode(const bool mode_switch); }; diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.cpp b/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.cpp index 6a9e3b17eb4..168a554d757 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.cpp +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.cpp @@ -209,5 +209,9 @@ carla::client::detail::EpisodeProxy& TrafficManagerRemote::GetEpisodeProxy() { return episodeProxyTM; } +void TrafficManagerRemote::SetRandomDeviceSeed(const uint64_t seed) { + client.SetRandomDeviceSeed(seed); +} + } // namespace traffic_manager } // namespace carla diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.h b/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.h index 82787f78d3d..790218b4bcc 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerRemote.h @@ -117,6 +117,9 @@ class TrafficManagerRemote : public TrafficManagerBase { /// Method to check server is alive or not. void HealthCheckRemoteTM(); + /// Method to set randomization seed. + void SetRandomDeviceSeed(const uint64_t seed); + private: /// Remote client using the IP and port information it connects to diff --git a/LibCarla/source/carla/trafficmanager/TrafficManagerServer.h b/LibCarla/source/carla/trafficmanager/TrafficManagerServer.h index 62b1374ae7e..67f113b818b 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficManagerServer.h +++ b/LibCarla/source/carla/trafficmanager/TrafficManagerServer.h @@ -178,6 +178,11 @@ class TrafficManagerServer { tm->SetSynchronousModeTimeOutInMiliSecond(time); }); + /// Method to set randomization seed. + server->bind("set_random_device_seed", [=](const uint64_t seed) { + tm->SetRandomDeviceSeed(seed); + }); + /// Method to provide synchronous tick. server->bind("synchronous_tick", [=]() -> bool { return tm->SynchronousTick(); diff --git a/PythonAPI/carla/source/libcarla/TrafficManager.cpp b/PythonAPI/carla/source/libcarla/TrafficManager.cpp index 795c4b96db7..204c9842f61 100644 --- a/PythonAPI/carla/source/libcarla/TrafficManager.cpp +++ b/PythonAPI/carla/source/libcarla/TrafficManager.cpp @@ -13,26 +13,28 @@ #include "carla/trafficmanager/TrafficManager.h" void export_trafficmanager() { - namespace cc = carla::client; - using namespace boost::python; + namespace cc = carla::client; + namespace ctm = carla::traffic_manager; + using namespace boost::python; - class_("TrafficManager", no_init) - .def("get_port", &carla::traffic_manager::TrafficManager::Port) - .def("vehicle_percentage_speed_difference", &carla::traffic_manager::TrafficManager::SetPercentageSpeedDifference) - .def("global_percentage_speed_difference", &carla::traffic_manager::TrafficManager::SetGlobalPercentageSpeedDifference) - .def("collision_detection", &carla::traffic_manager::TrafficManager::SetCollisionDetection) - .def("force_lane_change", &carla::traffic_manager::TrafficManager::SetForceLaneChange) - .def("auto_lane_change", &carla::traffic_manager::TrafficManager::SetAutoLaneChange) - .def("distance_to_leading_vehicle", &carla::traffic_manager::TrafficManager::SetDistanceToLeadingVehicle) - .def("reset_traffic_lights", &carla::traffic_manager::TrafficManager::ResetAllTrafficLights) - .def("ignore_walkers_percentage", &carla::traffic_manager::TrafficManager::SetPercentageIgnoreWalkers) - .def("ignore_vehicles_percentage", &carla::traffic_manager::TrafficManager::SetPercentageIgnoreVehicles) - .def("ignore_lights_percentage", &carla::traffic_manager::TrafficManager::SetPercentageRunningLight) - .def("ignore_signs_percentage", &carla::traffic_manager::TrafficManager::SetPercentageRunningSign) - .def("set_global_distance_to_leading_vehicle", &carla::traffic_manager::TrafficManager::SetGlobalDistanceToLeadingVehicle) - .def("set_percentage_keep_right_rule", &carla::traffic_manager::TrafficManager::SetKeepRightPercentage) - .def("set_synchronous_mode", &carla::traffic_manager::TrafficManager::SetSynchronousMode) - .def("set_hybrid_physics_mode", &carla::traffic_manager::TrafficManager::SetHybridPhysicsMode) - .def("set_hybrid_physics_radius", &carla::traffic_manager::TrafficManager::SetHybridPhysicsRadius) - .def("set_osm_mode", &carla::traffic_manager::TrafficManager::SetOSMMode); + class_("TrafficManager", no_init) + .def("get_port", &ctm::TrafficManager::Port) + .def("vehicle_percentage_speed_difference", &ctm::TrafficManager::SetPercentageSpeedDifference) + .def("global_percentage_speed_difference", &ctm::TrafficManager::SetGlobalPercentageSpeedDifference) + .def("collision_detection", &ctm::TrafficManager::SetCollisionDetection) + .def("force_lane_change", &ctm::TrafficManager::SetForceLaneChange) + .def("auto_lane_change", &ctm::TrafficManager::SetAutoLaneChange) + .def("distance_to_leading_vehicle", &ctm::TrafficManager::SetDistanceToLeadingVehicle) + .def("reset_traffic_lights", &ctm::TrafficManager::ResetAllTrafficLights) + .def("ignore_walkers_percentage", &ctm::TrafficManager::SetPercentageIgnoreWalkers) + .def("ignore_vehicles_percentage", &ctm::TrafficManager::SetPercentageIgnoreVehicles) + .def("ignore_lights_percentage", &ctm::TrafficManager::SetPercentageRunningLight) + .def("ignore_signs_percentage", &ctm::TrafficManager::SetPercentageRunningSign) + .def("set_global_distance_to_leading_vehicle", &ctm::TrafficManager::SetGlobalDistanceToLeadingVehicle) + .def("set_percentage_keep_right_rule", &ctm::TrafficManager::SetKeepRightPercentage) + .def("set_synchronous_mode", &ctm::TrafficManager::SetSynchronousMode) + .def("set_hybrid_physics_mode", &ctm::TrafficManager::SetHybridPhysicsMode) + .def("set_hybrid_physics_radius", &ctm::TrafficManager::SetHybridPhysicsRadius) + .def("set_random_device_seed", &ctm::TrafficManager::SetRandomDeviceSeed) + .def("set_osm_mode", &carla::traffic_manager::TrafficManager::SetOSMMode); } diff --git a/PythonAPI/examples/show_recorder_file_info.py b/PythonAPI/examples/show_recorder_file_info.py index f9f5f45aa25..1dde92ada52 100755 --- a/PythonAPI/examples/show_recorder_file_info.py +++ b/PythonAPI/examples/show_recorder_file_info.py @@ -47,14 +47,24 @@ def main(): '-a', '--show_all', action='store_true', help='show detailed info about all frames content') + argparser.add_argument( + '-s', '--save_to_file', + metavar='S', + help='save result to file (specify name and extension)') + args = argparser.parse_args() try: client = carla.Client(args.host, args.port) client.set_timeout(60.0) + if args.save_to_file: + doc = open(args.save_to_file, "w+") + doc.write(client.show_recorder_file_info(args.recorder_filename, args.show_all)) + doc.close() + else: + print(client.show_recorder_file_info(args.recorder_filename, args.show_all)) - print(client.show_recorder_file_info(args.recorder_filename, args.show_all)) finally: pass diff --git a/PythonAPI/examples/spawn_npc.py b/PythonAPI/examples/spawn_npc.py index 3442b8ded5d..a79929b923c 100755 --- a/PythonAPI/examples/spawn_npc.py +++ b/PythonAPI/examples/spawn_npc.py @@ -27,8 +27,7 @@ import argparse import logging -import random - +from numpy import random def main(): argparser = argparse.ArgumentParser( @@ -84,6 +83,11 @@ def main(): '--hybrid', action='store_true', help='Enanble') + argparser.add_argument( + '-s', '--seed', + metavar='S', + type=int, + help='Random device seed') argparser.add_argument( '--osm', action='store_true', @@ -103,14 +107,17 @@ def main(): client = carla.Client(args.host, args.port) client.set_timeout(10.0) synchronous_master = False + random.seed(args.seed if args.seed is not None else int(time.time())) try: world = client.get_world() traffic_manager = client.get_trafficmanager(args.tm_port) - traffic_manager.set_global_distance_to_leading_vehicle(2.0) + traffic_manager.set_global_distance_to_leading_vehicle(1.0) if args.hybrid: traffic_manager.set_hybrid_physics_mode(True) + if args.seed is not None: + traffic_manager.set_random_device_seed(args.seed) if args.osm: traffic_manager.set_osm_mode(True) @@ -136,6 +143,8 @@ def main(): blueprints = [x for x in blueprints if not x.id.endswith('cybertruck')] blueprints = [x for x in blueprints if not x.id.endswith('t2')] + blueprints = sorted(blueprints, key=lambda bp: bp.id) + spawn_points = world.get_map().get_spawn_points() number_of_spawn_points = len(spawn_points) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEngine.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEngine.cpp index c7c2ac374ba..3774c5e65d2 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEngine.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEngine.cpp @@ -10,6 +10,7 @@ #include "Carla/Game/CarlaEpisode.h" #include "Carla/Game/CarlaStaticDelegates.h" #include "Carla/Lights/CarlaLightSubsystem.h" +#include "Carla/Recorder/CarlaRecorder.h" #include "Carla/Settings/CarlaSettings.h" #include "Carla/Settings/EpisodeSettings.h" @@ -82,6 +83,15 @@ void FCarlaEngine::NotifyBeginEpisode(UCarlaEpisode &Episode) { Episode.EpisodeSettings.FixedDeltaSeconds = FCarlaEngine_GetFixedDeltaSeconds(); CurrentEpisode = &Episode; + + // make connection between Episode and Recorder + if (Recorder) + { + Recorder->SetEpisode(&Episode); + Episode.SetRecorder(Recorder); + Recorder->GetReplayer()->CheckPlayAfterMapLoaded(); + } + Server.NotifyBeginEpisode(Episode); } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEngine.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEngine.h index 986d82bca62..5625fd1f567 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEngine.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEngine.h @@ -6,6 +6,7 @@ #pragma once +#include "Carla/Recorder/CarlaRecorder.h" #include "Carla/Sensor/WorldObserver.h" #include "Carla/Server/CarlaServer.h" #include "Carla/Util/NonCopyable.h" @@ -37,6 +38,11 @@ class FCarlaEngine : private NonCopyable return CurrentEpisode; } + void SetRecorder(ACarlaRecorder *InRecorder) + { + Recorder = InRecorder; + } + private: void OnPreTick(UWorld *World, ELevelTick TickType, float DeltaSeconds); @@ -59,6 +65,8 @@ class FCarlaEngine : private NonCopyable UCarlaEpisode *CurrentEpisode = nullptr; + ACarlaRecorder *Recorder = nullptr; + FDelegateHandle OnPreTickHandle; FDelegateHandle OnPostTickHandle; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameInstance.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameInstance.cpp index 0c03ada2544..80a1bb45f21 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameInstance.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameInstance.cpp @@ -11,6 +11,9 @@ UCarlaGameInstance::UCarlaGameInstance() { CarlaSettings = CreateDefaultSubobject(TEXT("CarlaSettings")); + Recorder = CreateDefaultSubobject(TEXT("Recorder")); + CarlaEngine.SetRecorder(Recorder); + check(CarlaSettings != nullptr); CarlaSettings->LoadSettings(); CarlaSettings->LogSettings(); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameInstance.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameInstance.h index 9069249d7ef..8fc2ed05e01 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameInstance.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameInstance.h @@ -9,6 +9,7 @@ #include "Engine/GameInstance.h" #include "Carla/Game/CarlaEngine.h" +#include "Carla/Recorder/CarlaRecorder.h" #include "Carla/Server/CarlaServer.h" #include @@ -78,12 +79,14 @@ class CARLA_API UCarlaGameInstance : public UGameInstance } void SetOpendriveGenerationParameters( - const carla::rpc::OpendriveGenerationParameters & Parameters) { + const carla::rpc::OpendriveGenerationParameters & Parameters) + { GenerationParameters = Parameters; } const carla::rpc::OpendriveGenerationParameters& - GetOpendriveGenerationParameters() const { + GetOpendriveGenerationParameters() const + { return GenerationParameters; } @@ -94,6 +97,9 @@ class CARLA_API UCarlaGameInstance : public UGameInstance FCarlaEngine CarlaEngine; + UPROPERTY() + ACarlaRecorder *Recorder = nullptr; + carla::rpc::OpendriveGenerationParameters GenerationParameters; }; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h index 9abcc6ce995..e000cee702d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h @@ -86,7 +86,7 @@ class CARLA_API ACarlaGameModeBase : public AGameModeBase UCarlaEpisode *Episode = nullptr; UPROPERTY() - ACarlaRecorder *Recorder = nullptr; + ACarlaRecorder *Recorder = nullptr; /// The class of Weather to spawn. UPROPERTY(Category = "CARLA Game Mode", EditAnywhere) From 0c8362215396d30c3de7f1401875b69a719d1663 Mon Sep 17 00:00:00 2001 From: Jacopo Bartiromo <32928804+jackbart94@users.noreply.github.com> Date: Tue, 22 Sep 2020 15:41:10 +0200 Subject: [PATCH 102/179] Support Off state for traffic lights in Traffic Manager (#3332) * Support off state for traffic lights in Traffic Manager * Removed off state workarround. Co-authored-by: Axel --- LibCarla/source/carla/trafficmanager/ALSM.cpp | 2 +- .../carla/trafficmanager/CollisionStage.cpp | 2 +- .../carla/trafficmanager/TrafficLightStage.cpp | 10 ++++++---- .../Carla/Traffic/TrafficLightComponent.cpp | 17 ++--------------- 4 files changed, 10 insertions(+), 21 deletions(-) diff --git a/LibCarla/source/carla/trafficmanager/ALSM.cpp b/LibCarla/source/carla/trafficmanager/ALSM.cpp index b96ae7ba42b..db3f61dba7e 100644 --- a/LibCarla/source/carla/trafficmanager/ALSM.cpp +++ b/LibCarla/source/carla/trafficmanager/ALSM.cpp @@ -315,7 +315,7 @@ void ALSM::UpdateIdleTime(std::pair& max_idle_time, const Actor double &idle_duration = idle_time.at(actor_id); TrafficLightState tl_state = simulation_state.GetTLS(actor_id); if (simulation_state.GetVelocity(actor_id).SquaredLength() > SQUARE(STOPPED_VELOCITY_THRESHOLD) - || (tl_state.at_traffic_light && tl_state.tl_state != TLS::Green)) { + || (tl_state.at_traffic_light && tl_state.tl_state != TLS::Green && tl_state.tl_state != TLS::Off)) { idle_duration = current_timestamp.elapsed_seconds; } diff --git a/LibCarla/source/carla/trafficmanager/CollisionStage.cpp b/LibCarla/source/carla/trafficmanager/CollisionStage.cpp index 330c9e65e7c..2151158e82e 100644 --- a/LibCarla/source/carla/trafficmanager/CollisionStage.cpp +++ b/LibCarla/source/carla/trafficmanager/CollisionStage.cpp @@ -336,7 +336,7 @@ std::pair CollisionStage::NegotiateCollision(const ActorId referenc bool ego_inside_junction = closest_point->CheckJunction(); TrafficLightState reference_tl_state = simulation_state.GetTLS(reference_vehicle_id); bool ego_at_traffic_light = reference_tl_state.at_traffic_light; - bool ego_stopped_by_light = reference_tl_state.tl_state != TLS::Green; + bool ego_stopped_by_light = reference_tl_state.tl_state != TLS::Green && reference_tl_state.tl_state != TLS::Off; SimpleWaypointPtr look_ahead_point = reference_vehicle_buffer.at(reference_junction_look_ahead_index); bool ego_at_junction_entrance = !closest_point->CheckJunction() && look_ahead_point->CheckJunction(); diff --git a/LibCarla/source/carla/trafficmanager/TrafficLightStage.cpp b/LibCarla/source/carla/trafficmanager/TrafficLightStage.cpp index 026decbe65d..3d23fe5bd5c 100644 --- a/LibCarla/source/carla/trafficmanager/TrafficLightStage.cpp +++ b/LibCarla/source/carla/trafficmanager/TrafficLightStage.cpp @@ -44,15 +44,17 @@ void TrafficLightStage::Update(const unsigned long index) { // junction and there is a red or yellow light. if (is_at_traffic_light && traffic_light_state != TLS::Green && + traffic_light_state != TLS::Off && parameters.GetPercentageRunningLight(ego_actor_id) <= random_devices.at(ego_actor_id).next()) { traffic_light_hazard = true; } // Handle entry negotiation at non-signalised junction. - else if (look_ahead_point->CheckJunction() - && !is_at_traffic_light - && traffic_light_state != TLS::Green - && parameters.GetPercentageRunningSign(ego_actor_id) <= random_devices.at(ego_actor_id).next()) { + else if (look_ahead_point->CheckJunction() && + !is_at_traffic_light && + traffic_light_state != TLS::Green && + traffic_light_state != TLS::Off && + parameters.GetPercentageRunningSign(ego_actor_id) <= random_devices.at(ego_actor_id).next()) { traffic_light_hazard = HandleNonSignalisedJunction(ego_actor_id, junction_id, current_timestamp); } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightComponent.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightComponent.cpp index 9b05028751e..baaea9ddc9c 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightComponent.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Traffic/TrafficLightComponent.cpp @@ -97,16 +97,9 @@ void UTrafficLightComponent::SetLightState(ETrafficLightState NewState) { Controller->SetTrafficLight(nullptr); } - // workarround for tm not supporting off state - if (LightState == ETrafficLightState::Off) - { - Controller->SetTrafficLightState(ETrafficLightState::Green); - Controller->SetTrafficLight(nullptr); - } } } - if (LightState == ETrafficLightState::Green || - LightState == ETrafficLightState::Off) + if (LightState == ETrafficLightState::Green) { Vehicles.Empty(); } @@ -160,18 +153,12 @@ void UTrafficLightComponent::OnOverlapTriggerBox(UPrimitiveComponent *Overlapped if (VehicleController) { VehicleController->SetTrafficLightState(LightState); - if (LightState != ETrafficLightState::Green && - LightState != ETrafficLightState::Off) + if (LightState != ETrafficLightState::Green) { Vehicles.Add(VehicleController); VehicleController->SetTrafficLight( Cast(GetOwner())); } - // workarround for tm not supporting off state - if (LightState == ETrafficLightState::Off) - { - VehicleController->SetTrafficLightState(ETrafficLightState::Green); - } } } } From 625d032f23aac6cf13a9a52f6fcbf0d9aa64f81d Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Tue, 22 Sep 2020 15:49:08 +0200 Subject: [PATCH 103/179] Fixed debug lines with current illumination --- .../Plugins/Carla/Source/Carla/Util/DebugShapeDrawer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/DebugShapeDrawer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/DebugShapeDrawer.cpp index d648dfd21fb..27aeed3e2b0 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/DebugShapeDrawer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/DebugShapeDrawer.cpp @@ -182,7 +182,7 @@ struct FShapeVisitor uint8 DepthPriority = SDPG_World; - static constexpr double BrightMultiplier = 10000.0; + static constexpr double BrightMultiplier = 1.0; }; void FDebugShapeDrawer::Draw(const carla::rpc::DebugShape &Shape) From 1ef830d1735b0d42714e11f50d1cff96fbe3c688 Mon Sep 17 00:00:00 2001 From: Marc Garcia Puig Date: Tue, 22 Sep 2020 16:39:22 +0200 Subject: [PATCH 104/179] Added DefaultScalability.ini so UE4 doesn't disable EyeAdaptionQuality on Low Quality --- Unreal/CarlaUE4/Config/DefaultScalability.ini | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Unreal/CarlaUE4/Config/DefaultScalability.ini diff --git a/Unreal/CarlaUE4/Config/DefaultScalability.ini b/Unreal/CarlaUE4/Config/DefaultScalability.ini new file mode 100644 index 00000000000..933e476cb65 --- /dev/null +++ b/Unreal/CarlaUE4/Config/DefaultScalability.ini @@ -0,0 +1,14 @@ +# More info: +# https://docs.unrealengine.com/en-US/Engine/Performance/Scalability/ScalabilityReference/index.html + +[PostProcessQuality@0] +r.EyeAdaptationQuality=2 + +[PostProcessQuality@1] +r.EyeAdaptationQuality=2 + +[PostProcessQuality@2] +r.EyeAdaptationQuality=2 + +[PostProcessQuality@3] +r.EyeAdaptationQuality=2 From 39667c77b08d710017131cc8ade463244a09385c Mon Sep 17 00:00:00 2001 From: sergi-e Date: Sun, 20 Sep 2020 12:17:00 +0200 Subject: [PATCH 105/179] first iteration, missing contrast --- Docs/ref_sensors.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Docs/ref_sensors.md b/Docs/ref_sensors.md index 9be199a2a97..8b7327c251a 100644 --- a/Docs/ref_sensors.md +++ b/Docs/ref_sensors.md @@ -843,7 +843,7 @@ A value of 1.5 means that we want the sensor to capture data each second and a h fstop float -8.0 +1.4 Opening of the camera lens. Aperture is 1/fstop with typical lens going down to f/1.2 (larger opening). Larger numbers will reduce the Depth of Field effect. image_size_x @@ -858,7 +858,7 @@ A value of 1.5 means that we want the sensor to capture data each second and a h iso float -200.0 +100.0 The camera sensor sensitivity. gamma @@ -959,22 +959,22 @@ Since these effects are provided by UE, please make sure to check their document exposure_mode str -manual +histogram Can be manual or histogram. More in UE4 docs. exposure_compensation float --2.2 +Linux: -1.5
    Windows: 0.0 Logarithmic adjustment for the exposure. 0: no adjustment, -1:2x darker, -2:4 darker, 1:2x brighter, 2:4x brighter. exposure_min_bright float -0.1 +7.0 In exposure_mode: "histogram". Minimum brightness for auto exposure. The lowest the eye can adapt within. Must be greater than 0 and less than or equal to exposure_max_bright. exposure_max_bright float -2.0 +9.0 In `exposure_mode: "histogram"`. Maximum brightness for auto exposure. The highestthe eye can adapt within. Must be greater than 0 and greater than or equal to `exposure_min_bright`. exposure_speed_up From 81de76fa18b3169c83cf956ec04a3a2881fc0f86 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Mon, 21 Sep 2020 16:44:03 +0200 Subject: [PATCH 106/179] First iteration --- Docs/python_api.md | 6 +++--- Docs/ref_sensors.md | 24 ++++++++++++++++++++++++ PythonAPI/docs/sensor_data.yml | 6 +++--- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index 9eb1fb0dc20..e70923a70cf 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -501,13 +501,13 @@ Class that defines conversion patterns that can be applied to a [carla.Image](#c

    Instance Variables

    - **CityScapesPalette** -Converts the image to a segmentated map using tags provided by the blueprint library. Used by sensor.camera.semantic_segmentation. +Converts the image to a segmentated map using tags provided by the blueprint library. Used by the [semantic segmentation camera](ref_sensors.md#semantic-segmentation-camera). - **Depth** -Converts the image to a linear depth map. Used by sensor.camera.depth. +Converts the image to a linear depth map. Used by the [depth camera](ref_sensors.md#depth-camera). - **LogarithmicDepth** Converts the image to a depth map using a logarithmic scale, leading to better precision for small distances at the expense of losing it when further away. - **Raw** -No changes applied to the image. +No changes applied to the image. Used by the [RGB camera](ref_sensors.md#rgb-camera). --- diff --git a/Docs/ref_sensors.md b/Docs/ref_sensors.md index 8b7327c251a..7887d4528e3 100644 --- a/Docs/ref_sensors.md +++ b/Docs/ref_sensors.md @@ -1444,99 +1444,123 @@ The following tags are currently available: Value Tag Converted color +Description 0 Unlabeled (0, 0, 0) +Elements that have not been categorized are considered Unlabeled. This category is meant to be empty or at least contain elements with no collisions. 1 Building (70, 70, 70) +Buildings like houses, skyscrapers,... and the elements attached to them.
    E.g. air conditioners, scaffolding, awning or ladders and much more. 2 Fence (100, 40, 40) +Barriers, railing, or other upright structures. Basically wood or wire assemblies that enclose an area of ground. 3 Other (55, 90, 80) + Everything that does not belong to any other category. 4 Pedestrian (220, 20, 60) +Humans that walk or ride/drive any kind of vehicle or mobility system.
    E.g. bicycles or scooters, skateboards, horses, roller-blades, wheel-chairs, etc. 5 Pole (153, 153, 153) +Small mainly vertically oriented pole. If the pole has a horizontal part (often for traffic light poles) this is also considered pole.
    E.g. sign pole, traffic light poles.E 6 RoadLine (157, 234, 50) +The markings on the road. 7 Road (128, 64, 128) +Part of ground on which cars usually drive.
    E.g. lanes in any directions, and streets. 8 SideWalk (244, 35, 232) +Part of ground designated for pedestrians or cyclists. Delimited from the road by some obstacle (such as curbs or poles), not only by markings. This label includes a possibly delimiting curb, traffic islands (the walkable part), and pedestrian zones. 9 Vegetation (107, 142, 35) + Trees, hedges, all kinds of vertical vegetation. Ground-level vegetation is considered Terrain. 10 Vehicles (0, 0, 142) +Cars, vans, trucks, motorcycles, bikes, buses, trains. 11 Wall (102, 102, 156) +Individual standing walls. Not part of a building. 12 TrafficSign (220, 220, 0) +Signs installed by the state/city authority, usually for traffic regulation. This category does not include the poles where signs are attached to.
    E.g. traffic- signs, parking signs, direction signs... 13 Sky (70, 130, 180) +Open sky. Includes clouds and the sun. 14 Ground (81, 0, 81) +Any horizontal ground-level structures that does not match any other category. For example areas shared by vehicles and pedestrians, or flat roundabouts delimited from the road by a curb. 15 Bridge (150, 100, 100) +Only the structure of the bridge. Fences, people, vehicles, an other elements on top of it are labeled separately. 16 RailTrack (230, 150, 140) +All kind of rail tracks that are non-drivable by cars.
    E.g. subway and train rail tracks. 17 GuardRail (180, 165, 180) +All types of guard rails/crash barriers. 18 TrafficLight (250, 170, 30) +Traffic light boxes without their poles. 19 Static (110, 190, 160) +Elements in the scene and props that are immovable. E.g. fire hydrants, fixed benches, fountains, bus stops, etc. 20 Dynamic (170, 120, 50) +Elements whose position is susceptible to change over time. E.g. Movable trash bins, buggies, bags, wheelchairs, animals, etc. 21 Water (45, 60, 150) +Horizontal water surfaces.
    E.g. Lakes, sea, rivers. 22 Terrain (145, 170, 100) +Grass, ground-level vegetation, soil or sand. These areas are not meant to be driven on. This label includes a possibly delimiting curb.
    diff --git a/PythonAPI/docs/sensor_data.yml b/PythonAPI/docs/sensor_data.yml index 8ba111626b1..1a334992dbd 100644 --- a/PythonAPI/docs/sensor_data.yml +++ b/PythonAPI/docs/sensor_data.yml @@ -40,16 +40,16 @@ instance_variables: - var_name: CityScapesPalette doc: > - Converts the image to a segmentated map using tags provided by the blueprint library. Used by sensor.camera.semantic_segmentation. + Converts the image to a segmentated map using tags provided by the blueprint library. Used by the [semantic segmentation camera](ref_sensors.md#semantic-segmentation-camera). - var_name: Depth doc: > - Converts the image to a linear depth map. Used by sensor.camera.depth. + Converts the image to a linear depth map. Used by the [depth camera](ref_sensors.md#depth-camera). - var_name: LogarithmicDepth doc: > Converts the image to a depth map using a logarithmic scale, leading to better precision for small distances at the expense of losing it when further away. - var_name: Raw doc: > - No changes applied to the image. + No changes applied to the image. Used by the [RGB camera](ref_sensors.md#rgb-camera). - class_name: Image parent: carla.SensorData From 3140ba3f2e423d9898c32d48b10905a98663ce77 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Mon, 21 Sep 2020 22:30:57 +0200 Subject: [PATCH 107/179] New iteration with semantic pic and additional code lines --- Docs/img/ref_sensors_semantic.jpg | Bin 76429 -> 98975 bytes Docs/ref_sensors.md | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Docs/img/ref_sensors_semantic.jpg b/Docs/img/ref_sensors_semantic.jpg index 79d05730e19101b1264528fcd534a88ed2d3af24..281de6e8d93ef42cc89a0749e826e9a2e92ce245 100644 GIT binary patch literal 98975 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 YCMFwGMmEi;ybf%z`M+^xE&N^jAL8AJ{{R30 literal 76429 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�KXZ>50HG8=`zN6Nf1MEW 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 diff --git a/Docs/ref_sensors.md b/Docs/ref_sensors.md index 7887d4528e3..435d3d63a93 100644 --- a/Docs/ref_sensors.md +++ b/Docs/ref_sensors.md @@ -80,6 +80,12 @@ in_meters = 1000 * normalized The output [carla.Image](python_api.md#carla.Image) should then be saved to disk using a [carla.colorConverter](python_api.md#carla.ColorConverter) that will turn the distance stored in RGB channels into a __[0,1]__ float containing the distance and then translate this to grayscale. There are two options in [carla.colorConverter](python_api.md#carla.ColorConverter) to get a depth view: __Depth__ and __Logaritmic depth__. The precision is milimetric in both, but the logarithmic approach provides better results for closer objects. +```py +... +raw_image.save_to_disk("path/to/save/converted/image",carla.Depth) +``` + + ![ImageDepth](img/ref_sensors_depth.jpg) @@ -1435,8 +1441,16 @@ __2.__ Run the simulation using `python3 config.py --fps=10`. This camera classifies every object in sight by displaying it in a different color according to its tags (e.g., pedestrians in a different color than vehicles). When the simulation starts, every element in scene is created with a tag. So it happens when an actor is spawned. The objects are classified by their relative file path in the project. For example, meshes stored in `Unreal/CarlaUE4/Content/Static/Pedestrians` are tagged as `Pedestrian`. +![ImageSemanticSegmentation](img/ref_sensors_semantic.jpg) + The server provides an image with the tag information __encoded in the red channel__: A pixel with a red value of `x` belongs to an object with tag `x`. This raw [carla.Image](python_api.md#carla.Image) can be stored and converted it with the help of __CityScapesPalette__ in [carla.ColorConverter](python_api.md#carla.ColorConverter) to apply the tags information and show picture with the semantic segmentation. + +```py +... +raw_image.save_to_disk("path/to/save/converted/image",carla.cityScapesPalette) +``` + The following tags are currently available: @@ -1569,8 +1583,6 @@ The following tags are currently available: **Adding new tags**: It requires some C++ coding. Add a new label to the `ECityObjectLabel` enum in "Tagger.h", and its corresponding filepath check inside `GetLabelByFolderName()` function in "Tagger.cpp". -![ImageSemanticSegmentation](img/ref_sensors_semantic.jpg) - #### Basic camera attributes
    From 39530ee688e37f578ee82ae3d1c5db26090c2e85 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Tue, 22 Sep 2020 11:38:58 +0200 Subject: [PATCH 108/179] Fixed typo. --- Docs/ref_sensors.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Docs/ref_sensors.md b/Docs/ref_sensors.md index 435d3d63a93..6e874d3461e 100644 --- a/Docs/ref_sensors.md +++ b/Docs/ref_sensors.md @@ -1489,7 +1489,7 @@ The following tags are currently available: - + @@ -1559,12 +1559,12 @@ The following tags are currently available: - + - + From 3a8db3fd9fc098f995092bc692853a2cb24fe451 Mon Sep 17 00:00:00 2001 From: bernat Date: Wed, 23 Sep 2020 10:50:13 +0200 Subject: [PATCH 109/179] Adding nightly build on dev branch also --- Jenkinsfile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4d0a5ffa553..c1f64610fbe 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -106,6 +106,12 @@ pipeline } stage('ubuntu deploy') { + when { branch "dev"; } + steps + { + sh 'git checkout .' + sh 'make deploy ARGS="--replace-latest"' + } when { anyOf { branch "master"; buildingTag() } } steps { @@ -238,7 +244,7 @@ pipeline } stage('windows deploy') { - when { anyOf { branch "master"; buildingTag() } } + when { anyOf { branch "master"; branch "dev"; buildingTag() } } steps { bat """ call ../setEnv64.bat From f2c3b9fce6f1dbba1852996c546fb2127de93371 Mon Sep 17 00:00:00 2001 From: bernat Date: Wed, 23 Sep 2020 10:50:13 +0200 Subject: [PATCH 110/179] Revert "Adding nightly build on dev branch also" This reverts commit 3a8db3fd9fc098f995092bc692853a2cb24fe451. --- Jenkinsfile | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index c1f64610fbe..4d0a5ffa553 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -106,12 +106,6 @@ pipeline } stage('ubuntu deploy') { - when { branch "dev"; } - steps - { - sh 'git checkout .' - sh 'make deploy ARGS="--replace-latest"' - } when { anyOf { branch "master"; buildingTag() } } steps { @@ -244,7 +238,7 @@ pipeline } stage('windows deploy') { - when { anyOf { branch "master"; branch "dev"; buildingTag() } } + when { anyOf { branch "master"; buildingTag() } } steps { bat """ call ../setEnv64.bat From 43ce1b0f0108ea9a7c702b28bd5f0889dd82b667 Mon Sep 17 00:00:00 2001 From: bernat Date: Wed, 23 Sep 2020 12:00:19 +0200 Subject: [PATCH 111/179] Adding nightly build on dev branch --- Jenkinsfile | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4d0a5ffa553..a2b190b1f93 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -104,7 +104,16 @@ pipeline } } } - stage('ubuntu deploy') + stage('ubuntu deploy dev') + { + when { branch "dev"; } + steps + { + sh 'git checkout .' + sh 'make deploy ARGS="--replace-latest"' + } + } + stage('ubuntu deploy master') { when { anyOf { branch "master"; buildingTag() } } steps @@ -238,7 +247,7 @@ pipeline } stage('windows deploy') { - when { anyOf { branch "master"; buildingTag() } } + when { anyOf { branch "master"; branch "dev"; buildingTag() } } steps { bat """ call ../setEnv64.bat From e82a6d352cb8de22d1f652f48bbe69835117fb5b Mon Sep 17 00:00:00 2001 From: Axel Date: Wed, 23 Sep 2020 14:25:14 +0200 Subject: [PATCH 112/179] Removed debug warning. --- Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp index 7c40769da54..e9518b8ebee 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaEpisode.cpp @@ -329,7 +329,6 @@ void UCarlaEpisode::InitializeAtBeginPlay() Description.Variations.Add("mass", FActorAttribute{"mass", EActorAttributeType::Float, FString::SanitizeFloat(MeshComponent->GetMass())}); - carla::log_warning(carla::rpc::FromFString(MeshComponent->GetStaticMesh()->GetPathName())); ActorDispatcher->RegisterActor(*Actor, Description); } } From fd611b2e330a838db268ba9ceef21b3376a2385a Mon Sep 17 00:00:00 2001 From: bernat Date: Wed, 16 Sep 2020 13:22:09 +0200 Subject: [PATCH 113/179] Adding smoke_tests again --- Jenkinsfile | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index a2b190b1f93..d6448c140ee 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -102,6 +102,52 @@ pipeline stash includes: 'Dist/CARLA*.tar.gz', name: 'ubuntu_package' stash includes: 'Examples/', name: 'ubuntu_examples' } + success + { + node('master') + { + script + { + JOB_ID = "${env.BUILD_TAG}" + jenkinsLib = load("/home/jenkins/jenkins.groovy") + + jenkinsLib.CreateUbuntuTestNode(JOB_ID) + } + } + } + } + } + stage('ubuntu smoke tests') + { + agent { label "ubuntu && gpu && ${JOB_ID}" } + steps + { + unstash name: 'ubuntu_eggs' + unstash name: 'ubuntu_package' + unstash name: 'ubuntu_examples' + sh 'tar -xvzf Dist/CARLA*.tar.gz -C Dist/' + sh 'DISPLAY= ./Dist/CarlaUE4.sh -opengl --carla-rpc-port=3654 --carla-streaming-port=0 -nosound > CarlaUE4.log &' + sh 'make smoke_tests ARGS="--xml"' + sh 'make run-examples ARGS="localhost 3654"' + } + post + { + always + { + archiveArtifacts 'CarlaUE4.log' + junit 'Build/test-results/smoke-tests-*.xml' + deleteDir() + node('master') + { + script + { + JOB_ID = "${env.BUILD_TAG}" + jenkinsLib = load("/home/jenkins/jenkins.groovy") + + jenkinsLib.DeleteUbuntuTestNode(JOB_ID) + } + } + } } } stage('ubuntu deploy dev') From 3e7678321770943ad14cd32f4fad73df7e5bd4f6 Mon Sep 17 00:00:00 2001 From: bernat Date: Wed, 16 Sep 2020 15:57:43 +0200 Subject: [PATCH 114/179] Fixing python version --- Jenkinsfile | 2 +- Util/BuildTools/Check.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index d6448c140ee..17f3036ab4c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -127,7 +127,7 @@ pipeline unstash name: 'ubuntu_examples' sh 'tar -xvzf Dist/CARLA*.tar.gz -C Dist/' sh 'DISPLAY= ./Dist/CarlaUE4.sh -opengl --carla-rpc-port=3654 --carla-streaming-port=0 -nosound > CarlaUE4.log &' - sh 'make smoke_tests ARGS="--xml"' + sh 'make smoke_tests ARGS="--xml --python-version=3.7"' sh 'make run-examples ARGS="localhost 3654"' } post diff --git a/Util/BuildTools/Check.sh b/Util/BuildTools/Check.sh index c8553894e0d..b1f75587b7d 100755 --- a/Util/BuildTools/Check.sh +++ b/Util/BuildTools/Check.sh @@ -197,7 +197,7 @@ popd >/dev/null if ${SMOKE_TESTS} ; then pushd "${CARLA_PYTHONAPI_ROOT_FOLDER}/util" >/dev/null log "Checking connection with the simulator." - python${PY_VERSION} test_connection.py -p 3654 --timeout=60.0 + /usr/bin/env python${PY_VERSION} test_connection.py -p 3654 --timeout=60.0 popd >/dev/null fi From 0ff1dc4561a091b9589ec86cfcdac16c15a6183e Mon Sep 17 00:00:00 2001 From: bernat Date: Tue, 22 Sep 2020 12:14:04 +0200 Subject: [PATCH 115/179] New content version --- Util/ContentVersions.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Util/ContentVersions.txt b/Util/ContentVersions.txt index 3e8371eea74..fd3af8e48b1 100644 --- a/Util/ContentVersions.txt +++ b/Util/ContentVersions.txt @@ -32,4 +32,4 @@ 0.9.7: 20191221_c88604b 0.9.8: 20200306_06b6cb1 0.9.9: 20200422_ea5179a -Latest: 20200918_0931149 +Latest: 20200923_8adc984 From 4447661d664c40df256193b9758cae58b95e168d Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Tue, 22 Sep 2020 09:42:09 +0200 Subject: [PATCH 116/179] First version of the Constant velocity mode This mode can be enabled in the API and it will keep a velocity constant. For now, it needs to be disable automatically but this can be improved in the future. --- LibCarla/source/carla/client/Actor.cpp | 8 +++ LibCarla/source/carla/client/Actor.h | 5 ++ .../source/carla/client/detail/Client.cpp | 7 +++ LibCarla/source/carla/client/detail/Client.h | 6 ++ .../source/carla/client/detail/Simulator.h | 7 +++ PythonAPI/carla/source/libcarla/Actor.cpp | 2 + .../Carla/Source/Carla/Server/CarlaServer.cpp | 42 ++++++++++++++ .../Carla/Vehicle/CarlaWheeledVehicle.cpp | 13 +++++ .../Carla/Vehicle/CarlaWheeledVehicle.h | 10 ++++ .../Carla/Vehicle/VehicleVelocityControl.cpp | 55 ++++++++++++++++++ .../Carla/Vehicle/VehicleVelocityControl.h | 56 +++++++++++++++++++ 11 files changed, 211 insertions(+) create mode 100644 Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.cpp create mode 100644 Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.h diff --git a/LibCarla/source/carla/client/Actor.cpp b/LibCarla/source/carla/client/Actor.cpp index 87999be39a4..d8681dcad5c 100644 --- a/LibCarla/source/carla/client/Actor.cpp +++ b/LibCarla/source/carla/client/Actor.cpp @@ -48,6 +48,14 @@ namespace client { GetEpisode().Lock()->SetActorTargetAngularVelocity(*this, vector); } + void Actor::EnableConstantVelocity(const geom::Vector3D &vector) { + GetEpisode().Lock()->EnableActorConstantVelocity(*this, vector); + } + + void Actor::DisableConstantVelocity() { + GetEpisode().Lock()->DisableActorConstantVelocity(*this); + } + void Actor::AddImpulse(const geom::Vector3D &vector) { GetEpisode().Lock()->AddActorImpulse(*this, vector); } diff --git a/LibCarla/source/carla/client/Actor.h b/LibCarla/source/carla/client/Actor.h index bdc6e3ee549..7751f4cde15 100644 --- a/LibCarla/source/carla/client/Actor.h +++ b/LibCarla/source/carla/client/Actor.h @@ -69,6 +69,11 @@ namespace client { /// Set the angular velocity of the actor before applying physics. void SetTargetAngularVelocity(const geom::Vector3D &vector); + /// Enable a constant velocity mode + void EnableConstantVelocity(const geom::Vector3D &vector); + /// Disable the constant velocity mode + void DisableConstantVelocity(); + /// Add impulse to the actor. void AddImpulse(const geom::Vector3D &vector); diff --git a/LibCarla/source/carla/client/detail/Client.cpp b/LibCarla/source/carla/client/detail/Client.cpp index b528b2c618d..e813f37d33d 100644 --- a/LibCarla/source/carla/client/detail/Client.cpp +++ b/LibCarla/source/carla/client/detail/Client.cpp @@ -271,6 +271,13 @@ namespace detail { void Client::SetActorTargetAngularVelocity(rpc::ActorId actor, const geom::Vector3D &vector) { _pimpl->AsyncCall("set_actor_target_angular_velocity", actor, vector); } + void Client::EnableActorConstantVelocity(rpc::ActorId actor, const geom::Vector3D &vector) { + _pimpl->AsyncCall("enable_actor_constant_velocity", actor, vector); + } + + void Client::DisableActorConstantVelocity(rpc::ActorId actor) { + _pimpl->AsyncCall("disable_actor_constant_velocity", actor); + } void Client::AddActorImpulse(rpc::ActorId actor, const geom::Vector3D &vector) { _pimpl->AsyncCall("add_actor_impulse", actor, vector); diff --git a/LibCarla/source/carla/client/detail/Client.h b/LibCarla/source/carla/client/detail/Client.h index b8ed9fb504f..b0964747a5c 100644 --- a/LibCarla/source/carla/client/detail/Client.h +++ b/LibCarla/source/carla/client/detail/Client.h @@ -153,6 +153,12 @@ namespace detail { void SetActorTargetAngularVelocity( rpc::ActorId actor, const geom::Vector3D &vector); + void EnableActorConstantVelocity( + rpc::ActorId actor, + const geom::Vector3D &vector); + + void DisableActorConstantVelocity( + rpc::ActorId actor); void AddActorImpulse( rpc::ActorId actor, diff --git a/LibCarla/source/carla/client/detail/Simulator.h b/LibCarla/source/carla/client/detail/Simulator.h index 36c14e0c658..0fc1b838a44 100644 --- a/LibCarla/source/carla/client/detail/Simulator.h +++ b/LibCarla/source/carla/client/detail/Simulator.h @@ -330,6 +330,13 @@ namespace detail { void SetActorTargetAngularVelocity(const Actor &actor, const geom::Vector3D &vector) { _client.SetActorTargetAngularVelocity(actor.GetId(), vector); } + void EnableActorConstantVelocity(const Actor &actor, const geom::Vector3D &vector) { + _client.EnableActorConstantVelocity(actor.GetId(), vector); + } + + void DisableActorConstantVelocity(const Actor &actor) { + _client.DisableActorConstantVelocity(actor.GetId()); + } void AddActorImpulse(const Actor &actor, const geom::Vector3D &vector) { _client.AddActorImpulse(actor.GetId(), vector); diff --git a/PythonAPI/carla/source/libcarla/Actor.cpp b/PythonAPI/carla/source/libcarla/Actor.cpp index 564a35663ea..5066a586e09 100644 --- a/PythonAPI/carla/source/libcarla/Actor.cpp +++ b/PythonAPI/carla/source/libcarla/Actor.cpp @@ -87,6 +87,8 @@ void export_actor() { .def("set_transform", &cc::Actor::SetTransform, (arg("transform"))) .def("set_target_velocity", &cc::Actor::SetTargetVelocity, (arg("vector"))) .def("set_target_angular_velocity", &cc::Actor::SetTargetAngularVelocity, (arg("vector"))) + .def("enable_constant_velocity", &cc::Actor::EnableConstantVelocity, (arg("vector"))) + .def("disable_constant_velocity", &cc::Actor::DisableConstantVelocity) .def("add_impulse", &cc::Actor::AddImpulse, (arg("vector"))) .def("add_angular_impulse", &cc::Actor::AddAngularImpulse, (arg("vector"))) .def("set_simulate_physics", &cc::Actor::SetSimulatePhysics, (arg("enabled") = true)) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp index a4ff229f694..d2119eee92d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp @@ -557,6 +557,48 @@ void FCarlaServer::FPimpl::BindActions() return R::Success(); }; + BIND_SYNC(enable_actor_constant_velocity) << [this]( + cr::ActorId ActorId, + cr::Vector3D vector) -> R + { + REQUIRE_CARLA_EPISODE(); + auto ActorView = Episode->FindActor(ActorId); + if (!ActorView.IsValid()) + { + RESPOND_ERROR("unable to set actor velocity: actor not found"); + } + auto CarlaVehicle = Cast(ActorView.GetActor()); + if (CarlaVehicle == nullptr) + { + RESPOND_ERROR("unable to set actor velocity: not supported by actor"); + } + + CarlaVehicle->ActivateVelocityControl(vector.ToCentimeters().ToFVector()); + + return R::Success(); + }; + + BIND_SYNC(disable_actor_constant_velocity) << [this]( + cr::ActorId ActorId, + cr::Vector3D vector) -> R + { + REQUIRE_CARLA_EPISODE(); + auto ActorView = Episode->FindActor(ActorId); + if (!ActorView.IsValid()) + { + RESPOND_ERROR("unable to set actor velocity: actor not found"); + } + auto CarlaVehicle = Cast(ActorView.GetActor()); + if (CarlaVehicle == nullptr) + { + RESPOND_ERROR("unable to set actor velocity: not supported by actor"); + } + + CarlaVehicle->DeactivateVelocityControl(); + + return R::Success(); + }; + BIND_SYNC(add_actor_impulse) << [this]( cr::ActorId ActorId, cr::Vector3D vector) -> R diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.cpp index 310d39e3f12..63adb9e1c35 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.cpp @@ -30,6 +30,9 @@ ACarlaWheeledVehicle::ACarlaWheeledVehicle(const FObjectInitializer& ObjectIniti VehicleBounds->SetHiddenInGame(true); VehicleBounds->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName); + VelocityControl = CreateDefaultSubobject(TEXT("VelocityControl")); + VelocityControl->Deactivate(); + GetVehicleMovementComponent()->bReverseAsBrake = false; } @@ -432,6 +435,16 @@ void ACarlaWheeledVehicle::ApplyVehiclePhysicsControl(const FVehiclePhysicsContr } } +void ACarlaWheeledVehicle::ActivateVelocityControl(const FVector &Velocity) +{ + VelocityControl->Activate(Velocity); +} + +void ACarlaWheeledVehicle::DeactivateVelocityControl() +{ + VelocityControl->Deactivate(); +} + void ACarlaWheeledVehicle::SetVehicleLightState(const FVehicleLightState &LightState) { InputControl.LightState = LightState; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.h index 93a75da4587..890bb82fa00 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.h @@ -13,6 +13,7 @@ #include "Vehicle/VehicleLightState.h" #include "Vehicle/VehicleInputPriority.h" #include "Vehicle/VehiclePhysicsControl.h" +#include "VehicleVelocityControl.h" #include "WheeledVehicleMovementComponent4W.h" #include "CoreMinimal.h" @@ -136,6 +137,12 @@ class CARLA_API ACarlaWheeledVehicle : public AWheeledVehicle } } + UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable) + void ActivateVelocityControl(const FVector &Velocity); + + UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable) + void DeactivateVelocityControl(); + /// @todo This function should be private to AWheeledVehicleAIController. void FlushVehicleControl(); @@ -208,6 +215,9 @@ class CARLA_API ACarlaWheeledVehicle : public AWheeledVehicle UPROPERTY(Category = "CARLA Wheeled Vehicle", EditAnywhere) UBoxComponent *VehicleBounds; + UPROPERTY(Category = "CARLA Wheeled Vehicle", EditAnywhere) + UVehicleVelocityControl* VelocityControl; + struct { EVehicleInputPriority Priority = EVehicleInputPriority::INVALID; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.cpp new file mode 100644 index 00000000000..94939ddc693 --- /dev/null +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.cpp @@ -0,0 +1,55 @@ +// Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma +// de Barcelona (UAB). +// +// This work is licensed under the terms of the MIT license. +// For a copy, see . + +#include "Kismet/KismetMathLibrary.h" + +#include "VehicleVelocityControl.h" + + +UVehicleVelocityControl::UVehicleVelocityControl() +{ + PrimaryComponentTick.bCanEverTick = true; +} + +void UVehicleVelocityControl::BeginPlay() +{ + Super::BeginPlay(); + + SetComponentTickEnabled(false); + SetTickGroup(ETickingGroup::TG_PrePhysics); + + OwnerVehicle = GetOwner(); + PrimitiveComponent = Cast(OwnerVehicle->GetRootComponent()); +} + +void UVehicleVelocityControl::Activate(bool bReset) +{ + Super::Activate(bReset); + + TargetVelocity = FVector(); + SetComponentTickEnabled(true); +} + +void UVehicleVelocityControl::Activate(FVector Velocity, bool bReset) +{ + Super::Activate(bReset); + + TargetVelocity = Velocity; + SetComponentTickEnabled(true); +} + +void UVehicleVelocityControl::Deactivate() +{ + Super::Deactivate(); + SetComponentTickEnabled(false); +} + +void UVehicleVelocityControl::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) +{ + FTransform Transf = OwnerVehicle->GetActorTransform(); + const FVector LocVel = Transf.TransformVector(TargetVelocity); + PrimitiveComponent->SetPhysicsLinearVelocity(LocVel, false, "None"); +} diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.h new file mode 100644 index 00000000000..08f13cb5a67 --- /dev/null +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.h @@ -0,0 +1,56 @@ +// Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma +// de Barcelona (UAB). +// +// This work is licensed under the terms of the MIT license. +// For a copy, see . + +#pragma once + +#include "Components/ActorComponent.h" +#include "Components/PrimitiveComponent.h" +#include "CoreMinimal.h" + +#include "VehicleVelocityControl.generated.h" + +/// Component that controls that the velocity of an actor is constant. +UCLASS(Blueprintable, BlueprintType, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) +class CARLA_API UVehicleVelocityControl : public UActorComponent +{ + GENERATED_BODY() + + // =========================================================================== + /// @name Constructor and destructor + // =========================================================================== + /// @{ +public: + UVehicleVelocityControl(); + + /// @} + // =========================================================================== + /// @name Get functions + // =========================================================================== + /// @{ +public: + + void BeginPlay() override; + + virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override; + + // Activate the component setting the target velocity + virtual void Activate(bool bReset=false) override; + + // Activate the component setting the target velocity + virtual void Activate(FVector Velocity, bool bReset=false); + + // Deactivate the component + virtual void Deactivate() override; + +private: + /// + UPROPERTY(Category = "Vehicle Velocity Control", VisibleAnywhere) + FVector TargetVelocity; + + UPrimitiveComponent* PrimitiveComponent; + AActor* OwnerVehicle; + +}; From 2edd5427cb9d5a8fff16b90d980bfe311181e241 Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Tue, 22 Sep 2020 09:47:49 +0200 Subject: [PATCH 117/179] Minor format changes --- LibCarla/source/carla/client/Actor.h | 2 ++ LibCarla/source/carla/client/detail/Client.cpp | 1 + LibCarla/source/carla/client/detail/Client.h | 1 + 3 files changed, 4 insertions(+) diff --git a/LibCarla/source/carla/client/Actor.h b/LibCarla/source/carla/client/Actor.h index 7751f4cde15..916af9596e1 100644 --- a/LibCarla/source/carla/client/Actor.h +++ b/LibCarla/source/carla/client/Actor.h @@ -69,8 +69,10 @@ namespace client { /// Set the angular velocity of the actor before applying physics. void SetTargetAngularVelocity(const geom::Vector3D &vector); + /// Enable a constant velocity mode void EnableConstantVelocity(const geom::Vector3D &vector); + /// Disable the constant velocity mode void DisableConstantVelocity(); diff --git a/LibCarla/source/carla/client/detail/Client.cpp b/LibCarla/source/carla/client/detail/Client.cpp index e813f37d33d..eda02fa8918 100644 --- a/LibCarla/source/carla/client/detail/Client.cpp +++ b/LibCarla/source/carla/client/detail/Client.cpp @@ -271,6 +271,7 @@ namespace detail { void Client::SetActorTargetAngularVelocity(rpc::ActorId actor, const geom::Vector3D &vector) { _pimpl->AsyncCall("set_actor_target_angular_velocity", actor, vector); } + void Client::EnableActorConstantVelocity(rpc::ActorId actor, const geom::Vector3D &vector) { _pimpl->AsyncCall("enable_actor_constant_velocity", actor, vector); } diff --git a/LibCarla/source/carla/client/detail/Client.h b/LibCarla/source/carla/client/detail/Client.h index b0964747a5c..f175519e16c 100644 --- a/LibCarla/source/carla/client/detail/Client.h +++ b/LibCarla/source/carla/client/detail/Client.h @@ -153,6 +153,7 @@ namespace detail { void SetActorTargetAngularVelocity( rpc::ActorId actor, const geom::Vector3D &vector); + void EnableActorConstantVelocity( rpc::ActorId actor, const geom::Vector3D &vector); From 1144e691133f551b7729a5ce7161eaabea912d73 Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Tue, 22 Sep 2020 10:54:55 +0200 Subject: [PATCH 118/179] Fix disable_constant_velocity binding --- .../CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp | 3 +-- .../Carla/Source/Carla/Vehicle/VehicleVelocityControl.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp index d2119eee92d..d38f0b340dc 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp @@ -579,8 +579,7 @@ void FCarlaServer::FPimpl::BindActions() }; BIND_SYNC(disable_actor_constant_velocity) << [this]( - cr::ActorId ActorId, - cr::Vector3D vector) -> R + cr::ActorId ActorId) -> R { REQUIRE_CARLA_EPISODE(); auto ActorView = Episode->FindActor(ActorId); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.cpp index 94939ddc693..160c37eebf4 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.cpp @@ -43,8 +43,8 @@ void UVehicleVelocityControl::Activate(FVector Velocity, bool bReset) void UVehicleVelocityControl::Deactivate() { - Super::Deactivate(); SetComponentTickEnabled(false); + Super::Deactivate(); } void UVehicleVelocityControl::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) From 7c3c259926760894c2a9b6d1d6d54be92c9e54d8 Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Tue, 22 Sep 2020 10:59:14 +0200 Subject: [PATCH 119/179] Updated CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8eb96630ce..c6c6ebf53cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ * Fixed colors of lane markings when importing a map, they were reversed (white and yellow) * Fixed missing include directive in file **WheelPhysicsControl.h** * Fixed gravity measurement bug from IMU sensor + * Added Constant Velocity mode * All sensors are now multi-stream, that means that the same sensor can be listened from different clients * Fixed point cloud of LiDAR. Now the points are given correctly in the sensor's coordinate system * Fixed light intensity and camera parameters to match From ad74bef0c3979c8a4ac232f2f199841ffbe2e831 Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Tue, 22 Sep 2020 11:05:04 +0200 Subject: [PATCH 120/179] Added Constant Velocity Mode to manual_control.py --- PythonAPI/examples/manual_control.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/PythonAPI/examples/manual_control.py b/PythonAPI/examples/manual_control.py index f6e7b3b0e90..5d6e56036d8 100755 --- a/PythonAPI/examples/manual_control.py +++ b/PythonAPI/examples/manual_control.py @@ -22,6 +22,7 @@ P : toggle autopilot M : toggle manual transmission ,/. : gear up/down + CTRL + W : toggle constant velocity mode at 60 km/h L : toggle next light type SHIFT + L : toggle high beam @@ -181,6 +182,7 @@ def __init__(self, carla_world, hud, args): self.world.on_tick(hud.on_world_tick) self.recording_enabled = False self.recording_start = 0 + self.constant_velocity_enabled = False def restart(self): self.player_max_speed = 1.589 @@ -330,6 +332,15 @@ def parse_events(self, client, world, clock): world.camera_manager.next_sensor() elif event.key == K_n: world.camera_manager.next_sensor() + elif event.key == K_w and (pygame.key.get_mods() & KMOD_CTRL): + if world.constant_velocity_enabled: + world.player.disable_constant_velocity() + world.constant_velocity_enabled = False + world.hud.notification("Disabled Constant Velocity Mode") + else: + world.player.enable_constant_velocity(carla.Vector3D(17, 0, 0)) + world.constant_velocity_enabled = True + world.hud.notification("Enabled Constant Velocity Mode at 60 km/h") elif event.key > K_0 and event.key <= K_9: world.camera_manager.set_sensor(event.key - 1 - K_0) elif event.key == K_r and not (pygame.key.get_mods() & KMOD_CTRL): From 30ba2b3323a7979f55ad0e1effc9f6820190e0b7 Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Tue, 22 Sep 2020 18:46:43 +0200 Subject: [PATCH 121/179] Exposed AddForce and AddTorque --- LibCarla/source/carla/client/Actor.cpp | 20 +++- LibCarla/source/carla/client/Actor.h | 15 ++- .../source/carla/client/detail/Client.cpp | 20 +++- LibCarla/source/carla/client/detail/Client.h | 20 +++- .../source/carla/client/detail/Simulator.h | 20 +++- PythonAPI/carla/source/libcarla/Actor.cpp | 26 +++++- .../Carla/Source/Carla/Server/CarlaServer.cpp | 91 +++++++++++++++++++ 7 files changed, 202 insertions(+), 10 deletions(-) diff --git a/LibCarla/source/carla/client/Actor.cpp b/LibCarla/source/carla/client/Actor.cpp index d8681dcad5c..476d51890d7 100644 --- a/LibCarla/source/carla/client/Actor.cpp +++ b/LibCarla/source/carla/client/Actor.cpp @@ -56,14 +56,30 @@ namespace client { GetEpisode().Lock()->DisableActorConstantVelocity(*this); } - void Actor::AddImpulse(const geom::Vector3D &vector) { - GetEpisode().Lock()->AddActorImpulse(*this, vector); + void Actor::AddImpulse(const geom::Vector3D &impulse) { + GetEpisode().Lock()->AddActorImpulse(*this, impulse); + } + + void Actor::AddImpulse(const geom::Vector3D &impulse, const geom::Vector3D &location) { + GetEpisode().Lock()->AddActorImpulse(*this, impulse, location); + } + + void Actor::AddForce(const geom::Vector3D &force) { + GetEpisode().Lock()->AddActorForce(*this, force); + } + + void Actor::AddForce(const geom::Vector3D &force, const geom::Vector3D &location) { + GetEpisode().Lock()->AddActorForce(*this, force, location); } void Actor::AddAngularImpulse(const geom::Vector3D &vector) { GetEpisode().Lock()->AddActorAngularImpulse(*this, vector); } + void Actor::AddTorque(const geom::Vector3D &torque) { + GetEpisode().Lock()->AddActorTorque(*this, torque); + } + void Actor::SetSimulatePhysics(const bool enabled) { GetEpisode().Lock()->SetActorSimulatePhysics(*this, enabled); } diff --git a/LibCarla/source/carla/client/Actor.h b/LibCarla/source/carla/client/Actor.h index 916af9596e1..3710765bb6f 100644 --- a/LibCarla/source/carla/client/Actor.h +++ b/LibCarla/source/carla/client/Actor.h @@ -76,13 +76,24 @@ namespace client { /// Disable the constant velocity mode void DisableConstantVelocity(); - - /// Add impulse to the actor. + /// Add impulse to the actor at its center of mass. void AddImpulse(const geom::Vector3D &vector); + /// Add impulse to the actor at certain location. + void AddImpulse(const geom::Vector3D &impulse, const geom::Vector3D &location); + + /// Add force to the actor at its center of mass. + void AddForce(const geom::Vector3D &force); + + /// Add force to the actor at certain location. + void AddForce(const geom::Vector3D &force, const geom::Vector3D &location); + /// Add angular impulse to the actor. void AddAngularImpulse(const geom::Vector3D &vector); + /// Add a torque to the actor. + void AddTorque(const geom::Vector3D &vector); + /// Enable or disable physics simulation on this actor. void SetSimulatePhysics(bool enabled = true); diff --git a/LibCarla/source/carla/client/detail/Client.cpp b/LibCarla/source/carla/client/detail/Client.cpp index eda02fa8918..77add06c63e 100644 --- a/LibCarla/source/carla/client/detail/Client.cpp +++ b/LibCarla/source/carla/client/detail/Client.cpp @@ -280,14 +280,30 @@ namespace detail { _pimpl->AsyncCall("disable_actor_constant_velocity", actor); } - void Client::AddActorImpulse(rpc::ActorId actor, const geom::Vector3D &vector) { - _pimpl->AsyncCall("add_actor_impulse", actor, vector); + void Client::AddActorImpulse(rpc::ActorId actor, const geom::Vector3D &impulse) { + _pimpl->AsyncCall("add_actor_impulse", actor, impulse); + } + + void Client::AddActorImpulse(rpc::ActorId actor, const geom::Vector3D &impulse, const geom::Vector3D &location) { + _pimpl->AsyncCall("add_actor_impulse_at_location", actor, impulse, location); + } + + void Client::AddActorForce(rpc::ActorId actor, const geom::Vector3D &force) { + _pimpl->AsyncCall("add_actor_force", actor, force); + } + + void Client::AddActorForce(rpc::ActorId actor, const geom::Vector3D &force, const geom::Vector3D &location) { + _pimpl->AsyncCall("add_actor_force_at_location", actor, force, location); } void Client::AddActorAngularImpulse(rpc::ActorId actor, const geom::Vector3D &vector) { _pimpl->AsyncCall("add_actor_angular_impulse", actor, vector); } + void Client::AddActorTorque(rpc::ActorId actor, const geom::Vector3D &vector) { + _pimpl->AsyncCall("add_actor_torque", actor, vector); + } + void Client::SetActorSimulatePhysics(rpc::ActorId actor, const bool enabled) { _pimpl->AsyncCall("set_actor_simulate_physics", actor, enabled); } diff --git a/LibCarla/source/carla/client/detail/Client.h b/LibCarla/source/carla/client/detail/Client.h index f175519e16c..eb4f840eca5 100644 --- a/LibCarla/source/carla/client/detail/Client.h +++ b/LibCarla/source/carla/client/detail/Client.h @@ -163,12 +163,30 @@ namespace detail { void AddActorImpulse( rpc::ActorId actor, - const geom::Vector3D &vector); + const geom::Vector3D &impulse); + + void AddActorImpulse( + rpc::ActorId actor, + const geom::Vector3D &impulse, + const geom::Vector3D &location); + + void AddActorForce( + rpc::ActorId actor, + const geom::Vector3D &force); + + void AddActorForce( + rpc::ActorId actor, + const geom::Vector3D &force, + const geom::Vector3D &location); void AddActorAngularImpulse( rpc::ActorId actor, const geom::Vector3D &vector); + void AddActorTorque( + rpc::ActorId actor, + const geom::Vector3D &vector); + void SetActorSimulatePhysics( rpc::ActorId actor, bool enabled); diff --git a/LibCarla/source/carla/client/detail/Simulator.h b/LibCarla/source/carla/client/detail/Simulator.h index 0fc1b838a44..0ceacf50c1a 100644 --- a/LibCarla/source/carla/client/detail/Simulator.h +++ b/LibCarla/source/carla/client/detail/Simulator.h @@ -338,14 +338,30 @@ namespace detail { _client.DisableActorConstantVelocity(actor.GetId()); } - void AddActorImpulse(const Actor &actor, const geom::Vector3D &vector) { - _client.AddActorImpulse(actor.GetId(), vector); + void AddActorImpulse(const Actor &actor, const geom::Vector3D &impulse) { + _client.AddActorImpulse(actor.GetId(), impulse); + } + + void AddActorImpulse(const Actor &actor, const geom::Vector3D &impulse, const geom::Vector3D &location) { + _client.AddActorImpulse(actor.GetId(), impulse, location); + } + + void AddActorForce(const Actor &actor, const geom::Vector3D &force) { + _client.AddActorForce(actor.GetId(), force); + } + + void AddActorForce(const Actor &actor, const geom::Vector3D &force, const geom::Vector3D &location) { + _client.AddActorForce(actor.GetId(), force, location); } void AddActorAngularImpulse(const Actor &actor, const geom::Vector3D &vector) { _client.AddActorAngularImpulse(actor.GetId(), vector); } + void AddActorTorque(const Actor &actor, const geom::Vector3D &torque) { + _client.AddActorAngularImpulse(actor.GetId(), torque); + } + geom::Vector3D GetActorAcceleration(const Actor &actor) const { return GetActorSnapshot(actor).acceleration; } diff --git a/PythonAPI/carla/source/libcarla/Actor.cpp b/PythonAPI/carla/source/libcarla/Actor.cpp index 5066a586e09..92ba7ee59f8 100644 --- a/PythonAPI/carla/source/libcarla/Actor.cpp +++ b/PythonAPI/carla/source/libcarla/Actor.cpp @@ -37,6 +37,26 @@ static auto GetSemanticTags(const carla::client::Actor &self) { return boost::python::list(iter); } +static void AddActorImpulseCOM(carla::client::Actor &self, + const carla::geom::Vector3D &impulse) { + self.AddImpulse(impulse); +} + +static void AddActorImpulseLoc(carla::client::Actor &self, + const carla::geom::Vector3D &impulse, const carla::geom::Vector3D &location) { + self.AddImpulse(impulse, location); +} + +static void AddActorForceCOM(carla::client::Actor &self, + const carla::geom::Vector3D &force) { + self.AddForce(force); +} + +static void AddActorForceLoc(carla::client::Actor &self, + const carla::geom::Vector3D &force, const carla::geom::Vector3D &location) { + self.AddForce(force, location); +} + static auto GetGroupTrafficLights(carla::client::TrafficLight &self) { namespace py = boost::python; auto values = self.GetGroupTrafficLights(); @@ -89,8 +109,12 @@ void export_actor() { .def("set_target_angular_velocity", &cc::Actor::SetTargetAngularVelocity, (arg("vector"))) .def("enable_constant_velocity", &cc::Actor::EnableConstantVelocity, (arg("vector"))) .def("disable_constant_velocity", &cc::Actor::DisableConstantVelocity) - .def("add_impulse", &cc::Actor::AddImpulse, (arg("vector"))) + .def("add_impulse", &AddActorImpulseCOM, (arg("impulse"))) +// .def("add_impulse", &AddActorImpulseLoc, (args("impulse", "location"))) + .def("add_force", &AddActorForceCOM, (arg("force"))) +// .def("add_force", &AddActorForceLoc, (args("force", "location"))) .def("add_angular_impulse", &cc::Actor::AddAngularImpulse, (arg("vector"))) + .def("add_torque", &cc::Actor::AddTorque, (arg("vector"))) .def("set_simulate_physics", &cc::Actor::SetSimulatePhysics, (arg("enabled") = true)) .def("destroy", CALL_WITHOUT_GIL(cc::Actor, Destroy)) .def(self_ns::str(self_ns::self)) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp index d38f0b340dc..18b6c65a0e9 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp @@ -620,6 +620,75 @@ void FCarlaServer::FPimpl::BindActions() return R::Success(); }; + BIND_SYNC(add_actor_impulse_at_location) << [this]( + cr::ActorId ActorId, + cr::Vector3D impulse, + cr::Vector3D location) -> R + { + REQUIRE_CARLA_EPISODE(); + auto ActorView = Episode->FindActor(ActorId); + if (!ActorView.IsValid()) + { + RESPOND_ERROR("unable to add actor impulse: actor not found"); + } + auto RootComponent = Cast(ActorView.GetActor()->GetRootComponent()); + if (RootComponent == nullptr) + { + RESPOND_ERROR("unable to add actor impulse: not supported by actor"); + } + + RootComponent->AddImpulseAtLocation( + impulse.ToCentimeters().ToFVector(), + location.ToCentimeters().ToFVector(), + "None"); + return R::Success(); + }; + + BIND_SYNC(add_actor_force) << [this]( + cr::ActorId ActorId, + cr::Vector3D vector) -> R + { + REQUIRE_CARLA_EPISODE(); + auto ActorView = Episode->FindActor(ActorId); + if (!ActorView.IsValid()) + { + RESPOND_ERROR("unable to add actor impulse: actor not found"); + } + auto RootComponent = Cast(ActorView.GetActor()->GetRootComponent()); + if (RootComponent == nullptr) + { + RESPOND_ERROR("unable to add actor impulse: not supported by actor"); + } + RootComponent->AddForce( + vector.ToCentimeters().ToFVector(), + "None", + false); + return R::Success(); + }; + + BIND_SYNC(add_actor_force_at_location) << [this]( + cr::ActorId ActorId, + cr::Vector3D force, + cr::Vector3D location) -> R + { + REQUIRE_CARLA_EPISODE(); + auto ActorView = Episode->FindActor(ActorId); + if (!ActorView.IsValid()) + { + RESPOND_ERROR("unable to add actor impulse: actor not found"); + } + auto RootComponent = Cast(ActorView.GetActor()->GetRootComponent()); + if (RootComponent == nullptr) + { + RESPOND_ERROR("unable to add actor impulse: not supported by actor"); + } + RootComponent->AddForceAtLocation( + force.ToCentimeters().ToFVector(), + location.ToCentimeters().ToFVector(), + "None"); + return R::Success(); + }; + BIND_SYNC(add_actor_angular_impulse) << [this]( cr::ActorId ActorId, cr::Vector3D vector) -> R @@ -642,6 +711,28 @@ void FCarlaServer::FPimpl::BindActions() return R::Success(); }; + BIND_SYNC(add_actor_torque) << [this]( + cr::ActorId ActorId, + cr::Vector3D vector) -> R + { + REQUIRE_CARLA_EPISODE(); + auto ActorView = Episode->FindActor(ActorId); + if (!ActorView.IsValid()) + { + RESPOND_ERROR("unable to add actor torque: actor not found"); + } + auto RootComponent = Cast(ActorView.GetActor()->GetRootComponent()); + if (RootComponent == nullptr) + { + RESPOND_ERROR("unable to add actor torque: not supported by actor"); + } + RootComponent->AddTorqueInDegrees( + vector.ToFVector(), + "None", + false); + return R::Success(); + }; + BIND_SYNC(get_physics_control) << [this]( cr::ActorId ActorId) -> R { From ced3a6ab8ea9b840e7758003e961216e5f0f58d8 Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Tue, 22 Sep 2020 18:50:02 +0200 Subject: [PATCH 122/179] Added an script to test vehicle_physics --- PythonAPI/examples/vehicle_physics.py | 147 ++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 PythonAPI/examples/vehicle_physics.py diff --git a/PythonAPI/examples/vehicle_physics.py b/PythonAPI/examples/vehicle_physics.py new file mode 100644 index 00000000000..9b71c3a9ef2 --- /dev/null +++ b/PythonAPI/examples/vehicle_physics.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python + +# Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma de +# Barcelona (UAB). +# +# This work is licensed under the terms of the MIT license. +# For a copy, see . + +""" +Vehicle physics example for CARLA +Small example that shows the effect of different impulse and force aplication +methods to a vehicle. +""" + +import glob +import os +import sys +import argparse +import time +from datetime import datetime +import random +import numpy as np +from matplotlib import cm +import open3d as o3d + +try: + sys.path.append(glob.glob('../carla/dist/carla-*%d.%d-%s.egg' % ( + sys.version_info.major, + sys.version_info.minor, + 'win-amd64' if os.name == 'nt' else 'linux-x86_64'))[0]) +except IndexError: + pass + +import carla + + +def print_step_info(world, vehicle): + snapshot = world.get_snapshot() + print("%d %06.03f %+8.03f %+8.03f %+8.03f %+8.03f %+8.03f %+8.03f %+8.03f %+8.03f %+8.03f" % + (snapshot.frame, snapshot.timestamp.elapsed_seconds, \ + vehicle.get_acceleration().x, vehicle.get_acceleration().y, vehicle.get_acceleration().z, \ + vehicle.get_velocity().x, vehicle.get_velocity().y, vehicle.get_velocity().z, \ + vehicle.get_location().x, vehicle.get_location().y, vehicle.get_location().z)) + +def wait(world, frames=100): + for i in range(0, frames): + world.tick() + +def main(arg): + """Main function of the script""" + client = carla.Client(arg.host, arg.port) + client.set_timeout(2.0) + world = client.get_world() + + try: + # Setting the world and the spawn properties + original_settings = world.get_settings() + settings = world.get_settings() + + delta = 0.1 + settings.fixed_delta_seconds = delta + settings.synchronous_mode = True + world.apply_settings(settings) + + blueprint_library = world.get_blueprint_library() + vehicle_bp = blueprint_library.filter(arg.filter)[0] + + vehicle_transform = world.get_map().get_spawn_points()[0] + vehicle_transform.location.z += 3 + vehicle = world.spawn_actor(vehicle_bp, vehicle_transform) + + physics_vehicle = vehicle.get_physics_control() + car_mass = physics_vehicle.mass + + spectator_transform = carla.Transform(vehicle_transform.location, vehicle_transform.rotation) + spectator_transform.location += vehicle_transform.get_forward_vector() * 20 + spectator_transform.rotation.yaw += 180 + spectator = world.get_spectator() + spectator.set_transform(spectator_transform) + + + # We want to + wait(world) + vehicle.set_target_velocity(carla.Vector3D(0, 0, 0)) + vehicle_transform = vehicle.get_transform() + wait(world) + + # Impulse/Force at the center of mass of the object + impulse = 10 * car_mass + + print(car_mass) + + print("# Adding an Impulse of %f N·s" % impulse) + vehicle.add_impulse(carla.Vector3D(0, 0, impulse)) + + wait(world) + vehicle.set_transform(vehicle_transform) + vehicle.set_target_velocity(carla.Vector3D(0, 0, 0)) + wait(world) + + print("# Adding Force of %f N" % (impulse / delta)) + vehicle.add_force(carla.Vector3D(0, 0, impulse / delta)) + + wait(world) + vehicle.set_transform(vehicle_transform) + vehicle.set_target_velocity(carla.Vector3D(0, 0, 0)) + wait(world) + + wait(world) + wait(world) + wait(world) + wait(world) + wait(world) + + + finally: + world.apply_settings(original_settings) + + vehicle.destroy() + + +if __name__ == "__main__": + + argparser = argparse.ArgumentParser( + description=__doc__) + argparser.add_argument( + '--host', + metavar='H', + default='localhost', + help='IP of the host CARLA Simulator (default: localhost)') + argparser.add_argument( + '-p', '--port', + metavar='P', + default=2000, + type=int, + help='TCP port of CARLA Simulator (default: 2000)') + argparser.add_argument( + '--filter', + metavar='PATTERN', + default='model3', + help='actor filter (default: "vehicle.*")') + args = argparser.parse_args() + + try: + main(args) + except KeyboardInterrupt: + print(' - Exited by user.') From 709bfe016f709feebf22381a697c5f3b46be60ac Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Tue, 22 Sep 2020 18:57:59 +0200 Subject: [PATCH 123/179] Updated CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6c6ebf53cb..740dd1c6aed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ * Change API: set_velocity to set_target_velocity for linear and angular velocities * Added API function `add_angular_impulse()` to add angular impulse to any actor * Fixed rain drop spawn issues when spawning camera sensors + * Exposed add_force and add_torque * Fixed assets import pipeline * Fixed Update.sh from failing when the root folder contains a space on it * Fixed dynamic meshes not moving to initial position when replaying From befe694950904e7a52f082e1cb636b53666c1215 Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Wed, 23 Sep 2020 10:34:03 +0200 Subject: [PATCH 124/179] Commented ImpulseLoc/ForceLoc to avoid compiling error --- PythonAPI/carla/source/libcarla/Actor.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/PythonAPI/carla/source/libcarla/Actor.cpp b/PythonAPI/carla/source/libcarla/Actor.cpp index 92ba7ee59f8..c5e94c7c1af 100644 --- a/PythonAPI/carla/source/libcarla/Actor.cpp +++ b/PythonAPI/carla/source/libcarla/Actor.cpp @@ -42,20 +42,20 @@ static void AddActorImpulseCOM(carla::client::Actor &self, self.AddImpulse(impulse); } -static void AddActorImpulseLoc(carla::client::Actor &self, - const carla::geom::Vector3D &impulse, const carla::geom::Vector3D &location) { - self.AddImpulse(impulse, location); -} +//static void AddActorImpulseLoc(carla::client::Actor &self, +// const carla::geom::Vector3D &impulse, const carla::geom::Vector3D &location) { +// self.AddImpulse(impulse, location); +//} static void AddActorForceCOM(carla::client::Actor &self, const carla::geom::Vector3D &force) { self.AddForce(force); } -static void AddActorForceLoc(carla::client::Actor &self, - const carla::geom::Vector3D &force, const carla::geom::Vector3D &location) { - self.AddForce(force, location); -} +//static void AddActorForceLoc(carla::client::Actor &self, +// const carla::geom::Vector3D &force, const carla::geom::Vector3D &location) { +// self.AddForce(force, location); +//} static auto GetGroupTrafficLights(carla::client::TrafficLight &self) { namespace py = boost::python; From 72d8fcb08e1ed4bcb952265366b0764297b74939 Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Wed, 23 Sep 2020 10:39:36 +0200 Subject: [PATCH 125/179] Add Warning in the internal use of impulse/force at location --- .../Plugins/Carla/Source/Carla/Server/CarlaServer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp index 18b6c65a0e9..99a4abeec78 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp @@ -637,6 +637,8 @@ void FCarlaServer::FPimpl::BindActions() RESPOND_ERROR("unable to add actor impulse: not supported by actor"); } + UE_LOG(LogCarla, Warning, TEXT("AddImpulseAtLocation: Experimental feature, use carefully.")); + RootComponent->AddImpulseAtLocation( impulse.ToCentimeters().ToFVector(), location.ToCentimeters().ToFVector(), @@ -682,6 +684,9 @@ void FCarlaServer::FPimpl::BindActions() { RESPOND_ERROR("unable to add actor impulse: not supported by actor"); } + + UE_LOG(LogCarla, Warning, TEXT("AddImpulseAtLocation: Experimental feature, use carefully.")); + RootComponent->AddForceAtLocation( force.ToCentimeters().ToFVector(), location.ToCentimeters().ToFVector(), From 14fa890aa9f6a6716a0e574944efb05ef5858cda Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Wed, 23 Sep 2020 10:42:11 +0200 Subject: [PATCH 126/179] Added some clarificacion to the example script --- PythonAPI/examples/vehicle_physics.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/PythonAPI/examples/vehicle_physics.py b/PythonAPI/examples/vehicle_physics.py index 9b71c3a9ef2..3f662523159 100644 --- a/PythonAPI/examples/vehicle_physics.py +++ b/PythonAPI/examples/vehicle_physics.py @@ -8,7 +8,7 @@ """ Vehicle physics example for CARLA -Small example that shows the effect of different impulse and force aplication +Small example that shows the effect of different impulse and force aplication methods to a vehicle. """ @@ -68,10 +68,10 @@ def main(arg): vehicle_transform = world.get_map().get_spawn_points()[0] vehicle_transform.location.z += 3 vehicle = world.spawn_actor(vehicle_bp, vehicle_transform) - + physics_vehicle = vehicle.get_physics_control() car_mass = physics_vehicle.mass - + spectator_transform = carla.Transform(vehicle_transform.location, vehicle_transform.rotation) spectator_transform.location += vehicle_transform.get_forward_vector() * 20 spectator_transform.rotation.yaw += 180 @@ -79,7 +79,7 @@ def main(arg): spectator.set_transform(spectator_transform) - # We want to + # We want to wait(world) vehicle.set_target_velocity(carla.Vector3D(0, 0, 0)) vehicle_transform = vehicle.get_transform() @@ -87,10 +87,10 @@ def main(arg): # Impulse/Force at the center of mass of the object impulse = 10 * car_mass - + print(car_mass) - print("# Adding an Impulse of %f N·s" % impulse) + print("# Adding an Impulse") vehicle.add_impulse(carla.Vector3D(0, 0, impulse)) wait(world) @@ -98,7 +98,9 @@ def main(arg): vehicle.set_target_velocity(carla.Vector3D(0, 0, 0)) wait(world) - print("# Adding Force of %f N" % (impulse / delta)) + print("# Adding an scaled Force") + # AddForce should not be use for instantaneous forces like this one. + # This is only to show a way of making an equivalence between impulse and force. vehicle.add_force(carla.Vector3D(0, 0, impulse / delta)) wait(world) From 11f5a749f4114aeefb663cb3b1d3b9918acbb0ed Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Wed, 23 Sep 2020 12:54:42 +0200 Subject: [PATCH 127/179] Removed commented features from PythonAPI --- PythonAPI/carla/source/libcarla/Actor.cpp | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/PythonAPI/carla/source/libcarla/Actor.cpp b/PythonAPI/carla/source/libcarla/Actor.cpp index c5e94c7c1af..3354a46da52 100644 --- a/PythonAPI/carla/source/libcarla/Actor.cpp +++ b/PythonAPI/carla/source/libcarla/Actor.cpp @@ -37,26 +37,16 @@ static auto GetSemanticTags(const carla::client::Actor &self) { return boost::python::list(iter); } -static void AddActorImpulseCOM(carla::client::Actor &self, +static void AddActorImpulse(carla::client::Actor &self, const carla::geom::Vector3D &impulse) { self.AddImpulse(impulse); } -//static void AddActorImpulseLoc(carla::client::Actor &self, -// const carla::geom::Vector3D &impulse, const carla::geom::Vector3D &location) { -// self.AddImpulse(impulse, location); -//} - -static void AddActorForceCOM(carla::client::Actor &self, +static void AddActorForce(carla::client::Actor &self, const carla::geom::Vector3D &force) { self.AddForce(force); } -//static void AddActorForceLoc(carla::client::Actor &self, -// const carla::geom::Vector3D &force, const carla::geom::Vector3D &location) { -// self.AddForce(force, location); -//} - static auto GetGroupTrafficLights(carla::client::TrafficLight &self) { namespace py = boost::python; auto values = self.GetGroupTrafficLights(); @@ -109,10 +99,8 @@ void export_actor() { .def("set_target_angular_velocity", &cc::Actor::SetTargetAngularVelocity, (arg("vector"))) .def("enable_constant_velocity", &cc::Actor::EnableConstantVelocity, (arg("vector"))) .def("disable_constant_velocity", &cc::Actor::DisableConstantVelocity) - .def("add_impulse", &AddActorImpulseCOM, (arg("impulse"))) -// .def("add_impulse", &AddActorImpulseLoc, (args("impulse", "location"))) - .def("add_force", &AddActorForceCOM, (arg("force"))) -// .def("add_force", &AddActorForceLoc, (args("force", "location"))) + .def("add_impulse", &AddActorImpulse, (arg("impulse"))) + .def("add_force", &AddActorForce, (arg("force"))) .def("add_angular_impulse", &cc::Actor::AddAngularImpulse, (arg("vector"))) .def("add_torque", &cc::Actor::AddTorque, (arg("vector"))) .def("set_simulate_physics", &cc::Actor::SetSimulatePhysics, (arg("enabled") = true)) From a22bdc51ccac35d804975cee9b444ea3ead1edcf Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Wed, 23 Sep 2020 15:30:53 +0200 Subject: [PATCH 128/179] Added commands for AddTorque and AddForce --- LibCarla/source/carla/rpc/Command.h | 20 +++++++++++++++++++ .../Carla/Source/Carla/Server/CarlaServer.cpp | 4 +++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/LibCarla/source/carla/rpc/Command.h b/LibCarla/source/carla/rpc/Command.h index 6e689a2be24..b5cec5d664f 100644 --- a/LibCarla/source/carla/rpc/Command.h +++ b/LibCarla/source/carla/rpc/Command.h @@ -132,6 +132,16 @@ namespace rpc { MSGPACK_DEFINE_ARRAY(actor, impulse); }; + struct ApplyForce : CommandBase { + ApplyForce() = default; + ApplyForce(ActorId id, const geom::Vector3D &value) + : actor(id), + force(value) {} + ActorId actor; + geom::Vector3D force; + MSGPACK_DEFINE_ARRAY(actor, force); + }; + struct ApplyAngularImpulse : CommandBase { ApplyAngularImpulse() = default; ApplyAngularImpulse(ActorId id, const geom::Vector3D &value) @@ -142,6 +152,16 @@ namespace rpc { MSGPACK_DEFINE_ARRAY(actor, impulse); }; + struct ApplyTorque : CommandBase { + ApplyTorque() = default; + ApplyTorque(ActorId id, const geom::Vector3D &value) + : actor(id), + torque(value) {} + ActorId actor; + geom::Vector3D torque; + MSGPACK_DEFINE_ARRAY(actor, torque); + }; + struct SetSimulatePhysics : CommandBase { SetSimulatePhysics() = default; SetSimulatePhysics(ActorId id, bool value) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp index 99a4abeec78..bc1384bffdd 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp @@ -1250,10 +1250,12 @@ void FCarlaServer::FPimpl::BindActions() [=](auto, const C::ApplyVehicleControl &c) { MAKE_RESULT(apply_control_to_vehicle(c.actor, c.control)); }, [=](auto, const C::ApplyWalkerControl &c) { MAKE_RESULT(apply_control_to_walker(c.actor, c.control)); }, [=](auto, const C::ApplyTransform &c) { MAKE_RESULT(set_actor_transform(c.actor, c.transform)); }, - [=](auto, const C::ApplyTargetVelocity &c) { MAKE_RESULT(set_actor_target_velocity(c.actor, c.velocity)); }, + [=](auto, const C::ApplyTargetVelocity &c) { MAKE_RESULT(set_actor_target_velocity(c.actor, c.velocity)); }, [=](auto, const C::ApplyTargetAngularVelocity &c) { MAKE_RESULT(set_actor_target_angular_velocity(c.actor, c.angular_velocity)); }, [=](auto, const C::ApplyImpulse &c) { MAKE_RESULT(add_actor_impulse(c.actor, c.impulse)); }, + [=](auto, const C::ApplyForce &c) { MAKE_RESULT(add_actor_force(c.actor, c.force)); }, [=](auto, const C::ApplyAngularImpulse &c) { MAKE_RESULT(add_actor_angular_impulse(c.actor, c.impulse)); }, + [=](auto, const C::ApplyTorque &c) { MAKE_RESULT(add_actor_torque(c.actor, c.torque)); }, [=](auto, const C::SetSimulatePhysics &c) { MAKE_RESULT(set_actor_simulate_physics(c.actor, c.enabled)); }, // TODO: SetAutopilot should be removed. This is the old way to control the vehicles [=](auto, const C::SetAutopilot &c) { MAKE_RESULT(set_actor_autopilot(c.actor, c.enabled)); }, From e93dae859a56191039777eec719d7e6c10847970 Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Wed, 23 Sep 2020 15:31:52 +0200 Subject: [PATCH 129/179] Change parameters name to be more descrive. --- PythonAPI/carla/source/libcarla/Actor.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PythonAPI/carla/source/libcarla/Actor.cpp b/PythonAPI/carla/source/libcarla/Actor.cpp index 3354a46da52..efe97a0abf9 100644 --- a/PythonAPI/carla/source/libcarla/Actor.cpp +++ b/PythonAPI/carla/source/libcarla/Actor.cpp @@ -95,14 +95,14 @@ void export_actor() { .def("get_acceleration", &cc::Actor::GetAcceleration) .def("set_location", &cc::Actor::SetLocation, (arg("location"))) .def("set_transform", &cc::Actor::SetTransform, (arg("transform"))) - .def("set_target_velocity", &cc::Actor::SetTargetVelocity, (arg("vector"))) - .def("set_target_angular_velocity", &cc::Actor::SetTargetAngularVelocity, (arg("vector"))) - .def("enable_constant_velocity", &cc::Actor::EnableConstantVelocity, (arg("vector"))) + .def("set_target_velocity", &cc::Actor::SetTargetVelocity, (arg("velocity"))) + .def("set_target_angular_velocity", &cc::Actor::SetTargetAngularVelocity, (arg("angular_velocity"))) + .def("enable_constant_velocity", &cc::Actor::EnableConstantVelocity, (arg("velocity"))) .def("disable_constant_velocity", &cc::Actor::DisableConstantVelocity) .def("add_impulse", &AddActorImpulse, (arg("impulse"))) .def("add_force", &AddActorForce, (arg("force"))) - .def("add_angular_impulse", &cc::Actor::AddAngularImpulse, (arg("vector"))) - .def("add_torque", &cc::Actor::AddTorque, (arg("vector"))) + .def("add_angular_impulse", &cc::Actor::AddAngularImpulse, (arg("angular_impulse"))) + .def("add_torque", &cc::Actor::AddTorque, (arg("torque"))) .def("set_simulate_physics", &cc::Actor::SetSimulatePhysics, (arg("enabled") = true)) .def("destroy", CALL_WITHOUT_GIL(cc::Actor, Destroy)) .def(self_ns::str(self_ns::self)) From c1f88565d59159cd69593c42e82dd160455b521e Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Wed, 23 Sep 2020 15:35:38 +0200 Subject: [PATCH 130/179] Improving the script --- PythonAPI/examples/vehicle_physics.py | 29 ++++++++++----------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/PythonAPI/examples/vehicle_physics.py b/PythonAPI/examples/vehicle_physics.py index 3f662523159..ff654d5df60 100644 --- a/PythonAPI/examples/vehicle_physics.py +++ b/PythonAPI/examples/vehicle_physics.py @@ -16,12 +16,6 @@ import os import sys import argparse -import time -from datetime import datetime -import random -import numpy as np -from matplotlib import cm -import open3d as o3d try: sys.path.append(glob.glob('../carla/dist/carla-*%d.%d-%s.egg' % ( @@ -79,18 +73,17 @@ def main(arg): spectator.set_transform(spectator_transform) - # We want to + # We let the vehicle stabilize and save the transform to reset it after each test. wait(world) vehicle.set_target_velocity(carla.Vector3D(0, 0, 0)) vehicle_transform = vehicle.get_transform() wait(world) + # Impulse/Force at the center of mass of the object impulse = 10 * car_mass - print(car_mass) - - print("# Adding an Impulse") + print("# Adding an Impulse of %f N·s", % impulse) vehicle.add_impulse(carla.Vector3D(0, 0, impulse)) wait(world) @@ -98,9 +91,13 @@ def main(arg): vehicle.set_target_velocity(carla.Vector3D(0, 0, 0)) wait(world) - print("# Adding an scaled Force") - # AddForce should not be use for instantaneous forces like this one. - # This is only to show a way of making an equivalence between impulse and force. + print("# Adding a Force of %f N", % impulse / delta) + # The add_force method should not be use for instantaneous forces like this one, + # it is more useful for constant or variable forces acting in a finite amount of time. + # In this script it is done with the proper scaling to show the equivalence + # between the add_impulse and add_force methods. + # As in this case the force is going to be applied during the whole step dt=delta + # a force more or less equivalent is impulse / delta. vehicle.add_force(carla.Vector3D(0, 0, impulse / delta)) wait(world) @@ -108,11 +105,7 @@ def main(arg): vehicle.set_target_velocity(carla.Vector3D(0, 0, 0)) wait(world) - wait(world) - wait(world) - wait(world) - wait(world) - wait(world) + wait(world, 500) finally: From ffabf4cf3ef327672a431e1ddd15eba29255fcfe Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Wed, 23 Sep 2020 18:15:36 +0200 Subject: [PATCH 131/179] Added ApplyForce and ApplyTorque --- LibCarla/source/carla/rpc/Command.h | 2 ++ PythonAPI/carla/source/libcarla/Commands.cpp | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/LibCarla/source/carla/rpc/Command.h b/LibCarla/source/carla/rpc/Command.h index b5cec5d664f..b029b4d2e84 100644 --- a/LibCarla/source/carla/rpc/Command.h +++ b/LibCarla/source/carla/rpc/Command.h @@ -209,7 +209,9 @@ namespace rpc { ApplyTargetVelocity, ApplyTargetAngularVelocity, ApplyImpulse, + ApplyForce, ApplyAngularImpulse, + ApplyTorque, SetSimulatePhysics, SetAutopilot, SetVehicleLightState>; diff --git a/PythonAPI/carla/source/libcarla/Commands.cpp b/PythonAPI/carla/source/libcarla/Commands.cpp index 1e1e8d93c86..2edd79387a6 100644 --- a/PythonAPI/carla/source/libcarla/Commands.cpp +++ b/PythonAPI/carla/source/libcarla/Commands.cpp @@ -144,6 +144,13 @@ void export_commands() { .def_readwrite("impulse", &cr::Command::ApplyImpulse::impulse) ; + class_("ApplyForce") + .def("__init__", &command_impl::CustomInit, (arg("actor"), arg("force"))) + .def(init((arg("actor_id"), arg("force")))) + .def_readwrite("actor_id", &cr::Command::ApplyForce::actor) + .def_readwrite("force", &cr::Command::ApplyForce::force) + ; + class_("ApplyAngularImpulse") .def("__init__", &command_impl::CustomInit, (arg("actor"), arg("impulse"))) .def(init((arg("actor_id"), arg("impulse")))) @@ -151,6 +158,13 @@ void export_commands() { .def_readwrite("impulse", &cr::Command::ApplyAngularImpulse::impulse) ; + class_("ApplyTorque") + .def("__init__", &command_impl::CustomInit, (arg("actor"), arg("torque"))) + .def(init((arg("actor_id"), arg("torque")))) + .def_readwrite("actor_id", &cr::Command::ApplyTorque::actor) + .def_readwrite("torque", &cr::Command::ApplyTorque::torque) + ; + class_("SetSimulatePhysics") .def("__init__", &command_impl::CustomInit, (arg("actor"), arg("enabled"))) .def(init((arg("actor_id"), arg("enabled")))) @@ -182,7 +196,9 @@ void export_commands() { implicitly_convertible(); implicitly_convertible(); implicitly_convertible(); + implicitly_convertible(); implicitly_convertible(); + implicitly_convertible(); implicitly_convertible(); implicitly_convertible(); implicitly_convertible(); From 8bc91527a7c924a37cbb1405cd839bc3a07ede15 Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Wed, 23 Sep 2020 18:36:54 +0200 Subject: [PATCH 132/179] VehiclePhysics: Small bug fixed --- PythonAPI/examples/vehicle_physics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PythonAPI/examples/vehicle_physics.py b/PythonAPI/examples/vehicle_physics.py index ff654d5df60..1246c0f5def 100644 --- a/PythonAPI/examples/vehicle_physics.py +++ b/PythonAPI/examples/vehicle_physics.py @@ -83,7 +83,7 @@ def main(arg): # Impulse/Force at the center of mass of the object impulse = 10 * car_mass - print("# Adding an Impulse of %f N·s", % impulse) + print("# Adding an Impulse of %f N s" % impulse) vehicle.add_impulse(carla.Vector3D(0, 0, impulse)) wait(world) @@ -91,7 +91,7 @@ def main(arg): vehicle.set_target_velocity(carla.Vector3D(0, 0, 0)) wait(world) - print("# Adding a Force of %f N", % impulse / delta) + print("# Adding a Force of %f N" % (impulse / delta)) # The add_force method should not be use for instantaneous forces like this one, # it is more useful for constant or variable forces acting in a finite amount of time. # In this script it is done with the proper scaling to show the equivalence From b0090775a1e59696f1eeb16d60d52b96501721bb Mon Sep 17 00:00:00 2001 From: Daniel Santos-Olivan Date: Wed, 23 Sep 2020 18:46:53 +0200 Subject: [PATCH 133/179] Fix format tabs/newlines --- PythonAPI/examples/vehicle_physics.py | 2 ++ .../Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/PythonAPI/examples/vehicle_physics.py b/PythonAPI/examples/vehicle_physics.py index 1246c0f5def..af1b23bf63a 100644 --- a/PythonAPI/examples/vehicle_physics.py +++ b/PythonAPI/examples/vehicle_physics.py @@ -36,10 +36,12 @@ def print_step_info(world, vehicle): vehicle.get_velocity().x, vehicle.get_velocity().y, vehicle.get_velocity().z, \ vehicle.get_location().x, vehicle.get_location().y, vehicle.get_location().z)) + def wait(world, frames=100): for i in range(0, frames): world.tick() + def main(arg): """Main function of the script""" client = carla.Client(arg.host, arg.port) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.h index 08f13cb5a67..9727f148eb0 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/VehicleVelocityControl.h @@ -43,7 +43,7 @@ class CARLA_API UVehicleVelocityControl : public UActorComponent virtual void Activate(FVector Velocity, bool bReset=false); // Deactivate the component - virtual void Deactivate() override; + virtual void Deactivate() override; private: /// From e7ff12fa780bbbb63df24c2fa202e98659a9bb9e Mon Sep 17 00:00:00 2001 From: Jacopo Bartiromo Date: Wed, 23 Sep 2020 18:29:06 +0200 Subject: [PATCH 134/179] Changes default behavior for OSM parameter in TM --- .../source/carla/trafficmanager/LocalizationStage.cpp | 9 ++++----- LibCarla/source/carla/trafficmanager/Parameters.h | 2 +- PythonAPI/examples/spawn_npc.py | 6 ------ 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp b/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp index c2d98a29e12..87b8238a1a1 100644 --- a/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp +++ b/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp @@ -169,12 +169,11 @@ void LocalizationStage::Update(const unsigned long index) { double s_bucket = 100.0 / next_waypoints.size(); selection_index = static_cast(std::floor(r_sample/s_bucket)); } else if (next_waypoints.size() == 0) { - if (parameters.GetOSMMode()) { - marked_for_removal.push_back(actor_id); - break; - } else { - throw std::invalid_argument("This is an OSM, please activate the set_open_street_map parameter"); + if (!parameters.GetOSMMode()) { + std::cout << "This is an OSM, please change the set_open_street_map parameter to true" << std::endl; } + marked_for_removal.push_back(actor_id); + break; } SimpleWaypointPtr next_wp_selection = next_waypoints.at(selection_index); PushWaypoint(actor_id, track_traffic, waypoint_buffer, next_wp_selection); diff --git a/LibCarla/source/carla/trafficmanager/Parameters.h b/LibCarla/source/carla/trafficmanager/Parameters.h index 234062ddbc1..d017b2030ec 100644 --- a/LibCarla/source/carla/trafficmanager/Parameters.h +++ b/LibCarla/source/carla/trafficmanager/Parameters.h @@ -65,7 +65,7 @@ class Parameters { /// Hybrid physics radius. std::atomic hybrid_physics_radius {70.0}; /// Parameter specifying Open Street Map mode. - std::atomic osm_mode {false}; + std::atomic osm_mode {true}; public: Parameters(); diff --git a/PythonAPI/examples/spawn_npc.py b/PythonAPI/examples/spawn_npc.py index a79929b923c..970e4fda467 100755 --- a/PythonAPI/examples/spawn_npc.py +++ b/PythonAPI/examples/spawn_npc.py @@ -88,10 +88,6 @@ def main(): metavar='S', type=int, help='Random device seed') - argparser.add_argument( - '--osm', - action='store_true', - help='Open Street Map mode') argparser.add_argument( '--car-lights-on', action='store_true', @@ -119,8 +115,6 @@ def main(): if args.seed is not None: traffic_manager.set_random_device_seed(args.seed) - if args.osm: - traffic_manager.set_osm_mode(True) if args.sync: settings = world.get_settings() From a4799d5fa8014e5a312de24059e8551f2421cb77 Mon Sep 17 00:00:00 2001 From: Jacopo Bartiromo Date: Wed, 23 Sep 2020 18:44:32 +0200 Subject: [PATCH 135/179] Minor change to warning message --- LibCarla/source/carla/trafficmanager/LocalizationStage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp b/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp index 87b8238a1a1..fa1c5ea0b23 100644 --- a/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp +++ b/LibCarla/source/carla/trafficmanager/LocalizationStage.cpp @@ -170,7 +170,7 @@ void LocalizationStage::Update(const unsigned long index) { selection_index = static_cast(std::floor(r_sample/s_bucket)); } else if (next_waypoints.size() == 0) { if (!parameters.GetOSMMode()) { - std::cout << "This is an OSM, please change the set_open_street_map parameter to true" << std::endl; + std::cout << "This map has dead-end roads, please change the set_open_street_map parameter to true" << std::endl; } marked_for_removal.push_back(actor_id); break; From 6abf474468cf9b6e8973b97634ae74337b073023 Mon Sep 17 00:00:00 2001 From: Joel Moriana Date: Wed, 23 Sep 2020 18:18:32 +0200 Subject: [PATCH 136/179] Updated set_velocity to set_target_velocity --- Co-Simulation/PTV-Vissim/vissim_integration/carla_simulation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Co-Simulation/PTV-Vissim/vissim_integration/carla_simulation.py b/Co-Simulation/PTV-Vissim/vissim_integration/carla_simulation.py index f7f1b1eabdd..1d82bef1775 100644 --- a/Co-Simulation/PTV-Vissim/vissim_integration/carla_simulation.py +++ b/Co-Simulation/PTV-Vissim/vissim_integration/carla_simulation.py @@ -94,7 +94,7 @@ def synchronize_vehicle(self, vehicle_id, transform, velocity, lights=None): vehicle.set_transform(transform) if velocity is not None: - vehicle.set_velocity(velocity) + vehicle.set_target_velocity(velocity) if lights is not None: vehicle.set_light_state(carla.VehicleLightState(lights)) From bd0f40ae5613a8ba79cf957ee6b4f6804af67173 Mon Sep 17 00:00:00 2001 From: berndgassmann <44812003+berndgassmann@users.noreply.github.com> Date: Thu, 24 Sep 2020 10:42:06 +0200 Subject: [PATCH 137/179] Upddate adv_rss docu (#3357) --- Docs/adv_rss.md | 75 ++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/Docs/adv_rss.md b/Docs/adv_rss.md index 07f19d41bcc..12df5f156d3 100644 --- a/Docs/adv_rss.md +++ b/Docs/adv_rss.md @@ -1,14 +1,14 @@ # RSS -CARLA integrates the [C++ Library for Responsibility Sensitive Safety](https://github.com/intel/ad-rss-lib) in the client library. This feature allows users to investigate behaviours of RSS without having to implement anything. CARLA will take care of providing the input, and applying the output to the AD systems on the fly. +CARLA integrates the [C++ Library for Responsibility Sensitive Safety](https://github.com/intel/ad-rss-lib) in the client library. This feature allows users to investigate behaviours of RSS without having to implement anything. CARLA will take care of providing the input, and applying the output to the AD systems on the fly. -* [__Overview__](#overview) -* [__Compilation__](#compilation) - * [Dependencies](#dependencies) - * [Build](#build) -* [__Current state__](#current-state) - * [RssSensor](#rsssensor) - * [RssRestrictor](#rssrestrictor) +* [__Overview__](#overview) +* [__Compilation__](#compilation) + * [Dependencies](#dependencies) + * [Build](#build) +* [__Current state__](#current-state) + * [RssSensor](#rsssensor) + * [RssRestrictor](#rssrestrictor) !!! Important This feature is a work in progress. Right now, it is only available for the Linux build. @@ -16,29 +16,29 @@ CARLA integrates the [C++ Library for Responsibility Sensitive Safety](https://g --- ## Overview -The RSS library implements a mathematical model for safety assurance. It receives sensor information, and provides restrictions to the controllers of a vehicle. To sum up, the RSS module uses the sensor data to define __situations__. A situation describes the state of the ego vehicle with an element of the environment. For each situation, safety checks are made, and a proper response is calculated. The overall response is the result of all of the combined. For specific information on the library, read the [documentation](https://intel.github.io/ad-rss-lib/), especially the [Background section](https://intel.github.io/ad-rss-lib/ad_rss/Overview/). +The RSS library implements a mathematical model for safety assurance. It receives sensor information, and provides restrictions to the controllers of a vehicle. To sum up, the RSS module uses the sensor data to define __situations__. A situation describes the state of the ego vehicle with an element of the environment. For each situation, safety checks are made, and a proper response is calculated. The overall response is the result of all of the combined. For specific information on the library, read the [documentation](https://intel.github.io/ad-rss-lib/), especially the [Background section](https://intel.github.io/ad-rss-lib/ad_rss/Overview/). -This is implemented in CARLA using two elements. +This is implemented in CARLA using two elements. -* __RssSensor__ is in charge of the situation analysis, and response generation using the *ad-rss-lib*. -* __RssRestrictor__ applies the response by restricting the commands of the vehicle. +* __RssSensor__ is in charge of the situation analysis, and response generation using the *ad-rss-lib*. +* __RssRestrictor__ applies the response by restricting the commands of the vehicle. -The following image sketches the integration of __RSS__ into the CARLA architecture. +The following image sketches the integration of __RSS__ into the CARLA architecture. ![Interate RSS into CARLA](img/rss_carla_integration_architecture.png) -__1. The server.__ -     __-__ Sends a camera image to the client. (Only if the client needs visualization). -     __-__ Provides the RssSensor with world data. -     __-__ Sends a physics model of the vehicle to the RssRestrictor. (Only if the default values are overwritten). -__2. The client.__ -     __-__ Provides the *RssSensor* with some [parameters](https://intel.github.io/ad-rss-lib/ad_rss/Appendix-ParameterDiscussion/) to be considered. -     __-__ Sends to the *RssResrictor* an initial [carla.VehicleControl](python_api.md#carla.VehicleControl). -__3. The RssSensor.__ -     __-__ Uses the *ad-rss-lib* to extract situations, do safety checks, and generate a response. -     __-__ Sends the *RssRestrictor* a response containing the proper response and aceleration restrictions to be applied. -__4. The RssRestrictor__ -     __-__ If the client asks for it, applies the response to the [carla.VehicleControl](python_api.md#carla.VehicleControl), and returns the resulting one. +__1. The server.__ +     __-__ Sends a camera image to the client. (Only if the client needs visualization). +     __-__ Provides the RssSensor with world data. +     __-__ Sends a physics model of the vehicle to the RssRestrictor. (Only if the default values are overwritten). +__2. The client.__ +     __-__ Provides the *RssSensor* with some [parameters](https://intel.github.io/ad-rss-lib/ad_rss/Appendix-ParameterDiscussion/) to be considered. +     __-__ Sends to the *RssResrictor* an initial [carla.VehicleControl](python_api.md#carla.VehicleControl). +__3. The RssSensor.__ +     __-__ Uses the *ad-rss-lib* to extract situations, do safety checks, and generate a response. +     __-__ Sends the *RssRestrictor* a response containing the proper response and aceleration restrictions to be applied. +__4. The RssRestrictor__ +     __-__ If the client asks for it, applies the response to the [carla.VehicleControl](python_api.md#carla.VehicleControl), and returns the resulting one. [![RSS sensor in CARLA](img/rss_carla_integration.png)](https://www.youtube.com/watch?v=UxKPXPT2T8Q)
    Visualization of the RssSensor results.
    @@ -46,20 +46,20 @@ __4. The RssRestrictor__ --- ## Compilation -The RSS integration has to be built aside from the rest of CARLA. The __ad-rss-lib__ comes with an LGPL-2.1 open-source license that creates conflict. It has to be linked statically into *libCarla*. +The RSS integration has to be built aside from the rest of CARLA. The __ad-rss-lib__ comes with an LGPL-2.1 open-source license that creates conflict. It has to be linked statically into *libCarla*. -As a reminder, the feature is only available for the Linux build so far. +As a reminder, the feature is only available for the Linux build so far. ### Dependencies There are additional prerequisites required for building RSS and its dependencies. Take a look at the [official documentation](https://intel.github.io/ad-rss-lib/BUILDING)) to know more about this. -Dependencies provided by Ubunutu (>= 16.04). +Dependencies provided by Ubunutu (>= 16.04). ```sh -sudo apt-get install libgtest-dev libpython-dev libpugixml-dev libproj-dev libtbb-dev +sudo apt-get install libgtest-dev libpython-dev libpugixml-dev libtbb-dev ``` -The dependencies are built using [colcon](https://colcon.readthedocs.io/en/released/user/installation.html), so it has to be installed. +The dependencies are built using [colcon](https://colcon.readthedocs.io/en/released/user/installation.html), so it has to be installed. ```sh pip3 install --user -U colcon-common-extensions ``` @@ -67,27 +67,26 @@ pip3 install --user -U colcon-common-extensions There are some additional dependencies for the Python bindings. ```sh sudo apt-get install castxml -pip install --user pygccxml -pip install --user https://bitbucket.org/ompl/pyplusplus/get/1.8.1.zip +pip3 install --user pygccxml pyplusplus ``` ### Build Once this is done, the full set of dependencies and RSS components can be built. -* Compile LibCarla to work with RSS. +* Compile LibCarla to work with RSS. ```sh make LibCarla.client.rss ``` -* Compile the PythonAPI to include the RSS feature. +* Compile the PythonAPI to include the RSS feature. ```sh make PythonAPI.rss ``` -* As an alternative, a package can be built directly. +* As an alternative, a package can be built directly. ```sh make package.rss ``` @@ -103,7 +102,7 @@ So far, the server provides the sensor with ground truth data of the surrounding ### RssRestrictor -When the client calls for it, the [__carla.RssRestrictor__](python_api.md#carla.RssRestrictor) will modify the vehicle controller to best reach the desired accelerations or decelerations by a given response. +When the client calls for it, the [__carla.RssRestrictor__](python_api.md#carla.RssRestrictor) will modify the vehicle controller to best reach the desired accelerations or decelerations by a given response. Due to the stucture of [carla.VehicleControl](python_api.md#carla.VehicleControl) objects, the restrictions applied have certain limitations. These controllers include `throttle`, `brake` and `streering` values. However, due to car physics and the simple control options these might not be met. The restriction intervenes in lateral direction simply by counter steering towards the parallel lane direction. The brake will be activated if deceleration requested by RSS. This depends on vehicle mass and brake torques provided by the [carla.Vehicle](python_api.md#carla.Vehicle). @@ -112,9 +111,9 @@ Due to the stucture of [carla.VehicleControl](python_api.md#carla.VehicleControl --- -That sets the basics regarding the RSS sensor in CARLA. Find out more about the specific attributes and parameters in the [sensor reference](ref_sensors.md#rss-sensor). +That sets the basics regarding the RSS sensor in CARLA. Find out more about the specific attributes and parameters in the [sensor reference](ref_sensors.md#rss-sensor). -Open CARLA and mess around for a while. If there are any doubts, feel free to post these in the forum. +Open CARLA and mess around for a while. If there are any doubts, feel free to post these in the forum.

    From 0bbeeddf6a2d28642703dd4295a672d884b8b78e Mon Sep 17 00:00:00 2001 From: doterop Date: Thu, 17 Sep 2020 18:39:11 +0200 Subject: [PATCH 138/179] First steps on ProceduralBuiding port to C++ --- .../Carla/MapGen/ProceduralBuilding.cpp | 212 ++++++++++++++++ .../Source/Carla/MapGen/ProceduralBuilding.h | 233 ++++++++++++++++++ 2 files changed, 445 insertions(+) create mode 100644 Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp create mode 100644 Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp new file mode 100644 index 00000000000..823c49f2a98 --- /dev/null +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp @@ -0,0 +1,212 @@ +// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de Barcelona (UAB). This work is licensed under the terms of the MIT license. For a copy, see . + + +#include "ProceduralBuilding.h" + + +// Sets default values +AProceduralBuilding::AProceduralBuilding() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + + SideVisibility.Init(true, 4); + CornerVisibility.Init(true, 4); +} + +// Called when the game starts or when spawned +void AProceduralBuilding::BeginPlay() +{ + Super::BeginPlay(); + +} + +void AProceduralBuilding::CreateBuilding() +{ + Init(); + +} + +void AProceduralBuilding::Reset() +{ + // Discard previous calculation + SidesLength.Reset(); + + // Remove all the instances of each HISMComp + for(auto& It : HISMComps) + { + const FString& MeshName = It.Key; + UHierarchicalInstancedStaticMeshComponent* HISMComp = It.Value; + + HISMComp->ClearInstances(); + } + // Empties out the map but preserves all allocations and capacities + HISMComps.Reset(); + +} + +void AProceduralBuilding::Init() +{ + CalculateSidesLength(); +} + +void AProceduralBuilding::CreateFloor( + const FloorMeshCollection& MeshCollection, + bool IncludeDoors, + bool IncludeWalls) +{ + + + + // Stores the total length covered. This is needed to place the doors. + int SideLengthAcumulator = 0; + + for(int i = 0; i < SidesLength.Num(); i++) + { + TSet DoorsPosition; + int SideLength = SidesLength[i]; + bool MainVisibility = true; + bool CornerVisbility = true; + + if (IncludeDoors) + { + DoorsPosition = CalculateDoorsIndexInSide(SideLengthAcumulator, SideLength); + } + + CalculateSideVisibilities(i, MainVisibility, CornerVisbility); + + CreateSide(MeshCollection, DoorsPosition, SideLength, MainVisibility, CornerVisbility); + + SideLengthAcumulator += SidesLength; + } +} + + +float AProceduralBuilding::CreateSide( + const FloorMeshCollection& MeshCollection, + const TSet& AuxiliarPositions, + int SideLength, + bool MainVisibility, + bool CornerVisbility) +{ + const TArray* MainMeshes = MeshCollection.MainMeshes; + const TArray* MainBPs = MeshCollection.MainBPs; + const TArray* CornerMeshes = MeshCollection.CornerMeshes; + const TArray* CornerBPs = MeshCollection.CornerBPs; + const TArray* AuxiliarMeshes = MeshCollection.AuxiliarMeshes; + const TArray* AuxiliarBPs = MeshCollection.AuxiliarBPs; + + /** + * Main part + */ + + // Check to know if there are meshes for the main part available + bool AreMainMeshesAvailable = (MainMeshes && (MainMeshes->Num() > 0)) || (MainBPs && (MainBPs->Num() > 0); + bool AreAuxMeshesAvailable = (MainMeshes && (MainMeshes->Num() > 0)) || (MainBPs && (MainBPs->Num() > 0); + for(int i = 0; (i < SideLength) && AreMainMeshesAvailable; i++) + { + UStaticMesh* SelectedMesh = nullptr; + UClass* SelectedBP = nullptr; + int* AuxiliarPosition = AuxiliarPositions.Find(i); + if(AreAuxMeshesAvailable && AuxiliarPosition) + { + // Add an auxiliar mesh + ChooseGeometryToSpawn(AuxiliarMeshes, AuxiliarBPs, SelectedMesh, SelectedBP); + } + else + { + // Add a main mesh + ChooseGeometryToSpawn(MainMeshes, MainBPs, SelectedMesh, SelectedBP); + } + + float MaxZ = AddGeometry(SelectedMesh, SelectedBP, MainVisibility); + + + + + } + + + + return 0.0f; +} + +void AProceduralBuilding::CalculateSidesLength() +{ + // Discard previous calculation + SidesLength.Reset(); + + if(UseFullBlocks) + { + // The full block configuration covers all the sides of the floor with one mesh + SidesLength.Emplace(1); + } + else + { + SidesLength.Emplace(LengthY); + SidesLength.Emplace(LengthX); + SidesLength.Emplace(LengthY); + SidesLength.Emplace(LengthX); + } + +} + +TSet AProceduralBuilding::CalculateDoorsIndexInSide(int StartIndex, int Length) +{ + TSet Result; + int MaxIndex = StartIndex + Length; + + for(int i : DoorsIndexPosition) + { + if( StartIndex <= i && i < MaxIndex ) + { + int RelativePostion = i - StartIndex; + Result.Emplace(RelativePostion); + + } + return Result +} + +void AProceduralBuilding::CalculateSideVisibilities(int SideIndex, bool& MainVisibility, bool& CornerVisbility) +{ + MainVisibility = UseFullBlocks || SideVisibility[SideIndex]; + CornerVisbility = UseFullBlocks || CornerVisibility[SideIndex] +} + +void AProceduralBuilding::ChooseGeometryToSpawn( + const TArray* InMeshes, + const TArray* InBPs, + UStaticMesh* OutMesh = nullptr, + UClass* OutBP = nullptr) +{ + int NumMeshes = InMeshes.Num(); + int NumBPs = InBPs.Num(); + int Range = NumMeshes + NumBPs; + + int Choosen = FMath::RandRange(0, Range - 1); + + if(Choosen < NumMeshes) + { + OutMesh = InMeshes[Choosen]; + } + if(NumMeshes <= Choosen && Choosen < NumBPs) + { + OutBP = InBPs[Choosen - NumMeshes]; + } +} + +float AProceduralBuilding::AddGeometry( + const UStaticMesh* SelectedMesh, + const UClass* SelectedBP, + bool Visible) +{ + if(SelectedMesh) + { + if(Visible) + { + // AddMeshToBuilding + } + // Update Current Transform + + } +} \ No newline at end of file diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h new file mode 100644 index 00000000000..d76e1c57e21 --- /dev/null +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h @@ -0,0 +1,233 @@ +// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de Barcelona (UAB). This work is licensed under the terms of the MIT license. For a copy, see . + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" + +#include "Components/HierarchicalInstancedStaticMeshComponent.h" + +#include "ProceduralBuilding.generated.h" + + +// TODO: support n-sides building + +// TODO: option (button) to clear all the values +// TODO: option (button) to clear all the meshes + +// TODO: + +struct FloorMeshCollection +{ + TArray* MainMeshes = nullptr; + TArray* MainBPs = nullptr; + TArray* CornerMeshes = nullptr; + TArray* CornerBPs = nullptr; + TArray* AuxiliarMeshes = nullptr; + TArray* AuxiliarBPs = nullptr; +}; + +UCLASS() +class CARLA_API AProceduralBuilding : public AActor +{ + GENERATED_BODY() + +public: + + // Sets default values for this actor's properties + AProceduralBuilding(); + +protected: + + // Called when the game starts or when spawned + virtual void BeginPlay() override; + + void CreateBuilding(); + + // Map containing the pair with the name of the mesh and the component that uses it + UPROPERTY(BlueprintReadOnly, VisibleAnywhere, AdvancedDisplay, Category="Procedural Building|Debug") + TMap HISMComps; + + + /** + * Base Parameters + */ + + // Set to contain the index of the doors that need to be placed on the base floor + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters", meta=(ToolTip="Index to indicate where the door is placed")) + TSet DoorsIndexPosition; + + // Indicates if the wall has to be filled with the wall-mesh or the body-mesh + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters", meta=(ToolTip="True to use wall-mesh instead of body-mesh")) + TArray UseWallMesh; + + // Number of floors for the building, base and roof not included + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters", meta=(ClampMin="0", UIMin="0", ToolTip="Number of floors for the building, base and roof not included")) + int NumFloors = 0; + + // Number of elements in X Axis + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters") + int LengthX = 0; + + // Number of elements in Y Axis + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters") + int LengthY = 0; + + // Enables the corners of the building + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters") + bool Corners = false; + + // Indicates if the meshes that are used on this buildings fill the whole floor + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters") + bool UseFullBlocks = false; + + /** + * Base Parameters | Visibility + */ + + // True to render the side of the building. Each index represents the side + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters|Visibility") + TArray SideVisibility; + + // True to render the corner of the building. Each index represents the corner + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters|Visibility") + TArray CornerVisibility; + + // True to render the roof + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Base Parameters|Visibility") + bool RoofVisibility = true; + + + /** + * Meshes + */ + + /** + * Meshes | Base + */ + + // Pool of meshes to be randomly selected for the base floor + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base") + TArray BaseMeshes; + + // Pool of BPs to be randomly selected for the base floor + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base") + TArray BaseBPs; + + // Pool of meshes to be randomly selected for doors + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base") + TArray DoorMeshes; + + // Pool of BPs to be randomly selected for doors + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base") + TArray DoorBPs; + + // Pool of meshes to be randomly selected for the corners of the base floor + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base") + TArray CornerBaseMeshes; + + // Pool of BPs to be randomly selected for the corners of the base floor + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base") + TArray CornerBaseBPs; + + /** + * Meshes | Body + */ + + // Pool of meshes to be randomly selected for the body + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body") + TArray BodyMeshes; + + // Pool of BPs to be randomly selected for the body + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body") + TArray BodyBPs; + + // Pool of meshes to be randomly selected for the walls of the body + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body") + TArray WallMeshes; + + // Pool of BPs to be randomly selected for the body walls of the body + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body") + TArray WallBPs; + + // Pool of meshes to be randomly selected for the corners of the body floor + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body") + TArray CornerBodyMeshes; + + // Pool of BPs to be randomly selected for the corners of the body floor + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body") + TArray CornerBodyBPs; + + /** + * Meshes | Top + */ + + // Pool of meshes to be randomly selected for the top + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top") + TArray TopMeshes; + + // Pool of BPs to be randomly selected for the top + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top") + TArray TopBPs; + + // Pool of meshes to be randomly selected for the corners of the top + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top") + TArray CornerTopMeshes; + + // Pool of BPs to be randomly selected for the corners of the top + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top") + TArray CornerTopBPs; + + // Pool of meshes to be randomly selected for the roof + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top") + TArray RoofMeshes; + + // Pool of BPs to be randomly selected for the roof + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top") + TArray RoofBPs; + +private: + + void Reset(); + + void Init(); + + void CreateFloor(const FloorMeshCollection& MeshCollection, bool IncludeDoors, bool IncludeWalls); + + // Creates the side of a floor of the building and returns the maximun height of the side + float CreateSide( + const FloorMeshCollection& MeshCollection, + const TSet& AuxiliarPositions, + int SideLength, + bool MainVisibility, + bool CornerVisbility); + + void CalculateSidesLength(); + + // Calculates the doors of DoorsIndexPosition inside the range between [StartIndex, StartIndex + Length) + // The set returns the position (index) of the doors relative to the side, ie: [0, Length) + TSet CalculateDoorsIndexInSide(int StartIndex, int Length); + + // Check if the main and corner part of the side is visible + void CalculateSideVisibilities(int SideIndex, bool& MainVisibility, bool& CornerVisbility); + + // Choose randomly between the Mesh and BP containers, only one option will be returned. + void ChooseGeometryToSpawn( + const TArray* InMeshes, + const TArray* InMainBPs, + UStaticMesh* OutMesh, + UClass* OutBP); + + float AddGeometry( + const UStaticMesh* SelectedMesh, + const UClass* SelectedBP, + bool Visible); + + // The lengths of each side of the building. The length of the array is the number of sides + // Helper to iterate throught all the sides of the building + TArray SidesLength; + + // Transform used to spawn the meshes of the building. It is updated (moved) with each new mesh + FTransform CurrentTransform; + +}; From efcb0068e3e915742daec286b0b579382c340c87 Mon Sep 17 00:00:00 2001 From: doterop Date: Fri, 18 Sep 2020 18:31:29 +0200 Subject: [PATCH 139/179] Continuation of the port --- .../Carla/MapGen/ProceduralBuilding.cpp | 245 +++++++++++++++--- .../Source/Carla/MapGen/ProceduralBuilding.h | 56 ++-- 2 files changed, 248 insertions(+), 53 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp index 823c49f2a98..326a024c7d6 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp @@ -25,6 +25,18 @@ void AProceduralBuilding::CreateBuilding() { Init(); + // Base Floor + CreateFloor( + { &BaseMeshes, &BaseBPs, &CornerBaseMeshes, &CornerBaseBPs, &DoorMeshes, &DoorBPs }, + true, + false); + + // Body floors + + // Top floor + + // Roof + } void AProceduralBuilding::Reset() @@ -56,7 +68,7 @@ void AProceduralBuilding::CreateFloor( bool IncludeWalls) { - + float MaxZ = 0.0f; // Stores the total length covered. This is needed to place the doors. int SideLengthAcumulator = 0; @@ -75,10 +87,25 @@ void AProceduralBuilding::CreateFloor( CalculateSideVisibilities(i, MainVisibility, CornerVisbility); - CreateSide(MeshCollection, DoorsPosition, SideLength, MainVisibility, CornerVisbility); + // Update Max Z + float SideMaxZ = CreateSide(MeshCollection, DoorsPosition, SideLength, MainVisibility, CornerVisbility); + MaxZ = (MaxZ < SideMaxZ) ? SideMaxZ : MaxZ; + + // Update the acumulator to calculate doors index in next sides + SideLengthAcumulator += SideLength; - SideLengthAcumulator += SidesLength; + // Update transform rotation for the next side + if(!UseFullBlocks) + { + const FQuat RotationToAdd = FRotator(0.0f, 90.0f, 0.0f).Quaternion(); + CurrentTransform.SetRotation(CurrentTransform.GetRotation() + RotationToAdd); + } } + + // Update transform for the next floor + FVector NewLocation = CurrentTransform.GetTranslation() + FVector(0.0f, 0.0f, MaxZ); + CurrentTransform.SetTranslation(NewLocation); + } @@ -90,45 +117,59 @@ float AProceduralBuilding::CreateSide( bool CornerVisbility) { const TArray* MainMeshes = MeshCollection.MainMeshes; - const TArray* MainBPs = MeshCollection.MainBPs; + const TArray>* MainBPs = MeshCollection.MainBPs; const TArray* CornerMeshes = MeshCollection.CornerMeshes; - const TArray* CornerBPs = MeshCollection.CornerBPs; + const TArray>* CornerBPs = MeshCollection.CornerBPs; const TArray* AuxiliarMeshes = MeshCollection.AuxiliarMeshes; - const TArray* AuxiliarBPs = MeshCollection.AuxiliarBPs; + const TArray>* AuxiliarBPs = MeshCollection.AuxiliarBPs; /** * Main part */ + UStaticMesh* SelectedMesh = nullptr; + TSubclassOf SelectedBP = nullptr; + FBox SelectedMeshBounds; + float MaxZ = 0.0f; + // Check to know if there are meshes for the main part available - bool AreMainMeshesAvailable = (MainMeshes && (MainMeshes->Num() > 0)) || (MainBPs && (MainBPs->Num() > 0); - bool AreAuxMeshesAvailable = (MainMeshes && (MainMeshes->Num() > 0)) || (MainBPs && (MainBPs->Num() > 0); + bool AreMainMeshesAvailable = (MainMeshes && (MainMeshes->Num() > 0)) || (MainBPs && (MainBPs->Num() > 0)); + bool AreAuxMeshesAvailable = (MainMeshes && (MainMeshes->Num() > 0)) || (MainBPs && (MainBPs->Num() > 0)); + for(int i = 0; (i < SideLength) && AreMainMeshesAvailable; i++) { - UStaticMesh* SelectedMesh = nullptr; - UClass* SelectedBP = nullptr; - int* AuxiliarPosition = AuxiliarPositions.Find(i); + const int* AuxiliarPosition = AuxiliarPositions.Find(i); if(AreAuxMeshesAvailable && AuxiliarPosition) { - // Add an auxiliar mesh - ChooseGeometryToSpawn(AuxiliarMeshes, AuxiliarBPs, SelectedMesh, SelectedBP); + // Choose an auxiliar mesh + ChooseGeometryToSpawn(*AuxiliarMeshes, *AuxiliarBPs, SelectedMesh, SelectedBP); } else { - // Add a main mesh - ChooseGeometryToSpawn(MainMeshes, MainBPs, SelectedMesh, SelectedBP); + // Choose a main mesh + ChooseGeometryToSpawn(*MainMeshes, *MainBPs, SelectedMesh, SelectedBP); } - - float MaxZ = AddGeometry(SelectedMesh, SelectedBP, MainVisibility); - - - - + float ChunkZ = AddChunck(SelectedMesh, SelectedBP, MainVisibility, SelectedMeshBounds); + MaxZ = (MaxZ < ChunkZ) ? ChunkZ : MaxZ; } + /** + * Corner part + */ + bool AreCornerMeshesAvailable = (CornerMeshes && (CornerMeshes->Num() > 0)) || (CornerBPs && (CornerBPs->Num() > 0)); + if(AreCornerMeshesAvailable) + { + // Choose a corner mesh + ChooseGeometryToSpawn(*CornerMeshes, *CornerBPs, SelectedMesh, SelectedBP); + float ChunkZ = AddChunck(SelectedMesh, SelectedBP, MainVisibility, SelectedMeshBounds); + MaxZ = (MaxZ < ChunkZ) ? ChunkZ : MaxZ; + + // Move the Transform location to the next side of the building + // because corners can be in two sides + UpdateTransformPositionToNextSide(SelectedMeshBounds); + } - - return 0.0f; + return MaxZ; } void AProceduralBuilding::CalculateSidesLength() @@ -162,22 +203,22 @@ TSet AProceduralBuilding::CalculateDoorsIndexInSide(int StartIndex, int Len { int RelativePostion = i - StartIndex; Result.Emplace(RelativePostion); - + } } - return Result + return Result; } void AProceduralBuilding::CalculateSideVisibilities(int SideIndex, bool& MainVisibility, bool& CornerVisbility) { MainVisibility = UseFullBlocks || SideVisibility[SideIndex]; - CornerVisbility = UseFullBlocks || CornerVisibility[SideIndex] + CornerVisbility = UseFullBlocks || CornerVisibility[SideIndex]; } void AProceduralBuilding::ChooseGeometryToSpawn( - const TArray* InMeshes, - const TArray* InBPs, + const TArray& InMeshes, + const TArray>& InBPs, UStaticMesh* OutMesh = nullptr, - UClass* OutBP = nullptr) + TSubclassOf OutBP = nullptr) { int NumMeshes = InMeshes.Num(); int NumBPs = InBPs.Num(); @@ -195,18 +236,152 @@ void AProceduralBuilding::ChooseGeometryToSpawn( } } -float AProceduralBuilding::AddGeometry( +float AProceduralBuilding::AddChunck( const UStaticMesh* SelectedMesh, - const UClass* SelectedBP, - bool Visible) + const TSubclassOf SelectedBP, + bool Visible, + FBox& OutSelectedMeshBounds) { + float Result = 0.0f; + // Static Mesh if(SelectedMesh) { if(Visible) { - // AddMeshToBuilding + AddMeshToBuilding(SelectedMesh); + } + FVector MeshBound = GetMeshBound(SelectedMesh); + Result = MeshBound.Z; + + UpdateTransformPositionToNextChunk(MeshBound); + OutSelectedMeshBounds = SelectedMesh->GetBoundingBox(); + } + // BP + else if(SelectedBP) + { + // Create a new ChildActorComponent + UChildActorComponent* ChildActorComp = NewObject(this, + FName(*FString::Printf(TEXT("ChildActorComp_%d"), ChildActorComps.Num()))); + ChildActorComp->SetupAttachment(GetRootComponent()); + ChildActorComp->RegisterComponent(); + + // Set the class that it will use + ChildActorComp->SetChildActorClass(SelectedBP); + + // Look for all the SMComps + TArray SMComps; + UStaticMeshComponent* PivotSMComp = nullptr; + + GetComponents(SMComps); + + int NumSMs = SMComps.Num(); + + if(Visible && NumSMs > 0) + { + ChildActorComps.Emplace(ChildActorComp); + + // The first mesh on the BP is the pivot to continue creating the floor + PivotSMComp = SMComps[0]; + const UStaticMesh* SM = PivotSMComp->GetStaticMesh(); + + AddMeshToBuilding(SM); + FVector MeshBound = GetMeshBound(SM); + Result = MeshBound.Z; + + UpdateTransformPositionToNextChunk(MeshBound); + + // Make it invisible on the child actor to avoid duplication with the HISMComp + PivotSMComp->SetVisibility(false, false); + OutSelectedMeshBounds = SM->GetBoundingBox(); + } + else + { + ChildActorComp->DestroyComponent(); } - // Update Current Transform + /* + // TODO: add the other meshes to a HISMComp + for(int i = 1; i < NumSMs; i++) + { + UStaticMeshComponent* SMComp = Cast(SMComps[i]); + const UStaticMesh* SM = SMComp->GetStaticMesh(); + } + */ } -} \ No newline at end of file + + return Result; +} + +void AProceduralBuilding::AddMeshToBuilding(const UStaticMesh* SM) +{ + UHierarchicalInstancedStaticMeshComponent* HISMComp = GetHISMComp(SM); + HISMComp->AddInstance(CurrentTransform); +} + +UHierarchicalInstancedStaticMeshComponent* AProceduralBuilding::GetHISMComp( + const UStaticMesh* SM) +{ + + FString SMName = SM->GetName(); + + UHierarchicalInstancedStaticMeshComponent** HISMCompPtr = HISMComps.Find(SMName); + + if(HISMCompPtr) return *HISMCompPtr; + + UHierarchicalInstancedStaticMeshComponent* HISMComp = *HISMCompPtr; + + // If it doesn't exist, create the component + HISMComp = NewObject(this, + FName(*FString::Printf(TEXT("HISMComp_%d"), HISMComps.Num()))); + HISMComp->SetupAttachment(GetRootComponent()); + HISMComp->RegisterComponent(); + + // Set the mesh that will be used + HISMComp->SetStaticMesh(const_cast(SM)); + + // Add to the map + HISMComps.Emplace(SMName, HISMComp); + + return HISMComp; +} + +FVector AProceduralBuilding::GetMeshBound(const UStaticMesh* SM) +{ + FBox Box = SM->GetBoundingBox(); + return (Box.Max - Box.Min); +} + +void AProceduralBuilding::UpdateTransformPositionToNextChunk(const FVector& Box) +{ + // Update Current Transform to the right side of the added chunk + // Nothing to change if the chunk is the size of a floor + if(UseFullBlocks) + { + FQuat Rotation = CurrentTransform.GetRotation(); + FVector ForwardVector = -Rotation.GetForwardVector(); + + FVector NewLocation = CurrentTransform.GetTranslation() + ForwardVector * Box.X; + CurrentTransform.SetTranslation(NewLocation); + } +} + +void AProceduralBuilding::UpdateTransformPositionToNextSide(const FBox& Box) +{ + // Update Current Transform to the right side of the added chunk + // Nothing to change if the chunk is the size of a floor + if(UseFullBlocks) + { + FQuat Rotation = CurrentTransform.GetRotation(); + FVector RightVector = -Rotation.GetRightVector(); + FVector Extent = (Box.Max - Box.Min); + + FVector NewLocation = CurrentTransform.GetTranslation() + RightVector * Extent.Y; + CurrentTransform.SetTranslation(NewLocation); + } +} + + + + + + diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h index d76e1c57e21..484f1da518f 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h @@ -20,11 +20,11 @@ struct FloorMeshCollection { TArray* MainMeshes = nullptr; - TArray* MainBPs = nullptr; + TArray>* MainBPs = nullptr; TArray* CornerMeshes = nullptr; - TArray* CornerBPs = nullptr; + TArray>* CornerBPs = nullptr; TArray* AuxiliarMeshes = nullptr; - TArray* AuxiliarBPs = nullptr; + TArray>* AuxiliarBPs = nullptr; }; UCLASS() @@ -42,6 +42,7 @@ class CARLA_API AProceduralBuilding : public AActor // Called when the game starts or when spawned virtual void BeginPlay() override; + UFUNCTION(BlueprintCallable, CallInEditor, Category="Procedural Building") void CreateBuilding(); // Map containing the pair with the name of the mesh and the component that uses it @@ -112,7 +113,7 @@ class CARLA_API AProceduralBuilding : public AActor // Pool of BPs to be randomly selected for the base floor UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base") - TArray BaseBPs; + TArray> BaseBPs; // Pool of meshes to be randomly selected for doors UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base") @@ -120,7 +121,7 @@ class CARLA_API AProceduralBuilding : public AActor // Pool of BPs to be randomly selected for doors UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base") - TArray DoorBPs; + TArray> DoorBPs; // Pool of meshes to be randomly selected for the corners of the base floor UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base") @@ -128,7 +129,7 @@ class CARLA_API AProceduralBuilding : public AActor // Pool of BPs to be randomly selected for the corners of the base floor UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Base") - TArray CornerBaseBPs; + TArray> CornerBaseBPs; /** * Meshes | Body @@ -140,7 +141,7 @@ class CARLA_API AProceduralBuilding : public AActor // Pool of BPs to be randomly selected for the body UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body") - TArray BodyBPs; + TArray> BodyBPs; // Pool of meshes to be randomly selected for the walls of the body UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body") @@ -148,7 +149,7 @@ class CARLA_API AProceduralBuilding : public AActor // Pool of BPs to be randomly selected for the body walls of the body UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body") - TArray WallBPs; + TArray> WallBPs; // Pool of meshes to be randomly selected for the corners of the body floor UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body") @@ -156,7 +157,7 @@ class CARLA_API AProceduralBuilding : public AActor // Pool of BPs to be randomly selected for the corners of the body floor UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Body") - TArray CornerBodyBPs; + TArray> CornerBodyBPs; /** * Meshes | Top @@ -168,7 +169,7 @@ class CARLA_API AProceduralBuilding : public AActor // Pool of BPs to be randomly selected for the top UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top") - TArray TopBPs; + TArray> TopBPs; // Pool of meshes to be randomly selected for the corners of the top UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top") @@ -176,7 +177,7 @@ class CARLA_API AProceduralBuilding : public AActor // Pool of BPs to be randomly selected for the corners of the top UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top") - TArray CornerTopBPs; + TArray> CornerTopBPs; // Pool of meshes to be randomly selected for the roof UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top") @@ -184,7 +185,7 @@ class CARLA_API AProceduralBuilding : public AActor // Pool of BPs to be randomly selected for the roof UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Meshes|Top") - TArray RoofBPs; + TArray> RoofBPs; private: @@ -213,15 +214,34 @@ class CARLA_API AProceduralBuilding : public AActor // Choose randomly between the Mesh and BP containers, only one option will be returned. void ChooseGeometryToSpawn( - const TArray* InMeshes, - const TArray* InMainBPs, + const TArray& InMeshes, + const TArray>& InMainBPs, UStaticMesh* OutMesh, - UClass* OutBP); + TSubclassOf OutBP); - float AddGeometry( + // Add one part on the side + float AddChunck( const UStaticMesh* SelectedMesh, - const UClass* SelectedBP, - bool Visible); + const TSubclassOf SelectedBP, + bool Visible, + FBox& OutSelectedMeshBounds); + + // Add the Static Mesh on the transform location with the transform orientation + void AddMeshToBuilding(const UStaticMesh* SM); + + // Looks for the HISMComp on the HISMComps Map that uses the SelectedMesh and returns it. + // If doesn't exist its created + UHierarchicalInstancedStaticMeshComponent* GetHISMComp(const UStaticMesh* SM); + + // Calculate the Bounds for the Static Mesh + FVector GetMeshBound(const UStaticMesh* SM); + + void UpdateTransformPositionToNextChunk(const FVector& Box); + + void UpdateTransformPositionToNextSide(const FBox& Box); + + // Contains all the ChildActorComps spawned for this Actor + TArray ChildActorComps; // The lengths of each side of the building. The length of the array is the number of sides // Helper to iterate throught all the sides of the building From eb11522d18e3fbc4f53e0f52c3e0ba8f61e05e1f Mon Sep 17 00:00:00 2001 From: doterop Date: Mon, 21 Sep 2020 04:07:57 +0200 Subject: [PATCH 140/179] Fixed trasnform update --- .../Carla/MapGen/ProceduralBuilding.cpp | 43 ++++++++++++------- .../Source/Carla/MapGen/ProceduralBuilding.h | 17 ++++---- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp index 326a024c7d6..4c5c31e7d67 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp @@ -12,12 +12,9 @@ AProceduralBuilding::AProceduralBuilding() SideVisibility.Init(true, 4); CornerVisibility.Init(true, 4); -} -// Called when the game starts or when spawned -void AProceduralBuilding::BeginPlay() -{ - Super::BeginPlay(); + USceneComponent* SceneComponent = CreateDefaultSubobject(TEXT("RootComponent")); + RootComponent = SceneComponent; } @@ -41,6 +38,8 @@ void AProceduralBuilding::CreateBuilding() void AProceduralBuilding::Reset() { + CurrentTransform = FTransform::Identity; + // Discard previous calculation SidesLength.Reset(); @@ -59,6 +58,8 @@ void AProceduralBuilding::Reset() void AProceduralBuilding::Init() { + Reset(); + CalculateSidesLength(); } @@ -67,7 +68,6 @@ void AProceduralBuilding::CreateFloor( bool IncludeDoors, bool IncludeWalls) { - float MaxZ = 0.0f; // Stores the total length covered. This is needed to place the doors. @@ -98,7 +98,7 @@ void AProceduralBuilding::CreateFloor( if(!UseFullBlocks) { const FQuat RotationToAdd = FRotator(0.0f, 90.0f, 0.0f).Quaternion(); - CurrentTransform.SetRotation(CurrentTransform.GetRotation() + RotationToAdd); + CurrentTransform.ConcatenateRotation(RotationToAdd); } } @@ -116,6 +116,9 @@ float AProceduralBuilding::CreateSide( bool MainVisibility, bool CornerVisbility) { + + UE_LOG(LogCarla, Warning, TEXT("AProceduralBuilding::CreateSide of length %d"), SideLength); + const TArray* MainMeshes = MeshCollection.MainMeshes; const TArray>* MainBPs = MeshCollection.MainBPs; const TArray* CornerMeshes = MeshCollection.CornerMeshes; @@ -142,13 +145,14 @@ float AProceduralBuilding::CreateSide( if(AreAuxMeshesAvailable && AuxiliarPosition) { // Choose an auxiliar mesh - ChooseGeometryToSpawn(*AuxiliarMeshes, *AuxiliarBPs, SelectedMesh, SelectedBP); + ChooseGeometryToSpawn(*AuxiliarMeshes, *AuxiliarBPs, &SelectedMesh, &SelectedBP); } else { // Choose a main mesh - ChooseGeometryToSpawn(*MainMeshes, *MainBPs, SelectedMesh, SelectedBP); + ChooseGeometryToSpawn(*MainMeshes, *MainBPs, &SelectedMesh, &SelectedBP); } + float ChunkZ = AddChunck(SelectedMesh, SelectedBP, MainVisibility, SelectedMeshBounds); MaxZ = (MaxZ < ChunkZ) ? ChunkZ : MaxZ; } @@ -160,7 +164,7 @@ float AProceduralBuilding::CreateSide( if(AreCornerMeshesAvailable) { // Choose a corner mesh - ChooseGeometryToSpawn(*CornerMeshes, *CornerBPs, SelectedMesh, SelectedBP); + ChooseGeometryToSpawn(*CornerMeshes, *CornerBPs, &SelectedMesh, &SelectedBP); float ChunkZ = AddChunck(SelectedMesh, SelectedBP, MainVisibility, SelectedMeshBounds); MaxZ = (MaxZ < ChunkZ) ? ChunkZ : MaxZ; @@ -217,8 +221,8 @@ void AProceduralBuilding::CalculateSideVisibilities(int SideIndex, bool& MainVis void AProceduralBuilding::ChooseGeometryToSpawn( const TArray& InMeshes, const TArray>& InBPs, - UStaticMesh* OutMesh = nullptr, - TSubclassOf OutBP = nullptr) + UStaticMesh** OutMesh = nullptr, + TSubclassOf* OutBP = nullptr) { int NumMeshes = InMeshes.Num(); int NumBPs = InBPs.Num(); @@ -228,11 +232,11 @@ void AProceduralBuilding::ChooseGeometryToSpawn( if(Choosen < NumMeshes) { - OutMesh = InMeshes[Choosen]; + *OutMesh = InMeshes[Choosen]; } if(NumMeshes <= Choosen && Choosen < NumBPs) { - OutBP = InBPs[Choosen - NumMeshes]; + *OutBP = InBPs[Choosen - NumMeshes]; } } @@ -243,6 +247,9 @@ float AProceduralBuilding::AddChunck( FBox& OutSelectedMeshBounds) { float Result = 0.0f; + + UE_LOG(LogCarla, Warning, TEXT("AddChunck")); + // Static Mesh if(SelectedMesh) { @@ -259,6 +266,9 @@ float AProceduralBuilding::AddChunck( // BP else if(SelectedBP) { + + UE_LOG(LogCarla, Warning, TEXT("AddChunck BP")); + // Create a new ChildActorComponent UChildActorComponent* ChildActorComp = NewObject(this, FName(*FString::Printf(TEXT("ChildActorComp_%d"), ChildActorComps.Num()))); @@ -314,6 +324,7 @@ float AProceduralBuilding::AddChunck( void AProceduralBuilding::AddMeshToBuilding(const UStaticMesh* SM) { + UHierarchicalInstancedStaticMeshComponent* HISMComp = GetHISMComp(SM); HISMComp->AddInstance(CurrentTransform); } @@ -355,7 +366,7 @@ void AProceduralBuilding::UpdateTransformPositionToNextChunk(const FVector& Box) { // Update Current Transform to the right side of the added chunk // Nothing to change if the chunk is the size of a floor - if(UseFullBlocks) + if(!UseFullBlocks) { FQuat Rotation = CurrentTransform.GetRotation(); FVector ForwardVector = -Rotation.GetForwardVector(); @@ -369,7 +380,7 @@ void AProceduralBuilding::UpdateTransformPositionToNextSide(const FBox& Box) { // Update Current Transform to the right side of the added chunk // Nothing to change if the chunk is the size of a floor - if(UseFullBlocks) + if(!UseFullBlocks) { FQuat Rotation = CurrentTransform.GetRotation(); FVector RightVector = -Rotation.GetRightVector(); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h index 484f1da518f..e6f603ea81f 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h @@ -39,14 +39,15 @@ class CARLA_API AProceduralBuilding : public AActor protected: - // Called when the game starts or when spawned - virtual void BeginPlay() override; - UFUNCTION(BlueprintCallable, CallInEditor, Category="Procedural Building") void CreateBuilding(); + UFUNCTION(BlueprintCallable, CallInEditor, Category="Procedural Building") + void Reset(); + // Map containing the pair with the name of the mesh and the component that uses it - UPROPERTY(BlueprintReadOnly, VisibleAnywhere, AdvancedDisplay, Category="Procedural Building|Debug") + //UPROPERTY(BlueprintReadOnly, VisibleAnywhere, AdvancedDisplay, Category="Procedural Building|Debug") + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Debug") TMap HISMComps; @@ -189,8 +190,6 @@ class CARLA_API AProceduralBuilding : public AActor private: - void Reset(); - void Init(); void CreateFloor(const FloorMeshCollection& MeshCollection, bool IncludeDoors, bool IncludeWalls); @@ -216,8 +215,8 @@ class CARLA_API AProceduralBuilding : public AActor void ChooseGeometryToSpawn( const TArray& InMeshes, const TArray>& InMainBPs, - UStaticMesh* OutMesh, - TSubclassOf OutBP); + UStaticMesh** OutMesh, + TSubclassOf* OutBP); // Add one part on the side float AddChunck( @@ -248,6 +247,6 @@ class CARLA_API AProceduralBuilding : public AActor TArray SidesLength; // Transform used to spawn the meshes of the building. It is updated (moved) with each new mesh - FTransform CurrentTransform; + FTransform CurrentTransform = FTransform::Identity; }; From 6841350a2811b0e89cb6b78a844b16778a7adb9b Mon Sep 17 00:00:00 2001 From: doterop Date: Tue, 22 Sep 2020 00:32:21 +0200 Subject: [PATCH 141/179] Fixing BP child actor creation --- .../Carla/MapGen/ProceduralBuilding.cpp | 74 +++++++++++++++++-- .../Source/Carla/MapGen/ProceduralBuilding.h | 11 ++- 2 files changed, 75 insertions(+), 10 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp index 4c5c31e7d67..150cbfb90b1 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp @@ -16,6 +16,28 @@ AProceduralBuilding::AProceduralBuilding() USceneComponent* SceneComponent = CreateDefaultSubobject(TEXT("RootComponent")); RootComponent = SceneComponent; + const TSet Comps = GetComponents(); + UE_LOG(LogCarla, Warning, TEXT("CTR - ChildActorComps %d, HISMComps %d, Comps %d"), + ChildActorComps.Num(), HISMComps.Num(), Comps.Num()); + + TArray ChildActors; + GetAllChildActors(ChildActors); + UE_LOG(LogCarla, Warning, TEXT("CTR - Attached Childs %d"), ChildActors.Num()); + +} + +void AProceduralBuilding::PostEditMove(bool bFinished) +{ + Super::PostEditMove(bFinished); + + UE_LOG(LogCarla, Warning, TEXT("AProceduralBuilding::PostEditMove")); + + const FTransform& Transform = GetTransform(); + for(UChildActorComponent* ChildActorComp : ChildActorComps) + { + ChildActorComp->SetRelativeTransform(Transform); + } + } void AProceduralBuilding::CreateBuilding() @@ -34,6 +56,10 @@ void AProceduralBuilding::CreateBuilding() // Roof + TArray ChildActors; + GetAllChildActors(ChildActors); + UE_LOG(LogCarla, Warning, TEXT("Attached Childs %d"), ChildActors.Num()); + } void AProceduralBuilding::Reset() @@ -43,7 +69,10 @@ void AProceduralBuilding::Reset() // Discard previous calculation SidesLength.Reset(); + const TSet Comps = GetComponents(); + // Remove all the instances of each HISMComp + UE_LOG(LogCarla, Warning, TEXT("HISMComps %d, Comps %d"), HISMComps.Num(), Comps.Num()); for(auto& It : HISMComps) { const FString& MeshName = It.Key; @@ -54,6 +83,24 @@ void AProceduralBuilding::Reset() // Empties out the map but preserves all allocations and capacities HISMComps.Reset(); + // Remove all child actors + TArray ChildActors; + GetAllChildActors(ChildActors); + UE_LOG(LogCarla, Warning, TEXT("Reset NumChilds = %d, ChildActorComps = %d"), + ChildActors.Num(), ChildActorComps.Num()); + /* + for(AActor* ChildActor : ChildActors) + { + ChildActor->Destroy(); + } + */ + for(UChildActorComponent* ChildActorComp : ChildActorComps) + { + ChildActorComp->DestroyChildActor(); + ChildActorComp->DestroyComponent(); + } + ChildActorComps.Reset(); + } void AProceduralBuilding::Init() @@ -108,7 +155,6 @@ void AProceduralBuilding::CreateFloor( } - float AProceduralBuilding::CreateSide( const FloorMeshCollection& MeshCollection, const TSet& AuxiliarPositions, @@ -248,8 +294,6 @@ float AProceduralBuilding::AddChunck( { float Result = 0.0f; - UE_LOG(LogCarla, Warning, TEXT("AddChunck")); - // Static Mesh if(SelectedMesh) { @@ -267,22 +311,37 @@ float AProceduralBuilding::AddChunck( else if(SelectedBP) { - UE_LOG(LogCarla, Warning, TEXT("AddChunck BP")); + UE_LOG(LogCarla, Warning, TEXT("AddChunck BP -> %s"), *SelectedBP->GetClass()->GetName()); // Create a new ChildActorComponent UChildActorComponent* ChildActorComp = NewObject(this, FName(*FString::Printf(TEXT("ChildActorComp_%d"), ChildActorComps.Num()))); ChildActorComp->SetupAttachment(GetRootComponent()); - ChildActorComp->RegisterComponent(); // Set the class that it will use ChildActorComp->SetChildActorClass(SelectedBP); + ChildActorComp->SetRelativeTransform(CurrentTransform); + + // Spawns the actor referenced by UChildActorComponent + ChildActorComp->RegisterComponent(); + + // Create and attach child actor to parent + //ChildActorComp->CreateChildActor(); + AActor* ChildActor = ChildActorComp->GetChildActor(); + //AddComponent() + //ChildActor->AttachToActor(this, FAttachmentTransformRules::KeepRelativeTransform); + //ChildActor->AttachToComponent(GetRootComponent(), FAttachmentTransformRules::KeepWorldTransform); + //ChildActorComp->SetRelativeTransform(CurrentTransform); + + //UE_LOG(LogCarla, Warning, TEXT("ChildActorComp->SetRelativeTransform \n%s"), *CurrentTransform.ToHumanReadableString()); + + UE_LOG(LogCarla, Warning, TEXT("Child Attached To %s"), *ChildActor->GetParentActor()->GetName()); // Look for all the SMComps TArray SMComps; UStaticMeshComponent* PivotSMComp = nullptr; - GetComponents(SMComps); + ChildActor->GetComponents(SMComps); int NumSMs = SMComps.Num(); @@ -306,7 +365,8 @@ float AProceduralBuilding::AddChunck( } else { - ChildActorComp->DestroyComponent(); + //ChildActorComp->DestroyComponent(); + ChildActor->Destroy(); } /* diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h index e6f603ea81f..6aa4f7fcb2a 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h @@ -37,6 +37,11 @@ class CARLA_API AProceduralBuilding : public AActor // Sets default values for this actor's properties AProceduralBuilding(); +#if WITH_EDITOR + /** Called after an actor has been moved in the editor */ + void PostEditMove(bool bFinished) override; +#endif // WITH_EDITOR + protected: UFUNCTION(BlueprintCallable, CallInEditor, Category="Procedural Building") @@ -50,6 +55,9 @@ class CARLA_API AProceduralBuilding : public AActor UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Debug") TMap HISMComps; + // Contains all the ChildActorComps spawned for this Actor + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Debug") + TArray ChildActorComps; /** * Base Parameters @@ -239,9 +247,6 @@ class CARLA_API AProceduralBuilding : public AActor void UpdateTransformPositionToNextSide(const FBox& Box); - // Contains all the ChildActorComps spawned for this Actor - TArray ChildActorComps; - // The lengths of each side of the building. The length of the array is the number of sides // Helper to iterate throught all the sides of the building TArray SidesLength; From 24975b908ccc65148206665ce0af84437685f51c Mon Sep 17 00:00:00 2001 From: doterop Date: Tue, 22 Sep 2020 12:55:07 +0200 Subject: [PATCH 142/179] Fixed corner visibility and editor updates --- .../Carla/MapGen/ProceduralBuilding.cpp | 118 ++++++++++-------- .../Source/Carla/MapGen/ProceduralBuilding.h | 27 +++- 2 files changed, 90 insertions(+), 55 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp index 150cbfb90b1..44821a7912d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp @@ -13,8 +13,8 @@ AProceduralBuilding::AProceduralBuilding() SideVisibility.Init(true, 4); CornerVisibility.Init(true, 4); - USceneComponent* SceneComponent = CreateDefaultSubobject(TEXT("RootComponent")); - RootComponent = SceneComponent; + UStaticMeshComponent* StaticMeshComponent = CreateDefaultSubobject(TEXT("RootComponent")); + RootComponent = StaticMeshComponent; const TSet Comps = GetComponents(); UE_LOG(LogCarla, Warning, TEXT("CTR - ChildActorComps %d, HISMComps %d, Comps %d"), @@ -24,22 +24,71 @@ AProceduralBuilding::AProceduralBuilding() GetAllChildActors(ChildActors); UE_LOG(LogCarla, Warning, TEXT("CTR - Attached Childs %d"), ChildActors.Num()); + +} + +#if WITH_EDITOR + +void AProceduralBuilding::EditorApplyTranslation( + const FVector& DeltaTranslation, + bool bAltDown, + bool bShiftDown, + bool bCtrlDown) +{ + Super::EditorApplyTranslation(DeltaTranslation, bAltDown, bShiftDown, bCtrlDown); + + const FTransform& ParentTransform = GetTransform(); + FTransform ChildTransform = ChildActorComps[0]->GetChildActor()->GetTransform(); + + for(UChildActorComponent* ChildActorComp : ChildActorComps) + { + AActor* ChildActor = ChildActorComp->GetChildActor(); + FVector ChildActorLocation = ChildActor->GetActorLocation(); + ChildActor->SetActorLocation(ChildActorLocation + DeltaTranslation); + } } -void AProceduralBuilding::PostEditMove(bool bFinished) +void AProceduralBuilding::EditorApplyRotation(const FRotator& DeltaRotation, bool bAltDown, bool bShiftDown, bool bCtrlDown) { - Super::PostEditMove(bFinished); + Super::EditorApplyRotation(DeltaRotation, bAltDown, bShiftDown, bCtrlDown); - UE_LOG(LogCarla, Warning, TEXT("AProceduralBuilding::PostEditMove")); + const FTransform& ParentTransform = GetTransform(); + FTransform ChildTransform = ChildActorComps[0]->GetChildActor()->GetTransform(); - const FTransform& Transform = GetTransform(); + FVector ParentLocation = GetActorLocation(); for(UChildActorComponent* ChildActorComp : ChildActorComps) { - ChildActorComp->SetRelativeTransform(Transform); + AActor* ChildActor = ChildActorComp->GetChildActor(); + FVector ChildActorLocation = ChildActor->GetActorLocation(); + FVector DeltaLocation = ChildActorLocation - ParentLocation; + FRotator ChildActorRotation = ChildActor->GetActorRotation(); + + // Add DeltaRotation + ChildActorRotation += DeltaRotation; + ChildActor->SetActorRotation(ChildActorRotation); + + // Rotate the location + DeltaLocation = DeltaRotation.RotateVector(DeltaLocation); + ChildActor->SetActorLocation(ParentLocation + DeltaLocation); } +} + +void AProceduralBuilding::EditorApplyScale(const FVector& DeltaScale, const FVector* PivotLocation, bool bAltDown, bool bShiftDown, bool bCtrlDown) +{ + Super::EditorApplyScale(DeltaScale, PivotLocation, bAltDown, bShiftDown, bCtrlDown); + + for(UChildActorComponent* ChildActorComp : ChildActorComps) + { + AActor* ChildActor = ChildActorComp->GetChildActor(); + FVector ChildActorScale = ChildActor->GetActorScale3D(); + // TODO: apply scale with rotation in mind + // ChildActor->SetActorScale3D(); + } } +#endif // WITH_EDITOR + void AProceduralBuilding::CreateBuilding() { Init(); @@ -56,10 +105,6 @@ void AProceduralBuilding::CreateBuilding() // Roof - TArray ChildActors; - GetAllChildActors(ChildActors); - UE_LOG(LogCarla, Warning, TEXT("Attached Childs %d"), ChildActors.Num()); - } void AProceduralBuilding::Reset() @@ -72,7 +117,6 @@ void AProceduralBuilding::Reset() const TSet Comps = GetComponents(); // Remove all the instances of each HISMComp - UE_LOG(LogCarla, Warning, TEXT("HISMComps %d, Comps %d"), HISMComps.Num(), Comps.Num()); for(auto& It : HISMComps) { const FString& MeshName = It.Key; @@ -84,16 +128,6 @@ void AProceduralBuilding::Reset() HISMComps.Reset(); // Remove all child actors - TArray ChildActors; - GetAllChildActors(ChildActors); - UE_LOG(LogCarla, Warning, TEXT("Reset NumChilds = %d, ChildActorComps = %d"), - ChildActors.Num(), ChildActorComps.Num()); - /* - for(AActor* ChildActor : ChildActors) - { - ChildActor->Destroy(); - } - */ for(UChildActorComponent* ChildActorComp : ChildActorComps) { ChildActorComp->DestroyChildActor(); @@ -162,9 +196,6 @@ float AProceduralBuilding::CreateSide( bool MainVisibility, bool CornerVisbility) { - - UE_LOG(LogCarla, Warning, TEXT("AProceduralBuilding::CreateSide of length %d"), SideLength); - const TArray* MainMeshes = MeshCollection.MainMeshes; const TArray>* MainBPs = MeshCollection.MainBPs; const TArray* CornerMeshes = MeshCollection.CornerMeshes; @@ -207,7 +238,7 @@ float AProceduralBuilding::CreateSide( * Corner part */ bool AreCornerMeshesAvailable = (CornerMeshes && (CornerMeshes->Num() > 0)) || (CornerBPs && (CornerBPs->Num() > 0)); - if(AreCornerMeshesAvailable) + if(Corners && AreCornerMeshesAvailable) { // Choose a corner mesh ChooseGeometryToSpawn(*CornerMeshes, *CornerBPs, &SelectedMesh, &SelectedBP); @@ -234,10 +265,10 @@ void AProceduralBuilding::CalculateSidesLength() } else { - SidesLength.Emplace(LengthY); SidesLength.Emplace(LengthX); SidesLength.Emplace(LengthY); SidesLength.Emplace(LengthX); + SidesLength.Emplace(LengthY); } } @@ -310,13 +341,10 @@ float AProceduralBuilding::AddChunck( // BP else if(SelectedBP) { - - UE_LOG(LogCarla, Warning, TEXT("AddChunck BP -> %s"), *SelectedBP->GetClass()->GetName()); - // Create a new ChildActorComponent UChildActorComponent* ChildActorComp = NewObject(this, - FName(*FString::Printf(TEXT("ChildActorComp_%d"), ChildActorComps.Num()))); - ChildActorComp->SetupAttachment(GetRootComponent()); + FName(*FString::Printf(TEXT("ChildActorComp_%d"), ChildActorComps.Num() ))); + ChildActorComp->SetupAttachment(RootComponent); // Set the class that it will use ChildActorComp->SetChildActorClass(SelectedBP); @@ -326,16 +354,15 @@ float AProceduralBuilding::AddChunck( ChildActorComp->RegisterComponent(); // Create and attach child actor to parent - //ChildActorComp->CreateChildActor(); AActor* ChildActor = ChildActorComp->GetChildActor(); - //AddComponent() - //ChildActor->AttachToActor(this, FAttachmentTransformRules::KeepRelativeTransform); - //ChildActor->AttachToComponent(GetRootComponent(), FAttachmentTransformRules::KeepWorldTransform); - //ChildActorComp->SetRelativeTransform(CurrentTransform); - - //UE_LOG(LogCarla, Warning, TEXT("ChildActorComp->SetRelativeTransform \n%s"), *CurrentTransform.ToHumanReadableString()); + FAttachmentTransformRules AttachmentTransformRules = + FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true); + ChildActor->AttachToComponent(RootComponent, AttachmentTransformRules); - UE_LOG(LogCarla, Warning, TEXT("Child Attached To %s"), *ChildActor->GetParentActor()->GetName()); +#if WITH_EDITOR + // Add the child actor to a subfolder of the actor's name + ChildActor->SetFolderPath(FName( *FString::Printf(TEXT("/Buildings/%s"), *GetName()))); + #endif // Look for all the SMComps TArray SMComps; @@ -368,15 +395,6 @@ float AProceduralBuilding::AddChunck( //ChildActorComp->DestroyComponent(); ChildActor->Destroy(); } - - /* - // TODO: add the other meshes to a HISMComp - for(int i = 1; i < NumSMs; i++) - { - UStaticMeshComponent* SMComp = Cast(SMComps[i]); - const UStaticMesh* SM = SMComp->GetStaticMesh(); - } - */ } return Result; @@ -404,7 +422,7 @@ UHierarchicalInstancedStaticMeshComponent* AProceduralBuilding::GetHISMComp( // If it doesn't exist, create the component HISMComp = NewObject(this, FName(*FString::Printf(TEXT("HISMComp_%d"), HISMComps.Num()))); - HISMComp->SetupAttachment(GetRootComponent()); + HISMComp->SetupAttachment(RootComponent); HISMComp->RegisterComponent(); // Set the mesh that will be used diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h index 6aa4f7fcb2a..9151a181e16 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h @@ -38,8 +38,25 @@ class CARLA_API AProceduralBuilding : public AActor AProceduralBuilding(); #if WITH_EDITOR - /** Called after an actor has been moved in the editor */ - void PostEditMove(bool bFinished) override; + /** + * Called by ApplyDeltaToActor to perform an actor class-specific operation based on widget manipulation. + * The default implementation is simply to translate the actor's location. + */ + void EditorApplyTranslation(const FVector& DeltaTranslation, bool bAltDown, bool bShiftDown, bool bCtrlDown) override; + + /** + * Called by ApplyDeltaToActor to perform an actor class-specific operation based on widget manipulation. + * The default implementation is simply to modify the actor's rotation. + */ + void EditorApplyRotation(const FRotator& DeltaRotation, bool bAltDown, bool bShiftDown, bool bCtrlDown) override; + + /** + * Called by ApplyDeltaToActor to perform an actor class-specific operation based on widget manipulation. + * The default implementation is simply to modify the actor's draw scale. + */ + void EditorApplyScale(const FVector& DeltaScale, const FVector* PivotLocation, bool bAltDown, bool bShiftDown, bool bCtrlDown) override; + + #endif // WITH_EDITOR protected: @@ -50,13 +67,13 @@ class CARLA_API AProceduralBuilding : public AActor UFUNCTION(BlueprintCallable, CallInEditor, Category="Procedural Building") void Reset(); + // TODO: AdvancedDisplay // Map containing the pair with the name of the mesh and the component that uses it - //UPROPERTY(BlueprintReadOnly, VisibleAnywhere, AdvancedDisplay, Category="Procedural Building|Debug") - UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Debug") + UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Procedural Building|Debug") TMap HISMComps; // Contains all the ChildActorComps spawned for this Actor - UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="Procedural Building|Debug") + UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category="Procedural Building|Debug") TArray ChildActorComps; /** From 68e009778787e10cd0297052f5532b1584bfd0cf Mon Sep 17 00:00:00 2001 From: doterop Date: Tue, 22 Sep 2020 16:20:52 +0200 Subject: [PATCH 143/179] Added roof --- .../Carla/MapGen/ProceduralBuilding.cpp | 83 ++++++++++++++----- .../Source/Carla/MapGen/ProceduralBuilding.h | 6 +- 2 files changed, 68 insertions(+), 21 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp index 44821a7912d..b0cb8dcab1b 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp @@ -15,16 +15,6 @@ AProceduralBuilding::AProceduralBuilding() UStaticMeshComponent* StaticMeshComponent = CreateDefaultSubobject(TEXT("RootComponent")); RootComponent = StaticMeshComponent; - - const TSet Comps = GetComponents(); - UE_LOG(LogCarla, Warning, TEXT("CTR - ChildActorComps %d, HISMComps %d, Comps %d"), - ChildActorComps.Num(), HISMComps.Num(), Comps.Num()); - - TArray ChildActors; - GetAllChildActors(ChildActors); - UE_LOG(LogCarla, Warning, TEXT("CTR - Attached Childs %d"), ChildActors.Num()); - - } #if WITH_EDITOR @@ -44,7 +34,7 @@ void AProceduralBuilding::EditorApplyTranslation( { AActor* ChildActor = ChildActorComp->GetChildActor(); FVector ChildActorLocation = ChildActor->GetActorLocation(); - ChildActor->SetActorLocation(ChildActorLocation + DeltaTranslation); + //ChildActor->SetActorLocation(ChildActorLocation + DeltaTranslation); } } @@ -65,11 +55,11 @@ void AProceduralBuilding::EditorApplyRotation(const FRotator& DeltaRotation, boo // Add DeltaRotation ChildActorRotation += DeltaRotation; - ChildActor->SetActorRotation(ChildActorRotation); + //ChildActor->SetActorRotation(ChildActorRotation); // Rotate the location DeltaLocation = DeltaRotation.RotateVector(DeltaLocation); - ChildActor->SetActorLocation(ParentLocation + DeltaLocation); + //ChildActor->SetActorLocation(ParentLocation + DeltaLocation); } } @@ -100,10 +90,21 @@ void AProceduralBuilding::CreateBuilding() false); // Body floors + const FloorMeshCollection BodyMeshCollection = + { &BodyMeshes, &BodyBPs, &CornerBodyMeshes, &CornerBodyBPs, &WallMeshes, &WallBPs }; + for(int i = 0; i < NumFloors; i++) + { + CreateFloor(BodyMeshCollection, false, true); + } // Top floor + CreateFloor( + { &TopMeshes, &TopBPs, &CornerTopMeshes, &CornerTopBPs }, + false, + false); // Roof + CreateRoof(); } @@ -189,6 +190,44 @@ void AProceduralBuilding::CreateFloor( } +void AProceduralBuilding::CreateRoof() +{ + UStaticMesh* SelectedMesh = nullptr; + TSubclassOf SelectedBP = nullptr; + FBox SelectedMeshBounds; + + bool AreRoofMeshesAvailable = (RoofMeshes.Num() > 0) || (RoofBPs.Num() > 0); + + // Hack for top meshes. Perhaps the top part has a little part of the roof + FVector BoxSize = LastSelectedMeshBounds.GetSize(); + BoxSize = FVector(0.0f, -BoxSize.Y, 0.0f); + CurrentTransform.SetTranslation(CurrentTransform.GetTranslation() + BoxSize); + + if(AreRoofMeshesAvailable) + { + + for(int i = 0; i < LengthY; i++) + { + FVector PivotLocation = CurrentTransform.GetTranslation(); + for(int j = 0; j < LengthX; j++) + { + UE_LOG(LogCarla, Warning, TEXT(" CurrLocation %s"), *CurrentTransform.GetTranslation().ToString()); + + // Choose a roof mesh + ChooseGeometryToSpawn(RoofMeshes, RoofBPs, &SelectedMesh, &SelectedBP); + + AddChunck(SelectedMesh, SelectedBP, RoofVisibility, SelectedMeshBounds); + + } + // Move the Transform location to the beginning of the next row + CurrentTransform.SetTranslation(PivotLocation); + UpdateTransformPositionToNextSide(SelectedMeshBounds); + } + } + + +} + float AProceduralBuilding::CreateSide( const FloorMeshCollection& MeshCollection, const TSet& AuxiliarPositions, @@ -250,6 +289,8 @@ float AProceduralBuilding::CreateSide( UpdateTransformPositionToNextSide(SelectedMeshBounds); } + LastSelectedMeshBounds = SelectedMeshBounds; + return MaxZ; } @@ -332,7 +373,7 @@ float AProceduralBuilding::AddChunck( { AddMeshToBuilding(SelectedMesh); } - FVector MeshBound = GetMeshBound(SelectedMesh); + FVector MeshBound = GetMeshSize(SelectedMesh); Result = MeshBound.Z; UpdateTransformPositionToNextChunk(MeshBound); @@ -357,7 +398,7 @@ float AProceduralBuilding::AddChunck( AActor* ChildActor = ChildActorComp->GetChildActor(); FAttachmentTransformRules AttachmentTransformRules = FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true); - ChildActor->AttachToComponent(RootComponent, AttachmentTransformRules); + //ChildActor->AttachToComponent(RootComponent, AttachmentTransformRules); #if WITH_EDITOR // Add the child actor to a subfolder of the actor's name @@ -381,7 +422,7 @@ float AProceduralBuilding::AddChunck( const UStaticMesh* SM = PivotSMComp->GetStaticMesh(); AddMeshToBuilding(SM); - FVector MeshBound = GetMeshBound(SM); + FVector MeshBound = GetMeshSize(SM); Result = MeshBound.Z; UpdateTransformPositionToNextChunk(MeshBound); @@ -434,10 +475,10 @@ UHierarchicalInstancedStaticMeshComponent* AProceduralBuilding::GetHISMComp( return HISMComp; } -FVector AProceduralBuilding::GetMeshBound(const UStaticMesh* SM) +FVector AProceduralBuilding::GetMeshSize(const UStaticMesh* SM) { FBox Box = SM->GetBoundingBox(); - return (Box.Max - Box.Min); + return Box.GetSize(); } void AProceduralBuilding::UpdateTransformPositionToNextChunk(const FVector& Box) @@ -451,6 +492,8 @@ void AProceduralBuilding::UpdateTransformPositionToNextChunk(const FVector& Box) FVector NewLocation = CurrentTransform.GetTranslation() + ForwardVector * Box.X; CurrentTransform.SetTranslation(NewLocation); + + UE_LOG(LogCarla, Warning, TEXT(" UpdateTransformPositionToNextChunk %s"), *NewLocation.ToString()); } } @@ -462,9 +505,9 @@ void AProceduralBuilding::UpdateTransformPositionToNextSide(const FBox& Box) { FQuat Rotation = CurrentTransform.GetRotation(); FVector RightVector = -Rotation.GetRightVector(); - FVector Extent = (Box.Max - Box.Min); + FVector Size = Box.GetSize(); - FVector NewLocation = CurrentTransform.GetTranslation() + RightVector * Extent.Y; + FVector NewLocation = CurrentTransform.GetTranslation() + RightVector * Size.Y; CurrentTransform.SetTranslation(NewLocation); } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h index 9151a181e16..8a6ba315c38 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h @@ -219,6 +219,8 @@ class CARLA_API AProceduralBuilding : public AActor void CreateFloor(const FloorMeshCollection& MeshCollection, bool IncludeDoors, bool IncludeWalls); + void CreateRoof(); + // Creates the side of a floor of the building and returns the maximun height of the side float CreateSide( const FloorMeshCollection& MeshCollection, @@ -258,7 +260,7 @@ class CARLA_API AProceduralBuilding : public AActor UHierarchicalInstancedStaticMeshComponent* GetHISMComp(const UStaticMesh* SM); // Calculate the Bounds for the Static Mesh - FVector GetMeshBound(const UStaticMesh* SM); + FVector GetMeshSize(const UStaticMesh* SM); void UpdateTransformPositionToNextChunk(const FVector& Box); @@ -271,4 +273,6 @@ class CARLA_API AProceduralBuilding : public AActor // Transform used to spawn the meshes of the building. It is updated (moved) with each new mesh FTransform CurrentTransform = FTransform::Identity; + FBox LastSelectedMeshBounds; + }; From b5050e0a79aecc22826118f7737538d671769488 Mon Sep 17 00:00:00 2001 From: doterop Date: Tue, 22 Sep 2020 18:05:07 +0200 Subject: [PATCH 144/179] Added Wall support --- .../Carla/MapGen/ProceduralBuilding.cpp | 66 +++++++++++-------- .../Source/Carla/MapGen/ProceduralBuilding.h | 3 + 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp index b0cb8dcab1b..6785927a435 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp @@ -12,6 +12,7 @@ AProceduralBuilding::AProceduralBuilding() SideVisibility.Init(true, 4); CornerVisibility.Init(true, 4); + UseWallMesh.Init(false, 4); UStaticMeshComponent* StaticMeshComponent = CreateDefaultSubobject(TEXT("RootComponent")); RootComponent = StaticMeshComponent; @@ -131,8 +132,10 @@ void AProceduralBuilding::Reset() // Remove all child actors for(UChildActorComponent* ChildActorComp : ChildActorComps) { - ChildActorComp->DestroyChildActor(); - ChildActorComp->DestroyComponent(); + if(ChildActorComp) + { + ChildActorComp->DestroyComponent(); + } } ChildActorComps.Reset(); @@ -157,20 +160,24 @@ void AProceduralBuilding::CreateFloor( for(int i = 0; i < SidesLength.Num(); i++) { - TSet DoorsPosition; + TSet AuxiliarPositions; int SideLength = SidesLength[i]; bool MainVisibility = true; bool CornerVisbility = true; if (IncludeDoors) { - DoorsPosition = CalculateDoorsIndexInSide(SideLengthAcumulator, SideLength); + AuxiliarPositions = CalculateDoorsIndexInSide(SideLengthAcumulator, SideLength); + } + if(IncludeWalls && UseWallMesh[i]) + { + AuxiliarPositions = GenerateWallsIndexPositions(SideLength); } CalculateSideVisibilities(i, MainVisibility, CornerVisbility); // Update Max Z - float SideMaxZ = CreateSide(MeshCollection, DoorsPosition, SideLength, MainVisibility, CornerVisbility); + float SideMaxZ = CreateSide(MeshCollection, AuxiliarPositions, SideLength, MainVisibility, CornerVisbility); MaxZ = (MaxZ < SideMaxZ) ? SideMaxZ : MaxZ; // Update the acumulator to calculate doors index in next sides @@ -201,6 +208,7 @@ void AProceduralBuilding::CreateRoof() // Hack for top meshes. Perhaps the top part has a little part of the roof FVector BoxSize = LastSelectedMeshBounds.GetSize(); BoxSize = FVector(0.0f, -BoxSize.Y, 0.0f); + CurrentTransform.SetTranslation(CurrentTransform.GetTranslation() + BoxSize); if(AreRoofMeshesAvailable) @@ -211,8 +219,6 @@ void AProceduralBuilding::CreateRoof() FVector PivotLocation = CurrentTransform.GetTranslation(); for(int j = 0; j < LengthX; j++) { - UE_LOG(LogCarla, Warning, TEXT(" CurrLocation %s"), *CurrentTransform.GetTranslation().ToString()); - // Choose a roof mesh ChooseGeometryToSpawn(RoofMeshes, RoofBPs, &SelectedMesh, &SelectedBP); @@ -281,7 +287,7 @@ float AProceduralBuilding::CreateSide( { // Choose a corner mesh ChooseGeometryToSpawn(*CornerMeshes, *CornerBPs, &SelectedMesh, &SelectedBP); - float ChunkZ = AddChunck(SelectedMesh, SelectedBP, MainVisibility, SelectedMeshBounds); + float ChunkZ = AddChunck(SelectedMesh, SelectedBP, CornerVisbility, SelectedMeshBounds); MaxZ = (MaxZ < ChunkZ) ? ChunkZ : MaxZ; // Move the Transform location to the next side of the building @@ -330,6 +336,16 @@ TSet AProceduralBuilding::CalculateDoorsIndexInSide(int StartIndex, int Len return Result; } +TSet AProceduralBuilding::GenerateWallsIndexPositions(int Length) +{ + TSet Result; + for(int i = 0; i < Length; i++) + { + Result.Emplace(i); + } + return Result; +} + void AProceduralBuilding::CalculateSideVisibilities(int SideIndex, bool& MainVisibility, bool& CornerVisbility) { MainVisibility = UseFullBlocks || SideVisibility[SideIndex]; @@ -411,31 +427,29 @@ float AProceduralBuilding::AddChunck( ChildActor->GetComponents(SMComps); - int NumSMs = SMComps.Num(); + // The first mesh on the BP is the pivot to continue creating the floor + PivotSMComp = SMComps[0]; + const UStaticMesh* SM = PivotSMComp->GetStaticMesh(); - if(Visible && NumSMs > 0) + if(Visible) { ChildActorComps.Emplace(ChildActorComp); - - // The first mesh on the BP is the pivot to continue creating the floor - PivotSMComp = SMComps[0]; - const UStaticMesh* SM = PivotSMComp->GetStaticMesh(); - AddMeshToBuilding(SM); - FVector MeshBound = GetMeshSize(SM); - Result = MeshBound.Z; - - UpdateTransformPositionToNextChunk(MeshBound); - - // Make it invisible on the child actor to avoid duplication with the HISMComp - PivotSMComp->SetVisibility(false, false); - OutSelectedMeshBounds = SM->GetBoundingBox(); } else { - //ChildActorComp->DestroyComponent(); - ChildActor->Destroy(); + ChildActorComp->DestroyComponent(); } + + FVector MeshBound = GetMeshSize(SM); + Result = MeshBound.Z; + + UpdateTransformPositionToNextChunk(MeshBound); + + // Make it invisible on the child actor to avoid duplication with the HISMComp + PivotSMComp->SetVisibility(false, false); + OutSelectedMeshBounds = SM->GetBoundingBox(); + } return Result; @@ -492,8 +506,6 @@ void AProceduralBuilding::UpdateTransformPositionToNextChunk(const FVector& Box) FVector NewLocation = CurrentTransform.GetTranslation() + ForwardVector * Box.X; CurrentTransform.SetTranslation(NewLocation); - - UE_LOG(LogCarla, Warning, TEXT(" UpdateTransformPositionToNextChunk %s"), *NewLocation.ToString()); } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h index 8a6ba315c38..8c4af447a4d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h @@ -235,6 +235,9 @@ class CARLA_API AProceduralBuilding : public AActor // The set returns the position (index) of the doors relative to the side, ie: [0, Length) TSet CalculateDoorsIndexInSide(int StartIndex, int Length); + // + TSet GenerateWallsIndexPositions(int Length); + // Check if the main and corner part of the side is visible void CalculateSideVisibilities(int SideIndex, bool& MainVisibility, bool& CornerVisbility); From bb56f3f1ce569c25487bdc2b7279fc4788c82fa3 Mon Sep 17 00:00:00 2001 From: doterop Date: Wed, 23 Sep 2020 15:26:40 +0200 Subject: [PATCH 145/179] Updated BP to code --- .../Carla/MapGen/ProceduralBuilding.cpp | 205 ++++++++++++++---- .../Source/Carla/MapGen/ProceduralBuilding.h | 60 ++++- 2 files changed, 218 insertions(+), 47 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp index 6785927a435..7fcdee240c3 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp @@ -18,6 +18,173 @@ AProceduralBuilding::AProceduralBuilding() RootComponent = StaticMeshComponent; } +UHierarchicalInstancedStaticMeshComponent* AProceduralBuilding::GetHISMComp( + const UStaticMesh* SM) +{ + + FString SMName = SM->GetName(); + + UHierarchicalInstancedStaticMeshComponent** HISMCompPtr = HISMComps.Find(SMName); + + if(HISMCompPtr) return *HISMCompPtr; + + UHierarchicalInstancedStaticMeshComponent* HISMComp = *HISMCompPtr; + + // If it doesn't exist, create the component + HISMComp = NewObject(this, + FName(*FString::Printf(TEXT("HISMComp_%d"), HISMComps.Num()))); + HISMComp->SetupAttachment(RootComponent); + HISMComp->RegisterComponent(); + + // Set the mesh that will be used + HISMComp->SetStaticMesh(const_cast(SM)); + + // Add to the map + HISMComps.Emplace(SMName, HISMComp); + + return HISMComp; +} + +void AProceduralBuilding::ConvertOldBP_ToNativeCodeObject(AActor* BP_Building) +{ + AProceduralBuilding* ProceduralBuilding = nullptr; + + // Look for all the HISMComps + TArray OtherHISMComps; + BP_Building->GetComponents(OtherHISMComps); + + for(UHierarchicalInstancedStaticMeshComponent* OtherHISMComp : OtherHISMComps) + { + const UStaticMesh* SM = OtherHISMComp->GetStaticMesh(); + + // Create a new HISMComp and set the SM + UHierarchicalInstancedStaticMeshComponent* NewHISMComp = GetHISMComp(SM); + + // Create the instances + const TArray& PerInstanceSMData = OtherHISMComp->PerInstanceSMData; + + for(const FInstancedStaticMeshInstanceData& InstSMIData : PerInstanceSMData) + { + FTransform Transform = FTransform(InstSMIData.Transform); + + NewHISMComp->AddInstance(Transform); + } + } + + // TODO: Look for all ChildActors -> Add new Child + TArray OtherChildComps; + BP_Building->GetComponents(OtherChildComps); + + for(const UChildActorComponent* OtherChildActor : OtherChildComps) + { + // Create a new ChildActorComponent + UChildActorComponent* ChildActorComp = NewObject(this, + FName(*FString::Printf(TEXT("ChildActorComp_%d"), ChildActorComps.Num() ))); + ChildActorComp->SetupAttachment(RootComponent); + + // Set the class that it will use + ChildActorComp->SetChildActorClass(OtherChildActor->GetChildActorClass()); + ChildActorComp->SetRelativeTransform(OtherChildActor->GetRelativeTransform()); + + // Spawns the actor referenced by UChildActorComponent + ChildActorComp->RegisterComponent(); + + AActor* NewChildActor = ChildActorComp->GetChildActor(); + +#if WITH_EDITOR + // Add the child actor to a subfolder of the actor's name + NewChildActor->SetFolderPath(FName( *FString::Printf(TEXT("/Buildings/%s"), *GetName()))); + #endif + + // Look for all the SMComps + TArray NewSMComps; + NewChildActor->GetComponents(NewSMComps); + + // Make it invisible on the child actor to avoid duplication with the HISMComp + UStaticMeshComponent* PivotSMComp = NewSMComps[0]; + PivotSMComp->SetVisibility(false, false); + + ChildActorComps.Emplace(ChildActorComp); + + } +} + +void AProceduralBuilding::SetBaseParameters( + const TSet& InDoorsIndexPosition, + const TArray& InUseWallMesh, + int InNumFloors, + int InLengthX, + int InLengthY, + bool InCorners, + bool InUseFullBlocks) +{ + DoorsIndexPosition = InDoorsIndexPosition; + UseWallMesh = InUseWallMesh; + NumFloors = InNumFloors; + LengthX = InLengthX; + LengthY = InLengthY; + Corners = InCorners; + UseFullBlocks = InUseFullBlocks; +} + +void AProceduralBuilding::SetVisibilityParameters( + const TArray& InSideVisibility, + const TArray& InCornerVisibility, + bool InRoofVisibility) +{ + SideVisibility = InSideVisibility; + CornerVisibility = InCornerVisibility; + RoofVisibility = InRoofVisibility; +} + +void AProceduralBuilding::SetBaseMeshes( + const TArray& InBaseMeshes, + const TArray>& InBaseBPs, + const TArray& InCornerBaseMeshes, + const TArray>& InCornerBaseBPs, + const TArray& InDoorMeshes, + const TArray>& InDoorBPs) +{ + BaseMeshes = InBaseMeshes; + BaseBPs = InBaseBPs; + CornerBaseMeshes = InCornerBaseMeshes; + CornerBaseBPs = InCornerBaseBPs; + DoorMeshes = InDoorMeshes; + DoorBPs = InDoorBPs; +} + +void AProceduralBuilding::SetBodyMeshes( + const TArray& InBodyMeshes, + const TArray>& InBodyBPs, + const TArray& InCornerBodyMeshes, + const TArray>& InCornerBodyBPs, + const TArray& InWallMeshes, + const TArray>& InWallBPs) +{ + BodyMeshes = InBodyMeshes; + BodyBPs = InBodyBPs; + CornerBodyMeshes = InCornerBodyMeshes; + CornerBodyBPs = InCornerBodyBPs; + WallMeshes = InWallMeshes; + WallBPs = InWallBPs; +} + +void AProceduralBuilding::SetTopMeshes( + const TArray& InTopMeshes, + const TArray>& InTopBPs, + const TArray& InCornerTopMeshes, + const TArray>& InCornerTopBPs, + const TArray& InRoofMeshes, + const TArray>& InRoofBPs) +{ + TopMeshes = InTopMeshes; + TopBPs = InTopBPs; + CornerTopMeshes = InCornerTopMeshes; + CornerTopBPs = InCornerTopBPs; + RoofMeshes = InRoofMeshes; + RoofBPs = InRoofBPs; +} + #if WITH_EDITOR void AProceduralBuilding::EditorApplyTranslation( @@ -28,9 +195,6 @@ void AProceduralBuilding::EditorApplyTranslation( { Super::EditorApplyTranslation(DeltaTranslation, bAltDown, bShiftDown, bCtrlDown); - const FTransform& ParentTransform = GetTransform(); - FTransform ChildTransform = ChildActorComps[0]->GetChildActor()->GetTransform(); - for(UChildActorComponent* ChildActorComp : ChildActorComps) { AActor* ChildActor = ChildActorComp->GetChildActor(); @@ -43,9 +207,6 @@ void AProceduralBuilding::EditorApplyRotation(const FRotator& DeltaRotation, boo { Super::EditorApplyRotation(DeltaRotation, bAltDown, bShiftDown, bCtrlDown); - const FTransform& ParentTransform = GetTransform(); - FTransform ChildTransform = ChildActorComps[0]->GetChildActor()->GetTransform(); - FVector ParentLocation = GetActorLocation(); for(UChildActorComponent* ChildActorComp : ChildActorComps) { @@ -74,7 +235,6 @@ void AProceduralBuilding::EditorApplyScale(const FVector& DeltaScale, const FVec FVector ChildActorScale = ChildActor->GetActorScale3D(); // TODO: apply scale with rotation in mind // ChildActor->SetActorScale3D(); - } } @@ -410,11 +570,7 @@ float AProceduralBuilding::AddChunck( // Spawns the actor referenced by UChildActorComponent ChildActorComp->RegisterComponent(); - // Create and attach child actor to parent AActor* ChildActor = ChildActorComp->GetChildActor(); - FAttachmentTransformRules AttachmentTransformRules = - FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true); - //ChildActor->AttachToComponent(RootComponent, AttachmentTransformRules); #if WITH_EDITOR // Add the child actor to a subfolder of the actor's name @@ -462,33 +618,6 @@ void AProceduralBuilding::AddMeshToBuilding(const UStaticMesh* SM) HISMComp->AddInstance(CurrentTransform); } -UHierarchicalInstancedStaticMeshComponent* AProceduralBuilding::GetHISMComp( - const UStaticMesh* SM) -{ - - FString SMName = SM->GetName(); - - UHierarchicalInstancedStaticMeshComponent** HISMCompPtr = HISMComps.Find(SMName); - - if(HISMCompPtr) return *HISMCompPtr; - - UHierarchicalInstancedStaticMeshComponent* HISMComp = *HISMCompPtr; - - // If it doesn't exist, create the component - HISMComp = NewObject(this, - FName(*FString::Printf(TEXT("HISMComp_%d"), HISMComps.Num()))); - HISMComp->SetupAttachment(RootComponent); - HISMComp->RegisterComponent(); - - // Set the mesh that will be used - HISMComp->SetStaticMesh(const_cast(SM)); - - // Add to the map - HISMComps.Emplace(SMName, HISMComp); - - return HISMComp; -} - FVector AProceduralBuilding::GetMeshSize(const UStaticMesh* SM) { FBox Box = SM->GetBoundingBox(); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h index 8c4af447a4d..c9bd3521ce5 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h @@ -12,11 +12,6 @@ // TODO: support n-sides building -// TODO: option (button) to clear all the values -// TODO: option (button) to clear all the meshes - -// TODO: - struct FloorMeshCollection { TArray* MainMeshes = nullptr; @@ -37,6 +32,57 @@ class CARLA_API AProceduralBuilding : public AActor // Sets default values for this actor's properties AProceduralBuilding(); + // Looks for the HISMComp on the HISMComps Map that uses the SelectedMesh and returns it. + // If doesn't exist its created + UFUNCTION(BlueprintCallable, Category="Procedural Building") + UHierarchicalInstancedStaticMeshComponent* GetHISMComp(const UStaticMesh* SM); + + UFUNCTION(BlueprintCallable, CallInEditor, Category="Procedural Building") + void ConvertOldBP_ToNativeCodeObject(AActor* BP_Building); + + UFUNCTION(BlueprintCallable, Category="Procedural Building|Conversion") + void SetBaseParameters( + const TSet& InDoorsIndexPosition, + const TArray& InUseWallMesh, + int InNumFloors, + int InLengthX, + int InLengthY, + bool InCorners, + bool InUseFullBlocks); + + UFUNCTION(BlueprintCallable, Category="Procedural Building|Conversion") + void SetVisibilityParameters( + const TArray& InSideVisibility, + const TArray& InCornerVisibility, + bool InRoofVisibility); + + UFUNCTION(BlueprintCallable, Category="Procedural Building|Conversion") + void SetBaseMeshes( + const TArray& InBaseMeshes, + const TArray>& InBaseBPs, + const TArray& InCornerBaseMeshes, + const TArray>& InCornerBaseBPs, + const TArray& InDoorMeshes, + const TArray>& InDoorBPs); + + UFUNCTION(BlueprintCallable, Category="Procedural Building|Conversion") + void SetBodyMeshes( + const TArray& InBodyMeshes, + const TArray>& InBodyBPs, + const TArray& InCornerBodyMeshes, + const TArray>& InCornerBodyBPs, + const TArray& InWallMeshes, + const TArray>& InWallBPs); + + UFUNCTION(BlueprintCallable, Category="Procedural Building|Conversion") + void SetTopMeshes( + const TArray& InTopMeshes, + const TArray>& InTopBPs, + const TArray& InCornerTopMeshes, + const TArray>& InCornerTopBPs, + const TArray& InRoofMeshes, + const TArray>& InRoofBPs); + #if WITH_EDITOR /** * Called by ApplyDeltaToActor to perform an actor class-specific operation based on widget manipulation. @@ -258,10 +304,6 @@ class CARLA_API AProceduralBuilding : public AActor // Add the Static Mesh on the transform location with the transform orientation void AddMeshToBuilding(const UStaticMesh* SM); - // Looks for the HISMComp on the HISMComps Map that uses the SelectedMesh and returns it. - // If doesn't exist its created - UHierarchicalInstancedStaticMeshComponent* GetHISMComp(const UStaticMesh* SM); - // Calculate the Bounds for the Static Mesh FVector GetMeshSize(const UStaticMesh* SM); From 161923c1dd645082d4a431fb64ede4815eb56099 Mon Sep 17 00:00:00 2001 From: doterop Date: Wed, 23 Sep 2020 16:35:18 +0200 Subject: [PATCH 146/179] Cleaned some unneeded code --- .../Carla/MapGen/ProceduralBuilding.cpp | 61 ------------------- .../Source/Carla/MapGen/ProceduralBuilding.h | 22 ------- 2 files changed, 83 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp index 7fcdee240c3..ce5ca0c2625 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.cpp @@ -185,61 +185,6 @@ void AProceduralBuilding::SetTopMeshes( RoofBPs = InRoofBPs; } -#if WITH_EDITOR - -void AProceduralBuilding::EditorApplyTranslation( - const FVector& DeltaTranslation, - bool bAltDown, - bool bShiftDown, - bool bCtrlDown) -{ - Super::EditorApplyTranslation(DeltaTranslation, bAltDown, bShiftDown, bCtrlDown); - - for(UChildActorComponent* ChildActorComp : ChildActorComps) - { - AActor* ChildActor = ChildActorComp->GetChildActor(); - FVector ChildActorLocation = ChildActor->GetActorLocation(); - //ChildActor->SetActorLocation(ChildActorLocation + DeltaTranslation); - } -} - -void AProceduralBuilding::EditorApplyRotation(const FRotator& DeltaRotation, bool bAltDown, bool bShiftDown, bool bCtrlDown) -{ - Super::EditorApplyRotation(DeltaRotation, bAltDown, bShiftDown, bCtrlDown); - - FVector ParentLocation = GetActorLocation(); - for(UChildActorComponent* ChildActorComp : ChildActorComps) - { - AActor* ChildActor = ChildActorComp->GetChildActor(); - FVector ChildActorLocation = ChildActor->GetActorLocation(); - FVector DeltaLocation = ChildActorLocation - ParentLocation; - FRotator ChildActorRotation = ChildActor->GetActorRotation(); - - // Add DeltaRotation - ChildActorRotation += DeltaRotation; - //ChildActor->SetActorRotation(ChildActorRotation); - - // Rotate the location - DeltaLocation = DeltaRotation.RotateVector(DeltaLocation); - //ChildActor->SetActorLocation(ParentLocation + DeltaLocation); - } -} - -void AProceduralBuilding::EditorApplyScale(const FVector& DeltaScale, const FVector* PivotLocation, bool bAltDown, bool bShiftDown, bool bCtrlDown) -{ - Super::EditorApplyScale(DeltaScale, PivotLocation, bAltDown, bShiftDown, bCtrlDown); - - for(UChildActorComponent* ChildActorComp : ChildActorComps) - { - AActor* ChildActor = ChildActorComp->GetChildActor(); - FVector ChildActorScale = ChildActor->GetActorScale3D(); - // TODO: apply scale with rotation in mind - // ChildActor->SetActorScale3D(); - } -} - -#endif // WITH_EDITOR - void AProceduralBuilding::CreateBuilding() { Init(); @@ -652,9 +597,3 @@ void AProceduralBuilding::UpdateTransformPositionToNextSide(const FBox& Box) CurrentTransform.SetTranslation(NewLocation); } } - - - - - - diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h index c9bd3521ce5..279c9850fb6 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/ProceduralBuilding.h @@ -83,28 +83,6 @@ class CARLA_API AProceduralBuilding : public AActor const TArray& InRoofMeshes, const TArray>& InRoofBPs); -#if WITH_EDITOR - /** - * Called by ApplyDeltaToActor to perform an actor class-specific operation based on widget manipulation. - * The default implementation is simply to translate the actor's location. - */ - void EditorApplyTranslation(const FVector& DeltaTranslation, bool bAltDown, bool bShiftDown, bool bCtrlDown) override; - - /** - * Called by ApplyDeltaToActor to perform an actor class-specific operation based on widget manipulation. - * The default implementation is simply to modify the actor's rotation. - */ - void EditorApplyRotation(const FRotator& DeltaRotation, bool bAltDown, bool bShiftDown, bool bCtrlDown) override; - - /** - * Called by ApplyDeltaToActor to perform an actor class-specific operation based on widget manipulation. - * The default implementation is simply to modify the actor's draw scale. - */ - void EditorApplyScale(const FVector& DeltaScale, const FVector* PivotLocation, bool bAltDown, bool bShiftDown, bool bCtrlDown) override; - - -#endif // WITH_EDITOR - protected: UFUNCTION(BlueprintCallable, CallInEditor, Category="Procedural Building") From 935644d8778e56fb0d17be799a5971e415c28ea8 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Mon, 14 Sep 2020 16:58:48 +0200 Subject: [PATCH 147/179] First iteration with units --- Docs/python_api.md | 428 +++++++++++++++---------------- PythonAPI/docs/actor.yml | 33 ++- PythonAPI/docs/client.yml | 24 +- PythonAPI/docs/commands.yml | 10 + PythonAPI/docs/control.yml | 41 ++- PythonAPI/docs/doc_gen.py | 21 +- PythonAPI/docs/geom.yml | 57 ++-- PythonAPI/docs/light_manager.yml | 14 +- PythonAPI/docs/map.yml | 28 +- PythonAPI/docs/osm2odr.yml | 4 + PythonAPI/docs/sensor_data.yml | 44 +++- PythonAPI/docs/snapshot.yml | 4 + PythonAPI/docs/weather.yml | 12 +- PythonAPI/docs/world.yml | 64 +++-- 14 files changed, 484 insertions(+), 300 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index e70923a70cf..f4dc3c06ba9 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -22,11 +22,11 @@ The identifier of the blueprint this actor was based on, e.g. "vehicle.ford.must - **add_impulse**(**self**, **impulse**) Adds an impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. - **Parameters:** - - `impulse` (_[carla.Vector3D](#carla.Vector3D)_) + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N * s_) - **add_angular_impulse**(**self**, **impulse**) Adds an angular impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. - **Parameters:** - - `impulse` (_[carla.Vector3D](#carla.Vector3D)_) + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N * m * s_) - **destroy**(**self**) Tells the simulator to destroy this actor and returns True if it was successful. It has no effect if it was already destroyed. - **Return:** _bool_ @@ -36,14 +36,14 @@ _

    Getters
    - **get_acceleration**(**self**) Returns the actor's 3D acceleration vector the client recieved during last tick. The method does not call the simulator. - - **Return:** _[carla.Vector3D](#carla.Vector3D)_ + - **Return:** _[carla.Vector3D](#carla.Vector3D) – m/s2_ - **get_angular_velocity**(**self**) Returns the actor's angular velocity vector the client recieved during last tick. The method does not call the simulator. - - **Return:** _[carla.Vector3D](#carla.Vector3D)_ + - **Return:** _[carla.Vector3D](#carla.Vector3D) – rad/s_ - **Setter:** _[carla.Actor.set_angular_velocity](#carla.Actor.set_angular_velocity)_ - **get_location**(**self**) Returns the actor's location the client recieved during last tick. The method does not call the simulator. - - **Return:** _[carla.Location](#carla.Location)_ + - **Return:** _[carla.Location](#carla.Location) – meters_ - **Setter:** _[carla.Actor.set_location](#carla.Actor.set_location)_ - **get_transform**(**self**) Returns the actor's transform (location and rotation) the client recieved during last tick. The method does not call the simulator. @@ -51,7 +51,7 @@ Returns the actor's transform (location and rotation) the client recieved during - **Setter:** _[carla.Actor.set_transform](#carla.Actor.set_transform)_ - **get_velocity**(**self**) Returns the actor's velocity vector the client recieved during last tick. The method does not call the simulator. - - **Return:** _[carla.Vector3D](#carla.Vector3D)_ + - **Return:** _[carla.Vector3D](#carla.Vector3D) – m/s_ - **Setter:** _[carla.Actor.set_velocity](#carla.Actor.set_velocity)_ - **get_world**(**self**) Returns the world this actor belongs to. @@ -66,7 +66,7 @@ Changes the actor's angular velocity vector. - **set_location**(**self**, **location**) Teleports the actor to a given location. - **Parameters:** - - `location` (_[carla.Location](#carla.Location)_) + - `location` (_[carla.Location](#carla.Location) – meters_) - **Getter:** _[carla.Actor.get_location](#carla.Actor.get_location)_ - **set_simulate_physics**(**self**, **enabled**=True) Enables or disables the simulation of physics on this actor. @@ -235,16 +235,16 @@ An identifier for the snapshot itself.
    Getters
    - **get_acceleration**(**self**) Returns the acceleration vector registered for an actor in that tick. - - **Return:** _[carla.Vector3D](#carla.Vector3D)_ + - **Return:** _[carla.Vector3D](#carla.Vector3D) – m/s2_ - **get_angular_velocity**(**self**) Returns the angular velocity vector registered for an actor in that tick. - - **Return:** _[carla.Vector3D](#carla.Vector3D)_ + - **Return:** _[carla.Vector3D](#carla.Vector3D) – rad/s_ - **get_transform**(**self**) Returns the actor's transform (location and rotation) for an actor in that tick. - **Return:** _[carla.Transform](#carla.Transform)_ - **get_velocity**(**self**) Returns the velocity vector registered for an actor in that tick. - - **Return:** _[carla.Vector3D](#carla.Vector3D)_ + - **Return:** _[carla.Vector3D](#carla.Vector3D) – m/s_ --- @@ -295,21 +295,21 @@ Parses the identifiers for every blueprint to string. Helper class defining a box location and its dimensions that will later be used by [carla.DebugHelper](#carla.DebugHelper) or a [carla.Client](#carla.Client) to draw shapes and detect collisions. Bounding boxes normally act for object colliders. Check out this [recipe](ref_code_recipes.md#debug-bounding-box-recipe) where the user takes a snapshot of the world and then proceeds to draw bounding boxes for traffic lights.

    Instance Variables

    -- **extent** (_[carla.Vector3D](#carla.Vector3D)_) +- **extent** (_[carla.Vector3D](#carla.Vector3D) – meters_) Vector from the center of the box to one vertex. The value in each axis equals half the size of the box for that axis. `extent.x * 2` would return the size of the box in the X-axis. -- **location** (_[carla.Location](#carla.Location)_) +- **location** (_[carla.Location](#carla.Location) – meters_) The center of the bounding box relative to its parent actor.

    Methods

    - **\__init__**(**self**, **location**, **extent**) - **Parameters:** - - `location` (_[carla.Location](#carla.Location)_) – Point to center the box. - - `extent` (_[carla.Vector3D](#carla.Vector3D)_) – Vector containing half the size of the box for every axis. + - `location` (_[carla.Location](#carla.Location)_) – Center of the box, relative to its parent. + - `extent` (_[carla.Vector3D](#carla.Vector3D) – meters_) – Vector containing half the size of the box for every axis. - **contains**(**self**, **world_point**, **transform**) Returns **True** if a point passed in world space is inside this bounding box. - **Parameters:** - - `world_point` (_[carla.Location](#carla.Location)_) – The point in world space to be checked. + - `world_point` (_[carla.Location](#carla.Location) – meters_) – The point in world space to be checked. - `transform` (_[carla.Transform](#carla.Transform)_) – Contains location and rotation needed to convert this object's local space to world space. - **Return:** _bool_ @@ -374,8 +374,8 @@ Reload the current world, note that a new world is created with default settings Load a new world with default settings using `map_name` map. All actors present in the current world will be destroyed, __but__ traffic manager instances will stay alive. - **Parameters:** - `name` (_str_) – Name of the file containing the information of the simulation. - - `start` (_float_) – Time in seconds where to start playing the simulation. Negative is read as beginning from the end, being -10 just 10 seconds before the recording finished. - - `duration` (_float_) – Time in seconds that will be reenacted using the information `name` file. If the end is reached, the simulation will continue. + - `start` (_float – seconds_) – Time where to start playing the simulation. Negative is read as beginning from the end, being -10 just 10 seconds before the recording finished. + - `duration` (_float – seconds_) – Time that will be reenacted using the information `name` file. If the end is reached, the simulation will continue. - `follow_id` (_int_) – ID of the actor to follow. If this is 0 then camera is disabled. - **stop_replayer**(**self**, **keep_actors**) Stop current replayer. @@ -385,8 +385,8 @@ Stop current replayer. The terminal will show the information registered for actors considered blocked. An actor is considered blocked when it does not move a minimum distance in a period of time, being these `min_distance` and `min_time`. - **Parameters:** - `filename` (_str_) – Name of the recorded file to load. - - `min_time` (_float_) – Minimum time in seconds the actor has to move a minimum distance before being considered blocked. Default is 60 seconds. - - `min_distance` (_float_) – Minimum distance in centimeters the actor has to move to not be considered blocked. Default is 100 centimeters. + - `min_time` (_float – seconds_) – Minimum time the actor has to move a minimum distance before being considered blocked. Default is 60 seconds. + - `min_distance` (_float – centimeters_) – Minimum distance the actor has to move to not be considered blocked. Default is 100 centimeters. - **Return:** _string_ - **show_recorder_collisions**(**self**, **filename**, **category1**, **category2**) The terminal will show the collisions registered by the recorder. These can be filtered by specifying the type of actor involved. The categories will be specified in `category1` and `category2` as follows: @@ -448,9 +448,9 @@ When used, the time speed of the reenacted simulation is modified at will. It ca - **Parameters:** - `time_factor` (_float_) – 1.0 means normal time speed. Greater than 1.0 means fast motion (2.0 would be double speed) and lesser means slow motion (0.5 would be half speed). - **set_timeout**(**self**, **seconds**) -Sets in seconds the maxixum time a network call is allowed before blocking it and raising a timeout exceeded error. +Sets the maxixum time a network call is allowed before blocking it and raising a timeout exceeded error. - **Parameters:** - - `seconds` (_float_) – New timeout value in seconds. Default is 5 seconds. + - `seconds` (_float – seconds_) – New timeout value. Default is 5 seconds. --- @@ -462,7 +462,7 @@ Sets in seconds the maxixum time a network call is allowed before blocking it an The actor the sensor is attached to, the one that measured the collision. - **other_actor** (_[carla.Actor](#carla.Actor)_) The second actor involved in the collision. -- **normal_impulse** (_[carla.Vector3D](#carla.Vector3D)_) +- **normal_impulse** (_[carla.Vector3D](#carla.Vector3D) – N*m_) Normal impulse resulting of the collision. --- @@ -535,8 +535,8 @@ Polarity of the event. __True__ for positive and __False__ for negative. Class that defines a stream of events in [[carla.DVSEvent](#carla.DVSEvent)](#[carla.DVSEvent](#carla.DVSEvent)). Such stream is an array of arbitrary size depending on the number of events. This class also stores the field of view, the height and width of the image and the timestamp from convenience. Learn more about them [here](ref_sensors.md).

    Instance Variables

    -- **fov** (_float_) -Horizontal field of view of the image in degrees. +- **fov** (_float – degrees_) +Horizontal field of view of the image. - **height** (_int_) Image height in pixels. - **width** (_int_) @@ -570,46 +570,46 @@ Returns an array with the polarity of all the events in the stream. Helper class part of [carla.World](#carla.World) that defines methods for creating debug shapes. By default, shapes last one second. They can be permanent, but take into account the resources needed to do so. Check out this [recipe](ref_code_recipes.md#debug-bounding-box-recipe) where the user takes a snapshot of the world and then proceeds to draw bounding boxes for traffic lights.

    Methods

    -- **draw_arrow**(**self**, **begin**, **end**, **thickness**=0.1f, **arrow_size**=0.1f, **color**=(255,0,0), **life_time**=-1.0f) +- **draw_arrow**(**self**, **begin**, **end**, **thickness**=0.1, **arrow_size**=0.1, **color**=(255,0,0), **life_time**=-1.0) Draws an arrow from `begin` to `end` pointing in that direction. - **Parameters:** - - `begin` (_[carla.Location](#carla.Location)_) – Point in the coordinate system where the arrow starts. - - `end` (_[carla.Location](#carla.Location)_) – Point in the coordinate system where the arrow ends and points towards to. - - `thickness` (_float_) – Density of the line. - - `arrow_size` (_float_) – Size of the tip of the arrow. + - `begin` (_[carla.Location](#carla.Location) – meters_) – Point in the coordinate system where the arrow starts. + - `end` (_[carla.Location](#carla.Location) – meters_) – Point in the coordinate system where the arrow ends and points towards to. + - `thickness` (_float – meters_) – Density of the line. + - `arrow_size` (_float – meters_) – Size of the tip of the arrow. - `color` (_[carla.Color](#carla.Color)_) – RGB code to color the object. Red by default. - - `life_time` (_float_) – Lifespan in seconds for the shape. By default it only lasts one frame. Set this to 0 for permanent shapes. -- **draw_box**(**self**, **box**, **rotation**, **thickness**=0.1f, **color**=(255,0,0), **life_time**=-1.0f) + - `life_time` (_float – seconds_) – Shape's lifespan. By default it only lasts one frame. Set this to 0 for permanent shapes. +- **draw_box**(**self**, **box**, **rotation**, **thickness**=0.1, **color**=(255,0,0), **life_time**=-1.0) Draws a box, ussually to act for object colliders. - **Parameters:** - `box` (_[carla.BoundingBox](#carla.BoundingBox)_) – Object containing a location and the length of a box for every axis. - - `rotation` (_[carla.Rotation](#carla.Rotation)_) – Orientation of the box according to Unreal Engine's axis system. - - `thickness` (_float_) – Density of the lines that define the box. + - `rotation` (_[carla.Rotation](#carla.Rotation) – degrees_) – Orientation of the box according to Unreal Engine's axis system. + - `thickness` (_float – meters_) – Density of the lines that define the box. - `color` (_[carla.Color](#carla.Color)_) – RGB code to color the object. Red by default. - - `life_time` (_float_) – Lifespan in seconds for the shape. By default it only lasts one frame. Set this to 0 for permanent shapes. -- **draw_line**(**self**, **begin**, **end**, **thickness**=0.1f, **color**=(255,0,0), **life_time**=-1.0f) + - `life_time` (_float – seconds_) – Shape's lifespan. By default it only lasts one frame. Set this to 0 for permanent shapes. +- **draw_line**(**self**, **begin**, **end**, **thickness**=0.1, **color**=(255,0,0), **life_time**=-1.0) Draws a line in between `begin` and `end`. - **Parameters:** - - `begin` (_[carla.Location](#carla.Location)_) – Point in the coordinate system where the line starts. - - `end` (_[carla.Location](#carla.Location)_) – Spot in the coordinate system where the line ends. - - `thickness` (_float_) – Density of the line. + - `begin` (_[carla.Location](#carla.Location) – meters_) – Point in the coordinate system where the line starts. + - `end` (_[carla.Location](#carla.Location) – meters_) – Spot in the coordinate system where the line ends. + - `thickness` (_float – meters_) – Density of the line. - `color` (_[carla.Color](#carla.Color)_) – RGB code to color the object. Red by default. - - `life_time` (_float_) – Lifespan in seconds for the shape. By default it only lasts one frame. Set this to 0 for permanent shapes. -- **draw_point**(**self**, **location**, **size**=0.1f, **color**=(255,0,0), **life_time**=-1.0f) + - `life_time` (_float – seconds_) – Shape's lifespan. By default it only lasts one frame. Set this to 0 for permanent shapes. +- **draw_point**(**self**, **location**, **size**=0.1, **color**=(255,0,0), **life_time**=-1.0) Draws a point `location`. - **Parameters:** - - `location` (_[carla.Location](#carla.Location)_) – Spot in the coordinate system to center the object. - - `size` (_float_) – Density of the point. + - `location` (_[carla.Location](#carla.Location) – meters_) – Spot in the coordinate system to center the object. + - `size` (_float – meters_) – Density of the point. - `color` (_[carla.Color](#carla.Color)_) – RGB code to color the object. Red by default. - - `life_time` (_float_) – Lifespan in seconds for the shape. By default it only lasts one frame. Set this to 0 for permanent shapes. -- **draw_string**(**self**, **location**, **text**, **draw_shadow**=False, **color**=(255,0,0), **life_time**=-1.0f) + - `life_time` (_float – seconds_) – Shape's lifespan. By default it only lasts one frame. Set this to 0 for permanent shapes. +- **draw_string**(**self**, **location**, **text**, **draw_shadow**=False, **color**=(255,0,0), **life_time**=-1.0) Draws a string in a given location of the simulation which can only be seen server-side. - **Parameters:** - - `location` (_[carla.Location](#carla.Location)_) – Spot in the simulation where the text will be centered. + - `location` (_[carla.Location](#carla.Location) – meters_) – Spot in the simulation where the text will be centered. - `text` (_str_) – Text intended to be shown in the world. - `draw_shadow` (_bool_) – Casts a shadow for the string that could help in visualization. It is disabled by default. - `color` (_[carla.Color](#carla.Color)_) – RGB code to color the string. Red by default. - - `life_time` (_float_) + - `life_time` (_float – seconds_) – Shape's lifespan. By default it only lasts one frame. Set this to 0 for permanent shapes. --- @@ -642,19 +642,19 @@ Quotient between current RPM and MaxRPM where the autonomous gear box should shi Class that contains geographical coordinates simulated data. The [carla.Map](#carla.Map) can convert simulation locations by using the tag in the OpenDRIVE file.

    Instance Variables

    -- **latitude** (_float_) +- **latitude** (_float – degrees_) North/South value of a point on the map. -- **longitude** (_float_) +- **longitude** (_float – degrees_) West/East value of a point on the map. -- **altitude** (_float_) +- **altitude** (_float – meters_) Height regarding ground level.

    Methods

    - **\__init__**(**self**, **latitude**=0.0, **longitude**=0.0, **altitude**=0.0) - **Parameters:** - - `latitude` (_float_) - - `longitude` (_float_) - - `altitude` (_float_) + - `latitude` (_float – degrees_) + - `longitude` (_float – degrees_) + - `altitude` (_float – meters_)
    Dunder methods
    - **\__eq__**(**self**, **other**=[carla.GeoLocation](#carla.GeoLocation)) @@ -667,11 +667,11 @@ Height regarding ground level.
    Inherited from _[carla.SensorData](#carla.SensorData)_

    Class that defines the Gnss data registered by a sensor.other.gnss. It essentially reports its position with the position of the sensor and an OpenDRIVE geo-reference.

    Instance Variables

    -- **altitude** (_float_) +- **altitude** (_float – meters_) Height regarding ground level. -- **latitude** (_float_) +- **latitude** (_float – degrees_) North/South value of a point on the map. -- **longitude** (_float_) +- **longitude** (_float – degrees_) West/East value of a point on the map.

    Methods

    @@ -685,12 +685,12 @@ West/East value of a point on the map.
    Inherited from _[carla.SensorData](#carla.SensorData)_

    Class that defines the data registered by a sensor.other.imu, regarding the sensor's transformation according to the current [carla.World](#carla.World). It essentially acts as accelerometer, gyroscope and compass.

    Instance Variables

    -- **accelerometer** (_[carla.Vector3D](#carla.Vector3D)_) -Linear acceleration in m/s^2. -- **compass** (_float_) -Orientation with regard to the North ((0.0, -1.0, 0.0) in Unreal Engine) in radians. -- **gyroscope** (_[carla.Vector3D](#carla.Vector3D)_) -Angular velocity in rad/sec. +- **accelerometer** (_[carla.Vector3D](#carla.Vector3D) – m*s2_) +Linear acceleration. +- **compass** (_float – radians_) +Orientation with regard to the North ([0.0, -1.0, 0.0] in Unreal Engine). +- **gyroscope** (_[carla.Vector3D](#carla.Vector3D) – rad/s_) +Angular velocity.

    Methods

    @@ -703,8 +703,8 @@ Angular velocity in rad/sec.
    Inherited from _[carla.SensorData](#carla.SensorData)_

    Class that defines an image of 32-bit BGRA colors that will be used as initial data retrieved by camera sensors. There are different camera sensors (currently three, RGB, depth and semantic segmentation) and each of these makes different use for the images. Learn more about them [here](ref_sensors.md).

    Instance Variables

    -- **fov** (_float_) -Horizontal field of view of the image in degrees. +- **fov** (_float – degrees_) +Horizontal field of view of the image. - **height** (_int_) Image height in pixels. - **width** (_int_) @@ -759,11 +759,11 @@ Landmarks will be accessed by [carla.Waypoint](#carla.Waypoint) objects trying t - **road_id** (_int_) The OpenDRIVE ID of the road where this landmark is defined. Due to OpenDRIVE road definitions, this road may be different from the road the landmark is currently affecting. It is mostly the case in junctions where the road diverges in different routes. Example: a traffic light is defined in one of the divergent roads in a junction, but it affects all the possible routes. -- **distance** (_float_) +- **distance** (_float – meters_) Distance between the landmark and the waypoint creating the object (querying `get_landmarks` or `get_landmarks_of_type`). -- **s** (_float_) +- **s** (_float – meters_) Distance where the landmark is positioned along the geometry of the road `road_id`. -- **t** (_float_) +- **t** (_float – meters_) Lateral distance where the landmark is positioned from the edge of the road `road_id`. - **id** (_str_) Unique ID of the landmark in the OpenDRIVE file. @@ -771,9 +771,9 @@ Unique ID of the landmark in the OpenDRIVE file. Name of the landmark in the in the OpenDRIVE file. - **is_dynamic** (_bool_) Indicates if the landmark has state changes over time such as traffic lights. -- **orientation** (_[carla.LandmarkOrientation](#carla.LandmarkOrientation)_) +- **orientation** (_[carla.LandmarkOrientation](#carla.LandmarkOrientation) – degrees_) Indicates which lanes the landmark is facing towards to. -- **z_offset** (_float_) +- **z_offset** (_float – meters_) Height where the landmark is placed. - **country** (_str_) Country code where the landmark is defined (default to OpenDRIVE is Germany 2017). @@ -785,18 +785,18 @@ Subtype identificator of the landmark according to the country code. Value printed in the signal (e.g. speed limit, maximum weight, etc). - **unit** (_str_) Units of measurement for the attribute `value`. -- **height** (_float_) +- **height** (_float – meters_) Total height of the signal. -- **width** (_float_) +- **width** (_float – meters_) Total width of the signal. - **text** (_str_) Additional text in the signal. -- **h_offset** (_float_) +- **h_offset** (_float – meters_) Orientation offset of the signal relative to the the definition of `road_id` at `s` in OpenDRIVE. -- **pitch** (_float_) -Pitch rotation of the signal. +- **pitch** (_float – meters_) +Pitch rotation (Y-axis) of the signal. - **roll** (_float_) -Roll rotation of the signal. +Roll rotation (X-axis) of the signal. - **waypoint** (_[carla.Waypoint](#carla.Waypoint)_) A waypoint placed in the lane of the one that made the query and at the `s` of the landmark. It is the first waypoint for which the landmark will be effective. - **transform** (_[carla.Transform](#carla.Transform)_) @@ -1015,10 +1015,10 @@ Every type except for NONE. Data contained inside a [carla.LidarMeasurement](#carla.LidarMeasurement). Each of these represents one of the points in the cloud with its location and its asociated intensity.

    Instance Variables

    -- **point** (_[carla.Location](#carla.Location)_) +- **point** (_[carla.Location](#carla.Location) – meters_) Point in xyz coordinates. - **intensity** (_float_) -Computed intensity for this point. +Computed intensity for this point as a scalar value between [0.0 , 1.0].

    Methods

    @@ -1033,8 +1033,8 @@ Computed intensity for this point.

    Instance Variables

    - **channels** (_int_) Number of lasers shot. -- **horizontal_angle** (_float_) -Horizontal angle the LIDAR is rotated at the time of the measurement (in radians). +- **horizontal_angle** (_float – radians_) +Horizontal angle the LIDAR is rotated at the time of the measurement. - **raw_data** (_bytes_) Received list of 4D points. Each point consists of [x,y,z] coordiantes plus the intensity computed for that point. @@ -1068,11 +1068,11 @@ Lights are automatically turned on when the simulator enters night mode (sun alt Color of the light. - **id** (_int_) Identifier of the light. -- **intensity** (_float_) -Intensity of the light in lumens. +- **intensity** (_float – lumens_) +Intensity of the light. - **is_on** (_bool_) Switch of the light. It is __True__ when the light is on. When the night mode starts, this is set to __True__. -- **location** (_[carla.Location](#carla.Location)_) +- **location** (_[carla.Location](#carla.Location) – meters_) Position of the light. - **light_group** (_[carla.LightGroup](#carla.LightGroup)_) Group the light belongs to. @@ -1093,7 +1093,7 @@ Changes the color of the light to `color`. - **set_intensity**(**self**, **intensity**) Changes the intensity of the light to `intensity`. - **Parameters:** - - `intensity` (_float_) + - `intensity` (_float – lumens_) - **set_light_group**(**self**, **light_group**) Changes the light to the group `light_group`. - **Parameters:** @@ -1156,7 +1156,7 @@ Returns a list with the colors of every element in `lights`. Returns a list with the intensity of every element in `lights`. - **Parameters:** - `lights` (_list([carla.Light](#carla.Light))_) – List of lights to be queried. - - **Return:** _list(float)_ + - **Return:** _list(float) – lumens_ - **Setter:** _[carla.LightManager.set_intensity](#carla.LightManager.set_intensity)_ - **get_light_group**(**self**, **lights**) Returns a list with the group of every element in `lights`. @@ -1202,13 +1202,13 @@ Changes the color of each element in `lights` to the corresponding in `colors`. Changes the intensity of every element in `lights` to `intensity`. - **Parameters:** - `lights` (_list([carla.Light](#carla.Light))_) – List of lights to be changed. - - `intensity` (_float_) – Intensity to be applied. + - `intensity` (_float – lumens_) – Intensity to be applied. - **Getter:** _[carla.LightManager.get_intensity](#carla.LightManager.get_intensity)_ - **set_intensities**(**self**, **lights**, **intensities**) Changes the intensity of each element in `lights` to the corresponding in `intensities`. - **Parameters:** - `lights` (_list([carla.Light](#carla.Light))_) – List of lights to be changed. - - `intensities` (_list(float)_) – List of intensities to be applied. + - `intensities` (_list(float) – lumens_) – List of intensities to be applied. - **set_light_group**(**self**, **lights**, **light_group**) Changes the group of every element in `lights` to `light_group`. - **Parameters:** @@ -1238,8 +1238,8 @@ Changes the state of the attributes of each element in `lights` to the correspon This class represents all the light variables except the identifier and the location, which are should to be static. Using this class allows to manage all the parametrization of the light in one call.

    Instance Variables

    -- **intensity** (_float_) -Intensity of a light in lumens. +- **intensity** (_float – lumens_) +Intensity of a light. - **color** (_[carla.Color](#carla.Color)_) Color of a light. - **group** (_[carla.LightGroup](#carla.LightGroup)_) @@ -1250,7 +1250,7 @@ Switch of a light. It is __True__ when the light is on.

    Methods

    - **\__init__**(**self**, **intensity**=0.0, **color**=[carla.Color](#carla.Color)(), **group**=[carla.LightGroup.None](#carla.LightGroup.None), **active**=False) - **Parameters:** - - `intensity` (_float_) – Intensity of the light in lumens. Default is `0.0`. + - `intensity` (_float – lumens_) – Intensity of the light. Default is `0.0`. - `color` (_[carla.Color](#carla.Color)_) – Color of the light. Default is black. - `group` (_[carla.LightGroup](#carla.LightGroup)_) – Group the light belongs to. Default is the generic group `None`. - `active` (_bool_) – Swith of the light. Default is `False`, light is off. @@ -1261,12 +1261,12 @@ Switch of a light. It is __True__ when the light is on.
    Inherited from _[carla.Vector3D](#carla.Vector3D)_

    Represents a spot in the world.

    Instance Variables

    -- **x** (_float_) -Distance in meters from origin to spot on X axis. -- **y** (_float_) -Distance in meters from origin to spot on Y axis. -- **z** (_float_) -Distance in meters from origin to spot on Z axis. +- **x** (_float – meters_) +Distance from origin to spot on X axis. +- **y** (_float – meters_) +Distance from origin to spot on Y axis. +- **z** (_float – meters_) +Distance from origin to spot on Z axis.

    Methods

    - **\__init__**(**self**, **x**=0.0, **y**=0.0, **z**=0.0) @@ -1275,10 +1275,10 @@ Distance in meters from origin to spot on Z axis. - `y` (_float_) - `z` (_float_) - **distance**(**self**, **location**) -Returns Euclidean distance in meters from this location to another one. +Returns Euclidean distance from this location to another one. - **Parameters:** - `location` (_[carla.Location](#carla.Location)_) – The other point to compute the distance with. - - **Return:** _float_ + - **Return:** _float – meters_
    Dunder methods
    - **\__eq__**(**self**, **other**=[carla.Location](#carla.Location)) @@ -1310,7 +1310,7 @@ Constructor for this class. Though a map is automatically generated when initial - **generate_waypoints**(**self**, **distance**) Returns a list of waypoints with a certain distance between them for every lane and centered inside of it. Waypoints are not listed in any particular order. Remember that waypoints closer than 2cm within the same road, section and lane will have the same identificator. - **Parameters:** - - `distance` (_float_) – Approximate distance between waypoints. + - `distance` (_float – meters_) – Approximate distance between waypoints. - **Return:** _list([carla.Waypoint](#carla.Waypoint))_ - **save_to_disk**(**self**, **path**) Saves the .xodr OpenDRIVE file of the current map to disk. @@ -1354,7 +1354,7 @@ Returns a list of tuples describing a minimal graph of the topology of the OpenD Returns a waypoint that can be located in an exact location or translated to the center of the nearest lane. Said lane type can be defined using flags such as `LaneType.Driving & LaneType.Shoulder`. The method will return None if the waypoint is not found, which may happen only when trying to retrieve a waypoint for an exact location. That eases checking if a point is inside a certain road, as otherwise, it will return the corresponding waypoint. - **Parameters:** - - `location` (_[carla.Location](#carla.Location)_) – Location used as reference for the [carla.Waypoint](#carla.Waypoint). + - `location` (_[carla.Location](#carla.Location) – meters_) – Location used as reference for the [carla.Waypoint](#carla.Waypoint). - `project_to_road` (_bool_) – If **True**, the waypoint will be at the center of the closest lane. This is the default setting. If **False**, the waypoint will be exactly in `location`. None means said location does not belong to a road. - `lane_type` (_[carla.LaneType](#carla.LaneType)_) – Limits the search for nearest lane to one or various lane types that can be flagged. - **Return:** _[carla.Waypoint](#carla.Waypoint)_ @@ -1363,7 +1363,7 @@ Returns a waypoint if all the parameters passed are correct. Otherwise, returns - **Parameters:** - `road_id` (_int_) – ID of the road to get the waypoint. - `lane_id` (_int_) – ID of the lane to get the waypoint. - - `s` (_float_) – Specify the length from the road start. + - `s` (_float – meters_) – Specify the length from the road start. - **Return:** _[carla.Waypoint](#carla.Waypoint)_
    Dunder methods
    @@ -1379,7 +1379,7 @@ Returns a waypoint if all the parameters passed are correct. Otherwise, returns The actor the sensor is attached to. - **other_actor** (_[carla.Actor](#carla.Actor)_) The actor or object considered to be an obstacle. -- **distance** (_float_) +- **distance** (_float – meters_) Distance between `actor` and `other`.

    Methods

    @@ -1429,13 +1429,13 @@ Helper class that contains the parameterization that will be used by [carla.Osm2

    Instance Variables

    - **use_offsets** (_bool_) Enables the use of offset for the conversion. The offset will move the origin position of the map. Default value is __False__. -- **offset_x** (_float_) +- **offset_x** (_float – meters_) Offset in the X axis. Default value is __0.0__. -- **offset_y** (_float_) +- **offset_y** (_float – meters_) Offset in the Y axis. Default value is __0.0__. -- **default_lane_width** (_float_) +- **default_lane_width** (_float – meters_) Width of the lanes described in the resulting XODR map. Default value is __4.0__. -- **elevation_layer_height** (_float_) +- **elevation_layer_height** (_float – meters_) Defines the height separating two different [OpenStreetMap layers](https://wiki.openstreetmap.org/wiki/Key:layer). Default value is __0.0__. --- @@ -1444,14 +1444,14 @@ Defines the height separating two different [OpenStreetMap layers](https://wiki. Data contained inside a [carla.RadarMeasurement](#carla.RadarMeasurement). Each of these represents one of the points in the cloud that a sensor.other.radar registers and contains the distance, angle and velocity in relation to the radar.

    Instance Variables

    -- **altitude** (_float_) -Altitude angle of the detection in radians. -- **azimuth** (_float_) -Azimuth angle of the detection in radians. -- **depth** (_float_) -Distance in meters from the sensor to the detection position. -- **velocity** (_float_) -The velocity of the detected object towards the sensor in m/s. +- **altitude** (_float – radians_) +Altitude angle of the detection. +- **azimuth** (_float – radians_) +Azimuth angle of the detection. +- **depth** (_float – meters_) +Distance from the sensor to the detection position. +- **velocity** (_float – m/s_) +The velocity of the detected object towards the sensor.

    Methods

    @@ -1488,34 +1488,34 @@ Class that represents a 3D rotation and therefore, an orientation in space. ![UE4_Rotation](https://d26ilriwvtzlb.cloudfront.net/8/83/BRMC_9.jpg) _Unreal Engine's standard (from [UE4 docs](https://wiki.unrealengine.com/Blueprint_Rotating_Movement_Component))_.

    Instance Variables

    -- **pitch** (_float_) -Degrees around the Y-axis. -- **yaw** (_float_) -Degrees around the Z-axis. -- **roll** (_float_) -Degrees around the X-axis. +- **pitch** (_float – degrees_) +Y-axis rotation angle. +- **yaw** (_float – degrees_) +Z-axis rotation angle. +- **roll** (_float – degrees_) +X-axis rotation angle.

    Methods

    - **\__init__**(**self**, **pitch**=0.0, **yaw**=0.0, **roll**=0.0) - **Parameters:** - - `pitch` (_float_) – Y rotation in degrees. - - `yaw` (_float_) – Z rotation in degrees. - - `roll` (_float_) – X rotation in degrees. + - `pitch` (_float – degrees_) – Y-axis rotation angle. + - `yaw` (_float – degrees_) – Z-axis rotation angle. + - `roll` (_float – degrees_) – X-axis rotation angle.
    Getters
    - **get_forward_vector**(**self**) -Computes the vector pointing forward according to the orientation of each axis. +Computes the vector pointing forward according to the rotation of the object. - **Return:** _[carla.Vector3D](#carla.Vector3D)_ - **get_right_vector**(**self**) -Computes the vector pointing to the right according to the orientation of each axis. +Computes the vector pointing to the right according to the rotation of the object. - **Return:** _[carla.Vector3D](#carla.Vector3D)_ - **get_up_vector**(**self**) -Computes the vector pointing upwards according to the orientation of each axis. +Computes the vector pointing upwards according to the rotation of the object. - **Return:** _[carla.Vector3D](#carla.Vector3D)_
    Dunder methods
    - **\__eq__**(**self**, **other**=[carla.Rotation](#carla.Rotation)) -Returns __True__ if both rotations represent the same orientation of each axis. +Returns __True__ if both rotations represent the same orientation for every axis. - **Return:** _bool_ - **\__ne__**(**self**, **other**=[carla.Rotation](#carla.Rotation)) Returns __True__ if both rotations represent the same orientation for every axis. @@ -1723,14 +1723,14 @@ Sets the log level. Data contained inside a [carla.SemanticLidarMeasurement](#carla.SemanticLidarMeasurement). Each of these represents one of the points in the cloud with its location, the cosine of the incident angle, index of the object hit, and its semantic tag.

    Instance Variables

    -- **point** (_[carla.Location](#carla.Location)_) +- **point** (_[carla.Location](#carla.Location) – meters_) [x,y,z] coordinates of the point. - **cos_inc_angle** (_float_) Cosine of the incident angle between the ray, and the normal of the hit object. - **object_idx** (_uint_) -Carla index of the hit actor. +[CARLA index](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/ref_sensors/#semantic-segmentation-camera) of the hit actor. - **object_tag** (_uint_) -Semantic tag of the hit component. +[Semantic tag](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/ref_sensors/#semantic-segmentation-camera) of the hit component.

    Methods

    @@ -1823,7 +1823,7 @@ Base class for all the objects containing data generated by a [carla.Sensor](#ca

    Instance Variables

    - **frame** (_int_) Frame count when the data was generated. -- **timestamp** (_float_) +- **timestamp** (_float – seconds_) Simulation-time when the data was generated. - **transform** (_[carla.Transform](#carla.Transform)_) Sensor's transform when the data was generated. @@ -1836,20 +1836,20 @@ Class that contains time information for simulated data. This information is aut

    Instance Variables

    - **frame** (_int_) The number of frames elapsed since the simulator was launched. -- **elapsed_seconds** (_float_) +- **elapsed_seconds** (_float – seconds_) Simulated seconds elapsed since the beginning of the current episode. -- **delta_seconds** (_float_) +- **delta_seconds** (_float – seconds_) Simulated seconds elapsed since the previous frame. -- **platform_timestamp** (_float_) +- **platform_timestamp** (_float – seconds_) Time register of the frame at which this measurement was taken given by the OS in seconds.

    Methods

    - **\__init__**(**self**, **frame**, **elapsed_seconds**, **delta_seconds**, **platform_timestamp**) - **Parameters:** - `frame` (_int_) - - `elapsed_seconds` (_float_) - - `delta_seconds` (_float_) - - `platform_timestamp` (_float_) + - `elapsed_seconds` (_float – seconds_) + - `delta_seconds` (_float – seconds_) + - `platform_timestamp` (_float – seconds_)
    Dunder methods
    - **\__eq__**(**self**, **other**=[carla.Timestamp](#carla.Timestamp)) @@ -1883,7 +1883,7 @@ _
    Getters
    - **get_elapsed_time**(**self**) The client returns the time in seconds since current light state started according to last tick. The method does not call the simulator. - - **Return:** _float_ + - **Return:** _float – seconds_ - **get_group_traffic_lights**(**self**) Returns all traffic lights in the group this one belongs to. - **Return:** _list([carla.TrafficLight](#carla.TrafficLight))_ @@ -1897,16 +1897,16 @@ The client returns the state of the traffic light according to last tick. The me - **Return:** _[carla.TrafficLightState](#carla.TrafficLightState)_ - **Setter:** _[carla.TrafficLight.set_state](#carla.TrafficLight.set_state)_ - **get_green_time**(**self**) -The client returns the seconds set for the traffic light to be green according to last tick. The method does not call the simulator. - - **Return:** _float_ +The client returns the time set for the traffic light to be green, according to last tick. The method does not call the simulator. + - **Return:** _float – seconds_ - **Setter:** _[carla.TrafficLight.set_green_time](#carla.TrafficLight.set_green_time)_ - **get_red_time**(**self**) -The client returns the seconds set for the traffic light to be red according to last tick. The method does not call the simulator. - - **Return:** _float_ +The client returns the time set for the traffic light to be red, according to last tick. The method does not call the simulator. + - **Return:** _float – seconds_ - **Setter:** _[carla.TrafficLight.set_red_time](#carla.TrafficLight.set_red_time)_ - **get_yellow_time**(**self**) -The client returns the the seconds set for the traffic light to be yellow according to last tick. The method does not call the simulator. - - **Return:** _float_ +The client returns the time set for the traffic light to be yellow, according to last tick. The method does not call the simulator. + - **Return:** _float – seconds_ - **Setter:** _[carla.TrafficLight.set_yellow_time](#carla.TrafficLight.set_yellow_time)_
    Setters
    @@ -1917,17 +1917,17 @@ Sets a given state to a traffic light actor. - **Getter:** _[carla.TrafficLight.get_state](#carla.TrafficLight.get_state)_ - **set_green_time**(**self**, **green_time**) - **Parameters:** - - `green_time` (_float_) – Sets a given time (in seconds) for the green light to be active. + - `green_time` (_float – seconds_) – Sets a given time for the green light to be active. - **Getter:** _[carla.TrafficLight.get_green_time](#carla.TrafficLight.get_green_time)_ - **set_red_time**(**self**, **red_time**) -Sets a given time (in seconds) for the red state to be active. +Sets a given time for the red state to be active. - **Parameters:** - - `red_time` (_float_) + - `red_time` (_float – seconds_) - **Getter:** _[carla.TrafficLight.get_red_time](#carla.TrafficLight.get_red_time)_ - **set_yellow_time**(**self**, **yellow_time**) -Sets a given time (in seconds) for the yellow light to be active. +Sets a given time for the yellow light to be active. - **Parameters:** - - `yellow_time` (_float_) + - `yellow_time` (_float – seconds_) - **Getter:** _[carla.TrafficLight.get_yellow_time](#carla.TrafficLight.get_yellow_time)_
    Dunder methods
    @@ -1967,7 +1967,7 @@ Tunes on/off collisions between a vehicle and another specific actor. In order t Sets the minimum distance in meters that a vehicle has to keep with the others. The distance is in meters and will affect the minimum moving distance. It is computed from front to back of the vehicle objects. - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor)_) – Vehicle whose minimum distance is being changed. - - `distance` (_float_) – Meters between both vehicles. + - `distance` (_float – meters_) – Meters between both vehicles. - **force_lane_change**(**self**, **actor**, **direction**) Forces a vehicle to change either to the lane on its left or right, if existing, as indicated in `direction`. This method applies the lane change no matter what, disregarding possible collisions. - **Parameters:** @@ -1976,7 +1976,7 @@ Forces a vehicle to change either to the lane on its left or right, if existing, - **global_distance_to_leading_vehicle**(**self**, **distance**) Sets the minimum distance in meters that vehicles have to keep with the rest. The distance is in meters and will affect the minimum moving distance. It is computed from center to center of the vehicle objects. - **Parameters:** - - `distance` (_float_) – Meters between vehicles. + - `distance` (_float – meters_) – Meters between vehicles. - **global_percentage_speed_difference**(**self**, **percentage**) Sets the difference the vehicle's intended speed and its current speed limit. Speed limits can be exceeded by setting the `perc` to a negative value. Default is 30. Exceeding a speed limit can be done using negative percentages. @@ -2019,7 +2019,7 @@ Enables or disables the hybrid physics mode. In this mode, vehicle's farther tha - **set_hybrid_mode_radius**(**self**, **r**=70.0) With hybrid physics on, changes the radius of the area of influence where physics are enabled. - **Parameters:** - - `r` (_float_) – New radius where physics are enabled. + - `r` (_float – meters_) – New radius where physics are enabled. --- @@ -2053,13 +2053,13 @@ Translates a 3D point from local to global coordinates using the current transfo
    Getters
    - **get_forward_vector**(**self**) -Computes a forward vector using its rotation. +Computes a forward vector using the rotation of the object. - **Return:** _[carla.Vector3D](#carla.Vector3D)_ - **get_right_vector**(**self**) -Computes a right vector using its rotation. +Computes a right vector using the rotatio of the object. - **Return:** _[carla.Vector3D](#carla.Vector3D)_ - **get_up_vector**(**self**) -Computes an up vector using its rotation. +Computes an up vector using the rotation of the object. - **Return:** _[carla.Vector3D](#carla.Vector3D)_ - **get_matrix**(**self**) Computes the 4-matrix representation of the transformation. @@ -2182,7 +2182,7 @@ The simulator returns the last physics control applied to this vehicle. - **Warning:** _This function does call the simulator to retrieve the value._ - **get_speed_limit**(**self**) The client returns the speed limit affecting this vehicle according to last tick (it does not call the simulator). The speed limit is updated when passing by a speed limit signal, so a vehicle might have none right after spawning. - - **Return:** _float_ + - **Return:** _float – m/s_ - **get_traffic_light**(**self**) Retrieves the traffic light actor affecting this vehicle (if any) according to last tick. The method does not call the simulator. - **Return:** _[carla.TrafficLight](#carla.TrafficLight)_ @@ -2229,9 +2229,9 @@ States which gear is the vehicle running on.

    Methods

    - **\__init__**(**self**, **throttle**=0.0, **steer**=0.0, **brake**=0.0, **hand_brake**=False, **reverse**=False, **manual_gear_shift**=False, **gear**=0) - **Parameters:** - - `throttle` (_float_) - - `steer` (_float_) - - `brake` (_float_) + - `throttle` (_float_) – Scalar value between [0.0,1.0]. + - `steer` (_float_) – Scalar value between [0.0,1.0]. + - `brake` (_float_) – Scalar value between [0.0,1.0]. - `hand_brake` (_bool_) - `reverse` (_bool_) - `manual_gear_shift` (_bool_) @@ -2276,7 +2276,7 @@ Summarizes the parameters that will be used to simulate a [carla.Vehicle](#carla Curve that indicates the torque measured in Nm for a specific RPM of the vehicle's engine. - **max_rpm** (_float_) The maximum RPM of the vehicle's engine. -- **moi** (_float_) +- **moi** (_float – kg*m2_) The moment of inertia of the vehicle's engine. - **damping_rate_full_throttle** (_float_) Damping ratio when the throttle is maximum. @@ -2286,20 +2286,20 @@ Damping ratio when the throttle is zero with clutch engaged. Damping ratio when the throttle is zero with clutch disengaged. - **use_gear_autobox** (_bool_) If True, the vehicle will have an automatic transmission. -- **gear_switch_time** (_float_) +- **gear_switch_time** (_float – seconds_) Switching time between gears. -- **clutch_strength** (_float_) -The clutch strength of the vehicle in Kgm^2/s. +- **clutch_strength** (_float – kg*m2/s_) +Clutch strength of the vehicle. - **final_ratio** (_float_) -The fixed ratio from transmission to wheels. +Fixed ratio from transmission to wheels. - **forward_gears** (_list([carla.GearPhysicsControl](#carla.GearPhysicsControl))_) List of objects defining the vehicle's gears. -- **mass** (_float_) -The mass of the vehicle in Kg. +- **mass** (_float – kilograms_) +Mass of the vehicle. - **drag_coefficient** (_float_) Drag coefficient of the vehicle's chassis. -- **center_of_mass** (_[carla.Vector3D](#carla.Vector3D)_) -The center of mass of the vehicle. +- **center_of_mass** (_[carla.Vector3D](#carla.Vector3D) – meters_) +Center of mass of the vehicle. - **steering_curve** (_list([carla.Vector2D](#carla.Vector2D))_) Curve that indicates the maximum steering for a specific forward speed. - **wheels** (_list([carla.WheelPhysicsControl](#carla.WheelPhysicsControl))_) @@ -2311,13 +2311,13 @@ VehiclePhysicsControl constructor. - **Parameters:** - `torque_curve` (_list([carla.Vector2D](#carla.Vector2D))_) - `max_rpm` (_float_) - - `moi` (_float_) + - `moi` (_float – kg*m2_) - `damping_rate_full_throttle` (_float_) - `damping_rate_zero_throttle_clutch_engaged` (_float_) - `damping_rate_zero_throttle_clutch_disengaged` (_float_) - `use_gear_autobox` (_bool_) - - `gear_switch_time` (_float_) - - `clutch_strength` (_float_) + - `gear_switch_time` (_float – seconds_) + - `clutch_strength` (_float – kg*m2/s_) - `final_ratio` (_float_) - `forward_gears` (_list([carla.GearPhysicsControl](#carla.GearPhysicsControl))_) - `drag_coefficient` (_float_) @@ -2366,7 +2366,7 @@ The client returns the control applied to this walker during last tick. The meth - **go_to_location**(**self**, **destination**) Sets the destination that the pedestrian will reach. - **Parameters:** - - `destination` (_[carla.Location](#carla.Location)_) + - `destination` (_[carla.Location](#carla.Location) – meters_) - **start**(**self**) Enables AI control for its parent walker. - **stop**(**self**) @@ -2376,7 +2376,7 @@ Disables AI control for its parent walker.
    - **set_max_speed**(**self**, **speed**=1.4) Sets a speed for the walker in meters per second. - **Parameters:** - - `speed` (_float_) – speed in m/s. An easy walking speed is set by default. + - `speed` (_float – m/s_) – An easy walking speed is set by default.
    Dunder methods
    - **\__str__**(**self**) @@ -2392,7 +2392,7 @@ List of tuples where the first value is the bone's name and the second value sto

    Methods

    - **\__init__**(**self**, **list(name,transform)**) -Intializes an object containing moves to be applied on tick. These are listed with the name of the bone and the transform that will be applied to it. +Initializes an object containing moves to be applied on tick. These are listed with the name of the bone and the transform that will be applied to it. - **Parameters:** - `list(name,transform)` (_tuple_) @@ -2409,7 +2409,7 @@ This class defines specific directions that can be commanded to a [carla.Walker]

    Instance Variables

    - **direction** (_[carla.Vector3D](#carla.Vector3D)_) Vector using global coordinates that will correspond to the direction of the walker. -- **speed** (_float_) +- **speed** (_float – m/s_) A scalar value to control the walker's speed. - **jump** (_bool_) If True, the walker will perform a jump. @@ -2464,23 +2464,23 @@ The left lane marking information based on the direction of the Waypoint. Returns a list of waypoints at a certain approximate `distance` from the current one. It takes into account the road and its possible deviations without performing any lane change and returns one waypoint per option. The list may be empty if the lane is not connected to any other at the specified distance. - **Parameters:** - - `distance` (_float_) – The approximate distance where to get the next waypoints. + - `distance` (_float – meters_) – The approximate distance where to get the next waypoints. - **Return:** _list([carla.Waypoint](#carla.Waypoint))_ - **next_until_lane_end**(**self**, **distance**) Returns a list of waypoints from this to the end of the lane separated by a certain `distance`. - **Parameters:** - - `distance` (_float_) – The approximate distance between waypoints. + - `distance` (_float – meters_) – The approximate distance between waypoints. - **Return:** _list([carla.Waypoint](#carla.Waypoint))_ - **previous**(**self**, **distance**) This method does not return the waypoint previously visited by an actor, but a list of waypoints at an approximate `distance` but in the opposite direction of the lane. Similarly to **next()**, it takes into account the road and its possible deviations without performing any lane change and returns one waypoint per option. The list may be empty if the lane is not connected to any other at the specified distance. - **Parameters:** - - `distance` (_float_) – The approximate distance where to get the previous waypoints. + - `distance` (_float – meters_) – The approximate distance where to get the previous waypoints. - **Return:** _list([carla.Waypoint](#carla.Waypoint))_ - **previous_until_lane_start**(**self**, **distance**) Returns a list of waypoints from this to the start of the lane separated by a certain `distance`. - **Parameters:** - - `distance` (_float_) – The approximate distance between waypoints. + - `distance` (_float – meters_) – The approximate distance between waypoints. - **Return:** _list([carla.Waypoint](#carla.Waypoint))_
    Getters
    @@ -2490,13 +2490,13 @@ If the waypoint belongs to a junction this function returns the asociated juncti - **get_landmarks**(**self**, **distance**, **stop_at_junction**=False) Returns a list of landmarks in the road from the current waypoint until the specified distance. - **Parameters:** - - `distance` (_float_) – The maximum distance to search for landmarks from the current waypoint. + - `distance` (_float – meters_) – The maximum distance to search for landmarks from the current waypoint. - `stop_at_junction` (_bool_) – Enables or disables the landmark search through junctions. - **Return:** _list([carla.Landmark](#carla.Landmark))_ - **get_landmarks_of_type**(**self**, **distance**, **type**, **stop_at_junction**=False) Returns a list of landmarks in the road of a specified type from the current waypoint until the specified distance. - **Parameters:** - - `distance` (_float_) – The maximum distance to search for landmarks from the current waypoint. + - `distance` (_float – meters_) – The maximum distance to search for landmarks from the current waypoint. - `type` (_str_) – The type of landmarks to search. - `stop_at_junction` (_bool_) – Enables or disables the landmark search through junctions. - **Return:** _list([carla.Landmark](#carla.Landmark))_ @@ -2527,14 +2527,14 @@ Rain intensity values range from 0 to 100, being 0 none at all and 100 a heavy r Determines the creation of puddles. Values range from 0 to 100, being 0 none at all and 100 a road completely capped with water. Puddles are created with static noise, meaning that they will always appear at the same locations. - **wind_intensity** (_float_) Controls the strenght of the wind with values from 0, no wind at all, to 100, a strong wind. The wind does affect rain direction and leaves from trees, so this value is restricted to avoid animation issues. -- **sun_azimuth_angle** (_float_) -The azimuth angle of the sun in degrees. Values range from 0 to 360. Zero is an origin point in a sphere determined by Unreal Engine. -- **sun_altitude_angle** (_float_) -Altitude angle of the sun in degrees. Values range from -90 to 90 corresponding to midnight and midday each. +- **sun_azimuth_angle** (_float – degrees_) +The azimuth angle of the sun. Values range from 0 to 360. Zero is an origin point in a sphere determined by Unreal Engine. +- **sun_altitude_angle** (_float – degrees_) +Altitude angle of the sun. Values range from -90 to 90 corresponding to midnight and midday each. - **fog_density** (_float_) Fog concentration or thickness. It only affects the RGB camera sensor. Values range from 0 to 100. -- **fog_distance** (_float_) -Fog start distance (in meters). Values range from 0 to infinite. +- **fog_distance** (_float – meters_) +Fog start distance. Values range from 0 to infinite. - **wetness** (_float_) Wetness intensity. It only affects the RGB camera sensor. Values range from 0 to 100. - **fog_falloff** (_float_) @@ -2548,10 +2548,10 @@ Method to initialize an object defining weather conditions. This class has some - `precipitation` (_float_) – 0 is no rain at all, 100 a heavy rain. - `precipitation_deposits` (_float_) – 0 means no puddles on the road, 100 means roads completely capped by rain. - `wind_intensity` (_float_) – 0 is calm, 100 a strong wind. - - `sun_azimuth_angle` (_float_) – 0 is an arbitrary North, 180 its corresponding South. - - `sun_altitude_angle` (_float_) – 90 is midday, -90 is midnight. + - `sun_azimuth_angle` (_float – degrees_) – 0 is an arbitrary North, 180 its corresponding South. + - `sun_altitude_angle` (_float – degrees_) – 90 is midday, -90 is midnight. - `fog_density` (_float_) – Concentration or thickness of the fog, from 0 to 100. - - `fog_distance` (_float_) – Distance where the fog starts in meters. + - `fog_distance` (_float – meters_) – Distance where the fog starts in meters. - `wetness` (_float_) – Humidity percentages of the road, from 0 to 100. - `fog_falloff` (_float_) – Density (specific mass) of the fog, from 0 to infinity. - **Note:** _ClearNoon, CloudyNoon, WetNoon, WetCloudyNoon, SoftRainNoon, MidRainyNoon, HardRainNoon, ClearSunset, CloudySunset, WetSunset, WetCloudySunset, SoftRainSunset, MidRainSunset, HardRainSunset. @@ -2576,14 +2576,14 @@ Class that defines specific physical parameters for wheel objects that will be p A scalar value that indicates the friction of the wheel. - **damping_rate** (_float_) Damping rate of the wheel. -- **max_steer_angle** (_float_) -Maximum angle in degrees that the wheel can steer. -- **radius** (_float_) -Radius of the wheel in centimeters. -- **max_brake_torque** (_float_) -Maximum brake torque in Nm. -- **max_handbrake_torque** (_float_) -Maximum handbrake torque in Nm. +- **max_steer_angle** (_float – degrees_) +Maximum angle that the wheel can steer. +- **radius** (_float – centimeters_) +Radius of the wheel. +- **max_brake_torque** (_float – N*m_) +Maximum brake torque. +- **max_handbrake_torque** (_float – N*m_) +Maximum handbrake torque. - **position** (_[carla.Vector3D](#carla.Vector3D)_) World position of the wheel. This is a read-only parameter. @@ -2592,11 +2592,11 @@ World position of the wheel. This is a read-only parameter. - **Parameters:** - `tire_friction` (_float_) - `damping_rate` (_float_) - - `max_steer_angle` (_float_) - - `radius` (_float_) - - `max_brake_torque` (_float_) - - `max_handbrake_torque` (_float_) - - `position` (_[carla.Vector3D](#carla.Vector3D)_) + - `max_steer_angle` (_float – degrees_) + - `radius` (_float – centimerers_) + - `max_brake_torque` (_float – N*m_) + - `max_handbrake_torque` (_float – N*m_) + - `position` (_[carla.Vector3D](#carla.Vector3D) – meters_)
    Dunder methods
    - **\__eq__**(**self**, **other**=[carla.WheelPhysicsControl](#carla.WheelPhysicsControl)) @@ -2632,12 +2632,12 @@ Stops the callback for `callback_id` started with **on_tic - **tick**(**self**, **seconds**=10.0) This method only has effect on synchronous mode, when both client and server move together. The client tells the server when to step to the next frame and returns the id of the newly started frame. - **Parameters:** - - `seconds` (_float_) – Maximum time in seconds the server should wait for a tick. It is set to 10.0 by default. + - `seconds` (_float – seconds_) – Maximum time the server should wait for a tick. It is set to 10.0 by default. - **Return:** _int_ - **wait_for_tick**(**self**, **seconds**=10.0) The client tells the server to pause the simulation until a **World.tick()** is received. - **Parameters:** - - `seconds` (_float_) – Maximum time in seconds the server should wait for a tick. It is set to 10.0 by default. + - `seconds` (_float – seconds_) – Maximum time the server should wait for a tick. It is set to 10.0 by default. - **Return:** _[carla.WorldSnapshot](#carla.WorldSnapshot)_ - **spawn_actor**(**self**, **blueprint**, **transform**, **attach_to**=None, **attachment**=Rigid) The method will create, return and spawn an actor into the world. The actor will need an available blueprint to be created and a transform (location and rotation). It can also be attached to a parent with a certain attachment type. @@ -2743,7 +2743,7 @@ Creates an object containing desired settings that could later be applied throug - **Parameters:** - `synchronous_mode` (_bool_) – Set this to true to enable client-server synchrony. - `no_rendering_mode` (_bool_) – Set this to true to completely disable rendering in the simulation. - - `fixed_delta_seconds` (_float_) – Set this time in seconds to get a fixed time-step in between frames. 0.0 means variable time-step and it is the default mode. + - `fixed_delta_seconds` (_float – seconds_) – Set a fixed time-step in between frames. 0.0 means variable time-step and it is the default mode.
    Dunder methods
    - **\__eq__**(**self**, **other**=[carla.WorldSettings](#carla.WorldSettings)) @@ -2766,7 +2766,7 @@ This snapshot comprises all the information for every actor on scene at a certai A value unique for every snapshot to differenciate them. - **frame** (_int_) Simulation frame in which the snapshot was taken. -- **timestamp** (_[carla.Timestamp](#carla.Timestamp)_) +- **timestamp** (_[carla.Timestamp](#carla.Timestamp) – seconds_) Precise moment in time when snapshot was taken. This class works in seconds as given by the operative system.

    Methods

    @@ -2802,14 +2802,14 @@ Command adaptation of **add_angular_impulse()** in

    Instance Variables

    - **actor_id** (_int_) Actor affected by the command. -- **impulse** (_[carla.Vector3D](#carla.Vector3D)_) +- **impulse** (_[carla.Vector3D](#carla.Vector3D) – N * m * s_) Angular impulse applied to the actor. Determines magnitude and global axis where it is applied.

    Methods

    - **\__init__**(**self**, **actor**, **impulse**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `impulse` (_[carla.Vector3D](#carla.Vector3D)_) + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N * m * s_) --- @@ -2819,14 +2819,14 @@ Command adaptation of **set_angular_velocity()** in

    Instance Variables

    - **actor_id** (_int_) Actor affected by the command. -- **angular_velocity** (_[carla.Vector3D](#carla.Vector3D)_) +- **angular_velocity** (_[carla.Vector3D](#carla.Vector3D) – rad/s_) The 3D angular velocity that will be applied to the actor.

    Methods

    - **\__init__**(**self**, **actor**, **angular_velocity**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `angular_velocity` (_[carla.Vector3D](#carla.Vector3D)_) + - `angular_velocity` (_[carla.Vector3D](#carla.Vector3D) – rad/s_) --- @@ -2836,14 +2836,14 @@ Command adaptation of **add_impulse()** in [carla.A

    Instance Variables

    - **actor_id** (_int_) Actor affected by the command. -- **impulse** (_[carla.Vector3D](#carla.Vector3D)_) +- **impulse** (_[carla.Vector3D](#carla.Vector3D) – N * s_) Impulse applied to the actor.

    Methods

    - **\__init__**(**self**, **actor**, **impulse**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `impulse` (_[carla.Vector3D](#carla.Vector3D)_) + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N * s_) --- @@ -2887,7 +2887,7 @@ Command adaptation of **set_velocity()** in [carla.

    Instance Variables

    - **actor_id** (_int_) Actor affected by the command. -- **velocity** (_[carla.Vector3D](#carla.Vector3D)_) +- **velocity** (_[carla.Vector3D](#carla.Vector3D) – m/s_) The 3D velocity applied to the actor.

    Methods

    @@ -2923,7 +2923,7 @@ Apply a state to the walker actor. Specially useful to initialize an actor them Walker actor affected by the command. - **transform** (_[carla.Transform](#carla.Transform)_) Transform to be applied. -- **speed** (_float_) +- **speed** (_float – m/s_) Speed to be applied.

    Methods

    @@ -2931,7 +2931,7 @@ Speed to be applied. - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - `transform` (_[carla.Transform](#carla.Transform)_) - - `speed` (_float_) + - `speed` (_float – m/s_) --- diff --git a/PythonAPI/docs/actor.yml b/PythonAPI/docs/actor.yml index 93f87373324..f5c9dcab186 100644 --- a/PythonAPI/docs/actor.yml +++ b/PythonAPI/docs/actor.yml @@ -39,6 +39,7 @@ params: - param_name: impulse type: carla.Vector3D + param_units: N * s doc: > Adds an impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. # -------------------------------------- @@ -46,6 +47,7 @@ params: - param_name: impulse type: carla.Vector3D + param_units: N * m * s doc: > Adds an angular impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. # -------------------------------------- @@ -58,16 +60,19 @@ # -------------------------------------- - def_name: get_acceleration return: carla.Vector3D + return_units: m/s2 doc: > Returns the actor's 3D acceleration vector the client recieved during last tick. The method does not call the simulator. # -------------------------------------- - def_name: get_angular_velocity return: carla.Vector3D + return_units: rad/s doc: > Returns the actor's angular velocity vector the client recieved during last tick. The method does not call the simulator. # -------------------------------------- - def_name: get_location return: carla.Location + return_units: meters doc: > Returns the actor's location the client recieved during last tick. The method does not call the simulator. # -------------------------------------- @@ -78,6 +83,7 @@ # -------------------------------------- - def_name: get_velocity return: carla.Vector3D + return_units: m/s doc: > Returns the actor's velocity vector the client recieved during last tick. The method does not call the simulator. # -------------------------------------- @@ -97,6 +103,7 @@ params: - param_name: location type: carla.Location + param_units: meters doc: > Teleports the actor to a given location. # -------------------------------------- @@ -198,7 +205,7 @@ return: carla.VehicleLightState doc: > Returns a flag representing the vehicle light state, - this represents which lights are active or not + this represents which lights are active or not. # -------------------------------------- - def_name: get_physics_control return: carla.VehiclePhysicsControl @@ -208,6 +215,7 @@ # -------------------------------------- - def_name: get_speed_limit return: float + return_units: m/s doc: > The client returns the speed limit affecting this vehicle according to last tick (it does not call the simulator). The speed limit is updated when passing by a speed limit signal, so a vehicle might have none right after spawning. # -------------------------------------- @@ -291,6 +299,7 @@ params: - param_name: destination type: carla.Location + param_units: meters doc: > Sets the destination that the pedestrian will reach. # -------------------------------------- @@ -307,8 +316,9 @@ - param_name: speed type: float default: 1.4 + param_units: m/s doc: > - speed in m/s. An easy walking speed is set by default. + An easy walking speed is set by default. doc: > Sets a speed for the walker in meters per second. # -------------------------------------- @@ -369,6 +379,7 @@ # -------------------------------------- - def_name: get_elapsed_time return: float + return_units: seconds doc: > The client returns the time in seconds since current light state started according to last tick. The method does not call the simulator. # -------------------------------------- @@ -397,18 +408,21 @@ # -------------------------------------- - def_name: get_green_time return: float + return_units: seconds doc: > - The client returns the seconds set for the traffic light to be green according to last tick. The method does not call the simulator. + The client returns the time set for the traffic light to be green, according to last tick. The method does not call the simulator. # -------------------------------------- - def_name: get_red_time return: float + return_units: seconds doc: > - The client returns the seconds set for the traffic light to be red according to last tick. The method does not call the simulator. + The client returns the time set for the traffic light to be red, according to last tick. The method does not call the simulator. # -------------------------------------- - def_name: get_yellow_time return: float + return_units: seconds doc: > - The client returns the the seconds set for the traffic light to be yellow according to last tick. The method does not call the simulator. + The client returns the time set for the traffic light to be yellow, according to last tick. The method does not call the simulator. # -------------------------------------- - def_name: set_state params: @@ -421,22 +435,25 @@ params: - param_name: green_time type: float + param_units: seconds doc: > - Sets a given time (in seconds) for the green light to be active. + Sets a given time for the green light to be active. # -------------------------------------- - def_name: set_red_time params: - param_name: red_time type: float + param_units: seconds doc: > - Sets a given time (in seconds) for the red state to be active. + Sets a given time for the red state to be active. # -------------------------------------- - def_name: set_yellow_time params: - param_name: yellow_time type: float + param_units: seconds doc: > - Sets a given time (in seconds) for the yellow light to be active. + Sets a given time for the yellow light to be active. # -------------------------------------- - def_name: __str__ # -------------------------------------- diff --git a/PythonAPI/docs/client.yml b/PythonAPI/docs/client.yml index be27b385ab1..ff1bca3edb1 100644 --- a/PythonAPI/docs/client.yml +++ b/PythonAPI/docs/client.yml @@ -102,12 +102,14 @@ Name of the file containing the information of the simulation. - param_name: start type: float + param_units: seconds doc: > - Time in seconds where to start playing the simulation. Negative is read as beginning from the end, being -10 just 10 seconds before the recording finished. + Time where to start playing the simulation. Negative is read as beginning from the end, being -10 just 10 seconds before the recording finished. - param_name: duration type: float + param_units: seconds doc: > - Time in seconds that will be reenacted using the information `name` file. If the end is reached, the simulation will continue. + Time that will be reenacted using the information `name` file. If the end is reached, the simulation will continue. - param_name: follow_id type: int doc: > @@ -133,12 +135,14 @@ Name of the recorded file to load - param_name: min_time type: float + param_units: seconds doc: > - Minimum time in seconds the actor has to move a minimum distance before being considered blocked. Default is 60 seconds. + Minimum time the actor has to move a minimum distance before being considered blocked. Default is 60 seconds. - param_name: min_distance type: float + param_units: centimeters doc: > - Minimum distance in centimeters the actor has to move to not be considered blocked. Default is 100 centimeters. + Minimum distance the actor has to move to not be considered blocked. Default is 100 centimeters. return: string doc: > The terminal will show the information registered for actors considered blocked. An actor is considered blocked when it does not move a minimum distance in a period of time, being these `min_distance` and `min_time`. @@ -259,10 +263,11 @@ params: - param_name: seconds type: float + param_units: seconds doc: > - New timeout value in seconds. Default is 5 seconds. + New timeout value. Default is 5 seconds. doc: > - Sets in seconds the maxixum time a network call is allowed before blocking it and raising a timeout exceeded error. + Sets the maxixum time a network call is allowed before blocking it and raising a timeout exceeded error. # -------------------------------------- - class_name: TrafficManager @@ -313,6 +318,7 @@ Vehicle whose minimum distance is being changed. - param_name: distance type: float + param_units: meters doc: > Meters between both vehicles. doc: > @@ -335,6 +341,7 @@ params: - param_name: distance type: float + param_units: meters doc: > Meters between vehicles. doc: > @@ -430,6 +437,7 @@ - param_name: r type: float default: 70.0 + param_units: meters doc: > New radius where physics are enabled. doc: > @@ -444,18 +452,22 @@ instance_variables: - var_name: vertex_distance type: float + param_units: meters doc: > Distance between vertices of the mesh generated. __Default is `2.0`__. - var_name: max_road_length type: float + param_units: meters doc: > Max road length for a single mesh portion. The mesh of the map is divided into portions, in order to avoid propagating issues. __Default is `50.0`__. - var_name: wall_height type: float + param_units: meters doc: > Height of walls created on the boundaries of the road. These prevent vehicles from falling off the road. __Default is `1.0`__. - var_name: additional_width type: float + param_units: meters doc: > Additional with applied junction lanes. Complex situations tend to occur at junctions, and a little increase can prevent vehicles from falling off the road. __Default is `0.6`__. - var_name: smooth_junctions diff --git a/PythonAPI/docs/commands.yml b/PythonAPI/docs/commands.yml index 78a606f6650..e7ac3341eea 100644 --- a/PythonAPI/docs/commands.yml +++ b/PythonAPI/docs/commands.yml @@ -184,6 +184,7 @@ Transform to be applied. - var_name: speed type: float + var_units: m/s doc: > Speed to be applied. # - METHODS ---------------------------- @@ -198,6 +199,7 @@ type: carla.Transform - param_name: speed type: float + param_units: m/s # -------------------------------------- - class_name: ApplyVelocity @@ -212,6 +214,7 @@ Actor affected by the command. - var_name: velocity type: carla.Vector3D + var_units: m/s doc: > The 3D velocity applied to the actor. # - METHODS ---------------------------- @@ -224,6 +227,7 @@ Actor or its ID to whom the command will be applied to. - param_name: velocity type: carla.Vector3D + param_untis: m/s # -------------------------------------- - class_name: ApplyAngularVelocity @@ -238,6 +242,7 @@ Actor affected by the command. - var_name: angular_velocity type: carla.Vector3D + var_units: rad/s doc: > The 3D angular velocity that will be applied to the actor. # - METHODS ---------------------------- @@ -250,6 +255,7 @@ Actor or its ID to whom the command will be applied to. - param_name: angular_velocity type: carla.Vector3D + param_units: rad/s # -------------------------------------- - class_name: ApplyImpulse @@ -264,6 +270,7 @@ Actor affected by the command. - var_name: impulse type: carla.Vector3D + var_units: N * s doc: > Impulse applied to the actor. # - METHODS ---------------------------- @@ -276,6 +283,7 @@ Actor or its ID to whom the command will be applied to. - param_name: impulse type: carla.Vector3D + param_units: N * s # -------------------------------------- - class_name: ApplyAngularImpulse @@ -290,6 +298,7 @@ Actor affected by the command. - var_name: impulse type: carla.Vector3D + var_units: N * m * s doc: > Angular impulse applied to the actor. Determines magnitude and global axis where it is applied. # - METHODS ---------------------------- @@ -302,6 +311,7 @@ Actor or its ID to whom the command will be applied to. - param_name: impulse type: carla.Vector3D + param_units: N * m * s # -------------------------------------- - class_name: SetSimulatePhysics diff --git a/PythonAPI/docs/control.yml b/PythonAPI/docs/control.yml index 4385d213ac3..46ca5fe735f 100644 --- a/PythonAPI/docs/control.yml +++ b/PythonAPI/docs/control.yml @@ -51,12 +51,15 @@ - param_name: throttle type: float default: 0.0 + doc: Scalar value between [0.0,1.0] - param_name: steer type: float default: 0.0 + doc: Scalar value between [0.0,1.0] - param_name: brake type: float default: 0.0 + doc: Scalar value between [0.0,1.0] - param_name: hand_brake type: bool default: False @@ -98,6 +101,7 @@ # -------------------------------------- - var_name: speed type: float + var_units: m/s doc: > A scalar value to control the walker's speed. # -------------------------------------- @@ -115,6 +119,7 @@ type: carla.Vector3D - param_name: speed default: 0.0 + param_Units: m/s type: float - param_name: jump default: False @@ -154,7 +159,7 @@ - param_name: 'list(name,transform)' type: tuple doc: > - Intializes an object containing moves to be applied on tick. These are listed with the name of the bone and the transform that will be applied to it. + Initializes an object containing moves to be applied on tick. These are listed with the name of the bone and the transform that will be applied to it. # -------------------------------------- - def_name: __str__ # -------------------------------------- @@ -224,6 +229,7 @@ # -------------------------------------- - var_name: moi type: float + var_units: kg*m2 doc: > The moment of inertia of the vehicle's engine. # -------------------------------------- @@ -249,18 +255,20 @@ # -------------------------------------- - var_name: gear_switch_time type: float + var_units: seconds doc: > Switching time between gears. # -------------------------------------- - var_name: clutch_strength type: float + var_units: kg*m2/s doc: > - The clutch strength of the vehicle in Kgm^2/s. + Clutch strength of the vehicle. # -------------------------------------- - var_name: final_ratio type: float doc: > - The fixed ratio from transmission to wheels. + Fixed ratio from transmission to wheels. # -------------------------------------- - var_name: forward_gears type: list(carla.GearPhysicsControl) @@ -269,8 +277,9 @@ # -------------------------------------- - var_name: mass type: float + var_units: kilograms doc: > - The mass of the vehicle in Kg. + Mass of the vehicle. # -------------------------------------- - var_name: drag_coefficient type: float @@ -279,8 +288,9 @@ # -------------------------------------- - var_name: center_of_mass type: carla.Vector3D + var_units: meters doc: > - The center of mass of the vehicle. + Center of mass of the vehicle. # -------------------------------------- - var_name: steering_curve type: list(carla.Vector2D) @@ -305,6 +315,7 @@ - param_name: moi default: 1.0 type: float + param_units: kg*m2 - param_name: damping_rate_full_throttle default: 0.15 type: float @@ -320,9 +331,11 @@ - param_name: gear_switch_time default: 0.5 type: float + param_units: seconds - param_name: clutch_strength default: 10.0 type: float + param_units: kg*m2/s - param_name: final_ratio default: 4.0 type: float @@ -331,6 +344,7 @@ type: list(carla.GearPhysicsControl) - param_name: mass default: 1000.0 + param_units: kilograms - param_name: drag_coefficient default: 0.3 type: float @@ -376,23 +390,27 @@ # -------------------------------------- - var_name: max_steer_angle type: float + var_units: degrees doc: > - Maximum angle in degrees that the wheel can steer. + Maximum angle that the wheel can steer. # -------------------------------------- - var_name: radius type: float + var_units: centimeters doc: > - Radius of the wheel in centimeters. + Radius of the wheel. # -------------------------------------- - var_name: max_brake_torque type: float + var_units: N*m doc: > - Maximum brake torque in Nm. + Maximum brake torque. # -------------------------------------- - var_name: max_handbrake_torque type: float + var_units: N*m doc: > - Maximum handbrake torque in Nm. + Maximum handbrake torque. # -------------------------------------- - var_name: position type: carla.Vector3D @@ -411,18 +429,23 @@ - param_name: max_steer_angle default: 70.0 type: float + param_units: degrees - param_name: radius default: 30.0 type: float + param_units: centimerers - param_name: max_brake_torque default: 1500.0 type: float + param_units: N*m - param_name: max_handbrake_torque default: 3000.0 type: float + param_units: N*m - param_name: position default: (0.0,0.0,0.0) type: carla.Vector3D + param_units: meters # -------------------------------------- - def_name: __eq__ params: diff --git a/PythonAPI/docs/doc_gen.py b/PythonAPI/docs/doc_gen.py index b0cd9de016a..7a271564ecb 100755 --- a/PythonAPI/docs/doc_gen.py +++ b/PythonAPI/docs/doc_gen.py @@ -328,11 +328,14 @@ def add_doc_method_param(md, param): param_name = param['param_name'] param_type = '' param_doc = '' + param_units = '' if valid_dic_val(param, 'type'): param_type = create_hyperlinks(param['type']) if valid_dic_val(param, 'doc'): param_doc = create_hyperlinks(md.prettify_doc(param['doc'])) - param_type = '' if not param_type else parentheses(italic(param_type)) + if valid_dic_val(param, 'param_units'): + param_units = ' – '+create_hyperlinks(param['param_units']+'') + param_type = '' if not param_type else parentheses(italic(param_type+param_units)) md.list_push(code(param_name)) if param_type: md.text(' ' + param_type) @@ -372,7 +375,10 @@ def add_doc_method(md, method, class_key): # Return doc if valid_dic_val(method, 'return'): md.list_push(bold('Return:') + ' ') - md.textn(italic(create_hyperlinks(method['return']))) + return_units = '' + if valid_dic_val(method, 'return_units'): + return_units = ' – '+create_hyperlinks(method['return_units']+'') + md.textn(italic(create_hyperlinks(method['return'])+return_units)) md.list_pop() # Note doc @@ -423,7 +429,10 @@ def add_doc_getter_setter(md, method,class_key,is_getter,other_list): # Return doc if valid_dic_val(method, 'return'): md.list_push(bold('Return:') + ' ') - md.textn(italic(create_hyperlinks(method['return']))) + return_units = '' + if valid_dic_val(method, 'return_units'): + return_units = ' – '+create_hyperlinks(method['return_units']+'') + md.textn(italic(create_hyperlinks(method['return'])+return_units)) md.list_pop() # If setter/getter @@ -493,11 +502,13 @@ def add_doc_inst_var(md, inst_var, class_key): var_name = inst_var['var_name'] var_key = join([class_key, var_name], '.') var_type = '' + var_units = '' # Instance variable type if valid_dic_val(inst_var, 'type'): - var_type = ' ' + parentheses(italic(create_hyperlinks(inst_var['type']))) - + if valid_dic_val(inst_var, 'var_units'): + var_units = ' – '+create_hyperlinks(inst_var['var_units']+'') + var_type = ' ' + parentheses(italic(create_hyperlinks(inst_var['type']+var_units))) md.list_pushn( html_key(var_key) + bold(color(COLOR_INSTANCE_VAR, var_name)) + diff --git a/PythonAPI/docs/geom.yml b/PythonAPI/docs/geom.yml index 1321fcc5ac1..8be2ad7ecbc 100644 --- a/PythonAPI/docs/geom.yml +++ b/PythonAPI/docs/geom.yml @@ -151,16 +151,19 @@ instance_variables: - var_name: x type: float + var_units: meters doc: > - Distance in meters from origin to spot on X axis. + Distance from origin to spot on X axis. - var_name: 'y' type: float + var_units: meters doc: > - Distance in meters from origin to spot on Y axis. + Distance from origin to spot on Y axis. - var_name: z type: float + var_units: meters doc: > - Distance in meters from origin to spot on Z axis. + Distance from origin to spot on Z axis. # - METHODS ---------------------------- methods: - def_name: __init__ @@ -182,8 +185,9 @@ doc: > The other point to compute the distance with. return: float + return_units: meters doc: > - Returns Euclidean distance in meters from this location to another one. + Returns Euclidean distance from this location to another one. # -------------------------------------- - def_name: __eq__ return: bool @@ -219,16 +223,19 @@ instance_variables: - var_name: pitch type: float + var_units: degrees doc: > - Degrees around the Y-axis. + Y-axis rotation angle. - var_name: yaw type: float + var_units: degrees doc: > - Degrees around the Z-axis. + Z-axis rotation angle. - var_name: roll type: float + var_units: degrees doc: > - Degrees around the X-axis. + X-axis rotation angle. # - METHODS ---------------------------- methods: - def_name: __init__ @@ -236,36 +243,39 @@ - param_name: pitch type: float default: 0.0 + param_units: degrees doc: > - Y rotation in degrees. + Y-axis rotation angle. - param_name: yaw type: float default: 0.0 + param_units: degrees doc: > - Z rotation in degrees. + Z-axis rotation angle. - param_name: roll type: float default: 0.0 + param_units: degrees doc: > - X rotation in degrees. + X-axis rotation angle. # -------------------------------------- - def_name: get_forward_vector params: return: carla.Vector3D doc: > - Computes the vector pointing forward according to the orientation of each axis. + Computes the vector pointing forward according to the rotation of the object. # -------------------------------------- - def_name: get_right_vector params: return: carla.Vector3D doc: > - Computes the vector pointing to the right according to the orientation of each axis. + Computes the vector pointing to the right according to the rotation of the object. # -------------------------------------- - def_name: get_up_vector params: return: carla.Vector3D doc: > - Computes the vector pointing upwards according to the orientation of each axis. + Computes the vector pointing upwards according to the rotation of the object. # -------------------------------------- - def_name: __eq__ return: bool @@ -273,7 +283,7 @@ - param_name: other type: carla.Rotation doc: > - Returns __True__ if both rotations represent the same orientation of each axis. + Returns __True__ if both rotations represent the same orientation for every axis. # -------------------------------------- - def_name: __ne__ params: @@ -323,17 +333,17 @@ - def_name: get_forward_vector return: carla.Vector3D doc: > - Computes a forward vector using its rotation. + Computes a forward vector using the rotation of the object. # -------------------------------------- - def_name: get_right_vector return: carla.Vector3D doc: > - Computes a right vector using its rotation. + Computes a right vector using the rotatio of the object. # -------------------------------------- - def_name: get_up_vector return: carla.Vector3D doc: > - Computes an up vector using its rotation. + Computes an up vector using the rotation of the object. # -------------------------------------- - def_name: get_matrix return: list(list(float)) @@ -375,12 +385,14 @@ instance_variables: - var_name: extent type: carla.Vector3D + var_units: meters doc: > Vector from the center of the box to one vertex. The value in each axis equals half the size of the box for that axis. `extent.x * 2` would return the size of the box in the X-axis. - var_name: location type: carla.Location + var_units: meters doc: > The center of the bounding box relative to its parent actor. # - METHODS ---------------------------- @@ -389,10 +401,12 @@ params: - param_name: location type: carla.Location + var_units: meters doc: > - Point to center the box. + Center of the box, relative to its parent. - param_name: extent type: carla.Vector3D + param_units: meters doc: > Vector containing half the size of the box for every axis. # -------------------------------------- @@ -401,6 +415,7 @@ params: - param_name: world_point type: carla.Location + param_units: meters doc: > The point in world space to be checked. - param_name: transform @@ -455,14 +470,17 @@ instance_variables: - var_name: latitude type: float + var_units: degrees doc: > North/South value of a point on the map. - var_name: longitude type: float + var_units: degrees doc: > West/East value of a point on the map. - var_name: altitude type: float + var_units: meters doc: > Height regarding ground level. # - METHODS ---------------------------- @@ -472,12 +490,15 @@ - param_name: latitude type: float default: 0.0 + param_units: degrees - param_name: longitude type: float default: 0.0 + param_units: degrees - param_name: altitude type: float default: 0.0 + param_units: meters # -------------------------------------- - def_name: __eq__ params: diff --git a/PythonAPI/docs/light_manager.yml b/PythonAPI/docs/light_manager.yml index e3267b3a003..3455644a89a 100644 --- a/PythonAPI/docs/light_manager.yml +++ b/PythonAPI/docs/light_manager.yml @@ -28,8 +28,9 @@ instance_variables: - var_name: intensity type: float + var_units: lumens doc: > - Intensity of a light in lumens. + Intensity of a light. # -------------------------------------- - var_name: color type: carla.Color @@ -52,8 +53,9 @@ - param_name: intensity type: float default: 0.0 + param_units: lumens doc: > - Intensity of the light in lumens. Default is `0.0`. + Intensity of the light. Default is `0.0`. # -------------------------------------- - param_name: color type: carla.Color @@ -94,8 +96,9 @@ # -------------------------------------- - var_name: intensity type: float + var_units: lumens doc: > - Intensity of the light in lumens. + Intensity of the light. # -------------------------------------- - var_name: is_on type: bool @@ -104,6 +107,7 @@ # -------------------------------------- - var_name: location type: carla.Location + var_units: meters doc: > Position of the light. # -------------------------------------- @@ -139,6 +143,7 @@ params: - param_name: intensity type: float + param_units: lumens # -------------------------------------- - def_name: set_light_group doc: > @@ -222,6 +227,7 @@ doc: List of lights to be queried. return: list(float) + return_units: lumens # -------------------------------------- - def_name: get_light_group doc: > @@ -312,6 +318,7 @@ List of lights to be changed. - param_name: intensity type: float + param_units: lumens doc: Intensity to be applied. # -------------------------------------- @@ -325,6 +332,7 @@ List of lights to be changed. - param_name: intensities type: list(float) + param_units: lumens doc: List of intensities to be applied. # -------------------------------------- diff --git a/PythonAPI/docs/map.yml b/PythonAPI/docs/map.yml index 88cbaad0a1c..994d8876be9 100644 --- a/PythonAPI/docs/map.yml +++ b/PythonAPI/docs/map.yml @@ -156,6 +156,7 @@ params: - param_name: distance type: float + param_units: meters doc: > Approximate distance between waypoints. return: list(carla.Waypoint) @@ -235,6 +236,7 @@ params: - param_name: location type: carla.Location + param_units: meters doc: > Location used as reference for the carla.Waypoint. - param_name: project_to_road @@ -263,6 +265,7 @@ ID of the lane to get the waypoint. - param_name: s type: float + param_units: meters doc: > Specify the length from the road start. return: carla.Waypoint @@ -322,6 +325,7 @@ OpenDRIVE lane's id, this value can be positive or negative which represents the direction of the current lane with respect to the road. For more information refer to OpenDRIVE [documentation](http://www.opendrive.org/docs/OpenDRIVEFormatSpecRev1.4H.pdf#page=20) - var_name: s type: float + param_units: meters doc: > OpenDRIVE s value of the current position. - var_name: is_junction @@ -330,6 +334,7 @@ True if the current Waypoint is on a junction as defined by OpenDRIVE. - var_name: lane_width type: float + param_units: meters doc: > Horizontal size of the road at current s. - var_name: lane_change @@ -354,6 +359,7 @@ params: - param_name: distance type: float + param_units: meters doc: > The approximate distance where to get the next waypoints. return: list(carla.Waypoint) @@ -366,8 +372,9 @@ params: - param_name: distance type: float + param_units: meters doc: > - The approximate distance between waypoints + The approximate distance between waypoints. return: list(carla.Waypoint) doc: > Returns a list of waypoints from this to the end of the lane separated by a certain `distance`. @@ -376,6 +383,7 @@ params: - param_name: distance type: float + param_units: meters doc: > The approximate distance where to get the previous waypoints. return: list(carla.Waypoint) @@ -388,8 +396,9 @@ params: - param_name: distance type: float + param_units: meters doc: > - The approximate distance between waypoints + The approximate distance between waypoints. return: list(carla.Waypoint) doc: > Returns a list of waypoints from this to the start of the lane separated by a certain `distance`. @@ -403,6 +412,7 @@ params: - param_name: distance type: float + param_units: meters doc: > The maximum distance to search for landmarks from the current waypoint. - param_name: stop_at_junction @@ -417,6 +427,7 @@ - def_name: get_landmarks_of_type params: - param_name: distance + param_units: meters type: float doc: > The maximum distance to search for landmarks from the current waypoint. @@ -623,14 +634,17 @@ Example: a traffic light is defined in one of the divergent roads in a junction, but it affects all the possible routes - var_name: distance type: float + var_units: meters doc: > Distance between the landmark and the waypoint creating the object (querying `get_landmarks` or `get_landmarks_of_type`). - var_name: s type: float + var_units: meters doc: > Distance where the landmark is positioned along the geometry of the road `road_id`. - var_name: t type: float + var_units: meters doc: > Lateral distance where the landmark is positioned from the edge of the road `road_id`. - var_name: id @@ -647,10 +661,12 @@ Indicates if the landmark has state changes over time such as traffic lights. - var_name: orientation type: carla.LandmarkOrientation + var_units: degrees doc: > Indicates which lanes the landmark is facing towards to. - var_name: z_offset type: float + var_units: meters doc: > Height where the landmark is placed. - var_name: country @@ -675,10 +691,12 @@ Units of measurement for the attribute `value`. - var_name: height type: float + var_units: meters doc: > Total height of the signal. - var_name: width type: float + var_units: meters doc: > Total width of the signal. - var_name: text @@ -687,16 +705,18 @@ Additional text in the signal. - var_name: h_offset type: float + var_units: meters doc: > Orientation offset of the signal relative to the the definition of `road_id` at `s` in OpenDRIVE. - var_name: pitch type: float + var_units: meters doc: > - Pitch rotation of the signal. + Pitch rotation (Y-axis) of the signal. - var_name: roll type: float doc: > - Roll rotation of the signal. + Roll rotation (X-axis) of the signal. - var_name: waypoint type: carla.Waypoint doc: > diff --git a/PythonAPI/docs/osm2odr.yml b/PythonAPI/docs/osm2odr.yml index 365992e6b0f..598db3d33c3 100644 --- a/PythonAPI/docs/osm2odr.yml +++ b/PythonAPI/docs/osm2odr.yml @@ -40,17 +40,21 @@ Enables the use of offset for the conversion. The offset will move the origin position of the map. Default value is __False__. - var_name: offset_x type: float + var_units: meters doc: > Offset in the X axis. Default value is __0.0__. - var_name: offset_y type: float + var_units: meters doc: > Offset in the Y axis. Default value is __0.0__. - var_name: default_lane_width type: float + var_units: meters doc: > Width of the lanes described in the resulting XODR map. Default value is __4.0__. - var_name: elevation_layer_height type: float + var_units: meters doc: > Defines the height separating two different [OpenStreetMap layers](https://wiki.openstreetmap.org/wiki/Key:layer). Default value is __0.0__. diff --git a/PythonAPI/docs/sensor_data.yml b/PythonAPI/docs/sensor_data.yml index 1a334992dbd..6897d85a76a 100644 --- a/PythonAPI/docs/sensor_data.yml +++ b/PythonAPI/docs/sensor_data.yml @@ -24,6 +24,7 @@ Frame count when the data was generated. - var_name: timestamp type: float + var_units: seconds doc: > Simulation-time when the data was generated. - var_name: transform @@ -60,8 +61,9 @@ instance_variables: - var_name: fov type: float + var_units: degrees doc: > - Horizontal field of view of the image in degrees. + Horizontal field of view of the image. - var_name: height type: int doc: > @@ -127,8 +129,9 @@ Number of lasers shot. - var_name: horizontal_angle type: float + var_units: radians doc: > - Horizontal angle the LIDAR is rotated at the time of the measurement (in radians). + Horizontal angle the LIDAR is rotated at the time of the measurement. - var_name: raw_data type: bytes doc: > @@ -176,13 +179,14 @@ instance_variables: - var_name: point type: carla.Location + var_units: meters doc: > Point in xyz coordinates. # -------------------------------------- - var_name: intensity type: float doc: > - Computed intensity for this point. + Computed intensity for this point as a scalar value between [0.0 , 1.0]. # - METHODS ---------------------------- methods: - def_name: __str__ @@ -250,6 +254,7 @@ instance_variables: - var_name: point type: carla.Location + var_units: meters doc: > [x,y,z] coordinates of the point. # -------------------------------------- @@ -261,12 +266,12 @@ - var_name: object_idx type: uint doc: > - Carla index of the hit actor. + [CARLA index](https://carla.readthedocs.io/en/latest/ref_sensors/#semantic-segmentation-camera) of the hit actor. # -------------------------------------- - var_name: object_tag type: uint doc: > - Semantic tag of the hit component. + [Semantic tag](https://carla.readthedocs.io/en/latest/ref_sensors/#semantic-segmentation-camera) of the hit component. # - METHODS ---------------------------- methods: - def_name: __str__ @@ -289,6 +294,7 @@ The second actor involved in the collision. - var_name: normal_impulse type: carla.Vector3D + var_units: N*m doc: > Normal impulse resulting of the collision. @@ -309,6 +315,7 @@ The actor or object considered to be an obstacle. - var_name: distance type: float + var_units: meters doc: > Distance between `actor` and `other`. # - METHODS ---------------------------- @@ -345,14 +352,17 @@ instance_variables: - var_name: altitude type: float + var_units: meters doc: > Height regarding ground level. - var_name: latitude type: float + var_units: degrees doc: > North/South value of a point on the map. - var_name: longitude type: float + var_units: degrees doc: > West/East value of a point on the map. # - METHODS ---------------------------- @@ -369,16 +379,19 @@ instance_variables: - var_name: accelerometer type: carla.Vector3D + var_units: m*s2 doc: > - Linear acceleration in m/s^2. + Linear acceleration. - var_name: compass type: float + var_units: radians doc: > - Orientation with regard to the North ((0.0, -1.0, 0.0) in Unreal Engine) in radians. + Orientation with regard to the North ([0.0, -1.0, 0.0] in Unreal Engine). - var_name: gyroscope type: carla.Vector3D + var_units: rad/s doc: > - Angular velocity in rad/sec. + Angular velocity. # - METHODS ---------------------------- methods: - def_name: __str__ @@ -428,23 +441,27 @@ instance_variables: - var_name: altitude type: float + var_units: radians doc: > - Altitude angle of the detection in radians. + Altitude angle of the detection. # -------------------------------------- - var_name: azimuth type: float + var_units: radians doc: > - Azimuth angle of the detection in radians. + Azimuth angle of the detection. # -------------------------------------- - var_name: depth type: float + var_units: meters doc: > - Distance in meters from the sensor to the detection position. + Distance from the sensor to the detection position. # -------------------------------------- - var_name: velocity type: float + var_units: m/s doc: > - The velocity of the detected object towards the sensor in m/s. + The velocity of the detected object towards the sensor. # - METHODS ---------------------------- methods: - def_name: __str__ @@ -688,8 +705,9 @@ instance_variables: - var_name: fov type: float + var_units: degrees doc: > - Horizontal field of view of the image in degrees. + Horizontal field of view of the image. # -------------------------------------- - var_name: height type: int diff --git a/PythonAPI/docs/snapshot.yml b/PythonAPI/docs/snapshot.yml index e94c5b563ca..04c310e302b 100644 --- a/PythonAPI/docs/snapshot.yml +++ b/PythonAPI/docs/snapshot.yml @@ -19,6 +19,7 @@ Simulation frame in which the snapshot was taken. - var_name: timestamp type: carla.Timestamp + var_units: seconds doc: > Precise moment in time when snapshot was taken. This class works in seconds as given by the operative system. # - METHODS ---------------------------- @@ -79,11 +80,13 @@ methods: - def_name: get_acceleration return: carla.Vector3D + return_units: m/s2 doc: > Returns the acceleration vector registered for an actor in that tick. # -------------------------------------- - def_name: get_angular_velocity return: carla.Vector3D + return_units: rad/s doc: > Returns the angular velocity vector registered for an actor in that tick. # -------------------------------------- @@ -94,6 +97,7 @@ # -------------------------------------- - def_name: get_velocity return: carla.Vector3D + return_units: m/s doc: > Returns the velocity vector registered for an actor in that tick. # -------------------------------------- diff --git a/PythonAPI/docs/weather.yml b/PythonAPI/docs/weather.yml index 9794239bf53..52e22e37266 100644 --- a/PythonAPI/docs/weather.yml +++ b/PythonAPI/docs/weather.yml @@ -32,13 +32,15 @@ # -------------------------------------- - var_name: sun_azimuth_angle type: float + var_units: degrees doc: > - The azimuth angle of the sun in degrees. Values range from 0 to 360. Zero is an origin point in a sphere determined by Unreal Engine. + The azimuth angle of the sun. Values range from 0 to 360. Zero is an origin point in a sphere determined by Unreal Engine. # -------------------------------------- - var_name: sun_altitude_angle type: float + var_units: degrees doc: > - Altitude angle of the sun in degrees. Values range from -90 to 90 corresponding to midnight and midday each. + Altitude angle of the sun. Values range from -90 to 90 corresponding to midnight and midday each. # -------------------------------------- - var_name: fog_density type: float @@ -47,8 +49,9 @@ # -------------------------------------- - var_name: fog_distance type: float + var_units: meters doc: > - Fog start distance (in meters). Values range from 0 to infinite. + Fog start distance. Values range from 0 to infinite. # -------------------------------------- - var_name: wetness type: float @@ -87,11 +90,13 @@ - param_name: sun_azimuth_angle type: float default: 0.0 + param_units: degrees doc: > 0 is an arbitrary North, 180 its corresponding South. - param_name: sun_altitude_angle type: float default: 0.0 + param_units: degrees doc: > 90 is midday, -90 is midnight. - param_name: fog_density @@ -102,6 +107,7 @@ - param_name: fog_distance type: float default: 0.0 + param_units: meters doc: > Distance where the fog starts in meters. - param_name: wetness diff --git a/PythonAPI/docs/world.yml b/PythonAPI/docs/world.yml index dcd374c68b8..cd9d519ff09 100644 --- a/PythonAPI/docs/world.yml +++ b/PythonAPI/docs/world.yml @@ -15,14 +15,17 @@ The number of frames elapsed since the simulator was launched. - var_name: elapsed_seconds type: float + var_units: seconds doc: > Simulated seconds elapsed since the beginning of the current episode. - var_name: delta_seconds type: float + var_units: seconds doc: > Simulated seconds elapsed since the previous frame. - var_name: platform_timestamp type: float + var_units: seconds doc: > Time register of the frame at which this measurement was taken given by the OS in seconds. # - METHODS ---------------------------- @@ -33,20 +36,25 @@ type: int - param_name: elapsed_seconds type: float + param_units: seconds - param_name: delta_seconds type: float + param_units: seconds - param_name: platform_timestamp type: float + param_units: seconds # -------------------------------------- - def_name: __eq__ params: - param_name: other type: carla.Timestamp + param_units: seconds # -------------------------------------- - def_name: __ne__ params: - param_name: other type: carla.Timestamp + param_units: seconds # -------------------------------------- - def_name: __str__ # -------------------------------------- @@ -131,8 +139,9 @@ - param_name: fixed_delta_seconds type: float default: 0.0 + param_units: seconds doc: > - Set this time in seconds to get a fixed time-step in between frames. 0.0 means variable time-step and it is the default mode. + Set a fixed time-step in between frames. 0.0 means variable time-step and it is the default mode. doc: > Creates an object containing desired settings that could later be applied through carla.World and its method **apply_settings()**. # -------------------------------------- @@ -226,8 +235,9 @@ - param_name: seconds type: float default: 10.0 + param_units: seconds doc: > - Maximum time in seconds the server should wait for a tick. It is set to 10.0 by default. + Maximum time the server should wait for a tick. It is set to 10.0 by default. doc: > This method only has effect on synchronous mode, when both client and server move together. The client tells the server when to step to the next frame and returns the id of the newly started frame. # -------------------------------------- @@ -237,8 +247,9 @@ - param_name: seconds type: float default: 10.0 + param_units: seconds doc: > - Maximum time in seconds the server should wait for a tick. It is set to 10.0 by default. + Maximum time the server should wait for a tick. It is set to 10.0 by default. doc: > The client tells the server to pause the simulation until a **World.tick()** is received. # -------------------------------------- @@ -411,20 +422,24 @@ params: - param_name: begin type: carla.Location + param_units: meters doc: > Point in the coordinate system where the arrow starts. - param_name: end type: carla.Location + param_units: meters doc: > Point in the coordinate system where the arrow ends and points towards to. - param_name: thickness type: float - default: 0.1f + default: 0.1 + param_units: meters doc: > Density of the line. - param_name: arrow_size type: float - default: 0.1f + default: 0.1 + param_units: meters doc: > Size of the tip of the arrow. - param_name: color @@ -434,9 +449,10 @@ RGB code to color the object. Red by default. - param_name: life_time type: float - default: -1.0f + default: -1.0 + param_units: seconds doc: > - Lifespan in seconds for the shape. By default it only lasts one frame. Set this to 0 for permanent shapes. + Shape's lifespan. By default it only lasts one frame. Set this to 0 for permanent shapes. doc: > Draws an arrow from `begin` to `end` pointing in that direction. @@ -449,11 +465,13 @@ Object containing a location and the length of a box for every axis. - param_name: rotation type: carla.Rotation + param_units: degrees doc: > Orientation of the box according to Unreal Engine's axis system. - param_name: thickness type: float - default: 0.1f + default: 0.1 + param_units: meters doc: > Density of the lines that define the box. - param_name: color @@ -463,9 +481,10 @@ RGB code to color the object. Red by default. - param_name: life_time type: float - default: -1.0f + default: -1.0 + param_units: seconds doc: > - Lifespan in seconds for the shape. By default it only lasts one frame. Set this to 0 for permanent shapes. + Shape's lifespan. By default it only lasts one frame. Set this to 0 for permanent shapes. doc: > Draws a box, ussually to act for object colliders. @@ -474,15 +493,18 @@ params: - param_name: begin type: carla.Location + param_units: meters doc: > Point in the coordinate system where the line starts. - param_name: end type: carla.Location + param_units: meters doc: > Spot in the coordinate system where the line ends. - param_name: thickness type: float - default: 0.1f + default: 0.1 + param_units: meters doc: > Density of the line. - param_name: color @@ -492,9 +514,10 @@ RGB code to color the object. Red by default. - param_name: life_time type: float - default: -1.0f + default: -1.0 + param_units: seconds doc: > - Lifespan in seconds for the shape. By default it only lasts one frame. Set this to 0 for permanent shapes. + Shape's lifespan. By default it only lasts one frame. Set this to 0 for permanent shapes. doc: > Draws a line in between `begin` and `end`. # -------------------------------------- @@ -502,11 +525,13 @@ params: - param_name: location type: carla.Location + param_units: meters doc: > Spot in the coordinate system to center the object. - param_name: size type: float - default: 0.1f + default: 0.1 + param_units: meters doc: > Density of the point. - param_name: color @@ -516,9 +541,10 @@ RGB code to color the object. Red by default. - param_name: life_time type: float - default: -1.0f + default: -1.0 + param_units: seconds doc: > - Lifespan in seconds for the shape. By default it only lasts one frame. Set this to 0 for permanent shapes. + Shape's lifespan. By default it only lasts one frame. Set this to 0 for permanent shapes. doc: > Draws a point `location`. # -------------------------------------- @@ -526,6 +552,7 @@ params: - param_name: location type: carla.Location + param_units: meters doc: > Spot in the simulation where the text will be centered. - param_name: text @@ -544,7 +571,10 @@ RGB code to color the string. Red by default. - param_name: life_time type: float - default: -1.0f + default: -1.0 + param_units: seconds + doc: > + Shape's lifespan. By default it only lasts one frame. Set this to 0 for permanent shapes. doc: > Draws a string in a given location of the simulation which can only be seen server-side. # -------------------------------------- From 638b43e97435ae0d665780435b285335adc71abd Mon Sep 17 00:00:00 2001 From: sergi-e Date: Mon, 14 Sep 2020 17:48:20 +0200 Subject: [PATCH 148/179] Added some specific notes on rotations --- Docs/core_actors.md | 5 ++++- Docs/python_api.md | 18 +++++++++--------- PythonAPI/docs/control.yml | 2 +- PythonAPI/docs/geom.yml | 11 ++++++++--- PythonAPI/docs/map.yml | 4 ++-- PythonAPI/docs/world.yml | 2 +- 6 files changed, 25 insertions(+), 17 deletions(-) diff --git a/Docs/core_actors.md b/Docs/core_actors.md index fa20569f047..b6cd046ccc4 100644 --- a/Docs/core_actors.md +++ b/Docs/core_actors.md @@ -74,10 +74,13 @@ The world has two different methods to spawn actors. * [`try_spawn_actor()`](python_api.md#carla.World.try_spawn_actor) returns `None` if the spawning fails. ```py -transform = Transform(Location(x=230, y=195, z=40), Rotation(yaw=180)) +transform = Transform(Location(x=230, y=195, z=40), Rotation(0,180,0)) actor = world.spawn_actor(blueprint, transform) ``` +!!! Note + CARLA uses the [Unreal Engine coordinates system](https://carla.readthedocs.io/en/latest/python_api/#carlarotation), and rotations are declared in a specific order, `(pitch,yaw,roll)`, which is different in the Unreal Engine Editor. + The actor will not be spawned in case of collision at the specified location. No matter if this happens with a static object or another actor. It is possible to try avoiding these undesired spawning collisions. * `map.get_spawn_points()` __for vehicles__. Returns a list of recommended spawning points. diff --git a/Docs/python_api.md b/Docs/python_api.md index f4dc3c06ba9..685fe31310e 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -583,7 +583,7 @@ Draws an arrow from `begin` to `end` pointing in that direction. Draws a box, ussually to act for object colliders. - **Parameters:** - `box` (_[carla.BoundingBox](#carla.BoundingBox)_) – Object containing a location and the length of a box for every axis. - - `rotation` (_[carla.Rotation](#carla.Rotation) – degrees_) – Orientation of the box according to Unreal Engine's axis system. + - `rotation` (_[carla.Rotation](#carla.Rotation) – degrees (pitch,yaw,roll)_) – Orientation of the box according to Unreal Engine's axis system. - `thickness` (_float – meters_) – Density of the lines that define the box. - `color` (_[carla.Color](#carla.Color)_) – RGB code to color the object. Red by default. - `life_time` (_float – seconds_) – Shape's lifespan. By default it only lasts one frame. Set this to 0 for permanent shapes. @@ -794,9 +794,9 @@ Additional text in the signal. - **h_offset** (_float – meters_) Orientation offset of the signal relative to the the definition of `road_id` at `s` in OpenDRIVE. - **pitch** (_float – meters_) -Pitch rotation (Y-axis) of the signal. +Pitch rotation of the signal (Y-axis in [UE coordinates system](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/python_api/#carlarotation)). - **roll** (_float_) -Roll rotation (X-axis) of the signal. +Roll rotation of the signal (X-axis in [UE coordinates system](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/python_api/#carlarotation)). - **waypoint** (_[carla.Waypoint](#carla.Waypoint)_) A waypoint placed in the lane of the one that made the query and at the `s` of the landmark. It is the first waypoint for which the landmark will be effective. - **transform** (_[carla.Transform](#carla.Transform)_) @@ -1483,9 +1483,8 @@ Retrieves the number of entries generated, same as **\__st --- ## carla.Rotation -Class that represents a 3D rotation and therefore, an orientation in space. - -![UE4_Rotation](https://d26ilriwvtzlb.cloudfront.net/8/83/BRMC_9.jpg) _Unreal Engine's standard (from [UE4 docs](https://wiki.unrealengine.com/Blueprint_Rotating_Movement_Component))_. +Class that represents a 3D rotation and therefore, an orientation in space. CARLA uses the Unreal Engine coordinates system. This is a Z-up left-handed system. However, the declaration order of the axis' rotation is different in CARLA than in Unreal Engine.
    +
    __CARLA:__ (pitch, yaw, roll) which correspond to (Y,Z,X) rotations.
    __UE4:__ (roll, pitch, yaw) which correspond to (X,Y,Z) rotations.

    ![UE4_Rotation](https://d26ilriwvtzlb.cloudfront.net/8/83/BRMC_9.jpg) *Unreal Engine's coordinates system*.

    Instance Variables

    - **pitch** (_float – degrees_) @@ -1501,6 +1500,7 @@ X-axis rotation angle. - `pitch` (_float – degrees_) – Y-axis rotation angle. - `yaw` (_float – degrees_) – Z-axis rotation angle. - `roll` (_float – degrees_) – X-axis rotation angle. + - **Warning:** _The declaration order is different in CARLA (pitch,yaw,roll) and in the Unreal Engine Editor (roll,pitch,yaw)._
    Getters
    - **get_forward_vector**(**self**) @@ -2038,14 +2038,14 @@ Class that defines a transformation, a combination of location and rotation, wit

    Instance Variables

    - **location** (_[carla.Location](#carla.Location)_) Describes a point in the coordinate system. -- **rotation** (_[carla.Rotation](#carla.Rotation)_) +- **rotation** (_[carla.Rotation](#carla.Rotation) – degrees (pitch, yaw, roll)_) Describes a rotation for an object according to Unreal Engine's axis system.

    Methods

    - **\__init__**(**self**, **location**, **rotation**) - **Parameters:** - `location` (_[carla.Location](#carla.Location)_) - - `rotation` (_[carla.Rotation](#carla.Rotation)_) + - `rotation` (_[carla.Rotation](#carla.Rotation) – degrees (pitch, yaw, roll)_) - **transform**(**self**, **in_point**) Translates a 3D point from local to global coordinates using the current transformation as frame of reference. - **Parameters:** @@ -2418,7 +2418,7 @@ If True, the walker will perform a jump. - **\__init__**(**self**, **direction**=[1.0, 0.0, 0.0], **speed**=0.0, **jump**=False) - **Parameters:** - `direction` (_[carla.Vector3D](#carla.Vector3D)_) - - `speed` (_float_) + - `speed` (_float – m/s_) - `jump` (_bool_)
    Dunder methods
    diff --git a/PythonAPI/docs/control.yml b/PythonAPI/docs/control.yml index 46ca5fe735f..5b289b21aed 100644 --- a/PythonAPI/docs/control.yml +++ b/PythonAPI/docs/control.yml @@ -119,7 +119,7 @@ type: carla.Vector3D - param_name: speed default: 0.0 - param_Units: m/s + param_units: m/s type: float - param_name: jump default: False diff --git a/PythonAPI/docs/geom.yml b/PythonAPI/docs/geom.yml index 8be2ad7ecbc..22f186f8598 100644 --- a/PythonAPI/docs/geom.yml +++ b/PythonAPI/docs/geom.yml @@ -214,11 +214,13 @@ - class_name: Rotation # - DESCRIPTION ------------------------ doc: > - Class that represents a 3D rotation and therefore, an orientation in space. - + Class that represents a 3D rotation and therefore, an orientation in space. CARLA uses the Unreal Engine coordinates system. This is a Z-up left-handed system. However, the declaration order of the axis' rotation is different in CARLA than in Unreal Engine.
    +
    __CARLA:__ (pitch, yaw, roll) which correspond to (Y,Z,X) rotations. +
    __UE4:__ (roll, pitch, yaw) which correspond to (X,Y,Z) rotations. +

    ![UE4_Rotation](https://d26ilriwvtzlb.cloudfront.net/8/83/BRMC_9.jpg) - _Unreal Engine's standard (from [UE4 docs](https://wiki.unrealengine.com/Blueprint_Rotating_Movement_Component))_ + *Unreal Engine's coordinates system* # - PROPERTIES ------------------------- instance_variables: - var_name: pitch @@ -258,6 +260,7 @@ param_units: degrees doc: > X-axis rotation angle. + warning: The declaration order is different in CARLA (pitch,yaw,roll) and in the Unreal Engine Editor (roll,pitch,yaw). # -------------------------------------- - def_name: get_forward_vector params: @@ -310,6 +313,7 @@ Describes a point in the coordinate system. - var_name: rotation type: carla.Rotation + var_units: degrees (pitch, yaw, roll) doc: > Describes a rotation for an object according to Unreal Engine's axis system. # - METHODS ---------------------------- @@ -320,6 +324,7 @@ type: carla.Location - param_name: rotation type: carla.Rotation + param_units: degrees (pitch, yaw, roll) # -------------------------------------- - def_name: transform params: diff --git a/PythonAPI/docs/map.yml b/PythonAPI/docs/map.yml index 994d8876be9..5c115b8a648 100644 --- a/PythonAPI/docs/map.yml +++ b/PythonAPI/docs/map.yml @@ -712,11 +712,11 @@ type: float var_units: meters doc: > - Pitch rotation (Y-axis) of the signal. + Pitch rotation of the signal (Y-axis in [UE coordinates system](https://carla.readthedocs.io/en/latest/python_api/#carlarotation)). - var_name: roll type: float doc: > - Roll rotation (X-axis) of the signal. + Roll rotation of the signal (X-axis in [UE coordinates system](https://carla.readthedocs.io/en/latest/python_api/#carlarotation)). - var_name: waypoint type: carla.Waypoint doc: > diff --git a/PythonAPI/docs/world.yml b/PythonAPI/docs/world.yml index cd9d519ff09..baa3c149dbb 100644 --- a/PythonAPI/docs/world.yml +++ b/PythonAPI/docs/world.yml @@ -465,7 +465,7 @@ Object containing a location and the length of a box for every axis. - param_name: rotation type: carla.Rotation - param_units: degrees + param_units: degrees (pitch,yaw,roll) doc: > Orientation of the box according to Unreal Engine's axis system. - param_name: thickness From d50cb35a9f833e97763db67139ad85ac40bd6e4c Mon Sep 17 00:00:00 2001 From: sergi-e Date: Tue, 15 Sep 2020 14:02:58 +0200 Subject: [PATCH 149/179] Fixed typos on normal impulse and accelerometer. Fixed angular impulse from N*m*s to degrees for carla.Actor and command.ApplyAngularImpulse() --- Docs/python_api.md | 16 ++++++++-------- PythonAPI/docs/actor.yml | 4 ++-- PythonAPI/docs/commands.yml | 8 ++++---- PythonAPI/docs/sensor_data.yml | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index 685fe31310e..7320d3d7e34 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -22,11 +22,11 @@ The identifier of the blueprint this actor was based on, e.g. "vehicle.ford.must - **add_impulse**(**self**, **impulse**) Adds an impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. - **Parameters:** - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N * s_) + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) - **add_angular_impulse**(**self**, **impulse**) Adds an angular impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. - **Parameters:** - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N * m * s_) + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – degrees_) - **destroy**(**self**) Tells the simulator to destroy this actor and returns True if it was successful. It has no effect if it was already destroyed. - **Return:** _bool_ @@ -462,7 +462,7 @@ Sets the maxixum time a network call is allowed before blocking it and raising a The actor the sensor is attached to, the one that measured the collision. - **other_actor** (_[carla.Actor](#carla.Actor)_) The second actor involved in the collision. -- **normal_impulse** (_[carla.Vector3D](#carla.Vector3D) – N*m_) +- **normal_impulse** (_[carla.Vector3D](#carla.Vector3D) – N*s_) Normal impulse resulting of the collision. --- @@ -685,7 +685,7 @@ West/East value of a point on the map.
    Inherited from _[carla.SensorData](#carla.SensorData)_

    Class that defines the data registered by a sensor.other.imu, regarding the sensor's transformation according to the current [carla.World](#carla.World). It essentially acts as accelerometer, gyroscope and compass.

    Instance Variables

    -- **accelerometer** (_[carla.Vector3D](#carla.Vector3D) – m*s2_) +- **accelerometer** (_[carla.Vector3D](#carla.Vector3D) – m/s2_) Linear acceleration. - **compass** (_float – radians_) Orientation with regard to the North ([0.0, -1.0, 0.0] in Unreal Engine). @@ -2802,14 +2802,14 @@ Command adaptation of **add_angular_impulse()** in

    Instance Variables

    - **actor_id** (_int_) Actor affected by the command. -- **impulse** (_[carla.Vector3D](#carla.Vector3D) – N * m * s_) +- **impulse** (_[carla.Vector3D](#carla.Vector3D) – degrees_) Angular impulse applied to the actor. Determines magnitude and global axis where it is applied.

    Methods

    - **\__init__**(**self**, **actor**, **impulse**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N * m * s_) + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – degrees_) --- @@ -2836,14 +2836,14 @@ Command adaptation of **add_impulse()** in [carla.A

    Instance Variables

    - **actor_id** (_int_) Actor affected by the command. -- **impulse** (_[carla.Vector3D](#carla.Vector3D) – N * s_) +- **impulse** (_[carla.Vector3D](#carla.Vector3D) – N*s_) Impulse applied to the actor.

    Methods

    - **\__init__**(**self**, **actor**, **impulse**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N * s_) + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) --- diff --git a/PythonAPI/docs/actor.yml b/PythonAPI/docs/actor.yml index f5c9dcab186..3685bd6e823 100644 --- a/PythonAPI/docs/actor.yml +++ b/PythonAPI/docs/actor.yml @@ -39,7 +39,7 @@ params: - param_name: impulse type: carla.Vector3D - param_units: N * s + param_units: N*s doc: > Adds an impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. # -------------------------------------- @@ -47,7 +47,7 @@ params: - param_name: impulse type: carla.Vector3D - param_units: N * m * s + param_units: degrees doc: > Adds an angular impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. # -------------------------------------- diff --git a/PythonAPI/docs/commands.yml b/PythonAPI/docs/commands.yml index e7ac3341eea..c0f89436300 100644 --- a/PythonAPI/docs/commands.yml +++ b/PythonAPI/docs/commands.yml @@ -270,7 +270,7 @@ Actor affected by the command. - var_name: impulse type: carla.Vector3D - var_units: N * s + var_units: N*s doc: > Impulse applied to the actor. # - METHODS ---------------------------- @@ -283,7 +283,7 @@ Actor or its ID to whom the command will be applied to. - param_name: impulse type: carla.Vector3D - param_units: N * s + param_units: N*s # -------------------------------------- - class_name: ApplyAngularImpulse @@ -298,7 +298,7 @@ Actor affected by the command. - var_name: impulse type: carla.Vector3D - var_units: N * m * s + var_units: degrees doc: > Angular impulse applied to the actor. Determines magnitude and global axis where it is applied. # - METHODS ---------------------------- @@ -311,7 +311,7 @@ Actor or its ID to whom the command will be applied to. - param_name: impulse type: carla.Vector3D - param_units: N * m * s + param_units: degrees # -------------------------------------- - class_name: SetSimulatePhysics diff --git a/PythonAPI/docs/sensor_data.yml b/PythonAPI/docs/sensor_data.yml index 6897d85a76a..56af9815ed8 100644 --- a/PythonAPI/docs/sensor_data.yml +++ b/PythonAPI/docs/sensor_data.yml @@ -294,7 +294,7 @@ The second actor involved in the collision. - var_name: normal_impulse type: carla.Vector3D - var_units: N*m + var_units: N*s doc: > Normal impulse resulting of the collision. @@ -379,7 +379,7 @@ instance_variables: - var_name: accelerometer type: carla.Vector3D - var_units: m*s2 + var_units: m/s2 doc: > Linear acceleration. - var_name: compass From c9e8c09b413fe4d9ba7a73208402f642fdf2d895 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Tue, 15 Sep 2020 15:40:57 +0200 Subject: [PATCH 150/179] New fixes on M and D comments --- Docs/core_actors.md | 6 +++--- Docs/python_api.md | 36 +++++++++++++++++----------------- PythonAPI/docs/doc_gen.py | 11 +++++++---- PythonAPI/docs/sensor.yml | 30 ++++++++++++++-------------- PythonAPI/docs/sensor_data.yml | 7 ++++--- 5 files changed, 47 insertions(+), 43 deletions(-) diff --git a/Docs/core_actors.md b/Docs/core_actors.md index b6cd046ccc4..39102d1b659 100644 --- a/Docs/core_actors.md +++ b/Docs/core_actors.md @@ -74,12 +74,12 @@ The world has two different methods to spawn actors. * [`try_spawn_actor()`](python_api.md#carla.World.try_spawn_actor) returns `None` if the spawning fails. ```py -transform = Transform(Location(x=230, y=195, z=40), Rotation(0,180,0)) +transform = Transform(Location(x=230, y=195, z=40), Rotation(yaw=180)) actor = world.spawn_actor(blueprint, transform) ``` -!!! Note - CARLA uses the [Unreal Engine coordinates system](https://carla.readthedocs.io/en/latest/python_api/#carlarotation), and rotations are declared in a specific order, `(pitch,yaw,roll)`, which is different in the Unreal Engine Editor. +!!! Important + CARLA uses the [Unreal Engine coordinates system](https://carla.readthedocs.io/en/latest/python_api/#carlarotation). Remember that [`carla.Rotation`](https://carla.readthedocs.io/en/latest/python_api/#carlarotation) constructor is defined as `(pitch, yaw, roll)`, that differs from Unreal Engine Editor `(roll, pitch, yaw)`. The actor will not be spawned in case of collision at the specified location. No matter if this happens with a static object or another actor. It is possible to try avoiding these undesired spawning collisions. diff --git a/Docs/python_api.md b/Docs/python_api.md index 7320d3d7e34..bce89d6f30a 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -1728,9 +1728,9 @@ Data contained inside a [carla.SemanticLidarMeasurement](#carla.SemanticLidarMea - **cos_inc_angle** (_float_) Cosine of the incident angle between the ray, and the normal of the hit object. - **object_idx** (_uint_) -[CARLA index](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/ref_sensors/#semantic-segmentation-camera) of the hit actor. +ID of the actor hit by the ray. - **object_tag** (_uint_) -[Semantic tag](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/ref_sensors/#semantic-segmentation-camera) of the hit component. +[Semantic tag](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/ref_sensors/#semantic-segmentation-camera) of the component hit by the ray.

    Methods

    @@ -1745,8 +1745,8 @@ Cosine of the incident angle between the ray, and the normal of the hit object.

    Instance Variables

    - **channels** (_int_) Number of lasers shot. -- **horizontal_angle** (_float_) -Horizontal angle the LIDAR is rotated at the time of the measurement (in radians). +- **horizontal_angle** (_float – radians_) +Horizontal angle the LIDAR is rotated at the time of the measurement. - **raw_data** (_bytes_) Received list of raw detection points. Each point consists of [x,y,z] coordinates plus the cosine of the incident angle, the index of the hit actor, and its semantic tag. @@ -1774,20 +1774,20 @@ Retrieves the number of points sorted by channel that are generated by this meas ## carla.Sensor
    Inherited from _[carla.Actor](#carla.Actor)_

    Sensors compound a specific family of actors quite diverse and unique. They are normally spawned as attachment/sons of a vehicle (take a look at [carla.World](#carla.World) to learn about actor spawning). Sensors are thoroughly designed to retrieve different types of data that they are listening to. The data they receive is shaped as different subclasses inherited from [carla.SensorData](#carla.SensorData) (depending on the sensor). - Most sensors can be divided in two groups: those receiving data on every tick (cameras, point clouds and some specific sensors) and those who only receive under certain circumstances (trigger detectors). CARLA provides a specific set of sensors and their blueprint can be found in [carla.BlueprintLibrary](#carla.BlueprintLibrary). All the information on their preferences and settlement can be found [here](ref_sensors.md), but the list of those available in CARLA so far goes as follow. - Receive data on every tick. - - [Depth camera](ref_sensors.md#depth-camera). - - [Gnss sensor](ref_sensors.md#gnss-sensor). - - [IMU sensor](ref_sensors.md#imu-sensor). - - [Lidar raycast](ref_sensors.md#lidar-raycast-sensor). - - [SemanticLidar raycast](ref_sensors.md#semanticlidar-raycast-sensor). - - [Radar](ref_sensors.md#radar-sensor). - - [RGB camera](ref_sensors.md#rgb-camera). - - [RSS sensor](ref_sensors.md#rss-sensor). - - [Semantic Segmentation camera](ref_sensors.md#semantic-segmentation-camera). - Only receive data when triggered. - - [Collision detector](ref_sensors.md#collision-detector). - - [Lane invasion detector](ref_sensors.md#lane-invasion-detector). + Most sensors can be divided in two groups: those receiving data on every tick (cameras, point clouds and some specific sensors) and those who only receive under certain circumstances (trigger detectors). CARLA provides a specific set of sensors and their blueprint can be found in [carla.BlueprintLibrary](#carla.BlueprintLibrary). All the information on their preferences and settlement can be found [here](ref_sensors.md), but the list of those available in CARLA so far goes as follow. +
    Receive data on every tick. + - [Depth camera](ref_sensors.md#depth-camera). + - [Gnss sensor](ref_sensors.md#gnss-sensor). + - [IMU sensor](ref_sensors.md#imu-sensor). + - [Lidar raycast](ref_sensors.md#lidar-raycast-sensor). + - [SemanticLidar raycast](ref_sensors.md#semanticlidar-raycast-sensor). + - [Radar](ref_sensors.md#radar-sensor). + - [RGB camera](ref_sensors.md#rgb-camera). + - [RSS sensor](ref_sensors.md#rss-sensor). + - [Semantic Segmentation camera](ref_sensors.md#semantic-segmentation-camera). +
    Only receive data when triggered. + - [Collision detector](ref_sensors.md#collision-detector). + - [Lane invasion detector](ref_sensors.md#lane-invasion-detector). - [Obstacle detector](ref_sensors.md#obstacle-detector).

    Instance Variables

    diff --git a/PythonAPI/docs/doc_gen.py b/PythonAPI/docs/doc_gen.py index 7a271564ecb..d8247a4228d 100755 --- a/PythonAPI/docs/doc_gen.py +++ b/PythonAPI/docs/doc_gen.py @@ -129,6 +129,9 @@ def brackets(buf): def parentheses(buf): return join(['(', buf, ')']) +def small_html(buf): + return join([''+buf+'']) + def small(buf): return join(['', buf, '']) @@ -334,7 +337,7 @@ def add_doc_method_param(md, param): if valid_dic_val(param, 'doc'): param_doc = create_hyperlinks(md.prettify_doc(param['doc'])) if valid_dic_val(param, 'param_units'): - param_units = ' – '+create_hyperlinks(param['param_units']+'') + param_units = small_html(' – '+param['param_units']) param_type = '' if not param_type else parentheses(italic(param_type+param_units)) md.list_push(code(param_name)) if param_type: @@ -377,7 +380,7 @@ def add_doc_method(md, method, class_key): md.list_push(bold('Return:') + ' ') return_units = '' if valid_dic_val(method, 'return_units'): - return_units = ' – '+create_hyperlinks(method['return_units']+'') + return_units = small_html(' – '+method['return_units']) md.textn(italic(create_hyperlinks(method['return'])+return_units)) md.list_pop() @@ -431,7 +434,7 @@ def add_doc_getter_setter(md, method,class_key,is_getter,other_list): md.list_push(bold('Return:') + ' ') return_units = '' if valid_dic_val(method, 'return_units'): - return_units = ' – '+create_hyperlinks(method['return_units']+'') + return_units = small_html(' – '+method['return_units']) md.textn(italic(create_hyperlinks(method['return'])+return_units)) md.list_pop() @@ -507,7 +510,7 @@ def add_doc_inst_var(md, inst_var, class_key): # Instance variable type if valid_dic_val(inst_var, 'type'): if valid_dic_val(inst_var, 'var_units'): - var_units = ' – '+create_hyperlinks(inst_var['var_units']+'') + var_units = small_html(' – '+inst_var['var_units']) var_type = ' ' + parentheses(italic(create_hyperlinks(inst_var['type']+var_units))) md.list_pushn( html_key(var_key) + diff --git a/PythonAPI/docs/sensor.yml b/PythonAPI/docs/sensor.yml index 466685b31a6..69aba6bc032 100644 --- a/PythonAPI/docs/sensor.yml +++ b/PythonAPI/docs/sensor.yml @@ -8,21 +8,21 @@ doc: > Sensors compound a specific family of actors quite diverse and unique. They are normally spawned as attachment/sons of a vehicle (take a look at carla.World to learn about actor spawning). Sensors are thoroughly designed to retrieve different types of data that they are listening to. The data they receive is shaped as different subclasses inherited from carla.SensorData (depending on the sensor). - Most sensors can be divided in two groups: those receiving data on every tick (cameras, point clouds and some specific sensors) and those who only receive under certain circumstances (trigger detectors). CARLA provides a specific set of sensors and their blueprint can be found in carla.BlueprintLibrary. All the information on their preferences and settlement can be found [here](ref_sensors.md), but the list of those available in CARLA so far goes as follow. - Receive data on every tick. - - [Depth camera](ref_sensors.md#depth-camera). - - [Gnss sensor](ref_sensors.md#gnss-sensor). - - [IMU sensor](ref_sensors.md#imu-sensor). - - [Lidar raycast](ref_sensors.md#lidar-raycast-sensor). - - [SemanticLidar raycast](ref_sensors.md#semanticlidar-raycast-sensor). - - [Radar](ref_sensors.md#radar-sensor). - - [RGB camera](ref_sensors.md#rgb-camera). - - [RSS sensor](ref_sensors.md#rss-sensor). - - [Semantic Segmentation camera](ref_sensors.md#semantic-segmentation-camera). - Only receive data when triggered. - - [Collision detector](ref_sensors.md#collision-detector). - - [Lane invasion detector](ref_sensors.md#lane-invasion-detector). - - [Obstacle detector](ref_sensors.md#obstacle-detector). + Most sensors can be divided in two groups: those receiving data on every tick (cameras, point clouds and some specific sensors) and those who only receive under certain circumstances (trigger detectors). CARLA provides a specific set of sensors and their blueprint can be found in carla.BlueprintLibrary. All the information on their preferences and settlement can be found [here](ref_sensors.md), but the list of those available in CARLA so far goes as follow. +
    Receive data on every tick. + - [Depth camera](ref_sensors.md#depth-camera). + - [Gnss sensor](ref_sensors.md#gnss-sensor). + - [IMU sensor](ref_sensors.md#imu-sensor). + - [Lidar raycast](ref_sensors.md#lidar-raycast-sensor). + - [SemanticLidar raycast](ref_sensors.md#semanticlidar-raycast-sensor). + - [Radar](ref_sensors.md#radar-sensor). + - [RGB camera](ref_sensors.md#rgb-camera). + - [RSS sensor](ref_sensors.md#rss-sensor). + - [Semantic Segmentation camera](ref_sensors.md#semantic-segmentation-camera). +
    Only receive data when triggered. + - [Collision detector](ref_sensors.md#collision-detector). + - [Lane invasion detector](ref_sensors.md#lane-invasion-detector). + - [Obstacle detector](ref_sensors.md#obstacle-detector). # - PROPERTIES ------------------------- instance_variables: diff --git a/PythonAPI/docs/sensor_data.yml b/PythonAPI/docs/sensor_data.yml index 56af9815ed8..4ea1c3e86b4 100644 --- a/PythonAPI/docs/sensor_data.yml +++ b/PythonAPI/docs/sensor_data.yml @@ -205,8 +205,9 @@ Number of lasers shot. - var_name: horizontal_angle type: float + var_units: radians doc: > - Horizontal angle the LIDAR is rotated at the time of the measurement (in radians). + Horizontal angle the LIDAR is rotated at the time of the measurement. - var_name: raw_data type: bytes doc: > @@ -266,12 +267,12 @@ - var_name: object_idx type: uint doc: > - [CARLA index](https://carla.readthedocs.io/en/latest/ref_sensors/#semantic-segmentation-camera) of the hit actor. + ID of the actor hit by the ray. # -------------------------------------- - var_name: object_tag type: uint doc: > - [Semantic tag](https://carla.readthedocs.io/en/latest/ref_sensors/#semantic-segmentation-camera) of the hit component. + [Semantic tag](https://carla.readthedocs.io/en/latest/ref_sensors/#semantic-segmentation-camera) of the component hit by the ray. # - METHODS ---------------------------- methods: - def_name: __str__ From 2613604bc11f7653b3d371bda41b46105d4cf42d Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 16 Sep 2020 22:28:30 +0200 Subject: [PATCH 151/179] New iteration on O and B reviews --- Docs/python_api.md | 18 +++++++++--------- PythonAPI/docs/actor.yml | 2 +- PythonAPI/docs/commands.yml | 8 ++++---- PythonAPI/docs/geom.yml | 12 +++++------- PythonAPI/docs/sensor_data.yml | 2 +- 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index bce89d6f30a..fc2f1d07062 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -22,7 +22,7 @@ The identifier of the blueprint this actor was based on, e.g. "vehicle.ford.must - **add_impulse**(**self**, **impulse**) Adds an impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. - **Parameters:** - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N_) - **add_angular_impulse**(**self**, **impulse**) Adds an angular impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. - **Parameters:** @@ -462,7 +462,7 @@ Sets the maxixum time a network call is allowed before blocking it and raising a The actor the sensor is attached to, the one that measured the collision. - **other_actor** (_[carla.Actor](#carla.Actor)_) The second actor involved in the collision. -- **normal_impulse** (_[carla.Vector3D](#carla.Vector3D) – N*s_) +- **normal_impulse** (_[carla.Vector3D](#carla.Vector3D) – N_) Normal impulse resulting of the collision. --- @@ -1483,8 +1483,8 @@ Retrieves the number of entries generated, same as **\__st --- ## carla.Rotation -Class that represents a 3D rotation and therefore, an orientation in space. CARLA uses the Unreal Engine coordinates system. This is a Z-up left-handed system. However, the declaration order of the axis' rotation is different in CARLA than in Unreal Engine.
    -
    __CARLA:__ (pitch, yaw, roll) which correspond to (Y,Z,X) rotations.
    __UE4:__ (roll, pitch, yaw) which correspond to (X,Y,Z) rotations.

    ![UE4_Rotation](https://d26ilriwvtzlb.cloudfront.net/8/83/BRMC_9.jpg) *Unreal Engine's coordinates system*. +Class that represents a 3D rotation and therefore, an orientation in space. CARLA uses the Unreal Engine coordinates system. This is a Z-up left-handed system.
    +
    The constructor method follows a specific order of declaration: `(pitch, yaw, roll)`, which corresponds to `(Y-rotation,Z-rotation,X-rotation)`.

    ![UE4_Rotation](https://d26ilriwvtzlb.cloudfront.net/8/83/BRMC_9.jpg) *Unreal Engine's coordinates system*.

    Instance Variables

    - **pitch** (_float – degrees_) @@ -1500,7 +1500,7 @@ X-axis rotation angle. - `pitch` (_float – degrees_) – Y-axis rotation angle. - `yaw` (_float – degrees_) – Z-axis rotation angle. - `roll` (_float – degrees_) – X-axis rotation angle. - - **Warning:** _The declaration order is different in CARLA (pitch,yaw,roll) and in the Unreal Engine Editor (roll,pitch,yaw)._ + - **Warning:** _The declaration order is different in CARLA (pitch,yaw,roll), and in the Unreal Engine Editor (roll,pitch,yaw). When working in a build from source, don't mix up the axes' rotations._
    Getters
    - **get_forward_vector**(**self**) @@ -2819,14 +2819,14 @@ Command adaptation of **set_angular_velocity()** in

    Instance Variables

    - **actor_id** (_int_) Actor affected by the command. -- **angular_velocity** (_[carla.Vector3D](#carla.Vector3D) – rad/s_) +- **angular_velocity** (_[carla.Vector3D](#carla.Vector3D) – deg/s_) The 3D angular velocity that will be applied to the actor.

    Methods

    - **\__init__**(**self**, **actor**, **angular_velocity**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `angular_velocity` (_[carla.Vector3D](#carla.Vector3D) – rad/s_) + - `angular_velocity` (_[carla.Vector3D](#carla.Vector3D) – deg/s_) --- @@ -2836,14 +2836,14 @@ Command adaptation of **add_impulse()** in [carla.A

    Instance Variables

    - **actor_id** (_int_) Actor affected by the command. -- **impulse** (_[carla.Vector3D](#carla.Vector3D) – N*s_) +- **impulse** (_[carla.Vector3D](#carla.Vector3D) – N_) Impulse applied to the actor.

    Methods

    - **\__init__**(**self**, **actor**, **impulse**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N_) --- diff --git a/PythonAPI/docs/actor.yml b/PythonAPI/docs/actor.yml index 3685bd6e823..2384f1276b3 100644 --- a/PythonAPI/docs/actor.yml +++ b/PythonAPI/docs/actor.yml @@ -39,7 +39,7 @@ params: - param_name: impulse type: carla.Vector3D - param_units: N*s + param_units: N doc: > Adds an impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. # -------------------------------------- diff --git a/PythonAPI/docs/commands.yml b/PythonAPI/docs/commands.yml index c0f89436300..0b5bca5e431 100644 --- a/PythonAPI/docs/commands.yml +++ b/PythonAPI/docs/commands.yml @@ -242,7 +242,7 @@ Actor affected by the command. - var_name: angular_velocity type: carla.Vector3D - var_units: rad/s + var_units: deg/s doc: > The 3D angular velocity that will be applied to the actor. # - METHODS ---------------------------- @@ -255,7 +255,7 @@ Actor or its ID to whom the command will be applied to. - param_name: angular_velocity type: carla.Vector3D - param_units: rad/s + param_units: deg/s # -------------------------------------- - class_name: ApplyImpulse @@ -270,7 +270,7 @@ Actor affected by the command. - var_name: impulse type: carla.Vector3D - var_units: N*s + var_units: N doc: > Impulse applied to the actor. # - METHODS ---------------------------- @@ -283,7 +283,7 @@ Actor or its ID to whom the command will be applied to. - param_name: impulse type: carla.Vector3D - param_units: N*s + param_units: N # -------------------------------------- - class_name: ApplyAngularImpulse diff --git a/PythonAPI/docs/geom.yml b/PythonAPI/docs/geom.yml index 22f186f8598..9ccc3f7da22 100644 --- a/PythonAPI/docs/geom.yml +++ b/PythonAPI/docs/geom.yml @@ -214,12 +214,10 @@ - class_name: Rotation # - DESCRIPTION ------------------------ doc: > - Class that represents a 3D rotation and therefore, an orientation in space. CARLA uses the Unreal Engine coordinates system. This is a Z-up left-handed system. However, the declaration order of the axis' rotation is different in CARLA than in Unreal Engine.
    - -
    __CARLA:__ (pitch, yaw, roll) which correspond to (Y,Z,X) rotations. -
    __UE4:__ (roll, pitch, yaw) which correspond to (X,Y,Z) rotations. -

    - ![UE4_Rotation](https://d26ilriwvtzlb.cloudfront.net/8/83/BRMC_9.jpg) + Class that represents a 3D rotation and therefore, an orientation in space. CARLA uses the Unreal Engine coordinates system. This is a Z-up left-handed system.
    + +
    The constructor method follows a specific order of declaration: `(pitch, yaw, roll)`, which corresponds to `(Y-rotation,Z-rotation,X-rotation)`.
    +
    ![UE4_Rotation](https://d26ilriwvtzlb.cloudfront.net/8/83/BRMC_9.jpg) *Unreal Engine's coordinates system* # - PROPERTIES ------------------------- instance_variables: @@ -260,7 +258,7 @@ param_units: degrees doc: > X-axis rotation angle. - warning: The declaration order is different in CARLA (pitch,yaw,roll) and in the Unreal Engine Editor (roll,pitch,yaw). + warning: The declaration order is different in CARLA (pitch,yaw,roll), and in the Unreal Engine Editor (roll,pitch,yaw). When working in a build from source, don't mix up the axes' rotations. # -------------------------------------- - def_name: get_forward_vector params: diff --git a/PythonAPI/docs/sensor_data.yml b/PythonAPI/docs/sensor_data.yml index 4ea1c3e86b4..4a03d86ab4f 100644 --- a/PythonAPI/docs/sensor_data.yml +++ b/PythonAPI/docs/sensor_data.yml @@ -295,7 +295,7 @@ The second actor involved in the collision. - var_name: normal_impulse type: carla.Vector3D - var_units: N*s + var_units: N doc: > Normal impulse resulting of the collision. From 8e52da614cb2eafdb22a6c43c38e466ee2236f9f Mon Sep 17 00:00:00 2001 From: sergi-e Date: Thu, 17 Sep 2020 13:10:57 +0200 Subject: [PATCH 152/179] Impulse fixed to N*s --- Docs/python_api.md | 8 ++++---- PythonAPI/docs/actor.yml | 2 +- PythonAPI/docs/commands.yml | 4 ++-- PythonAPI/docs/sensor_data.yml | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index fc2f1d07062..17c8f8bfe29 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -22,7 +22,7 @@ The identifier of the blueprint this actor was based on, e.g. "vehicle.ford.must - **add_impulse**(**self**, **impulse**) Adds an impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. - **Parameters:** - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N_) + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) - **add_angular_impulse**(**self**, **impulse**) Adds an angular impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. - **Parameters:** @@ -462,7 +462,7 @@ Sets the maxixum time a network call is allowed before blocking it and raising a The actor the sensor is attached to, the one that measured the collision. - **other_actor** (_[carla.Actor](#carla.Actor)_) The second actor involved in the collision. -- **normal_impulse** (_[carla.Vector3D](#carla.Vector3D) – N_) +- **normal_impulse** (_[carla.Vector3D](#carla.Vector3D) – N*s_) Normal impulse resulting of the collision. --- @@ -2836,14 +2836,14 @@ Command adaptation of **add_impulse()** in [carla.A

    Instance Variables

    - **actor_id** (_int_) Actor affected by the command. -- **impulse** (_[carla.Vector3D](#carla.Vector3D) – N_) +- **impulse** (_[carla.Vector3D](#carla.Vector3D) – N*s_) Impulse applied to the actor.

    Methods

    - **\__init__**(**self**, **actor**, **impulse**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N_) + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) --- diff --git a/PythonAPI/docs/actor.yml b/PythonAPI/docs/actor.yml index 2384f1276b3..3685bd6e823 100644 --- a/PythonAPI/docs/actor.yml +++ b/PythonAPI/docs/actor.yml @@ -39,7 +39,7 @@ params: - param_name: impulse type: carla.Vector3D - param_units: N + param_units: N*s doc: > Adds an impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. # -------------------------------------- diff --git a/PythonAPI/docs/commands.yml b/PythonAPI/docs/commands.yml index 0b5bca5e431..83b59498dfb 100644 --- a/PythonAPI/docs/commands.yml +++ b/PythonAPI/docs/commands.yml @@ -270,7 +270,7 @@ Actor affected by the command. - var_name: impulse type: carla.Vector3D - var_units: N + var_units: N*s doc: > Impulse applied to the actor. # - METHODS ---------------------------- @@ -283,7 +283,7 @@ Actor or its ID to whom the command will be applied to. - param_name: impulse type: carla.Vector3D - param_units: N + param_units: N*s # -------------------------------------- - class_name: ApplyAngularImpulse diff --git a/PythonAPI/docs/sensor_data.yml b/PythonAPI/docs/sensor_data.yml index 4a03d86ab4f..4ea1c3e86b4 100644 --- a/PythonAPI/docs/sensor_data.yml +++ b/PythonAPI/docs/sensor_data.yml @@ -295,7 +295,7 @@ The second actor involved in the collision. - var_name: normal_impulse type: carla.Vector3D - var_units: N + var_units: N*s doc: > Normal impulse resulting of the collision. From 634383f1aa8bb868120dd0cdf15a79f10a7dbde6 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 16 Sep 2020 23:06:42 +0200 Subject: [PATCH 153/179] First iteration --- Docs/build_linux.md | 11 +++++++++++ Docs/build_windows.md | 17 ++++++++++------- Docs/ros_installation.md | 18 ++++++++++++++---- Docs/start_quickstart.md | 9 +++++++++ 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/Docs/build_linux.md b/Docs/build_linux.md index 60dd0573e85..72aa10ba786 100644 --- a/Docs/build_linux.md +++ b/Docs/build_linux.md @@ -86,8 +86,13 @@ cd PythonAPI/examples python3 spawn_npc.py # Terminal B cd PythonAPI/examples +python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) python3 dynamic_weather.py # Support for Python2 was provided until 0.9.10 (not included) + +# Optionally, to compile the PythonAPI for Python2, run the following command in the root CARLA directory. +make PythonAPI ARGS="--python-version=2" ``` + --- @@ -300,6 +305,12 @@ python3 dynamic_weather.py !!! Important If the simulation is running at very low FPS rates, go to `Edit/Editor preferences/Performance` in the UE editor and disable __Use less CPU when in background__. +Optionally, to compile the PythonAPI for Python2, run the following command in the root CARLA directory. + +```sh +make PythonAPI ARGS="--python-version=2" +``` + Now CARLA is ready to go. Here is a brief summary of the most useful `make` commands available.
    5 Pole (153, 153, 153)Small mainly vertically oriented pole. If the pole has a horizontal part (often for traffic light poles) this is also considered pole.
    E.g. sign pole, traffic light poles.E
    Small mainly vertically oriented pole. If the pole has a horizontal part (often for traffic light poles) this is also considered pole.
    E.g. sign pole, traffic light poles.
    6 RoadLine19 Static (110, 190, 160)Elements in the scene and props that are immovable. E.g. fire hydrants, fixed benches, fountains, bus stops, etc.Elements in the scene and props that are immovable.
    E.g. fire hydrants, fixed benches, fountains, bus stops, etc.
    20 Dynamic (170, 120, 50)Elements whose position is susceptible to change over time. E.g. Movable trash bins, buggies, bags, wheelchairs, animals, etc.Elements whose position is susceptible to change over time.
    E.g. Movable trash bins, buggies, bags, wheelchairs, animals, etc.
    21 Water
    diff --git a/Docs/build_windows.md b/Docs/build_windows.md index b855d384fea..2694ceecfb2 100644 --- a/Docs/build_windows.md +++ b/Docs/build_windows.md @@ -23,9 +23,6 @@ The build process can be quite long and tedious. The **[F.A.Q.](build_faq.md)**
    To execute the make commands below, you must use the Visual Studio 2017 native console x64 with administrator rights, otherwise you may be getting permission errors. -!!! Important - To execute the ```make``` commands below, you **must** use the Visual Studio 2017 native console x64 **with** administrator rights, otherwise you may be getting permission errors. - ```sh # Make sure to meet the minimum requirements. @@ -46,13 +43,17 @@ git clone https://github.com/carla-simulator/carla make PythonAPI make launch -# Press play in the Editor to initialize the server, and run example scripts to test CARLA. +# Press play in the Editor to initialize the server +# Run example scripts to test CARLA # Terminal A cd PythonAPI/examples python3 spawn_npc.py # Terminal B cd PythonAPI/examples -python3 dynamic_weather.py # Support for Python2 was provided until 0.9.10 (not included) +python3 dynamic_weather.py +# The PythonAPI will be built based on the installed Python version +# The docs will use Python3, as support for Python2 was provided until 0.9.10 (not included) + ``` @@ -161,18 +162,20 @@ The project may ask to build other instances such as `UE4Editor-Carla.dll` the f Finally, let's test the simulator. Inside `PythonAPI/examples` and `PythonAPI/util` there are some example scripts that may be especially useful for starters. The following commands will spawn some life into the town, and create a weather cycle. Each script should be run in one terminal ```sh -# Support for Python2 was provided until 0.9.10 (not included) # Terminal A cd PythonAPI/examples python3 spawn_npc.py # Terminal B cd PythonAPI/examples python3 dynamic_weather.py +# The PythonAPI will be built based on the installed Python version +# The docs will use Python3, as support for Python2 was provided until 0.9.10 (not included) ``` + !!! Important If the simulation is running at very low FPS rates, go to `Edit/Editor preferences/Performance` in the UE editor and disable __Use less CPU when in background__. -Now CARLA is ready to go. Here is a brief summary of the most useful `make` commands available. +Now CARLA is ready to go. Here is a brief summary of the most useful `make` commands available.
    diff --git a/Docs/ros_installation.md b/Docs/ros_installation.md index 26f96ae6da2..5cf3a4b6986 100644 --- a/Docs/ros_installation.md +++ b/Docs/ros_installation.md @@ -1,6 +1,7 @@ # ROS bridge installation * [__Requirements__](#requirements) + * [Python2](#python2) * [__Bridge installation__](#bridge-installation) * [A. Using Debian repository](#a-using-debian-repository) * [B. Using source repository](#b-using-source-repository) @@ -11,7 +12,6 @@ The ROS bridge enables two-way communication between ROS and CARLA. The informat --- ## Requirements -### ROS Kinetic/Melodic * __ROS Kinetic/Melodic.__ Install ROS [Melodic](http://wiki.ros.org/melodic/Installation/Ubuntu), for Ubuntu 18.04, or [Kinetic](http://wiki.ros.org/kinetic/Installation), for Ubuntu 16.04. ROS packages may be required, depending on the user needs. [rviz](http://wiki.ros.org/rviz) to visualize ROS data.j * __CARLA 0.9.7 or later.__ Previous versions are not compatible with the ROS bridge. Follow the [quick start installation](start_quickstart.md) or make the build for the corresponding platform. @@ -19,9 +19,22 @@ The ROS bridge enables two-way communication between ROS and CARLA. The informat !!! Important Make sure that both CARLA and ROS work properly before continuing with the installation. +### Python2 + +Those using ROS Kinetic or Melodic will need Python2 in order to run the ROS bridge. This is no problem for previous versions of CARLA. However, since 0.9.10 (included), CARLA does not provide support for Python2. + +In order to compile the necessary `.egg` file of the PythonAPI for Python2, run the following command in the root CARLA directory. + +```sh +make PythonAPI ARGS="--python-version=2" +``` + --- ## Bridge installation +!!! Important + To install ROS bridge versions prior to 0.9.10, change to a previous version of the documentation using the pannel in the bottom right corner of the window, and follow the old instructions. + ### A. Using Debian repository Set up the Debian repository in the system. @@ -40,9 +53,6 @@ This repository contains features from CARLA 0.9.10 and later versions. To insta sudo apt-get install carla-ros-bridge=0.9.10-1 # In this case, "0.9.10" refers to the ROS bridge version, and "1" to the Debian revision. ``` -!!! Important - To install ROS bridge versions prior to 0.9.10, change to a previous version of the documentation using the pannel in the bottom right corner of the window, and follow the old instructions. - ### B. Using source repository A catkin workspace is needed to use the ROS bridge. It should be cloned and built in there. The following code creates a new workspace, and clones the repository in there. diff --git a/Docs/start_quickstart.md b/Docs/start_quickstart.md index 2d9ee32404a..954d6b06c9c 100644 --- a/Docs/start_quickstart.md +++ b/Docs/start_quickstart.md @@ -49,6 +49,9 @@ cd /opt/carla-simulator cd PythonAPI/examples python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) +# Optionally, to compile the PythonAPI for Python2, run the following command in the root CARLA directory. +make PythonAPI ARGS="--python-version=2" + ``` @@ -149,6 +152,12 @@ Now it is time to start running scripts. The following example will spawn some l > python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) ``` +Optionally, to compile the PythonAPI for Python2, run the following command in the root CARLA directory. + +```sh +make PythonAPI ARGS="--python-version=2" +``` + #### Command-line options There are some configuration options available when launching CARLA. From fb1bb8c4d79030038f466424b3c5657a82103ad6 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Sun, 20 Sep 2020 10:53:48 +0200 Subject: [PATCH 154/179] Second iteration on J comments --- Docs/build_linux.md | 2 +- Docs/build_windows.md | 4 ++-- Docs/ros_installation.md | 28 +++++++++++++++++----------- Docs/start_quickstart.md | 31 ++++++++++++++----------------- 4 files changed, 34 insertions(+), 31 deletions(-) diff --git a/Docs/build_linux.md b/Docs/build_linux.md index 72aa10ba786..79377a4c936 100644 --- a/Docs/build_linux.md +++ b/Docs/build_linux.md @@ -89,7 +89,7 @@ cd PythonAPI/examples python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) python3 dynamic_weather.py # Support for Python2 was provided until 0.9.10 (not included) -# Optionally, to compile the PythonAPI for Python2, run the following command in the root CARLA directory. +# Optionally, to compile the PythonAPI for Python2, run the following command in the root CARLA directory make PythonAPI ARGS="--python-version=2" ``` diff --git a/Docs/build_windows.md b/Docs/build_windows.md index 2694ceecfb2..614fbee8817 100644 --- a/Docs/build_windows.md +++ b/Docs/build_windows.md @@ -24,7 +24,7 @@ The build process can be quite long and tedious. The **[F.A.Q.](build_faq.md)** To execute the make commands below, you must use the Visual Studio 2017 native console x64 with administrator rights, otherwise you may be getting permission errors. ```sh -# Make sure to meet the minimum requirements. +# Make sure to meet the minimum requirements # Necessary software: # CMake @@ -32,7 +32,7 @@ To execute the make commands below, you must use the Visual # Make # Python3 x64 # Unreal Engine 4.24 -# Visual Studio 2017 with Windows 8.1 SDK and x64 Visual C++ Toolset. +# Visual Studio 2017 with Windows 8.1 SDK and x64 Visual C++ Toolset # Set environment variables for the software diff --git a/Docs/ros_installation.md b/Docs/ros_installation.md index 5cf3a4b6986..7e055f9cb9e 100644 --- a/Docs/ros_installation.md +++ b/Docs/ros_installation.md @@ -13,17 +13,23 @@ The ROS bridge enables two-way communication between ROS and CARLA. The informat --- ## Requirements -* __ROS Kinetic/Melodic.__ Install ROS [Melodic](http://wiki.ros.org/melodic/Installation/Ubuntu), for Ubuntu 18.04, or [Kinetic](http://wiki.ros.org/kinetic/Installation), for Ubuntu 16.04. ROS packages may be required, depending on the user needs. [rviz](http://wiki.ros.org/rviz) to visualize ROS data.j -* __CARLA 0.9.7 or later.__ Previous versions are not compatible with the ROS bridge. Follow the [quick start installation](start_quickstart.md) or make the build for the corresponding platform. +Make sure that both requirements work properly before continuing with the installation. -!!! Important - Make sure that both CARLA and ROS work properly before continuing with the installation. +* __ROS Kinetic/Melodic.__ Install ROS [Melodic](http://wiki.ros.org/melodic/Installation/Ubuntu), for Ubuntu 18.04, or [Kinetic](http://wiki.ros.org/kinetic/Installation), for Ubuntu 16.04. ROS packages may be required, depending on the user needs. [rviz](http://wiki.ros.org/rviz) to visualize ROS data. +* __CARLA 0.9.7 or later.__ Previous versions are not compatible with the ROS bridge. Follow the [quick start installation](start_quickstart.md) or make the build for the corresponding platform. + +!!! Warning + CARLA 0.9.10 and later release packages will not be able to run the ROS bridge, as no support for Python2 is provided. Running CARLA in a build from source will be necessary. ### Python2 -Those using ROS Kinetic or Melodic will need Python2 in order to run the ROS bridge. This is no problem for previous versions of CARLA. However, since 0.9.10 (included), CARLA does not provide support for Python2. +Those using ROS Kinetic or Melodic will need Python2 in order to run the ROS bridge. Release packages since 0.9.10 (included) do not provide support for Python2, so a build from source will be necessary. + +Make the [Linux](build_linux.md) or [Windows](build_windows.md) build from source. To compile the PythonAPI for Python2, the instructions depend on the system being used. + +* __Windows__ — The PythonAPI will be built based on the installed Python version. If the system runs with Python2, the PythonAPI will be compiled properly. -In order to compile the necessary `.egg` file of the PythonAPI for Python2, run the following command in the root CARLA directory. +* __Linux__ — Run the following command in the root CARLA directory. ```sh make PythonAPI ARGS="--python-version=2" @@ -50,7 +56,7 @@ sudo apt-get install carla-ros-bridge # Install the latest ROS bridge version, o This repository contains features from CARLA 0.9.10 and later versions. To install a specific version add the version tag to the installation command. ```sh -sudo apt-get install carla-ros-bridge=0.9.10-1 # In this case, "0.9.10" refers to the ROS bridge version, and "1" to the Debian revision. +sudo apt-get install carla-ros-bridge=0.9.10-1 # In this case, "0.9.10" refers to the ROS bridge version, and "1" to the Debian revision ``` ### B. Using source repository @@ -58,7 +64,7 @@ sudo apt-get install carla-ros-bridge=0.9.10-1 # In this case, "0.9.10" refers t A catkin workspace is needed to use the ROS bridge. It should be cloned and built in there. The following code creates a new workspace, and clones the repository in there. ```sh -#setup folder structure +# Setup folder structure mkdir -p ~/carla-ros-bridge/catkin_ws/src cd ~/carla-ros-bridge git clone https://github.com/carla-simulator/ros-bridge.git @@ -66,14 +72,14 @@ cd ros-bridge git submodule update --init cd ../catkin_ws/src ln -s ../../ros-bridge -source /opt/ros/kinetic/setup.bash #Watch out, this sets ROS Kinetic. +source /opt/ros/kinetic/setup.bash # Watch out, this sets ROS Kinetic cd .. -#install required ros-dependencies +# Install required ros-dependencies rosdep update rosdep install --from-paths src --ignore-src -r -#build +# Build catkin_make ``` diff --git a/Docs/start_quickstart.md b/Docs/start_quickstart.md index 954d6b06c9c..1b6408b47be 100644 --- a/Docs/start_quickstart.md +++ b/Docs/start_quickstart.md @@ -20,37 +20,36 @@ ```sh -# Install required modules Pygame and Numpy. +# Install required modules Pygame and Numpy pip install --user pygame numpy -# There are two different ways to install CARLA. +# There are two different ways to install CARLA # Option A) Debian package installation -# This repository contains CARLA 0.9.10 and later. To install previous CARLA versions, change to a previous version of the docs using the pannel in the bottom right part of the window. +# This repository contains CARLA 0.9.10 and later. To install previous CARLA versions, change to a previous version of the docs using the pannel in the bottom right part of the window sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1AF1527DE64CB8D9 sudo add-apt-repository "deb [arch=amd64] http://dist.carla.org/carla $(lsb_release -sc) main" sudo apt-get update -sudo apt-get install carla-simulator # Install the latest CARLA version or update the current installation. -sudo apt-get install carla-simulator=0.9.10-1 # install a specific CARLA version. +sudo apt-get install carla-simulator # Install the latest CARLA version or update the current installation +sudo apt-get install carla-simulator=0.9.10-1 # install a specific CARLA version cd /opt/carla-simulator ./CarlaUE4.sh # Option B) Package installation # Go to: https://github.com/carla-simulator/carla/blob/master/Docs/download.md -# Download the desired package and additional assets. -# Extract the package. -# Extract the additional assets in `/Import`. +# Download the desired package and additional assets +# Extract the package +# Extract the additional assets in `/Import` # Run CARLA (Linux). ./CarlaUE.sh -# Run CARLA (Windows). +# Run CARLA (Windows) > CarlaUE4.exe # Run a script to test CARLA. cd PythonAPI/examples python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) -# Optionally, to compile the PythonAPI for Python2, run the following command in the root CARLA directory. -make PythonAPI ARGS="--python-version=2" +# The PythonAPI can be compiled for Python2 when using a Linux build from source ``` @@ -92,7 +91,7 @@ cd /opt/carla-simulator # Open the folder where CARLA is installed This repository contains CARLA 0.9.10 and later versions. To install a specific version add the version tag to the installation command. ```sh -sudo apt-get install carla-simulator=0.9.10-1 # In this case, "0.9.10" refers to a CARLA version, and "1" to the Debian revision. +sudo apt-get install carla-simulator=0.9.10-1 # In this case, "0.9.10" refers to a CARLA version, and "1" to the Debian revision ``` !!! Important @@ -152,11 +151,9 @@ Now it is time to start running scripts. The following example will spawn some l > python3 spawn_npc.py # Support for Python2 was provided until 0.9.10 (not included) ``` -Optionally, to compile the PythonAPI for Python2, run the following command in the root CARLA directory. +!!! Note + The PythonAPI can be compiled for Python2 when using a [Linux build from source](build_linux.md). -```sh -make PythonAPI ARGS="--python-version=2" -``` #### Command-line options @@ -178,7 +175,7 @@ The script `PythonAPI/util/config.py` provides for more configuration options. > ./config.py --map Town05 # Change map > ./config.py --weather ClearNoon # Change weather -> ./config.py --help # Check all the available configuration options. +> ./config.py --help # Check all the available configuration options ``` --- From 521c0183e6567949fecb27f115ff3fea3d655b64 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Mon, 21 Sep 2020 23:05:44 +0200 Subject: [PATCH 155/179] Added docs for ROS Noetic and prerequirements for ROS bridge installation --- Docs/ros_installation.md | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/Docs/ros_installation.md b/Docs/ros_installation.md index 7e055f9cb9e..e0ecf47fd42 100644 --- a/Docs/ros_installation.md +++ b/Docs/ros_installation.md @@ -1,12 +1,12 @@ # ROS bridge installation -* [__Requirements__](#requirements) - * [Python2](#python2) -* [__Bridge installation__](#bridge-installation) - * [A. Using Debian repository](#a-using-debian-repository) - * [B. Using source repository](#b-using-source-repository) -* [__Run the ROS bridge__](#run-the-ros-bridge) -* [__Setting CARLA__](#setting-carla) +* [__Requirements__](#requirements) + * [Python2](#python2) +* [__Bridge installation__](#bridge-installation) + * [A. Using Debian repository](#a-using-debian-repository) + * [B. Using source repository](#b-using-source-repository) +* [__Run the ROS bridge__](#run-the-ros-bridge) +* [__Setting CARLA__](#setting-carla) The ROS bridge enables two-way communication between ROS and CARLA. The information from the CARLA server is translated to ROS topics. In the same way, the messages sent between nodes in ROS get translated to commands to be applied in CARLA. @@ -15,17 +15,24 @@ The ROS bridge enables two-way communication between ROS and CARLA. The informat Make sure that both requirements work properly before continuing with the installation. -* __ROS Kinetic/Melodic.__ Install ROS [Melodic](http://wiki.ros.org/melodic/Installation/Ubuntu), for Ubuntu 18.04, or [Kinetic](http://wiki.ros.org/kinetic/Installation), for Ubuntu 16.04. ROS packages may be required, depending on the user needs. [rviz](http://wiki.ros.org/rviz) to visualize ROS data. -* __CARLA 0.9.7 or later.__ Previous versions are not compatible with the ROS bridge. Follow the [quick start installation](start_quickstart.md) or make the build for the corresponding platform. +* __ROS Kinetic/Melodic__ — Install the ROS version corresponding to your system. Additional ROS packages may be required, depending on the user needs. [rviz](http://wiki.ros.org/rviz) is highly recommended to visualize ROS data. + * [__ROS Melodic__](http://wiki.ros.org/melodic/Installation/Ubuntu) — For Ubuntu 16.04 (Xenial). + * [__ROS Kinetic__](http://wiki.ros.org/kinetic/Installation) — For Ubuntu 18.04 (Bionic). + * [__ROS Noetic__](http://wiki.ros.org/noetic#Installation) — For Ubuntu 20.04 (Focal). +* __CARLA 0.9.7 or later__ — Previous versions are not compatible with the ROS bridge. Follow the [quick start installation](start_quickstart.md) or make the build for [Linux](build_linux.md) or [Windows](build_windows.md). -!!! Warning - CARLA 0.9.10 and later release packages will not be able to run the ROS bridge, as no support for Python2 is provided. Running CARLA in a build from source will be necessary. +### Python + +The version of Python needed to run the ROS bridge depends on the ROS version being used. + +* __ROS Melodic__ and __ROS Kinetic__ — Python2. +* __ROS Noetic__ — Python3. -### Python2 +All the CARLA releases provide support for Python3, so ROS Noetic users do not need more preparation. However, ROS Melodic/Kinetic users cannot use the latest CARLA release packages, and they will have to build CARLA form source. -Those using ROS Kinetic or Melodic will need Python2 in order to run the ROS bridge. Release packages since 0.9.10 (included) do not provide support for Python2, so a build from source will be necessary. +CARLA release packages since 0.9.10 (included) do not provide support for Python2, so users will have to make the [Linux](build_linux.md) or [Windows](build_windows.md) build from source, and compile the PythonAPI for Python2. -Make the [Linux](build_linux.md) or [Windows](build_windows.md) build from source. To compile the PythonAPI for Python2, the instructions depend on the system being used. +The instructions depend on the system being used. * __Windows__ — The PythonAPI will be built based on the installed Python version. If the system runs with Python2, the PythonAPI will be compiled properly. From 23148d243cc961330666078e511240878d3c3562 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 23 Sep 2020 18:40:37 +0200 Subject: [PATCH 156/179] Fixed for Windows. Note added --- Docs/ros_installation.md | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Docs/ros_installation.md b/Docs/ros_installation.md index e0ecf47fd42..d53abfb70cc 100644 --- a/Docs/ros_installation.md +++ b/Docs/ros_installation.md @@ -1,5 +1,7 @@ # ROS bridge installation +The ROS bridge enables two-way communication between ROS and CARLA. The information from the CARLA server is translated to ROS topics. In the same way, the messages sent between nodes in ROS get translated to commands to be applied in CARLA. + * [__Requirements__](#requirements) * [Python2](#python2) * [__Bridge installation__](#bridge-installation) @@ -7,8 +9,9 @@ * [B. Using source repository](#b-using-source-repository) * [__Run the ROS bridge__](#run-the-ros-bridge) * [__Setting CARLA__](#setting-carla) - -The ROS bridge enables two-way communication between ROS and CARLA. The information from the CARLA server is translated to ROS topics. In the same way, the messages sent between nodes in ROS get translated to commands to be applied in CARLA. + +!!! Important + ROS is still [experimental](http://wiki.ros.org/noetic/Installation) for Windows, so the ROS bridge has only been tested for Linux systems. --- ## Requirements @@ -19,7 +22,7 @@ Make sure that both requirements work properly before continuing with the instal * [__ROS Melodic__](http://wiki.ros.org/melodic/Installation/Ubuntu) — For Ubuntu 16.04 (Xenial). * [__ROS Kinetic__](http://wiki.ros.org/kinetic/Installation) — For Ubuntu 18.04 (Bionic). * [__ROS Noetic__](http://wiki.ros.org/noetic#Installation) — For Ubuntu 20.04 (Focal). -* __CARLA 0.9.7 or later__ — Previous versions are not compatible with the ROS bridge. Follow the [quick start installation](start_quickstart.md) or make the build for [Linux](build_linux.md) or [Windows](build_windows.md). +* __CARLA 0.9.7 or later__ — Previous versions are not compatible with the ROS bridge. Follow the [quick start installation](start_quickstart.md) or make the build for [Linux](build_linux.md). ### Python @@ -28,15 +31,9 @@ The version of Python needed to run the ROS bridge depends on the ROS version be * __ROS Melodic__ and __ROS Kinetic__ — Python2. * __ROS Noetic__ — Python3. -All the CARLA releases provide support for Python3, so ROS Noetic users do not need more preparation. However, ROS Melodic/Kinetic users cannot use the latest CARLA release packages, and they will have to build CARLA form source. - -CARLA release packages since 0.9.10 (included) do not provide support for Python2, so users will have to make the [Linux](build_linux.md) or [Windows](build_windows.md) build from source, and compile the PythonAPI for Python2. - -The instructions depend on the system being used. - -* __Windows__ — The PythonAPI will be built based on the installed Python version. If the system runs with Python2, the PythonAPI will be compiled properly. +All the CARLA releases provide support for Python3, so ROS Noetic users do not need more preparation. However, ROS Melodic/Kinetic users cannot use the latest CARLA release packages. Since 0.9.10 (included), CARLA does not provide support for Python2, so users will have to make the [build from source](build_linux.md), and compile the PythonAPI for Python2. -* __Linux__ — Run the following command in the root CARLA directory. +* Run the following command in the root CARLA directory of your Linux build to compile the PythonAPI for Python2. ```sh make PythonAPI ARGS="--python-version=2" From d324f3a28b4e12d290192e685917c2049a615e52 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 23 Sep 2020 11:53:46 +0200 Subject: [PATCH 157/179] First iteration --- Docs/adv_synchrony_timestep.md | 2 +- Docs/python_api.md | 68 ++++++++++++++++++++------------- PythonAPI/docs/actor.yml | 69 +++++++++++++++++++++++++++------- PythonAPI/docs/client.yml | 4 +- PythonAPI/docs/commands.yml | 10 +++-- PythonAPI/docs/map.yml | 2 +- 6 files changed, 109 insertions(+), 46 deletions(-) diff --git a/Docs/adv_synchrony_timestep.md b/Docs/adv_synchrony_timestep.md index 4757484912a..4401471cc5c 100644 --- a/Docs/adv_synchrony_timestep.md +++ b/Docs/adv_synchrony_timestep.md @@ -74,7 +74,7 @@ CARLA has a [recorder feature](adv_recorder.md) that allows a simulation to be r Physics must be computed within very low time steps to be precise. The more time goes by, the more variables and chaos come to place, and the more defective the simulation will be. CARLA uses up to 6 substeps to compute physics in every step, each with a maximum delta time of 0.016667s. -To know how many of these are needed, the time-step used gets divided by the maximum delta time a substep can use `number_of_substeps = time_step/0.016667`. Being these a maximum of 6, `6*0.016667 = 0.1`. If the time-step is greater than `0.1``, there will not be enough physical substeps. Physics will not be in synchrony with the delta time. +To know how many of these are needed, the time-step used gets divided by the maximum delta time a substep can use `number_of_substeps = time_step/0.016667`. Being these a maximum of 6, `6*0.016667 = 0.1`. If the time-step is greater than `0.1`, there will not be enough physical substeps. Physics will not be in synchrony with the delta time. !!! Warning __Do not use a time-step greater than 0.1s.__
    diff --git a/Docs/python_api.md b/Docs/python_api.md index 17c8f8bfe29..5897ef3d5d1 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -14,24 +14,40 @@ Returns whether this object was destroyed using this actor handle. - **parent** (_[carla.Actor](#carla.Actor)_) Actors may be attached to a parent actor that they will follow around. This is said actor. - **semantic_tags** (_list(int)_) -A list of semantic tags provided by the blueprint listing components for this actor. E.g. a traffic light could be tagged with "pole" and "traffic light". These tags are used by the semantic segmentation sensor. Find more about this and other sensors [here](ref_sensors.md#semantic-segmentation-camera). +A list of semantic tags provided by the blueprint listing components for this actor. E.g. a traffic light could be tagged with `Pole` and `TrafficLight`. These tags are used by the semantic segmentation sensor. Find more about this and other sensors [here](ref_sensors.md#semantic-segmentation-camera). - **type_id** (_str_) -The identifier of the blueprint this actor was based on, e.g. "vehicle.ford.mustang". +The identifier of the blueprint this actor was based on, e.g. `vehicle.ford.mustang`.

    Methods

    +- **add_angular_impulse**(**self**, **impulse**) +Applies an angular impulse at the center of mass of the actor. Angular impulses are instantaneous. Use __add_torque()__ to apply rotation forces over time. + - **Parameters:** + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) – Angular impulse vector in global coordinates. - **add_impulse**(**self**, **impulse**) -Adds an impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. +Applies an impulse at the center of mass of the actor. Impulses are instantaneous. Use __add_force()__ to apply forces over time. - **Parameters:** - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) -- **add_angular_impulse**(**self**, **impulse**) -Adds an angular impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – degrees_) – Impulse vector in global coordinates. +- **add_force**(**self**, **force**) +Applies a force at the center of mass of the actor. The effects of the force depend on the delta time (time between simulation steps) during which it is applied. Use __add_angular_impulse()__ to apply an instantaneous rotation impulse. - **Parameters:** - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – degrees_) + - `force` (_[carla.Vector3D](#carla.Vector3D)_) – Force vector in global coordinates. +- **add_torque**(**self**, **torque**) +Applies a torque at the center of mass of the actor. The effects of the torque depend on the delta time (time between simulation steps) during which it is applied. Use __add_angular_impulse()__ to apply an instantaneous rotation impulse. + - **Parameters:** + - `torque` (_[carla.Vector3D](#carla.Vector3D)_) – Torque vector in global coordinates. - **destroy**(**self**) Tells the simulator to destroy this actor and returns True if it was successful. It has no effect if it was already destroyed. - **Return:** _bool_ - **Warning:** _This method blocks the script until the destruction is completed by the simulator. _ +- **disable_constant_velocity**(**self**) +Disables any constant velocity previously set for a [carla.Vehicle](#carla.Vehicle) actor. +- **enable_constant_velocity**(**self**, **velocity**) +Sets the actor's velocity vector to a constant value over time. The modification is instantaneous. The resulting velocity will not be exactly the `velocity` being set. It will be affected by external forces such as friction. + - **Parameters:** + - `velocity` (_[carla.Vector3D](#carla.Vector3D)_) – Velocity vector in local space. + - **Warning:** _Enabling a constant velocity for a vehicle managed by the [Traffic Manager](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/adv_traffic_manager/) may cause conflicts. It will not be able to override the constant velocity being set. +_
    Getters
    - **get_acceleration**(**self**) @@ -40,7 +56,6 @@ Returns the actor's 3D acceleration vector the client recieved during last tick. - **get_angular_velocity**(**self**) Returns the actor's angular velocity vector the client recieved during last tick. The method does not call the simulator. - **Return:** _[carla.Vector3D](#carla.Vector3D) – rad/s_ - - **Setter:** _[carla.Actor.set_angular_velocity](#carla.Actor.set_angular_velocity)_ - **get_location**(**self**) Returns the actor's location the client recieved during last tick. The method does not call the simulator. - **Return:** _[carla.Location](#carla.Location) – meters_ @@ -52,17 +67,17 @@ Returns the actor's transform (location and rotation) the client recieved during - **get_velocity**(**self**) Returns the actor's velocity vector the client recieved during last tick. The method does not call the simulator. - **Return:** _[carla.Vector3D](#carla.Vector3D) – m/s_ - - **Setter:** _[carla.Actor.set_velocity](#carla.Actor.set_velocity)_ - **get_world**(**self**) Returns the world this actor belongs to. - **Return:** _[carla.World](#carla.World)_
    Setters
    -
    - **set_angular_velocity**(**self**, **angular_velocity**) -Changes the actor's angular velocity vector. +
    - **set_target_angular_velocity**(**self**, **angular_velocity**) +Sets the actor's angular velocity vector. The modification is instantaneous, and done before physics. The resulting angular velocity will be affected by external forces over time (such as friction). - **Parameters:** - `angular_velocity` (_[carla.Vector3D](#carla.Vector3D)_) - - **Getter:** _[carla.Actor.get_angular_velocity](#carla.Actor.get_angular_velocity)_ + - **Note:** _The update will not be effective until two frames after it is set. +_ - **set_location**(**self**, **location**) Teleports the actor to a given location. - **Parameters:** @@ -77,11 +92,12 @@ Teleports the actor to a given transform (location and rotation). - **Parameters:** - `transform` (_[carla.Transform](#carla.Transform)_) - **Getter:** _[carla.Actor.get_transform](#carla.Actor.get_transform)_ -- **set_velocity**(**self**, **velocity**) -Sets the actor's velocity vector. +- **set_target_velocity**(**self**, **velocity**) +Sets the actor's velocity vector. The modification is instantaneous, and done before physics. The resulting velocity will be affected by external forces over time (such as friction). - **Parameters:** - `velocity` (_[carla.Vector3D](#carla.Vector3D)_) - - **Getter:** _[carla.Actor.get_velocity](#carla.Actor.get_velocity)_ + - **Note:** _The update will not be effective until two frames after it is set. +_
    Dunder methods
    - **\__str__**(**self**) @@ -349,13 +365,13 @@ Client constructor. - `port` (_int_) – TCP port where the CARLA Simulator instance is running. Default are 2000 and the subsequent 2001. - `worker_threads` (_int_) – Number of working threads used for background updates. If 0, use all available concurrency. - **apply_batch**(**self**, **commands**) -Executes a list of commands on a single simulation step and retrieves no information. If you need information about the response of each command, use the **apply_batch_sync()** function right below this one. [Here](https://github.com/carla-simulator/carla/blob/10c5f6a482a21abfd00220c68c7f12b4110b7f63/PythonAPI/examples/spawn_npc.py#L126) is an example on how to delete the actors that appear in [carla.ActorList](#carla.ActorList) all at once. +Executes a list of commands on a single simulation step and retrieves no information. If you need information about the response of each command, use the __apply_batch_sync()__ method. [Here](https://github.com/carla-simulator/carla/blob/10c5f6a482a21abfd00220c68c7f12b4110b7f63/PythonAPI/examples/spawn_npc.py#L126) is an example on how to delete the actors that appear in [carla.ActorList](#carla.ActorList) all at once. - **Parameters:** - `commands` (_list_) – A list of commands to execute in batch. Each command is different and has its own parameters. They appear listed at the bottom of this page. - **apply_batch_sync**(**self**, **commands**, **due_tick_cue**=False) Executes a list of commands on a single simulation step, blocks until the commands are linked, and returns a list of command.Response that can be used to determine whether a single command succeeded or not. [Here](https://github.com/carla-simulator/carla/blob/10c5f6a482a21abfd00220c68c7f12b4110b7f63/PythonAPI/examples/spawn_npc.py#L112-L116) is an example of it being used to spawn actors. - **Parameters:** - - `commands` (_list_) – A list of commands to execute in batch. The commands available are listed right above, in the function **apply_batch()**. + - `commands` (_list_) – A list of commands to execute in batch. The commands available are listed right above, in the method **apply_batch()**. - `due_tick_cue` (_bool_) – A boolean parameter to specify whether or not to perform a [carla.World.tick](#carla.World.tick) after applying the batch in _synchronous mode_. It is __False__ by default. - **Return:** _list(command.Response)_ - **generate_opendrive_world**(**self**, **opendrive**, **parameters**=(2.0, 50.0, 1.0, 0.6, true, true)) @@ -1877,7 +1893,7 @@ The client returns True if a traffic light is frozen according to last ti - **Return:** _bool_ - **reset_group**(**self**) Resets the state of the traffic lights of the group to the initial state at the start of the simulation. - - **Note:** _This function calls the simulator. + - **Note:** _This method calls the simulator. _
    Getters
    @@ -1887,7 +1903,7 @@ The client returns the time in seconds since current light state started accordi - **get_group_traffic_lights**(**self**) Returns all traffic lights in the group this one belongs to. - **Return:** _list([carla.TrafficLight](#carla.TrafficLight))_ - - **Note:** _This function calls the simulator. + - **Note:** _This method calls the simulator. _ - **get_pole_index**(**self**) Returns the index of the pole that identifies it as part of the traffic light group of a junction. @@ -2179,7 +2195,7 @@ Returns a flag representing the vehicle light state, this represents which light - **get_physics_control**(**self**) The simulator returns the last physics control applied to this vehicle. - **Return:** _[carla.VehiclePhysicsControl](#carla.VehiclePhysicsControl)_ - - **Warning:** _This function does call the simulator to retrieve the value._ + - **Warning:** _This method does call the simulator to retrieve the value._ - **get_speed_limit**(**self**) The client returns the speed limit affecting this vehicle according to last tick (it does not call the simulator). The speed limit is updated when passing by a speed limit signal, so a vehicle might have none right after spawning. - **Return:** _float – m/s_ @@ -2485,7 +2501,7 @@ Returns a list of waypoints from this to the start of the lane separated by a ce
    Getters
    - **get_junction**(**self**) -If the waypoint belongs to a junction this function returns the asociated junction object. Otherwise returns null. +If the waypoint belongs to a junction this method returns the asociated junction object. Otherwise returns null. - **Return:** _[carla.Junction](#carla.Junction)_ - **get_landmarks**(**self**, **distance**, **stop_at_junction**=False) Returns a list of landmarks in the road from the current waypoint until the specified distance. @@ -2814,7 +2830,7 @@ Angular impulse applied to the actor. Determines magnitude and global axis where --- ## command.ApplyAngularVelocity -Command adaptation of **set_angular_velocity()** in [carla.Actor](#carla.Actor). Sets an actor's angular velocity. +Command adaptation of **set_angular_velocity()** in [carla.Actor](#carla.Actor). Sets the actor's angular velocity vector. The modification is instantaneous, and done before physics. The resulting angular velocity will be affected by external forces over time (such as friction).

    Instance Variables

    - **actor_id** (_int_) @@ -2826,7 +2842,7 @@ The 3D angular velocity that will be applied to the actor. - **\__init__**(**self**, **actor**, **angular_velocity**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `angular_velocity` (_[carla.Vector3D](#carla.Vector3D) – deg/s_) + - `angular_velocity` (_[carla.Vector3D](#carla.Vector3D) – deg/s_) – Angular velocity vector applied to the actor. --- @@ -2882,7 +2898,7 @@ Vehicle control to be applied. --- ## command.ApplyVelocity -Command adaptation of **set_velocity()** in [carla.Actor](#carla.Actor). Sets an actor's velocity. +Command adaptation of **set_target_velocity()** in [carla.Actor](#carla.Actor). Sets the actor's velocity vector. The modification is instantaneous, and done before physics. The resulting velocity will be affected by external forces over time (such as friction).

    Instance Variables

    - **actor_id** (_int_) @@ -2894,7 +2910,7 @@ The 3D velocity applied to the actor. - **\__init__**(**self**, **actor**, **velocity**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `velocity` (_[carla.Vector3D](#carla.Vector3D)_) + - `velocity` (_[carla.Vector3D](#carla.Vector3D)_) – Velocity vector applied to the actor. --- @@ -2950,7 +2966,7 @@ Actor affected by the command. --- ## command.Response -States the result of executing a command as either the ID of the actor to whom the command was applied to (when succeeded) or an error string (when failed). actor ID, depending on whether or not the command succeeded. The method **apply_batch_sync()** in [carla.Client](#carla.Client) returns a list of these to summarize the execution of a batch. +States the result of executing a command as either the ID of the actor to whom the command was applied to (when succeeded) or an error string (when failed). actor ID, depending on whether or not the command succeeded. The method __apply_batch_sync()__ in [carla.Client](#carla.Client) returns a list of these to summarize the execution of a batch.

    Instance Variables

    - **actor_id** (_int_) diff --git a/PythonAPI/docs/actor.yml b/PythonAPI/docs/actor.yml index 3685bd6e823..09881946130 100644 --- a/PythonAPI/docs/actor.yml +++ b/PythonAPI/docs/actor.yml @@ -27,29 +27,51 @@ - var_name: semantic_tags type: list(int) doc: > - A list of semantic tags provided by the blueprint listing components for this actor. E.g. a traffic light could be tagged with "pole" and "traffic light". These tags are used by the semantic segmentation sensor. Find more about this and other sensors [here](ref_sensors.md#semantic-segmentation-camera). + A list of semantic tags provided by the blueprint listing components for this actor. E.g. a traffic light could be tagged with `Pole` and `TrafficLight`. These tags are used by the semantic segmentation sensor. Find more about this and other sensors [here](ref_sensors.md#semantic-segmentation-camera). - var_name: type_id type: str doc: > - The identifier of the blueprint this actor was based on, e.g. "vehicle.ford.mustang". + The identifier of the blueprint this actor was based on, e.g. `vehicle.ford.mustang`. # - METHODS ---------------------------- methods: - - def_name: add_impulse + - def_name: add_angular_impulse params: - param_name: impulse type: carla.Vector3D param_units: N*s + doc: > + Angular impulse vector in global coordinates. doc: > - Adds an impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. + Applies an angular impulse at the center of mass of the actor. Angular impulses are instantaneous. Use __add_torque()__ to apply rotation forces over time. # -------------------------------------- - - def_name: add_angular_impulse + - def_name: add_impulse params: - param_name: impulse type: carla.Vector3D param_units: degrees + doc: > + Impulse vector in global coordinates. + doc: > + Applies an impulse at the center of mass of the actor. Impulses are instantaneous. Use __add_force()__ to apply forces over time. + # -------------------------------------- + - def_name: add_force + params: + - param_name: force + type: carla.Vector3D + doc: > + Force vector in global coordinates. doc: > - Adds an angular impulse to the actor. The parameter `impulse` determines magnitude and global axis where it is applied. + Applies a force at the center of mass of the actor. The effects of the force depend on the delta time (time between simulation steps) during which it is applied. Use __add_angular_impulse()__ to apply an instantaneous rotation impulse. + # -------------------------------------- + - def_name: add_torque + params: + - param_name: torque + type: carla.Vector3D + doc: > + Torque vector in global coordinates. + doc: > + Applies a torque at the center of mass of the actor. The effects of the torque depend on the delta time (time between simulation steps) during which it is applied. Use __add_angular_impulse()__ to apply an instantaneous rotation impulse. # -------------------------------------- - def_name: destroy return: bool @@ -58,6 +80,23 @@ warning: > This method blocks the script until the destruction is completed by the simulator. # -------------------------------------- + - def_name: disable_constant_velocity + doc: > + Disables any constant velocity previously set for a carla.Vehicle actor. + # -------------------------------------- + - def_name: enable_constant_velocity + params: + - param_name: velocity + type: carla.Vector3D + doc: > + Velocity vector in local space. + doc: > + Sets the actor's velocity vector to a constant value over time. The modification is instantaneous. The resulting velocity will not be exactly the `velocity` being set. It will be affected by external forces such as friction. + Note: > + Only carla.Vehicle actors can use this method. + warning: > + Enabling a constant velocity for a vehicle managed by the [Traffic Manager](https://carla.readthedocs.io/en/latest/adv_traffic_manager/) may cause conflicts. It will not be able to override the constant velocity being set. + # -------------------------------------- - def_name: get_acceleration return: carla.Vector3D return_units: m/s2 @@ -92,12 +131,14 @@ doc: > Returns the world this actor belongs to. # -------------------------------------- - - def_name: set_angular_velocity + - def_name: set_target_angular_velocity params: - param_name: angular_velocity type: carla.Vector3D doc: > - Changes the actor's angular velocity vector. + Sets the actor's angular velocity vector. The modification is instantaneous, and done before physics. The resulting angular velocity will be affected by external forces over time (such as friction). + note: > + The update will not be effective until two frames after it is set. # -------------------------------------- - def_name: set_location params: @@ -122,12 +163,14 @@ doc: > Teleports the actor to a given transform (location and rotation). # -------------------------------------- - - def_name: set_velocity + - def_name: set_target_velocity params: - param_name: velocity type: carla.Vector3D doc: > - Sets the actor's velocity vector. + Sets the actor's velocity vector. The modification is instantaneous, and done before physics. The resulting velocity will be affected by external forces over time (such as friction). + note: > + The update will not be effective until two frames after it is set. # -------------------------------------- - def_name: __str__ # -------------------------------------- @@ -211,7 +254,7 @@ return: carla.VehiclePhysicsControl doc: > The simulator returns the last physics control applied to this vehicle. - warning: This function does call the simulator to retrieve the value. + warning: This method does call the simulator to retrieve the value. # -------------------------------------- - def_name: get_speed_limit return: float @@ -388,13 +431,13 @@ doc: > Returns all traffic lights in the group this one belongs to. note: > - This function calls the simulator. + This method calls the simulator. # -------------------------------------- - def_name: reset_group doc: > Resets the state of the traffic lights of the group to the initial state at the start of the simulation. note: > - This function calls the simulator. + This method calls the simulator. # -------------------------------------- - def_name: get_pole_index return: int diff --git a/PythonAPI/docs/client.yml b/PythonAPI/docs/client.yml index ff1bca3edb1..1e6b7a4ad85 100644 --- a/PythonAPI/docs/client.yml +++ b/PythonAPI/docs/client.yml @@ -42,7 +42,7 @@ doc: > A list of commands to execute in batch. Each command is different and has its own parameters. They appear listed at the bottom of this page. doc: > - Executes a list of commands on a single simulation step and retrieves no information. If you need information about the response of each command, use the **apply_batch_sync()** function right below this one. + Executes a list of commands on a single simulation step and retrieves no information. If you need information about the response of each command, use the __apply_batch_sync()__ method. [Here](https://github.com/carla-simulator/carla/blob/10c5f6a482a21abfd00220c68c7f12b4110b7f63/PythonAPI/examples/spawn_npc.py#L126) is an example on how to delete the actors that appear in carla.ActorList all at once. # -------------------------------------- - def_name: apply_batch_sync @@ -50,7 +50,7 @@ - param_name: commands type: list doc: > - A list of commands to execute in batch. The commands available are listed right above, in the function **apply_batch()**. + A list of commands to execute in batch. The commands available are listed right above, in the method **apply_batch()**. - param_name: due_tick_cue type: bool default: false diff --git a/PythonAPI/docs/commands.yml b/PythonAPI/docs/commands.yml index 83b59498dfb..56cd313b1d3 100644 --- a/PythonAPI/docs/commands.yml +++ b/PythonAPI/docs/commands.yml @@ -6,7 +6,7 @@ # - DESCRIPTION ------------------------ doc: > States the result of executing a command as either the ID of the actor to whom the command was applied to (when succeeded) or an error string (when failed). - actor ID, depending on whether or not the command succeeded. The method **apply_batch_sync()** in carla.Client returns a list of these to summarize the execution of a batch. + actor ID, depending on whether or not the command succeeded. The method __apply_batch_sync()__ in carla.Client returns a list of these to summarize the execution of a batch. # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id @@ -205,7 +205,7 @@ - class_name: ApplyVelocity # - DESCRIPTION ------------------------ doc: > - Command adaptation of **set_velocity()** in carla.Actor. Sets an actor's velocity. + Command adaptation of **set_target_velocity()** in carla.Actor. Sets the actor's velocity vector. The modification is instantaneous, and done before physics. The resulting velocity will be affected by external forces over time (such as friction). # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id @@ -228,12 +228,14 @@ - param_name: velocity type: carla.Vector3D param_untis: m/s + doc: > + Velocity vector applied to the actor. # -------------------------------------- - class_name: ApplyAngularVelocity # - DESCRIPTION ------------------------ doc: > - Command adaptation of **set_angular_velocity()** in carla.Actor. Sets an actor's angular velocity. + Command adaptation of **set_angular_velocity()** in carla.Actor. Sets the actor's angular velocity vector. The modification is instantaneous, and done before physics. The resulting angular velocity will be affected by external forces over time (such as friction). # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id @@ -256,6 +258,8 @@ - param_name: angular_velocity type: carla.Vector3D param_units: deg/s + doc: > + Angular velocity vector applied to the actor. # -------------------------------------- - class_name: ApplyImpulse diff --git a/PythonAPI/docs/map.yml b/PythonAPI/docs/map.yml index 5c115b8a648..b40a42ee878 100644 --- a/PythonAPI/docs/map.yml +++ b/PythonAPI/docs/map.yml @@ -406,7 +406,7 @@ - def_name: get_junction return: carla.Junction doc: > - If the waypoint belongs to a junction this function returns the asociated junction object. Otherwise returns null. + If the waypoint belongs to a junction this method returns the asociated junction object. Otherwise returns null. # -------------------------------------- - def_name: get_landmarks params: From 402731cefafa50f2e689d2046bf6af67bb643176 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 23 Sep 2020 12:06:22 +0200 Subject: [PATCH 158/179] Fixes on commands --- Docs/python_api.md | 58 ++++++++++++++++++------------------- PythonAPI/docs/commands.yml | 6 ++-- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index 5897ef3d5d1..ee1e09babe3 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -2829,37 +2829,54 @@ Angular impulse applied to the actor. Determines magnitude and global axis where --- -## command.ApplyAngularVelocity -Command adaptation of **set_angular_velocity()** in [carla.Actor](#carla.Actor). Sets the actor's angular velocity vector. The modification is instantaneous, and done before physics. The resulting angular velocity will be affected by external forces over time (such as friction). +## command.ApplyImpulse +Command adaptation of **add_impulse()** in [carla.Actor](#carla.Actor). Adds impulse to an actor. + +

    Instance Variables

    +- **actor_id** (_int_) +Actor affected by the command. +- **impulse** (_[carla.Vector3D](#carla.Vector3D) – N*s_) +Impulse applied to the actor. + +

    Methods

    +- **\__init__**(**self**, **actor**, **impulse**) + - **Parameters:** + - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) + +--- + +## command.ApplyTargetAngularVelocity +Command adaptation of **set_target_angular_velocity()** in [carla.Actor](#carla.Actor). Sets the actor's angular velocity vector. The modification is instantaneous, and done before physics. The resulting angular velocity will be affected by external forces over time (such as friction).

    Instance Variables

    -- **actor_id** (_int_) +- **actor_id** (_int_) Actor affected by the command. -- **angular_velocity** (_[carla.Vector3D](#carla.Vector3D) – deg/s_) +- **angular_velocity** (_[carla.Vector3D](#carla.Vector3D) – deg/s_) The 3D angular velocity that will be applied to the actor.

    Methods

    -- **\__init__**(**self**, **actor**, **angular_velocity**) +- **\__init__**(**self**, **actor**, **angular_velocity**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - `angular_velocity` (_[carla.Vector3D](#carla.Vector3D) – deg/s_) – Angular velocity vector applied to the actor. --- -## command.ApplyImpulse -Command adaptation of **add_impulse()** in [carla.Actor](#carla.Actor). Adds impulse to an actor. +## command.ApplyTargetVelocity +Command adaptation of **set_target_velocity()** in [carla.Actor](#carla.Actor). Sets the actor's velocity vector. The modification is instantaneous, and done before physics. The resulting velocity will be affected by external forces over time (such as friction).

    Instance Variables

    -- **actor_id** (_int_) +- **actor_id** (_int_) Actor affected by the command. -- **impulse** (_[carla.Vector3D](#carla.Vector3D) – N*s_) -Impulse applied to the actor. +- **velocity** (_[carla.Vector3D](#carla.Vector3D) – m/s_) +The 3D velocity applied to the actor.

    Methods

    -- **\__init__**(**self**, **actor**, **impulse**) +- **\__init__**(**self**, **actor**, **velocity**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) + - `velocity` (_[carla.Vector3D](#carla.Vector3D)_) – Velocity vector applied to the actor. --- @@ -2897,23 +2914,6 @@ Vehicle control to be applied. --- -## command.ApplyVelocity -Command adaptation of **set_target_velocity()** in [carla.Actor](#carla.Actor). Sets the actor's velocity vector. The modification is instantaneous, and done before physics. The resulting velocity will be affected by external forces over time (such as friction). - -

    Instance Variables

    -- **actor_id** (_int_) -Actor affected by the command. -- **velocity** (_[carla.Vector3D](#carla.Vector3D) – m/s_) -The 3D velocity applied to the actor. - -

    Methods

    -- **\__init__**(**self**, **actor**, **velocity**) - - **Parameters:** - - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `velocity` (_[carla.Vector3D](#carla.Vector3D)_) – Velocity vector applied to the actor. - ---- - ## command.ApplyWalkerControl Command adaptation of **apply_control()** in [carla.Walker](#carla.Walker). Applies a control to a walker. diff --git a/PythonAPI/docs/commands.yml b/PythonAPI/docs/commands.yml index 56cd313b1d3..a0ab3839366 100644 --- a/PythonAPI/docs/commands.yml +++ b/PythonAPI/docs/commands.yml @@ -202,7 +202,7 @@ param_units: m/s # -------------------------------------- - - class_name: ApplyVelocity + - class_name: ApplyTargetVelocity # - DESCRIPTION ------------------------ doc: > Command adaptation of **set_target_velocity()** in carla.Actor. Sets the actor's velocity vector. The modification is instantaneous, and done before physics. The resulting velocity will be affected by external forces over time (such as friction). @@ -232,10 +232,10 @@ Velocity vector applied to the actor. # -------------------------------------- - - class_name: ApplyAngularVelocity + - class_name: ApplyTargetAngularVelocity # - DESCRIPTION ------------------------ doc: > - Command adaptation of **set_angular_velocity()** in carla.Actor. Sets the actor's angular velocity vector. The modification is instantaneous, and done before physics. The resulting angular velocity will be affected by external forces over time (such as friction). + Command adaptation of **set_target_angular_velocity()** in carla.Actor. Sets the actor's angular velocity vector. The modification is instantaneous, and done before physics. The resulting angular velocity will be affected by external forces over time (such as friction). # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id From b79461f0c46ee52791e695fb9c1ad1c19bcdb83f Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 23 Sep 2020 23:32:23 +0200 Subject: [PATCH 159/179] New iteration with parameters, commands and fixes on DS comments --- Docs/python_api.md | 86 ++++++++++++++++++++++++++----------- PythonAPI/docs/actor.yml | 28 ++++++------ PythonAPI/docs/commands.yml | 80 ++++++++++++++++++++++++++++------ 3 files changed, 140 insertions(+), 54 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index ee1e09babe3..1b7ae086460 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -19,20 +19,20 @@ A list of semantic tags provided by the blueprint listing components for this ac The identifier of the blueprint this actor was based on, e.g. `vehicle.ford.mustang`.

    Methods

    -- **add_angular_impulse**(**self**, **impulse**) -Applies an angular impulse at the center of mass of the actor. Angular impulses are instantaneous. Use __add_torque()__ to apply rotation forces over time. +- **add_angular_impulse**(**self**, **angular_impulse**) +Applies an angular impulse at the center of mass of the actor. Angular impulses only last an instant. Use __add_torque()__ to apply rotation forces over a period of time. - **Parameters:** - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) – Angular impulse vector in global coordinates. -- **add_impulse**(**self**, **impulse**) -Applies an impulse at the center of mass of the actor. Impulses are instantaneous. Use __add_force()__ to apply forces over time. - - **Parameters:** - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – degrees_) – Impulse vector in global coordinates. + - `angular_impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) – Angular impulse vector in global coordinates. - **add_force**(**self**, **force**) -Applies a force at the center of mass of the actor. The effects of the force depend on the delta time (time between simulation steps) during which it is applied. Use __add_angular_impulse()__ to apply an instantaneous rotation impulse. +Applies a force at the center of mass of the actor. This method should be used for forces that are applied over a certain period of time. Use __add_impulse()__ to apply an impulse that only lasts an instant. + - **Parameters:** + - `force` (_[carla.Vector3D](#carla.Vector3D) – degrees_) – Force vector in global coordinates. +- **add_impulse**(**self**, **impulse**) +Applies an impulse at the center of mass of the actor. Impulses only last an instant. Use __add_force()__ to apply forces over a period of time. - **Parameters:** - - `force` (_[carla.Vector3D](#carla.Vector3D)_) – Force vector in global coordinates. + - `impulse` (_[carla.Vector3D](#carla.Vector3D)_) – Impulse vector in global coordinates. - **add_torque**(**self**, **torque**) -Applies a torque at the center of mass of the actor. The effects of the torque depend on the delta time (time between simulation steps) during which it is applied. Use __add_angular_impulse()__ to apply an instantaneous rotation impulse. +Applies a torque at the center of mass of the actor. The effects of the torque depend on the delta time (time between simulation steps) during which it is applied. Use __add_angular_impulse()__ to apply a rotation impulse that only lasts an instant. - **Parameters:** - `torque` (_[carla.Vector3D](#carla.Vector3D)_) – Torque vector in global coordinates. - **destroy**(**self**) @@ -43,7 +43,7 @@ _
    - **disable_constant_velocity**(**self**) Disables any constant velocity previously set for a [carla.Vehicle](#carla.Vehicle) actor. - **enable_constant_velocity**(**self**, **velocity**) -Sets the actor's velocity vector to a constant value over time. The modification is instantaneous. The resulting velocity will not be exactly the `velocity` being set. It will be affected by external forces such as friction. +Sets the actor's velocity vector to a constant value over time. The resulting velocity will be approximately the `velocity` being set, as with __set_target_velocity()__. - **Parameters:** - `velocity` (_[carla.Vector3D](#carla.Vector3D)_) – Velocity vector in local space. - **Warning:** _Enabling a constant velocity for a vehicle managed by the [Traffic Manager](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/adv_traffic_manager/) may cause conflicts. It will not be able to override the constant velocity being set. @@ -73,7 +73,7 @@ Returns the world this actor belongs to.
    Setters
    - **set_target_angular_velocity**(**self**, **angular_velocity**) -Sets the actor's angular velocity vector. The modification is instantaneous, and done before physics. The resulting angular velocity will be affected by external forces over time (such as friction). +Sets the actor's angular velocity vector. The modification will be effective two frames after the setting, and the update between angular velocities will be sudden. Also, this is applied before the physics step so the resulting angular velocity will be affected by external forces at this frame such as friction. - **Parameters:** - `angular_velocity` (_[carla.Vector3D](#carla.Vector3D)_) - **Note:** _The update will not be effective until two frames after it is set. @@ -93,7 +93,7 @@ Teleports the actor to a given transform (location and rotation). - `transform` (_[carla.Transform](#carla.Transform)_) - **Getter:** _[carla.Actor.get_transform](#carla.Actor.get_transform)_ - **set_target_velocity**(**self**, **velocity**) -Sets the actor's velocity vector. The modification is instantaneous, and done before physics. The resulting velocity will be affected by external forces over time (such as friction). +Sets the actor's velocity vector. The modification will be effective two frames after the setting, and the update between velocities will be sudden. Also, this is applied before the physics step so the resulting velocity will be affected by external forces at this frame such as friction. - **Parameters:** - `velocity` (_[carla.Vector3D](#carla.Vector3D)_) - **Note:** _The update will not be effective until two frames after it is set. @@ -2813,13 +2813,13 @@ Returns True if both **timestamp** are diffe --- ## command.ApplyAngularImpulse -Command adaptation of **add_angular_impulse()** in [carla.Actor](#carla.Actor). Adds angular impulse to an actor. +Command adaptation of __add_angular_impulse()__ in [carla.Actor](#carla.Actor). Applies an angular impulse to an actor.

    Instance Variables

    - **actor_id** (_int_) Actor affected by the command. - **impulse** (_[carla.Vector3D](#carla.Vector3D) – degrees_) -Angular impulse applied to the actor. Determines magnitude and global axis where it is applied. +Angular impulse applied to the actor.

    Methods

    - **\__init__**(**self**, **actor**, **impulse**) @@ -2829,8 +2829,25 @@ Angular impulse applied to the actor. Determines magnitude and global axis where --- +## command.ApplyForce +Command adaptation of __add_force()__ in [carla.Actor](#carla.Actor). Applies a force to an actor. + +

    Instance Variables

    +- **actor_id** (_int_) +Actor affected by the command. +- **force** (_[carla.Vector3D](#carla.Vector3D)_) +Force applied to the actor over time. + +

    Methods

    +- **\__init__**(**self**, **actor**, **force**) + - **Parameters:** + - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. + - `force` (_[carla.Vector3D](#carla.Vector3D)_) + +--- + ## command.ApplyImpulse -Command adaptation of **add_impulse()** in [carla.Actor](#carla.Actor). Adds impulse to an actor. +Command adaptation of __add_impulse()__ in [carla.Actor](#carla.Actor). Applies an impulse to an actor.

    Instance Variables

    - **actor_id** (_int_) @@ -2847,7 +2864,7 @@ Impulse applied to the actor. --- ## command.ApplyTargetAngularVelocity -Command adaptation of **set_target_angular_velocity()** in [carla.Actor](#carla.Actor). Sets the actor's angular velocity vector. The modification is instantaneous, and done before physics. The resulting angular velocity will be affected by external forces over time (such as friction). +Command adaptation of __set_target_angular_velocity()__ in [carla.Actor](#carla.Actor). Sets the actor's angular velocity vector.

    Instance Variables

    - **actor_id** (_int_) @@ -2864,7 +2881,7 @@ The 3D angular velocity that will be applied to the actor. --- ## command.ApplyTargetVelocity -Command adaptation of **set_target_velocity()** in [carla.Actor](#carla.Actor). Sets the actor's velocity vector. The modification is instantaneous, and done before physics. The resulting velocity will be affected by external forces over time (such as friction). +Command adaptation of __set_target_velocity()__ in [carla.Actor](#carla.Actor).

    Instance Variables

    - **actor_id** (_int_) @@ -2880,8 +2897,25 @@ The 3D velocity applied to the actor. --- +## command.ApplyTorque +Command adaptation of __add_torque()__ in [carla.Actor](#carla.Actor). Applies a torque to an actor. + +

    Instance Variables

    +- **actor_id** (_int_) +Actor affected by the command. +- **torque** (_[carla.Vector3D](#carla.Vector3D)_) +Torque applied to the actor over time. + +

    Methods

    +- **\__init__**(**self**, **actor**, **torque**) + - **Parameters:** + - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. + - `torque` (_[carla.Vector3D](#carla.Vector3D)_) + +--- + ## command.ApplyTransform -Command adaptation of **set_transform()** in [carla.Actor](#carla.Actor). Sets a new transform to an actor. +Command adaptation of __set_transform()__ in [carla.Actor](#carla.Actor). Sets a new transform to an actor.

    Instance Variables

    - **actor_id** (_int_) @@ -2898,7 +2932,7 @@ Transformation to be applied. --- ## command.ApplyVehicleControl -Command adaptation of **apply_control()** in [carla.Vehicle](#carla.Vehicle). Applies a certain control to a vehicle. +Command adaptation of __apply_control()__ in [carla.Vehicle](#carla.Vehicle). Applies a certain control to a vehicle.

    Instance Variables

    - **actor_id** (_int_) @@ -2915,7 +2949,7 @@ Vehicle control to be applied. --- ## command.ApplyWalkerControl -Command adaptation of **apply_control()** in [carla.Walker](#carla.Walker). Applies a control to a walker. +Command adaptation of __apply_control()__ in [carla.Walker](#carla.Walker). Applies a control to a walker.

    Instance Variables

    - **actor_id** (_int_) @@ -2952,7 +2986,7 @@ Speed to be applied. --- ## command.DestroyActor -Command adaptation of **destroy()** in [carla.Actor](#carla.Actor) that tells the simulator to destroy this actor. It has no effect if the actor was already destroyed. When executed with **apply_batch_sync()** in [carla.Client](#carla.Client) there will be a command.Response that will return a boolean stating whether the actor was successfully destroyed. +Command adaptation of __destroy()__ in [carla.Actor](#carla.Actor) that tells the simulator to destroy this actor. It has no effect if the actor was already destroyed. When executed with __apply_batch_sync()__ in [carla.Client](#carla.Client) there will be a command.Response that will return a boolean stating whether the actor was successfully destroyed.

    Instance Variables

    - **actor_id** (_int_) @@ -2982,7 +3016,7 @@ Returns True if the command execution fails, and False if it was s --- ## command.SetAutopilot -Command adaptation of **set_autopilot()** in [carla.Vehicle](#carla.Vehicle). Turns on/off the vehicle's autopilot mode. +Command adaptation of __set_autopilot()__ in [carla.Vehicle](#carla.Vehicle). Turns on/off the vehicle's autopilot mode.

    Instance Variables

    - **actor_id** (_int_) @@ -3002,7 +3036,7 @@ Port of the Traffic Manager where the vehicle is to be registered or unlisted. --- ## command.SetSimulatePhysics -Command adaptation of **set_simulate_physics()** in [carla.Actor](#carla.Actor). Determines whether an actor will be affected by physics or not. +Command adaptation of __set_simulate_physics()__ in [carla.Actor](#carla.Actor). Determines whether an actor will be affected by physics or not.

    Instance Variables

    - **actor_id** (_int_) @@ -3019,7 +3053,7 @@ If physics should be activated or not. --- ## command.SetVehicleLightState -Command adaptation of **set_light_state()** in [carla.Vehicle](#carla.Vehicle). Sets the light state of a vehicle. +Command adaptation of __set_light_state()__ in [carla.Vehicle](#carla.Vehicle). Sets the light state of a vehicle.

    Instance Variables

    - **actor_id** (_int_) @@ -3036,7 +3070,7 @@ Defines the light state of a vehicle. --- ## command.SpawnActor -Command adaptation of **spawn_actor()** in [carla.World](#carla.World). Spawns an actor into the world based on the blueprint provided and the transform. If a parent is provided, the actor is attached to it. +Command adaptation of __spawn_actor()__ in [carla.World](#carla.World). Spawns an actor into the world based on the blueprint provided and the transform. If a parent is provided, the actor is attached to it.

    Instance Variables

    - **transform** (_[carla.Transform](#carla.Transform)_) diff --git a/PythonAPI/docs/actor.yml b/PythonAPI/docs/actor.yml index 09881946130..2bc9a17e6de 100644 --- a/PythonAPI/docs/actor.yml +++ b/PythonAPI/docs/actor.yml @@ -37,32 +37,32 @@ methods: - def_name: add_angular_impulse params: - - param_name: impulse + - param_name: angular_impulse type: carla.Vector3D param_units: N*s doc: > Angular impulse vector in global coordinates. doc: > - Applies an angular impulse at the center of mass of the actor. Angular impulses are instantaneous. Use __add_torque()__ to apply rotation forces over time. + Applies an angular impulse at the center of mass of the actor. Angular impulses only last an instant. Use __add_torque()__ to apply rotation forces over a period of time. # -------------------------------------- - - def_name: add_impulse + - def_name: add_force params: - - param_name: impulse + - param_name: force type: carla.Vector3D param_units: degrees doc: > - Impulse vector in global coordinates. + Force vector in global coordinates. doc: > - Applies an impulse at the center of mass of the actor. Impulses are instantaneous. Use __add_force()__ to apply forces over time. + Applies a force at the center of mass of the actor. This method should be used for forces that are applied over a certain period of time. Use __add_impulse()__ to apply an impulse that only lasts an instant. # -------------------------------------- - - def_name: add_force + - def_name: add_impulse params: - - param_name: force + - param_name: impulse type: carla.Vector3D doc: > - Force vector in global coordinates. + Impulse vector in global coordinates. doc: > - Applies a force at the center of mass of the actor. The effects of the force depend on the delta time (time between simulation steps) during which it is applied. Use __add_angular_impulse()__ to apply an instantaneous rotation impulse. + Applies an impulse at the center of mass of the actor. Impulses only last an instant. Use __add_force()__ to apply forces over a period of time. # -------------------------------------- - def_name: add_torque params: @@ -71,7 +71,7 @@ doc: > Torque vector in global coordinates. doc: > - Applies a torque at the center of mass of the actor. The effects of the torque depend on the delta time (time between simulation steps) during which it is applied. Use __add_angular_impulse()__ to apply an instantaneous rotation impulse. + Applies a torque at the center of mass of the actor. The effects of the torque depend on the delta time (time between simulation steps) during which it is applied. Use __add_angular_impulse()__ to apply a rotation impulse that only lasts an instant. # -------------------------------------- - def_name: destroy return: bool @@ -91,7 +91,7 @@ doc: > Velocity vector in local space. doc: > - Sets the actor's velocity vector to a constant value over time. The modification is instantaneous. The resulting velocity will not be exactly the `velocity` being set. It will be affected by external forces such as friction. + Sets the actor's velocity vector to a constant value over time. The resulting velocity will be approximately the `velocity` being set, as with __set_target_velocity()__. Note: > Only carla.Vehicle actors can use this method. warning: > @@ -136,7 +136,7 @@ - param_name: angular_velocity type: carla.Vector3D doc: > - Sets the actor's angular velocity vector. The modification is instantaneous, and done before physics. The resulting angular velocity will be affected by external forces over time (such as friction). + Sets the actor's angular velocity vector. The modification will be effective two frames after the setting, and the update between angular velocities will be sudden. Also, this is applied before the physics step so the resulting angular velocity will be affected by external forces at this frame such as friction. note: > The update will not be effective until two frames after it is set. # -------------------------------------- @@ -168,7 +168,7 @@ - param_name: velocity type: carla.Vector3D doc: > - Sets the actor's velocity vector. The modification is instantaneous, and done before physics. The resulting velocity will be affected by external forces over time (such as friction). + Sets the actor's velocity vector. The modification will be effective two frames after the setting, and the update between velocities will be sudden. Also, this is applied before the physics step so the resulting velocity will be affected by external forces at this frame such as friction. note: > The update will not be effective until two frames after it is set. # -------------------------------------- diff --git a/PythonAPI/docs/commands.yml b/PythonAPI/docs/commands.yml index a0ab3839366..d9f4a996335 100644 --- a/PythonAPI/docs/commands.yml +++ b/PythonAPI/docs/commands.yml @@ -29,7 +29,7 @@ - class_name: SpawnActor # - DESCRIPTION ------------------------ doc: > - Command adaptation of **spawn_actor()** in carla.World. Spawns an actor into the world based on the blueprint provided and the transform. If a parent is provided, the actor is attached to it. + Command adaptation of __spawn_actor()__ in carla.World. Spawns an actor into the world based on the blueprint provided and the transform. If a parent is provided, the actor is attached to it. # - PROPERTIES ------------------------- instance_variables: - var_name: transform @@ -73,7 +73,7 @@ - class_name: DestroyActor # - DESCRIPTION ------------------------ doc: > - Command adaptation of **destroy()** in carla.Actor that tells the simulator to destroy this actor. It has no effect if the actor was already destroyed. When executed with **apply_batch_sync()** in carla.Client there will be a command.Response that will return a boolean stating whether the actor was successfully destroyed. + Command adaptation of __destroy()__ in carla.Actor that tells the simulator to destroy this actor. It has no effect if the actor was already destroyed. When executed with __apply_batch_sync()__ in carla.Client there will be a command.Response that will return a boolean stating whether the actor was successfully destroyed. # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id @@ -93,7 +93,7 @@ - class_name: ApplyVehicleControl # - DESCRIPTION ------------------------ doc: > - Command adaptation of **apply_control()** in carla.Vehicle. Applies a certain control to a vehicle. + Command adaptation of __apply_control()__ in carla.Vehicle. Applies a certain control to a vehicle. # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id @@ -119,7 +119,7 @@ - class_name: ApplyWalkerControl # - DESCRIPTION ------------------------ doc: > - Command adaptation of **apply_control()** in carla.Walker. Applies a control to a walker. + Command adaptation of __apply_control()__ in carla.Walker. Applies a control to a walker. # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id @@ -145,7 +145,7 @@ - class_name: ApplyTransform # - DESCRIPTION ------------------------ doc: > - Command adaptation of **set_transform()** in carla.Actor. Sets a new transform to an actor. + Command adaptation of __set_transform()__ in carla.Actor. Sets a new transform to an actor. # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id @@ -205,7 +205,7 @@ - class_name: ApplyTargetVelocity # - DESCRIPTION ------------------------ doc: > - Command adaptation of **set_target_velocity()** in carla.Actor. Sets the actor's velocity vector. The modification is instantaneous, and done before physics. The resulting velocity will be affected by external forces over time (such as friction). + Command adaptation of __set_target_velocity()__ in carla.Actor. # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id @@ -235,7 +235,7 @@ - class_name: ApplyTargetAngularVelocity # - DESCRIPTION ------------------------ doc: > - Command adaptation of **set_target_angular_velocity()** in carla.Actor. Sets the actor's angular velocity vector. The modification is instantaneous, and done before physics. The resulting angular velocity will be affected by external forces over time (such as friction). + Command adaptation of __set_target_angular_velocity()__ in carla.Actor. Sets the actor's angular velocity vector. # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id @@ -265,7 +265,7 @@ - class_name: ApplyImpulse # - DESCRIPTION ------------------------ doc: > - Command adaptation of **add_impulse()** in carla.Actor. Adds impulse to an actor. + Command adaptation of __add_impulse()__ in carla.Actor. Applies an impulse to an actor. # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id @@ -290,21 +290,47 @@ param_units: N*s # -------------------------------------- - - class_name: ApplyAngularImpulse + - class_name: ApplyForce # - DESCRIPTION ------------------------ doc: > - Command adaptation of **add_angular_impulse()** in carla.Actor. Adds angular impulse to an actor. + Command adaptation of __add_force()__ in carla.Actor. Applies a force to an actor. # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id type: int doc: > Actor affected by the command. + - var_name: force + type: carla.Vector3D + doc: > + Force applied to the actor over time. + # - METHODS ---------------------------- + methods: + - def_name: __init__ + params: + - param_name: actor + type: carla.Actor or int + doc: > + Actor or its ID to whom the command will be applied to. + - param_name: force + type: carla.Vector3D + # -------------------------------------- + + - class_name: ApplyAngularImpulse + # - DESCRIPTION ------------------------ + doc: > + Command adaptation of __add_angular_impulse()__ in carla.Actor. Applies an angular impulse to an actor. + # - PROPERTIES ------------------------- + instance_variables: + - var_name: actor_id + type: int + doc: > + Actor affected by the command. - var_name: impulse type: carla.Vector3D var_units: degrees doc: > - Angular impulse applied to the actor. Determines magnitude and global axis where it is applied. + Angular impulse applied to the actor. # - METHODS ---------------------------- methods: - def_name: __init__ @@ -318,10 +344,36 @@ param_units: degrees # -------------------------------------- + - class_name: ApplyTorque + # - DESCRIPTION ------------------------ + doc: > + Command adaptation of __add_torque()__ in carla.Actor. Applies a torque to an actor. + # - PROPERTIES ------------------------- + instance_variables: + - var_name: actor_id + type: int + doc: > + Actor affected by the command. + - var_name: torque + type: carla.Vector3D + doc: > + Torque applied to the actor over time. + # - METHODS ---------------------------- + methods: + - def_name: __init__ + params: + - param_name: actor + type: carla.Actor or int + doc: > + Actor or its ID to whom the command will be applied to. + - param_name: torque + type: carla.Vector3D + # -------------------------------------- + - class_name: SetSimulatePhysics # - DESCRIPTION ------------------------ doc: > - Command adaptation of **set_simulate_physics()** in carla.Actor. Determines whether an actor will be affected by physics or not. + Command adaptation of __set_simulate_physics()__ in carla.Actor. Determines whether an actor will be affected by physics or not. # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id @@ -347,7 +399,7 @@ - class_name: SetAutopilot # - DESCRIPTION ------------------------ doc: > - Command adaptation of **set_autopilot()** in carla.Vehicle. Turns on/off the vehicle's autopilot mode. + Command adaptation of __set_autopilot()__ in carla.Vehicle. Turns on/off the vehicle's autopilot mode. # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id @@ -382,7 +434,7 @@ - class_name: SetVehicleLightState # - DESCRIPTION ------------------------ doc: > - Command adaptation of **set_light_state()** in carla.Vehicle. Sets the light state of a vehicle. + Command adaptation of __set_light_state()__ in carla.Vehicle. Sets the light state of a vehicle. # - PROPERTIES ------------------------- instance_variables: - var_name: actor_id From 6b1298111b8fd8937d1832b2d6bee14f8507748a Mon Sep 17 00:00:00 2001 From: sergi-e Date: Thu, 24 Sep 2020 12:21:18 +0200 Subject: [PATCH 160/179] New iteration with units and fixes --- Docs/python_api.md | 38 ++++++++++++++++++------------------- PythonAPI/docs/actor.yml | 21 +++++++++++--------- PythonAPI/docs/commands.yml | 12 ++++++++---- 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index 1b7ae086460..d7b594bead5 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -20,21 +20,21 @@ The identifier of the blueprint this actor was based on, e.g. `vehicle.ford.must

    Methods

    - **add_angular_impulse**(**self**, **angular_impulse**) -Applies an angular impulse at the center of mass of the actor. Angular impulses only last an instant. Use __add_torque()__ to apply rotation forces over a period of time. +Applies an angular impulse at the center of mass of the actor. This method should be used for instantaneous torques, usually applied once. Use __add_torque()__ to apply rotation forces over a period of time. - **Parameters:** - - `angular_impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) – Angular impulse vector in global coordinates. + - `angular_impulse` (_[carla.Vector3D](#carla.Vector3D) – degrees*s_) – Angular impulse vector in global coordinates. - **add_force**(**self**, **force**) Applies a force at the center of mass of the actor. This method should be used for forces that are applied over a certain period of time. Use __add_impulse()__ to apply an impulse that only lasts an instant. - **Parameters:** - - `force` (_[carla.Vector3D](#carla.Vector3D) – degrees_) – Force vector in global coordinates. + - `force` (_[carla.Vector3D](#carla.Vector3D) – N_) – Force vector in global coordinates. - **add_impulse**(**self**, **impulse**) -Applies an impulse at the center of mass of the actor. Impulses only last an instant. Use __add_force()__ to apply forces over a period of time. +Applies an impulse at the center of mass of the actor. This method should be used for instantaneous forces, usually applied once. Use __add_force()__ to apply forces over a period of time. - **Parameters:** - - `impulse` (_[carla.Vector3D](#carla.Vector3D)_) – Impulse vector in global coordinates. + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – N*s_) – Impulse vector in global coordinates. - **add_torque**(**self**, **torque**) -Applies a torque at the center of mass of the actor. The effects of the torque depend on the delta time (time between simulation steps) during which it is applied. Use __add_angular_impulse()__ to apply a rotation impulse that only lasts an instant. +Applies a torque at the center of mass of the actor. This method should be used for torques that are applied over a certain period of time. Use __add_angular_impulse()__ to apply a torque that only lasts an instant. - **Parameters:** - - `torque` (_[carla.Vector3D](#carla.Vector3D)_) – Torque vector in global coordinates. + - `torque` (_[carla.Vector3D](#carla.Vector3D) – degrees_) – Torque vector in global coordinates. - **destroy**(**self**) Tells the simulator to destroy this actor and returns True if it was successful. It has no effect if it was already destroyed. - **Return:** _bool_ @@ -43,10 +43,10 @@ _
    - **disable_constant_velocity**(**self**) Disables any constant velocity previously set for a [carla.Vehicle](#carla.Vehicle) actor. - **enable_constant_velocity**(**self**, **velocity**) -Sets the actor's velocity vector to a constant value over time. The resulting velocity will be approximately the `velocity` being set, as with __set_target_velocity()__. +Sets a vehicle's velocity vector to a constant value over time. The resulting velocity will be approximately the `velocity` being set, as with __set_target_velocity()__. - **Parameters:** - - `velocity` (_[carla.Vector3D](#carla.Vector3D)_) – Velocity vector in local space. - - **Warning:** _Enabling a constant velocity for a vehicle managed by the [Traffic Manager](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/adv_traffic_manager/) may cause conflicts. It will not be able to override the constant velocity being set. + - `velocity` (_[carla.Vector3D](#carla.Vector3D) – m/s_) – Velocity vector in local space. + - **Warning:** _Enabling a constant velocity for a vehicle managed by the [Traffic Manager](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/adv_traffic_manager/) may cause conflicts. This method overrides any changes in velocity by the TM. _
    Getters
    @@ -73,7 +73,7 @@ Returns the world this actor belongs to.
    Setters
    - **set_target_angular_velocity**(**self**, **angular_velocity**) -Sets the actor's angular velocity vector. The modification will be effective two frames after the setting, and the update between angular velocities will be sudden. Also, this is applied before the physics step so the resulting angular velocity will be affected by external forces at this frame such as friction. +Sets the actor's angular velocity vector. The modification will be effective two frames after the setting. Also, this is applied before the physics step so the resulting angular velocity will be affected by external forces at this frame such as friction. - **Parameters:** - `angular_velocity` (_[carla.Vector3D](#carla.Vector3D)_) - **Note:** _The update will not be effective until two frames after it is set. @@ -93,7 +93,7 @@ Teleports the actor to a given transform (location and rotation). - `transform` (_[carla.Transform](#carla.Transform)_) - **Getter:** _[carla.Actor.get_transform](#carla.Actor.get_transform)_ - **set_target_velocity**(**self**, **velocity**) -Sets the actor's velocity vector. The modification will be effective two frames after the setting, and the update between velocities will be sudden. Also, this is applied before the physics step so the resulting velocity will be affected by external forces at this frame such as friction. +Sets the actor's velocity vector. The modification will be effective two frames after the setting. Also, this is applied before the physics step so the resulting velocity will be affected by external forces at this frame such as friction. - **Parameters:** - `velocity` (_[carla.Vector3D](#carla.Vector3D)_) - **Note:** _The update will not be effective until two frames after it is set. @@ -2818,14 +2818,14 @@ Command adaptation of __add_angular_impulse()__ in

    Instance Variables

    - **actor_id** (_int_) Actor affected by the command. -- **impulse** (_[carla.Vector3D](#carla.Vector3D) – degrees_) +- **impulse** (_[carla.Vector3D](#carla.Vector3D) – degrees*s_) Angular impulse applied to the actor.

    Methods

    - **\__init__**(**self**, **actor**, **impulse**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `impulse` (_[carla.Vector3D](#carla.Vector3D) – degrees_) + - `impulse` (_[carla.Vector3D](#carla.Vector3D) – degrees*s_) --- @@ -2835,14 +2835,14 @@ Command adaptation of __add_force()__ in [carla.Act

    Instance Variables

    - **actor_id** (_int_) Actor affected by the command. -- **force** (_[carla.Vector3D](#carla.Vector3D)_) +- **force** (_[carla.Vector3D](#carla.Vector3D) – N_) Force applied to the actor over time.

    Methods

    - **\__init__**(**self**, **actor**, **force**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `force` (_[carla.Vector3D](#carla.Vector3D)_) + - `force` (_[carla.Vector3D](#carla.Vector3D) – N_) --- @@ -2893,7 +2893,7 @@ The 3D velocity applied to the actor. - **\__init__**(**self**, **actor**, **velocity**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `velocity` (_[carla.Vector3D](#carla.Vector3D)_) – Velocity vector applied to the actor. + - `velocity` (_[carla.Vector3D](#carla.Vector3D) – m/s_) – Velocity vector applied to the actor. --- @@ -2903,14 +2903,14 @@ Command adaptation of __add_torque()__ in [carla.Ac

    Instance Variables

    - **actor_id** (_int_) Actor affected by the command. -- **torque** (_[carla.Vector3D](#carla.Vector3D)_) +- **torque** (_[carla.Vector3D](#carla.Vector3D) – degrees_) Torque applied to the actor over time.

    Methods

    - **\__init__**(**self**, **actor**, **torque**) - **Parameters:** - `actor` (_[carla.Actor](#carla.Actor) or int_) – Actor or its ID to whom the command will be applied to. - - `torque` (_[carla.Vector3D](#carla.Vector3D)_) + - `torque` (_[carla.Vector3D](#carla.Vector3D) – degrees_) --- diff --git a/PythonAPI/docs/actor.yml b/PythonAPI/docs/actor.yml index 2bc9a17e6de..21e9285f192 100644 --- a/PythonAPI/docs/actor.yml +++ b/PythonAPI/docs/actor.yml @@ -39,17 +39,17 @@ params: - param_name: angular_impulse type: carla.Vector3D - param_units: N*s + param_units: degrees*s doc: > Angular impulse vector in global coordinates. doc: > - Applies an angular impulse at the center of mass of the actor. Angular impulses only last an instant. Use __add_torque()__ to apply rotation forces over a period of time. + Applies an angular impulse at the center of mass of the actor. This method should be used for instantaneous torques, usually applied once. Use __add_torque()__ to apply rotation forces over a period of time. # -------------------------------------- - def_name: add_force params: - param_name: force type: carla.Vector3D - param_units: degrees + param_units: N doc: > Force vector in global coordinates. doc: > @@ -59,19 +59,21 @@ params: - param_name: impulse type: carla.Vector3D + param_units: N*s doc: > Impulse vector in global coordinates. doc: > - Applies an impulse at the center of mass of the actor. Impulses only last an instant. Use __add_force()__ to apply forces over a period of time. + Applies an impulse at the center of mass of the actor. This method should be used for instantaneous forces, usually applied once. Use __add_force()__ to apply forces over a period of time. # -------------------------------------- - def_name: add_torque params: - param_name: torque type: carla.Vector3D + param_units: degrees doc: > Torque vector in global coordinates. doc: > - Applies a torque at the center of mass of the actor. The effects of the torque depend on the delta time (time between simulation steps) during which it is applied. Use __add_angular_impulse()__ to apply a rotation impulse that only lasts an instant. + Applies a torque at the center of mass of the actor. This method should be used for torques that are applied over a certain period of time. Use __add_angular_impulse()__ to apply a torque that only lasts an instant. # -------------------------------------- - def_name: destroy return: bool @@ -90,12 +92,13 @@ type: carla.Vector3D doc: > Velocity vector in local space. + param_units: m/s doc: > - Sets the actor's velocity vector to a constant value over time. The resulting velocity will be approximately the `velocity` being set, as with __set_target_velocity()__. + Sets a vehicle's velocity vector to a constant value over time. The resulting velocity will be approximately the `velocity` being set, as with __set_target_velocity()__. Note: > Only carla.Vehicle actors can use this method. warning: > - Enabling a constant velocity for a vehicle managed by the [Traffic Manager](https://carla.readthedocs.io/en/latest/adv_traffic_manager/) may cause conflicts. It will not be able to override the constant velocity being set. + Enabling a constant velocity for a vehicle managed by the [Traffic Manager](https://carla.readthedocs.io/en/latest/adv_traffic_manager/) may cause conflicts. This method overrides any changes in velocity by the TM. # -------------------------------------- - def_name: get_acceleration return: carla.Vector3D @@ -136,7 +139,7 @@ - param_name: angular_velocity type: carla.Vector3D doc: > - Sets the actor's angular velocity vector. The modification will be effective two frames after the setting, and the update between angular velocities will be sudden. Also, this is applied before the physics step so the resulting angular velocity will be affected by external forces at this frame such as friction. + Sets the actor's angular velocity vector. The modification will be effective two frames after the setting. Also, this is applied before the physics step so the resulting angular velocity will be affected by external forces at this frame such as friction. note: > The update will not be effective until two frames after it is set. # -------------------------------------- @@ -168,7 +171,7 @@ - param_name: velocity type: carla.Vector3D doc: > - Sets the actor's velocity vector. The modification will be effective two frames after the setting, and the update between velocities will be sudden. Also, this is applied before the physics step so the resulting velocity will be affected by external forces at this frame such as friction. + Sets the actor's velocity vector. The modification will be effective two frames after the setting. Also, this is applied before the physics step so the resulting velocity will be affected by external forces at this frame such as friction. note: > The update will not be effective until two frames after it is set. # -------------------------------------- diff --git a/PythonAPI/docs/commands.yml b/PythonAPI/docs/commands.yml index d9f4a996335..f9edf58fe4d 100644 --- a/PythonAPI/docs/commands.yml +++ b/PythonAPI/docs/commands.yml @@ -115,7 +115,7 @@ - param_name: control type: carla.VehicleControl # -------------------------------------- - + - class_name: ApplyWalkerControl # - DESCRIPTION ------------------------ doc: > @@ -227,7 +227,7 @@ Actor or its ID to whom the command will be applied to. - param_name: velocity type: carla.Vector3D - param_untis: m/s + param_units: m/s doc: > Velocity vector applied to the actor. # -------------------------------------- @@ -304,6 +304,7 @@ type: carla.Vector3D doc: > Force applied to the actor over time. + var_units: N # - METHODS ---------------------------- methods: - def_name: __init__ @@ -314,6 +315,7 @@ Actor or its ID to whom the command will be applied to. - param_name: force type: carla.Vector3D + param_units: N # -------------------------------------- - class_name: ApplyAngularImpulse @@ -328,7 +330,7 @@ Actor affected by the command. - var_name: impulse type: carla.Vector3D - var_units: degrees + var_units: degrees*s doc: > Angular impulse applied to the actor. # - METHODS ---------------------------- @@ -341,7 +343,7 @@ Actor or its ID to whom the command will be applied to. - param_name: impulse type: carla.Vector3D - param_units: degrees + param_units: degrees*s # -------------------------------------- - class_name: ApplyTorque @@ -358,6 +360,7 @@ type: carla.Vector3D doc: > Torque applied to the actor over time. + var_units: degrees # - METHODS ---------------------------- methods: - def_name: __init__ @@ -368,6 +371,7 @@ Actor or its ID to whom the command will be applied to. - param_name: torque type: carla.Vector3D + param_units: degrees # -------------------------------------- - class_name: SetSimulatePhysics From 549bed21f2aba24cd88fbc80ff9af6891514fc69 Mon Sep 17 00:00:00 2001 From: bernat Date: Thu, 24 Sep 2020 12:49:58 +0200 Subject: [PATCH 161/179] New content version --- Util/ContentVersions.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Util/ContentVersions.txt b/Util/ContentVersions.txt index fd3af8e48b1..d673e5cbb0e 100644 --- a/Util/ContentVersions.txt +++ b/Util/ContentVersions.txt @@ -32,4 +32,4 @@ 0.9.7: 20191221_c88604b 0.9.8: 20200306_06b6cb1 0.9.9: 20200422_ea5179a -Latest: 20200923_8adc984 +Latest: 20200924_958819f From b926304b4cc9341dfa009533c669b588cfa132b1 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 23 Sep 2020 22:42:30 +0200 Subject: [PATCH 162/179] First iteration --- Docs/core_map.md | 11 +++++++++-- Docs/python_api.md | 6 ++++-- PythonAPI/docs/map.yml | 4 +++- PythonAPI/docs/world.yml | 4 +++- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Docs/core_map.md b/Docs/core_map.md index 6b8ad65b0df..5de8e0d7cca 100644 --- a/Docs/core_map.md +++ b/Docs/core_map.md @@ -86,7 +86,7 @@ waypoints_junc = my_junction.get_waypoints() ### Waypoints -A [__carla.Waypoint__](python_api.md#carla.Waypoint) is a 3D-directed point. These are prepared to mediate between the world and the openDRIVE definition of the road. +A [__carla.Waypoint__](python_api.md#carla.Waypoint) is a 3D-directed point. These are prepared to mediate between the world and the openDRIVE definition of the road. Everything related with waypoints happens on the client-side, so there no communication with the server is needed. Each waypoint contains a [carla.Transform](python_api.md#carla.Transform). This states its location on the map and the orientation of the lane containing it. The variables `road_id`,`section_id`,`lane_id` and `s` translate this transform to the OpenDRIVE road. These combined, create the `id` of the waypoint. @@ -105,6 +105,11 @@ right_lm_color = waypoint.right_lane_marking.color --- ## Navigation in CARLA +Navigation in CARLA is managed via the waypoint API. This consists of a summary of methods in [carla.Waypoint](python_api.md#carla.Waypoint) and [carla.Map](python_api.md#carla.Map) that provide connections between waypoints, and use these to generate a map navigation. + +All the queries happen on the client-side. The client only communicates with the server when retrieving the map object that will be used for the queries. Communication with the server is not needed after that, so the computational cost of the waypoint API is heavily reduced. + + ### Navigating through waypoints Waypoints have a set of methods to connect with others and create a road flow. All of these methods follow traffic rules to determine only places where the vehicle can go. @@ -125,7 +130,9 @@ while True: ### Generating a map navigation -The instance of the map is provided by the world. It will be useful to create routes and make vehicles roam around the city and reach goal destinations. +The instance of the map is provided by the world. It will be useful to create routes and make vehicles roam around the city and reach goal destinations. + +The following method asks the server for the XODR map file, and parses it to a [carla.Map](python_api.md#carla.Map) object. It only needs to be calle once. Maps can be quite heavy, and successive calls are unnecessary and expensive. ```py map = world.get_map() diff --git a/Docs/python_api.md b/Docs/python_api.md index d7b594bead5..e997b08c832 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -2447,7 +2447,7 @@ Compares every variable with `other` and returns True if any of these dif --- ## carla.Waypoint -Waypoints in CARLA are described as 3D directed points. They store a certain [carla.Transform](#carla.Transform) which locates the waypoint in a road and orientates it according to the lane. They also store the road information belonging to said point regarding its lane and lane markings. All of this information is retrieved as provided by the OpenDRIVE file. +Waypoints in CARLA are described as 3D directed points. They store a certain [carla.Transform](#carla.Transform) which locates the waypoint in a road and orientates it according to the lane. They also store the road information belonging to said point regarding its lane and lane markings.

    All the information regarding waypoints and the [waypoint API](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/core_map/#navigation-in-carla) is retrieved as provided by the OpenDRIVE file. Once the client asks for the map object to the server, no longer communication will be needed.

    Instance Variables

    - **id** (_int_) @@ -2699,8 +2699,10 @@ Returns a dict where the keys are [carla.Actor](#carla.Actor) IDs and the values Returns an instance of [carla.LightManager](#carla.LightManager) that can be used to handle the lights in the scene. - **Return:** _[carla.LightManager](#carla.LightManager)_ - **get_map**(**self**) -Returns the object containing the navigation map used to describe this world. +Asks the server for the XODR containing the map file, and returns this parsed as a [carla.Map](#carla.Map). - **Return:** _[carla.Map](#carla.Map)_ + - **Warning:** _This method does call the simulation. +_ - **get_traffic_light**(**self**, **landmark**) Provided a landmark, returns the traffic light object it describes. - **Parameters:** diff --git a/PythonAPI/docs/map.yml b/PythonAPI/docs/map.yml index b40a42ee878..7efaa8762a3 100644 --- a/PythonAPI/docs/map.yml +++ b/PythonAPI/docs/map.yml @@ -300,7 +300,9 @@ - class_name: Waypoint # - DESCRIPTION ------------------------ doc: > - Waypoints in CARLA are described as 3D directed points. They store a certain carla.Transform which locates the waypoint in a road and orientates it according to the lane. They also store the road information belonging to said point regarding its lane and lane markings. All of this information is retrieved as provided by the OpenDRIVE file. + Waypoints in CARLA are described as 3D directed points. They store a certain carla.Transform which locates the waypoint in a road and orientates it according to the lane. They also store the road information belonging to said point regarding its lane and lane markings. +

    + All the information regarding waypoints and the [waypoint API](https://carla.readthedocs.io/en/latest/core_map/#navigation-in-carla) is retrieved as provided by the OpenDRIVE file. Once the client asks for the map object to the server, no longer communication will be needed. # - PROPERTIES ------------------------- instance_variables: - var_name: id diff --git a/PythonAPI/docs/world.yml b/PythonAPI/docs/world.yml index baa3c149dbb..5ebc90faf47 100644 --- a/PythonAPI/docs/world.yml +++ b/PythonAPI/docs/world.yml @@ -349,7 +349,9 @@ - def_name: get_map return: carla.Map doc: > - Returns the object containing the navigation map used to describe this world. + Asks the server for the XODR containing the map file, and returns this parsed as a carla.Map. + warning: > + This method does call the simulation. # -------------------------------------- - def_name: get_traffic_light return: carla.TrafficLight From fda9e9fb9e34dc41087b5aabe4cf13005e9c9bdf Mon Sep 17 00:00:00 2001 From: sergi-e Date: Thu, 24 Sep 2020 12:57:15 +0200 Subject: [PATCH 163/179] New iteration on M comments --- Docs/core_map.md | 4 ++-- Docs/python_api.md | 4 ++-- PythonAPI/docs/map.yml | 4 ++-- PythonAPI/docs/world.yml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Docs/core_map.md b/Docs/core_map.md index 5de8e0d7cca..d3621067c6d 100644 --- a/Docs/core_map.md +++ b/Docs/core_map.md @@ -105,9 +105,9 @@ right_lm_color = waypoint.right_lane_marking.color --- ## Navigation in CARLA -Navigation in CARLA is managed via the waypoint API. This consists of a summary of methods in [carla.Waypoint](python_api.md#carla.Waypoint) and [carla.Map](python_api.md#carla.Map) that provide connections between waypoints, and use these to generate a map navigation. +Navigation in CARLA is managed via the waypoint API. This consists of a summary of methods in [carla.Waypoint](python_api.md#carla.Waypoint) and [carla.Map](python_api.md#carla.Map). -All the queries happen on the client-side. The client only communicates with the server when retrieving the map object that will be used for the queries. Communication with the server is not needed after that, so the computational cost of the waypoint API is heavily reduced. +All the queries happen on the client-side. The client only communicates with the server when retrieving the map object that will be used for the queries. There is no need to retrieve the map (`world.get_map()`) more than once. ### Navigating through waypoints diff --git a/Docs/python_api.md b/Docs/python_api.md index e997b08c832..732ece739f0 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -2447,7 +2447,7 @@ Compares every variable with `other` and returns True if any of these dif --- ## carla.Waypoint -Waypoints in CARLA are described as 3D directed points. They store a certain [carla.Transform](#carla.Transform) which locates the waypoint in a road and orientates it according to the lane. They also store the road information belonging to said point regarding its lane and lane markings.

    All the information regarding waypoints and the [waypoint API](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/core_map/#navigation-in-carla) is retrieved as provided by the OpenDRIVE file. Once the client asks for the map object to the server, no longer communication will be needed. +Waypoints in CARLA are described as 3D directed points. They have a [carla.Transform](#carla.Transform) which locates the waypoint in a road and orientates it according to the lane. They also store the road information belonging to said point regarding its lane and lane markings.

    All the information regarding waypoints and the [waypoint API](../../core_map/#navigation-in-carla) is retrieved as provided by the OpenDRIVE file. Once the client asks for the map object to the server, no longer communication will be needed.

    Instance Variables

    - **id** (_int_) @@ -2701,7 +2701,7 @@ Returns an instance of [carla.LightManager](#carla.LightManager) that can be use - **get_map**(**self**) Asks the server for the XODR containing the map file, and returns this parsed as a [carla.Map](#carla.Map). - **Return:** _[carla.Map](#carla.Map)_ - - **Warning:** _This method does call the simulation. + - **Warning:** _This method does call the simulation. It is expensive, and should only be called once. _ - **get_traffic_light**(**self**, **landmark**) Provided a landmark, returns the traffic light object it describes. diff --git a/PythonAPI/docs/map.yml b/PythonAPI/docs/map.yml index 7efaa8762a3..77bede69ef5 100644 --- a/PythonAPI/docs/map.yml +++ b/PythonAPI/docs/map.yml @@ -300,9 +300,9 @@ - class_name: Waypoint # - DESCRIPTION ------------------------ doc: > - Waypoints in CARLA are described as 3D directed points. They store a certain carla.Transform which locates the waypoint in a road and orientates it according to the lane. They also store the road information belonging to said point regarding its lane and lane markings. + Waypoints in CARLA are described as 3D directed points. They have a carla.Transform which locates the waypoint in a road and orientates it according to the lane. They also store the road information belonging to said point regarding its lane and lane markings.

    - All the information regarding waypoints and the [waypoint API](https://carla.readthedocs.io/en/latest/core_map/#navigation-in-carla) is retrieved as provided by the OpenDRIVE file. Once the client asks for the map object to the server, no longer communication will be needed. + All the information regarding waypoints and the [waypoint API](../../core_map/#navigation-in-carla) is retrieved as provided by the OpenDRIVE file. Once the client asks for the map object to the server, no longer communication will be needed. # - PROPERTIES ------------------------- instance_variables: - var_name: id diff --git a/PythonAPI/docs/world.yml b/PythonAPI/docs/world.yml index 5ebc90faf47..5cb3503fbce 100644 --- a/PythonAPI/docs/world.yml +++ b/PythonAPI/docs/world.yml @@ -351,7 +351,7 @@ doc: > Asks the server for the XODR containing the map file, and returns this parsed as a carla.Map. warning: > - This method does call the simulation. + This method does call the simulation. It is expensive, and should only be called once. # -------------------------------------- - def_name: get_traffic_light return: carla.TrafficLight From e97bb44b5c808f41d6ea91af84b1d2f3534c99b3 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Sun, 20 Sep 2020 11:21:44 +0200 Subject: [PATCH 164/179] First iteration --- Docs/python_api.md | 4 ++++ PythonAPI/docs/client.yml | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/Docs/python_api.md b/Docs/python_api.md index 732ece739f0..34388f48ae2 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -2036,6 +2036,10 @@ Enables or disables the hybrid physics mode. In this mode, vehicle's farther tha With hybrid physics on, changes the radius of the area of influence where physics are enabled. - **Parameters:** - `r` (_float – meters_) – New radius where physics are enabled. +- **set_osm_mode**(**self**, **set_osm_mode**=True) +Enables or disables the OSM mode. This mode fixes a bug when running a map created with the [OSM feature](tuto_G_openstreetmap.md). These maps usually have roads with abrupt ends (borders when the map is outlined). Vehicles cannot find the next waypoint, causing the TM to crash. When OSM mode is enabled, vehicles will be destroyed when no next waypoint is found. + - **Parameters:** + - `set_osm_mode` (_bool_) – If __True__, the OSM is enabled. --- diff --git a/PythonAPI/docs/client.yml b/PythonAPI/docs/client.yml index 1e6b7a4ad85..5d16c0488b3 100644 --- a/PythonAPI/docs/client.yml +++ b/PythonAPI/docs/client.yml @@ -443,6 +443,16 @@ doc: > With hybrid physics on, changes the radius of the area of influence where physics are enabled. # -------------------------------------- + - def_name: set_osm_mode + params: + - param_name: set_osm_mode + type: bool + default: true + doc: > + If __True__, the OSM is enabled. + doc: > + Enables or disables the OSM mode. This mode fixes a bug when running a map created with the [OSM feature](tuto_G_openstreetmap.md). These maps usually have roads with abrupt ends (borders when the map is outlined). Vehicles cannot find the next waypoint, causing the TM to crash. When OSM mode is enabled, vehicles will be destroyed when no next waypoint is found. + # -------------------------------------- - class_name: OpendriveGenerationParameters # - DESCRIPTION ------------------------ From a8059e76f43493e6e82538e557907764a0605111 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Sun, 20 Sep 2020 11:34:17 +0200 Subject: [PATCH 165/179] Added a note on OSM tutorial --- Docs/tuto_G_openstreetmap.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Docs/tuto_G_openstreetmap.md b/Docs/tuto_G_openstreetmap.md index c95a591a755..9f3c90c9e76 100644 --- a/Docs/tuto_G_openstreetmap.md +++ b/Docs/tuto_G_openstreetmap.md @@ -93,13 +93,16 @@ __b) Using `config.py`__ — The script can load an OpenStreetMap file directly ``` python3 config.py --osm-file=/path/to/OSM/file ``` -!!! Warning +!!! Important [client.generate_opendrive_world()](python_api.md#carla.Client.generate_opendrive_world) requires the __content of the OpenDRIVE file parsed as string__, and allows parameterization. On the contrary, __`config.py`__ script needs __the path to the `.xodr` file__ and always uses default parameters. Either way, the map should be ingested automatically in CARLA and the result should be similar to this. ![opendrive_meshissue](img/tuto_g_osm_carla.jpg)
    Outcome of the CARLA map generation using OpenStreetMap.
    +!!! Warning + The roads generated end abruptly in the borders of the map. This will cause the TM to crash when vehicles are not able to find the next waypoint. Temporarily, to workaround this bug, use [set_osm_mode()](python_api.md#carlatrafficmanager) to enable de OSM mode. This will destroy the vehicles when no next waypoint is found. + --- That is all there is to know about how to use OpenStreetMap to generate CARLA maps. From 017f8e3290f59b6bba957bfe45b59d51d78eb361 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Sun, 20 Sep 2020 12:48:52 +0200 Subject: [PATCH 166/179] Changed parameter name --- Docs/python_api.md | 4 ++-- PythonAPI/docs/client.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index 34388f48ae2..b78d9820004 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -2036,10 +2036,10 @@ Enables or disables the hybrid physics mode. In this mode, vehicle's farther tha With hybrid physics on, changes the radius of the area of influence where physics are enabled. - **Parameters:** - `r` (_float – meters_) – New radius where physics are enabled. -- **set_osm_mode**(**self**, **set_osm_mode**=True) +- **set_osm_mode**(**self**, **mode_switch**=True) Enables or disables the OSM mode. This mode fixes a bug when running a map created with the [OSM feature](tuto_G_openstreetmap.md). These maps usually have roads with abrupt ends (borders when the map is outlined). Vehicles cannot find the next waypoint, causing the TM to crash. When OSM mode is enabled, vehicles will be destroyed when no next waypoint is found. - **Parameters:** - - `set_osm_mode` (_bool_) – If __True__, the OSM is enabled. + - `mode_switch` (_bool_) – If __True__, the OSM is enabled. --- diff --git a/PythonAPI/docs/client.yml b/PythonAPI/docs/client.yml index 5d16c0488b3..5f27284cafe 100644 --- a/PythonAPI/docs/client.yml +++ b/PythonAPI/docs/client.yml @@ -445,7 +445,7 @@ # -------------------------------------- - def_name: set_osm_mode params: - - param_name: set_osm_mode + - param_name: mode_switch type: bool default: true doc: > From aa2d37a12481144820df899ae750fa6d0cff0348 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Mon, 21 Sep 2020 23:48:17 +0200 Subject: [PATCH 167/179] New iteration on Ja comments --- Docs/python_api.md | 4 ++-- Docs/tuto_G_openstreetmap.md | 2 +- PythonAPI/docs/client.yml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index b78d9820004..b3c556c1071 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -2037,9 +2037,9 @@ With hybrid physics on, changes the radius of the area of influence where physic - **Parameters:** - `r` (_float – meters_) – New radius where physics are enabled. - **set_osm_mode**(**self**, **mode_switch**=True) -Enables or disables the OSM mode. This mode fixes a bug when running a map created with the [OSM feature](tuto_G_openstreetmap.md). These maps usually have roads with abrupt ends (borders when the map is outlined). Vehicles cannot find the next waypoint, causing the TM to crash. When OSM mode is enabled, vehicles will be destroyed when no next waypoint is found. +Enables or disables the OSM mode. This mode allows the user to run TM in a map created with the [OSM feature](tuto_G_openstreetmap.md). These maps allow having dead-end streets. Normally, if vehicles cannot find the next waypoint, TM crashes. Now it throws an exception, warning the user to activate set_osm_mode and then stops. - **Parameters:** - - `mode_switch` (_bool_) – If __True__, the OSM is enabled. + - `mode_switch` (_bool_) – If __True__, the OSM mode is enabled. --- diff --git a/Docs/tuto_G_openstreetmap.md b/Docs/tuto_G_openstreetmap.md index 9f3c90c9e76..4abb2d56b1a 100644 --- a/Docs/tuto_G_openstreetmap.md +++ b/Docs/tuto_G_openstreetmap.md @@ -101,7 +101,7 @@ Either way, the map should be ingested automatically in CARLA and the result sho
    Outcome of the CARLA map generation using OpenStreetMap.
    !!! Warning - The roads generated end abruptly in the borders of the map. This will cause the TM to crash when vehicles are not able to find the next waypoint. Temporarily, to workaround this bug, use [set_osm_mode()](python_api.md#carlatrafficmanager) to enable de OSM mode. This will destroy the vehicles when no next waypoint is found. + The roads generated end abruptly in the borders of the map. This will cause the TM to crash when vehicles are not able to find the next waypoint. Use [set_osm_mode()](python_api.md#carlatrafficmanager) to enable de OSM mode. This will destroy the vehicles when no next waypoint is found. --- diff --git a/PythonAPI/docs/client.yml b/PythonAPI/docs/client.yml index 5f27284cafe..23eba0374ae 100644 --- a/PythonAPI/docs/client.yml +++ b/PythonAPI/docs/client.yml @@ -449,9 +449,9 @@ type: bool default: true doc: > - If __True__, the OSM is enabled. + If __True__, the OSM mode is enabled. doc: > - Enables or disables the OSM mode. This mode fixes a bug when running a map created with the [OSM feature](tuto_G_openstreetmap.md). These maps usually have roads with abrupt ends (borders when the map is outlined). Vehicles cannot find the next waypoint, causing the TM to crash. When OSM mode is enabled, vehicles will be destroyed when no next waypoint is found. + Enables or disables the OSM mode. This mode allows the user to run TM in a map created with the [OSM feature](tuto_G_openstreetmap.md). These maps allow having dead-end streets. Normally, if vehicles cannot find the next waypoint, TM crashes. Now it throws an exception, warning the user to activate set_osm_mode and then stops. # -------------------------------------- - class_name: OpendriveGenerationParameters From b17b2e44df803da54464e701bb856853ed4be78d Mon Sep 17 00:00:00 2001 From: sergi-e Date: Tue, 22 Sep 2020 00:00:27 +0200 Subject: [PATCH 168/179] Notes on spawn_npc.py --- Docs/python_api.md | 2 ++ Docs/tuto_G_openstreetmap.md | 2 +- PythonAPI/docs/client.yml | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index b3c556c1071..a8f7912282f 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -2040,6 +2040,8 @@ With hybrid physics on, changes the radius of the area of influence where physic Enables or disables the OSM mode. This mode allows the user to run TM in a map created with the [OSM feature](tuto_G_openstreetmap.md). These maps allow having dead-end streets. Normally, if vehicles cannot find the next waypoint, TM crashes. Now it throws an exception, warning the user to activate set_osm_mode and then stops. - **Parameters:** - `mode_switch` (_bool_) – If __True__, the OSM mode is enabled. + - **Note:** _The argument `--osm` in `PythonAPI/examples/spawn_npc.py` makes use of this method to enable OSM mode. +_ --- diff --git a/Docs/tuto_G_openstreetmap.md b/Docs/tuto_G_openstreetmap.md index 4abb2d56b1a..bd3acc3621f 100644 --- a/Docs/tuto_G_openstreetmap.md +++ b/Docs/tuto_G_openstreetmap.md @@ -101,7 +101,7 @@ Either way, the map should be ingested automatically in CARLA and the result sho
    Outcome of the CARLA map generation using OpenStreetMap.
    !!! Warning - The roads generated end abruptly in the borders of the map. This will cause the TM to crash when vehicles are not able to find the next waypoint. Use [set_osm_mode()](python_api.md#carlatrafficmanager) to enable de OSM mode. This will destroy the vehicles when no next waypoint is found. + The roads generated end abruptly in the borders of the map. This will cause the TM to crash when vehicles are not able to find the next waypoint. Use [set_osm_mode()](python_api.md#carlatrafficmanager) or directly the `--osm` argument in `PythonAPI/examples/spawn_npc.py` to enable de OSM mode. This will destroy the vehicles when no next waypoint is found. --- diff --git a/PythonAPI/docs/client.yml b/PythonAPI/docs/client.yml index 23eba0374ae..6af03c766d3 100644 --- a/PythonAPI/docs/client.yml +++ b/PythonAPI/docs/client.yml @@ -450,6 +450,8 @@ default: true doc: > If __True__, the OSM mode is enabled. + note: > + The argument `--osm` in `PythonAPI/examples/spawn_npc.py` makes use of this method to enable OSM mode. doc: > Enables or disables the OSM mode. This mode allows the user to run TM in a map created with the [OSM feature](tuto_G_openstreetmap.md). These maps allow having dead-end streets. Normally, if vehicles cannot find the next waypoint, TM crashes. Now it throws an exception, warning the user to activate set_osm_mode and then stops. # -------------------------------------- From 79457a6e76e8c1c6f0152f13e160558f42a228c9 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Thu, 24 Sep 2020 13:21:52 +0200 Subject: [PATCH 169/179] New iteration on Ja comments --- Docs/python_api.md | 4 +--- Docs/tuto_G_openstreetmap.md | 2 +- PythonAPI/docs/client.yml | 4 +--- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index a8f7912282f..832e3d3f429 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -2037,11 +2037,9 @@ With hybrid physics on, changes the radius of the area of influence where physic - **Parameters:** - `r` (_float – meters_) – New radius where physics are enabled. - **set_osm_mode**(**self**, **mode_switch**=True) -Enables or disables the OSM mode. This mode allows the user to run TM in a map created with the [OSM feature](tuto_G_openstreetmap.md). These maps allow having dead-end streets. Normally, if vehicles cannot find the next waypoint, TM crashes. Now it throws an exception, warning the user to activate set_osm_mode and then stops. +Enables or disables the OSM mode. This mode allows the user to run TM in a map created with the [OSM feature](tuto_G_openstreetmap.md). These maps allow having dead-end streets. Normally, if vehicles cannot find the next waypoint, TM crashes. If OSM mode is enabled, it will show a warning, and destroy vehicles when necessary. - **Parameters:** - `mode_switch` (_bool_) – If __True__, the OSM mode is enabled. - - **Note:** _The argument `--osm` in `PythonAPI/examples/spawn_npc.py` makes use of this method to enable OSM mode. -_ --- diff --git a/Docs/tuto_G_openstreetmap.md b/Docs/tuto_G_openstreetmap.md index bd3acc3621f..eb6a4d9a920 100644 --- a/Docs/tuto_G_openstreetmap.md +++ b/Docs/tuto_G_openstreetmap.md @@ -101,7 +101,7 @@ Either way, the map should be ingested automatically in CARLA and the result sho
    Outcome of the CARLA map generation using OpenStreetMap.
    !!! Warning - The roads generated end abruptly in the borders of the map. This will cause the TM to crash when vehicles are not able to find the next waypoint. Use [set_osm_mode()](python_api.md#carlatrafficmanager) or directly the `--osm` argument in `PythonAPI/examples/spawn_npc.py` to enable de OSM mode. This will destroy the vehicles when no next waypoint is found. + The roads generated end abruptly in the borders of the map. This will cause the TM to crash when vehicles are not able to find the next waypoint. To avoid this, the OSM mode is set to __True__ by default ([set_osm_mode()](python_api.md#carlatrafficmanager)). This will show a warning, and destroy vehicles when necessary. --- diff --git a/PythonAPI/docs/client.yml b/PythonAPI/docs/client.yml index 6af03c766d3..4b9c128611e 100644 --- a/PythonAPI/docs/client.yml +++ b/PythonAPI/docs/client.yml @@ -450,10 +450,8 @@ default: true doc: > If __True__, the OSM mode is enabled. - note: > - The argument `--osm` in `PythonAPI/examples/spawn_npc.py` makes use of this method to enable OSM mode. doc: > - Enables or disables the OSM mode. This mode allows the user to run TM in a map created with the [OSM feature](tuto_G_openstreetmap.md). These maps allow having dead-end streets. Normally, if vehicles cannot find the next waypoint, TM crashes. Now it throws an exception, warning the user to activate set_osm_mode and then stops. + Enables or disables the OSM mode. This mode allows the user to run TM in a map created with the [OSM feature](tuto_G_openstreetmap.md). These maps allow having dead-end streets. Normally, if vehicles cannot find the next waypoint, TM crashes. If OSM mode is enabled, it will show a warning, and destroy vehicles when necessary. # -------------------------------------- - class_name: OpendriveGenerationParameters From 7d91a14fae62db8286651b7672fcece3dc762a5a Mon Sep 17 00:00:00 2001 From: Jacopo Bartiromo Date: Thu, 24 Sep 2020 16:05:54 +0200 Subject: [PATCH 170/179] Fixes float conversion in TM --- LibCarla/source/carla/trafficmanager/Constants.h | 1 + LibCarla/source/carla/trafficmanager/MotionPlanStage.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/LibCarla/source/carla/trafficmanager/Constants.h b/LibCarla/source/carla/trafficmanager/Constants.h index 5d3e611f654..d53cdfc08cf 100644 --- a/LibCarla/source/carla/trafficmanager/Constants.h +++ b/LibCarla/source/carla/trafficmanager/Constants.h @@ -28,6 +28,7 @@ static const double DELTA_TIME_BETWEEN_DESTRUCTIONS = 10.0; } // namespace VehicleRemoval namespace HybridMode { +static const float HYBRID_MODE_DT_FL = 0.05f; static const double HYBRID_MODE_DT = 0.05; static const double INV_HYBRID_DT = 1.0 / HYBRID_MODE_DT; static const float PHYSICS_RADIUS = 50.0f; diff --git a/LibCarla/source/carla/trafficmanager/MotionPlanStage.cpp b/LibCarla/source/carla/trafficmanager/MotionPlanStage.cpp index f39961892ff..cda69919f32 100644 --- a/LibCarla/source/carla/trafficmanager/MotionPlanStage.cpp +++ b/LibCarla/source/carla/trafficmanager/MotionPlanStage.cpp @@ -12,6 +12,7 @@ using namespace constants::WaypointSelection; using namespace constants::SpeedThreshold; using constants::HybridMode::HYBRID_MODE_DT; +using constants::HybridMode::HYBRID_MODE_DT_FL; MotionPlanStage::MotionPlanStage( const std::vector &vehicle_id_list, @@ -147,7 +148,7 @@ void MotionPlanStage::Update(const unsigned long index) { if (!emergency_stop && (parameters.GetSynchronousMode() || elapsed_time > HYBRID_MODE_DT)) { // Target displacement magnitude to achieve target velocity. - const float target_displacement = dynamic_target_velocity * HYBRID_MODE_DT; + const float target_displacement = dynamic_target_velocity * HYBRID_MODE_DT_FL; const SimpleWaypointPtr teleport_target_waypoint = GetTargetWaypoint(waypoint_buffer, target_displacement).first; // Construct target transform to accurately achieve desired velocity. From a58a1f5b6d33ab3fe54214a7457da253e7babbb5 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 16 Sep 2020 17:33:51 +0200 Subject: [PATCH 171/179] First iteration --- Docs/python_api.md | 45 +++++++++++++++++++++++++++++++--- PythonAPI/docs/actor.yml | 4 +-- PythonAPI/docs/geom.yml | 8 ++++-- PythonAPI/docs/sensor_data.yml | 31 +++++++++++++++++++++++ PythonAPI/docs/world.yml | 11 +++++++++ 5 files changed, 91 insertions(+), 8 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index 832e3d3f429..50376b0f181 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -308,14 +308,16 @@ Parses the identifiers for every blueprint to string. --- ## carla.BoundingBox -Helper class defining a box location and its dimensions that will later be used by [carla.DebugHelper](#carla.DebugHelper) or a [carla.Client](#carla.Client) to draw shapes and detect collisions. Bounding boxes normally act for object colliders. Check out this [recipe](ref_code_recipes.md#debug-bounding-box-recipe) where the user takes a snapshot of the world and then proceeds to draw bounding boxes for traffic lights. +Bounding boxes contain the geometry of an actor or an element in the scene. They can be used by [carla.DebugHelper](#carla.DebugHelper) or a [carla.Client](#carla.Client) to draw their shapes for debugging. Check out this [recipe](ref_code_recipes.md#debug-bounding-box-recipe) where the user takes a snapshot of the world and then proceeds to draw bounding boxes for traffic lights.

    Instance Variables

    - **extent** (_[carla.Vector3D](#carla.Vector3D) – meters_) Vector from the center of the box to one vertex. The value in each axis equals half the size of the box for that axis. `extent.x * 2` would return the size of the box in the X-axis. - **location** (_[carla.Location](#carla.Location) – meters_) -The center of the bounding box relative to its parent actor. +The center of the bounding box. +- **rotation** (_[carla.Rotation](#carla.Rotation)_) +The orientation of the bounding box.

    Methods

    - **\__init__**(**self**, **location**, **extent**) @@ -352,6 +354,36 @@ Parses the location and extent of the bounding box to string. --- +## carla.CityObjectLabel +Enum declaration that contains the different tags available to filter the bounding boxes returned by [carla.World.get_level_bbs](#carla.World.get_level_bbs)(). These values correspond to the [semantic tag](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/ref_sensors/#semantic-segmentation-camera) that the elements in the scene have. + +

    Instance Variables

    +- **None** +- **Buildings** +- **Fences** +- **Other** +- **Pedestrians** +- **Poles** +- **RoadLines** +- **Roads** +- **Sidewalks** +- **TrafficSigns** +- **Vegetation** +- **Vehicles** +- **Walls** +- **Sky** +- **Ground** +- **Bridge** +- **RailTrack** +- **GuardRail** +- **TrafficLight** +- **Static** +- **Dynamic** +- **Water** +- **Terrain** + +--- + ## carla.Client The Client connects CARLA to the server which runs the simulation. Both server and client contain a CARLA library (libcarla) with some differences that allow communication between them. Many clients can be created and each of these will connect to the RPC server inside the simulation to send commands. The simulation runs server-side. Once the connection is established, the client will only receive data retrieved from the simulation. Walkers are the exception. The client is in charge of managing pedestrians so, if you are running a simulation with multiple clients, some issues may arise. For example, if you spawn walkers through different clients, collisions may happen, as each client is only aware of the ones it is in charge of. @@ -2173,7 +2205,7 @@ Returns the axis values for the vector parsed as string.

    Instance Variables

    - **bounding_box** (_[carla.BoundingBox](#carla.BoundingBox)_) -The vehicle's collider volume. +Bounding box containing the geometry of the vehicle. Its location and rotation are relative to the vehicle it is attached to.

    Methods

    - **apply_control**(**self**, **control**) @@ -2357,7 +2389,7 @@ VehiclePhysicsControl constructor.

    Instance Variables

    - **bounding_box** (_[carla.BoundingBox](#carla.BoundingBox)_) -The walker's collider defined by a bounding box. +Bounding box containing the geometry of the walker. Its location and rotation are relative to the walker it is attached to.

    Methods

    - **apply_control**(**self**, **control**) @@ -2699,6 +2731,11 @@ Returns a list of actor blueprints available to ease the spawn of these into the - **get_vehicles_light_states**(**self**) Returns a dict where the keys are [carla.Actor](#carla.Actor) IDs and the values are [carla.VehicleLightState](#carla.VehicleLightState) of that vehicle. - **Return:** _dict_ +- **get_level_bbs**(**self**, **actor_type**=None) +Returns an array of bounding boxes with location and rotation in world space. The function returns all the bounding boxes in the level by default, but the result can be filtered using semantic tags with the argument `actor_type`. + - **Parameters:** + - `actor_type` (_[carla.CityObjectLabel](#carla.CityObjectLabel)_) – Semantic tag of the elements contained in the bounding boxes that are returned. + - **Return:** _array([carla.BoundingBox](#carla.BoundingBox))_ - **get_lightmanager**(**self**) Returns an instance of [carla.LightManager](#carla.LightManager) that can be used to handle the lights in the scene. - **Return:** _[carla.LightManager](#carla.LightManager)_ diff --git a/PythonAPI/docs/actor.yml b/PythonAPI/docs/actor.yml index 21e9285f192..361b84ed62e 100644 --- a/PythonAPI/docs/actor.yml +++ b/PythonAPI/docs/actor.yml @@ -220,7 +220,7 @@ - var_name: bounding_box type: carla.BoundingBox doc: > - The vehicle's collider volume. + Bounding box containing the geometry of the vehicle. Its location and rotation are relative to the vehicle it is attached to. # - METHODS ---------------------------- methods: - def_name: apply_control @@ -309,7 +309,7 @@ - var_name: bounding_box type: carla.BoundingBox doc: > - The walker's collider defined by a bounding box. + Bounding box containing the geometry of the walker. Its location and rotation are relative to the walker it is attached to. # - METHODS ---------------------------- methods: - def_name: apply_control diff --git a/PythonAPI/docs/geom.yml b/PythonAPI/docs/geom.yml index 9ccc3f7da22..29e92d9a926 100644 --- a/PythonAPI/docs/geom.yml +++ b/PythonAPI/docs/geom.yml @@ -383,7 +383,7 @@ - class_name: BoundingBox # - DESCRIPTION ------------------------ doc: > - Helper class defining a box location and its dimensions that will later be used by carla.DebugHelper or a carla.Client to draw shapes and detect collisions. Bounding boxes normally act for object colliders. Check out this [recipe](ref_code_recipes.md#debug-bounding-box-recipe) where the user takes a snapshot of the world and then proceeds to draw bounding boxes for traffic lights. + Bounding boxes contain the geometry of an actor or an element in the scene. They can be used by carla.DebugHelper or a carla.Client to draw their shapes for debugging. Check out this [recipe](ref_code_recipes.md#debug-bounding-box-recipe) where the user takes a snapshot of the world and then proceeds to draw bounding boxes for traffic lights. # - PROPERTIES ------------------------- instance_variables: - var_name: extent @@ -397,7 +397,11 @@ type: carla.Location var_units: meters doc: > - The center of the bounding box relative to its parent actor. + The center of the bounding box. + - var_name: rotation + type: carla.Rotation + doc: > + The orientation of the bounding box. # - METHODS ---------------------------- methods: - def_name: __init__ diff --git a/PythonAPI/docs/sensor_data.yml b/PythonAPI/docs/sensor_data.yml index 4ea1c3e86b4..fc5166fcff0 100644 --- a/PythonAPI/docs/sensor_data.yml +++ b/PythonAPI/docs/sensor_data.yml @@ -52,6 +52,37 @@ doc: > No changes applied to the image. Used by the [RGB camera](ref_sensors.md#rgb-camera). + - class_name: CityObjectLabel + # - DESCRIPTION ------------------------ + doc: > + Enum declaration that contains the different tags available to filter the bounding boxes returned by carla.World.get_level_bbs(). These values correspond to the [semantic tag](https://carla.readthedocs.io/en/latest/ref_sensors/#semantic-segmentation-camera) that the elements in the scene have. + + # - PROPERTIES ------------------------- + instance_variables: + - var_name: None + - var_name: Buildings + - var_name: Fences + - var_name: Other + - var_name: Pedestrians + - var_name: Poles + - var_name: RoadLines + - var_name: Roads + - var_name: Sidewalks + - var_name: TrafficSigns + - var_name: Vegetation + - var_name: Vehicles + - var_name: Walls + - var_name: Sky + - var_name: Ground + - var_name: Bridge + - var_name: RailTrack + - var_name: GuardRail + - var_name: TrafficLight + - var_name: Static + - var_name: Dynamic + - var_name: Water + - var_name: Terrain + - class_name: Image parent: carla.SensorData # - DESCRIPTION ------------------------ diff --git a/PythonAPI/docs/world.yml b/PythonAPI/docs/world.yml index 5cb3503fbce..02f9a2b1891 100644 --- a/PythonAPI/docs/world.yml +++ b/PythonAPI/docs/world.yml @@ -330,6 +330,17 @@ doc: > Returns a dict where the keys are carla.Actor IDs and the values are carla.VehicleLightState of that vehicle. # -------------------------------------- + - def_name: get_level_bbs + params: + - param_name: actor_type + type: carla.CityObjectLabel + default: None + doc: > + Semantic tag of the elements contained in the bounding boxes that are returned. + return: array(carla.BoundingBox) + doc: > + Returns an array of bounding boxes with location and rotation in world space. The function returns all the bounding boxes in the level by default, but the result can be filtered using semantic tags with the argument `actor_type`. + # -------------------------------------- - def_name: get_lightmanager return: carla.LightManager doc: > From 568ca0ee3355295bb99de5528143ac997312d3ec Mon Sep 17 00:00:00 2001 From: sergi-e Date: Thu, 24 Sep 2020 15:59:45 +0200 Subject: [PATCH 172/179] Last fixes --- Docs/python_api.md | 4 ++-- PythonAPI/docs/sensor_data.yml | 2 +- PythonAPI/docs/world.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Docs/python_api.md b/Docs/python_api.md index 50376b0f181..9269d643854 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -355,7 +355,7 @@ Parses the location and extent of the bounding box to string. --- ## carla.CityObjectLabel -Enum declaration that contains the different tags available to filter the bounding boxes returned by [carla.World.get_level_bbs](#carla.World.get_level_bbs)(). These values correspond to the [semantic tag](https://[carla.readthedocs.io](#carla.readthedocs.io)/en/latest/ref_sensors/#semantic-segmentation-camera) that the elements in the scene have. +Enum declaration that contains the different tags available to filter the bounding boxes returned by [carla.World.get_level_bbs](#carla.World.get_level_bbs)(). These values correspond to the [semantic tag](../../ref_sensors/#semantic-segmentation-camera) that the elements in the scene have.

    Instance Variables

    - **None** @@ -2732,7 +2732,7 @@ Returns a list of actor blueprints available to ease the spawn of these into the Returns a dict where the keys are [carla.Actor](#carla.Actor) IDs and the values are [carla.VehicleLightState](#carla.VehicleLightState) of that vehicle. - **Return:** _dict_ - **get_level_bbs**(**self**, **actor_type**=None) -Returns an array of bounding boxes with location and rotation in world space. The function returns all the bounding boxes in the level by default, but the result can be filtered using semantic tags with the argument `actor_type`. +Returns an array of bounding boxes with location and rotation in world space. The method returns all the bounding boxes in the level by default, but the query can be filtered by semantic tags with the argument `actor_type`. - **Parameters:** - `actor_type` (_[carla.CityObjectLabel](#carla.CityObjectLabel)_) – Semantic tag of the elements contained in the bounding boxes that are returned. - **Return:** _array([carla.BoundingBox](#carla.BoundingBox))_ diff --git a/PythonAPI/docs/sensor_data.yml b/PythonAPI/docs/sensor_data.yml index fc5166fcff0..4b0422507fb 100644 --- a/PythonAPI/docs/sensor_data.yml +++ b/PythonAPI/docs/sensor_data.yml @@ -55,7 +55,7 @@ - class_name: CityObjectLabel # - DESCRIPTION ------------------------ doc: > - Enum declaration that contains the different tags available to filter the bounding boxes returned by carla.World.get_level_bbs(). These values correspond to the [semantic tag](https://carla.readthedocs.io/en/latest/ref_sensors/#semantic-segmentation-camera) that the elements in the scene have. + Enum declaration that contains the different tags available to filter the bounding boxes returned by carla.World.get_level_bbs(). These values correspond to the [semantic tag](../../ref_sensors/#semantic-segmentation-camera) that the elements in the scene have. # - PROPERTIES ------------------------- instance_variables: diff --git a/PythonAPI/docs/world.yml b/PythonAPI/docs/world.yml index 02f9a2b1891..3edcc54e7b9 100644 --- a/PythonAPI/docs/world.yml +++ b/PythonAPI/docs/world.yml @@ -339,7 +339,7 @@ Semantic tag of the elements contained in the bounding boxes that are returned. return: array(carla.BoundingBox) doc: > - Returns an array of bounding boxes with location and rotation in world space. The function returns all the bounding boxes in the level by default, but the result can be filtered using semantic tags with the argument `actor_type`. + Returns an array of bounding boxes with location and rotation in world space. The method returns all the bounding boxes in the level by default, but the query can be filtered by semantic tags with the argument `actor_type`. # -------------------------------------- - def_name: get_lightmanager return: carla.LightManager From 25f1780a1e1dead7a6b22bb030892033a9db719a Mon Sep 17 00:00:00 2001 From: bernat Date: Thu, 24 Sep 2020 20:39:58 +0200 Subject: [PATCH 173/179] New content version --- Util/ContentVersions.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Util/ContentVersions.txt b/Util/ContentVersions.txt index d673e5cbb0e..e34785f11d0 100644 --- a/Util/ContentVersions.txt +++ b/Util/ContentVersions.txt @@ -32,4 +32,4 @@ 0.9.7: 20191221_c88604b 0.9.8: 20200306_06b6cb1 0.9.9: 20200422_ea5179a -Latest: 20200924_958819f +Latest: 20200924_ea7f083 From e05b58c2a49381d09f22805f6e7e901eed3666c3 Mon Sep 17 00:00:00 2001 From: doterop Date: Thu, 24 Sep 2020 23:33:11 +0200 Subject: [PATCH 174/179] Retrieve BBs of level (#3360) * Added new function to calculate BBs on SKM and SM * Added BB calculation for an array of actors * Added BB folliage calculation * Added a call on the GM to get all the BBs of the level * Fixed Folliage BB calculation. * GM::GetAllBBsOfLevel now returns the array of BBs * Added call on the server side to retrieve the BBs * Removed debug draw calls * Added call to the PythonAPI * Added check for empty folliage actors * Added missing EOF * Added new RotateVector function * Added rotation to the BBs * Update changelog * Split BB calculation on more functions * Add tag query and simplified Folliage actor BB calculation * Look for ISM instead of HISM * Cleaning comments * Fixed BB duplication on BP_Procedural_Buildings * Fixed BB duplication on vehicles BPs * Added pedestrians case * Added CityObjectLabel enum on PythonAPI * Splitted logic in small functions * Fixed uint8_t * Merged BB of the lights in a TL * Splitted work into more functions * Added missing BB and rotation to TL * Cleaned comments * Added missing include * Changed None to Any in PythonAPI * Fixed Any enum * Added check for empty folliage actors * Added missing EOF * Added new RotateVector function * Added rotation to the BBs * Update changelog * Split BB calculation on more functions * Add tag query and simplified Folliage actor BB calculation * Look for ISM instead of HISM * Cleaning comments * Fixed BB duplication on BP_Procedural_Buildings * Fixed BB duplication on vehicles BPs * Added pedestrians case * Added CityObjectLabel enum on PythonAPI * Splitted logic in small functions * Fixed uint8_t * Merged BB of the lights in a TL * Splitted work into more functions * Added missing BB and rotation to TL * Cleaned comments * Changed None to Any in PythonAPI * Fixed Any enum * Fixed rebase * Fixing wrong BB on splines * Fixed ISM transform to World * Fixed duplication of RotateVector * Added Rotation to BB output string * Removed hidden components and procedural building * Fixed string BB output * Removed logs * Fixed filter on pedestrians * Fixed black debug lines in package Co-authored-by: Marc Garcia Puig --- LibCarla/source/carla/geom/Rotation.h | 26 +---------- PythonAPI/carla/source/libcarla/Geom.cpp | 1 + .../Carla/Source/Carla/Sensor/PixelReader.cpp | 1 - .../Carla/Util/BoundingBoxCalculator.cpp | 44 ++++++++++++------- .../Source/Carla/Util/DebugShapeDrawer.cpp | 9 ++++ 5 files changed, 41 insertions(+), 40 deletions(-) diff --git a/LibCarla/source/carla/geom/Rotation.h b/LibCarla/source/carla/geom/Rotation.h index 207f20b15a8..3096dc2de2f 100644 --- a/LibCarla/source/carla/geom/Rotation.h +++ b/LibCarla/source/carla/geom/Rotation.h @@ -88,30 +88,8 @@ namespace geom { } Vector3D RotateVector(const Vector3D& in_point) const { - // Rotates Rz(yaw) * Ry(pitch) * Rx(roll) = first x, then y, then z. - const float cy = std::cos(Math::ToRadians(yaw)); - const float sy = std::sin(Math::ToRadians(yaw)); - const float cr = std::cos(Math::ToRadians(roll)); - const float sr = std::sin(Math::ToRadians(roll)); - const float cp = std::cos(Math::ToRadians(pitch)); - const float sp = std::sin(Math::ToRadians(pitch)); - - Vector3D out_point; - out_point.x = - in_point.x * (cp * cy) + - in_point.y * (cy * sp * sr - sy * cr) + - in_point.z * (-cy * sp * cr - sy * sr); - - out_point.y = - in_point.x * (cp * sy) + - in_point.y * (sy * sp * sr + cy * cr) + - in_point.z * (-sy * sp * cr + cy * sr); - - out_point.z = - in_point.x * (sp) + - in_point.y * (-cp * sr) + - in_point.z * (cp * cr); - + Vector3D out_point = in_point; + RotateVector(out_point); return out_point; } diff --git a/PythonAPI/carla/source/libcarla/Geom.cpp b/PythonAPI/carla/source/libcarla/Geom.cpp index c772176364e..05044d85f4b 100644 --- a/PythonAPI/carla/source/libcarla/Geom.cpp +++ b/PythonAPI/carla/source/libcarla/Geom.cpp @@ -65,6 +65,7 @@ namespace geom { std::ostream &operator<<(std::ostream &out, const BoundingBox &box) { out << "BoundingBox(" << box.location << ", "; WriteVector3D(out, "Extent", box.extent); + out << ", " << box.rotation; out << ')'; return out; } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp index 917af42ae76..41f687a4bbe 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp @@ -61,7 +61,6 @@ static void WritePixelsToBuffer_Vulkan( FTexture2DRHIRef Texture = RenderResource->GetRenderTargetTexture(); if (!Texture) { - UE_LOG(LogCarla, Error, TEXT("FPixelReader: UTextureRenderTarget2D missing render target texture")); return; } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp index 4f4c016c10b..ab90777a6d8 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp @@ -156,8 +156,14 @@ FBoundingBox UBoundingBoxCalculator::GetCharacterBoundingBox( { check(Character); + crp::CityObjectLabel TagQueried = (crp::CityObjectLabel)InTagQueried; + bool FilterByTag = TagQueried == crp::CityObjectLabel::None || + TagQueried == crp::CityObjectLabel::Pedestrians; + UCapsuleComponent* Capsule = Character->GetCapsuleComponent(); - if (Capsule) + + + if (Capsule && FilterByTag) { const float Radius = Capsule->GetScaledCapsuleRadius(); const float HalfHeight = Capsule->GetScaledCapsuleHalfHeight(); @@ -318,12 +324,15 @@ void UBoundingBoxCalculator::GetISMBoundingBox( return; } - const TArray& PerInstanceSMData = ISMComp->PerInstanceSMData; + const TArray& PerInstanceSMData = ISMComp->PerInstanceSMData; + + const FTransform ParentTransform = ISMComp->GetComponentTransform(); for(auto& InstSMIData : PerInstanceSMData) { - const FTransform Transform = FTransform(InstSMIData.Transform); + const FTransform Transform = FTransform(InstSMIData.Transform) * ParentTransform; FBoundingBox BoundingBox = ApplyTransformToBB(SMBoundingBox, Transform); + OutBoundingBox.Add(BoundingBox); } @@ -339,6 +348,10 @@ void UBoundingBoxCalculator::GetBBsOfStaticMeshComponents( for(UStaticMeshComponent* Comp : StaticMeshComps) { + + // Avoid duplication with SMComp and not visible meshes + if(!Comp->IsVisible() || Cast(Comp)) continue; + // Filter by tag crp::CityObjectLabel Tag = ATagger::GetTagOfTaggedComponent(*Comp); if(FilterByTagEnabled && Tag != TagQueried) continue; @@ -372,7 +385,8 @@ void UBoundingBoxCalculator::GetBBsOfSkeletalMeshComponents( { // Filter by tag crp::CityObjectLabel Tag = ATagger::GetTagOfTaggedComponent(*Comp); - if(FilterByTagEnabled && Tag != TagQueried) continue; + + if(!Comp->IsVisible() || (FilterByTagEnabled && Tag != TagQueried)) continue; USkeletalMesh* SkeletalMesh = Comp->SkeletalMesh; FBoundingBox BoundingBox = GetSkeletalMeshBoundingBox(SkeletalMesh); @@ -406,7 +420,7 @@ TArray UBoundingBoxCalculator::GetBoundingBoxOfActors( // When improved the BP_Procedural_Building this maybe should be removed // Note: We don't use casting here because the base class is a BP and is easier to do it this way, // than getting the UClass of the BP to cast the actor. - if(ClassName.Contains("BP_Procedural_Bulding")) continue; + if( ClassName.Contains("Procedural_Bulding") ) continue; // The vehicle's BP has a low-polystatic mesh for collisions, we should avoid it ACarlaWheeledVehicle* Vehicle = Cast(Actor); @@ -441,16 +455,6 @@ TArray UBoundingBoxCalculator::GetBoundingBoxOfActors( continue; } - // Calculate FBoundingBox of SM - TArray StaticMeshComps; - Actor->GetComponents(StaticMeshComps); - GetBBsOfStaticMeshComponents(StaticMeshComps, Result, InTagQueried); - - // Calculate FBoundingBox of SK_M - TArray SkeletalMeshComps; - Actor->GetComponents(SkeletalMeshComps); - GetBBsOfSkeletalMeshComponents(SkeletalMeshComps, Result, InTagQueried); - // Calculate FBoundingBox of ISM TArray ISMComps; Actor->GetComponents(ISMComps); @@ -463,6 +467,16 @@ TArray UBoundingBoxCalculator::GetBoundingBoxOfActors( GetISMBoundingBox(Comp, Result); } + // Calculate FBoundingBox of SM + TArray StaticMeshComps; + Actor->GetComponents(StaticMeshComps); + GetBBsOfStaticMeshComponents(StaticMeshComps, Result, InTagQueried); + + // Calculate FBoundingBox of SK_M + TArray SkeletalMeshComps; + Actor->GetComponents(SkeletalMeshComps); + GetBBsOfSkeletalMeshComponents(SkeletalMeshComps, Result, InTagQueried); + } return Result; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/DebugShapeDrawer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/DebugShapeDrawer.cpp index 27aeed3e2b0..d2cd7e8016d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/DebugShapeDrawer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/DebugShapeDrawer.cpp @@ -182,7 +182,16 @@ struct FShapeVisitor uint8 DepthPriority = SDPG_World; + // Debug lines are way more dark in the package, that's why this + // multiplier is needed. +#if UE_BUILD_SHIPPING + static constexpr double BrightMultiplier = 1000.0; +#else + // @TODO: Use UKismetSystemLibrary::IsStandalone to support colors + // in Editor's standalone mode. static constexpr double BrightMultiplier = 1.0; +#endif + }; void FDebugShapeDrawer::Draw(const carla::rpc::DebugShape &Shape) From d45505b8cdb68ed2a558e90a8eb4c50ea99e6531 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 23 Sep 2020 18:16:35 +0200 Subject: [PATCH 175/179] First iteration --- Docs/img/tuto_suspension_blueprints.jpg | Bin 0 -> 69234 bytes Docs/img/tuto_suspension_parameterization.jpg | Bin 0 -> 31781 bytes Docs/index.md | 4 +- Docs/tuto_D_customize_vehicle_suspension.md | 224 ++++++++++++++++++ mkdocs.yml | 1 + 5 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 Docs/img/tuto_suspension_blueprints.jpg create mode 100644 Docs/img/tuto_suspension_parameterization.jpg create mode 100644 Docs/tuto_D_customize_vehicle_suspension.md diff --git a/Docs/img/tuto_suspension_blueprints.jpg b/Docs/img/tuto_suspension_blueprints.jpg new file mode 100644 index 0000000000000000000000000000000000000000..259769e89d77ac096c7b34bd9cf6b046511ef006 GIT binary patch literal 69234 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

    yw_V?V-9> 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

    2Vcr^Vy*MK!usZYDP>P#3p6=`f6;2v8Dw_ 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 ary^+y&jec*sv%~<|F`__N5Jvl%Krief@Pin literal 0 HcmV?d00001 diff --git a/Docs/img/tuto_suspension_parameterization.jpg b/Docs/img/tuto_suspension_parameterization.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a3da00d3c91c80c0dad9f2a166c7d6e2b780bed8 GIT binary patch literal 31781 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 aFd}089&G?_NtBMCmDK;dn*ho0_5T6us-kWH literal 0 HcmV?d00001 diff --git a/Docs/index.md b/Docs/index.md index 7cb5ee6015a..5afd923f01a 100644 --- a/Docs/index.md +++ b/Docs/index.md @@ -143,10 +143,12 @@ CARLA forum — Add new content to CARLA. [__Create a sensor__](tuto_D_create_sensor.md) — Develop a new sensor to be used in CARLA. + [__Customize vehicle suspension__](tuto_D_customize_vehicle_suspension.md) + — Modify the suspension system of a vehicle. [__Make a release__](tuto_D_make_release.md) — For developers who want to publish a release. [__Generate detailed colliders__](tuto_D_generate_colliders.md) - — Created detailed colliders for vehicles. + — Create detailed colliders for vehicles. [__Generate pedestrian navigation__](tuto_D_generate_pedestrian_navigation.md) — Obtain the information needed for walkers to move around.

    diff --git a/Docs/tuto_D_customize_vehicle_suspension.md b/Docs/tuto_D_customize_vehicle_suspension.md new file mode 100644 index 00000000000..c755ac76b0b --- /dev/null +++ b/Docs/tuto_D_customize_vehicle_suspension.md @@ -0,0 +1,224 @@ +# Customize vehicle suspension + +This tutorial covers the basics of the suspension system for CARLA vehicles, and how are these implemented for the different vehicles available. Use this information to access the suspension parameterization of a vehicle in Unreal Engine, and customize it at will. + +* [__Basics of the suspension system__](#basics-of-the-suspension-system) +* [__Suspension groups__](#suspension-groups) + + +--- +## Basics of the suspension system + +The suspension system of a vehicle is defined by the wheels of said vehicle. Each wheel has an independent blueprint with some parameterization, which includes the suspension system. + +These blueprints can be found in `Content/Carla/Blueprints/Vehicles/`. They are named such as: `BP__W`. + +* `F` or `B` is used for front or back wheels correspondingly. +* `R` or `L` is used for right or left wheels correspondingly. + +![tuto_suspension_blueprints](img/tuto_suspension_blueprints.jpg) +
    In this example, the blueprint of the front left wheel of the Audi A2 is named as BP_AudiA2_FLW.
    + +`shape_radius` for the wheel to rest over the road, neither hovering nor inside of it. + +Inside the blueprint, there is a section with some parameterization regarding the suspension of the wheel. Here are their definitions as described in Unreal Engine. + +* `Suspension Force Offset` — Vertical offset from where suspension forces are applied (along Z axis). +* `Suspension Max Raise` — How far the wheel can go above the resting position. +* `Suspension Max Drop` — How far the wheel can drop below the resting position. +* `Suspension Natural Frequency` — Oscillation frequency of the suspension. Standard cars have values between 5 and 10. +* `Suspension Damping Ratio` — The rate at which energy is dissipated from the spring. Standard cars have values between 0.8 and 1.2. Values < 1 are more sluggish, values > 1 are more twitchy. +* `Sweep Type` — Wether wheel suspension considers simple, complex or both. + +![tuto_suspension_parameterization](img/tuto_suspension_parameterization.jpg) +
    The Suspension panel inside a wheel blueprint.
    + +!!! Note + By default, all the wheels of a vehicle have the same parameterization in CARLA. The following explanations will be covered per vehicle, instead of per wheel. + +--- +## Suspension groups + +According to their system suspension, vehicles in CARLA can be classified in five groups. All the vehicles in a group have the same parameterization, as they are expected to have a similar behaviour on the road. The suspension of a vehicle can be modified at will, and is no subject to these five groups. However understanding these, and observing their behaviour in the simulation can be of great use to define a custom suspension. + +The five groups are: *Coupé*, *Off-road*, *Truck*, *Urban*, and *Van*. In closer observation, the parameterization of these groups follows a specific pattern. + +
    + + + + + + + + + +
    Stiff suspensionCoupéUrbanVanOff-roadTruckSoft suspension
    +
    + +The closer a vehicle is to a stiff suspension, its parameterization changes. + +* __Decrease__ of `Suspension Max Raise` and `Suspension Max Drop` — Stiff vehicles are meant to drive over plane roads with no bumps. For the sake of aerodynamics, the chassis is not supposed to move greatly, but remain constantly close to the ground. +* __Decrease__ of `Suspension Natural Frequency` — Stiff vehicles tend to be lighter, so the amount of bounces for the same joggle is expected to be lower. +* __Increase__ of `Suspension Damping Ratio` — The absortion of the bouncing by the dampers is greater for stiff vehicles. + +> TO BE DISCUSSED: Suspension natural frequency increases for stiff vehicles instead?? !! + +!!! Note + `Suspension Force Offset` and `Sweep Type` remain constant for every group. No offset is intended to be applied on forces, and the sweep tests for detecting collisions should be the same for all vehicles. + + +* __Coupé__ — Vehicles with the stiffest suspension. + + + + + + + + + +
    ParameterizationVehicles
    +Suspension Force Offset0.0
    +Suspension Max Raise7.5
    +Suspension Max Drop7.5
    +Suspension Natural Frequency10.0
    +Suspension Damping Ratio1.0
    +Sweep TypeSimpleAndComplex
    +
    +vehicle.seat.leon
    +vehicle.audi.a2
    +vehicle.audi.tt
    +vehicle.tesla.model3
    +vehicle.lincoln.mkz2017
    +vehicle.mercedes-benz.coupe
    +
    +
    + + +* __Off-road__ — Vehicles with a soft suspension. + + + + + + + + + +
    ParameterizationVehicles
    +Suspension Force Offset0.0
    +Suspension Max Raise15.0
    +Suspension Max Drop15.0
    +Suspension Natural Frequency7.0
    +Suspension Damping Ratio0.5
    +Sweep TypeSimpleAndComplex
    +
    +vehicle.audi.etron
    +vehicle.nissan.patrol
    +vehicle.tesla.cybertruck
    +vehicle.jeep.wrangler_rubicon
    +
    +
    + +* __Truck__ — Vehicles with the softest suspension. + + + + + + + + + +
    ParameterizationVehicles
    +Suspension Force Offset0.0
    +Suspension Max Raise17.0
    +Suspension Max Drop17.0
    +Suspension Natural Frequency6.0
    +Suspension Damping Ratio0.4
    +Sweep TypeSimpleAndComplex
    +
    +vehicle.carlamotors.carlacola
    +
    +
    + +* __Urban__ — Vehicles with a soft suspension. + + + + + + + + + +
    ParameterizationVehicles
    +Suspension Force Offset0.0
    +Suspension Max Raise8.0
    +Suspension Max Drop8.0
    +Suspension Natural Frequency9.0
    +Suspension Damping Ratio0.8
    +Sweep TypeSimpleAndComplex
    +
    +vehicle.nissan.micra
    +vehicle.mustang.mustang
    +vehicle.mini.cooperst
    +vehicle.citroen.c3
    +vehicle.chevrolet.impala
    +vehicle.toyota.prius
    +vehicle.dodge_charger.police
    +vehicle.bmw.grandtourer
    +
    +
    + +* __Van__ — Vehicles with a middle-ground suspension. + + + + + + + + + +
    ParameterizationVehicles
    +Suspension Force Offset0.0
    +Suspension Max Raise9.0
    +Suspension Max Drop9.0
    +Suspension Natural Frequency9.0
    +Suspension Damping Ratio0.9
    +Sweep TypeSimpleAndComplex
    +
    +vehicle.volkswagen.t2
    +
    +
    + + +--- + +Use the forum to post any doubts, issues or suggestions regarding this topic. + +

    + +Here are some advised readings after this one. + + diff --git a/mkdocs.yml b/mkdocs.yml index a86c2c397ea..ea5f1ca68db 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -62,6 +62,7 @@ nav: - Tutorials (developers): - 'Contribute with assets': 'tuto_D_contribute_assets.md' - 'Create a sensor': 'tuto_D_create_sensor.md' + - 'Customize vehicle suspension': 'tuto_D_customize_vehicle_suspension.md' - 'Generate detailed colliders': 'tuto_D_generate_colliders.md' - 'Make a release': 'tuto_D_make_release.md' - 'Generate pedestrian navigation': 'tuto_D_generate_pedestrian_navigation.md' From 2898cc4be45bca42a477f2a5ac7fe1a62c1fb15f Mon Sep 17 00:00:00 2001 From: sergi-e Date: Fri, 25 Sep 2020 12:38:43 +0200 Subject: [PATCH 176/179] New iteration with minor fixes --- Docs/tuto_D_customize_vehicle_suspension.md | 45 +++++++++++++-------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/Docs/tuto_D_customize_vehicle_suspension.md b/Docs/tuto_D_customize_vehicle_suspension.md index c755ac76b0b..d4e82ca3162 100644 --- a/Docs/tuto_D_customize_vehicle_suspension.md +++ b/Docs/tuto_D_customize_vehicle_suspension.md @@ -4,16 +4,20 @@ This tutorial covers the basics of the suspension system for CARLA vehicles, and * [__Basics of the suspension system__](#basics-of-the-suspension-system) * [__Suspension groups__](#suspension-groups) - + * [Coupe](#coupe) + * [Off-road](#off-road) + * [Truck](#truck) + * [Urban](#urban) + * [Van](#van) --- ## Basics of the suspension system The suspension system of a vehicle is defined by the wheels of said vehicle. Each wheel has an independent blueprint with some parameterization, which includes the suspension system. -These blueprints can be found in `Content/Carla/Blueprints/Vehicles/`. They are named such as: `BP__W`. +These blueprints can be found in `Content/Carla/Blueprints/Vehicles/`. They are named such as: `BP__W`. -* `F` or `B` is used for front or back wheels correspondingly. +* `F` or `R` is used for front or back wheels correspondingly. * `R` or `L` is used for right or left wheels correspondingly. ![tuto_suspension_blueprints](img/tuto_suspension_blueprints.jpg) @@ -41,12 +45,12 @@ Inside the blueprint, there is a section with some parameterization regarding th According to their system suspension, vehicles in CARLA can be classified in five groups. All the vehicles in a group have the same parameterization, as they are expected to have a similar behaviour on the road. The suspension of a vehicle can be modified at will, and is no subject to these five groups. However understanding these, and observing their behaviour in the simulation can be of great use to define a custom suspension. -The five groups are: *Coupé*, *Off-road*, *Truck*, *Urban*, and *Van*. In closer observation, the parameterization of these groups follows a specific pattern. +The five groups are: *coupe*, *Off-road*, *Truck*, *Urban*, and *Van*. In closer observation, the parameterization of these groups follows a specific pattern. - + @@ -56,19 +60,15 @@ The five groups are: *Coupé*, *Off-road*, *Truck*, *Urban*, and *Van*. In close
    Stiff suspensionCoupécoupe Urban Van Off-road

    -The closer a vehicle is to a stiff suspension, its parameterization changes. +When moving from a soft to a stiff suspension, there are some clear tendencies in their parameterization. * __Decrease__ of `Suspension Max Raise` and `Suspension Max Drop` — Stiff vehicles are meant to drive over plane roads with no bumps. For the sake of aerodynamics, the chassis is not supposed to move greatly, but remain constantly close to the ground. -* __Decrease__ of `Suspension Natural Frequency` — Stiff vehicles tend to be lighter, so the amount of bounces for the same joggle is expected to be lower. * __Increase__ of `Suspension Damping Ratio` — The absortion of the bouncing by the dampers is greater for stiff vehicles. -> TO BE DISCUSSED: Suspension natural frequency increases for stiff vehicles instead?? !! - -!!! Note - `Suspension Force Offset` and `Sweep Type` remain constant for every group. No offset is intended to be applied on forces, and the sweep tests for detecting collisions should be the same for all vehicles. +### Coupe +Vehicles with the stiffest suspension. -* __Coupé__ — Vehicles with the stiffest suspension. @@ -95,8 +95,10 @@ The closer a vehicle is to a stiff suspension, its parameterization changes.
    Parameterization

    +### Off-road + +Vehicles with a soft suspension. -* __Off-road__ — Vehicles with a soft suspension. @@ -121,7 +123,11 @@ The closer a vehicle is to a stiff suspension, its parameterization changes.
    Parameterization

    -* __Truck__ — Vehicles with the softest suspension. + +### Truck + +Vehicles with the softest suspension. + @@ -143,7 +149,11 @@ The closer a vehicle is to a stiff suspension, its parameterization changes.
    Parameterization

    -* __Urban__ — Vehicles with a soft suspension. + +### Urban + +Vehicles with a soft suspension. + @@ -172,7 +182,10 @@ The closer a vehicle is to a stiff suspension, its parameterization changes.
    Parameterization

    -* __Van__ — Vehicles with a middle-ground suspension. +### Van + +Vehicles with a middle-ground suspension. + From d0390bad2554350705b2497214b8692c6a596cdf Mon Sep 17 00:00:00 2001 From: sergi-e Date: Fri, 25 Sep 2020 13:03:17 +0200 Subject: [PATCH 177/179] Fixed parameters, rear, images --- Docs/img/tuto_suspension_blueprints.jpg | Bin 69234 -> 59006 bytes Docs/img/tuto_suspension_blueprints.png | Bin 0 -> 42428 bytes Docs/tuto_D_customize_vehicle_suspension.md | 38 ++++++++++---------- 3 files changed, 19 insertions(+), 19 deletions(-) create mode 100644 Docs/img/tuto_suspension_blueprints.png diff --git a/Docs/img/tuto_suspension_blueprints.jpg b/Docs/img/tuto_suspension_blueprints.jpg index 259769e89d77ac096c7b34bd9cf6b046511ef006..d59978d5f7fc7045096180ab9b51e39645397ed5 100644 GIT binary patch delta 50145 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 beb`9&{$JaR{}1nt{@Z+j|JN`4XZ3#o6Q+cw delta 60454 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 q5aPj%X#9T^?Eh2lf5%?^k7FzRoAY0-Dy0bk diff --git a/Docs/img/tuto_suspension_blueprints.png b/Docs/img/tuto_suspension_blueprints.png new file mode 100644 index 0000000000000000000000000000000000000000..f6cb6bc33e01a8188d017950644160b878348914 GIT binary patch literal 42428 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 literal 0 HcmV?d00001 diff --git a/Docs/tuto_D_customize_vehicle_suspension.md b/Docs/tuto_D_customize_vehicle_suspension.md index d4e82ca3162..deec87efc54 100644 --- a/Docs/tuto_D_customize_vehicle_suspension.md +++ b/Docs/tuto_D_customize_vehicle_suspension.md @@ -17,7 +17,7 @@ The suspension system of a vehicle is defined by the wheels of said vehicle. Eac These blueprints can be found in `Content/Carla/Blueprints/Vehicles/`. They are named such as: `BP__W`. -* `F` or `R` is used for front or back wheels correspondingly. +* `F` or `R` is used for front or rear wheels correspondingly. * `R` or `L` is used for right or left wheels correspondingly. ![tuto_suspension_blueprints](img/tuto_suspension_blueprints.jpg) @@ -30,8 +30,8 @@ Inside the blueprint, there is a section with some parameterization regarding th * `Suspension Force Offset` — Vertical offset from where suspension forces are applied (along Z axis). * `Suspension Max Raise` — How far the wheel can go above the resting position. * `Suspension Max Drop` — How far the wheel can drop below the resting position. -* `Suspension Natural Frequency` — Oscillation frequency of the suspension. Standard cars have values between 5 and 10. -* `Suspension Damping Ratio` — The rate at which energy is dissipated from the spring. Standard cars have values between 0.8 and 1.2. Values < 1 are more sluggish, values > 1 are more twitchy. +* `Suspension Natural Frequency` — Oscillation frequency of the suspension. Standard cars have values between `5` and `10`. +* `Suspension Damping Ratio` — The rate at which energy is dissipated from the spring. Standard cars have values between `0.8` and `1.2`. Values `<1` are more sluggish, values `>1` are more twitchy. * `Sweep Type` — Wether wheel suspension considers simple, complex or both. ![tuto_suspension_parameterization](img/tuto_suspension_parameterization.jpg) @@ -45,12 +45,12 @@ Inside the blueprint, there is a section with some parameterization regarding th According to their system suspension, vehicles in CARLA can be classified in five groups. All the vehicles in a group have the same parameterization, as they are expected to have a similar behaviour on the road. The suspension of a vehicle can be modified at will, and is no subject to these five groups. However understanding these, and observing their behaviour in the simulation can be of great use to define a custom suspension. -The five groups are: *coupe*, *Off-road*, *Truck*, *Urban*, and *Van*. In closer observation, the parameterization of these groups follows a specific pattern. +The five groups are: *Coupe*, *Off-road*, *Truck*, *Urban*, and *Van*. In closer observation, the parameterization of these groups follows a specific pattern.

    Parameterization
    - + @@ -60,7 +60,7 @@ The five groups are: *coupe*, *Off-road*, *Truck*, *Urban*, and *Van*. In closer
    Stiff suspensioncoupeCoupe Urban Van Off-road

    -When moving from a soft to a stiff suspension, there are some clear tendencies in their parameterization. +When moving from a soft to a stiff suspension, there are some clear tendencies in the parameterization. * __Decrease__ of `Suspension Max Raise` and `Suspension Max Drop` — Stiff vehicles are meant to drive over plane roads with no bumps. For the sake of aerodynamics, the chassis is not supposed to move greatly, but remain constantly close to the ground. * __Increase__ of `Suspension Damping Ratio` — The absortion of the bouncing by the dampers is greater for stiff vehicles. @@ -79,17 +79,16 @@ Vehicles with the stiffest suspension. Suspension Force Offset0.0
    Suspension Max Raise7.5
    Suspension Max Drop7.5
    -Suspension Natural Frequency10.0
    +Suspension Natural Frequency9.5
    Suspension Damping Ratio1.0
    Sweep TypeSimpleAndComplex
    -vehicle.seat.leon
    -vehicle.audi.a2
    vehicle.audi.tt
    -vehicle.tesla.model3
    vehicle.lincoln.mkz2017
    vehicle.mercedes-benz.coupe
    +vehicle.seat.leon
    +vehicle.tesla.model3
    @@ -115,9 +114,9 @@ Vehicles with a soft suspension. vehicle.audi.etron
    +vehicle.jeep.wrangler_rubicon
    vehicle.nissan.patrol
    vehicle.tesla.cybertruck
    -vehicle.jeep.wrangler_rubicon
    @@ -169,14 +168,15 @@ Vehicles with a soft suspension. Sweep TypeSimpleAndComplex
    -vehicle.nissan.micra
    -vehicle.mustang.mustang
    -vehicle.mini.cooperst
    -vehicle.citroen.c3
    +vehicle.audi.a2
    +vehicle.bmw.grandtourer
    vehicle.chevrolet.impala
    -vehicle.toyota.prius
    +vehicle.citroen.c3
    vehicle.dodge_charger.police
    -vehicle.bmw.grandtourer
    +vehicle.mini.cooperst
    +vehicle.mustang.mustang
    +vehicle.nissan.micra
    +vehicle.toyota.prius
    @@ -196,8 +196,8 @@ Vehicles with a middle-ground suspension. Suspension Force Offset0.0
    Suspension Max Raise9.0
    Suspension Max Drop9.0
    -Suspension Natural Frequency9.0
    -Suspension Damping Ratio0.9
    +Suspension Natural Frequency8.0
    +Suspension Damping Ratio0.8
    Sweep TypeSimpleAndComplex
    From 55a83f911a76852986fbb33a9d2560a4e2e0b284 Mon Sep 17 00:00:00 2001 From: bernat Date: Fri, 25 Sep 2020 14:52:05 +0200 Subject: [PATCH 178/179] New version 0.9.10 --- Docs/download.md | 10 +--------- README.md | 1 - Util/ContentVersions.txt | 2 +- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/Docs/download.md b/Docs/download.md index b410c90650c..e6f33e586b9 100644 --- a/Docs/download.md +++ b/Docs/download.md @@ -9,21 +9,13 @@ - [CARLA Nightly Build (Linux)](https://carla-releases.s3.eu-west-3.amazonaws.com/Linux/Dev/CARLA_Latest.tar.gz) - [CARLA Nightly Build (Windows)](https://carla-releases.s3.eu-west-3.amazonaws.com/Windows/Dev/CARLA_Latest.zip) -### Pre-Release 0.9.10 - -- `[Ubuntu 16.04]` [CARLA_0.9.10-Pre_Ubuntu16.tar.gz](https://carla-releases.s3.eu-west-3.amazonaws.com/Linux/CARLA_0.9.10-Pre_Ubuntu16.tar.gz) -- `[Ubuntu 16.04]` [AdditionalMaps_0.9.10-Pre_Ubuntu16.tar.gz](https://carla-releases.s3.eu-west-3.amazonaws.com/Linux/AdditionalMaps_0.9.10-Pre_Ubuntu16.tar.gz) -- `[Ubuntu 18.04]` [CARLA_0.9.10-Pre_Ubuntu18.tar.gz](https://carla-releases.s3.eu-west-3.amazonaws.com/Linux/CARLA_0.9.10-Pre_Ubuntu18.tar.gz) -- `[Ubuntu 18.04]` [AdditionalMaps_0.9.10-Pre_Ubuntu18.tar.gz](https://carla-releases.s3.eu-west-3.amazonaws.com/Linux/AdditionalMaps_0.9.10-Pre_Ubuntu18.tar.gz) -- `[Windows x64]` [CARLA_0.9.10-Pre_Win.zip](https://carla-releases.s3.eu-west-3.amazonaws.com/Windows/CARLA_0.9.10-Pre_Win.zip) -- `[Windows x64]` [AdditionalMaps_0.9.10-Pre_Win.zip](https://carla-releases.s3.eu-west-3.amazonaws.com/Windows/AdditionalMaps_0.9.10-Pre_Win.zip) - ### Development [[Documentation](https://carla.readthedocs.io/en/latest/)] > These are the version of CARLA, more frequently updated and with the latest > features. Keep in mind that the API and features in this channel can (and > probably will) change. +- [CARLA 0.9.10](https://github.com/carla-simulator/carla/releases/tag/0.9.10) - [CARLA 0.9.9](https://github.com/carla-simulator/carla/releases/tag/0.9.9) - [CARLA 0.9.8](https://github.com/carla-simulator/carla/releases/tag/0.9.8) - [CARLA 0.9.7](https://github.com/carla-simulator/carla/releases/tag/0.9.7) diff --git a/README.md b/README.md index 62feb1cda41..18447726e94 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,6 @@ If you want to benchmark your model in the same conditions as in our CoRL’17 paper, check out [Benchmarking](https://github.com/carla-simulator/driving-benchmarks). -* [**Give feedback for CARLA 0.9.10 pre-release**](https://github.com/carla-simulator/carla/blob/master/Docs/download.md#pre-release-0910) * [**Get CARLA overnight build**](http://carla-releases.s3.amazonaws.com/Linux/Dev/CARLA_Latest.tar.gz) ## CARLA Ecosystem diff --git a/Util/ContentVersions.txt b/Util/ContentVersions.txt index e34785f11d0..a3d4c873cb9 100644 --- a/Util/ContentVersions.txt +++ b/Util/ContentVersions.txt @@ -32,4 +32,4 @@ 0.9.7: 20191221_c88604b 0.9.8: 20200306_06b6cb1 0.9.9: 20200422_ea5179a -Latest: 20200924_ea7f083 +0.9.10: 20200925_88f9ceb From 159801fd40b8de11a583fd63fb9bb45c42faff62 Mon Sep 17 00:00:00 2001 From: bernat Date: Fri, 25 Sep 2020 21:15:47 +0200 Subject: [PATCH 179/179] Changelog --- CHANGELOG.md | 117 +++++++++++++++++++++++++++------------------------ 1 file changed, 61 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 740dd1c6aed..4dccd598915 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,71 +1,76 @@ ## CARLA 0.9.10 - * Deterministic mode for Traffic Manager, limited by computational power - * Support for OSM in Traffic Manager - * Fixed a map change error when Traffic Manager is in synchronous mode - * Fixes add entry issue for applying parameters more than once in Traffic Manager - * Fixes std::numeric_limits::epsilon error in Traffic Manager - * Upgraded carla Docker image to Ubuntu 18.04 - * Fixed memory leak on manual_control scripts (sensor listenning was not stoped before destroying) - * Added PythonAPI `carla.Osm2Odr.convert()` function and `calra.Osm2OdrSettings` class to support Open Street Maps to OpenDRIVE conversions + * Added retrieval of bounding boxes for all the elements of the level + * Added deterministic mode for Traffic Manager + * Added support in Traffic Manager for dead-end roads + * Upgraded CARLA Docker image to Ubuntu 18.04 * Upgraded to AD RSS v4.1.0 supporting unstructured scenes and pedestrians, and fixed spdlog to v1.7.0 - * Fixed a bug in `spawn_npc_sumo` script computing not allowed routes for a given vehicle class - * Fixed a bug where `get_traffic_light` would always return `None` * Changed frozen behavior for traffic lights. It now affects to all traffic lights at the same time - * Added API function `freeze_all_traffic_lights` and `reset_group` - * Fixed recorder determinism problems - * Added function to stop the replayer - * Added Light ids - * Added new semantic segmenation tags: `RailTrack`, `GuardRail`, `TrafficLight`, `Static`, `Dynamic`, `Water` and `Terrain` - * Fixed several untagged and mistagged objects - * Added vehicle light and street light data to recorder - * Change API: set_velocity to set_target_velocity for linear and angular velocities - * Added API function `add_angular_impulse()` to add angular impulse to any actor - * Fixed rain drop spawn issues when spawning camera sensors - * Exposed add_force and add_torque - * Fixed assets import pipeline - * Fixed Update.sh from failing when the root folder contains a space on it - * Fixed dynamic meshes not moving to initial position when replaying - * Fixed colors of lane markings when importing a map, they were reversed (white and yellow) - * Fixed missing include directive in file **WheelPhysicsControl.h** - * Fixed gravity measurement bug from IMU sensor - * Added Constant Velocity mode - * All sensors are now multi-stream, that means that the same sensor can be listened from different clients - * Fixed point cloud of LiDAR. Now the points are given correctly in the sensor's coordinate system - * Fixed light intensity and camera parameters to match - * Fixed and improved auto exposure camera (`histogram` exposure mode) - * RGB cameras `exposure_mode` is now set to `histogram` by default - * New Lidar sensor ('lidar.ray_cast_semantic') that returns the point cloud with information regarding to the object that have collided: incident angle, idx of collided actor and it semantic tag - * Added `opend3D.py`, a more friendly LiDAR visualizer - * Exposed matrix form of transformation to the client and Python API + * Added new pedestrian models + * API changes: + - Renamed `actor.set_velocity()` to `actor.set_target_velocity()` + - Renamed `actor.set_angular_velocity()` to `actor.set_target_velocity()` + - RGB cameras `exposure_mode` is now set to `histogram` by default + * API extensions: + - Added `carla.Osm2Odr.convert()` function and `carla.Osm2OdrSettings` class to support Open Street Maps to OpenDRIVE conversion + - Added `world.freeze_all_traffic_lights()` and `traffic_light.reset_group()` + - Added `client.stop_replayer()` to stop the replayer + - Added `world.get_vehicles_light_states()` to get all the car light states at once + - Added constant velocity mode (`actor.enable_constant_velocity()` / `actor.disable_constant_velocity()`) + - Added function `actor.add_angular_impulse()` to add angular impulse to any actor + - Added `actor.add_force()` and `actor.add_torque()` + - Added functions `transform.get_right_vector()` and `transform.get_up_vector()` + - Added command to set multiple car light states at once + - Added 4-matrix form of transformations + * Added new semantic segmentation tags: `RailTrack`, `GuardRail`, `TrafficLight`, `Static`, `Dynamic`, `Water` and `Terrain` + * Added fixed ids for street and building lights + * Added vehicle light and street light data to the recorder + * Improved the colliders and physics for all vehicles + * All sensors are now multi-stream, the same sensor can be listened from different clients + * New semantic LiDAR sensor (`lidar.ray_cast_semantic`) + * Added `open3D_lidar.py`, a more friendly LiDAR visualizer * Added make command to download contributions as plugins (`make plugins`) - * Added PythonAPI command to set multiple car light states at once - * Added PythonAPI `carla.world.get_vehicles_light_states` to get all the car light states at once - * OpenDRIVE ingestion bugfixes - * Added a warning if the user tries to use the SpringArm exactly in the 'z' axis of the attached actor - * Improved the LiDAR and Radar sensors with a parallel implentation of the raycasting + * Added a warning when using SpringArm exactly in the 'z' axis of the attached actor + * Improved performance of raycast-based sensors through parallelization * Added an approximation of the intensity of each point of the cloud in the LiDAR sensor * Added Dynamic Vision Sensor (DVS) camera based on ESIM simulation http://rpg.ifi.uzh.ch/esim.html * Improved LiDAR and radar to better match the shape of the vehicles * Added support for additional TraCI clients in Sumo co-simulation - * Added script example to syncronize the gathering of sensor data in client - * Added API functions `get_right_vector` and `get_up_vector` + * Added script example to synchronize the gathering of sensor data in client * Added default values and a warning message for lanes missing the width parameter in OpenDRIVE * Added parameter to enable/disable pedestrian navigation in standalone mode - * Improved mesh split in standalone mode - * Fixed delay in the tcp communication from server to client, improving performance in synchronous mode in linux systems - * Fixed large RAM usage when loading polinomial geometry from OpenDRIVE - * Fixed collision issues when debug draw(debug.draw_line) is called - * Fixed Gyroscope sensor to properly give angular velocity readings in local frame + * Improved mesh partition in standalone mode * Added Renderdoc plugin to the Unreal project - * Added configurable noise to Lidar sensor - * Replace deprectated `platform.dist()` with recommended `distro.linux_distribution()` - * Improved the performance on capture sensors. - * Fixed minor typo in the introduction section of documentation. - * Fixed a bug at the local planner when changing the route, causing it to maintain the first part of the previous one. This was only relevant when using very large buffer sizes. - * Added automatic calculation of vehicle's BB - * Retrieve BBs of all the elements of the level - + * Added configurable noise to LiDAR sensor + * Replace deprecated `platform.dist()` with recommended `distro.linux_distribution()` + * Improved the performance of capture sensors + * Fixed the center of mass for vehicles + * Fixed a number of OpenDRIVE parsing bugs + * Fixed vehicles' bounding boxes, now they are automatic + * Fixed a map change error when Traffic Manager is in synchronous mode + * Fixes add entry issue for applying parameters more than once in Traffic Manager + * Fixes std::numeric_limits::epsilon error in Traffic Manager + * Fixed memory leak on `manual_control.py` scripts (sensor listening was not stopped before destroying) + * Fixed a bug in `spawn_npc_sumo.py` script computing not allowed routes for a given vehicle class + * Fixed a bug where `get_traffic_light()` would always return `None` + * Fixed recorder determinism problems + * Fixed several untagged and mistagged objects + * Fixed rain drop spawn issues when spawning camera sensors + * Fixed semantic tags in the asset import pipeline + * Fixed `Update.sh` from failing when the root folder contains a space on it + * Fixed dynamic meshes not moving to the initial position when replaying + * Fixed colors of lane markings when importing a map, they were reversed (white and yellow) + * Fixed missing include directive in file `WheelPhysicsControl.h` + * Fixed gravity measurement bug from IMU sensor + * Fixed LiDAR’s point cloud reference frame + * Fixed light intensity and camera parameters to match + * Fixed and improved auto-exposure camera (`histogram` exposure mode) + * Fixed delay in the TCP communication from server to the client in synchronous mode for Linux + * Fixed large RAM usage when loading polynomial geometry from OpenDRIVE + * Fixed collision issues when `debug.draw_line()` is called + * Fixed gyroscope sensor to properly give angular velocity readings in the local frame + * Fixed minor typo in the introduction section of the documentation + * Fixed a bug at the local planner when changing the route, causing it to maintain the first part of the previous one. This was only relevant when using very large buffer sizes ## CARLA 0.9.9

    2nNXU##rvYqZTrHWA{29j({mbpId&_FU$A#dIQ zTmDu=Sp?IBC|sGGg`o*l>^=rPD&u*`{x0NEM9yIo4GjBB<{ZLxA`ok44HT+rhQ72BH$p79? zL-SY15jb$n&90!1CsY0LM(<9QxxOK&7$YPklvaFSt2oQdDMV{6v!=RXHxs$ClRm08C71HF_yeS=4Z#?cJw<;@ z6FT&3=ug|wvap+_a;GayY^3Rct(HS^;e4dQK6=`*v>3XBo!Z3U9AI7O{ANW^Oe4XM zF->NRzT$Ywk=264q5O}vBUVe7Vg8`Qj*mb=U!hF57GoEw9`oGgWgi}^xuNf<~S zwW{J0qbb5%9hEA)`yh-o)p+aO;QNDR3s%oJY~e5e8FN9j||%yk!pEc zY5l~%dDz^YeS8T1xi+ELL5PWGda#L`;B3@k0ITExq(#7WmB6N~d%*-DQhi2UUBQPne^HB*a1e+EJ8{c-nkdnjjtRJ{XC z&o$pCpsLPDi-(2XJlW2dv0SQI;@bBYKR2j0hf7;2J#WTWh^m^TKc5FSycps^!%c*S zXj`mVSH{WpIVTJ6`%f%8sGA)nkeJhmY=5Qh2Lk*-rx*cOl+?tf%n;#(q#+o5-jX#H z$0Kt6k(gT@AANFY!(nHew4FQ!5=WqUVKOZ6jKilq=}RqgSDW-oa-Ivj^p;HnG=@`# zVM{p*hnBH1H%F=r0168(r3g~nmU(t=J)Y#6TkNUi3AOYX+J=8>MHyhngYrN1vfug4cm)x(8fwoF>+ zkpLfh(`xEF*zN;EOq^EU&27-?b7GTN7}9n{CHZq|%4KIVM;s_p>BJaYK0oi(9UY~r zRp#RpN$krU-U8m@gT(MZoQ0?L`+Ski75e}W_vIfBv;Tm|9gim`!PwgJv#gE##cFuc z?knEu&>)~J7Qhc1r6EPG(0u1_&Ci7O2N+xOeac!k;`!kMLN^-=M8|TJg$ttDpP^bB zZ^*uPP?vS~6B?%6B!}_UEp3R);wty*jMRRRep;>x?(vwc{7#(Q+ZU>E;ri|_<*T=c zjqgx#ZQ_)<*2XF+dp@_-{Boie(j&gh8`Huget$xQJ&!>9>n$g0Vu#UWD_CbS1h+dQ zD~*C^SkV+`sG$;wKdP;+drMP0`uehmFZ`aisQ)+@@Tsj3sBA1{?@6y2r!agOMlyB!jlO87uAGZE3~Fw_@K z-EDJ8GJ_|kGhwiJca;dhf!PJw_y-ft1Bunz_#Oj{+2*3E!&XQRiX^}ya^m8k&Hd5=?90OuVP9n!Er9>0c7QmnH>znSHVr~BB zh?4SDWd12PvxgWVDhs%qsw90bq{pZZL!Sm|VJmzh>ma*a!QhOv z@CJmlDS)v}TNtG=FNDFmXbe4ubW^Z+HkBO$U8}f>e^)kHX@Hd^69>;iU{#H0#0}(f z8TDy7+GCmZVY>_b!!UByz}<^D62|j;YE{{YoT)s98!bN!wXd6`DQO_+exCw5x~-4M zlGp_{375@I3y!&~UnVZd*IBt7-Ms%z`ZilydUM1|jxB#~^hD{m+kCGj0nvJl6kno$ z9cYI8fh4K5+fNgM(+u}XZ;Hyby?*)Te%7+>W@;i9EsXNm-dDN;sg4YK74ql56LaIXK3SeS2LKyKs0HNI@M;&D4%v|Z*E9VLiNkd0N zGc~6be3&C9Ykn%WkQZhTN~33N0%oLudvEPc@$$IxJ<+0S6}E9TnhY6vOW^%Ll!raa zHsld}zKzSQU2^LCSJE!dfsPrYv`asBG~5eM9ON`$jO^t&hZ&ay#jPJlnI_DChbSwX zn56`r^pZApyrOTy?l`Bz?}Rkp@m0?8dR+m*kfoN0Ja1P~`C<#?6&f{z>(Wqp{CsPO z6%+aO@XLzPXwp}<9g)_vhs+UrWm2moG{wWq2vjsz1-mPn36S2SQ3~1ES2>r}k~9Ow zHP}d!A%rFDr?vyM?@tA>>FblG5x|KOATn_1B&l;CfS(O_%?I)Ca%2eXA)|ZXrXwE1&nlS0DLuoh8-=RI$%htELR~q940`NyA7m zFX=g9AA_2vzWcQF3j)DJwG%yFpM^4iK$uwd$NE3M;&(1Eu0F-K2IV?4G+>Y7R6;h( zHhscSkKrNfGSMTPhb-nVhClI72@x=HJ(EP#KCYCIiDR6Zp(9*`^Fh|kK#*fX!an+Z z9|%Ptf52;>cgK^vK^>=bq1}yVhv)EfTW_J#LQrE!A``M4?Zv z=~^uXf;S{QzhULe&`2hg%B)!vM+(X*lX7G(oZV$W41hDw<8Nw36PB!);_rer+XYeB zjHfCk-6m0H;f7%r-qlhVYRw2<)dv7T!gKv|H;&D`IC^*cwl!ezXq!vn5e z$5um!?&|Ljt}0$_ZXHN@(5*347=f3wUaycmXNA$L^Bvs>4@Qq`%h_z{emtDXoU?t$FHb9h){qzRX zkX(W|?xi`nUFs{mL0^I^nRgDcIWnp46pAxb;ZS5=6$Dn=Y$PWhXyAfW>76OcJ2DMi z7+;BidK|Ow%DDv?=@Egtj{+!F0T3#NzLW03T_iQ#wT6JD_cB-A6TXe&Ra!7QCF{Ww&MHF1t)?QfONv*x}z8Vo9f6Z+oAt$WZuHyZ+;T@=}u^@v_WJaX&?pu8s zg72u>&{c`2my|=k_ppprmfl&5$o|y&!m`^IO2$dS)s?6csr3~|)vXB01yql;=-sQ7 z75D&}FJ#y^kMZt>Y_Aa1g`Jk_7lEA%k&W_}3#ydt;u+G|S%`@uH0rwEC^%pP(Oi(BE zy9XV4*k`rV1T7YxVMI|NOp|XR=d%Z;8ZoI)tEQbIito#L%#><+`<&-R=X}qQoD~+L z9uWgKovntaXCz4*Zpj5(rPcB`BXXa9%1I4y_A$$=OeU^+opR!brs!3TzXMuqdN~HK zL82=boMtXjIY_h5d_sj+>;|Qa+BY|S&)Ra@KpxF9j%{pLV+2=Rw+8D6dMfmdiLp)+is44K{`(A z0~HlmWy|>_YTjlB-6^~jMwY9IyU(UxV%L%Ci8hSFTzcy8-7_$nawJ9xORkybF`hdVgj0S_6?(h zcu8%`=dONc;Y2I5>ASYv>?r}{DYc__v)cMVN|u%@oRfrkhINV`kbSwlwvk#`2upJgSUA(pg{;_&3Ntqp)MMVI4Ciwotzm7$t5 zldB}1cZ=g~so$S*<71l@pFgHV-t&2DpfVQdr0&8VMwP9{E_wl2wn$d`Mqv1h_H93k zcdFVsc5nC3LL{tQ_NGd0pc1VeFY07$aoa+rKY`t+&ET~dwbL6Rvdy4$0!;#K(Tjst(s!XKmX%XyTZ+K^EWkpD4P#o+v{oRg!UTq8d?}gc4%b}PaE!U=c zlx680mk|y|%-e_oqy=@v=J{9Cgs2xSHvT9dE`LMYa_DSzXR@~GI>1CPFvS~6}i9fuvPSpEWM8(@vDpfTrDN`<%S1KG46L)mn>_Q#l7sBnHP`ydv zgKx1L@g%*HOL_TOrJ+G!YiW{)bAp|!NgyLDtuHc`Hoaakf9gzhtIXWubs|^jF&gmWYwJ~Lq+WKPZea~ugcf;i z)>LFIEgv8K@Y_zd^K%S~EPyaeSu4E6|JWNjcrPwH0 z^|`qYE_&y+d6|Tmtc&Yo+m*r(p072`N0D!wnm3g3ctK!~1IUMnC8q8ZUr-!%Xu5EAx+(cdHvmP?~2G)_$Mdf|u!!d~73}?KCp|E^miJsMGhh^9fCB7{BsK-w-Fjcw5k_R;I6qVV$EdlrYrAJZ z<;yLbm~~01M;Sanx7_XXjyL_cQmg_-jRqgRQer(hOxj=p>>u-i3Lk*+8GH)YbX(g$ zS$l_+;n{T{Vf>q{|?_BoRkjaq`v8h0Ay=AI*>3dQ$7W5?bC8=U>`+zi)ne^9#Cz0>zL zO&Z5JI=a7={Y z9zV+ac_J_$_4Z2c#elLwrty`+7CmhVsQ`%TZFp*Z>V3aai=p`1er!~F%M`_mOCp2& zQ*^f??J1M9`^;2rT<2`NiFNs(ryd?EY?eA0<9ouPv1Z5_1Kjg;Vt0eN@#m_I_^7OK z^oXM>KRm}oSu2^g49$nFFKSZsbB)x_-*gfYy{CfOG^G+`tZg;%b;Y}Sln}^R`r-%z zAmw&U)?CveyW>Xj+_XlBu0HM*m-o!v9YbzGmNWuK>LKbG&G5d?Pen9sMKxZ+z6sy* z)aUZPSqdd9bSU^$&CbJ-Z8#_0o{o(Np5oVPwUhLG5hZV)WXyGQLEHufv2e295B3oz z3&KMKc_t8`GhpA&Q$1zF2CtNsioTmXhr<;`z*NWGM)+*!uBqOS4n#IO>wSw_^ei6% zycyg9gL~MYI*8DhWc=DVd70NSt1bk;l2#rwNc9Kz@>SAG!(cr(d$h{So*x#T*DvyY zNGcEdTv(i6mY#+oNXv{sYFy&WRsHn}qatKSCXASV)d2t#8p^sW`O-bWFx@}F`Yfha z1IcFqota}kuaHTxA`|anHzMX_cOpXK!P<5rPf{ts88EWFp}D~jk|`ba$DKY1CWJFp z5R&0p{o~Y2HVWI}DJ0S|3u63&U`~mBWo$xD;Tm1+q<1sV4&j6FRDjRc6GhN5S2qg1 z1R%y*VOADaB2G&InVZcdj}}hE?PDfqE#<3bc241uQ@br&awdYfRIQK%Z_Jm5 z%|+Qx`U3uW?sUQ00RtCQYTT;9QGr-t>wAY@0d|-I*i5At5KR;Klxs~{?s{}YZ-G`< z8gL{P_;Qx@w3>IO!$46geSW1w=wXF9lYbSP-OE9p;>spjU*;D%O{3ZmXR>gIgMr`e z+8?Yqr8P0~pBESS}HZ>#F@bp6Hi3qy-Ghm(7KBZn6kEQ zeUEIst_5JcLtY0hNKmeb6&6B%>=ZJW1{69;--TXEuri9c{h-J~0#eLi71d8}g_+-R z5!V!IIS`qbk{=vfNPp{c>zv1lsGqH9m7?#HF3Ed>i=Z@v!Zf@BEWgYFqDR6yTGcPa zD+q?apDIYu6-VV0Qu`U_ETE`0w7_u02q~@)S@gI)KO9YrPZIT)OR5-Qcm?LErABFt z5{O1X_4Z1)Qv+4`0EFJ8G8?tz?<~?=@4L%TxP=q$sH6*j9CthJ{pS)QzE8(M}|9Rh1GN*gf*cRj>oL})m|K^ycqlPM`SHTpJ z#6&63%_6m95U1x!dFJa5MZ_yF;qN(`xjb%#BKI6Yd1=z1ut2J=YLDg{vO(R9ufp@_ za2~fwM|=|V(vo-ET!_qDliH~R9I;gXS!<(j12e45b}>~e1QvG(NSkq;rv23v#G&yX&N_L`+~8z5jEr8@PdSm z3nc0DH=UBc)M&`&m52lEottB6@Wbq_-y!bxHw$znb-YZ@2KY)bOkX;Og$lpCz^>c&7Yjbh+qk_Ve%)#OpKV3wV{QF_7C3j z3;*P)K&?m;dXN~40r3%$@)bShRQ0Fnp$k*qZyQ-at{go>^y9(O!`kFHQqTV18SudJZS#{%5618i6;gE^In2$Tc~8Bx@L zp+D=XovCpXG?YxuJYjc5WR{~B+)nGt!q3>hT^3`?Io8PCKF75$o)gsW@9atqg!;qX znZqo!lARE`j}1`fJa!-WH91?sBYa*N;X}kG9T8)(Z|5_=!+szH65;7epk}1rCZn{=(o{rsp66_3Zgp!rYqxi-hme0L~et>>~ew-Gv$)8W?%BR6J=hx zeVQ32j~GYg%~I&lbL_I;!>%?nQK9pH9o@C%0RHawL%uYoWQwP4uI;$sbsk%mPJ=6t zP*oe&Vxl?z0muZvhWuDazJd5};(wLy{}$S~*VO8qaJT*+z?rWMkE=AwUA2FlyZI$h z;T^^6QpkO@^!5^?O*Q?DS5T6R#6i^E}q=zO~cprd*}R) zY2~5&L}dFRFqQYr?mn+7N%vvf-@0H?o}x{^-{<&{bJHQcqTZjU=|XDTTID%!=JC$2)Hm#8BA3*esUM8rNB$vG zcvmpxhX+&1A(O+5}@-X$XWrCEQu%V%6KZ?f3RT_72KVWQ)wlrqyWtI;|qSFhoumcN8*v%yrQNd^9QIZ{yjN*LY~a5y-X7pM}ri z*G%2H4taqSd&gx-6Ptehhqx#0CG-rh894vXh3q?WeY)!POwV|7IEKyrls{zH;Pp#JEduK3?me*kH_N_~fyl`Ow_ z8?5YX#;zn}kN~Go{|eV9gL2bDIqXQ-Qy7g-l}<4*y$e18+f6GIUdS2QV?-ySE^?=@ zj7`~g9RGm6{S~)mZ|PpW9@3wy*!w)X2C|dL6!(KCCXGOEg0T^vZ$$?3Z9~@OU$^%x zP?H*MU5hYb1gJ;G1<%Oz6z_BmIPfI*WuYJo|8~|WN%yDCI%bFxv*av2`3`(z8Y#ek ze@KevZ=!41Ak)hwkW0jY{=Ag?OOW74t{*%7!^)qFD|)*d9vn`+!-x0|vby25gda>R z^Lr4;`UD9p<-e?kByR4^m*sC$P(L6_9$tJs_vl4xHY)+p-ZRF0PxD^&#@ARv8WH1v zX_?Se+@;r3qNp_GYnl{Fymup7h;Iw;bohY(`+rG>p8I&?z+Zn0eyF}o&ZoW|bBpp} zYyFMyb?Ee8HN^jsOy}#Qz>wH}h7h@bujS?M+l2oamXS+IoY!6rPXwSxWn57Ng^>-z zm!X9w(2IB;4!Q^w>2?g@@x7PYmTc@OUCp)yxti2ozF))hBZ2v=45@Huae2}l9C!Zr zVUiEqEM}9rH#4gMd6fQ_F*7X@R7}hgB^btTV|St#?2|mQuu5M@cBDn`FGp0rvwwNr z;PRu*;Dbs1x%Zas(RKm~3D1OqHc>E8;bum=z|4`iFBLceLc z53m2+nk!s&hZErQ1(KCtOUsd@%hv$fPMiq%}72(biZ?_cV*$G)oe2Vb$_iReTFu~X2ETLd+&It zI&tbfo>_YFsQNF<^)EWYZ7j5k$9BN~!NC5qT;f)n&#zxT9xkLr(o<`){yPy4Q3F7J zYbK4&ot7Gu|I1i(AL1{@>(@E!2h5{0e?hIUu|y$5cr;-EyaI>SF6aT}-OVKXw4 z(^M-wsJ3v92h|Rb#_$_Z2Bg+s+O|?kEu;oq4=*LHMlSuGB>wk2{|;^t!^p{1YW3tm zu$L8HE;0y@+&vmt|EqvmDaA{hWR(BHNET?jt?!V(IEbay5|_2fZ*DG=k3H*Qk!|bm z_5X$B`aS=TDZ4mI#e*e5bdk3pm3YYR!4TtLqRyHIw{ee@C-R(|gJt3`ScpFkx&NwD zG$@V#B~-KyWX?{0L;jyr z(_csNtHbnmO?H&Q4qBrAP@x^=kzrpBqU2ElSAoO**9s{}0ca)MPrCwna#(|%XM~MT z&_``UQ~(5EC?12_FC;_J%aXk5(tQ4hREDR_f8xs{O0QEK%ZFzK(sobgu6P!xgk%K? z`?1n??T|knj%o1Ca0hnLKj~Z|K^c=h-T+FE{VR^VgtCu{clG*c5{2L>IEw?w_kBYe zMZy=#)-+^E8uYPQ|7*Q$Dw=6gX9;&{HOI%Xk^}UwYvcuJH-~N<$B>ONWBI72%4#gs zgw%~d)6zq640~Tt>X)h^TbVDsdIpVZ`&f#-$CF7P6iyuXF)S^rjl(R@pz3*ah>cR& zXEvwg{Bocq9aVC~ci;Q}0L-$`YjCZDck5_h-er+9R7?J#qqsK3twz)xT_b^xyI!Ag zQc4SDG-2V^ zO0G}+9ETmO?&R;{6&dsxrZlM8yEB`#=cx)mJvFM@TAk<4M*3ZAvak{UW_bW&wb#^I zZN}!d;B%wb2v77GV^ox{Po{}_S#@+{j0z0kYhKX15`5D6+gO4x))=vv2P4o}b@Q^3 z0+^VcgNTBUspj&#VqEHc^8?bj;I}jw*SV9{gTncEc!gz-0XLT~^Ri;UY8%m8nnw{#^c4w*-R%>7Sqv4sSa<;WDiri$I+UKv%bXa_tT4{ zG!q)G#ic@+4jrJx0)T3Iv#&+JRW+Xo(Jy{iBtjJ`lc{8{6%&J1ywj#(O3o1dF+K5H z$QsqW+WBWev9cE4kjokK^_w;c-#GNv1v^2Pg8AhpZ8l8@`i%bZwhe6> zUYyA8>&HV>c*EgVg5l>i#c9T^E@QyTz+w=s9}ik2?2#NGxlL!mLh07JmBNL?W(!)s=JsU@Jnwy85Ix#*DNmu6hC;M5CQmoOZ;8|Uk3d)j zUR2AltPM{?u3Ex zb|1`BA>eCI)Pn^tCsH0DL(G-Aiqg&>eYNP|(nghdoB+PK4OA$G=wKu;Q$b*`ee}{o zP(%c>#1kG5Dsz=6tO0r1%dHfQ(~G%%B6O8L+9W&HrQ$ys<4t{x26wo@Dvjg#nc zy1hriz$)3PfpVN-WW$Jv&W#mr>h(&5r6)#>-vu#K8WqjY3II`V!SxjcuE2O%d@2^M zrQ{Q)hsKhP=#vebN%eB!ptzx1(#!M@%G#PE7Ujh;6~I&bB9KS>2n(ysK?r#)VQoJ< z#Uehu#fLorCF4=QQpcxn;K5Fj_-&3PRBNM6difWJYuYDKbejfK+7}}j!CO>*azeul zlA%#0#vj58g&7+-^MEkry_~$Dva$^#PIHdmVI12LIAIm9B#h!6z_1mgpTGz;#?}&k zaLa3UCZN3@4XWgNP3mhy`+AFMrl1%9el=xR|L|K8cNq+C>J)JmQ@_~h*3+FE%#4s_ zSO>IijrU_$vfr_0s@k7{dBjN<=PTLDml8p1Ir;-%)X2yv zE@#)m@Pp=gijWDlF^+7jWuB|HPNDR*j2`)AxQnlx$)4;9dvbD}`kSN=O(jKP_>UO+ zCJF*&_OzI%HW=zOhV~vJc_YLaeTn8a7+4vB)JvmPiH8jJe+6AE_}@LG!dtWsAh)<~p~n)<^ON#Lt9O{sAahu_^0u3gURM4g!2wOL#9RIp%9` zT~zCwVbq%^wyyI>Ov_D$Ai1zn+uW!2gWT>?_rS-im#Ew>x(eGxk~wiOY|9 zB3ncsxqqLrSrvtfS-b!Z`2wX@5TtMw^CDCkVa98^NlNPX4uU3RI9}783yCCueG7#9HG5Zm+SbqnrKKVNYF{)CwK433VmH)P7ZMpl zO*?yA#BF_#g6kq4WL7?0fhWX)$^5_Z5dnog;Rx^2mKPHyyFFwI3eGAs01z;0jf?<< zVu~iV*{BduG--dLsiNGxC+XABIT)R4+3u>`!Ut^!(1o-Lz_x;^je*bgs3wM8ALn&v zo>}Vcwraep%Frob(aajmBkW|`Z^nJbsCjKxedw|o%UaqsD;W(*(D^VcZtF1gIOQ{f z?}!xVBUH;3e2SYPtG}yx!5J?lSHIa(laAI5A@$^0JrxW?U%m!P&O{`%MZrfz%!Rq`!`wn}L&V@PH6&UaL7)x&A6@2Zc@x*eh= znVIm4Q!VE&@1NCAjhVaAv8423V9#WY`4{5UNX5B~kvVTf`89m7mdZ(vSHXQa54(2u z$S0x>4L|jy@h_Z+!g-iMgod%aHf+7EU0co8=n39F)FLwC3k#_+ltgHk6XdL5aHcaYoRIjT5C_)`Ji~4n?K{KF5xIjoLD%)bT||4a!nDoR0aTd{{-r zQf>D|=18H*^8wAKDYHO&c8_6gKa~z5p*9rji?_V3dK;EHvg2{0vVBt}94epc(3qhS zUYH&^u>#1RVbJFXkzw4Oo5SGe(wk6{;oQYdb7~P5eD*tlB-TG?d$Ru}x7^rFeS|dB zNEazFL&ga?Jzd&gNg@M11x8&Ko-6AkGVcSw9gFB%FZ}IFQ1#VPVy6bL#D45t7-_&sd`$Xk~`GDJ4ep61he9G_@_b&(j>q-j| z0CzvUOn}-vOvG;?;AHEzbmzf40vnIclwp^G)|DqTitqf=(&(Gdh%>8Y^mcGODH|+6 zyC*bR0Ubzi|!J8BE^aa zQ9Db!u!Fv>=L@mG;9m>RySUDMYYnRm>#Um}?0OBoQu{8_saiK(OVK_Ug?*B!Rn^Q}?SA0p z{R;7<$*MyBL`+kB{ozRhEK#RFvJHza*`kum^lXm=aqyDbD#UL7TD05PNWN9p=@z30#wvAb;>gnzwHzpzqQPriNa07Iv*v_bbrj!LNjp-vPNTSfdsGX4?7+Sipko$u^Z z|2l2%{8(>5Gq1f{wTofU$@Bgut-t{ zdB~7jkYlW#$vi38Yb?IqZRMBO-i(Ue(9|I@znla~cWmA?Yrp z>OK7(`rG-?)IVkJm?$RYl~aW5@XD415}#ZiTvGJZwEf<}oo**YBx}RBmJy)c3YQe< ze*7v>#Hry5hS>6wPapfsrmg$4TI-%r@<3ZUV$vjTORuVh`_+2gFi!^G?n%Cqi|Sn# z9O*eRrh*s9$Sqp>d_*|#A*}PBjB)uN9U@;AN?eP)y4`b3nDKW?D?BVxm9I(rMtEKa z-bA4T<#{a(9wp`e0AL$_ak<`%k^hk#Gn&aRk-e!c`NUe-tuOz9lAL<36_lVsFU~*_ zv2Q*RH}zhgOEE%6_IUD1Rs7JNJ_nTR+VXXA{rebhldzykEtUYPX^A}MG3 zh|4YA^ILQIHk`VPUA^CJ!WaqX*ma5KMpGD%6AfZ+k^h;yRi{W*6DS>W-im8DG)s_D z>@?ARfih@TzjaY60)IkL#U}!{rG2vsqmDGx4_5rc$5)*%B)NB}S*hczn`UzB^{KHL zQusRtTZ1=Ge9w3cl%|F=8A|z2jMUthk^hRy{iq)SA1$~LUm?WQJ5}~*Uc`)^$RsfTxWeS>F*7s`ojh%2zyA-I|MmF<3N(8L?Nk zUd6|3NL>r7$Z2JUa*0VOH$(HxsFALhLC812#%C@O96F-DY#xh(OSTqKHFq1ftfc6b zcJ6bvgIXS~`Vy#k6O6b{N0fE=7xWBBbyviYoiGfZEid776|x>z8M=W8JHB548D`g%e7OZs0>zUfSFcoq z#1Wo~%}8whpShG<$@8RpYJuBoM3DO{(KYWnTIG62jhjuZpAQ)c8dXj23~Z;FJe}D` z1Hm(&tsKSb6R2nfe)bCf21=k_*%+r*#xV0)ZisifP*br=yXS?qwmhj}k z^qwl*Qm%}r{_#oa!xmK7BwMPDdD$dlWUX|q7-o? z?vy_R&wk4U$v)BNlgy)Xk%gFA0LECS&E1@SKq`48?GN7wDF5hZ~ zg{!eDYhEWMhnV9#FYC00ZKqhT(ZD;xb{pIH262g{Y3h1f zDa277%{qWKn}98X0mmr;dyW%neB)8+@K&crBi-5kWoOenN((L}7Y`2)>aq)yH3;XI z0VFscc5!BAuKOD^GQMkwcILfbWWI>bWdUsys(Yf;II)GMZQuHe9E%f%CDKejHiR`D z^Q{q_5)eOa3~k*Yoh+WOI^iqD2@7bcvgo?>DYD|rTkh#P^-0-0F+zk>KO3-NjrUtkgdoJx7%3a0VfKX_vXn3EreZ!$ zoGh#}m5e@#>WxgCWmR`IojBDSXQMPdB1~=GNMU93ZU;G3l5k(t5C?VLkq<}OoL@9m z*BH9_cU~8g-BY78DL2}G+;v+r*vJCm1=e7rA&mi%2~%*vg!C1B$n!!vTVTG=g%(Vp zboVpZ$29oqW?#FWKPYi30a-zToz#u^-a+%b74l@_9jqxjl_k3e4>=y0!ncOjbg274c9X~LFrc{r9j zJ>qk%OE1y33i(lJ&4;Lh3b@bB53^|)nzH2yaack`{UiMl^YdPR4@zE5Kl&JFF8Jz8 z`=f16d*&hwkEr4yg$n4F=#?H#d?U-AKZo^!mX}M{f$W0uYpL92Zo~-P`}$hBuYd&u zBdec#oB-%>nqFwmSW&E5wqAY5VE{R9>?f;hK0ztmaR)Sje6G>5z7DTckgYxIBpQDF8kolhsxT!$8UrRoB~R90t=v4#YzT zR3g5m!&!OtC^1LM_L--)gXe4HrS0YWy7^DawTe_D%H1Uhfk3B=r{&m2_R|(J;+w#v z`U_MGaWhwRYH3Dcwiu&>)S$Y@oBZXA+<|_o*23(#Iil?qek$F%^yz)wSUI*{b|s<* z+ED}AHRsC+%NL(5DySdx-?xS5p2E*zPLrLATAlc({SLg}gw5e7WN%V%q>j7 z%*G1n_orsFM?y>@?6icrm_gwX-jd&cJDQjOHtfnGa3$t-{o!&R#;z@Hfpy~9Mr8&y zjjW>n6QT792OZ?nqf{qz;uW+Q9fZ!H2%iX2w?fwD`nIn0nhBIr)5IQw+fz-om^SbK}M#YK!v)>KQH1vzVKZopR=O9@Z!Yy6Q! zqrDdtNaXy*D9}15lA{xryPVutav$qzk4u!il`LL+`j85sbnZx8HJkM*P?pJ>@{fPJ zrw30@?LPOakLD|PE0nXjE=C=1DNz)gIn-u&-67s#Tv?a%Se7{72izi{#7nf}VJy9U zJ*%*gS?}56<-fZ?{_gAnw8AYb4~m%Iu(p!)XyHIeRqzeZMvZ3%jJcaYHaNyH?WpQ_ z3~=_T7PrK6!;XQ-3;cX!McNLGU?IW~A4bMR<6OJBps z$rKy#5X2BQbyh@ZAcZR@?T6PF&(ypRkhNyspPqFJf1;UW<}3VI>Z?2R(<%w;I8KK+ zHW$0=gi&F;Dbc|3aCRb-s+zbEK`}?S%0b}UUV}GRoO8^ugvkkB=5=eE#f5D?kEN{+ zcdO9cV9=bG<^_2Pe{Sg-2J_364-nz9aYn<#EgwLBSRw;KB;tSVNDa4WTorOevjjKE zV}*;v)l_*N#ooM1Yyqi0BNV+Ph~VbhP!;$h%AWFpWc*Wsd6)Xf`($vx1atGKVp~Q$ zq7*G<6ibK2V4aMGx1*Zn1xyoNr|KlXlv(?roj(ckUNoKZK;Rj-tLOxD%`O#0Dqh?% zlX5#-eyx%n+#{L=|%m&9p&=e}7itm+tzF1*BmN`9@quzb(MasC2gkL7iT~uZ-ATXP} z>EP3a-ZmbAZDaL?jpYV(6Omrn6a3;vyr`Xo^rurL{kAUJ9M9@qK%LS&*;NKZZo`a3 zJE)}z$2|?uzCuJS8694`D^Q@cV2rgJ@`7|s!(%SU>u1Xb)ztXt-UoW2SME}0oX zTsBbPEV62l^+=GN|1LlZhU~5n5~PTGsO{JSoepPd%Qnjf`F|&#cPzS}I~CPG(Fjf2 zn5m%#?HkuhO@G=jAx`Wxj=2b+_(*72O0FcD?v{{$KN&@0NNfoK;Xy< zJ15r*H^B*{ao5X&nNDQ)^L3(KWkK+oJ+jvhS2TG#f=9`#cfHId5*}q+3>qC$-|2)1 z+AFg`!IN~4C=_nDQ_Q5qldjbr(Dr`W3gGJSo?RTi$klF-Ux%J&fZpk{|((Bn3+`E7-+++Y{1tXS~($MOY;lO!>I2c$mU&Z((RfH`)qan z^9r(7#P}9?9*nozSU8IWzItrWy6H?PWZxxqt|)vzD1hCECQmoz%!Y!U$-o+JngRYL z!_1{-#Zk;AWoT+&s!_8c79#$J4!(rN2!PX+ufZD+JN%FY4tR(Bo7cM#)B`U&ow~N= zfh7vffI+EGNJ`Hrn3R-_Du@)gNt*ogZ{YefK*4l+6h!^XG>TPe7F8148qN$5rf4`@ z<8rN{Z_h$4U%}y_dDH+F9890u^oN3d(UVu4#-a>XW-yHLD_NM|Cll-~?$O>}fPF^( zVV|{KlL^V}UPr@97~?Tl9nvdmtREKF^@nb__`B0iSae5s!MCkq!AiQxTXe<6fPEq0 z3*W|8Unyl(ijtq7|D+~&&BTj1nayKl+cXm05?I4@pI8f!#=LK};wG$9%7Ra`f&$=4wRk7@m3*0s+Jk)&2S~-|H%ao_NOh41^gJc{ zbw(e4YjyJ|IP}GEi3Wwk&kIG>s763kG-N=oOGU{0s5CR68Y5Pim3;H5j+X00!+;v+Br-h>)z2la_ z)*nEtzv?%~n=|#)*Q64LWn>X0(XU=3YBoVxVHlf)hZN<;ov zJMi-8!G}h}N>8nbMea!cba{x1<|!a7_J^tTB@z$Od@^;E*t9t0kAd^4PZ+MgDR%vvjwyF zu=5sP+iVce$D(Ze$VYjgeBr@sl}wa^{A?rq;B{Um8O}qG=rHcojW56hMELJ~z4+E5 zKID|6*oc2i2WQyHYiC*CPy@ILN_A9?)W0(MSkE(*ThL|3?c> zoHfBIJ?$H`@nanZ=`mFOt_|HclQNA?9fg9Sy#QyYWJ^zMUF`J;pQ_N7NR^VU!f!8C zcJP`P5i)FX(Gx1GaM+f{*ZymLZcE%i0DsDLwKmrl+pyy%6RN~?fuq_(T*-vIHfssx zPXpylO&^i#$y|(Du|`!MfWJSa5*IA-maVa%Ne|39EaGngva-l!l2m_&|P^Nh$W zGVGnbJ5KyoFjbf6n5WgI(bs#-re6Zl#%k?fydG-l;h4+@EX7b=6->wRSXrF^NnNg` z{luQrd7yjf?z2=_v38C-NLo+tHqF7aI9MOMIZ~gbfy3LLCB2O(9aG7l+Y-%5!{}7u z7rwk%&!0gP zDMP^nEinl$#WqKXv0;zXt?>L`xU|%r1&=7YRjm%c4{dwVg$mx_rcXq?w*)NMc!h2^ z;GNgki7Dl{huL5~d)gA}X*W+^8*x*g!{NyGwJ&^1I>}ni#BVc2?hnOclh;- z<@^+nTQE!%X?9_$VNT($wwdGiw@Ym2&j*cb%r30B?eb*0FNf}{htM~d7JUrQrl#?A zYNzp*!Zq(2>w^SbYW!K97WnNjF}D%!qR+gl6>6p9HV4r+ndRM@KQ?1XCNx5rr9X8`AuQ?Tor|XzGou}vd=voIE9Sv4Wftn zMzLmAo?qdhq)ZaN=u!x1Qg$ru1@UZV<`Jc^nfwqXX$2dAn5A`n$5CIQkfyHpTk`o| z_vf?ZCV?X~=KV^Ma@@sFGV9g8Tw6OF^6+pHAqIQIwQ?3|QiJa5IMToK3j0m;8g9KO z>(D7m7tC|P(Y~-5rGwcK((kLaCJJR4TAuoTMV}er$kY*3MgNFa05t_6ay5n z+fz#QYacGshmt;<;!VBOaCkeDnJ<(nlrde>&UPH#&c^Fir1&gp*Qg!HndB$()tmb! z&Gs<<9SI`Gzr6!b+u_fd$7zlG*%NM$vn5e>;BPP>2;@Nun{4bruE^d;YDggCG=!T> z>F+;)Z6@gAVIx1HU3vqp&60J6k?-`8sEvZx9v|mB@seajNTMviG+?U0NWn9zB~_v* zD(*C2qO*~UfyxFhOmypYp`GlVn;sOxQ$x1qg44!oozY=uVK{TDQ0~zAur_z=5u4UZ zj>W%nPz!Ls*hhSSd{>&b{kuTL-6@)!OAd|J&P`g1o|d2KrQJ(B{V zGG1A-tZn4vCD%JaqoeDt<3JUMs&>}Bwq_?VZ`!mH_zfEoKav1Ks;Efzop?OSR-wOZ zzIyb79bJ3y;)zPp@cD@rFlE?#;H5e1|H76p8C3ZXl-WAFH3+omKY(bH8U>zz02Krx z@y8sqih>EXXfCE@KW0zLbRiZ|LR&hZDbeN)PWerhUNkxpogbL4VkZ2p4B zi5$#jk@<|!#!a|bci&&8@rk=>l1YqSr>FahN`-fyNw$feteFJC*YSZ?FR>Z;=QqP8 zB;(ODxjYB0KGr_Kj?^VEm7U_-B|C@kA(P-a{-(yA=m!2I zwg1rfkbePR1~t;?MoupC|3ajMuSDP_wI2#t{{EdRzTW*m-Q9%pcx~}Fh_nZ_FVfOP zoe4<(kV&P;dN{bhhk#rE7aC2g$sp9H4-$IN4_+D&m{R-$atcl%v6uju-KeS(``Pf0 z$OgrB@-yKnM+#C)*Y_LNJkR|8FsF=OQy_-)DT*k{I~g!T-p*KHE&T_Oa+j{)1j;Y} zMElFQL${O;-_;AbuL%x83VW^T8>>puMeo>bpN}B*x!*PzoWm99=OK$|eRAZG^8c?z zJ#(f_zpz#`4{h+UV-Wu@ZA)PC%k|4ve}#WJkbF`W_U}*g8<`_?_g~1CCOT!99bNq5 zMbX5 zjDkF3YEXY^wax2nboG&PQF5Yb-#zV zCzyARX`~WLU&DP|c$0%PG=&(#mYmSD!#MY6d#LE3& z6G)?frg1&{Z+u~sQc!{G?#!Q;%7k0?H&g8m3$yBxbf>LU-P9AoQZrjcz78VBsiyw z&(G&hqwb##df~IkWBn`bZAIrVl9H`*Em@sCSw@fD z`eo7GG=v(#3ovS^qGGT##6v;-pIZy^2yZ`3lJsu{{old|8xr=&cC{0?ijR-;H$U<2 zs5rsEf0Qm~PFl+uim#~;nxoSq$!PuoOrpUiNyth+QqHg!Yc+HUZPTGqL_fYCeru(S zCRjw0b*frGf}JMtl5Z%VmyB!45d=*^x!}UV*&mhh{Wo_6EPjWiimm&!{yX=dhd1#@0>pu?> z&T)DE>MRhJ#YZRq7W`lEsNCi8B4tGW-yW3YRF;JQcmv2e>cZ1h+RlGF{jZ~9ZAhQy zB=mn!{r`TZ@HO(w$^RhVV}xZZ`G0Ps2ju?|QT!wz-{|Yq7d$F~K%V^G%l02C6eLOi zF;}qu0GrVcZ7#m}2S9JWESb*`hBPEB#{l5nX{F!^!lmMQ8J+$|kn;RR{@%ZGg`{=@ z82`VEJGG0*{>cD7iR3_81$oKV{Vx`-PPCISsP?bpVaQ(X@cQPmm+)$fkR4KSI2p{W zYm@x>JlIKvB$14S5J7rx5}~vBTw>k3y=P{;(ky1OTMogmHra&Y3k}-diaV+?wl<)N}LvG`<$;YvEmF zixa_9$dnPK9mMloch{zA&G3Ghb2xa;r9HKD3~ObYS%pKZWb$x#P3sm109nWcxLu$I z@fdLK$hW|&s>e33YH3Y1npiWzII9+aS!y^Ylj)EMh8L`iDun`pUbly5ynfbLxXw&o zXLXDCwsf8e_R#(V$SXW5d}dew1kF19Mhe=7;sG9vEVHnE+Kp{*dDG-!4%8LiZ$NyaMYz6>h5!jqz0!0Oi^;mmK;ejSF79l7jfdQ`>=O8>zXfZl z+5yyv0Zv%kaqKOovI|RYjZsxHV&b>6L|-|a%^lOLZmqw4w_4ZQW3fm$U-;W2i3X;W znWitgS(9ottszFYq4LXSnHD4gz98@u1m8=0e z0WwcfJ#8Khd$qjs)nd^6$oVSz4zhFE#eFI@pE`R1ceuO>ahg7Hf9hn0yAlrv|KQ9A z&7AcI82Q5jD|jU8`b|47OolIufvL?T>(dHkPu&m&fSQxp&LFJ9i-@ccl|pJXG`nxT zRLxlBO=tBKf8G5|HJqKzHmzm~%uOOLslQ_yN%W?@p}k=d5q1LpW z`8ggvy^~oiP=+xETQ>?{Rg&CnjmdvA;FBDKVv1-A)DMoi({aCRf9vr>;d)tag5+<* zqFR1)@*SO2G=8MM#5;vs2V}$kBp&-K z9ig{PY@ca2mt*aiOdlGEQREwY=zd!=Ftn$5i2*R}1q&&zsWXq4AnJ$)MDJ^4cF8>^@+`FaPFeV@*RQ~>~kk{wiAfyrhl10E{0Y?SVOWZ<#TKnFkNdrak zlDWy&qqd^V458|T8WFlERMe})qu9$1RZ6??IUuP$*2TtTHE$w$TH1p=mA~ov?j87w zjob3~O~2orBk$C*YbDE?J7ZiqPFUZPaYO)7L9B!^`OzvbA)R5O*`A)?P+#qzaExP2 zH!9Vu0O2D5`}yOP`%2(jnXv&3Dqt+K+fOS%8%*@wc5#tTnshmn^{z(3zPLcYICjJ> zjLaWQJi@Ie0K7d`r8stGAo=O$gK(g68J{?$v4!y)mdP}tWx=GD7}{%u&*ZAyiF$L! zH*pHLF-xP6SL;XY9hDGD8P2Kd(Davs{1d}g)7`p3{^ zWA%4h$_BrmmvzCb2Om@4S=)5E*DZ<8?3&#Oe!B-kTc!sronxy=sDzC#U^n1B2o1G5 zP1ijX4vfL1){8l*zd19_R(~PZK4(VS+$bxu@By=^k=h<-4MH9EI4Sn!hcuTOKak^! zEt%eRP;*M9+J2VDddl%x+YtTo(It2`3PPcLBC|TmDHMV7g#b1wIJQ0VC1Nyr<=G7%B*c17By_n(%>8SZp6@6+?D_-(#;U$=nyTj~4# z4+!D(GFS16?u9DCX#(w?+OPfTgI)oT$)X9Xz_7!dHhRk=btxQ?nkib+%0@^eNi3Ug z5bO~`AS)X>{ZRMYS8Dm_xKi6G4h=+c$%|}yJch~Dnt;)e4HrS2ttZ5A6@vYj3`r6ckust_jt`{js705h{z_8~odtygcSDd@QFVrTa5MN%z)P3C zZb*peXkD=>QdXZIm_d3_@?z1=*hjOOOiU6)Kzq`!f}Y7y6ajQn0x&@P*a!?lTg-sQ zG33{73V=rUdhnz-$N^E0J(3-sh6Imy9f;|q6kjx!LU5OR6OuK?@-=PCw#ADEY1IFM zBU*reP&MRBCQblw->crcBdr}D*Xb>qrG?>_XvIEqx8T5+SL<3$H{N#_Pl0swdzVqG zYbh-9XW`*yeSKCxzF)nbh&pKSBOfw7?V4}xu`Uu>$r(uf^zDz8{c}yTJ3AlR@W%}+ zh%2Y!NKMuoQ{Z`Ye%LCEpNhW{piQ(^Bdl*QIS}hfe1+LL9UF@P%0g97iP#rC0f3C| z7ak8@AGyx6nwBA{%%}`!K5Fg*0P@C(gw2ifWd8^sl}8jQBKWzpr(DV(OO4RWaKqRK zdI5rONYS{|+$(k1+lJmAlE#q@il=^d&KluwLd%gWEtrd0#gdQRN`VTTusl#G%T2yMvEEJYtG-yQ6r!M5sSk zflL=Zy)h-5PA@ivSlRV;}(F>rWOm?87s@U;+g@v&4%#)b( z;nS#ZUcLVA@nkuaXhvupsSATIA*gh$BJSoe`4WvTRz@LXb{gc?qV*Lz;qP7agY&k~ zu^`R5XP@kY{`v+EJ4|5CpdW=zObR$-sFXDS0Z??Nbc`ze16aL-xDMpe@RHQsev=y` zgV}A?F(GG&JKr(N%s{Cbu@GWynCOBJ0Ko*M+=-;yr3|8?;NrskkMG-dUfNw!xcXkS zg~DH6@i(kwulab%oempBz)>x-wK#WL*$8zg)vr)YEd!o=tPiFeYy%Eje<4L7$+=dtev7lGS(Kj+ZP{xEP4dT zn>V}S#Ih#k=l$2DK}!X$YI=NyM!CehQ}{<&5y^qrdsSPK;E&lFICDesT=9u#LBa{qAamDm=JRZ=jnngIXQA3bL%}M>a=3UAy1%z+{yMx=?gFcr z$RUoa9c5W1IW63N793A4c)hCjala5&oHYfVl~3<8tm=LiH2$W*Y7=Cr2Fpq3b`7Z@ zA|;b;2)}tYZMD?-QMJplk>2EE!?*8L3r;gfD~0`$*0B~Pu;dBn&tAC$at-c3>=GMx zU)ekrdDF+lh2Clwi@p3C>T-tom;nJk@s|INy#kX2}kH9d2XS4>Yv_@_f3!?`r#O}K!b<1*xa0^{=u2E^eJ|iMz|Ih z${fe9YYP?DN7p@N_)s#QKGzRzkR`v}D7#O2ffgIL54{3)`_sMVi)UHX8=4tuiD;{u z{!*FpSjI3^m~(n7DZW2oFE8-_eBYSM zI3i#ra!#m*Qn%5)dDL8_(M9$eQPT3QS$UcXJ@Zj9MyzFv9{aKY=5)FoUEKQ6Y*2?B zXWxyzDl%-`0cU-2Rk{#^o#lK}`unOaFik4AsXWgvbi6vq*kDO{;Zw1ixNXibQv+lx z1cXi3cyo(7;eK^MrsF(X8Xr)J(%wJ!sI%>^R;+4sl5hE?DAjWyk7zma6!YqA9oVqq z)b-dMv5FXmM-0E_r>JO(B=ues1d}EmRT6zdzkl?J!W;tJq^SAiT`(M;u%b9q=NI-- zOy9X<fzDhwu!d>VVF#w1*=8CZQomC2p{bLiXttm9!s`}o}Zs!rI8}70cjcFzWX(Qy6B7p11I?^|@{+I&J z2q@pbtCCg1@BZgl;jd=oei5(+x`#W1ub%qJJffmc;Ib$C$@6R~+ki`FKS_)~D2LN( z<97Q>LF$f&-^sASid7FB_Gcp*6Xk1I*Tc`x^C8Z_X>iQWY>D^LQB+wG@OUwhbc>77 zuFt-i1KO_1jX}Rz_o5Ou6eQfL%sY2K{sUNirKA#nK*`Ryfv-;g7JSIKaG7;3Q*MSPjBhr2oLNQu~)*5$40oNUhgNg0-~?$ zTaT@$itNh1dFVP{k0Q0es(pP#6uvJ=*Pp%20?T|A5EGI$FgGMbbM~P4!;E~y+)sPw z<57&C$HxsK!Xg+v!mrX>UcUA0dD=Dhc<);W+c2ll`z1dluyX9PyR}}-IY4?1Zn%*u ziHXHm07yD#GYUu71SD2pf2-?D^LgFV0^!s{yg63iciF8Qq zTCs`_v6KogU#K?$t%EC!X{o*RBp2@54}>f+cf_abVOoZinX+z7>p)agAUGVpWqLuO z-@?8-x!P)?OV`Z*kWQ<&9A%LN!E9=M5}ZAF{Xm9sH0=)4)^AL8Etz8Z*bL!M4xS3E z$gOv00{kVf+6OSkx_v1vNR@LQjR)AzHsQPr=FBCdV; zOdTvZD(L*7qP1deC9niPiJJgEdyu%mWNBS5;8x8MJ(jswuE9xZ;#J#j7n^8G!JM7Y_{%~`#cfN3u?%@wN_@+xK&PFxhD%tlH^j+O8^2$J{F zHIQA2_A$QsawmPi8iu|vQIDcJ$st3WR{+q_vAoW|pLxgOL++HEg-y~@8?(T?GFxEP zGM&H~Q6*U7CKN32hVfl?l^g#vCMd!lgGonM(dt|ohg{%P-EXC^z7_G3nOAPC+0(DQ z_DirzL}%-XU*P&J5I{cRpAs8rl$~`wi6!@HcgugpWfy9ozyb-C^O0Ep6X^5YvdtxWO(%m>IQ6AAL)6ckbX zdqG#~0RC%k|5YbJvX6Z8rM2FTLbHK=sdW2$WIDjBTQLWdJ}RE6`6yWtaAR9yIx_s{ z9Uig7Zr9UyLBPUm&rf;hUF(Y%yKw=DO4b8!t|KIi2sufk!eT^RX;7 z1pb1%ZLM*otA8`HNFx1j_5&>Y0-9yKHK#cpUBNZ2DjEVA5eE(O`Loi$nf5Y#3^KNgYUg$z7MPNQw z8l{iK?8}-M5bEE9CLx0RPSU(lDC?dHtaabK@(YXf<;M*cuW~rQY}_Yh^x%v>@m35~ z4y1^P-^hw@{w+CX@-!zQlW%bpV$f8#fTy7a27sEkVk)aNMR@6+pH+D5e{hT#6dpvS!cgN_Anb(589i z3mbTv+jG&0^X2a7iuYQpL>f-8@G8}|VEk{P1SOS*=bnBepEdV<@lh$*c$?UV>NrAj zuHI|#sfQtfI)S12DU1f;xU2zpczNG-3K?w0sbR?K=UXvXTvUj#9msHKUHkj}43AhJ zz3z)>60cJfBL1TE%C>s;i>EiO8g{7u6Qk=isH&>umhR)wI^`C9=2*3?6;~5jZHQEf zkWN$uHw@UzViJdimt{TTRyEJzjvu1Y6RiuT*_Ub=@c*weR zt*4d!{_ZI}9p<52*x6n9Q!zufALFnwI8)pzY6&sO@|v!arFkVaR)DB+GWM+dBR^C5 zJH2ljdiP{xVkNFMbS^?>YO!|Op-c?f2C-E%vhODUPiY&l=?wv<@>}hbWym8al zl4EK@PSzbHi(fo=m|o6&EaCIgHdNcs4wX4|IQKT|MP(c~ZSlStsi{X@Eo) zPsVj+yI_eoY%$ipk2+bgWxZ&22$;_%+avFbbI#LpyuL;AQNH^j7RJ#0)@(km5Ml<@ zWT83o%?lESbz{V(aILYIyqRR~xHIdITyyZOpYd=FOxE)#=`62fY!qO6PBWS!z~(0=X{K zYQ$Z~LKiH4iGHag9wuet=4Wqm-&`c{YB_F`h5hs1CwFPpSm{|*W+nJC{VrXwUUL>n ziclt)8hZBpSnBy;f096@%?HD!pE2jH@tugO?|il{?E4H?vsBk`X~2+1w(o#SM%=c_q8GdzY`+zR}+=H$HD3=Dk1P63M5P_g*vt0E>8#X3{F!g|^9^e$?H$oiB8tLN1#GcSB`QxAt2hs=9!W zqR_>El;HKRFtbt3nVD|}-2`9)Z!vqMGbWNwWm?m?{t zWO%;WgH5ON&sk@V(t;FDs=PA}7WZ8W8T7_#RQMebvv?-Jt$@NGa|DgtT$iDAR3=54 zTWSx@`P>AZ2mZsmcZ|zAkqrEEuIDlGS6eFvGkq@O9z7QK3vEcVra25DBxD+% z+*4#Fm&Y?(b4JiwvpF~hyUI}QA-SZ>C^2A}B3rtoE9@z@zF`8#)K(@ZpKQOltBl{D zahnEVRzVeN1onfk!g?kJ^5XFwGYk$EbF-2Q&n2y>73kT8CG1h@Gs#N*MgIf9l09_l zDtMTt_>heGx8&Ad7B=U0X-QO{6?(!tRnF(Uum#+o?DC>&EZFdXJTMQ0v!{CW@WmCs$Tm2n!MrIljBtjlnXpnh zX5n{QdAcr4tC_@wG?f()JLU@3mS8BqG0^O$G8@_bP!CWO^HmV`tUeZS&Wk> zQcTxmA%F>ceQP>}gJ=(4;N}}$X~~zB|Ig^<90d2iN{+6YHklWJ<9yU(U z+Ua|Iv$D2vr^KIHdlwJ>RBu;TOMk0?o$gFCH)NHgOM$}7fIA5i0QY8lOV45lQ|{`K z6eSrY6|AU_uD1UV%HQpRu`9jU!ZJ#Dt+&>u?*`pzLIA8gOy_rOrG*(zxz+OdAvbfW*C~-q~xuO zCQ@Uu_84l%^5Fg*7U~BcWCH$QuF((pT6YKP;z#Tjx4wJm8UlF#0d(Y`sNT_Jx9MM? zY?kIHD3vpv~)Ab*V6UNSohC!O?*yrCwAZ~etSp7Jg+G=LTE^;cnhYC$XWmJ zp{=6F$bNuks#(ARd8wZxsc|M&HzBm$<}MG^;U<``jLhGwCbzOpXCs)XzP(q$E)=vg zPUG#Kod2$Z{$LV*(yLvkq|)a=21?n4b{E0Qm`Y1$;(cQ82G~2ZzO|Oa@6gya|J2U? z5-O(?tD524(|PCKml-{+SMbMUp(S-W5L@-F>K;8Ak2uyd74z5B#;4RS{8imlCLa=} z%HEXaLR{x5h4=2G>eTOi?UjPe6N&3Z&IH|`Hx3iawqCv|bQi7;##KL%W*Uktv6qow zw0XOvb(8uFQLn88p0>-NmXS^89@7F=#Tp4fmvI=&Ca$q=CYSTIC89P~_AF`3LYh;pX6a zY04p)XefZ*=`5a?>YiHdTgl%SiU&kM+5k-Q^NKfr$MoBWH9Bu{xF)z z$zO}~M4q9huv9f*1u4$9GmNV!b+~&1(Z){1o2C>+3D~UoT|v?9v`yc0vb}LHMImSm*jV{ox5`;m%*f zcYg`)Ph_sbgFN5Q22L|6;6P^xzturF zs5PtSVq#^}7=#~JcJacp^3TEi(xveCKv`x(97D;3m%Ukei~hP>gHOM-J=4R&NUiAT zHK1Ufg8jk6*3I|~lPhS*GNCliIJ+bZ>C>A+*2+13X!aJ^dCx63{MBNV%#HKs?n|U8-1q8^nMr z_pD<_=|Em}gTNAQN`0H~{D}y|QM&(A)s+V_{r~@oT1kcya!k<&mGjd_liBES_5HXy zKPhu0`Q#ePy*X2^IVwISOX@?P4s;ljIhv88P}DFs_qjQ?+12kg^*Mfj`NOvN`*l2@ zuh;WB?(qjTR$f+X%R7mwXk@r;&h}n4`-lg-+6+{= zg?6W%T=OzUEvR9I5pB$%7kY1YP3%Ujm6w{!NV#Nwz^3Wh7MGZF5sk=DQP%mDO0O3$ z?kJ_*O}Vtw$^Yqn<@?K*AX|2~LHycPTL!9Ke|bm!MfO6BE#ZKC*|NgtJ5vfr{Jhsh zKbn@w&>+5V+pYsqs+t+QSnl=!vHU-%YjB&)>`LSKRn5EY0mZj`UJ~AG)?kXnpeo=~ z@?gaLy6*MlRN14oiMdYZfQ{rvl!Bet!Z5G$1T5O_ll3~-gSDwt5wAd zd)Q#Ykmt00)SS_OdTUab!h@9kU#t5pu8+lrGwpoN>F-82j@=zSs|~pUFURlo(NWdT zOI+7)Fi|%W<{#i1yltKB9{X)8ncZvLQtN-=?YJ_a z9$~i!TQcn~;nXveo<|j+4`?=iT6`OfyV+&zP+Fu2 z&3`-^i@3cuMfXDTvHMwto6LI(ht93R53_RXG?ZoHW0JFEKz8)$(I@vOUf5>e`AiBQ zcZ0aunkjz@(R+h{$Ruv)0Q7v)%ccc$2b$CiRz6jJgK&P$YNFn#8tnjS`AF|ejyCF9 ziv4}3hx)_DFKWFi3@>)diif!M^o4mU9g~8L48=6UJ2Z9UokI38Ww$1SEF1pqce6{{;{w*#@q$`DQ1mq97q?f<|JojNsHugv zJSeQM3s-B&c5Jh8%d!s%kUh3ue}2vov0YD_Xw{0`oc(yah5eVqb)^;?cD2etvG)7y3Ef40yypV#8~{XuPaO52fHijqWj&KTyB3> zB&e%4UXHqE+4shpd|8mmtz<7RP!DY0N$MggxU7rWqbuXP(}GqBh`q84*X(PFY#?=a zcV|7gzeise;-H?QFF$O_fxse@raM2s?ES-hpHt35kKcDy7=KcR$iH1vJ`Y3sSV(K8 zZfirnS#&H_nc?qp`QmEe+I{CRTmG`%j%Ox$BYAm=p%D$R^Ut*dWOhbx-jxnp1EK%H z<}#XJSm1j7%bCr(OH<+_`{7JCvHghW?Qe-4j8WujpaaVbkR3=o0i9^ z_Ry?W%yO`OJ2PFLZ<9CKaila=r>p!b1f6>8QmuFK2~}@JabL7F<#P}EMlfM=O#Rjk znA}9kE?F1qwbE^AYaCizU7zae2Iuue+d{o^nu(?TU&Gu>FL8`^d8E7UQd+zJkpuC_ zWB;4QzZQR*d|7+$uj7tuos@!9=UOv_4ndI3J8u+^m+ z(JOyt+)6p*KY8EbgqjBRr-I+J9qe4ff0m89zk5*o8sUY-1<$j8?y@=gLie_M&_4B~ z!LuB%;cFfbgNo~3cWn?m9M)5FaMj;6rRG>kM6Kw=YDtII(i{%dS%-X-SBkD2Vc1wE z)u8Ok%I;7V{NG<1JN)79Yb^)a1u<-Xm=NN(&}i-rmT-|Dp$4lx2#w*XCpbG4FnhHf=f2-4zb4ZJk?}iyL0vO<7aY-Lodz zW)c#WZPim2n4yHt%x;*OrYmL0e<*NOV(sfFZNds9KZO`R^{nvjUkKdorLCcW7LwOi>Y|iou~=Z56j#!si*2v z5j=Q*$TOVygzRM3oQ}RCKG&c@_<^-SljE@z(L>OBaf4R2#bE4(qgsplU23LftJx!V5{OxV5Ysgco!N|JkYBW?4n-ve2<^;oqHRtIaJ51iG$o^yv? zWvv%jeGk*%>=x~s@i;>|A^vA_oo!#==I(wi?ZUXAG3>8vI9XTTRvZkRPQAl+3;CB}`cNUEramkaO}=K)H!fDD7BBS26*|n!c}G!UKVNi&+H{sW ze^`4(hrJ9@NA|8`j$LJq*{Ev@<7|1iN8ePRaP6vaaCB(hAT4t#3Qn@zoRq;%pv0Tp zNpo|%nAq46_`Pxke=RhWf1{CaB56E5w(r<~@Z-t(IH9qo!+r}ek?ZJMnlWr!1@^KNHNX=fCJcqS!lz zVc~w>QVoJ?ukh2<9v|$~pMQE>uA4r4OSmCtfN-qT`QGatFGB`z&NgeiP2SiWAuG$~u!Y61Vqhdmtk!0qMUGMe(;gj0h` z=#e^{8w;B!wLe?M6UenVnLYTekGp^(1HNra1LOX`E%$)!J#+U08b2!{SGP6&7FapG z%-}%lUMarA5z_hWT7Q3{#snRixQdv{HaFzRCRBC2rHhdBGWB;gQt%;buD zbS<1Le?qBTjJ0KQ9rqX^?YTM3Oz-d1wPy7YOyOcTklnLV2ik@(rC& zABI{EeeWj+cpB%{47~yPZ-IH&Sz4C8@pSY!62UzKQ z$DAMP>557-7VbkeS=6yAduW@Z7%N!cFkh%7FH{*mp`!PYQji{RAr%~abQT5JH6e(8 z(3>qIT}i>-*wsNLPfED+Q-mtaT_^7l@WzB?)}O1Bu+Df0e9quUuet;;V^oAG`2nGs z=3&7$X_Y{NTES>BlPlbVhC%`romm-NQa#{ox2=pttYJhSFq*^B?vS-gWaOzM}vx6ZjyCyWJ+PoKf=;BFm{dmZ_kdu6PC zdTwz_8|KyY@LtEGm5}=nI~Di_R1q8#@w6r~;8kGzzk6gZmQKBiaov$c(MA3yGJ@KsobENqSPA92g zlPX03!L+)002nL9lOj9@ugIbto{JEf=VodsN5e=C{1qE%qtvGzQc-+pk+jSWqf_@E)b&Va_98-7`H|e z-!n&|JYOkl#y~aKi*F_L;}gwyt<0d1n$wxkMd(#l>w>PvW!IT_Ko57aY;mZh`)q`P z^TGv`1B$)!$cF^uf1_a5{Kfnm98w{##G5j`IPbw-v7@b;+ z`jpIm>R4Gh3t0ajEycd_3-sN1fEsSF8@@N&Zi10~Mv-~#s5fl4Ldf~h{X6#~uSZkG zr)1G9l}Ke7Fr`!1#IB`K->RdF6BeEQm0av2#;t=8J4;w#6{X$Z+YlQ=YZA<|X93;^ zem`0QL$PIoJprH@DLH{zMw_@3QSkTdspSC)>H_No-Qru%B+~e?Y{a`Qu>asDB)FO; zwcrsuN|xN&mP6&Oz${4|ksv8hxi00!4%~(|cu_7YFwVY%W zIRrU?Qp%C&vS?NVsK^q*>A#Q_R4R2zR9_$QkGes7BhJY2>Pj@OL%$7RG+^*oDlH-Q z78<^?(D5-u6VN_@V5^5unMfdTtB@Z`zblYL!3XK8gMOJvVK@SyT2>Kg_Y5l=$IyAb zD+Ej=0OG9b;H-+ntj+w`6y(CnVnA-5O|Pah&E9-B?q&dX-WKRjQVz#5X~DjAFhaj zQTe>Oy{3Jzf=*@;s%?E^UkbFTK^(Ip4CHCMYLmj@7*uM^eAggSRO_`R8eVB3I+&h( z25*W%B@vr7f{@!;-ynaXgH`bU`^M*2tpiVO}ui7sy^W_H~E za!veuJp=8)sDF#UhlkTz#*5Kt62~XKS(~dW4C89)T|w4_RseU?V?rr*?uX$EXkJ6G z2Gy>sWNFTbxP;P#Lf_`wO~6T+oryW(8F3yZR@+hm)j7?G^tt&a^7H@>wNGx#E!z!WC2kr_m8q4*wRU|qtTiB%Y}mog}e55WgR z<-)!KpvUMmzmE0ku4~Xx6)p7TizQm~64PO(fddf{g~7@kOzQAANDKQFE45i%CaOE5 zZoeRcm&xmDPj|M836G|m*RGlE-?}U~j}k>|A7s742JapX@eGv+Wa z9&o47~+3wS*rilXceuf$}V&zQoU|*WPDt7cPhmW>KQx^jLg=dl$)>g5kvlj+G3$P`BziX(^ z(l^LHAFwHykpovgiWG48YQ{VSZ;gYKQds#zFymJy@bZ*` z9uXB!qNP9ecy;DX;0o$U`vBhWFFwYH2d_b%*-qFCFEZu-+%jo+pW`$bi4et}W4W>g zyrZ^IQxd_rfddI>}XJD=+r;`y`UWpT-Kee#Tpy9JD9S$3xNXSCr z%lXx=S2s0~pMUE522tk~p7L!q46&}B4DMeE`t>!JGa<7F{|$n!z(!u1{sws>#fPbP zu7$(N2}30xL_(LlR)%aghru+o=@Qn^F8Ytop=dt8&ggZsPx6t+4xp0e^p;998R|BD z-_}H;)7$$|Qo`Gml5LxC6-@MSd%zBnSIzziF5SNgUr+g+g5Z&(AN5Jl)G`$p9@yN4c=i zFlCOZXbb4MCqK_*T?numLj6V^rijfTHv z!o~7b=Nadlz5Lg9J2%P==^*l zg)$o2^R*$IE!G~L=OLU0isEa6&Kbs1^MXG7=W&2=JIQPjG&n!S;}bMaexVi%2(yg) zk-|{)Wh1j5b6Ruhqau1qXx!<)9|-&L;NY&$JPT^8*m9gLeq7W63lPNEa?cgnY| zHK98usvLC|YV7yxi=sE^dnmR5QC^WHQjZ?zSJNL9a(BVc_j{%{_}M-SgJuB5cwm}{zB0~tGD=SBKM{S?3aRm}H&>?#*k ziuQs(N>Tc)Gqji!NEw8Pa|EgDb+XMTKj61SMvIuuL7u)JAAX75AAloFjLu9Z&sXB( zaZE8mW&Lm9lxFhTO{sscPlHzK9GaApgMXAQeluIu%Nu+{XNLy{&DMmAslQeE zM2;d`7^wvgXsoDEKM7hv8_VP4gVm5yA{}1H^Q!*&sRfM}MB|7u?`A^+cXv!y(Z%*J zv3fG5B26(w++nQnT=+?H%BDbntdUM@p{Pa(+o&B0PmhAZGt0eh7Qduq(S`Ny!OMLM zReRT{G>GoPzec|5b1nvpiT9J$1^e+X&K(;OPjtiKd+auP+l=xfw9c$t;?G`F`#sBN zN=$t#?m0{<|*e+{#D?;CvsNFKI_ zD2;a&nJ-5Md)>6f>xPd9Gl(0P$d89DXAbgp=HbuNU&rGQ;m{MTKjlV(v+=mWd1V#~ zO<2YrArSlqO?CFzyiBQLX~9EK&Wh1H_P?G_YVH z>#2X@Pa$1N{T|}yLJYZ`x>e0PuwrstKqPohzuz~5mJx#}TUo)bz?1Bwz?7>kB2MY@715?Bkz2h!!98I>6s#$BP?QHz>q*i9F# zrQ6|q#Eq1}Mj|(dAL%MU@Nn=6c8K2)?5p!|mcDyab3SIqd3)!b*QuY<<(`@y?!g4U zC#RDz(!sv`VRLOC5py|-0tN<#UyC@pPD(u<*1i-|2mE6*xJ}um+!3R!sw>)cwr;b2 zS&R1(7R`gHUSo+TkI!L2HO2WAC!s0tOFcXlyl?|2`1{rIK=V7eB`*u_#SsMZ9wJpr z^LNJ$wy((PStSe6^3V!ClLaqhJv;)*Y=DjuUJWqnJ5cacK5`HF;4-~6jr6A7Y`;O);7`h)-$%Ou*~#B~5otV2gOWY3VecG#|av zsr)$>M?Oh>G#DEqS83tzQ6zn*jzInV2M5MN<6ouMm%~4TwZsR@Iz#YwKwp(H)CzwO z|CvCAKTk8&3pvbT(eo#`D;Z~eFGT%C59ElA29N<(xPu#fkJ|L>;crC)*zozLDNF2YY=A_Y?ZPyshasQLvGXaoCFRGMJHvpukSFi#J@uCfqkUM-wcURU75qp z_p|@dDJ9XzTP(8&fvP6nFFz}M%e3-U&2_>$i%XN8!I*1B{qp)-wjj#a`;s0N3)lsl zYGR{+uAPSb?$kBw1$I|J5ZA!S0GUq#4uvfJJ43}~=Oqd~ByxGJeEi9YmCGl7;*NJx z7vW?&Y0spq^P6aFl+-~T@_Z#z<+~!Plu94tE#)#$79)|f|d z_#5nnolq!gRYdmTo~q?=G;Z4_u4+4F5-1ju6-5|wbGnp7cW=GSDTa+UNQq<9L-;EfQc00QP0yX)b>ASGC~-+_;7;nn ztDI`_!tr@T&M1AibiEYxv5)rXA&7D&2D-!1^i#^Ys`3s^zVlN2qL!m{sEO^6bZl!Q zyxq*KtHNGAd2_WkL1g<_P+Eb2sySi%P64KuP1V@40Q&WMEziivm4#{VYamz_63Umw zL}F~A3iBWC3#<&rCyl8GCUkhu{pdQJQ1$h0pvIZs%*A)5w9dyyQeix=z_Qh)mf z*_gP6gFKno`gU6rf#SXdt5b&W(Swq=zRhEz?#a75S7%&quzbYqiI^=a%IU`*Fb>|> zzaq}~MLyZ^Q%i4h6x+cwA8YHy{;DZLB-wT z{>W%KypSy<~sMz_~z1iXQOf)I3cJtwR~?-ims+?{oQN5Nf$h8IEe!vSvQ} z`o3C*s2(^=&Zq7j|C7`+xG7MwyUOE@rvHB2>VpIO zqT;mlO#L^=d2^?ZOYd`px%fs&;xYg~lCU^b6js@`*ja!sNBPXoQxF>44nGO3-@iyX zQn^nzZ@m3e(1~Rq?Gxr`FA=$Z5Epxn2|?Lmd4#JxF%e}f+alE;1*dnvi;Asm`Xg`* zM#)lrg2%Y7W{r}~PLG80sS~_KO65Pv^zM0+158V_X=ScCPRK7{>T73Y>AwZC z(DTj5%crOQAFqt$=Ri?q!w#B;y9x`~ww&o{nncQXLSS{~uPt`%-9Ta64ADrj(II`$ zuwL;&|EN`feeLy~!D;xAyAP06{Z3`p$_HMA+#=r9j>jD2GHggxv`&H~-3XOVQLv># z3ux`lOHl$o#_af=SMY9uBp>~~Fb2{xn0Xe%gmQ5PpWn`03Hv@U-yt#(evW;O_LKc# zV&iDL_t8;NaAR1+m7hZp5Q)P|2FvM*&5=}Ia+by9?!|eD+^apkfH(e~ZR+3B7my$S zf+&V8HYdo$l{Ehl#+CIY6`;2w3eP(xtnhIi|BuyddoC@@Lko_RJO3Zkki6FSyzeI# zqrfy@vg^EqVx7qvCnd`lmrZ4?y%=4aaps2N!jh=)Jk&C4BYTz0DoI{FJ{C)qe8DSi z0QP*2C$Ny;wLu-^>W7+5|Jc>aTOsr=FjydOyj7B>P0EHTZF*{v^v>&TZ{H%^z|cfB12p+bArmK6U_0CmsK^hTH7gqmAURNVN&Nec``GdLT z!%+qb?X>$lkrMb(!~8N1fk5bJ2qc+A5wh(5;h<_|npi;i8LWGtAeuK&2_;gpc2ib) zj{uX>&YQhZe22-0Ami@@QxG8V>-010rhAYD{1G&VrylnWq7e_6mw@gsrB2@99~Lo5 zQk#k1cxlXzG|v-66=9qSp zBjeoVWsRc=O@D+l0`Vj;xn2(12_w#Pk?$!$^miR{kps4ZVejpj7NgoI#m;gnwKt;; za#=S?vh7vf?h&spG55)OI_r3&$b^r*YZLEK8b_iDgsc+jw2Y|n8IW*Sa6opF%BhoV zgeN4l#Uq(dYz7%URn;~@WJ_WgL5GLUPkz~0xo-;9NeIr;1DsbOI4wMRo)2WwDIp(} zQ+J08P*!3+wX_2ykyh-{yU~&#@IGcE-8xJ7(h~G{p+ad(s5XY$@>!(9=H#SF5zKJ0 z+pc8SxOUmv#69MRrzAcW?zf@0cLr??!QGT9YKc38zTn@4Vn_}96f6@+@(I%KWfh+v z*(TUnwmclxbiV3wtG||m-=mQeFV~>dx1&>KbvM&K1PTz2$FKiyJYgpLt6h8Z0kR`O zF8gdiG?A<+|NB>iy;;t?jH`eC23d$%OH z8({aUC1U%CBvJp_mc9CSvcyqLy$zl=Y_iT2n@5K{yKMqp3`N7+v6ME*OeidW9`LAP z&+M~j!M6%X?CFfx(mi5u`A=q6qJst1FJ<+7>IZmj6gA^eP-rS;c0yb%U<5*D2UJB* ztv@?9s}D$JPXd+uN?qyBKjpCg_Ex-?GMpuKT!&eRVqBJ-i<}%7zDIUmWd{xbk>vqv z+s(6jtqaY^u4vS_55?3A&u@^fM3cWz`cEa=gGEc{70WD`qfe4lAo8bP+}9MqU0V(% z-^mJ_uKEVK(htVEZu|*>K<#BFsYOE{3ekQlQkl>~T5$C^M;IGruN|h+z!>g|$wh+_;~-SFIsD-WG#_0~Wm12@DQH(==Tj`lm}|G+M2V~Jf280n!v^t(4z%wPOn`ZxoY*hyc|Fs z_DjpqY)@n;_}Vp!bwi6Yt>w@Iyx;AT7~ml#zmnmst#Gn0!;fJGA`8W7PPCVyKmY22mLDJ8Zgy!BbUQ*&JD$akduL zyhNY@s>;1_BmGqZP65p;|Euj_K9>*HZ-{YY|_zTQd?hoz(Ust71{D;J~PX{jk@Cv0rrtQoG_#u&R(6={E`U2-L6% zV_j|tvqn}2<#{QmKc?gXB+)VjhWZ7mc9T&U7d4aUk~5)%PYXIs>+=vM;&3SilLw4>?PH{qpF-gD*JRE zKC38&il=Q)R1%Hu?ziI|y4)!r*n$<MRF09qY9o;Z=Qz)s#mFe696 zP2%ROwKn~^Mrln^oPkyx!k*`KQFLLRB%{3l0AXB)a0r6ld;>;Kci3g&s>{!H5OhkZ zOb2V0v)NU<)Sx?cS6-5qr80@>YYFe{(u&8ko=}Ny9JOU@q<84usVeIuKH_Kf3#Q*7 zw^#=gn!XrTkACLWw*K1ETpoTZoFj^CXFRbpGH~RT<=U>$P#D-Na8ajBx&qt6&F61< z!!$t%Vh9-e{E*MP%OW_sCsxcdpx997=|ho^^n-PnN#C#IaL{_y-Xc9puwqZvz#paE z&$eFB<0AFb)wK#tZ>J>@u7VVZ4;!5C+8~ye4s0=&rBcvWfiY__-(m9;Mb)h^2i2L! z8qt2q&nA~OEKZB-&Pl9)`^{dRd{?e_-+v(r)?YLCrPP9~PI5)1`H122@U54-h^GXm*}xkp z{~*-tq+nH7<6&(@4qVP&7ycshpUlQ;svzU4YhN54^etsp4B4nhzs9r)3)&O!d$C)(0`2Bv!cDu_LhKydE z?TN!hzLT`u_4aZkJyma0Hdiia@*K9BTbTx6B#+BDdn!??U-LDlL|JC_rYsavRU;ux zEakV=aBbf@#E&_qlQRq~)OgJFY6ls04bURN+_vR1JfbfH zx6 Date: Wed, 9 Sep 2020 15:27:07 +0200 Subject: [PATCH 044/179] New iteration with no release dependent command --- Docs/build_faq.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Docs/build_faq.md b/Docs/build_faq.md index a99af7658f4..42cb757a0d7 100644 --- a/Docs/build_faq.md +++ b/Docs/build_faq.md @@ -136,23 +136,27 @@ python3 dynamic_weather.py If the error persists, the problem is probably related with your PythonPATH. These scripts automatically look for the `.egg` file associated with the build, so maybe there is any other `.egg` file in your PythonPATH interfering with the process. Show the content of the PythonPATH with the following command. ```sh -python -c "import sys; print('\n'.join(sys.path))" +echo $PYTHONPATH ``` -Look up in the output for other instances of `.egg` files in a route similar to `PythonAPI/carla/dist`, and get rid of these. They probably belong to other instances of CARLA installations. +Look up in the output for other instances of `.egg` files in a route similar to `PythonAPI/carla/dist`, and get rid of these. They probably belong to other instances of CARLA installations. For example, if you also installed CARLA via *apt-get*, you can remove it with the following command, and the PythonPATH will be cleaned too. +```sh +sudo apt-get purge carla-simulator +``` -Ultimately there is the option to add the `.egg` file of your build to the PythonPATH using the `~/.bashrc`. This is not the recommended way, as the path will need an update for every new release. +Ultimately there is the option to add the `.egg` file of your build to the PythonPATH using the `~/.bashrc`. This is not the recommended way. It would be better to have a clear PythonPATH,and simply add the path to the necessary `.egg` files in the scripts. First, open the `~/.bashrc`. ```sh gedit ~/.bashrc ``` -Edit the following line to match your CARLA and Python version. In other words, change `carla-0.9.10-py3.6-linux-x86_64.egg` for the name of your `.egg` file. + +Add the following lines to the `~/.bashrc`. These store the path to the build `.egg` file, so that Python can automatically find it. Save the file, and reset the terminal for changes to be effective. ``` -export PYTHONPATH=$PYTHONPATH:${CARLA_ROOT}/PythonAPI/carla/dist/carla-0.9.10-py3.6-linux-x86_64.egg:${CARLA_ROOT}/PythonAPI/carla/agents:${CARLA_ROOT}/PythonAPI/carla +export PYTHONPATH=$PYTHONPATH:"${CARLA_ROOT}/PythonAPI/carla/dist/$(ls ${CARLA_ROOT}/PythonAPI/carla/dist | grep py3.)" +export PYTHONPATH=$PYTHONPATH:${CARLA_ROOT}/PythonAPI/carla ``` -Add the line to the `~/.bashrc`, save the file, and reset the terminal for changes to be effective. -After cleaning the PythonPATH or adding the path to the new `.egg` file, all the example scripts should work properly. +After cleaning the PythonPATH or adding the path to the build `.egg` file, all the example scripts should work properly. From 7afdebedca00c2dcd05339b4bf658a9e060b4e93 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Wed, 9 Sep 2020 15:34:22 +0200 Subject: [PATCH 045/179] coma fixed --- Docs/build_faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/build_faq.md b/Docs/build_faq.md index 42cb757a0d7..2d4b435ec83 100644 --- a/Docs/build_faq.md +++ b/Docs/build_faq.md @@ -143,7 +143,7 @@ Look up in the output for other instances of `.egg` files in a route similar to sudo apt-get purge carla-simulator ``` -Ultimately there is the option to add the `.egg` file of your build to the PythonPATH using the `~/.bashrc`. This is not the recommended way. It would be better to have a clear PythonPATH,and simply add the path to the necessary `.egg` files in the scripts. +Ultimately there is the option to add the `.egg` file of your build to the PythonPATH using the `~/.bashrc`. This is not the recommended way. It would be better to have a clear PythonPATH and simply add the path to the necessary `.egg` files in the scripts. First, open the `~/.bashrc`. ```sh From f4fc32f9110246ba3957f7daaee68cdae4cf1316 Mon Sep 17 00:00:00 2001 From: sergi-e Date: Sun, 6 Sep 2020 13:43:19 +0200 Subject: [PATCH 046/179] Fixed index --- Docs/adv_ptv.md | 4 +- Docs/adv_recorder.md | 16 ++--- Docs/adv_rendering_options.md | 29 ++++---- Docs/adv_rss.md | 12 ++-- Docs/adv_sumo.md | 12 ++-- Docs/adv_synchrony_timestep.md | 18 ++--- Docs/build_docker.md | 8 +-- Docs/build_linux.md | 22 +++---- Docs/build_update.md | 16 ++--- Docs/build_windows.md | 26 ++++---- Docs/cont_code_of_conduct.md | 7 ++ Docs/cont_coding_standard.md | 4 ++ Docs/cont_contribution_guidelines.md | 9 ++- Docs/cont_doc_standard.md | 7 +- Docs/core_concepts.md | 8 +-- Docs/plugins_carlaviz.md | 12 ++-- Docs/ref_code_recipes.md | 17 ++++- Docs/ref_recorder_binary_file_format.md | 47 ++++++++----- Docs/ref_sensors.md | 24 +++---- Docs/tuto_A_create_standalone.md | 4 +- Docs/tuto_A_vehicle_modelling.md | 15 +++-- Docs/tuto_D_create_sensor.md | 39 ++++++----- Docs/tuto_D_generate_pedestrian_navigation.md | 38 ++++++++--- Docs/tuto_G_control_walker_skeletons.md | 14 ++-- Docs/tuto_G_retrieve_data.md | 66 +++++++++---------- 25 files changed, 282 insertions(+), 192 deletions(-) diff --git a/Docs/adv_ptv.md b/Docs/adv_ptv.md index 376e7737345..0fcdba9e26d 100644 --- a/Docs/adv_ptv.md +++ b/Docs/adv_ptv.md @@ -4,8 +4,8 @@ CARLA has developed a co-simulation feature with PTV-Vissim. This allows to dist * [__Requisites__](#requisites) * [__Run a co-simulation__](#run-the-co-simulation) - * [Create a new network](#create-a-new-network) - + * [Create a new network](#create-a-new-network) + --- ## Requisites diff --git a/Docs/adv_recorder.md b/Docs/adv_recorder.md index 235229cce7d..79d2c5c6363 100644 --- a/Docs/adv_recorder.md +++ b/Docs/adv_recorder.md @@ -2,14 +2,14 @@ This feature allows to record and reenact a previous simulation. All the events happened are registered in the [recorder file](ref_recorder_binary_file_format.md). There are some high-level queries to trace and study those events. -* [__Recording__](#recording) -* [__Simulation playback__](#simulation-playback) - * [Setting a time factor](#setting-a-time-factor) -* [__Recorded file__](#recorded-file) -* [__Queries__](#queries) - * [Collisions](#collisions) - * [Blocked actors](#blocked-actors) -* [__Sample Python scripts__](#sample-python-scripts) +* [__Recording__](#recording) +* [__Simulation playback__](#simulation-playback) + * [Setting a time factor](#setting-a-time-factor) +* [__Recorded file__](#recorded-file) +* [__Queries__](#queries) + * [Collisions](#collisions) + * [Blocked actors](#blocked-actors) +* [__Sample Python scripts__](#sample-python-scripts) --- ## Recording diff --git a/Docs/adv_rendering_options.md b/Docs/adv_rendering_options.md index 08f85320839..4272bc167a3 100644 --- a/Docs/adv_rendering_options.md +++ b/Docs/adv_rendering_options.md @@ -2,15 +2,15 @@ There are few details to take into account at the time of configuring a simulation. This page covers the more important ones. -* [__Graphics quality__](#graphics-quality) - * Vulkan vs OpenGL - * Quality levels -* [__No-rendering mode__](#no-rendering-mode) -* [__Off-screen mode__](#off-screen-mode) - * Off-screen Vs no-rendering -* [__Running off-screen using a preferred GPU__](#running-off-screen-using-a-preferred-gpu) - * Docker: recommended approach - * Deprecated: emulate the virtual display +* [__Graphics quality__](#graphics-quality) + * [Vulkan vs OpenGL](#vulkan-vs-opengl) + * [Quality levels](#quality-levels) +* [__No-rendering mode__](#no-rendering-mode) +* [__Off-screen mode__](#off-screen-mode) + * [Off-screen Vs no-rendering](#off-screen-vs-no-rendering) +* [__Running off-screen using a preferred GPU__](#running-off-screen-using-a-preferred-gpu) + * [Docker - recommended approach](#docker-recommended-approach) + * [Deprecated - emulate the virtual display](#deprecated-emulate-the-virtual-display) !!! Important @@ -117,16 +117,19 @@ DISPLAY= ./CarlaUE4.sh -opengl --- ## Running off-screen using a preferred GPU -### Docker: recommended approach +### Docker - recommended approach The best way to run a headless CARLA and select the GPU is to [__run CARLA in a Docker__](build_docker.md). This section contains an alternative tutorial, but this method is deprecated and performance is much worse. It is here only for those who Docker is not an option. + +### Deprecated - emulate the virtual display +