diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index fcf482fb780..47619171b92 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,13 +2,15 @@ Thanks for sending a pull request! Please make sure you click the link above to view the contribution guidelines, then fill out the blanks below. +Please, make sure if your contribution is for UE4 version of CARLA you merge against ue4-dev branch. +if it is for UE5 version of CARLA you merge agaisnt ue5-dev branch Checklist: - - [ ] Your branch is up-to-date with the `dev` branch and tested with latest changes + - [ ] Your branch is up-to-date with the `ue4-dev/ue5-dev` branch and tested with latest changes - [ ] Extended the README / documentation, if necessary - [ ] Code compiles correctly - - [ ] All tests passing with `make check` (only Linux) + - [ ] All tests passing with `make check` (only Linux and ue4-dev) - [ ] If relevant, update CHANGELOG.md with your changes --> diff --git a/.github/stale.yml b/.github/stale.yml index 80ef6cce0f7..6e82371427e 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,10 +1,11 @@ # Number of days of inactivity before an issue becomes stale daysUntilStale: 60 # Number of days of inactivity before a stale issue is closed -daysUntilClose: 7 +daysUntilClose: 700000 # Issues with these labels will never be considered stale exemptLabels: - backlog + - TeamTask # Label to use when marking an issue as stale staleLabel: stale # Comment to post when marking an issue as stale. Set to `false` to disable diff --git a/CHANGELOG.md b/CHANGELOG.md index d743c9c7efa..625865dc362 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ ## Latest Changes + * Fixed waypoint.next and .previous causing loops when two opposite-direction lanes follow each other in the map. + * Fixed a bug that caused navigation information not to be loaded when switching maps * Prevent from segfault on failing SignalReference identification when loading OpenDrive files * Added vehicle doors to the recorder * Added functions to get actor' components transform @@ -12,13 +14,16 @@ * Fixed bug in python agents when vehicle list was empty causing a check on all vehicles (BasicAgent.py) and detected pedestrians as vehicles if no pedestrains are present (BehaviourAgent.py) * Extended debug drawing functions to allow drawing primitives on HUD layer * Added possibility to change gravity variable in imui sensor for the accelerometer - * Fixed ROS2 native extension build error when ROS2 is installed in the system. - * ROS2Native: Force fast-dds dependencies download to avoid build crash when boost_asio and tinyxml2 are not installed in Linux. * Added API function `get_telemetry_data` to the vehicle actor. * PythonAPI `Sensor.is_listening` was defined twice (property and method), cleaned and clarified it as a method. * Added V2X sensors for cooperative awareness message and custom user-defined messages to support vehicle-to-vehicle communication * Added named tuples for BasicAgent.py's detection result to allow for type-hints and better semantics. - + * Cleaned up the client/server build and respective naming + * Added type-hint support for the PythonAPI + * Added type-hints to GlobalRoutePlanner and use carla.Vector3D code instead of pre 0.9.13 numpy code. + * If available, use ActorIDs instead of Unreal Engine IDs for instance segmentation + * Synchronized actor BoundingBox between server and client + * Add actor_id to bounding boxes ## CARLA 0.9.15 diff --git a/Docs/3rd_party_integrations.md b/Docs/3rd_party_integrations.md index 87e5133e849..3a4b1552510 100644 --- a/Docs/3rd_party_integrations.md +++ b/Docs/3rd_party_integrations.md @@ -10,7 +10,6 @@ CARLA has been developed to integrate with several 3rd party applications in ord - [__Chrono__](tuto_G_chrono.md) - [__ASAM OpenDRIVE__](adv_opendrive.md) - [__PTV Vissim__](adv_ptv.md) -- [__RSS__](adv_rss.md) - [__AWS and RLlib__](tuto_G_rllib_integration.md) --- @@ -63,10 +62,6 @@ Learn how to use CARLA alongside CarSIM [here](tuto_G_carsim_integration.md). [__ASAM OpenDRIVE__](https://www.asam.net/standards/detail/opendrive/) is an open format specification used to describe the logic of a road network intended to standardise the discription of road networks in digital format and allow different applications to exchange data on road networks. Please refer to the full documentation [__here__](adv_opendrive.md) -## RSS - Responsibility Sensitive Safety - -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. Refer to the full documentation [__here__](adv_rss.md) - ## AWS and RLlib integration The RLlib integration brings support between the Ray/RLlib library and CARLA, allowing the easy use of the CARLA environment for training and inference purposes. Ray is an open source framework that provides a simple, universal API for building distributed applications. Ray is packaged with RLlib, a scalable reinforcement learning library, and Tune, a scalable hyperparameter tuning library. Read more about operating CARLA on AWS and RLlib [__here__](tuto_G_rllib_integration.md). diff --git a/Docs/adv_benchmarking.md b/Docs/adv_benchmarking.md index 8027c829a8c..180b55e10fc 100644 --- a/Docs/adv_benchmarking.md +++ b/Docs/adv_benchmarking.md @@ -156,7 +156,7 @@ python3 performance_benchmark.py --show_scenarios >> * Show what scenarios will run when configurations are applied without actually executing them: ```shell -python3 performance_benchmark.py --sensors 2 5 --maps Town03 Town05 --weather 0 1 --show_scenarios` +python3 performance_benchmark.py --sensors 2 5 --maps Town03 Town05 --weather 0 1 --show_scenarios ``` >> * Execute the performance benchmark for those scenarios: diff --git a/Docs/adv_cpp_client.md b/Docs/adv_cpp_client.md index e1eb0b163ac..8a8f6025854 100644 --- a/Docs/adv_cpp_client.md +++ b/Docs/adv_cpp_client.md @@ -138,5 +138,3 @@ TOOLCHAIN=$(CURDIR)/ToolChain.cmake - - diff --git a/Docs/adv_digital_twin.md b/Docs/adv_digital_twin.md index 8c06a4013e7..b98d6602802 100644 --- a/Docs/adv_digital_twin.md +++ b/Docs/adv_digital_twin.md @@ -15,6 +15,8 @@ The __Digital Twin Tool__ enables procedural generation of unique 3D environments based on road networks derived from the [OpenStreetMap](https://www.openstreetmap.org) (OSM) service. Through the Digital Twin Tool interface in CARLA's Unreal Engine editor a user can select a region of map from OSM and download the road network as the basis for a new CARLA map. The tool then fills the spaces between the roads with procedurally generated 3D buildings that adjust to the layout of the road, creating a realistic 3D road environment with high variability. + + ## Building the OSM renderer If you are using Linux, you have the option of using the OSM renderer in the CARLA interface to navigate a large OSM map region that you have downloaded. You first need to build the OSM renderer before proceeding to build CARLA. Run `make osmrenderer` inside the CARLA root directory. You may need to upgrade your version of CMake to v3.2 or above in order for this to work. This will create two folders in your build directory called `libosmcout-source` and `libosmcout-build`. Before proceeding to build CARLA, you need to then edit the `Build.sh` file in the directory `$CARLA_ROOT/Build/libosmcout-source/maps` like so, to ensure the executable is found: @@ -103,4 +105,3 @@ The generation step will take around 10 minutes for a 2x2 km2 region, ## Save the map If you are satisfied with the generated map then you can press *Save Map* button to save the map. __This step will take a significant amount of time__, it may take over an hour and could take several. You should prepare to leave your computer running for several hours while this step is completed. Once this step is completed, the map will be available through the Unreal Engine editor or through the CARLA API, the same as any other map. - diff --git a/Docs/adv_rss.md b/Docs/adv_rss.md deleted file mode 100644 index e357822d4a2..00000000000 --- a/Docs/adv_rss.md +++ /dev/null @@ -1,130 +0,0 @@ -# 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. - -* [__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. - ---- -## 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. - -* __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. - -![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. - -[![RSS sensor in CARLA](img/rss_carla_integration.png)](https://www.youtube.com/watch?v=UxKPXPT2T8Q) -
Visualization of the RssSensor results.
- ---- -## 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*. - -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). -```sh -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. -```sh -pip3 install --user -U colcon-common-extensions -``` - -There are some additional dependencies for the Python bindings. -```sh -sudo apt-get install castxml -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. - -```sh -make LibCarla.client.rss -``` - -* Compile the PythonAPI to include the RSS feature. - -```sh -make PythonAPI.rss -``` - -* As an alternative, a package can be built directly. -```sh -make package.rss -``` - ---- -## Current state - -### RssSensor - -[__carla.RssSensor__](python_api.md#carla.RssSensor) supports [ad-rss-lib v4.2.0 feature set](https://intel.github.io/ad-rss-lib/RELEASE_NOTES_AND_DISCLAIMERS) completely, including intersections, [stay on road](https://intel.github.io/ad-rss-lib/ad_rss_map_integration/HandleRoadBoundaries/) support and [unstructured constellations (e.g. with pedestrians)](https://intel.github.io/ad-rss-lib/ad_rss/UnstructuredConstellations/). - -So far, the server provides the sensor with ground truth data of the surroundings that includes the state of other traffic participants and traffic lights. - -### 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. - -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). - -!!! Note - In an automated vehicle controller it might be possible to adapt the planned trajectory to the restrictions. A fast control loop (>1KHz) can be used to ensure these are followed. - ---- - -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. - -
-

- -CARLA forum -

-
diff --git a/Docs/bp_library.md b/Docs/bp_library.md index 416b5aa7fb1..7536df1a54b 100755 --- a/Docs/bp_library.md +++ b/Docs/bp_library.md @@ -255,9 +255,6 @@ Check out the [introduction to blueprints](core_actors.md). - `role_name` (_String_) _- Modifiable_ - `sensor_tick` (_Float_) _- Modifiable_ - `vertical_fov` (_Float_) _- Modifiable_ -- **sensor.other.rss** - - **Attributes:** - - `role_name` (_String_) _- Modifiable_ ### static - **static.prop.advertisement** diff --git a/Docs/build_carla.md b/Docs/build_carla.md index d0e1fed62db..8a0b6cbc108 100644 --- a/Docs/build_carla.md +++ b/Docs/build_carla.md @@ -11,8 +11,7 @@ Build instructions are available for Linux and Windows. You can also build CARLA * [__Updating CARLA__](build_update.md) * [__Build system__](build_system.md) -* [__Linux build with Unreal Engine 5.3__](build_linux_ue5.md) -* [__Windows build with Unreal Engine 5.3__](build_windows_ue5.md) - -* [__FAQ__](build_faq.md) +* [__FAQ__](build_faq.md) +!!! note + These build instructions are for the **Unreal Engine 4.26 version of CARLA**, if you are looking for build instructions for the Unreal Engine 5.5 version of CARLA, please visit [the correct build instructions for that version](https://carla-ue5.readthedocs.io/en/latest/build_carla/). diff --git a/Docs/build_linux.md b/Docs/build_linux.md index e292a71d5d6..3be447d91e6 100644 --- a/Docs/build_linux.md +++ b/Docs/build_linux.md @@ -40,7 +40,7 @@ CARLA requires many different kinds of software to run. Some are built during th sudo apt-get update && sudo apt-get install wget software-properties-common && sudo add-apt-repository ppa:ubuntu-toolchain-r/test && -wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add +sudo apt-get update ``` !!! Warning @@ -50,41 +50,28 @@ To avoid compatibility issues between Unreal Engine and the CARLA dependencies, __Ubuntu 22.04__. ```sh -sudo apt-add-repository "deb http://archive.ubuntu.com/ubuntu focal main universe" -sudo apt-get update -sudo apt-get install build-essential clang-10 lld-10 g++-7 cmake ninja-build libvulkan1 python python3 python3-dev python3-pip libpng-dev libtiff5-dev libjpeg-dev tzdata sed curl unzip autoconf libtool rsync libxml2-dev git git-lfs -sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/lib/llvm-10/bin/clang++ 180 && -sudo update-alternatives --install /usr/bin/clang clang /usr/lib/llvm-10/bin/clang 180 && -sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 180 +sudo apt-get install build-essential g++-13 cmake ninja-build libvulkan1 python3 python3-dev python3-pip libpng-dev libtiff5-dev libjpeg-dev tzdata sed curl unzip autoconf libtool rsync libxml2-dev git git-lfs +sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 180 ``` __Ubuntu 20.04__. ```sh -sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal main" -sudo apt-get update -sudo apt-get install build-essential clang-10 lld-10 g++-7 cmake ninja-build libvulkan1 python python-dev python3-dev python3-pip libpng-dev libtiff5-dev libjpeg-dev tzdata sed curl unzip autoconf libtool rsync libxml2-dev git -sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/lib/llvm-10/bin/clang++ 180 && -sudo update-alternatives --install /usr/bin/clang clang /usr/lib/llvm-10/bin/clang 180 +sudo apt-get install build-essential g++-13 cmake ninja-build libvulkan1 python python-dev python3-dev python3-pip libpng-dev libtiff5-dev libjpeg-dev tzdata sed curl unzip autoconf libtool rsync libxml2-dev git +sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 180 ``` __Ubuntu 18.04__. ```sh -sudo apt-add-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main" -sudo apt-get update -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 git -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 +sudo apt-get install build-essential g++-13 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 git +sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 180 ``` __Ubuntu 16.04__. ```sh -sudo apt-add-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main" && -sudo apt-get update -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 git -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 +sudo apt-get install build-essential g++-13 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 git +sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 180 ``` __Previous Ubuntu versions__. @@ -92,11 +79,8 @@ __Previous Ubuntu versions__. We strongly advise using Ubuntu 18.04 or later to build CARLA. However, you may attempt to build CARLA on older versions of Ubuntu with the following commands: ```sh -sudo apt-add-repository "deb http://apt.llvm.org// llvm-toolchain--8 main" && -sudo apt-get update -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 git -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 +sudo apt-get install build-essential g++-13 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 git +sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 180 ``` __All Ubuntu systems__. diff --git a/Docs/build_linux_ue5.md b/Docs/build_linux_ue5.md deleted file mode 100644 index 54de572a34d..00000000000 --- a/Docs/build_linux_ue5.md +++ /dev/null @@ -1,95 +0,0 @@ -!!! warning - This is a work in progress!! This version of CARLA is not considered a stable release. Over the following months many significant changes may be made to this branch which could break any modifications you make. We advise you to treat this branch as experimental. - -# Building CARLA in Linux with Unreal Engine 5.3 - -!!! note - This build process is implemented and tested for Ubuntu 22.04. We recommend to use this Ubuntu version. - -## Set up the environment - -This guide details how to build CARLA from source on Linux with Unreal Engine 5.3. - -Clone the `ue5-dev` branch of CARLA on your local machine: - -```sh -git clone -b ue5-dev https://github.com/carla-simulator/carla.git CarlaUE5 -``` - -Run the setup script: - -```sh -cd CarlaUE5 -bash -x Setup.sh -``` - -The Setup.sh script installs all the required packages, including Cmake, debian packages, Python packages and Unreal Engine 5.3. It also downloads the CARLA content and builds CARLA. This script can therefore take a long time to complete. - -!!! note - * This version of CARLA requires the **CARLA fork of Unreal Engine 5.3**. You need to link your GitHub account to Epic Games in order to gain permission to clone the UE repository. If you have not already linked your accounts, follow [this guide](https://www.unrealengine.com/en-US/ue4-on-github) - * For using CARLA Unreal Engine 5 previous builds, **ensure CARLA_UNREAL_ENGINE_PATH environment variable is defined** pointing to the CARLA Unreal Engine 5.3 absolute path. If this variable is not defined, the Setup.sh script will download and build CARLA Unreal Engine 5 and **this takes more than 1 extra hour of build and 225Gb of disk space**. - * The Setup.sh script checks if there is any Python installed at the top of the PATH variable, and installs Python otherwise. **To use your own version of Python, ensure that the PATH variable is properly set for Python before running the script**. - * CARLA cannot be built on an external disk, Ubuntu is not giving the required read/write/execution permissions for builds. - - -## Build and Run CARLA UE5 - -The setup script launches the following commands itself, you will need to use the following commands once you modify the code and wish to relaunch: - -* Configure: - -```sh -cmake -G Ninja -S . -B Build --toolchain=$PWD/CMake/LinuxToolchain.cmake \ --DLAUNCH_ARGS="-prefernvidia" -DCMAKE_BUILD_TYPE=Release -DENABLE_ROS2=ON \ --DBUILD_CARLA_UNREAL=ON -DCARLA_UNREAL_ENGINE_PATH=$CARLA_UNREAL_ENGINE_PATH -``` - -* Build CARLA: - -```sh -cmake --build Build -``` - -* Build and install the Python API: - -```sh -cmake --build Build --target carla-python-api-install -``` - -* Launch the editor: - -```sh -cmake --build Build --target launch -``` - -## Build a package with CARLA UE5 - -```sh -cmake --build Build --target package -``` - -The package will be generated in the directory `$CARLA_PATH/Build/Package` - -## Run the package - -Run the package with the following command. - -```sh -./CarlaUnreal.sh -``` - -If you want to run the native ROS2 interface, add the `--ros2` argument - -```sh -./CarlaUnreal.sh --ros2 -``` - -If you want to install the Python API corresponding to the package you have built: - -```sh -pip3 install PythonAPI/carla/dist/carla-*.whl -``` - -## Additional build targets - -The procedure outlined above will download all necessary components to build CARLA, you may not want to \ No newline at end of file diff --git a/Docs/build_windows_ue5.md b/Docs/build_windows_ue5.md deleted file mode 100644 index 70b1eeb9ea9..00000000000 --- a/Docs/build_windows_ue5.md +++ /dev/null @@ -1,79 +0,0 @@ -!!! warning - This is a work in progress!! This version of CARLA is not considered a stable release. Over the following months many significant changes may be made to this branch which could break any modifications you make. We advise you to treat this branch as experimental. - -# Building CARLA in Windowswith Unreal Engine 5.3 - -## Set up the environment - -This guide details how to build CARLA from source on Windows with Unreal Engine 5.3. - -Clone the `ue5-dev` branch of CARLA on your local machine: - -```sh -git clone -b ue5-dev https://github.com/carla-simulator/carla.git CarlaUE5 -``` - -Run the setup script: - -```sh -cd CarlaUE5 -Setup.bat -``` - -The Setup.bat script installs all the required packages, including Visual Studio 2022, Cmake, Python packages and Unreal Engine 5. It also downloads the CARLA content and builds CARLA. This batch file can therefore take a long time to complete. - -!!! note - * This version of CARLA requires the **CARLA fork of Unreal Engine 5.3**. You need to link your GitHub account to Epic Games in order to gain permission to clone the UE repository. If you have not already linked your accounts, follow [this guide](https://www.unrealengine.com/en-US/ue4-on-github) - * For using CARLA Unreal Engine 5 previous builds, ensure CARLA_UNREAL_ENGINE_PATH environment variable is defined pointing to the CARLA Unreal Engine 5 absolute path. If this variable is not defined, Setup.bat script will download and build CARLA Unreal Engine 5 and **this takes more than 1 extra hour of build and a 225Gb of disk space**. - * Setup.bat script checks if there is any Python version installed at the top of the PATH variable, and installs Python otherwise. **To use your own version of Python, ensure that the PATH variable is properly set for Python before running the script**. - * **Windows Developer Mode should be active**, otherwise build will fail. Please see [here](https://learn.microsoft.com/en-us/gaming/game-bar/guide/developer-mode) for instructions on how to activate Developer Mode. - * **CARLA cannot be built on an external disk**, Windows does not give the required read/write/execution permissions for builds. - - -## Build and Run CARLA UE5 - -The Setup.bat file launches the following commands itself, you will need to use the following commands once you modify the code and wish to relaunch: - -!!! warning - Ensure CARLA_UNREAL_ENGINE_PATH environment variable is defined pointing to the CARLA Unreal Engine 5.3 absolute path. Setup.bat sets this variable, but I may not be set if another approach was followed to install the requirements. - -* **Configure**. Open x64 Native Tools Command Prompt for VS 2022 at the CarlaUE5 folder and runn the following command: - -```sh -cmake -G Ninja -S . -B Build -DCMAKE_BUILD_TYPE=Release -DBUILD_CARLA_UNREAL=ON -DCARLA_UNREAL_ENGINE_PATH=%CARLA_UNREAL_ENGINE_PATH% -``` - -* **Build CARLA**. Open the x64 Native Tools Command Prompt for VS 2022 at the CarlaUE5 folder and run the following command: - -```sh -cmake --build Build -``` - -* **Build and install the Python API**. Open the x64 Native Tools Command Prompt for VS 2022 at the CarlaUE5 folder and run the following command:: - -```sh -cmake --build Build --target carla-python-api-install -``` - -* **Launch the editor**. Open the x64 Native Tools Command Prompt for VS 2022 at the CarlaUE5 folder and run the following command: - -```sh -cmake --build Build --target launch -``` - -## Build a package with CARLA UE5 - -!!! warning - The package build for Carla UE5 is not yet fully tested for Windows. - -Open the x64 Native Tools Command Prompt for VS 2022 at the CarlaUE5 folder and run the following command: - -```sh -cmake --build Build --target package -``` - -The package will be generated in the directory `Build/Package` - -## Run the package - -The package build is not yet tested for Windows diff --git a/Docs/core_actors.md b/Docs/core_actors.md index b08653aeadf..c8e0d0c30f6 100644 --- a/Docs/core_actors.md +++ b/Docs/core_actors.md @@ -42,7 +42,7 @@ vehicle_bp = random.choice(blueprint_library.filter('vehicle.*.*')) Besides that, each [carla.ActorBlueprint](python_api.md#carla.ActorBlueprint) has a series of [carla.ActorAttribute](python_api.md#carla.ActorAttribute) that can be _get_ and _set_. ```py is_bike = [vehicle.get_attribute('number_of_wheels') == 2] -if(is_bike) +if is_bike: vehicle.set_attribute('color', '255,0,0') ``` !!! Note diff --git a/Docs/core_concepts.md b/Docs/core_concepts.md index 895647273af..bc4cc5ddff0 100644 --- a/Docs/core_concepts.md +++ b/Docs/core_concepts.md @@ -57,7 +57,6 @@ A sensor is an actor attached to a parent vehicle. It follows the vehicle around * Lane invasion detector. * Obstacle detector. * Radar. -* RSS. --- ## Advanced steps @@ -68,7 +67,6 @@ CARLA offers a wide range of features that go beyond the scope of this introduct * [__PTV-Vissim co-simulation__](adv_ptv.md). Run a synchronous simulation between CARLA and PTV-Vissim traffic simulator. * [__Recorder__](adv_recorder.md). Saves snapshots of the simulation state to reenact a simulation with exact precision. * [__Rendering options__](adv_rendering_options.md). Graphics quality settings, off-screen rendering and a no-rendering mode. -* [__RSS__](adv_rss.md). Integration of the [C++ Library for Responsibility Sensitive Safety](https://github.com/intel/ad-rss-lib) to modify a vehicle's trajectory using safety checks. * [__Simulation time and synchrony__](adv_synchrony_timestep.md). Everything regarding the simulation time and server-client communication. * [__SUMO co-simulation__](adv_sumo.md). Run a synchronous simulation between CARLA and SUMO traffic simulator. * [__Traffic manager__](adv_traffic_manager.md). This module is in charge of every vehicle set to autopilot mode. It simulates traffic in the city for the simulation to look like a real urban environment. diff --git a/Docs/core_sensors.md b/Docs/core_sensors.md index 0a3ab237cf5..4ed6dc0c380 100644 --- a/Docs/core_sensors.md +++ b/Docs/core_sensors.md @@ -152,7 +152,6 @@ Different functionalities such as navigation, measurement of physical properties | [IMU](ref_sensors.md#imu-sensor) | [carla.IMUMeasurement](<../python_api#carlaimumeasurement>) | Comprises an accelerometer, a gyroscope, and a compass. | | [LIDAR](ref_sensors.md#lidar-sensor) | [carla.LidarMeasurement](<../python_api#carlalidarmeasurement>) | A rotating LIDAR. Generates a 4D point cloud with coordinates and intensity per point to model the surroundings. | | [Radar](ref_sensors.md#radar-sensor) | [carla.RadarMeasurement](<../python_api#carlaradarmeasurement>) | 2D point map modelling elements in sight and their movement regarding the sensor. | -| [RSS](ref_sensors.md#rss-sensor) | [carla.RssResponse](<../python_api#carlarssresponse>) | Modifies the controller applied to a vehicle according to safety checks. This sensor works in a different manner than the rest, and there is specific [RSS documentation](<../adv_rss>) for it. | | [Semantic LIDAR](ref_sensors.md#semantic-lidar-sensor) | [carla.SemanticLidarMeasurement](<../python_api#carlasemanticlidarmeasurement>) | A rotating LIDAR. Generates a 3D point cloud with extra information regarding instance and semantic segmentation. |
diff --git a/Docs/img/unreal_lhcs.png b/Docs/img/unreal_lhcs.png new file mode 100644 index 00000000000..0a85ae82bcb Binary files /dev/null and b/Docs/img/unreal_lhcs.png differ diff --git a/Docs/index.md b/Docs/index.md index efa4a5b4f9e..2134555b8e3 100644 --- a/Docs/index.md +++ b/Docs/index.md @@ -1,10 +1,13 @@ -# CARLA Documentation +# CARLA Unreal Engine 4 Documentation + +!!! note + You are currently viewing the documentation for the **Unreal Engine 4.26 version of CARLA**. If you are using the **Unreal Engine version 5.5 version of CARLA** you should refer to the [documentation for that version](https://carla-ue5.readthedocs.io/en/latest/). Welcome to the CARLA documentation. This home page contains an index with a brief description of the different sections in the documentation. Feel free to read in whatever order preferred. In any case, here are a few suggestions for newcomers. -* __Install CARLA.__ Either follow the [Quick start installation](start_quickstart.md) to get a CARLA release or [make the build](build_carla.md) for a desired platform. +* __Install CARLA.__ Either follow the [Quick start installation](start_quickstart.md) to get a CARLA release or [build CARLA](build_carla.md) for a desired platform. * __Start using CARLA.__ The section titled [Foundations](foundations.md) is an introduction to the most important concepts and the [first steps tutorial](tuto_first_steps.md) shows you how to get started. * __Check the API.__ there is a handy [Python API reference](python_api.md) to look up the classes and methods available. @@ -52,7 +55,6 @@ CARLA forum [__Chrono__](tuto_G_chrono.md) — Details of the Chrono physics simulation integration with CARLA. [__OpenDrive__](adv_opendrive.md) — Details of the OpenDrive support in CARLA. [__PTV-Vissim__](adv_ptv.md) — Details of the co-simulation feature with PTV-Vissim. -[__RSS__](adv_rss.md) — Details of the Responsibility Sensitive Safety library integration with CARLA. [__AWS__](tuto_G_rllib_integration) — Details of using RLlib to run CARLA as a distributed application on Amazon Web Services. [__ANSYS__](ecosys_ansys.md) — Brief overview of how the Ansys Real Time Radar Model was integrated into CARLA. [__carlaviz — web visualizer__](plugins_carlaviz.md) — Plugin that listens the simulation and shows the scene and some simulation data in a web browser. diff --git a/Docs/python_api.md b/Docs/python_api.md index a7ab163a211..901b3fd1204 100644 --- a/Docs/python_api.md +++ b/Docs/python_api.md @@ -1998,8 +1998,7 @@ Iterate over the [carla.RadarDetection](#carla.RadarDetection) retrieved as data --- ## 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.
-
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*. +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)`.
*Unreal Engine's left handed coordinate system with rotations*. ### Instance Variables - **pitch** (_float - degrees_) @@ -2040,212 +2039,6 @@ Parses the axis' orientations to string. --- -## carla.RssActorConstellationData -Data structure that is provided within the callback registered by RssSensor.register_actor_constellation_callback(). - -### Instance Variables -- **ego_match_object** (_ad.map.match.Object_) -The ego map matched information. -- **ego_route** (_ad.map.route.FullRoute_) -The ego route. -- **ego_dynamics_on_route** (_[carla.RssEgoDynamicsOnRoute](#carla.RssEgoDynamicsOnRoute)_) -Current ego vehicle dynamics regarding the route. -- **other_match_object** (_ad.map.match.Object_) -The other object's map matched information. This is only valid if 'other_actor' is not 'None'. -- **other_actor** (_[carla.Actor](#carla.Actor)_) -The other actor. This is 'None' in case of query of default parameters or articial objects of kind ad.rss.world.ObjectType.ArtificialObject with no dedicated '[carla.Actor](#carla.Actor)' (as e.g. for the [road boundaries](ref_sensors.md#rss-sensor) at the moment). - -### Methods - -##### Dunder methods -- **\__str__**(**self**) - ---- - -## carla.RssActorConstellationResult -Data structure that should be returned by the callback registered by RssSensor.register_actor_constellation_callback(). - -### Instance Variables -- **rss_calculation_mode** (_ad.rss.map.RssMode_) -The calculation mode to be applied with the actor. -- **restrict_speed_limit_mode** (_ad.rss.map.RestrictSpeedLimitMode_) -The mode for restricting speed limit. -- **ego_vehicle_dynamics** (_ad.rss.world.RssDynamics_) -The RSS dynamics to be applied for the ego vehicle. -- **actor_object_type** (_ad.rss.world.ObjectType_) -The RSS object type to be used for the actor. -- **actor_dynamics** (_ad.rss.world.RssDynamics_) -The RSS dynamics to be applied for the actor. - -### Methods - -##### Dunder methods -- **\__str__**(**self**) - ---- - -## carla.RssEgoDynamicsOnRoute -Part of the data contained inside a [carla.RssResponse](#carla.RssResponse) describing the state of the vehicle. The parameters include its current dynamics, and how it is heading regarding the target route. - -### Instance Variables -- **ego_speed** (_ad.physics.Speed_) -The ego vehicle's speed. -- **min_stopping_distance** (_ad.physics.Distance_) -The current minimum stopping distance. -- **ego_center** (_ad.map.point.ENUPoint_) -The considered enu position of the ego vehicle. -- **ego_heading** (_ad.map.point.ENUHeading_) -The considered heading of the ego vehicle. -- **ego_center_within_route** (_bool_) -States if the ego vehicle's center is within the route. -- **crossing_border** (_bool_) -States if the vehicle is already crossing one of the lane borders. -- **route_heading** (_ad.map.point.ENUHeading_) -The considered heading of the route. -- **route_nominal_center** (_ad.map.point.ENUPoint_) -The considered nominal center of the current route. -- **heading_diff** (_ad.map.point.ENUHeading_) -The considered heading diff towards the route. -- **route_speed_lat** (_ad.physics.Speed_) -The ego vehicle's speed component _lat_ regarding the route. -- **route_speed_lon** (_ad.physics.Speed_) -The ego vehicle's speed component _lon_ regarding the route. -- **route_accel_lat** (_ad.physics.Acceleration_) -The ego vehicle's acceleration component _lat_ regarding the route. -- **route_accel_lon** (_ad.physics.Acceleration_) -The ego vehicle's acceleration component _lon_ regarding the route. -- **avg_route_accel_lat** (_ad.physics.Acceleration_) -The ego vehicle's acceleration component _lat_ regarding the route smoothened by an average filter. -- **avg_route_accel_lon** (_ad.physics.Acceleration_) -The ego acceleration component _lon_ regarding the route smoothened by an average filter. - -### Methods - -##### Dunder methods -- **\__str__**(**self**) - ---- - -## carla.RssLogLevel -Enum declaration used in [carla.RssSensor](#carla.RssSensor) to set the log level. - -### Instance Variables -- **trace** -- **debug** -- **info** -- **warn** -- **err** -- **critical** -- **off** - ---- - -## carla.RssResponse -Inherited from _[carla.SensorData](#carla.SensorData)_
-Class that contains the output of a [carla.RssSensor](#carla.RssSensor). This is the result of the RSS calculations performed for the parent vehicle of the sensor. - -A [carla.RssRestrictor](#carla.RssRestrictor) will use the data to modify the [carla.VehicleControl](#carla.VehicleControl) of the vehicle. - -### Instance Variables -- **response_valid** (_bool_) -States if the response is valid. It is __False__ if calculations failed or an exception occured. -- **proper_response** (_ad.rss.state.ProperResponse_) -The proper response that the RSS calculated for the vehicle. -- **rss_state_snapshot** (_ad.rss.state.RssStateSnapshot_) -Detailed RSS states at the current moment in time. -- **ego_dynamics_on_route** (_[carla.RssEgoDynamicsOnRoute](#carla.RssEgoDynamicsOnRoute)_) -Current ego vehicle dynamics regarding the route. -- **world_model** (_ad.rss.world.WorldModel_) -World model used for calculations. -- **situation_snapshot** (_ad.rss.situation.SituationSnapshot_) -Detailed RSS situations extracted from the world model. - -### Methods - -##### Dunder methods -- **\__str__**(**self**) - ---- - -## carla.RssRestrictor -These objects apply restrictions to a [carla.VehicleControl](#carla.VehicleControl). It is part of the CARLA implementation of the [C++ Library for Responsibility Sensitive Safety](https://github.com/intel/ad-rss-lib). This class works hand in hand with a [rss sensor](ref_sensors.md#rss-sensor), which provides the data of the restrictions to be applied. - -### Methods -- **restrict_vehicle_control**(**self**, **vehicle_control**, **proper_response**, **ego_dynamics_on_route**, **vehicle_physics**) -Applies the safety restrictions given by a [carla.RssSensor](#carla.RssSensor) to a [carla.VehicleControl](#carla.VehicleControl). - - **Parameters:** - - `vehicle_control` (_[carla.VehicleControl](#carla.VehicleControl)_) - The input vehicle control to be restricted. - - `proper_response` (_ad.rss.state.ProperResponse_) - Part of the response generated by the sensor. Contains restrictions to be applied to the acceleration of the vehicle. - - `ego_dynamics_on_route` (_[carla.RssEgoDynamicsOnRoute](#carla.RssEgoDynamicsOnRoute)_) - Part of the response generated by the sensor. Contains dynamics and heading of the vehicle regarding its route. - - `vehicle_physics` (_[carla.VehiclePhysicsControl](#carla.VehiclePhysicsControl)_) - The current physics of the vehicle. Used to apply the restrictions properly. - - **Return:** _[carla.VehicleControl](#carla.VehicleControl)_ - -##### Setters -- **set_log_level**(**self**, **log_level**) -Sets the log level. - - **Parameters:** - - `log_level` (_[carla.RssLogLevel](#carla.RssLogLevel)_) - New log level. - ---- - -## carla.RssRoadBoundariesMode -Enum declaration used in [carla.RssSensor](#carla.RssSensor) to enable or disable the [stay on road](https://intel.github.io/ad-rss-lib/ad_rss_map_integration/HandleRoadBoundaries/) feature. In summary, this feature considers the road boundaries as virtual objects. The minimum safety distance check is applied to these virtual walls, in order to make sure the vehicle does not drive off the road. - -### Instance Variables -- **On** -Enables the _stay on road_ feature. -- **Off** -Disables the _stay on road_ feature. - ---- - -## carla.RssSensor -Inherited from _[carla.Sensor](#carla.Sensor)_
-This sensor works a bit differently than the rest. Take look at the [specific documentation](adv_rss.md), and the [rss sensor reference](ref_sensors.md#rss-sensor) to gain full understanding of it. - -The RSS sensor uses world information, and a [RSS library](https://github.com/intel/ad-rss-lib) to make safety checks on a vehicle. The output retrieved by the sensor is a [carla.RssResponse](#carla.RssResponse). This will be used by a [carla.RssRestrictor](#carla.RssRestrictor) to modify a [carla.VehicleControl](#carla.VehicleControl) before applying it to a vehicle. - -### Instance Variables -- **ego_vehicle_dynamics** (_ad.rss.world.RssDynamics_) -States the [RSS parameters](https://intel.github.io/ad-rss-lib/ad_rss/Appendix-ParameterDiscussion/) that the sensor will consider for the ego vehicle if no actor constellation callback is registered. -- **other_vehicle_dynamics** (_ad.rss.world.RssDynamics_) -States the [RSS parameters](https://intel.github.io/ad-rss-lib/ad_rss/Appendix-ParameterDiscussion/) that the sensor will consider for the rest of vehicles if no actor constellation callback is registered. -- **pedestrian_dynamics** (_ad.rss.world.RssDynamics_) -States the [RSS parameters](https://intel.github.io/ad-rss-lib/ad_rss/Appendix-ParameterDiscussion/) that the sensor will consider for pedestrians if no actor constellation callback is registered. -- **road_boundaries_mode** (_[carla.RssRoadBoundariesMode](#carla.RssRoadBoundariesMode)_) -Switches the [stay on road](https://intel.github.io/ad-rss-lib/ad_rss_map_integration/HandleRoadBoundaries/) feature. By default is __Off__. -- **routing_targets** (_vector<[carla.Transform](#carla.Transform)>_) -The current list of targets considered to route the vehicle. If no routing targets are defined, a route is generated at random. - -### Methods -- **append_routing_target**(**self**, **routing_target**) -Appends a new target position to the current route of the vehicle. - - **Parameters:** - - `routing_target` (_[carla.Transform](#carla.Transform)_) - New target point for the route. Choose these after the intersections to force the route to take the desired turn. -- **drop_route**(**self**) -Discards the current route. If there are targets remaining in **routing_targets**, creates a new route using those. Otherwise, a new route is created at random. -- **register_actor_constellation_callback**(**self**, **callback**) -Register a callback to customize a [carla.RssActorConstellationResult](#carla.RssActorConstellationResult). By this callback the settings of RSS parameters are done per actor constellation and the settings (ego_vehicle_dynamics, other_vehicle_dynamics and pedestrian_dynamics) have no effect. - - **Parameters:** - - `callback` - The function to be called whenever a RSS situation is about to be calculated. -- **reset_routing_targets**(**self**) -Erases the targets that have been appended to the route. - -##### Setters -- **set_log_level**(**self**, **log_level**) -Sets the log level. - - **Parameters:** - - `log_level` (_[carla.RssLogLevel](#carla.RssLogLevel)_) - New log level. -- **set_map_log_level**(**self**, **log_level**) -Sets the map log level. - - **Parameters:** - - `log_level` (_[carla.RssLogLevel](#carla.RssLogLevel)_) - New map log level. - -##### Dunder methods -- **\__str__**(**self**) - ---- - ## carla.SemanticLidarDetection 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. @@ -2313,7 +2106,6 @@ Sensors compound a specific family of actors quite diverse and unique. They are - [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)
@@ -2376,7 +2168,6 @@ Base class for all the objects containing data generated by a [carla.Sensor](#ca - 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).
- Cooperative awareness messages V2X sensor: [carla.CAMEvent](#carla.CAMEvent).
- Custom V2X messages V2X sensor: [carla.CustomV2XEvent](#carla.CustomV2XEvent). diff --git a/Docs/ref_sensors.md b/Docs/ref_sensors.md index 142798920fc..2a523b80fdd 100644 --- a/Docs/ref_sensors.md +++ b/Docs/ref_sensors.md @@ -9,7 +9,6 @@ - [__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) - [__Instance segmentation camera__](#instance-segmentation-camera) @@ -494,139 +493,6 @@ Since these effects are provided by UE, please make sure to check their document | `fov` | float | Horizontal field of view in degrees. | | `raw_data` | bytes | Array of BGRA 32-bit pixels. | - - ---- -## RSS sensor - -* __Blueprint:__ sensor.other.rss -* __Output:__ [carla.RssResponse](python_api.md#carla.RssResponse) per step (unless `sensor_tick` says otherwise). - -!!! Important - It is highly recommended to read the specific [rss documentation](adv_rss.md) before reading this. - -This sensor integrates the [C++ Library for Responsibility Sensitive Safety](https://github.com/intel/ad-rss-lib) in CARLA. It is disabled by default in CARLA, and it has to be explicitly built in order to be used. - -The RSS sensor calculates the RSS state of a vehicle and retrieves the current RSS Response as sensor data. The [carla.RssRestrictor](python_api.md#carla.RssRestrictor) will use this data to adapt a [carla.VehicleControl](python_api.md#carla.VehicleControl) before applying it to a vehicle. - -These controllers can be generated by an *Automated Driving* stack or user input. For instance, hereunder there is a fragment of code from `PythonAPI/examples/rss/manual_control_rss.py`, where the user input is modified using RSS when necessary. - -__1.__ Checks if the __RssSensor__ generates a valid response containing restrictions. -__2.__ Gathers the current dynamics of the vehicle and the vehicle physics. -__3.__ Applies restrictions to the vehicle control using the response from the RssSensor, and the current dynamics and physicis of the vehicle. - -```py -rss_proper_response = self._world.rss_sensor.proper_response if self._world.rss_sensor and self._world.rss_sensor.response_valid else None -if rss_proper_response: -... - vehicle_control = self._restrictor.restrict_vehicle_control( - vehicle_control, rss_proper_response, self._world.rss_sensor.ego_dynamics_on_route, self._vehicle_physics) -``` - - -#### The carla.RssSensor class - -The blueprint for this sensor has no modifiable attributes. However, the [carla.RssSensor](python_api.md#carla.RssSensor) object that it instantiates has attributes and methods that are detailed in the Python API reference. Here is a summary of them. - -| [carla.RssSensor variables](<../python_api#carlarsssensor>) | Type | Description | -| ---------------------------------------- | ---------------------------------------- | ---------------------------------------- | -| `ego_vehicle_dynamics` | [ad.rss.world.RssDynamics]() | RSS parameters to be applied for the ego vehicle | -| `other_vehicle_dynamics` | [ad.rss.world.RssDynamics]() | RSS parameters to be applied for the other vehicles | -| `pedestrian_dynamics` | [ad.rss.world.RssDynamics]() | RSS parameters to be applied for pedestrians | -| `road_boundaries_mode` | [carla.RssRoadBoundariesMode](<../python_api#carlarssroadboundariesmode>) | Enables/Disables the [stay on road]() feature. Default is **Off**. | - -
- - -```py -# Fragment of rss_sensor.py -# The carla.RssSensor is updated when listening for a new carla.RssResponse -def _on_rss_response(weak_self, response): -... - self.timestamp = response.timestamp - self.response_valid = response.response_valid - self.proper_response = response.proper_response - self.ego_dynamics_on_route = response.ego_dynamics_on_route - self.rss_state_snapshot = response.rss_state_snapshot - self.situation_snapshot = response.situation_snapshot - self.world_model = response.world_model -``` - -!!! Warning - This sensor works fully on the client side. There is no blueprint in the server. Changes on the attributes will have effect __after__ the *listen()* has been called. - -The methods available in this class are related to the routing of the vehicle. RSS calculations are always based on a route of the ego vehicle through the road network. - -The sensor allows to control the considered route by providing some key points, which could be the [carla.Transform](python_api.md#carla.Transform) in a [carla.Waypoint](python_api.md#carla.Waypoint). These points are best selected after the intersections to force the route to take the desired turn. - -| [carla.RssSensor methods](<../python_api#carlarsssensor>) | Description | -| ----------------------------------------- | ----------------------------------------- | -| `routing_targets` | Get the current list of routing targets used for route. | -| `append_routing_target` | Append an additional position to the current routing targets. | -| `reset_routing_targets` | Deletes the appended routing targets. | -| `drop_route` | Discards the current route and creates a new one. | -| `register_actor_constellation_callback` | Register a callback to customize the calculations. | -| `set_log_level` | Sets the log level. | -| `set_map_log_level` | Sets the log level used for map related logs. | - - - -
- ---- - - -```py -# Update the current route -self.sensor.reset_routing_targets() -if routing_targets: - for target in routing_targets: - self.sensor.append_routing_target(target) -``` - -!!! Note - If no routing targets are defined, a random route is created. - -#### Output attributes - -| [carla.RssResponse attributes](<../python_api#carlarssresponse>) | Type | Description | -| ------------------------------------- | ------------------------------------- | ------------------------------------- | -| `response_valid` | bool | Validity of the response data. | -| `proper_response` | [ad.rss.state.ProperResponse]() | Proper response that the RSS calculated for the vehicle including acceleration restrictions. | -| `rss_state_snapshot` | [ad.rss.state.RssStateSnapshot]() | RSS states at the current point in time. This is the detailed individual output of the RSS calclulations. | -| `situation_snapshot` | [ad.rss.situation.SituationSnapshot]() | RSS situation at the current point in time. This is the processed input data for the RSS calclulations. | -| `world_model` | [ad.rss.world.WorldModel]() | RSS world model at the current point in time. This is the input data for the RSS calculations. | -| `ego_dynamics_on_route` | [carla.RssEgoDynamicsOnRoute](<../python_api#carlarssegodynamicsonroute>) | Current ego vehicle dynamics regarding the route. | - - -In case a actor_constellation_callback is registered, a call is triggered for: - -1. default calculation (`actor_constellation_data.other_actor=None`) -2. per-actor calculation - -```py -# Fragment of rss_sensor.py -# The function is registered as actor_constellation_callback -def _on_actor_constellation_request(self, actor_constellation_data): - actor_constellation_result = carla.RssActorConstellationResult() - actor_constellation_result.rss_calculation_mode = ad.rss.map.RssMode.NotRelevant - actor_constellation_result.restrict_speed_limit_mode = ad.rss.map.RssSceneCreation.RestrictSpeedLimitMode.IncreasedSpeedLimit10 - actor_constellation_result.ego_vehicle_dynamics = self.current_vehicle_parameters - actor_constellation_result.actor_object_type = ad.rss.world.ObjectType.Invalid - actor_constellation_result.actor_dynamics = self.current_vehicle_parameters - - actor_id = -1 - actor_type_id = "none" - if actor_constellation_data.other_actor != None: - # customize actor_constellation_result for specific actor - ... - else: - # default - ... - return actor_constellation_result -``` - - --- ## Semantic LIDAR sensor @@ -736,7 +602,7 @@ The following tags are currently available (Note, tags changed from version 0.9. | `14` | Car | `(0, 0, 142)` | Cars, vans | | `15` | Truck | `(0, 0, 70)` | Trucks | | `16` | Bus | `(0, 60, 100)` | Busses | -| `17` | Train | `(0, 60, 100)` | Trains | +| `17` | Train | `(0, 80, 100)` | Trains | | `18` | Motorcycle | `(0, 0, 230)` | Motorcycle, Motorbike | | `19` | Bicycle | `(119, 11, 32)` | Bicylces | | `20` | Static | `(110, 190, 160)` | Elements in the scene and props that are immovable.
E.g. fire hydrants, fixed benches, fountains, bus stops, etc. | @@ -940,21 +806,19 @@ While the visibility is simulated within CARLA, the scenario can be configured b * __Output:__ [carla.CAMData](python_api.md#carla.CAMData), triggered according to the ETSI CAM standard, unless configured otherwise Triggering conditions according to ETSI standard: -- Heading angle change > $4$° -- Position difference > $4$ m -- Speed change > $5$ m/s +- Heading angle change > 4° +- Position difference > 4 m +- Speed change > 5 m/s - Time elapsed > CAM Generation time (configurable) -- Low Frequency Container Time Elapsed $> 500$ ms +- Low Frequency Container Time Elapsed > 500 ms For the CAM V2X sensor, additional blueprint attributes apply: | Blueprint attribute | Type | Default | Description | |-------------------------|--------|-------------------------|------------------------------------| -| Message generation | -| gen\_cam\_min | float | $0.1$ | Minimum elapsed time between two successive CAMs in seconds (s) | -| gen\_cam\_max | float | $1.0$ | Maximum elapsed time between two successive CAMs in seconds (s) | +| gen\_cam\_min | float | 0.1 | Minimum elapsed time between two successive CAMs in seconds (s) | +| gen\_cam\_max | float | 1.0 | Maximum elapsed time between two successive CAMs in seconds (s) | | fixed\_rate | bool | false [true] | Generate a CAM in every CARLA tick (only for debug purposes, will result in slowdown) | -| Data generation | | `noise_vel_stddev_x` | float | 0\.0 | Standard deviation parameter in the noise model for velocity (X axis). | | `noise_accel_stddev_x` | float | 0\.0 | Standard deviation parameter in the noise model for acceleration (X axis). | | `noise_accel_stddev_y` | float | 0\.0 | Standard deviation parameter in the noise model for acceleration (Y axis). | @@ -993,17 +857,16 @@ Example: | Blueprint attribute | Type | Default | Description | |-------------------------|--------|-------------------------|------------------------------------| -| transmit\_power | float | $21.5$ | Sender transmission power in dBm | -| receiver\_sensitivity | float | $-99$ | Receiver sensitivity in dBm | -| frequency\_ghz | float | $5.9$ | Transmission frequency in GHz. 5.9 GHz is standard for several physical channels. | -| noise\_seed | int | $0$ | Random parameter for initialization of noise | -| filter\_distance | float | $500$ | Maximum transmission distance in meter, path loss calculations above are skipped for simulation speed | -| __Path loss model parameters__ | -| combined\_antenna\_gain | float | $10.0$ | Combined gain of sender and receiver antennas in dBi, parameter for radiation efficiency and directivity | -| d\_ref | float | $ 1.0 $ | reference distance for Log-distance path loss model in meter | +| transmit\_power | float | 21.5 | Sender transmission power in dBm | +| receiver\_sensitivity | float | -99 | Receiver sensitivity in dBm | +| frequency\_ghz | float | 5.9 | Transmission frequency in GHz. 5.9 GHz is standard for several physical channels. | +| noise\_seed | int | 0 | Random parameter for initialization of noise | +| filter\_distance | float | 500 | Maximum transmission distance in meter, path loss calculations above are skipped for simulation speed | +| __Path loss model parameters__ | | | | +| combined\_antenna\_gain | float | 10.0 | Combined gain of sender and receiver antennas in dBi, parameter for radiation efficiency and directivity | +| d\_ref | float | 1.0 | reference distance for Log-distance path loss model in meter | | path\_loss\_exponent | float | 2.7 | Loss parameter for non-line of sight due to building obstruction | | scenario | string | urban | Options: [urban, rural, highway], defines the fading noise parameters | | path\_loss\_model | string | geometric | general path loss model to be used. Options: [geometric, winner] | | use\_etsi\_fading | bool | true | Use the fading params as mentioned in the ETSI publication (true), or use the custom fading standard deviation | | custom\_fading\_stddev | float | 0.0 | Custom value for fading standard deviation, only used if `use_etsi_fading` is set to `false` | - diff --git a/Docs/tuto_G_bounding_boxes.md b/Docs/tuto_G_bounding_boxes.md index 378de40d862..a0d5f245e82 100644 --- a/Docs/tuto_G_bounding_boxes.md +++ b/Docs/tuto_G_bounding_boxes.md @@ -21,6 +21,9 @@ client = carla.Client('localhost', 2000) world = client.get_world() bp_lib = world.get_blueprint_library() +# Get the map spawn points +spawn_points = world.get_map().get_spawn_points() + # spawn vehicle vehicle_bp =bp_lib.find('vehicle.lincoln.mkz_2020') vehicle = world.try_spawn_actor(vehicle_bp, random.choice(spawn_points)) @@ -37,9 +40,6 @@ settings.synchronous_mode = True # Enables synchronous mode settings.fixed_delta_seconds = 0.05 world.apply_settings(settings) -# Get the map spawn points -spawn_points = world.get_map().get_spawn_points() - # Create a queue to store and retrieve the sensor data image_queue = queue.Queue() camera.listen(image_queue.put) @@ -114,7 +114,7 @@ CARLA objects all have an associated bounding box. CARLA [actors](python_api.md# It is important to note that to get the 3D coordinates of the bounding box in world coordinates, you need to include the transform of the actor as an argument to the `get_world_vertices()` method like so: ```py -actor.get_world_vertices(actor.get_transform()) +bounding_box.get_world_vertices(actor.get_transform()) ``` @@ -128,7 +128,7 @@ bounding_box_set = world.get_level_bbs(carla.CityObjectLabel.TrafficLight) nearby_bboxes = [] for bbox in bounding_box_set: if bbox.location.distance(actor.get_transform().location) < 50: - nearby_bboxes + nearby_bboxes.append() ``` This list can be further filtered using actor location to identify objects that are nearby and therefore likely to be within the field of view of a camera attached to an actor. diff --git a/Examples/CppClient/Makefile b/Examples/CppClient/Makefile index 05713a94c61..a2baa9104ee 100644 --- a/Examples/CppClient/Makefile +++ b/Examples/CppClient/Makefile @@ -4,8 +4,8 @@ BINDIR=$(CURDIR)/bin INSTALLDIR=$(CURDIR)/libcarla-install TOOLCHAIN=$(CURDIR)/ToolChain.cmake -CC=/usr/bin/gcc-7 -CXX=/usr/bin/g++-7 +CC=/usr/bin/gcc-13 +CXX=/usr/bin/g++-13 CXXFLAGS=-std=c++14 -pthread -fPIC -O3 -DNDEBUG -Werror -Wall -Wextra define log diff --git a/Jenkinsfile b/Jenkinsfile index 2eb1304192d..6e3eec7ba1d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -125,14 +125,14 @@ pipeline } stage('Checkout Doxygen repo') { - when { anyOf { branch "master"; branch "dev"; buildingTag() } } + when { anyOf { branch "master"; branch "ue4-dev"; buildingTag() } } steps { dir('doc_repo') { checkout scmGit( - branches: [[name: '*/dev']], + branches: [[name: '*/ue4-dev']], extensions: [ cleanBeforeCheckout(), checkoutOption(120), @@ -236,7 +236,7 @@ pipeline { stage('ubuntu Doxygen generation') { - when { anyOf { branch "master"; branch "dev"; buildingTag() } } + when { anyOf { branch "master"; branch "ue4-dev"; buildingTag() } } steps { sh 'make docs' @@ -279,9 +279,9 @@ pipeline } - stage('ubuntu deploy dev') + stage('ubuntu deploy ue4-dev') { - when { branch "dev"; } + when { branch "ue4-dev"; } steps { sh 'git checkout .' @@ -305,7 +305,7 @@ pipeline { stage('ubuntu Doxygen upload') { - when { anyOf { branch "master"; branch "dev"; buildingTag() } } + when { anyOf { branch "master"; branch "ue4-dev"; buildingTag() } } steps { dir('doc_repo') @@ -316,7 +316,7 @@ pipeline tar -xvzf carla_doc.tar.gz git add Doxygen git commit -m "Updated c++ docs" || true - git push --set-upstream origin dev + git push --set-upstream origin ue4-dev ''' } } @@ -444,7 +444,7 @@ pipeline stage('windows deploy') { - when { anyOf { branch "master"; branch "dev"; buildingTag() } } + when { anyOf { branch "master"; branch "ue4-dev"; buildingTag() } } steps { bat """ call C:\\Users\\jenkins\\setEnv64.bat diff --git a/LibCarla/cmake/CMakeLists.txt b/LibCarla/cmake/CMakeLists.txt index d876d72b6d9..e1ede8f3d06 100644 --- a/LibCarla/cmake/CMakeLists.txt +++ b/LibCarla/cmake/CMakeLists.txt @@ -4,10 +4,12 @@ project(libcarla) option(LIBCARLA_BUILD_DEBUG "Build debug configuration" ON) option(LIBCARLA_BUILD_RELEASE "Build release configuration" ON) option(LIBCARLA_BUILD_TEST "Build unit tests" ON) +option(LIBCARLA_USE_ROS "Build ROS variant" OFF) message(STATUS "Build debug: ${LIBCARLA_BUILD_DEBUG}") message(STATUS "Build release: ${LIBCARLA_BUILD_RELEASE}") message(STATUS "Build test: ${LIBCARLA_BUILD_TEST}") +message(STATUS "Enable ROS: ${LIBCARLA_USE_ROS}") set(libcarla_source_path "${PROJECT_SOURCE_DIR}/../source") set(libcarla_source_thirdparty_path "${libcarla_source_path}/third-party") @@ -24,14 +26,12 @@ if (CMAKE_BUILD_TYPE STREQUAL "Client") elseif (CMAKE_BUILD_TYPE STREQUAL "Server") add_subdirectory("server") elseif (CMAKE_BUILD_TYPE STREQUAL "Pytorch") -add_subdirectory("pytorch") -elseif (CMAKE_BUILD_TYPE STREQUAL "ros2") -add_subdirectory("fast_dds") + add_subdirectory("pytorch") else () message(FATAL_ERROR "Unknown build type '${CMAKE_BUILD_TYPE}'") endif () # GTest is not compiled on Windows. -if ((LIBCARLA_BUILD_TEST) AND (NOT WIN32) AND (NOT (CMAKE_BUILD_TYPE STREQUAL "Pytorch")) AND (NOT (CMAKE_BUILD_TYPE STREQUAL "ros2"))) +if ((LIBCARLA_BUILD_TEST) AND (NOT WIN32) AND (NOT (CMAKE_BUILD_TYPE STREQUAL "Pytorch"))) add_subdirectory("test") endif() diff --git a/LibCarla/cmake/client/CMakeLists.txt b/LibCarla/cmake/client/CMakeLists.txt index 20438ad3ebf..b1287087554 100644 --- a/LibCarla/cmake/client/CMakeLists.txt +++ b/LibCarla/cmake/client/CMakeLists.txt @@ -21,8 +21,8 @@ if (BUILD_RSS_VARIANT) install(FILES ${spdlog_file} DESTINATION lib) list(APPEND ADRSS_LIBS ${spdlog_file}) - set(proj_include_dir ${ADRSS_INSTALL_DIR}/../../proj-install/include) - set(proj_lib ${ADRSS_INSTALL_DIR}/../../proj-install/lib/libproj.a) + set(proj_include_dir ${PROJ_INCLUDE_PATH}) + set(proj_lib ${PROJ_LIBPATH}/libproj.a) install(DIRECTORY ${proj_include_dir} DESTINATION include/system) list(APPEND ADRSS_INCLUDE_DIRS ${proj_include_dir}) install(FILES ${proj_lib} DESTINATION lib) @@ -98,6 +98,12 @@ file(GLOB libcarla_carla_sources set(libcarla_sources "${libcarla_sources};${libcarla_carla_sources}") install(FILES ${libcarla_carla_sources} DESTINATION include/carla) +file(GLOB libcarla_carla_actors_sources + "${libcarla_source_path}/carla/actors/*.cpp" + "${libcarla_source_path}/carla/actors/*.h") +set(libcarla_sources "${libcarla_sources};${libcarla_carla_actors_sources}") +install(FILES ${libcarla_carla_actors_sources} DESTINATION include/carla/actors) + file(GLOB libcarla_carla_client_sources "${libcarla_source_path}/carla/client/*.cpp" "${libcarla_source_path}/carla/client/*.h") @@ -266,11 +272,10 @@ file(GLOB libcarla_carla_trafficmanager_sources set(libcarla_sources "${libcarla_sources};${libcarla_carla_trafficmanager_sources}") install(FILES ${libcarla_carla_trafficmanager_sources} DESTINATION include/carla/trafficmanager) -file(GLOB libcarla_carla_ros2_sources - "${libcarla_source_path}/carla/ros2/*.cpp" - "${libcarla_source_path}/carla/ros2/*.h") -set(libcarla_sources "${libcarla_sources};${libcarla_carla_ros2_sources}") -install(FILES ${libcarla_carla_ros2_sources} DESTINATION include/carla/ros2) + file(GLOB libcarla_carla_ros2_public_headers + "${libcarla_source_path}/carla/ros2/*.h" + ) + install(FILES ${libcarla_carla_ros2_public_headers} DESTINATION include/carla/ros2) # ============================================================================== # Create targets for debug and release in the same build type. diff --git a/LibCarla/cmake/fast_dds/CMakeLists.txt b/LibCarla/cmake/fast_dds/CMakeLists.txt deleted file mode 100644 index 9f2bd03785b..00000000000 --- a/LibCarla/cmake/fast_dds/CMakeLists.txt +++ /dev/null @@ -1,56 +0,0 @@ -cmake_minimum_required(VERSION 3.5.1) -project(libcarla_fastdds) - -# Install headers. - -file(GLOB libcarla_carla_fastdds_headers - "${libcarla_source_path}/carla/ros2/publishers/*.h" - "${libcarla_source_path}/carla/ros2/subscribers/*.h" - "${libcarla_source_path}/carla/ros2/listeners/*.h" - "${libcarla_source_path}/carla/ros2/types/*.h" - ) -install(FILES ${libcarla_carla_fastdds_headers} DESTINATION include/carla/ros2) - -file(GLOB fast_dds_dependencies "${FASTDDS_LIB_PATH}/*.so*") -install(FILES ${fast_dds_dependencies} DESTINATION lib) - - -file(GLOB libcarla_fastdds_sources - "${libcarla_source_path}/carla/ros2/publishers/*.cpp" - "${libcarla_source_path}/carla/ros2/subscribers/*.cpp" - "${libcarla_source_path}/carla/ros2/listeners/*.cpp" - "${libcarla_source_path}/carla/ros2/types/*.cpp") - -set(FASTDDS_CPP_STD_INCLUDES "/usr/include/c++/7") -set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fPIC -D_GLIBCXX_USE_CXX11_ABI=0 -I${FASTDDS_CPP_STD_INCLUDES}" CACHE STRING "" FORCE) - -# ============================================================================== -# Create targets for debug and release in the same build type. -# ============================================================================== - -if (LIBCARLA_BUILD_RELEASE) - add_library(carla_fastdds STATIC ${libcarla_fastdds_sources}) - - target_include_directories(carla_fastdds SYSTEM PRIVATE - "${BOOST_INCLUDE_PATH}" - "${RPCLIB_INCLUDE_PATH}") - - target_include_directories(carla_fastdds PRIVATE "${FASTDDS_INCLUDE_PATH}") - target_include_directories(carla_fastdds PRIVATE "${libcarla_source_path}/carla/ros2") - target_link_libraries(carla_fastdds fastrtps fastcdr "${FAST_DDS_LIBRARIES}") - install(TARGETS carla_fastdds DESTINATION lib) - set_target_properties(carla_fastdds PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS_RELEASE}") - -endif() - -if (LIBCARLA_BUILD_DEBUG) - - add_library(carla_fastdds_debug STATIC ${libcarla_fastdds_sources}) - target_include_directories(carla_fastdds_debug SYSTEM PRIVATE - "${BOOST_INCLUDE_PATH}" - "${RPCLIB_INCLUDE_PATH}") - install(TARGETS carla_fastdds_debug DESTINATION lib) - set_target_properties(carla_fastdds_debug PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS_DEBUG}") - target_compile_definitions(carla_fastdds_debug PUBLIC -DBOOST_ASIO_ENABLE_BUFFER_DEBUGGING) - -endif() diff --git a/LibCarla/cmake/server/CMakeLists.txt b/LibCarla/cmake/server/CMakeLists.txt index 5c642dd4911..3ee53037927 100644 --- a/LibCarla/cmake/server/CMakeLists.txt +++ b/LibCarla/cmake/server/CMakeLists.txt @@ -1,78 +1,51 @@ cmake_minimum_required(VERSION 3.5.1) project(libcarla-server) -# Install libc++ shared libraries. -file(GLOB LibCXX_Libraries "${LLVM_LIB_PATH}/libc++*") -install(FILES ${LibCXX_Libraries} DESTINATION lib) - -# Install rpclib. -install(DIRECTORY "${RPCLIB_INCLUDE_PATH}/rpc" DESTINATION include) -file(GLOB libcarla_carla_rpclib "${RPCLIB_LIB_PATH}/*.*") -install(FILES ${libcarla_carla_rpclib} DESTINATION lib) - -# Install headers. - install(DIRECTORY "${libcarla_source_path}/compiler" DESTINATION include) -file(GLOB libcarla_carla_headers "${libcarla_source_path}/carla/*.h") -install(FILES ${libcarla_carla_headers} DESTINATION include/carla) - -file(GLOB libcarla_carla_geom_headers "${libcarla_source_path}/carla/geom/*.h") -install(FILES ${libcarla_carla_geom_headers} DESTINATION include/carla/geom) - -file(GLOB libcarla_carla_opendrive "${libcarla_source_path}/carla/opendrive/*.h") -install(FILES ${libcarla_carla_opendrive} DESTINATION include/carla/opendrive) - -file(GLOB libcarla_carla_opendrive_parser "${libcarla_source_path}/carla/opendrive/parser/*.h") -install(FILES ${libcarla_carla_opendrive_parser} DESTINATION include/carla/opendrive/parser) - -file(GLOB libcarla_carla_profiler_headers "${libcarla_source_path}/carla/profiler/*.h") -install(FILES ${libcarla_carla_profiler_headers} DESTINATION include/carla/profiler) - -file(GLOB libcarla_carla_road_headers "${libcarla_source_path}/carla/road/*.h") -install(FILES ${libcarla_carla_road_headers} DESTINATION include/carla/road) - -file(GLOB libcarla_carla_road_element_headers "${libcarla_source_path}/carla/road/element/*.h") -install(FILES ${libcarla_carla_road_element_headers} DESTINATION include/carla/road/element) - -file(GLOB libcarla_carla_road_general_headers "${libcarla_source_path}/carla/road/general/*.h") -install(FILES ${libcarla_carla_road_general_headers} DESTINATION include/carla/road/general) - -file(GLOB libcarla_carla_road_object_headers "${libcarla_source_path}/carla/road/object/*.h") -install(FILES ${libcarla_carla_road_object_headers} DESTINATION include/carla/road/object) - -file(GLOB libcarla_carla_road_signal_headers "${libcarla_source_path}/carla/road/signal/*.h") -install(FILES ${libcarla_carla_road_signal_headers} DESTINATION include/carla/road/signal) - -file(GLOB libcarla_carla_rpc_headers "${libcarla_source_path}/carla/rpc/*.h") -install(FILES ${libcarla_carla_rpc_headers} DESTINATION include/carla/rpc) - -file(GLOB libcarla_carla_sensor_headers "${libcarla_source_path}/carla/sensor/*.h") -install(FILES ${libcarla_carla_sensor_headers} DESTINATION include/carla/sensor) - -file(GLOB libcarla_carla_sensor_data_headers "${libcarla_source_path}/carla/sensor/data/*.h") -install(FILES ${libcarla_carla_sensor_data_headers} DESTINATION include/carla/sensor/data) - -file(GLOB libcarla_carla_sensor_s11n_headers "${libcarla_source_path}/carla/sensor/s11n/*.h") -install(FILES ${libcarla_carla_sensor_s11n_headers} DESTINATION include/carla/sensor/s11n) - -file(GLOB libcarla_carla_streaming_headers "${libcarla_source_path}/carla/streaming/*.h") -install(FILES ${libcarla_carla_streaming_headers} DESTINATION include/carla/streaming) - -file(GLOB libcarla_carla_streaming_detail_headers "${libcarla_source_path}/carla/streaming/detail/*.h") -install(FILES ${libcarla_carla_streaming_detail_headers} DESTINATION include/carla/streaming/detail) - -file(GLOB libcarla_carla_streaming_detail_tcp_headers "${libcarla_source_path}/carla/streaming/detail/tcp/*.h") -install(FILES ${libcarla_carla_streaming_detail_tcp_headers} DESTINATION include/carla/streaming/detail/tcp) - -file(GLOB libcarla_carla_streaming_low_level_headers "${libcarla_source_path}/carla/streaming/low_level/*.h") -install(FILES ${libcarla_carla_streaming_low_level_headers} DESTINATION include/carla/streaming/low_level) - -file(GLOB libcarla_carla_multigpu_headers "${libcarla_source_path}/carla/multigpu/*.h") -install(FILES ${libcarla_carla_multigpu_headers} DESTINATION include/carla/multigpu) - -file(GLOB libcarla_carla_ros2_headers "${libcarla_source_path}/carla/ros2/*.h") -install(FILES ${libcarla_carla_ros2_headers} DESTINATION include/carla/ros2) +foreach(dir "" + "actors/" + "geom/" + "opendrive/" "opendrive/parser/" + "profiler/" + "road/" "road/element/" "road/general/" "road/object/" "road/signal/" + "rpc/" + "sensor/" "sensor/data/" "sensor/s11n/" + "streaming/" "streaming/detail/" "streaming/detail/tcp/" "streaming/low_level/" + "multigpu/") + + file(GLOB headers "${libcarla_source_path}/carla/${dir}*.h") + install(FILES ${headers} DESTINATION include/carla/${dir}) + +endforeach() + + + + # only install the required public interface headers + foreach(dir "" "types/" ) + file(GLOB libcarla_carla_ros2_public_headers + "${libcarla_source_path}/carla/ros2/${dir}*.h" + ) + install(FILES ${libcarla_carla_ros2_public_headers} DESTINATION include/carla/ros2/${dir}) + endforeach() +if (LIBCARLA_USE_ROS) + + file(GLOB subdirs RELATIVE "${libcarla_source_path}/carla/ros2/${ROS2_MW_NAME}" "${libcarla_source_path}/carla/ros2/${ROS2_MW_NAME}/*") + foreach(typedir "msg" "srv") + foreach(dir ${subdirs}) + if(IS_DIRECTORY "${libcarla_source_path}/carla/ros2/${ROS2_MW_NAME}/${dir}/${typedir}") + file(GLOB libcarla_carla_ros2_types_${dir}_headers + "${libcarla_source_path}/carla/ros2/${ROS2_MW_NAME}/${dir}/${typedir}/*.h" + ) + install(FILES ${libcarla_carla_ros2_types_${dir}_headers} DESTINATION include/carla/ros2/ros_types/${dir}/${typedir}/) + endif() + endforeach() + endforeach() + + if(NOT WIN32) + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3" CACHE STRING "" FORCE) + endif() +endif() install(DIRECTORY "${BOOST_INCLUDE_PATH}/boost" DESTINATION include) @@ -85,47 +58,62 @@ if(WIN32) endif() # carla_server library. +# first the sources which are picked from some directories +set(libcarla_server_sources + "${libcarla_source_path}/carla/Buffer.cpp" + "${libcarla_source_path}/carla/Exception.cpp" + "${libcarla_source_path}/carla/StringUtil.cpp" + # other cpp files only define Deserialize used in client + "${libcarla_source_path}/carla/sensor/s11n/SensorHeaderSerializer.cpp" + ) +# then the globs on the folders to add as a whole +foreach(dir + "actors" + "geom" + "opendrive" "opendrive/parser" + "profiler" + "road" "road/element" "road/general" "road/object" "road/signal" + "rpc" + "sensor" "sensor/data" + "streaming" "streaming/detail" "streaming/detail/tcp" "streaming/low_level" + "multigpu") + + file(GLOB sources "${libcarla_source_path}/carla/${dir}/*.cpp") + list(APPEND libcarla_server_sources ${sources}) + +endforeach() + +foreach(thirdparty_dir + "odrSpiral" + "moodycamel" + "pugixml") + + file(GLOB sources "${libcarla_source_thirdparty_path}/${thirdparty_dir}/*.cpp") + list(APPEND libcarla_server_sources ${sources}) + +endforeach() + +if (LIBCARLA_USE_ROS) + foreach(ros2_dir + "/" + "${ROS2_MW_NAME}/carla/ros2/impl/" + "listeners/" + "publishers/" + "services/" + "subscribers/" + "types/") + + file(GLOB sources "${libcarla_source_path}/carla/ros2/${ros2_dir}*.cpp") + list(APPEND libcarla_server_sources ${sources}) + endforeach() + + file(GLOB msg_sources "${libcarla_source_path}/carla/ros2/${ROS2_MW_NAME}/*/msg/*.cxx") + list(APPEND libcarla_server_sources ${msg_sources}) + + file(GLOB srv_sources "${libcarla_source_path}/carla/ros2/${ROS2_MW_NAME}/*/srv/*.cxx") + list(APPEND libcarla_server_sources ${srv_sources}) -file(GLOB libcarla_server_sources - "${libcarla_source_path}/carla/*.h" - "${libcarla_source_path}/carla/Buffer.cpp" - "${libcarla_source_path}/carla/Exception.cpp" - "${libcarla_source_path}/carla/geom/*.cpp" - "${libcarla_source_path}/carla/geom/*.h" - "${libcarla_source_path}/carla/opendrive/*.cpp" - "${libcarla_source_path}/carla/opendrive/*.h" - "${libcarla_source_path}/carla/opendrive/parser/*.cpp" - "${libcarla_source_path}/carla/opendrive/parser/*.h" - "${libcarla_source_path}/carla/road/*.cpp" - "${libcarla_source_path}/carla/road/*.h" - "${libcarla_source_path}/carla/road/element/*.cpp" - "${libcarla_source_path}/carla/road/element/*.h" - "${libcarla_source_path}/carla/road/general/*.cpp" - "${libcarla_source_path}/carla/road/general/*.h" - "${libcarla_source_path}/carla/road/object/*.cpp" - "${libcarla_source_path}/carla/road/object/*.h" - "${libcarla_source_path}/carla/road/signal/*.cpp" - "${libcarla_source_path}/carla/road/signal/*.h" - "${libcarla_source_path}/carla/rpc/*.cpp" - "${libcarla_source_path}/carla/rpc/*.h" - "${libcarla_source_path}/carla/sensor/*.h" - "${libcarla_source_path}/carla/sensor/s11n/*.h" - "${libcarla_source_path}/carla/sensor/s11n/SensorHeaderSerializer.cpp" - "${libcarla_source_path}/carla/streaming/*.h" - "${libcarla_source_path}/carla/streaming/detail/*.cpp" - "${libcarla_source_path}/carla/streaming/detail/*.h" - "${libcarla_source_path}/carla/streaming/detail/tcp/*.cpp" - "${libcarla_source_path}/carla/streaming/low_level/*.h" - "${libcarla_source_path}/carla/multigpu/*.h" - "${libcarla_source_path}/carla/multigpu/*.cpp" - "${libcarla_source_path}/carla/ros2/*.h" - "${libcarla_source_path}/carla/ros2/*.cpp" - "${libcarla_source_thirdparty_path}/odrSpiral/*.cpp" - "${libcarla_source_thirdparty_path}/odrSpiral/*.h" - "${libcarla_source_thirdparty_path}/moodycamel/*.cpp" - "${libcarla_source_thirdparty_path}/moodycamel/*.h" - "${libcarla_source_thirdparty_path}/pugixml/*.cpp" - "${libcarla_source_thirdparty_path}/pugixml/*.hpp") +endif() # ============================================================================== # Create targets for debug and release in the same build type. @@ -133,7 +121,10 @@ file(GLOB libcarla_server_sources if (LIBCARLA_BUILD_RELEASE) - add_library(carla_server STATIC ${libcarla_server_sources}) + add_library(carla_server STATIC + ${libcarla_server_sources} + ) + target_compile_definitions(carla_server PUBLIC -DCARLA_SERVER_BUILD) target_include_directories(carla_server SYSTEM PRIVATE "${BOOST_INCLUDE_PATH}" @@ -143,11 +134,23 @@ if (LIBCARLA_BUILD_RELEASE) set_target_properties(carla_server PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS_RELEASE}") + if (LIBCARLA_USE_ROS) + target_include_directories(carla_server SYSTEM PRIVATE + # first the ROS2_MW_NAME local folder allowing potential overrides of header files + "${libcarla_source_path}/carla/ros2/${ROS2_MW_NAME}" + "${ROS2_MW_INCLUDE_PATH}") + target_link_directories(carla_server PRIVATE ${ROS2_MW_LIB_PATH}) + target_link_libraries(carla_server ${ROS2_MW_LINK_LIBRARIES}) + target_compile_definitions(carla_server PUBLIC -DWITH_ROS2) + endif() endif() if (LIBCARLA_BUILD_DEBUG) - add_library(carla_server_debug STATIC ${libcarla_server_sources}) + add_library(carla_server_debug STATIC + ${libcarla_server_sources} + ) + target_compile_definitions(carla_server_debug PUBLIC -DCARLA_SERVER_BUILD) target_include_directories(carla_server_debug SYSTEM PRIVATE "${BOOST_INCLUDE_PATH}" @@ -158,4 +161,13 @@ if (LIBCARLA_BUILD_DEBUG) set_target_properties(carla_server_debug PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS_DEBUG}") target_compile_definitions(carla_server_debug PUBLIC -DBOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + if (LIBCARLA_USE_ROS) + target_include_directories(carla_server_debug SYSTEM PRIVATE + # first the ROS2_MW_NAME local folder allowing potential overrides of header files + "${libcarla_source_path}/carla/ros2/${ROS2_MW_NAME}" + "${ROS2_MW_INCLUDE_PATH}") + target_link_directories(carla_server_debug PRIVATE ${ROS2_MW_LIB_PATH}) + target_link_libraries(carla_server_debug ${ROS2_MW_LINK_LIBRARIES}) + target_compile_definitions(carla_server_debug PUBLIC -DWITH_ROS2) + endif() endif() diff --git a/LibCarla/cmake/test/CMakeLists.txt b/LibCarla/cmake/test/CMakeLists.txt index 432f509e726..23eefc167d7 100644 --- a/LibCarla/cmake/test/CMakeLists.txt +++ b/LibCarla/cmake/test/CMakeLists.txt @@ -15,6 +15,10 @@ endif() link_directories( ${RPCLIB_LIB_PATH} ${GTEST_LIB_PATH}) +if (LIBCARLA_USE_ROS) + link_directories(${ROS2_MW_LIB_PATH}) +endif() + file(GLOB libcarla_test_sources "${libcarla_source_path}/carla/profiler/*.cpp" diff --git a/LibCarla/source/carla/Exception.cpp b/LibCarla/source/carla/Exception.cpp index 1ed5c796561..3dfd7ec8afd 100644 --- a/LibCarla/source/carla/Exception.cpp +++ b/LibCarla/source/carla/Exception.cpp @@ -15,19 +15,18 @@ namespace boost { - void throw_exception(const std::exception &e) { - carla::throw_exception(e); - } +void throw_exception(const std::exception &e) { + carla::throw_exception(e); +} - void throw_exception( - const std::exception &e, - boost::source_location const & loc) { - throw_exception(e); - } +void throw_exception(const std::exception &e, boost::source_location const &loc) { + (void)loc; + throw_exception(e); +} -} // namespace boost +} // namespace boost -#endif // BOOST_NO_EXCEPTIONS +#endif // BOOST_NO_EXCEPTIONS // ============================================================================= // -- Workaround for Boost.Asio bundled with rpclib ---------------------------- @@ -42,16 +41,47 @@ namespace boost { namespace clmdep_asio { namespace detail { - template - void throw_exception(const Exception& e) { - carla::throw_exception(e); - } +template +void throw_exception(const Exception &e) { + carla::throw_exception(e); +} - template void throw_exception(const std::bad_cast &); - template void throw_exception(const std::exception &); - template void throw_exception(const std::system_error &); +template void throw_exception(const std::bad_cast &e); +template void throw_exception(const std::exception &e); +template void throw_exception(const std::system_error &e); -} // namespace detail -} // namespace clmdep_asio +} // namespace detail +} // namespace clmdep_asio -#endif // ASIO_NO_EXCEPTIONS +namespace asio { +namespace detail { + +template +void throw_exception(const Exception &e) { + carla::throw_exception(e); +} + +template void throw_exception(const std::bad_cast &e); +template void throw_exception(const std::exception &e); +template void throw_exception(const std::system_error &e); + +} // namespace detail +} // namespace asio + +#endif // ASIO_NO_EXCEPTIONS + +#ifndef LIBCARLA_NO_EXCEPTIONS + +namespace carla { +template +#ifndef __clang__ + // clang doesn't support C++11 attributes in template explicit instantiation, since attributes in each case cannot + // be changed here MSVC requires it (might be a bit too conservative and requires the attributes also in explicit + // instanciation) + [[noreturn]] +#endif + void + throw_exception(const std::exception &); +} // namespace carla + +#endif diff --git a/LibCarla/source/carla/Exception.h b/LibCarla/source/carla/Exception.h index 6df36e08672..843294a2933 100644 --- a/LibCarla/source/carla/Exception.h +++ b/LibCarla/source/carla/Exception.h @@ -6,38 +6,34 @@ #pragma once -#ifdef LIBCARLA_NO_EXCEPTIONS - -namespace std { +#include - class exception; - -} // namespace std +#ifdef LIBCARLA_NO_EXCEPTIONS namespace carla { - /// User define function, similar to Boost throw_exception. - /// - /// @important Boost exceptions are also routed to this function. - /// - /// When compiled with LIBCARLA_NO_EXCEPTIONS, this function is left undefined - /// in LibCarla, and the modules using LibCarla are expected to supply an - /// appropriate definition. Callers of throw_exception are allowed to assume - /// that the function never returns; therefore, if the user-defined - /// throw_exception returns, the behavior is undefined. - [[ noreturn ]] void throw_exception(const std::exception &e); +/// User define function, similar to Boost throw_exception. +/// +/// @important Boost exceptions are also routed to this function. +/// +/// When compiled with LIBCARLA_NO_EXCEPTIONS, this function is left undefined +/// in LibCarla, and the modules using LibCarla are expected to supply an +/// appropriate definition. Callers of throw_exception are allowed to assume +/// that the function never returns; therefore, if the user-defined +/// throw_exception returns, the behavior is undefined. +[[noreturn]] void throw_exception(const std::exception &e); -} // namespace carla +} // namespace carla #else namespace carla { - template - [[ noreturn ]] void throw_exception(const T &e) { - throw e; - } +template +[[noreturn]] void throw_exception(const T &e) { + throw e; +} -} // namespace carla +} // namespace carla -#endif // LIBCARLA_NO_EXCEPTIONS +#endif // LIBCARLA_NO_EXCEPTIONS diff --git a/LibCarla/source/carla/client/Actor.cpp b/LibCarla/source/carla/client/Actor.cpp index 497c99b0293..d63a26b33aa 100644 --- a/LibCarla/source/carla/client/Actor.cpp +++ b/LibCarla/source/carla/client/Actor.cpp @@ -32,6 +32,10 @@ namespace client { return GetEpisode().Lock()->GetActorAcceleration(*this); } + geom::BoundingBox Actor::GetBoundingBox() const { + return GetEpisode().Lock()->GetActorBoundingBox(*this); + } + geom::Transform Actor::GetComponentWorldTransform(const std::string componentName) const { return GetEpisode().Lock()->GetActorComponentWorldTransform(*this, componentName); } diff --git a/LibCarla/source/carla/client/Actor.h b/LibCarla/source/carla/client/Actor.h index c84d59798af..9ca6a29a2c9 100644 --- a/LibCarla/source/carla/client/Actor.h +++ b/LibCarla/source/carla/client/Actor.h @@ -26,7 +26,6 @@ namespace client { : LIBCARLA_INITIALIZE_LIFETIME_PROFILER(init.GetDisplayId()), Super(std::move(init)) {} - using ActorState::GetBoundingBox; virtual ~Actor() = default; @@ -60,6 +59,8 @@ namespace client { /// acceleration calculated after the actor's velocity. geom::Vector3D GetAcceleration() const; + geom::BoundingBox GetBoundingBox() const; + geom::Transform GetComponentWorldTransform(const std::string componentName) const; geom::Transform GetComponentRelativeTransform(const std::string componentName) const; diff --git a/LibCarla/source/carla/client/detail/Client.cpp b/LibCarla/source/carla/client/detail/Client.cpp index 49cf59e0080..2e5cfcc1019 100644 --- a/LibCarla/source/carla/client/detail/Client.cpp +++ b/LibCarla/source/carla/client/detail/Client.cpp @@ -418,6 +418,10 @@ namespace detail { _pimpl->AsyncCall("add_actor_torque", actor, vector); } + geom::BoundingBox Client::GetActorBoundingBox(rpc::ActorId actor) { + return _pimpl->CallAndWait("get_actor_bounding_box", actor); + } + geom::Transform Client::GetActorComponentWorldTransform(rpc::ActorId actor, const std::string componentName) { return _pimpl->CallAndWait("get_actor_component_world_transform", actor, componentName); } diff --git a/LibCarla/source/carla/client/detail/Client.h b/LibCarla/source/carla/client/detail/Client.h index ffd3c8fba18..7be74a929bb 100644 --- a/LibCarla/source/carla/client/detail/Client.h +++ b/LibCarla/source/carla/client/detail/Client.h @@ -238,6 +238,9 @@ namespace detail { rpc::ActorId actor, const geom::Vector3D &vector); + geom::BoundingBox GetActorBoundingBox( + rpc::ActorId actor); + geom::Transform GetActorComponentWorldTransform( rpc::ActorId actor, const std::string componentName); diff --git a/LibCarla/source/carla/client/detail/Simulator.cpp b/LibCarla/source/carla/client/detail/Simulator.cpp index 8b4089a8846..5083dd37885 100644 --- a/LibCarla/source/carla/client/detail/Simulator.cpp +++ b/LibCarla/source/carla/client/detail/Simulator.cpp @@ -88,6 +88,12 @@ namespace detail { const auto id = GetCurrentEpisode().GetId(); _client.LoadEpisode(std::move(map_name), reset_settings, map_layers); + // delete the pointer to _episode so that the Navigation information + // will be loaded for the correct map + assert(_episode.use_count() == 1); + _episode.reset(); + GetReadyCurrentEpisode(); + // We are waiting 50ms for the server to reload the episode. // If in this time we have not detected a change of episode, we try again // 'number_of_attempts' times. diff --git a/LibCarla/source/carla/client/detail/Simulator.h b/LibCarla/source/carla/client/detail/Simulator.h index 0ff8f3c1794..23a1376ac86 100644 --- a/LibCarla/source/carla/client/detail/Simulator.h +++ b/LibCarla/source/carla/client/detail/Simulator.h @@ -447,6 +447,10 @@ namespace detail { return GetActorSnapshot(actor).acceleration; } + geom::BoundingBox GetActorBoundingBox(const Actor &actor) { + return _client.GetActorBoundingBox(actor.GetId()); + } + geom::Transform GetActorComponentWorldTransform(const Actor &actor, const std::string componentName) { return _client.GetActorComponentWorldTransform(actor.GetId(), componentName); } diff --git a/LibCarla/source/carla/geom/BoundingBox.h b/LibCarla/source/carla/geom/BoundingBox.h index 172be006fe1..630f83c57c3 100644 --- a/LibCarla/source/carla/geom/BoundingBox.h +++ b/LibCarla/source/carla/geom/BoundingBox.h @@ -32,6 +32,12 @@ namespace geom { // -- Constructors --------------------------------------------------------- // ========================================================================= + explicit BoundingBox(const Location &in_location, const Vector3D &in_extent, const Rotation &in_rotation, const uint32_t &in_actor_id) + : location(in_location), + extent(in_extent), + rotation(in_rotation), + actor_id(in_actor_id) {} + explicit BoundingBox(const Location &in_location, const Vector3D &in_extent, const Rotation &in_rotation) : location(in_location), extent(in_extent), @@ -50,6 +56,7 @@ namespace geom { Location location; ///< Center 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 + uint32_t actor_id; // ========================================================================= // -- Other methods -------------------------------------------------------- @@ -137,11 +144,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), - rotation(Box.Rotation) {} + rotation(Box.Rotation), + actor_id(Box.ActorId) {} #endif // LIBCARLA_INCLUDED_FROM_UE4 - MSGPACK_DEFINE_ARRAY(location, extent, rotation); + MSGPACK_DEFINE_ARRAY(location, extent, rotation, actor_id); }; } // namespace geom diff --git a/LibCarla/source/carla/geom/Location.h b/LibCarla/source/carla/geom/Location.h index 1ce3fcecf8e..9e86a15e507 100644 --- a/LibCarla/source/carla/geom/Location.h +++ b/LibCarla/source/carla/geom/Location.h @@ -54,7 +54,7 @@ namespace geom { // ========================================================================= Location &operator+=(const Location &rhs) { - static_cast(*this) += rhs; + static_cast(*this) += static_cast(rhs); return *this; } @@ -64,7 +64,7 @@ namespace geom { } Location &operator-=(const Location &rhs) { - static_cast(*this) -= rhs; + static_cast(*this) -= static_cast(rhs); return *this; } @@ -78,7 +78,7 @@ namespace geom { // ========================================================================= bool operator==(const Location &rhs) const { - return static_cast(*this) == rhs; + return static_cast(*this) == static_cast(rhs); } bool operator!=(const Location &rhs) const { diff --git a/LibCarla/source/carla/opendrive/parser/SignalParser.cpp b/LibCarla/source/carla/opendrive/parser/SignalParser.cpp index bbc18d9e633..c848cc39a48 100644 --- a/LibCarla/source/carla/opendrive/parser/SignalParser.cpp +++ b/LibCarla/source/carla/opendrive/parser/SignalParser.cpp @@ -50,7 +50,7 @@ namespace parser { const std::string name = signal_node.attribute("name").value(); const std::string dynamic = signal_node.attribute("dynamic").value(); const std::string orientation = signal_node.attribute("orientation").value(); - const double zOffset = signal_node.attribute("zOffSet").as_double(); + const double zOffset = signal_node.attribute("zOffset").as_double(); const std::string country = signal_node.attribute("country").value(); const std::string type = signal_node.attribute("type").value(); const std::string subtype = signal_node.attribute("subtype").value(); diff --git a/LibCarla/source/carla/road/Map.cpp b/LibCarla/source/carla/road/Map.cpp index 282452c66e3..44e5e55821d 100644 --- a/LibCarla/source/carla/road/Map.cpp +++ b/LibCarla/source/carla/road/Map.cpp @@ -582,10 +582,23 @@ namespace road { successor.road_id != waypoint.road_id || successor.section_id != waypoint.section_id || successor.lane_id != waypoint.lane_id); - result = ConcatVectors(result, GetNext(successor, distance - remaining_lane_length)); - } + // Fix situations, when next waypoint is in the opposite dirrection and + // this waypoint is his successor, so this function would end up in a loop + bool is_broken = false; + for (const auto &future_succcessor : GetSuccessors(successor)) { + if (future_succcessor.road_id == waypoint.road_id + && future_succcessor.lane_id == waypoint.lane_id + && future_succcessor.section_id == waypoint.section_id){ + is_broken = true; + break; + } + } // end inner for + if (!is_broken){ + result = ConcatVectors(result, GetNext(successor, distance - remaining_lane_length)); + } + } // end outer for return result; - } + } // end GetNext std::vector Map::GetPrevious( const Waypoint waypoint, @@ -618,10 +631,23 @@ namespace road { successor.road_id != waypoint.road_id || successor.section_id != waypoint.section_id || successor.lane_id != waypoint.lane_id); - result = ConcatVectors(result, GetPrevious(successor, distance - remaining_lane_length)); - } + // Fix situations, when next waypoint is in the opposite dirrection and + // this waypoint is his predeccessor, so this function would end up in a loop + bool is_broken = false; + for (const auto &future_predecessor : GetPredecessors(successor)) { + if (future_predecessor.road_id == waypoint.road_id + && future_predecessor.lane_id == waypoint.lane_id + && future_predecessor.section_id == waypoint.section_id){ + is_broken = true; + break; + } + } // end inner for + if (!is_broken){ + result = ConcatVectors(result, GetPrevious(successor, distance - remaining_lane_length)); + } + } // end outer for return result; - } + } // end GetPrevious boost::optional Map::GetRight(Waypoint waypoint) const { RELEASE_ASSERT(waypoint.lane_id != 0); diff --git a/LibCarla/source/carla/ros2/Exception.cpp b/LibCarla/source/carla/ros2/Exception.cpp new file mode 100644 index 00000000000..58f298c822a --- /dev/null +++ b/LibCarla/source/carla/ros2/Exception.cpp @@ -0,0 +1,30 @@ +// 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 "carla/Exception.h" +#include + +#ifdef ASIO_NO_EXCEPTIONS + +namespace asio { +namespace detail { + +template +void throw_exception(const Exception &e) { + carla::throw_exception(e); +} + +template void throw_exception(const std::length_error &e); +template void throw_exception(const asio::service_already_exists &e); +template void throw_exception(const asio::invalid_service_owner &e); +template void throw_exception(const asio::execution::bad_executor &e); +template void throw_exception(const asio::ip::bad_address_cast &e); +template void throw_exception(const std::out_of_range &e); + +} // namespace detail +} // namespace asio + +#endif // ASIO_NO_EXCEPTIONS diff --git a/LibCarla/source/carla/ros2/ROS2.cpp b/LibCarla/source/carla/ros2/ROS2.cpp index 719e66237c6..63536aacbf7 100644 --- a/LibCarla/source/carla/ros2/ROS2.cpp +++ b/LibCarla/source/carla/ros2/ROS2.cpp @@ -16,6 +16,7 @@ #include "carla/sensor/s11n/ImageSerializer.h" #include "carla/sensor/s11n/SensorHeaderSerializer.h" +#include "fastdds/carla/ros2/impl/DdsDomainParticipantImpl.h" #include "publishers/CarlaPublisher.h" #include "publishers/CarlaClockPublisher.h" #include "publishers/CarlaRGBCameraPublisher.h" @@ -46,6 +47,14 @@ namespace ros2 { // static fields std::shared_ptr ROS2::_instance; +std::shared_ptr ROS2::GetDdsDomainParticipant() { + auto _instance = ROS2::GetInstance(); + if (_instance->_domain_participant_impl == nullptr) + { + _instance->_domain_participant_impl = std::make_shared(); + } + return _instance->_domain_participant_impl; +} // list of sensors (should be equal to the list of SensorsRegistry enum ESensors { @@ -841,6 +850,9 @@ void ROS2::Shutdown() { _clock_publisher.reset(); _controller.reset(); _enabled = false; + // finally, release the rest of our resources by destroying our instance + // to prevent from race conditions on system level shutdown of global resources + _instance = nullptr; } } // namespace ros2 diff --git a/LibCarla/source/carla/ros2/ROS2.h b/LibCarla/source/carla/ros2/ROS2.h index 8955d3d1426..4de19d7a2be 100644 --- a/LibCarla/source/carla/ros2/ROS2.h +++ b/LibCarla/source/carla/ros2/ROS2.h @@ -41,6 +41,7 @@ namespace ros2 { class CarlaTransformPublisher; class CarlaClockPublisher; class CarlaEgoVehicleControlSubscriber; + class DdsDomainParticipantImpl; class ROS2 { @@ -54,6 +55,8 @@ class ROS2 return _instance; } + static std::shared_ptr GetDdsDomainParticipant(); + // general void Enable(bool enable); void Shutdown(); @@ -148,6 +151,7 @@ void ProcessDataFromCollisionSensor( ROS2() {}; static std::shared_ptr _instance; + std::shared_ptr _domain_participant_impl; bool _enabled { false }; uint64_t _frame { 0 }; diff --git a/LibCarla/source/carla/ros2/fastdds/carla/ros2/impl/DdsDomainParticipantImpl.cpp b/LibCarla/source/carla/ros2/fastdds/carla/ros2/impl/DdsDomainParticipantImpl.cpp new file mode 100644 index 00000000000..b498e27cc99 --- /dev/null +++ b/LibCarla/source/carla/ros2/fastdds/carla/ros2/impl/DdsDomainParticipantImpl.cpp @@ -0,0 +1,51 @@ +// Copyright (c) 2022 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 "carla/ros2/impl/DdsDomainParticipantImpl.h" + +#include +#include + +#include +#include + +#include "carla/Logging.h" + +namespace carla { +namespace ros2 { + +DdsDomainParticipantImpl::DdsDomainParticipantImpl() { + _factory = eprosima::fastdds::dds::DomainParticipantFactory::get_shared_instance(); + if (_factory == nullptr) { + carla::log_error("DdsDomainParticipantImpl(): Failed to acquire DomainParticipantFactory"); + return; + } + + const char *ros_domain_id_env = std::getenv("ROS_DOMAIN_ID"); + unsigned int ros_domain_id = 0; + if ( ros_domain_id_env != nullptr ) { + try { + ros_domain_id = (unsigned int)(std::atoi(ros_domain_id_env)); + } catch (...) { + ros_domain_id = 0; + } + } + auto pqos = eprosima::fastdds::dds::PARTICIPANT_QOS_DEFAULT; + pqos.name("carla-server"); + _participant = _factory->create_participant(ros_domain_id, pqos); + if (_participant == nullptr) { + carla::log_error("DdsDomainParticipantImpl(): Failed to create DomainParticipant"); + } +} + +DdsDomainParticipantImpl::~DdsDomainParticipantImpl() { + carla::log_warning("DdsDomainParticipantImpl::Destructor()"); + if ((_participant != nullptr) && (_factory != nullptr)) { + _factory->delete_participant(_participant); + _participant=nullptr; + } +} + +} // namespace ros2 +} // namespace carla diff --git a/LibCarla/source/carla/ros2/fastdds/carla/ros2/impl/DdsDomainParticipantImpl.h b/LibCarla/source/carla/ros2/fastdds/carla/ros2/impl/DdsDomainParticipantImpl.h new file mode 100644 index 00000000000..1b8f7612adb --- /dev/null +++ b/LibCarla/source/carla/ros2/fastdds/carla/ros2/impl/DdsDomainParticipantImpl.h @@ -0,0 +1,30 @@ + +// Copyright (c) 2022 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 +#include + +namespace carla { +namespace ros2 { + +class DdsDomainParticipantImpl { +public: + DdsDomainParticipantImpl(); + ~DdsDomainParticipantImpl(); + + eprosima::fastdds::dds::DomainParticipant* GetDomainParticipant() { + return _participant; + } + +private: + eprosima::fastdds::dds::DomainParticipant* _participant{nullptr}; + // keep also a copy of the factory that the underlying DDS is keeping their stuff up + std::shared_ptr _factory; +}; + +} // namespace ros2 +} // namespace carla \ No newline at end of file diff --git a/LibCarla/source/carla/ros2/publishers/CarlaClockPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaClockPublisher.cpp index b59e1f38d19..2c195c61426 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaClockPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaClockPublisher.cpp @@ -13,8 +13,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -30,7 +30,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaClockPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -44,18 +43,12 @@ namespace ros2 { std::cerr << "Invalid TypeSupport" << std::endl; return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant();; + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -63,7 +56,7 @@ namespace ros2 { efd::TopicQos tqos = efd::TOPIC_QOS_DEFAULT; const std::string topic_name { "rt/clock" }; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -157,17 +150,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); } CarlaClockPublisher::CarlaClockPublisher(const CarlaClockPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaCollisionPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaCollisionPublisher.cpp index 2df478c6089..4cb037deb38 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaCollisionPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaCollisionPublisher.cpp @@ -13,8 +13,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -31,7 +31,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaCollisionPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -46,18 +45,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -69,7 +62,7 @@ namespace ros2 { if (!_parent.empty()) topic_name += _parent + "/"; topic_name += _name; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -183,17 +176,16 @@ void CarlaCollisionPublisher::SetData(int32_t seconds, uint32_t nanoseconds, uin if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); } CarlaCollisionPublisher::CarlaCollisionPublisher(const CarlaCollisionPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaDVSCameraPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaDVSCameraPublisher.cpp index 174df73e2af..27b67662f05 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaDVSCameraPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaDVSCameraPublisher.cpp @@ -17,8 +17,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -35,7 +35,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaDVSCameraPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -45,7 +44,6 @@ namespace ros2 { }; struct CarlaCameraInfoPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -56,7 +54,6 @@ namespace ros2 { }; struct CarlaPointCloudPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -85,18 +82,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -110,7 +101,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -134,18 +125,11 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _info->_participant = factory->create_participant(0, pqos); - if (_info->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _info->_type.register_type(_info->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + _info->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _info->_publisher = _info->_participant->create_publisher(pubqos, nullptr); + _info->_publisher = participant->create_publisher(pubqos, nullptr); if (_info->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -159,7 +143,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _info->_topic = _info->_participant->create_topic(topic_name, _info->_type->getName(), tqos); + _info->_topic = participant->create_topic(topic_name, _info->_type->getName(), tqos); if (_info->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -182,18 +166,11 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _point_cloud->_participant = factory->create_participant(0, pqos); - if (_point_cloud->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _point_cloud->_type.register_type(_point_cloud->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + _point_cloud->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _point_cloud->_publisher = _point_cloud->_participant->create_publisher(pubqos, nullptr); + _point_cloud->_publisher = participant->create_publisher(pubqos, nullptr); if (_point_cloud->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -207,7 +184,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _point_cloud->_topic = _point_cloud->_participant->create_topic(topic_name, _point_cloud->_type->getName(), tqos); + _point_cloud->_topic = participant->create_topic(topic_name, _point_cloud->_type->getName(), tqos); if (_point_cloud->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -519,17 +496,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); if (!_info) return; @@ -538,13 +514,10 @@ namespace ros2 { _info->_publisher->delete_datawriter(_info->_datawriter); if (_info->_publisher) - _info->_participant->delete_publisher(_info->_publisher); + participant->delete_publisher(_info->_publisher); if (_info->_topic) - _info->_participant->delete_topic(_info->_topic); - - if (_info->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_info->_participant); + participant->delete_topic(_info->_topic); if (!_point_cloud) return; @@ -553,13 +526,10 @@ namespace ros2 { _point_cloud->_publisher->delete_datawriter(_point_cloud->_datawriter); if (_point_cloud->_publisher) - _point_cloud->_participant->delete_publisher(_point_cloud->_publisher); + participant->delete_publisher(_point_cloud->_publisher); if (_point_cloud->_topic) - _point_cloud->_participant->delete_topic(_point_cloud->_topic); - - if (_point_cloud->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_point_cloud->_participant); + participant->delete_topic(_point_cloud->_topic); } CarlaDVSCameraPublisher::CarlaDVSCameraPublisher(const CarlaDVSCameraPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaDepthCameraPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaDepthCameraPublisher.cpp index 895fab63cba..e742c0f3e2b 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaDepthCameraPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaDepthCameraPublisher.cpp @@ -14,8 +14,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -32,7 +32,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaDepthCameraPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -42,7 +41,6 @@ namespace ros2 { }; struct CarlaCameraInfoPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -72,18 +70,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -97,7 +89,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -121,18 +113,11 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl_info->_participant = factory->create_participant(0, pqos); - if (_impl_info->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl_info->_type.register_type(_impl_info->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + _impl_info->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl_info->_publisher = _impl_info->_participant->create_publisher(pubqos, nullptr); + _impl_info->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl_info->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -146,7 +131,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl_info->_topic = _impl_info->_participant->create_topic(topic_name, _impl_info->_type->getName(), tqos); + _impl_info->_topic = participant->create_topic(topic_name, _impl_info->_type->getName(), tqos); if (_impl_info->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -348,17 +333,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); if (!_impl_info) return; @@ -367,13 +351,10 @@ namespace ros2 { _impl_info->_publisher->delete_datawriter(_impl_info->_datawriter); if (_impl_info->_publisher) - _impl_info->_participant->delete_publisher(_impl_info->_publisher); + participant->delete_publisher(_impl_info->_publisher); if (_impl_info->_topic) - _impl_info->_participant->delete_topic(_impl_info->_topic); - - if (_impl_info->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl_info->_participant); + participant->delete_topic(_impl_info->_topic); } CarlaDepthCameraPublisher::CarlaDepthCameraPublisher(const CarlaDepthCameraPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaGNSSPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaGNSSPublisher.cpp index fc0762d111c..55ab83984f0 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaGNSSPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaGNSSPublisher.cpp @@ -13,8 +13,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -30,7 +30,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaGNSSPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -45,18 +44,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -68,7 +61,7 @@ namespace ros2 { if (!_parent.empty()) topic_name += _parent + "/"; topic_name += _name; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -173,17 +166,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); } CarlaGNSSPublisher::CarlaGNSSPublisher(const CarlaGNSSPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaIMUPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaIMUPublisher.cpp index b7c305eb39c..59217b4676e 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaIMUPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaIMUPublisher.cpp @@ -13,8 +13,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -30,7 +30,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaIMUPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -45,18 +44,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -68,7 +61,7 @@ namespace ros2 { if (!_parent.empty()) topic_name += _parent + "/"; topic_name += _name; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -175,7 +168,7 @@ namespace ros2 { geometry_msgs::msg::Quaternion orientation; const float rx = 0.0f; // pitch - const float ry = (M_PIf32 / 2.0f) - compass; // yaw + const float ry = (float(M_PI_2) / 2.0f) - compass; // yaw const float rz = 0.0f; // roll const float cr = cosf(rz * 0.5f); @@ -206,17 +199,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); } CarlaIMUPublisher::CarlaIMUPublisher(const CarlaIMUPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaISCameraPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaISCameraPublisher.cpp index 6c582a302de..d5087e11825 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaISCameraPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaISCameraPublisher.cpp @@ -14,8 +14,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -31,7 +31,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaISCameraPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -41,7 +40,6 @@ namespace ros2 { }; struct CarlaCameraInfoPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -70,18 +68,12 @@ namespace ros2 { std::cerr << "Invalid TypeSupport" << std::endl; return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -95,7 +87,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -119,18 +111,11 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl_info->_participant = factory->create_participant(0, pqos); - if (_impl_info->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl_info->_type.register_type(_impl_info->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + _impl_info->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl_info->_publisher = _impl_info->_participant->create_publisher(pubqos, nullptr); + _impl_info->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl_info->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -144,7 +129,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl_info->_topic = _impl_info->_participant->create_topic(topic_name, _impl_info->_type->getName(), tqos); + _impl_info->_topic = participant->create_topic(topic_name, _impl_info->_type->getName(), tqos); if (_impl_info->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -347,17 +332,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); if (!_impl_info) return; @@ -366,13 +350,10 @@ namespace ros2 { _impl_info->_publisher->delete_datawriter(_impl_info->_datawriter); if (_impl_info->_publisher) - _impl_info->_participant->delete_publisher(_impl_info->_publisher); + participant->delete_publisher(_impl_info->_publisher); if (_impl_info->_topic) - _impl_info->_participant->delete_topic(_impl_info->_topic); - - if (_impl_info->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl_info->_participant); + participant->delete_topic(_impl_info->_topic); } CarlaISCameraPublisher::CarlaISCameraPublisher(const CarlaISCameraPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaLidarPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaLidarPublisher.cpp index 4a8c5d53a36..2f9c063581b 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaLidarPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaLidarPublisher.cpp @@ -13,8 +13,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -30,7 +30,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaLidarPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -45,18 +44,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -68,7 +61,7 @@ namespace ros2 { if (!_parent.empty()) topic_name += _parent + "/"; topic_name += _name; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -214,17 +207,16 @@ void CarlaLidarPublisher::SetData(int32_t seconds, uint32_t nanoseconds, size_t if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); } CarlaLidarPublisher::CarlaLidarPublisher(const CarlaLidarPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaLineInvasionPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaLineInvasionPublisher.cpp index ce906048c53..2f754b175fd 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaLineInvasionPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaLineInvasionPublisher.cpp @@ -13,8 +13,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -30,7 +30,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaLineInvasionPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -45,18 +44,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -68,7 +61,7 @@ namespace ros2 { if (!_parent.empty()) topic_name += _parent + "/"; topic_name += _name; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -171,17 +164,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); } CarlaLineInvasionPublisher::CarlaLineInvasionPublisher(const CarlaLineInvasionPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaMapSensorPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaMapSensorPublisher.cpp index 536576f94e6..fcd2f250822 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaMapSensorPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaMapSensorPublisher.cpp @@ -13,8 +13,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -30,7 +30,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaMapSensorPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -45,18 +44,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -68,7 +61,7 @@ namespace ros2 { if (!_parent.empty()) topic_name += _parent + "/"; topic_name += _name; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -162,17 +155,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); } CarlaMapSensorPublisher::CarlaMapSensorPublisher(const CarlaMapSensorPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaNormalsCameraPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaNormalsCameraPublisher.cpp index 94dabce727b..74b7f99129e 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaNormalsCameraPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaNormalsCameraPublisher.cpp @@ -14,8 +14,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -32,7 +32,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaNormalsCameraPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -42,7 +41,6 @@ namespace ros2 { }; struct CarlaCameraInfoPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -72,18 +70,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -97,7 +89,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -121,18 +113,11 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl_info->_participant = factory->create_participant(0, pqos); - if (_impl_info->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl_info->_type.register_type(_impl_info->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + _impl_info->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl_info->_publisher = _impl_info->_participant->create_publisher(pubqos, nullptr); + _impl_info->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl_info->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -146,7 +131,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl_info->_topic = _impl_info->_participant->create_topic(topic_name, _impl_info->_type->getName(), tqos); + _impl_info->_topic = participant->create_topic(topic_name, _impl_info->_type->getName(), tqos); if (_impl_info->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -348,17 +333,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); if (!_impl_info) return; @@ -367,13 +351,10 @@ namespace ros2 { _impl_info->_publisher->delete_datawriter(_impl_info->_datawriter); if (_impl_info->_publisher) - _impl_info->_participant->delete_publisher(_impl_info->_publisher); + participant->delete_publisher(_impl_info->_publisher); if (_impl_info->_topic) - _impl_info->_participant->delete_topic(_impl_info->_topic); - - if (_impl_info->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl_info->_participant); + participant->delete_topic(_impl_info->_topic); } CarlaNormalsCameraPublisher::CarlaNormalsCameraPublisher(const CarlaNormalsCameraPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaOpticalFlowCameraPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaOpticalFlowCameraPublisher.cpp index afa2e125c10..c6b93de7555 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaOpticalFlowCameraPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaOpticalFlowCameraPublisher.cpp @@ -15,8 +15,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -36,7 +36,6 @@ namespace ros2 { namespace efd = eprosima::fastdds::dds; using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaOpticalFlowCameraPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -46,7 +45,6 @@ namespace ros2 { }; struct CarlaCameraInfoPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -76,18 +74,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -101,7 +93,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -125,18 +117,11 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl_info->_participant = factory->create_participant(0, pqos); - if (_impl_info->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl_info->_type.register_type(_impl_info->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + _impl_info->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl_info->_publisher = _impl_info->_participant->create_publisher(pubqos, nullptr); + _impl_info->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl_info->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -150,7 +135,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl_info->_topic = _impl_info->_participant->create_topic(topic_name, _impl_info->_type->getName(), tqos); + _impl_info->_topic = participant->create_topic(topic_name, _impl_info->_type->getName(), tqos); if (_impl_info->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -430,17 +415,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); if (!_impl_info) return; @@ -449,13 +433,10 @@ namespace ros2 { _impl_info->_publisher->delete_datawriter(_impl_info->_datawriter); if (_impl_info->_publisher) - _impl_info->_participant->delete_publisher(_impl_info->_publisher); + participant->delete_publisher(_impl_info->_publisher); if (_impl_info->_topic) - _impl_info->_participant->delete_topic(_impl_info->_topic); - - if (_impl_info->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl_info->_participant); + participant->delete_topic(_impl_info->_topic); } CarlaOpticalFlowCameraPublisher::CarlaOpticalFlowCameraPublisher(const CarlaOpticalFlowCameraPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaRGBCameraPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaRGBCameraPublisher.cpp index 36a6d7ad14c..e7e3f4039c2 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaRGBCameraPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaRGBCameraPublisher.cpp @@ -14,8 +14,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -32,7 +32,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaRGBCameraPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -42,7 +41,6 @@ namespace ros2 { }; struct CarlaCameraInfoPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -72,18 +70,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -97,7 +89,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -121,18 +113,11 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl_info->_participant = factory->create_participant(0, pqos); - if (_impl_info->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl_info->_type.register_type(_impl_info->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + _impl_info->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl_info->_publisher = _impl_info->_participant->create_publisher(pubqos, nullptr); + _impl_info->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl_info->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -146,7 +131,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl_info->_topic = _impl_info->_participant->create_topic(topic_name, _impl_info->_type->getName(), tqos); + _impl_info->_topic = participant->create_topic(topic_name, _impl_info->_type->getName(), tqos); if (_impl_info->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -350,17 +335,16 @@ void CarlaRGBCameraPublisher::SetImageData(int32_t seconds, uint32_t nanoseconds if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); if (!_impl_info) return; @@ -369,13 +353,10 @@ void CarlaRGBCameraPublisher::SetImageData(int32_t seconds, uint32_t nanoseconds _impl_info->_publisher->delete_datawriter(_impl_info->_datawriter); if (_impl_info->_publisher) - _impl_info->_participant->delete_publisher(_impl_info->_publisher); + participant->delete_publisher(_impl_info->_publisher); if (_impl_info->_topic) - _impl_info->_participant->delete_topic(_impl_info->_topic); - - if (_impl_info->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl_info->_participant); + participant->delete_topic(_impl_info->_topic); } CarlaRGBCameraPublisher::CarlaRGBCameraPublisher(const CarlaRGBCameraPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaRadarPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaRadarPublisher.cpp index 5ef6fd3e95b..5b6704b0ccd 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaRadarPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaRadarPublisher.cpp @@ -14,8 +14,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -32,7 +32,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaRadarPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -54,18 +53,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -77,7 +70,7 @@ namespace ros2 { if (!_parent.empty()) topic_name += _parent + "/"; topic_name += _name; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -241,17 +234,16 @@ void CarlaRadarPublisher::SetData(int32_t seconds, uint32_t nanoseconds, size_t if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); } CarlaRadarPublisher::CarlaRadarPublisher(const CarlaRadarPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaSSCameraPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaSSCameraPublisher.cpp index b096a6b80d8..2b67d9a2631 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaSSCameraPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaSSCameraPublisher.cpp @@ -14,8 +14,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -31,7 +31,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaSSCameraPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -41,7 +40,6 @@ namespace ros2 { }; struct CarlaCameraInfoPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -70,18 +68,12 @@ namespace ros2 { std::cerr << "Invalid TypeSupport" << std::endl; return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -95,7 +87,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -119,18 +111,11 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl_info->_participant = factory->create_participant(0, pqos); - if (_impl_info->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl_info->_type.register_type(_impl_info->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + _impl_info->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl_info->_publisher = _impl_info->_participant->create_publisher(pubqos, nullptr); + _impl_info->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl_info->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -144,7 +129,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl_info->_topic = _impl_info->_participant->create_topic(topic_name, _impl_info->_type->getName(), tqos); + _impl_info->_topic = participant->create_topic(topic_name, _impl_info->_type->getName(), tqos); if (_impl_info->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -347,17 +332,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); if (!_impl_info) return; @@ -366,13 +350,10 @@ namespace ros2 { _impl_info->_publisher->delete_datawriter(_impl_info->_datawriter); if (_impl_info->_publisher) - _impl_info->_participant->delete_publisher(_impl_info->_publisher); + participant->delete_publisher(_impl_info->_publisher); if (_impl_info->_topic) - _impl_info->_participant->delete_topic(_impl_info->_topic); - - if (_impl_info->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl_info->_participant); + participant->delete_topic(_impl_info->_topic); } CarlaSSCameraPublisher::CarlaSSCameraPublisher(const CarlaSSCameraPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaSemanticLidarPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaSemanticLidarPublisher.cpp index 2a64776d0e0..65b6ee8ae6a 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaSemanticLidarPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaSemanticLidarPublisher.cpp @@ -13,8 +13,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -31,7 +31,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaSemanticLidarPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -45,18 +44,12 @@ namespace ros2 { std::cerr << "Invalid TypeSupport" << std::endl; return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -68,7 +61,7 @@ namespace ros2 { if (!_parent.empty()) topic_name += _parent + "/"; topic_name += _name; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -224,17 +217,16 @@ void CarlaSemanticLidarPublisher::SetData(int32_t seconds, uint32_t nanoseconds, if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); } CarlaSemanticLidarPublisher::CarlaSemanticLidarPublisher(const CarlaSemanticLidarPublisher& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaSpeedometerSensor.cpp b/LibCarla/source/carla/ros2/publishers/CarlaSpeedometerSensor.cpp index 042e1dcfc7c..0abf556012b 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaSpeedometerSensor.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaSpeedometerSensor.cpp @@ -13,8 +13,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -30,7 +30,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaSpeedometerSensorImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -44,18 +43,12 @@ namespace ros2 { std::cerr << "Invalid TypeSupport" << std::endl; return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -67,7 +60,7 @@ namespace ros2 { if (!_parent.empty()) topic_name += _parent + "/"; topic_name += _name; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -161,17 +154,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); } CarlaSpeedometerSensor::CarlaSpeedometerSensor(const CarlaSpeedometerSensor& other) { diff --git a/LibCarla/source/carla/ros2/publishers/CarlaTransformPublisher.cpp b/LibCarla/source/carla/ros2/publishers/CarlaTransformPublisher.cpp index caf9d5339d5..3a3ed20bf0b 100644 --- a/LibCarla/source/carla/ros2/publishers/CarlaTransformPublisher.cpp +++ b/LibCarla/source/carla/ros2/publishers/CarlaTransformPublisher.cpp @@ -13,8 +13,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -30,7 +30,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaTransformPublisherImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Publisher* _publisher { nullptr }; efd::Topic* _topic { nullptr }; efd::DataWriter* _datawriter { nullptr }; @@ -50,18 +49,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::PublisherQos pubqos = efd::PUBLISHER_QOS_DEFAULT; - _impl->_publisher = _impl->_participant->create_publisher(pubqos, nullptr); + _impl->_publisher = participant->create_publisher(pubqos, nullptr); if (_impl->_publisher == nullptr) { std::cerr << "Failed to create Publisher" << std::endl; return false; @@ -69,7 +62,7 @@ namespace ros2 { efd::TopicQos tqos = efd::TOPIC_QOS_DEFAULT; const std::string topic_name { "rt/tf" }; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -161,9 +154,9 @@ namespace ros2 { const float ty = *translation++; const float tz = *translation++; - const float rx = ((*rotation++) * -1.0f) * (M_PIf32 / 180.0f); - const float ry = ((*rotation++) * -1.0f) * (M_PIf32 / 180.0f); - const float rz = *rotation++ * (M_PIf32 / 180.0f); + const float rx = ((*rotation++) * -1.0f) * (float(M_PI_2) / 180.0f); + const float ry = ((*rotation++) * -1.0f) * (float(M_PI_2) / 180.0f); + const float rz = *rotation++ * (float(M_PI_2) / 180.0f); const float cr = cosf(rz * 0.5f); const float sr = sinf(rz * 0.5f); @@ -211,17 +204,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datawriter) _impl->_publisher->delete_datawriter(_impl->_datawriter); if (_impl->_publisher) - _impl->_participant->delete_publisher(_impl->_publisher); + participant->delete_publisher(_impl->_publisher); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); } CarlaTransformPublisher::CarlaTransformPublisher(const CarlaTransformPublisher& other) { diff --git a/LibCarla/source/carla/ros2/subscribers/CarlaEgoVehicleControlSubscriber.cpp b/LibCarla/source/carla/ros2/subscribers/CarlaEgoVehicleControlSubscriber.cpp index 4a31b7e7046..24af107565f 100644 --- a/LibCarla/source/carla/ros2/subscribers/CarlaEgoVehicleControlSubscriber.cpp +++ b/LibCarla/source/carla/ros2/subscribers/CarlaEgoVehicleControlSubscriber.cpp @@ -13,8 +13,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -31,7 +31,6 @@ namespace ros2 { using erc = eprosima::fastrtps::types::ReturnCode_t; struct CarlaEgoVehicleControlSubscriberImpl { - efd::DomainParticipant* _participant { nullptr }; efd::Subscriber* _subscriber { nullptr }; efd::Topic* _topic { nullptr }; efd::DataReader* _datareader { nullptr }; @@ -50,18 +49,12 @@ namespace ros2 { return false; } - efd::DomainParticipantQos pqos = efd::PARTICIPANT_QOS_DEFAULT; - pqos.name(_name); - auto factory = efd::DomainParticipantFactory::get_instance(); - _impl->_participant = factory->create_participant(0, pqos); - if (_impl->_participant == nullptr) { - std::cerr << "Failed to create DomainParticipant" << std::endl; - return false; - } - _impl->_type.register_type(_impl->_participant); + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); + + _impl->_type.register_type(participant); efd::SubscriberQos subqos = efd::SUBSCRIBER_QOS_DEFAULT; - _impl->_subscriber = _impl->_participant->create_subscriber(subqos, nullptr); + _impl->_subscriber = participant->create_subscriber(subqos, nullptr); if (_impl->_subscriber == nullptr) { std::cerr << "Failed to create Subscriber" << std::endl; return false; @@ -75,7 +68,7 @@ namespace ros2 { topic_name += _parent + "/"; topic_name += _name; topic_name += publisher_type; - _impl->_topic = _impl->_participant->create_topic(topic_name, _impl->_type->getName(), tqos); + _impl->_topic = participant->create_topic(topic_name, _impl->_type->getName(), tqos); if (_impl->_topic == nullptr) { std::cerr << "Failed to create Topic" << std::endl; return false; @@ -191,17 +184,16 @@ namespace ros2 { if (!_impl) return; + auto participant = ROS2::GetDdsDomainParticipant()->GetDomainParticipant(); if (_impl->_datareader) _impl->_subscriber->delete_datareader(_impl->_datareader); if (_impl->_subscriber) - _impl->_participant->delete_subscriber(_impl->_subscriber); + participant->delete_subscriber(_impl->_subscriber); if (_impl->_topic) - _impl->_participant->delete_topic(_impl->_topic); + participant->delete_topic(_impl->_topic); - if (_impl->_participant) - efd::DomainParticipantFactory::get_instance()->delete_participant(_impl->_participant); } CarlaEgoVehicleControlSubscriber::CarlaEgoVehicleControlSubscriber(const CarlaEgoVehicleControlSubscriber& other) { diff --git a/LibCarla/source/carla/rpc/BoundingBox.h b/LibCarla/source/carla/rpc/BoundingBox.h new file mode 100644 index 00000000000..9bdf399c3e8 --- /dev/null +++ b/LibCarla/source/carla/rpc/BoundingBox.h @@ -0,0 +1,17 @@ +// Copyright (c) 2019 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/geom/BoundingBox.h" + +namespace carla { +namespace rpc { + + using BoundingBox = geom::BoundingBox; + +} // namespace rpc +} // namespace carla diff --git a/LibCarla/source/carla/rss/RssCheck.cpp b/LibCarla/source/carla/rss/RssCheck.cpp index 713cf9a62e2..fd8a781a755 100644 --- a/LibCarla/source/carla/rss/RssCheck.cpp +++ b/LibCarla/source/carla/rss/RssCheck.cpp @@ -57,14 +57,14 @@ EgoDynamicsOnRoute::EgoDynamicsOnRoute() time_since_epoch_check_end_ms(0.), ego_speed(0.), min_stopping_distance(0.), - ego_center({0., 0., 0.}), + ego_center(), ego_heading(0.), ego_heading_change(0.), ego_steering_angle(0.), ego_center_within_route(false), crossing_border(false), route_heading(0.), - route_nominal_center({0., 0., 0.}), + route_nominal_center(), heading_diff(0.), route_speed_lat(0.), route_speed_lon(0.), @@ -73,6 +73,12 @@ EgoDynamicsOnRoute::EgoDynamicsOnRoute() avg_route_accel_lat(0.), avg_route_accel_lon(0.) { timestamp.elapsed_seconds = 0.; + ego_center.x = 0.; + ego_center.y = 0.; + ego_center.z = 0., + route_nominal_center.x = 0.; + route_nominal_center.y = 0.; + route_nominal_center.z = 0.; } std::shared_ptr getLogger() { diff --git a/LibCarla/source/carla/streaming/detail/tcp/Client.cpp b/LibCarla/source/carla/streaming/detail/tcp/Client.cpp index e3982f614f3..47f9e4c25d1 100644 --- a/LibCarla/source/carla/streaming/detail/tcp/Client.cpp +++ b/LibCarla/source/carla/streaming/detail/tcp/Client.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -86,7 +85,6 @@ namespace tcp { void Client::Connect() { auto self = shared_from_this(); - boost::asio::post(_strand, [this, self]() { if (_done) { return; } @@ -139,18 +137,15 @@ namespace tcp { log_debug("streaming client: connecting to", ep); _socket.async_connect(ep, boost::asio::bind_executor(_strand, handle_connect)); - }); } void Client::Stop() { _connection_timer.cancel(); auto self = shared_from_this(); - boost::asio::post(_strand, [this, self]() { _done = true; if (_socket.is_open()) { _socket.close(); } - }); } void Client::Reconnect() { @@ -165,7 +160,6 @@ namespace tcp { void Client::ReadData() { auto self = shared_from_this(); - boost::asio::post(_strand, [this, self]() { if (_done) { return; } @@ -182,7 +176,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"); - boost::asio::post(_strand, [self, message]() { self->_callback(message->pop()); }); + self->_callback(message->pop()); ReadData(); } else { // As usual, if anything fails start over from the very top. @@ -219,7 +213,6 @@ namespace tcp { _socket, message->size_as_buffer(), boost::asio::bind_executor(_strand, handle_read_header)); - }); } } // namespace tcp diff --git a/LibCarla/source/carla/streaming/detail/tcp/ServerSession.cpp b/LibCarla/source/carla/streaming/detail/tcp/ServerSession.cpp index a726fbf1cf7..8851f1fa5f2 100644 --- a/LibCarla/source/carla/streaming/detail/tcp/ServerSession.cpp +++ b/LibCarla/source/carla/streaming/detail/tcp/ServerSession.cpp @@ -79,7 +79,6 @@ namespace tcp { DEBUG_ASSERT(message != nullptr); DEBUG_ASSERT(!message->empty()); auto self = shared_from_this(); - boost::asio::post(_strand, [=]() { if (!_socket.is_open()) { return; } @@ -111,11 +110,8 @@ namespace tcp { log_debug("session", _session_id, ": sending message of", message->size(), "bytes"); _deadline.expires_from_now(_timeout); - boost::asio::async_write( - _socket, - message->GetBufferSequence(), - handle_sent); - }); + boost::asio::async_write(_socket, message->GetBufferSequence(), + boost::asio::bind_executor(_strand, handle_sent)); } void ServerSession::Close() { diff --git a/LibCarla/source/test/client/test_image.cpp b/LibCarla/source/test/client/test_image.cpp index bda3d7bb634..0d710ca438f 100644 --- a/LibCarla/source/test/client/test_image.cpp +++ b/LibCarla/source/test/client/test_image.cpp @@ -14,7 +14,6 @@ template struct TestImage { - TestImage(TestImage &&) = default; using pixel_type = PixelT; std::unique_ptr data; ViewT view; @@ -28,7 +27,7 @@ static auto MakeTestImage(size_t width, size_t height) { height, reinterpret_cast(data.get()), static_cast(sizeof(PixelT) * width)); - return TestImage{std::move(data), view}; + return TestImage{.data = std::move(data), .view = view}; } #ifndef PLATFORM_WINDOWS diff --git a/PythonAPI/carla/agents/navigation/basic_agent.py b/PythonAPI/carla/agents/navigation/basic_agent.py index 2d0b9b91a1a..9f34fef796d 100644 --- a/PythonAPI/carla/agents/navigation/basic_agent.py +++ b/PythonAPI/carla/agents/navigation/basic_agent.py @@ -6,7 +6,7 @@ """ This module implements an agent that roams around a track following random waypoints and avoiding other vehicles. The agent also responds to traffic lights. -It can also make use of the global route planner to follow a specifed route +It can also make use of the global route planner to follow a specified route """ import carla @@ -15,13 +15,12 @@ from agents.navigation.local_planner import LocalPlanner, RoadOption from agents.navigation.global_route_planner import GlobalRoutePlanner from agents.tools.misc import (get_speed, is_within_distance, - get_trafficlight_trigger_location, - compute_distance) + get_trafficlight_trigger_location) from agents.tools.hints import ObstacleDetectionResult, TrafficLightDetectionResult -class BasicAgent(object): +class BasicAgent: """ BasicAgent implements an agent that navigates the scene. This agent respects traffic lights and other vehicles, but ignores stop signs. @@ -31,7 +30,7 @@ class BasicAgent(object): def __init__(self, vehicle, target_speed=20, opt_dict={}, map_inst=None, grp_inst=None): """ - Initialization the agent paramters, the local and the global planner. + Initialization the agent parameters, the local and the global planner. :param vehicle: actor to apply to agent logic onto :param target_speed: speed (in Km/h) at which the vehicle will move @@ -102,7 +101,7 @@ def __init__(self, vehicle, target_speed=20, opt_dict={}, map_inst=None, grp_ins # Get the static elements of the scene self._lights_list = self._world.get_actors().filter("*traffic_light*") - self._lights_map = {} # Dictionary mapping a traffic light to a wp corrspoing to its trigger volume location + self._lights_map = {} # Dictionary mapping a traffic light to a wp corresponding to its trigger volume location def add_emergency_stop(self, control): """ @@ -139,14 +138,14 @@ def get_local_planner(self): def get_global_planner(self): """Get method for protected member local planner""" return self._global_planner - + def set_destination(self, end_location, start_location=None, clean_queue=True): # type: (carla.Location, carla.Location | None, bool) -> None """ This method creates a list of waypoints between a starting and ending location, based on the route returned by the global router, and adds it to the local planner. - If no starting location is passed and `clean_queue` is True, the vehicle local planner's - target location is chosen, which corresponds (by default), to a location about 5 meters + If no starting location is passed and `clean_queue` is True, the vehicle local planner's + target location is chosen, which corresponds (by default), to a location about 5 meters in front of the vehicle. If `clean_queue` is False the newly planned route will be appended to the current route. @@ -157,19 +156,19 @@ def set_destination(self, end_location, start_location=None, clean_queue=True): if not start_location: if clean_queue and self._local_planner.target_waypoint: # Plan from the waypoint in front of the vehicle onwards - start_location = self._local_planner.target_waypoint.transform.location + start_location = self._local_planner.target_waypoint.transform.location elif not clean_queue and self._local_planner._waypoints_queue: # Append to the current plan start_location = self._local_planner._waypoints_queue[-1][0].transform.location else: # no target_waypoint or _waypoints_queue empty, use vehicle location - start_location = self._vehicle.get_location() + start_location = self._vehicle.get_location() start_waypoint = self._map.get_waypoint(start_location) end_waypoint = self._map.get_waypoint(end_location) - + route_trace = self.trace_route(start_waypoint, end_waypoint) self._local_planner.set_global_plan(route_trace, clean_queue=clean_queue) - + def set_global_plan(self, plan, stop_waypoint_creation=True, clean_queue=True): """ Adds a specific plan to the agent. @@ -325,7 +324,7 @@ def _vehicle_obstacle_detected(self, vehicle_list=None, max_distance=None, up_an """ Method to check if there is a vehicle in front of the agent blocking its path. - :param vehicle_list (list of carla.Vehicle): list contatining vehicle objects. + :param vehicle_list (list of carla.Vehicle): list containing vehicle objects. If None, all vehicle in the scene are used :param max_distance: max freespace to check for obstacles. If None, the base threshold value is used @@ -354,7 +353,7 @@ def get_route_polygon(): return None return Polygon(route_bb) - + if self._ignore_vehicles: return ObstacleDetectionResult(False, None, -1) @@ -404,7 +403,7 @@ def get_route_polygon(): target_polygon = Polygon(target_list) if route_polygon.intersects(target_polygon): - return ObstacleDetectionResult(True, target_vehicle, compute_distance(target_vehicle.get_location(), ego_location)) + return ObstacleDetectionResult(True, target_vehicle, target_vehicle.get_location().distance(ego_location)) # Simplified approach, using only the plan waypoints (similar to TM) else: @@ -425,13 +424,15 @@ def get_route_polygon(): ) if is_within_distance(target_rear_transform, ego_front_transform, max_distance, [low_angle_th, up_angle_th]): - return ObstacleDetectionResult(True, target_vehicle, compute_distance(target_transform.location, ego_transform.location)) + return ObstacleDetectionResult(True, target_vehicle, target_transform.location.distance(ego_transform.location)) return ObstacleDetectionResult(False, None, -1) - def _generate_lane_change_path(self, waypoint, direction='left', distance_same_lane=10, + @staticmethod + def _generate_lane_change_path(waypoint, direction='left', distance_same_lane=10, distance_other_lane=25, lane_change_distance=25, check=True, lane_changes=1, step_distance=2): + # type: (carla.Waypoint, str, float, float, float, bool, int, float) -> list[tuple[carla.Waypoint, RoadOption]] """ This methods generates a path that results in a lane change. Use the different distances to fine-tune the maneuver. diff --git a/PythonAPI/carla/agents/navigation/behavior_agent.py b/PythonAPI/carla/agents/navigation/behavior_agent.py index 3e52fafd392..f4cc1bf2795 100644 --- a/PythonAPI/carla/agents/navigation/behavior_agent.py +++ b/PythonAPI/carla/agents/navigation/behavior_agent.py @@ -8,14 +8,13 @@ waypoints and avoiding other vehicles. The agent also responds to traffic lights, traffic signs, and has different possible configurations. """ -import random import numpy as np import carla from agents.navigation.basic_agent import BasicAgent from agents.navigation.local_planner import RoadOption from agents.navigation.behavior_types import Cautious, Aggressive, Normal -from agents.tools.misc import get_speed, positive, is_within_distance, compute_distance +from agents.tools.misc import get_speed, positive class BehaviorAgent(BasicAgent): """ diff --git a/PythonAPI/carla/agents/navigation/behavior_types.py b/PythonAPI/carla/agents/navigation/behavior_types.py index 3008f9f73bf..9eb81dd21ea 100644 --- a/PythonAPI/carla/agents/navigation/behavior_types.py +++ b/PythonAPI/carla/agents/navigation/behavior_types.py @@ -4,7 +4,7 @@ """ This module contains the different parameters sets for each behavior. """ -class Cautious(object): +class Cautious: """Class for Cautious agent.""" max_speed = 40 speed_lim_dist = 6 @@ -15,7 +15,7 @@ class Cautious(object): tailgate_counter = 0 -class Normal(object): +class Normal: """Class for Normal agent.""" max_speed = 50 speed_lim_dist = 3 @@ -26,7 +26,7 @@ class Normal(object): tailgate_counter = 0 -class Aggressive(object): +class Aggressive: """Class for Aggressive agent.""" max_speed = 70 speed_lim_dist = 1 diff --git a/PythonAPI/carla/agents/navigation/constant_velocity_agent.py b/PythonAPI/carla/agents/navigation/constant_velocity_agent.py index 8d3b1c5aa8f..c6e0e24468f 100644 --- a/PythonAPI/carla/agents/navigation/constant_velocity_agent.py +++ b/PythonAPI/carla/agents/navigation/constant_velocity_agent.py @@ -6,7 +6,7 @@ """ This module implements an agent that roams around a track following random waypoints and avoiding other vehicles. The agent also responds to traffic lights. -It can also make use of the global route planner to follow a specifed route +It can also make use of the global route planner to follow a specified route """ import carla diff --git a/PythonAPI/carla/agents/navigation/controller.py b/PythonAPI/carla/agents/navigation/controller.py index a87488c748f..0b23d8571ec 100644 --- a/PythonAPI/carla/agents/navigation/controller.py +++ b/PythonAPI/carla/agents/navigation/controller.py @@ -12,7 +12,7 @@ from agents.tools.misc import get_speed -class VehiclePIDController(): +class VehiclePIDController: """ VehiclePIDController is the combination of two PID controllers (lateral and longitudinal) to perform the @@ -105,7 +105,7 @@ def set_offset(self, offset): self._lat_controller.set_offset(offset) -class PIDLongitudinalController(): +class PIDLongitudinalController: """ PIDLongitudinalController implements longitudinal control using a PID. """ @@ -171,7 +171,7 @@ def change_parameters(self, K_P, K_I, K_D, dt): self._dt = dt -class PIDLateralController(): +class PIDLateralController: """ PIDLateralController implements lateral control using a PID. """ @@ -199,7 +199,7 @@ def __init__(self, vehicle, offset=0, K_P=1.0, K_I=0.0, K_D=0.0, dt=0.03): def run_step(self, waypoint): """ Execute one step of lateral control to steer - the vehicle towards a certain waypoin. + the vehicle towards a certain waypoint. :param waypoint: target waypoint :return: steering control in the range [-1, 1] where: diff --git a/PythonAPI/carla/agents/navigation/global_route_planner.py b/PythonAPI/carla/agents/navigation/global_route_planner.py index 7bc2a5a93bb..47310b84c18 100644 --- a/PythonAPI/carla/agents/navigation/global_route_planner.py +++ b/PythonAPI/carla/agents/navigation/global_route_planner.py @@ -14,20 +14,55 @@ import carla from agents.navigation.local_planner import RoadOption -from agents.tools.misc import vector -class GlobalRoutePlanner(object): +# Python 2 compatibility +TYPE_CHECKING = False +if TYPE_CHECKING: + import sys + if sys.version_info >= (3, 11): + from typing import TypedDict, NotRequired + elif sys.version_info >= (3, 8): + from typing import TypedDict + from typing_extensions import NotRequired + else: + from typing_extensions import TypedDict, NotRequired + + TopologyDict = TypedDict('TopologyDict', + { + 'entry': carla.Waypoint, + 'exit': carla.Waypoint, + 'entryxyz': tuple[float, float, float], + 'exitxyz': tuple[float, float, float], + 'path': list[carla.Waypoint] + }) + + EdgeDict = TypedDict('EdgeDict', + { + 'length': int, + 'path': list[carla.Waypoint], + 'entry_waypoint': carla.Waypoint, + 'exit_waypoint': carla.Waypoint, + 'entry_vector': np.ndarray, + 'exit_vector': np.ndarray, + 'net_vector': list[float], + 'intersection': bool, + 'type': RoadOption, + 'change_waypoint': NotRequired[carla.Waypoint] + }) + +class GlobalRoutePlanner: """ This class provides a very high level route plan. """ def __init__(self, wmap, sampling_resolution): + # type: (carla.Map, float) -> None self._sampling_resolution = sampling_resolution self._wmap = wmap - self._topology = None - self._graph = None - self._id_map = None - self._road_id_to_edge = None + self._topology = [] # type: list[TopologyDict] + self._graph = None # type: nx.DiGraph # type: ignore[assignment] + self._id_map = None # type: dict[tuple[float, float, float], int] # type: ignore[assignment] + self._road_id_to_edge = None # type: dict[int, dict[int, dict[int, tuple[int, int]]]] # type: ignore[assignment] self._intersection_end_node = -1 self._previous_decision = RoadOption.VOID @@ -39,28 +74,29 @@ def __init__(self, wmap, sampling_resolution): self._lane_change_link() def trace_route(self, origin, destination): + # type: (carla.Location, carla.Location) -> list[tuple[carla.Waypoint, RoadOption]] """ This method returns list of (carla.Waypoint, RoadOption) from origin to destination """ - route_trace = [] + route_trace = [] # type: list[tuple[carla.Waypoint, RoadOption]] route = self._path_search(origin, destination) current_waypoint = self._wmap.get_waypoint(origin) destination_waypoint = self._wmap.get_waypoint(destination) for i in range(len(route) - 1): road_option = self._turn_decision(i, route) - edge = self._graph.edges[route[i], route[i+1]] - path = [] + edge = self._graph.edges[route[i], route[i + 1]] # type: EdgeDict + path = [] # type: list[carla.Waypoint] if edge['type'] != RoadOption.LANEFOLLOW and edge['type'] != RoadOption.VOID: route_trace.append((current_waypoint, road_option)) exit_wp = edge['exit_waypoint'] n1, n2 = self._road_id_to_edge[exit_wp.road_id][exit_wp.section_id][exit_wp.lane_id] - next_edge = self._graph.edges[n1, n2] + next_edge = self._graph.edges[n1, n2] # type: EdgeDict if next_edge['path']: closest_index = self._find_closest_in_list(current_waypoint, next_edge['path']) - closest_index = min(len(next_edge['path'])-1, closest_index+5) + closest_index = min(len(next_edge['path']) - 1, closest_index + 5) current_waypoint = next_edge['path'][closest_index] else: current_waypoint = next_edge['exit_waypoint'] @@ -72,9 +108,11 @@ def trace_route(self, origin, destination): for waypoint in path[closest_index:]: current_waypoint = waypoint route_trace.append((current_waypoint, road_option)) - if len(route)-i <= 2 and waypoint.transform.location.distance(destination) < 2*self._sampling_resolution: + if len(route) - i <= 2 and waypoint.transform.location.distance( + destination) < 2 * self._sampling_resolution: break - elif len(route)-i <= 2 and current_waypoint.road_id == destination_waypoint.road_id and current_waypoint.section_id == destination_waypoint.section_id and current_waypoint.lane_id == destination_waypoint.lane_id: + elif len( + route) - i <= 2 and current_waypoint.road_id == destination_waypoint.road_id and current_waypoint.section_id == destination_waypoint.section_id and current_waypoint.lane_id == destination_waypoint.lane_id: destination_index = self._find_closest_in_list(destination_waypoint, path) if closest_index > destination_index: break @@ -101,7 +139,7 @@ def _build_topology(self): # Rounding off to avoid floating point imprecision x1, y1, z1, x2, y2, z2 = np.round([l1.x, l1.y, l1.z, l2.x, l2.y, l2.z], 0) wp1.transform.location, wp2.transform.location = l1, l2 - seg_dict = dict() + seg_dict = dict() # type: TopologyDict # type: ignore[assignment] seg_dict['entry'], seg_dict['exit'] = wp1, wp2 seg_dict['entryxyz'], seg_dict['exitxyz'] = (x1, y1, z1), (x2, y2, z2) seg_dict['path'] = [] @@ -163,6 +201,7 @@ def _build_graph(self): entry_carla_vector = entry_wp.transform.rotation.get_forward_vector() exit_carla_vector = exit_wp.transform.rotation.get_forward_vector() + net_carla_vector = (exit_wp.transform.location - entry_wp.transform.location).make_unit_vector() # Adding edge with attributes self._graph.add_edge( @@ -173,7 +212,7 @@ def _build_graph(self): [entry_carla_vector.x, entry_carla_vector.y, entry_carla_vector.z]), exit_vector=np.array( [exit_carla_vector.x, exit_carla_vector.y, exit_carla_vector.z]), - net_vector=vector(entry_wp.transform.location, exit_wp.transform.location), + net_vector=[net_carla_vector.x, net_carla_vector.y, net_carla_vector.z], intersection=intersection, type=RoadOption.LANEFOLLOW) def _find_loose_ends(self): @@ -198,10 +237,10 @@ def _find_loose_ends(self): if section_id not in self._road_id_to_edge[road_id]: self._road_id_to_edge[road_id][section_id] = dict() n1 = self._id_map[exit_xyz] - n2 = -1*count_loose_ends + n2 = -1 * count_loose_ends self._road_id_to_edge[road_id][section_id][lane_id] = (n1, n2) next_wp = end_wp.next(hop_resolution) - path = [] + path = [] # type: list[carla.Waypoint] while next_wp is not None and next_wp \ and next_wp[0].road_id == road_id \ and next_wp[0].section_id == section_id \ @@ -263,12 +302,13 @@ def _lane_change_link(self): break def _localize(self, location): + # type: (carla.Location) -> None | tuple[int, int] """ This function finds the road segment that a given location is part of, returning the edge it belongs to """ waypoint = self._wmap.get_waypoint(location) - edge = None + edge = None # type: None | tuple[int, int] try: edge = self._road_id_to_edge[waypoint.road_id][waypoint.section_id][waypoint.lane_id] except KeyError: @@ -282,9 +322,10 @@ def _distance_heuristic(self, n1, n2): """ l1 = np.array(self._graph.nodes[n1]['vertex']) l2 = np.array(self._graph.nodes[n2]['vertex']) - return np.linalg.norm(l1-l2) + return np.linalg.norm(l1 - l2) def _path_search(self, origin, destination): + # type: (carla.Location, carla.Location) -> list[int] """ This function finds the shortest path connecting origin and destination using A* search with distance heuristic. @@ -302,6 +343,7 @@ def _path_search(self, origin, destination): return route def _successive_last_intersection_edge(self, index, route): + # type: (int, list[int]) -> tuple[int | None, EdgeDict | None] """ This method returns the last successive intersection edge from a starting index on the route. @@ -309,10 +351,10 @@ def _successive_last_intersection_edge(self, index, route): proper turn decisions. """ - last_intersection_edge = None + last_intersection_edge = None # type: EdgeDict | None last_node = None - for node1, node2 in [(route[i], route[i+1]) for i in range(index, len(route)-1)]: - candidate_edge = self._graph.edges[node1, node2] + for node1, node2 in [(route[i], route[i + 1]) for i in range(index, len(route) - 1)]: + candidate_edge = self._graph.edges[node1, node2] # type: EdgeDict if node1 == route[index]: last_intersection_edge = candidate_edge if candidate_edge['type'] == RoadOption.LANEFOLLOW and candidate_edge['intersection']: @@ -324,16 +366,17 @@ def _successive_last_intersection_edge(self, index, route): return last_node, last_intersection_edge def _turn_decision(self, index, route, threshold=math.radians(35)): + # type: (int, list[int], float) -> RoadOption """ This method returns the turn decision (RoadOption) for pair of edges around current index of route list """ decision = None - previous_node = route[index-1] + previous_node = route[index - 1] current_node = route[index] - next_node = route[index+1] - next_edge = self._graph.edges[current_node, next_node] + next_node = route[index + 1] + next_edge = self._graph.edges[current_node, next_node] # type: EdgeDict if index > 0: if self._previous_decision != RoadOption.VOID \ and self._intersection_end_node > 0 \ @@ -343,7 +386,7 @@ def _turn_decision(self, index, route, threshold=math.radians(35)): decision = self._previous_decision else: self._intersection_end_node = -1 - current_edge = self._graph.edges[previous_node, current_node] + current_edge = self._graph.edges[previous_node, current_node] # type: EdgeDict calculate_turn = current_edge['type'] == RoadOption.LANEFOLLOW and not current_edge[ 'intersection'] and next_edge['type'] == RoadOption.LANEFOLLOW and next_edge['intersection'] if calculate_turn: @@ -358,12 +401,12 @@ def _turn_decision(self, index, route, threshold=math.radians(35)): for neighbor in self._graph.successors(current_node): select_edge = self._graph.edges[current_node, neighbor] if select_edge['type'] == RoadOption.LANEFOLLOW: - if neighbor != route[index+1]: + if neighbor != route[index + 1]: sv = select_edge['net_vector'] cross_list.append(np.cross(cv, sv)[2]) next_cross = np.cross(cv, nv)[2] deviation = math.acos(np.clip( - np.dot(cv, nv)/(np.linalg.norm(cv)*np.linalg.norm(nv)), -1.0, 1.0)) + np.dot(cv, nv) / (np.linalg.norm(cv) * np.linalg.norm(nv)), -1.0, 1.0)) if not cross_list: cross_list.append(0) if deviation < threshold: diff --git a/PythonAPI/carla/agents/navigation/local_planner.py b/PythonAPI/carla/agents/navigation/local_planner.py index e4f4b7fb712..25833cecf5c 100644 --- a/PythonAPI/carla/agents/navigation/local_planner.py +++ b/PythonAPI/carla/agents/navigation/local_planner.py @@ -28,7 +28,7 @@ class RoadOption(IntEnum): CHANGELANERIGHT = 6 -class LocalPlanner(object): +class LocalPlanner: """ LocalPlanner implements the basic behavior of following a trajectory of waypoints that is generated on-the-fly. @@ -151,7 +151,7 @@ def set_speed(self, speed): def follow_speed_limits(self, value=True): """ - Activates a flag that makes the max speed dynamically vary according to the spped limits + Activates a flag that makes the max speed dynamically vary according to the speed limits :param value: bool :return: @@ -287,7 +287,7 @@ def get_incoming_waypoint_and_direction(self, steps=3): try: wpt, direction = self._waypoints_queue[-1] return wpt, direction - except IndexError as i: + except IndexError: return None, RoadOption.VOID def get_plan(self): @@ -316,7 +316,7 @@ def _retrieve_options(list_waypoints, current_waypoint): options = [] for next_waypoint in list_waypoints: # this is needed because something we are linking to - # the beggining of an intersection, therefore the + # the beginning of an intersection, therefore the # variation in angle is small next_next_waypoint = next_waypoint.next(3.0)[0] link = _compute_connection(current_waypoint, next_next_waypoint) diff --git a/PythonAPI/carla/agents/tools/hints.py b/PythonAPI/carla/agents/tools/hints.py index 475d93d3dd3..6a6bf520e6a 100644 --- a/PythonAPI/carla/agents/tools/hints.py +++ b/PythonAPI/carla/agents/tools/hints.py @@ -18,7 +18,7 @@ class ObstacleDetectionResult(NamedTuple): obstacle_was_found : bool obstacle : Union[Actor, None] - distance : float + distance : float # distance : Union[float, Literal[-1]] # Python 3.8+ only class TrafficLightDetectionResult(NamedTuple): @@ -30,5 +30,5 @@ class TrafficLightDetectionResult(NamedTuple): ObstacleDetectionResult = NamedTuple('ObstacleDetectionResult', [('obstacle_was_found', bool), ('obstacle', Union[Actor, None]), ('distance', Union[float, Literal[-1]])]) else: ObstacleDetectionResult = NamedTuple('ObstacleDetectionResult', [('obstacle_was_found', bool), ('obstacle', Union[Actor, None]), ('distance', float)]) - + TrafficLightDetectionResult = NamedTuple('TrafficLightDetectionResult', [('traffic_light_was_found', bool), ('traffic_light', Union[TrafficLight, None])]) diff --git a/PythonAPI/carla/agents/tools/misc.py b/PythonAPI/carla/agents/tools/misc.py index 2d3d4c334f3..9400e151753 100644 --- a/PythonAPI/carla/agents/tools/misc.py +++ b/PythonAPI/carla/agents/tools/misc.py @@ -12,6 +12,8 @@ import numpy as np import carla +_EPS = np.finfo(float).eps + def draw_waypoints(world, waypoints, z=0.5): """ Draw a list of waypoints at a certain height given in z. @@ -140,12 +142,15 @@ def vector(location_1, location_2): Returns the unit vector from location_1 to location_2 :param location_1, location_2: carla.Location objects + + .. note:: + Alternatively you can use: + `(location_2 - location_1).make_unit_vector()` """ x = location_2.x - location_1.x y = location_2.y - location_1.y z = location_2.z - location_1.z - norm = np.linalg.norm([x, y, z]) + np.finfo(float).eps - + norm = np.linalg.norm([x, y, z]) + _EPS return [x / norm, y / norm, z / norm] @@ -154,11 +159,14 @@ def compute_distance(location_1, location_2): Euclidean distance between 3D points :param location_1, location_2: 3D points + + .. deprecated:: 0.9.13 + Use `location_1.distance(location_2)` instead """ x = location_2.x - location_1.x y = location_2.y - location_1.y z = location_2.z - location_1.z - norm = np.linalg.norm([x, y, z]) + np.finfo(float).eps + norm = np.linalg.norm([x, y, z]) + _EPS return norm diff --git a/PythonAPI/carla/source/carla/libcarla.pyi b/PythonAPI/carla/source/carla/libcarla.pyi new file mode 100644 index 00000000000..b8691681fcc --- /dev/null +++ b/PythonAPI/carla/source/carla/libcarla.pyi @@ -0,0 +1,5749 @@ +from enum import Enum, Flag, IntFlag +import sys +from typing import (Callable, Iterable, Iterator, Union, Optional, overload, ClassVar, Any, TypeVar, + type_check_only) + +if sys.version_info >= (3, 11): + from typing import Self +else: + from typing_extensions import Self + +if sys.version_info >= (3, 9): + from typing import Annotated +else: + from typing_extensions import Annotated + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from typing_extensions import Literal + + +# Note: __protected_variables are not part of the carla module, they are helpers to complete the stubs. + +__SensorData = TypeVar("__SensorData", bound=SensorData) +"""Generic that allows subclassing.""" + +@type_check_only +class __CarlaEnum(Enum): + """ + CARLA's Enums have a `values` and `names` attribute that are not part of the python `enum.Enum` + class. This abstract stub class adds these attributes. + """ + + values : ClassVar[dict[int, Self]] + names : ClassVar[dict[str, Self]] + + def __init_subclass__(cls): + cls.values : dict[int, cls] + cls.names : dict[str, cls] + + +class AckermannControllerSettings(): + """Manages the settings of the Ackermann PID controller.""" + + # region Instance Variables + @property + def speed_kp(self) -> float: + """Proportional term of the speed PID controller.""" + ... + + @property + def speed_ki(self) -> float: + """Integral term of the speed PID controller.""" + ... + + @property + def speed_kd(self) -> float: + """Derivative term of the speed PID controller.""" + ... + + @property + def accel_kp(self) -> float: + """Proportional term of the acceleration PID controller.""" + ... + + @property + def accel_ki(self) -> float: + """Integral term of the acceleration PID controller.""" + ... + + @property + def accel_kd(self) -> float: + """Derivative term of the acceleration PID controller.""" + ... + # endregion + + # region Methods + def __init__(self, + speed_kp: float = 0.15, + speed_ki: float = 0.0, + speed_kd: float = 0.25, + accel_kp: float = 0.01, + accel_ki: float = 0.0, + accel_kd: float = 0.01): + """Manages the settings of the Ackermann PID controller. + """ + # endregion + + # region Dunder Methods + def __eq__(self, __value: AckermannControllerSettings) -> bool: ... + + def __ne__(self, __value: AckermannControllerSettings) -> bool: ... + + def __str__(self) -> str: ... + # endregion + + +class Actor(): + """CARLA defines actors as anything that plays a role in the simulation or can be moved around. + + That includes: pedestrians, vehicles, sensors and traffic signs (considering traffic lights as part of these). Actors are spawned in the simulation by `carla.World` and they need for a `carla.ActorBlueprint` to be created. These blueprints belong into a library provided by CARLA, find more about them here. + https://carla.readthedocs.io/en/latest/bp_library/ + """ + + # region Instance Variables + @property + def attributes(self) -> dict: + """A dictionary containing the attributes of the blueprint this actor was based on. + """ + ... + + @property + def id(self) -> int: + """Identifier for this actor. Unique during a given episode. + """ + ... + + @property + def type_id(self) -> str: + """The identifier of the blueprint this actor was based on, + + e.g., `vehicle.ford.mustang.`""" + ... + + @property + def is_alive(self) -> bool: + """Returns whether this object was destroyed using this actor handle.""" + ... + + @property + def is_active(self) -> bool: + """Returns whether this actor is active (`True`) or not (`False`).""" + ... + + @property + def is_dormant(self) -> bool: + """Returns whether this actor is dormant (`True`) or not (`False`) - the opposite of `is_active`.""" + ... + + @property + def parent(self) -> Actor | None: + """Actors may be attached to a parent actor that they will follow around. This is said actor.""" + ... + + @property + def semantic_tags(self) -> 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 `TrafficLight`. These tags are used by the semantic segmentation sensor. Find more about this and other sensors here + https://carla.readthedocs.io/en/latest/ref_sensors/#semantic-segmentation-camera + """ + + @property + def actor_state(self) -> ActorState: + """Returns the carla.ActorState, which can identify if the actor is Active, Dormant or Invalid.""" + ... + + @property + def bounding_box(self) -> BoundingBox: + """Bounding box containing the geometry of the actor. Its location and rotation are relative to the actor it is attached to.""" + # endregion + + # region Methods + def add_angular_impulse(self, angular_impulse: Vector3D): + """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. + + Args: + `angular_impulse (Vector3D - degrees*s)`: Angular impulse vector in global coordinates.\n + """ + ... + + def add_force(self, force: Vector3D): + """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. + + Args: + `force (Vector3D - N)`: Force vector in global coordinates.\n + """ + ... + + def add_impulse(self, impulse: Vector3D): + """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. + + Args: + `impulse (Vector3D - N*s)`: Impulse vector in global coordinates.\n + """ + ... + + def add_torque(self, torque: Vector3D): + """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. + + Args: + `torque (Vector3D - degrees)`: Torque vector in global coordinates.\n + """ + ... + + def destroy(self) -> bool: + """Tells the simulator to destroy this actor and returns True if it was successful. + + It has no effect if it was already destroyed. + + + Warning: This method blocks the script until the destruction is completed by the simulator. + """ + ... + + def disable_constant_velocity(self): + """Disables any constant velocity previously set for a `carla.Vehicle` actor. + """ + ... + + def enable_constant_velocity(self, velocity: Vector3D): + """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` may cause conflicts. This method overrides any changes in velocity by the TM. + + Args: + `velocity (Vector3D - m/s)`: Velocity vector in local space.\n + """ + ... + # endregion + + # region Getters + def get_acceleration(self) -> Vector3D: + """Returns the actor's 3D acceleration vector the client received during last tick. + + The method does not call the simulator. + + Returns: + `Vector3D`: m/s^2\n + """ + ... + + def get_angular_velocity(self) -> Vector3D: + """Returns the actor's angular velocity vector the client received during last tick. + + The method does not call the simulator. + + Returns: + `Vector3D`: deg/s\n + """ + ... + + def get_location(self) -> Location: + """Returns the actor's location the client received during last tick. + + The method does not call the simulator. + + + Setter: `carla.Actor.set_location` + + Returns: + `Location`: - meters\n + """ + ... + + def get_transform(self) -> Transform: + """Returns the actor's transform (location and rotation) the client received during last tick. + + The method does not call the simulator. + + + Setter: `carla.Actor.set_transform` + + Returns: + `Transform`\n + """ + + def get_velocity(self) -> Vector3D: + """Returns the actor's velocity vector the client received during last tick. + + The method does not call the simulator. + + Returns: + `Vector3D`: m/s\n + """ + ... + + def get_world(self) -> World: + """Returns the world this actor belongs to. + + Returns: + `World`\n + """ + ... + # endregion + + # region Setters + def set_enable_gravity(self, enabled: bool): + """Enables or disables gravity for the actor. + Default is `True`. + + Args: + `enabled (bool)`\n + """ + ... + + def set_location(self, location: Location): + """Teleports the actor to a given location. + + + Getter: `carla.Actor.get_location` + + Args: + `location (Location)`: meters\n + """ + ... + + def set_simulate_physics(self, enabled=True): + """Enables or disables the simulation of physics on this actor. + + Args: + `enabled (bool, optional)`: Defaults to True.\n + """ + ... + + def set_target_angular_velocity(self, angular_velocity: Vector3D): + """_summary_Sets the actor's angular velocity vector. + + This is applied before the physics step so the resulting angular velocity will be affected by external forces such as friction. + + Args: + `angular_velocity (Vector3D)`: deg/s\n + """ + ... + + def set_target_velocity(self, velocity: Vector3D): + """Sets the actor's velocity vector. + + This is applied before the physics step so the resulting angular velocity will be affected by external forces such as friction. + + Args: + `velocity (Vector3D)`\n + """ + ... + + def set_transform(self, transform: Transform): + """Teleports the actor to a given transform (location and rotation). + + + Getter: `carla.Actor.get_transform` + + Args: + `transform (Transform)`\n + """ + ... + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class ActorAttribute(): + """CARLA provides a library of blueprints for actors that can be accessed as `carla.BlueprintLibrary`. Each of these blueprints has a series of attributes defined internally. Some of these are modifiable, others are not. A list of recommended values is provided for those that can be set. + """ + + # region Instance Variables + @property + def id(self) -> str: + """The attribute's name and identifier in the library. + """ + @property + def is_modifiable(self) -> bool: + """It is True if the attribute's value can be modified.""" + @property + def recommended_values(self) -> list[str]: + """A list of values suggested by those who designed the blueprint.""" + @property + def type(self) -> ActorAttributeType: + """The attribute's parameter type.""" + # endregion + + # region Methods + def as_bool(self) -> bool: + """Reads the attribute as boolean value.""" + ... + + def as_color(self) -> Color: + """Reads the attribute as `carla.Color`.""" + ... + + def as_float(self) -> float: + """Reads the attribute as float.""" + ... + + def as_int(self) -> int: + """Reads the attribute as int.""" + ... + + def as_str(self) -> str: + """Reads the attribute as string.""" + ... + # endregion + + # region Dunder Methods + def __bool__(self) -> bool: ... + def __eq__(self, __value: Union[bool, int, float, str, Color, ActorAttribute]) -> bool: ... + def __float__(self) -> float: ... + def __int__(self) -> int: ... + def __ne__(self, __value: Union[bool, int, float, str, Color, ActorAttribute]) -> bool: ... + def __nonzero__(self) -> bool: ... + def __str__(self) -> str: ... + # endregion + + +class ActorAttributeType(int, __CarlaEnum): + """CARLA provides a library of blueprints for actors in `carla.BlueprintLibrary` with different attributes each. This class defines the types those at `carla.ActorAttribute` can be as a series of enum. All this information is managed internally and listed here for a better comprehension of how CARLA works. + """ + # region Instance Variables + Bool = 0 + Int = 1 + Float = 2 + String = 3 + RGBColor = 4 + # endregion + + +class ActorBlueprint(): + """CARLA provides a blueprint library for actors that can be consulted through `carla.BlueprintLibrary`. Each of these consists of an identifier for the blueprint and a series of attributes that may be modifiable or not. This class is the intermediate step between the library and the actor creation. Actors need an actor blueprint to be spawned. These store the information for said blueprint in an object with its attributes and some tags to categorize them. The user can then customize some attributes and eventually spawn the actors through `carla.World`. + """ + + # region Instance Variables + @property + def id(self) -> str: + """The identifier of said blueprint inside the library. + + E.g. `walker.pedestrian.0001`.""" + + @property + def tags(self) -> list[str]: + """A list of tags each blueprint has that helps describing them. + + E.g. `['0001', 'pedestrian', 'walker']`. + """ + ... + # endregion + + # region Methods + def has_attribute(self, id: str) -> bool: + """Returns `True` if the blueprint contains the attribute `id`. + + Args: + `id (str)`: e.g. `gender` would return True for pedestrians' blueprints.\n + + Returns: + `bool`\n + """ + ... + + def has_tag(self, tag: str) -> bool: + """Returns `True` if the blueprint has the specified `tag` listed. + + Args: + `tag (str)`: e.g. `'walker'`\n + + Returns: + `bool`\n + """ + ... + + def match_tags(self, wildcard_pattern: str) -> bool: + """Returns `True` if any of the tags listed for this blueprint matches `wildcard_pattern`. + + Matching follows `fnmatch` standard. https://docs.python.org/3.12/library/fnmatch.html + + Args: + `wildcard_pattern (str)`\n + + Returns: + `bool`\n + """ + # endregion + + # region Getters + def get_attribute(self, id: str) -> ActorAttribute: + """Returns the actor's attribute with `id` as identifier if existing. + + + Setter: `carla.ActorBlueprint.set_attribute` + + Args: + `id (str)`\n + + Returns: + `ActorAttribute`\n + """ + ... + # endregion + + # region Setters + def set_attribute(self, id: str, value: str) -> None: + """If the `id` attribute is modifiable, changes its value to `value`. + + Args: + `id (str)`: The identifier for the attribute that is intended to be changed.\n + `value (str)`: The new value for said attribute.\n + """ + # endregion + + # region Dunder Methods + def __iter__(self) -> Iterator[ActorAttribute]: + """Iterate over the `carla.ActorAttribute` that this blueprint has. + """ + ... + + def __len__(self) -> int: + """Returns the amount of attributes for this blueprint.""" + ... + + def __str__(self) -> str: ... + # endregion + + +class ActorList(): + """ + A class that contains every actor present on the scene and provides access to them. + The list is automatically created and updated by the server and it can be returned using `carla.World`. + """ + + # region Methods + def filter(self, wildcard_pattern: str) -> ActorList: + """Filters a list of Actors matching wildcard_pattern against their variable `type_id` (which identifies the blueprint used to spawn them). Matching follows fnmatch standard. + + Args: + `wildcard_pattern (str)`\n + + Returns: + `ActorList`\n + """ + ... + + def find(self, actor_id: int) -> Actor: + """Finds an actor using its identifier and returns it or None if it is not present. + + Args: + `actor_id (int)`\n + + Returns: + `Actor`\n + """ + ... + # endregion + + # region Dunder methods + def __getitem__(self, pos: int) -> Actor: + """Returns the actor corresponding to pos position in the list.""" + ... + + def __iter__(self) -> Iterator[Actor]: + """Iterate over the `carla.Actor` contained in the list.""" + ... + + def __len__(self) -> int: + """Returns the amount of actors listed.""" + ... + + def __str__(self) -> str: + """Parses to the ID for every actor listed.""" + ... + # endregion + + +class ActorSnapshot(): + """A class that comprises all the information for an actor at a certain moment in time. These objects are contained in a `carla.WorldSnapshot` and sent to the client once every tick. + """ + + # region Instance Variables + @property + def id(self) -> int: + """An identifier for the snapshot itself.""" + ... + # endregion + + # region Getters + def get_acceleration(self) -> Vector3D: + """Returns the acceleration vector registered for an actor in that tick. + + Returns: + `Vector3D`: m/s^2\n + """ + ... + + def get_angular_velocity(self) -> Vector3D: + """Returns the angular velocity vector registered for an actor in that tick. + + Returns: + `Vector3D`: rad/s\n + """ + ... + + def get_transform(self) -> Transform: + """Returns the actor's transform (location and rotation) for an actor in that tick. + + Returns: + `Transform`\n + """ + ... + + def get_velocity(self) -> Vector3D: + """Returns the velocity vector registered for an actor in that tick. + + Returns: + `Vector3D`: m/s\n + """ + ... + # endregion + + +class ActorState(int, __CarlaEnum): + """Class that defines the state of an actor.""" + # region Instance Variables + Invalid = 0 + """An actor is Invalid if a problem has occurred.""" + Active = 1 + """An actor is Active when it visualized and can affect other actors.""" + Dormant = 2 + """An actor is Dormant when it is not visualized and will not affect other actors through physics. For example, actors are dormant if they are on an unloaded tile in a large map.""" + # endregion + + +class AttachmentType(int, __CarlaEnum): + """ + Class that defines attachment options between an actor and its parent. + When spawning actors, these can be attached to another actor so their + position changes accordingly. This is specially useful for sensors. + The snippet in `carla.World.spawn_actor` shows some sensors being + attached to a car when spawned. + + + Note that the attachment type is declared as an enum within the class.""" + + # region Instance Variables + Rigid = 0 + """With this fixed attachment the object follow its parent position strictly. + This is the recommended attachment to retrieve precise data from the simulation.""" + + SpringArm = 1 + """ + An attachment that expands or retracts the position of the actor, + depending on its parent. This attachment is only recommended to record + videos from the simulation where a smooth movement is needed. SpringArms + are an Unreal Engine component so check the UE docs to learn more about + them. + + https://docs.unrealengine.com/5.3/en-US/using-spring-arm-components-in-unreal-engine/ + + + Warning: The `SpringArm` attachment presents weird behaviors when an + actor is spawned with a relative translation in the Z-axis (e.g. `child_location = Location(0,0,2)`). + """ + + SpringArmGhost = 2 + """ + An attachment like the previous one but that does not make the collision test, + and that means that it does not expands or retracts the position of the actor. + The term ghost is because then the camera can cross walls and other geometries. + This attachment is only recommended to record videos from the simulation where + a smooth movement is needed. SpringArms are an Unreal Engine component so + check the UE docs to learn more about them. + + https://docs.unrealengine.com/5.3/en-US/using-spring-arm-components-in-unreal-engine/ + + + Warning: The `SpringArm` attachment presents weird behaviors when an actor is + spawned with a relative translation in the Z-axis (e.g. `child_location = Location(0,0,2)`). + """ + # endregion + + +class BlueprintLibrary(): + """A class that contains the blueprints provided for actor spawning. Its main application is to return `carla.ActorBlueprint` objects needed to spawn actors. Each blueprint has an identifier and attributes that may or may not be modifiable. The library is automatically created by the server and can be accessed through `carla.World`. + + Here is a reference containing every available blueprint and its specifics. + """ + + # region Methods + def filter(self, wildcard_pattern: str) -> BlueprintLibrary: + """Filters a list of blueprints matching the `wildcard_pattern` against the id and tags of every blueprint contained in this library and returns the result as a new one. Matching follows fnmatch standard. + + Args: + `wildcard_pattern (str)`\n + + Returns: + `BlueprintLibrary`\n + """ + + def filter_by_attribute(self, name: str, value: str) -> BlueprintLibrary: + """Filters a list of blueprints with a given attribute matching the `value` against every blueprint contained in this library and returns the result as a new one. Matching follows fnmatch standard. + + Args: + `name (str)`\n + `value (str)`\n + + Returns: + `ActorBlueprint`\n + """ + + def find(self, id: str) -> ActorBlueprint: + """Returns the blueprint corresponding to that identifier. + + Args: + `id (str)`\n + + Returns: + `ActorBlueprint`\n + """ + # endregion + + # region Dunder Methods + def __getitem__(self, pos: int) -> ActorBlueprint: + """Returns the blueprint stored in `pos` position inside the data structure containing them. + """ + + def __iter__(self) -> Iterator[ActorBlueprint]: + """Iterate over the `carla.ActorBlueprint` stored in the library.""" + + def __len__(self): + """Returns the amount of blueprints comprising the library.""" + + def __str__(self) -> str: + """Parses the identifiers for every blueprint to string.""" + ... + # endregion + + +class BoundingBox(): + """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 the snippet in `carla.DebugHelper.draw_box` where a snapshot of the world is used to draw bounding boxes for traffic lights. + """ + + # region Instance Variables + @property + def extent(self) -> Vector3D: + """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. + + Returns: + `Vector3D`: meters\n + """ + @property + def location(self) -> Location: + """The center of the bounding box. + + Returns: + `Location`: meters\n + """ + + @property + def rotation(self) -> Rotation: + """The orientation of the bounding box.""" + # endregion + + # region Methods + def __init__(self, location: Location, extent: Vector3D): + """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 the snippet in `carla.DebugHelper.draw_box` where a snapshot of the world is used to draw bounding boxes for traffic lights. + + Args: + `location (Location)`: Center of the box, relative to its parent.\n + `extent (Vector3D)`: Vector containing half the size of the box for every axis.\n + """ + ... + + def contains(self, world_point: Location, transform: Transform) -> bool: + """Returns `True` if a point passed in world space is inside this bounding box. + + + Args: + `world_point (Location)`: meters. The point in world space to be checked.\n + `transform (Transform)`: Contains location and rotation needed to convert this object's local space to world space.\n + + Returns: + `bool`\n + """ + # endregion + + # region Getters + def get_local_vertices(self) -> list[Location]: + """Returns a list containing the locations of this object's vertices in local space.""" + ... + + def get_world_vertices(self, transform: Transform) -> list[Location]: + """Returns a list containing the locations of this object's vertices in world space. + + Args: + `transform (Transform)`: Contains location and rotation needed to convert this object's local space to world space.\n + """ + ... + # endregion + + # region Dunder Methods + def __eq__(self, __value: BoundingBox) -> bool: + """Returns true if both location and extent are equal for this and `other`.""" + + def __ne__(self, __value: BoundingBox) -> bool: + """Returns true if either location or extent are different for this and `other`.""" + + def __str__(self) -> str: + """Parses the location and extent of the bounding box to string.""" + # endregion + + +class CityObjectLabel(int, __CarlaEnum): + """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 that the elements in the scene have.""" + NONE = 0 + Buildings = 3 + Fences = 5 + Other = 22 + Pedestrians = 12 + Poles = 6 + RoadLines = 24 + Roads = 1 + Sidewalks = 2 + TrafficSigns = 8 + Vegetation = 9 + Car = 14 + Walls = 4 + Sky = 11 + Ground = 25 + Bridge = 26 + RailTrack = 27 + GuardRail = 28 + TrafficLight = 7 + Static = 20 + Dynamic = 21 + Water = 23 + Terrain = 10 + Truck = 15 + Motorcycle = 18 + Bicycle = 19 + Bus = 16 + Rider = 13 + Train = 17 + Any = 255 + + +class 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. + + The client also has a recording feature that saves all the information of a simulation while running it. This allows the server to replay it at will to obtain information and experiment with it. Here is some information about how to use this recorder. + + https://carla.readthedocs.io/en/latest/adv_recorder/ + """ + # region Methods + + def __init__(self, host="127.0.0.1", port=2000, worker_threads=0): + """Client constructor. + + Args: + `host (str, optional)`: IP address where a CARLA Simulator instance is running. Defaults to "127.0.0.1".\n + `port (int, optional)`: TCP port where the CARLA Simulator instance is running. Defaults to 2000 and the subsequent 2001.\n + `worker_threads (int, optional)`: Number of working threads used for background updates. If 0, use all available concurrency. Defaults to 0.\n + """ + + def apply_batch(self, commands: list[command]): + """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 is an example on how to delete the actors that appear in `carla.ActorList` all at once. + + https://github.com/carla-simulator/carla/blob/master/PythonAPI/examples/generate_traffic.py + + Args: + `commands (list)`: A list of commands to execute in batch. Each command is different and has its own parameters. \n + """ + + def apply_batch_sync(self, commands: list[command], due_tick_cue=False) -> list[command.Response]: + """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 is an example of it being used to spawn actors. + + https://github.com/carla-simulator/carla/blob/master/PythonAPI/examples/generate_traffic.py + + Args: + `commands (list[command])`: A list of commands to execute in batch. The commands available are listed right above, in the method `apply_batch()`.\n + `due_tick_cue (bool, optional)`: A boolean parameter to specify whether or not to perform a `carla.World.tick` after applying the batch in synchronous mode. Defaults to False.\n + + Returns: + `list[command.Response]`\n + """ + + def generate_opendrive_world(self, opendrive: str, parameters: OpendriveGenerationParameters = OpendriveGenerationParameters(2.0, 50.0, 1.0, 0.6, True, True), reset_settings=True): + """Loads a new world with a basic 3D topology generated from the content of an OpenDRIVE file. This content is passed as a `string` parameter. It is similar to `client.load_world(map_name)` but allows for custom OpenDRIVE maps in server side. Cars can drive around the map, but there are no graphics besides the road and sidewalks. + + Args: + `opendrive (str)`: Content of an OpenDRIVE file as `string`, not the path to the `.xodr`.\n + `parameters (OpendriveGenerationParameters, optional)`: Additional settings for the mesh generation. Defaults to (2.0, 50.0, 1.0, 0.6, True, True).\n + `reset_settings (bool, optional)`: Option to reset the episode setting to default values, set to false to keep the current settings. This is useful to keep sync mode when changing map and to keep deterministic scenarios. Defaults to True.\n + """ + + def load_world(self, map_name: str, reset_settings=True, map_layers=MapLayer.All) -> World: + """Creates a new world with default settings using `map_name` map. All actors in the current world will be destroyed. + + + Warning: `map_layers` are only available for "Opt" maps + + Args: + `map_name (str)`: Name of the map to be used in this world. Accepts both full paths and map names,e.g. `'/Game/Carla/Maps/Town01'` or `'Town01'`. Remember that these paths are dynamic.\n + `reset_settings (bool, optional)`: Option to reset the episode setting to default values, set to false to keep the current settings. This is useful to keep sync mode when changing map and to keep deterministic scenarios. Defaults to True.\n + `map_layers (MapLayer, optional)`: Layers of the map that will be loaded. This parameter works like a flag mask. Defaults to MapLayer.All.\n + + Returns: + `World`\n + """ + + def reload_world(self, reset_settings=True) -> World: + """Reload the current world, note that a new world is created with default settings using the same map. All actors present in the world will be destroyed, but traffic manager instances will stay alive. + + Args: + `reset_settings (bool, optional)`: Option to reset the episode setting to default values, set to false to keep the current settings. This is useful to keep sync mode when changing map and to keep deterministic scenarios. Defaults to True.\n + + Raises: + `RuntimeError` when corresponding. + + Returns: + `World`\n + """ + + def load_world_if_different(self, map_name: str, reset_settings=True, map_layers=MapLayer.All): + """" + Creates a new world with default settings using `map_name` map only if it is a different map + from the currently loaded map. + Otherwise this function returns `None`. All actors in the current world will be destroyed. + + Args: + `map_name (str)`: Name of the map to be used in this world. Accepts both full paths and map names, + e.g.'/Game/Carla/Maps/Town01' or 'Town01'. Remember that these paths are dynamic.\n + `reset_settings (bool, optional)`: Option to reset the episode setting to default values, set to false to keep the current settings. + This is useful to keep sync mode when changing map and to keep deterministic scenarios. + Defaults to True.\n + `map_layers (MapLayer, optional)`: Layers of the map that will be loaded. This parameter works like a flag mask. + Defaults to MapLayer.All.\n + + Returns: + None + """ + + def replay_file(self, name: str, start: float, duration: float, follow_id: int, replay_sensors: bool): + """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. + + Args: + `name (str)`: Name of the file containing the information of the simulation.\n + `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.\n + `duration (float - seconds)`: Time that will be reenacted using the information `name` file. If the end is reached, the simulation will continue.\n + `follow_id (int)`: ID of the actor to follow. If this is 0 then camera is disabled.\n + `replay_sensors (bool)`: Flag to enable or disable the spawn of sensors during playback.\n + """ + + def request_file(self, name: str): + """Requests one of the required files returned by `carla.Client.get_required_files`. + + Args: + `name (str)`: Name of the file you are requesting.\n + """ + + def show_recorder_actors_blocked(self, filename: str, min_time: float, min_distance: float) -> str: + """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`. + + Args: + `filename (str)`: Name of the recorded file to load.\n + `min_time (float - seconds)`: Minimum time the actor has to move a minimum distance before being considered blocked. Default is 60 seconds.\n + `min_distance (float - centimeters)`: Minimum distance the actor has to move to not be considered blocked. Default is 100 centimeters.\n + + Returns: + `str`\n + """ + + def show_recorder_collisions(self, filename: str, category1: str, category2: str) -> str: + """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: 'h' = Hero, the one vehicle that can be controlled manually or managed by the user. 'v' = Vehicle 'w' = Walker 't' = Traffic light 'o' = Other 'a' = Any If you want to see only collisions between a vehicles and a walkers, use for `category1` as 'v' and `category2` as 'w' or vice versa. If you want to see all the collisions (filter off) you can use 'a' for both parameters. + + Args: + `filename (str)`: Name or absolute path of the file recorded, depending on your previous choice.\n + `category1 (str)`: Character variable specifying a first type of actor involved in the collision.\n + `category2 (str)`: Character variable specifying the second type of actor involved in the collision.\n + + Returns: + `str`\n + """ + + def show_recorder_file_info(self, filename: str, show_all: bool) -> str: + """The information saved by the recorder will be parsed and shown in your terminal as text (frames, times, events, state, positions...). The information shown can be specified by using the `show_all` parameter. Here is some more information about how to read the recorder file. + + https://carla.readthedocs.io/en/latest/ref_recorder_binary_file_format/ + + Args: + `filename (str)`: Name or absolute path of the file recorded, depending on your previous choice.\n + `show_all (bool)`: If `True`, returns all the information stored for every frame (traffic light states, positions of all actors, orientation and animation data...). If `False`, returns a summary of key events and frames.\n + + Returns: + `str`\n + """ + + def start_recorder(self, filename: str, additional_data=False): + """Enables the recording feature, which will start saving every information possible needed by the server to replay the simulation. + + Args: + `filename (str)`: Name of the file to write the recorded data. A simple name will save the recording in 'CarlaUE4/Saved/recording.log'. Otherwise, if some folder appears in the name, it will be considered an absolute path.\n + `additional_data (bool, optional)`: Enables or disable recording non-essential data for reproducing the simulation (bounding box location, physics control parameters, etc). Defaults to False.\n + """ + + def stop_recorder(self): + """Stops the recording in progress. If you specified a path in `filename`, the recording will be there. If not, look inside `CarlaUE4/Saved/`.""" + + def stop_replayer(self, keep_actors: bool): + """Stop current replayer. + + Args: + `keep_actors (bool)`: `True` if you want autoremove all actors from the replayer, or `False` to keep them.\n + """ + # endregion + + # region Getters + def get_available_maps(self) -> list[str]: + """Returns a list of strings containing the paths of the maps available on server. These paths are dynamic, they will be created during the simulation and so you will not find them when looking up in your files. One of the possible returns for this method would be: + + >>> ['/Game/Carla/Maps/Town01', '/Game/Carla/Maps/Town02', '/Game/Carla/Maps/Town03', '/Game/Carla/Maps/Town04', '/Game/Carla/Maps/Town05', '/Game/Carla/Maps/Town06', '/Game/Carla/Maps/Town07'] + """ + + def get_client_version(self) -> str: + """Returns the client libcarla version by consulting it in the "Version.h" file. Both client and server can use different libcarla versions but some issues may arise regarding unexpected incompatibilities. + """ + + def get_required_files(self, folder: str, download=True): + """Asks the server which files are required by the client to use the current map. Option to download files automatically if they are not already in the cache. + + Args: + `folder (str)`: Folder where files required by the client will be downloaded to.\n + `download (bool, optional)`: If `True`, downloads files that are not already in cache.. Defaults to True.\n + """ + + def get_server_version(self) -> str: + """Returns the server libcarla version by consulting it in the "Version.h" file. Both client and server should use the same libcarla version. + """ + + def get_trafficmanager(self, client_connection=8000) -> TrafficManager: + """Returns an instance of the traffic manager related to the specified port. If it does not exist, this will be created. + + Args: + `client_connection (int, optional)`: Port that will be used by the traffic manager.. Defaults to 8000.\n + """ + + def get_world(self) -> World: + """Returns the world object currently active in the simulation. This world will be later used for example to load maps. + """ + # endregion + + # region Setters + def set_files_base_folder(self, path: str): + """Specifies the base folder where the local cache for required files will be placed. + + Args: + `path (str)`: Specifies the base folder where the local cache for required files will be placed.\n + """ + + def set_replayer_ignore_hero(self, ignore_hero: bool): + """Enables or disables playback of the hero vehicle during a playback of a recorded simulation. + + Args: + `ignore_hero (bool)`: Enables or disables playback of the hero vehicle during a playback of a recorded simulation.\n + """ + + def set_replayer_ignore_spectator(self, ignore_spectator: bool): + """Determines whether the recorded spectator movements will be replicated by the replayer. + + Args: + `ignore_spectator (bool)`: Determines whether the recorded spectator movements will be replicated by the replayer.\n + """ + + def set_replayer_time_factor(self, time_factor=1.0): + """When used, the time speed of the reenacted simulation is modified at will. It can be used several times while a playback is in curse. + + Args: + `time_factor (float, optional)`: 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). Defaults to 1.0.\n + """ + + def set_timeout(self, second: float): + """Sets the maximum time a network call is allowed before blocking it and raising a timeout exceeded error. + + Args: + `second (float - seconds)`: New timeout value. Default is 5 seconds.\n + """ + + # endregion + + +class CollisionEvent(SensorData): + """Class that defines a collision data for sensor.other.collision. The sensor creates one of these for every collision detected. Each collision sensor produces one collision event per collision per frame. Multiple collision events may be produced in a single frame by collisions with multiple other actors. Learn more about this here. + + https://carla.readthedocs.io/en/latest/ref_sensors/#collision-detector + """ + # region Instance Variables + @property + def actor(self) -> Actor: + """The actor the sensor is attached to, the one that measured the collision.""" + @property + def other_actor(self) -> Actor: + """The second actor involved in the collision.""" + @property + def normal_impulse(self) -> Vector3D: + """Normal impulse resulting of the collision.(N*s)""" + # endregion + + +class Color(): + """Class that defines a 32-bit RGBA color.""" + + # region Instance Variables + @property + def r(self) -> int: + """Red color (0-255).""" + @property + def g(self) -> int: + """Green color (0-255).""" + @property + def b(self) -> int: + """Blue color (0-255).""" + @property + def a(self) -> int: + """Alpha channel (0-255).""" + # endregion + + # region Methods + def __init__(self, r=0, g=0, b=0, a=255): + """Initializes a color, black by default. + + Args: + `r (int, optional)`: Red color (0-255). Defaults to 0.\n + `g (int, optional)`: Green color (0-255). Defaults to 0.\n + `b (int, optional)`: Blue color (0-255). Defaults to 0.\n + `a (int, optional)`: Alpha channel (0-255). Defaults to 255.\n + """ + # endregion + + # region Dunder Methods + def __eq__(self, __value: Color) -> bool: ... + def __ne__(self, __value: Color) -> bool: ... + def __str__(self) -> str: ... + # endregion + + +class ColorConverter(int, __CarlaEnum): + """ + Class that defines conversion patterns that can be applied to a `carla.Image` in order to show + information provided by `carla.Sensor`. Depth conversions cause a loss of accuracy, as sensors + detect depth as float that is then converted to a grayscale value between 0 and 255. Take a look + at the snippet in `carla.Sensor.listen` to see an example of how to create and save image data + for `sensor.camera.semantic_segmentation`. + """ + + # region Instance Variables + Raw = 0 + """No changes applied to the image. Used by the `RGB camera`.""" + Depth = 1 + """Converts the image to a linear depth map. Used by the `depth camera`.""" + LogarithmicDepth = 2 + """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.""" + CityScapesPalette = 3 + """Converts the image to a segmented map using tags provided by the blueprint library. Used by the `semantic segmentation camera`.""" + # endregion + + +class DVSEvent(): + """Class that defines a DVS event. An event is a quadruple, so a tuple of 4 elements, with `x`, `y` pixel coordinate location, timestamp `t` and polarity `pol` of the event. Learn more about them here. + + https://carla.readthedocs.io/en/latest/ref_sensors/ + """ + + # region Instance Variables + @property + def x(self) -> int: + """X pixel coordinate.""" + @property + def y(self) -> int: + """Y pixel coordinate.""" + @property + def t(self) -> int: + """Timestamp of the moment the event happened.""" + @property + def pol(self) -> bool: + """Polarity of the event. True for positive and False for negative.""" + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class DVSEventArray(): + """ + Class that defines a stream of events in `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. + + https://carla.readthedocs.io/en/latest/ref_sensors/ + """ + + # region Instance Variables + @property + def fov(self) -> float: + """Horizontal field of view of the image.""" + @property + def height(self) -> int: + """Image height in pixels.""" + @property + def width(self) -> int: + """Image width in pixels.""" + @property + def raw_data(self) -> bytes: ... + # endregion + + # region Methods + def to_array(self) -> Iterable: + """Converts the stream of events to an array of int values in the following order `[x, y, t, pol]`.""" + + def to_array_pol(self) -> Iterable: + """Returns an array with the polarity of all the events in the stream.""" + + def to_array_t(self) -> Iterable: + """Returns an array with the timestamp of all the events in the stream.""" + + def to_array_x(self) -> Iterable: + """Returns an array with X pixel coordinate of all the events in the stream.""" + + def to_array_y(self) -> Iterable: + """Returns an array with Y pixel coordinate of all the events in the stream.""" + + def to_image(self) -> Image: + """Converts the image following this pattern: blue indicates positive events, red indicates negative events.""" + # endregion + + # region Dunder Methods + def __getitem__(self, pos: int): ... + + def __iter__(self) -> Iterator[DVSEvent]: + """Iterate over the `carla.DVSEvent` retrieved as data.""" + + def __len__(self): ... + def __setitem(self, pos: int, color: Color): ... + def __str__(self) -> str: ... + # endregion + + +class DebugHelper(): + """ + Helper class part of `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. Take a look at the snippets available for this class to learn how to debug easily in CARLA. + """ + + # region Methods + def draw_arrow(self, begin: Location, end: Location, thickness=0.1, arrow_size=0.1, color: Color =Color(255, 0, 0), life_time=-1.0, persistent_lines=True) -> None: + """ + Draws an arrow from `begin` to `end` pointing in that direction. + + Args: + begin (Location): Point in the coordinate system where the arrow starts (meters). + end (Location): Point in the coordinate system where the arrow ends and points towards to (meters). + thickness (float, optional): Density of the line (meters). Defaults to 0.1. + arrow_size (float, optional): Size of the tip of the arrow (meters). Defaults to 0.1. + color (Color, optional): RGB code to color the object. Defaults to (255,0,0). + life_time (float, optional): Shape's lifespan. By default it only lasts one frame. Set this to `0` for permanent shapes (seconds). Defaults to -1.0. + """ + ... + + def draw_hud_arrow(self, begin: Location, end: Location, thickness=0.1, arrow_size=0.1, color: Color =Color(255, 0, 0), life_time=-1.0, persistent_lines=True) -> None: + """ + Draws an arrow on the HUD from `begin` to `end` which can only be seen server-side. + + Args: + begin (Location): Point in the coordinate system where the arrow starts (meters). + end (Location): Point in the coordinate system where the arrow ends and points towards to (meters). + thickness (float, optional): Density of the line (meters). Defaults to 0.1. + arrow_size (float, optional): Size of the tip of the arrow (meters). Defaults to 0.1. + color (Color, optional): RGB code to color the object. Defaults to (255,0,0). + life_time (float, optional): Shape's lifespan. By default it only lasts one frame. Set this to `0` for permanent shapes (seconds). Defaults to -1.0. + """ + + def draw_box(self, box: BoundingBox, rotation: Rotation, thickness=0.1, color: Color =Color(255, 0, 0), life_time=-1.0, persistent_lines=True) -> None: + """Draws a box, usually to act for object colliders. + + Args: + box (BoundingBox): Object containing a location and the length of a box for every axis. + rotation (Rotation): Orientation of the box according to Unreal Engine's axis system (degrees (pitch,yaw,roll)). + thickness (float, optional): Density of the lines that define the box (meters). Defaults to 0.1. + color (Color, optional): RGB code to color the object. Defaults to (255,0,0). + life_time (float, optional): Shape's lifespan. By default it only lasts one frame. Set this to `0` for permanent shapes. Defaults to -1.0. + """ + ... + + def draw_hud_box(self, box: BoundingBox, rotation: Rotation, thickness=0.1, color: Color =Color(255, 0, 0), life_time=-1.0, persistent_lines=True) -> None: + """ + Draws a box on the HUD, usually to act for object colliders. The box can only be seen server-side. + + Args: + box (BoundingBox): Object containing a location and the length of a box for every axis. + rotation (Rotation): Orientation of the box according to Unreal Engine's axis system (degrees (pitch,yaw,roll)). + thickness (float, optional): Density of the lines that define the box (meters). Defaults to 0.1. + color (Color, optional): RGB code to color the object. Defaults to (255,0,0). + life_time (float, optional): Shape's lifespan. By default it only lasts one frame. Set this to `0` for permanent shapes. Defaults to -1.0. + """ + ... + + + def draw_line(self, begin: Location, end: Location, thickness=0.1, color: Color =Color(255, 0, 0), life_time=-1.0, persistent_lines=True) -> None: + """ + Draws a line in between `begin` and `end`. + + Args: + begin (Location): Point in the coordinate system where the line starts (meters). + end (Location): Spot in the coordinate system where the line ends (meters). + thickness (float, optional): Density of the line. Defaults to 0.1. + color (Color, optional): RGB code to color the object. Defaults to (255,0,0). + life_time (float, optional): Shape's lifespan. By default it only lasts one frame. Set this to `0` for permanent shapes. Defaults to -1.0. + """ + ... + + def draw_hud_line(self, begin: Location, end: Location, thickness=0.1, color: Color =Color(255, 0, 0), life_time=-1.0, persistent_lines=True) -> None: + """ + Draws a line on the HUD in between `begin` and `end`. The line can only be seen server-side. + + Args: + begin (Location): Point in the coordinate system where the line starts (meters). + end (Location): Spot in the coordinate system where the line ends (meters). + thickness (float, optional): Density of the line. Defaults to 0.1. + color (Color, optional): RGB code to color the object. Defaults to (255,0,0). + life_time (float, optional): Shape's lifespan. By default it only lasts one frame. Set this to `0` for permanent shapes. Defaults to -1.0. + """ + ... + + def draw_point(self, location: Location, size=0.1, color: Color=Color(255, 0, 0), life_time=-1.0, persistent_lines=True) -> None: + """ + Draws a point location. + + Args: + location (Location): Spot in the coordinate system to center the object (meters). + size (float, optional): Density of the point (meters). Defaults to 0.1. + color (tuple, optional): RGB code to color the object. Defaults to (255,0,0). + life_time (float, optional): Shape's lifespan. By default it only lasts one frame. Set this to 0 for permanent shapes (seconds). Defaults to -1.0. + """ + ... + + def draw_hud_point(self, location: Location, size=0.1, color: Color=Color(255, 0, 0), life_time=-1.0, persistent_lines=True) -> None: + """ + Draws a point on the HUD at `location`. The point can only be seen server-side. + + Args: + location (Location): Spot in the coordinate system to center the object (meters). + size (float, optional): Density of the point (meters). Defaults to 0.1. + color (tuple, optional): RGB code to color the object. Defaults to (255,0,0). + life_time (float, optional): Shape's lifespan. By default it only lasts one frame. Set this to 0 for permanent shapes (seconds). Defaults to -1.0. + """ + ... + + def draw_string(self, location: Location, text: str, draw_shadow=False, color: Color = Color(255, 0, 0), life_time=-1.0, persistent_lines=True) -> None: + """Draws a string in a given location of the simulation which can only be seen server-side. + + Args: + location (Location): Spot in the simulation where the text will be centered (meters). + text (str): Text intended to be shown in the world. + draw_shadow (bool, optional): Casts a shadow for the string that could help in visualization. It is disabled by default. Defaults to False. + color (Color, optional): RGB code to color the string. Defaults to (255,0,0). + life_time (float, optional): Shape's lifespan. By default it only lasts one frame. Set this to `0` for permanent shapes (seconds). Defaults to -1.0. + """ + ... + # endregion + + +class EnvironmentObject(): + """Class that represents a geometry in the level, this geometry could be part of an actor formed with other EnvironmentObjects (i.e.: buildings).""" + + # region Instance Variables + @property + def transform(self) -> Transform: + """Contains the location and orientation of the EnvironmentObject in world space.""" + ... + + @property + def bounding_box(self) -> BoundingBox: + """Object containing a location, rotation and the length of a box for every axis in world space.""" + ... + + @property + def id(self) -> int: + """Unique ID to identify the object in the level.""" + ... + + @property + def name(self) -> str: + """Name of the EnvironmentObject.""" + ... + + @property + def type(self) -> CityObjectLabel: + """Semantic tag.""" + ... + # endregion + + # region Dunder Methods + def __str__(self) -> str: + """Parses the EnvironmentObject to a string and shows them in command line.""" + ... + # endregion + + +class FloatColor(): + """Class that defines a float RGBA color.""" + + # region Instance Variables + @property + def r(self) -> float: + """Red color.""" + ... + + @property + def g(self) -> float: + """Green color.""" + ... + + @property + def b(self) -> float: + """Blue color.""" + ... + + @property + def a(self) -> float: + """Alpha channel.""" + ... + # endregion + + # region Methods + def __init__(self, r=.0, g=.0, b=.0, a=1.0): + """Initializes a color, black by default. + + Args: + r (float, optional): Red color. Defaults to .0. + g (float, optional): Green color. Defaults to .0. + b (float, optional): Blue color. Defaults to .0. + a (float, optional): Alpha channel. Defaults to 1.0. + """ + ... + # endregion + + # region Dunder Methods + def __eq__(self, __value: FloatColor) -> bool: ... + def __ne__(self, __value: FloatColor) -> bool: ... + # endregion + + +class GBufferTextureID(int, __CarlaEnum): + """Defines the identifiers of each GBuffer texture (See the method `carla.Sensor.listen_to_gbuffer`).""" + + # region Instance Variables + SceneColor = 0 + """The texture "SceneColor" contains the final color of the image.""" + SceneDepth = 1 + """The texture "SceneDepth" contains the depth buffer - linear in world units.""" + SceneStencil = 2 + """The texture "SceneStencil" contains the stencil buffer.""" + GBufferA = 3 + """The texture "GBufferA" contains the world-space normal vectors in the RGB channels. The alpha channel contains "per-object data".""" + GBufferB = 4 + """The texture "GBufferB" contains the metallic, specular and roughness in the RGB channels, respectively. The alpha channel contains a mask where the lower 4 bits indicate the shading model and the upper 4 bits contain the selective output mask.""" + GBufferC = 5 + """The texture "GBufferC" contains the diffuse color in the RGB channels, with the indirect irradiance in the alpha channel. + + If static lightning is not allowed, the alpha channel will contain the ambient occlusion instead.""" + GBufferD = 6 + """ + The contents of the "GBufferD" varies depending on the rendered object's material shading model (GBufferB): + MSM_Subsurface (2), MSM_PreintegratedSkin (3), MSM_TwoSidedFoliage (6): + RGB: Subsurface color. + A: Opacity. + MSM_ClearCoat (4): + R: Clear coat. + G: Roughness. + MSM_SubsurfaceProfile (5): + RGB: Subsurface profile. + MSM_Hair (7): + RG: World normal. + B: Backlit value. + MSM_Cloth (8): + RGB: Subsurface color. + A: Cloth value. + MSM_Eye (9): + RG: Eye tangent. + B: Iris mask. + A: Iris distance. + """ + GBufferE = 7 + """The texture "GBufferE" contains the precomputed shadow factors in the RGBA channels. This texture is unavailable if the selective output mask (GBufferB) does not have its 4th bit set.""" + GBufferF = 8 + """The texture "GBufferF" contains the world-space tangent in the RGB channels and the anisotropy in the alpha channel. This texture is unavailable if the selective output mask (GBufferB) does not have its 5th bit set.""" + Velocity = 9 + """The texture "Velocity" contains the screen-space velocity of the scene objects.""" + SSAO = 10 + """The texture "SSAO" contains the screen-space ambient occlusion texture.""" + CustomDepth = 11 + """The texture "CustomDepth" contains the Unreal Engine custom depth data.""" + CustomStencil = 12 + """The texture "CustomStencil" contains the Unreal Engine custom stencil data.""" + # endregion + + +class GearPhysicsControl(): + """Class that provides access to vehicle transmission details by defining a gear and when to run on it. This will be later used by `carla.VehiclePhysicsControl` to help simulate physics. + """ + + # region Instance Variables + @property + def ratio(self) -> float: + """The transmission ratio of the gear.""" + ... + + @property + def down_ratio(self) -> float: + """Quotient between current RPM and MaxRPM where the autonomous gear box should shift down.""" + + @property + def up_ratio(self) -> float: + """Quotient between current RPM and MaxRPM where the autonomous gear box should shift up.""" + # endregion + + # region Methods + def __init__(self, ratio=1.0, down_ratio=0.5, up_ratio=0.65): + """Class that provides access to vehicle transmission details by defining a gear and when to run on it. This will be later used by `carla.VehiclePhysicsControl` to help simulate physics. + + Args: + `ratio (float, optional)`: The transmission ratio of the gear. Defaults to 1.0.\n + `down_ratio (float, optional)`: Quotient between current RPM and MaxRPM where the autonomous gear box should shift down. Defaults to 0.5.\n + `up_ratio (float, optional)`: Quotient between current RPM and MaxRPM where the autonomous gear box should shift up. Defaults to 0.65.\n + """ + ... + # endregion + + # region Dunder Methods + def __eq__(self, __value: GearPhysicsControl) -> bool: ... + def __ne__(self, __value: GearPhysicsControl) -> bool: ... + def __str__(self) -> str: ... + # endregion + + +class GeoLocation(): + """Class that contains geographical coordinates simulated data. The `carla.Map` can convert simulation locations by using the tag in the OpenDRIVE file.""" + + # region Instance Variables + @property + def latitude(self) -> float: + """North/South value of a point on the map (degrees).""" + ... + + @property + def longitude(self) -> float: + """West/East value of a point on the map (degrees).""" + ... + + @property + def altitude(self) -> float: + """Height regarding ground level (meters).""" + ... + # endregion + + # region Methods + def __init__(self, latitude=0.0, longitude=0.0, altitude=0.0): + """Class that contains geographical coordinates simulated data. The `carla.Map` can convert simulation locations by using the tag in the OpenDRIVE file. + + Args: + `latitude (float, optional)`: North/South value of a point on the map (degrees). Defaults to 0.0.\n + `longitude (float, optional)`: West/East value of a point on the map (degrees). Defaults to 0.0.\n + `altitude (float, optional)`: Height regarding ground level (meters). Defaults to 0.0.\n + """ + ... + # endregion + + # region Dunder Methods + def __eq__(self, __value: GeoLocation) -> bool: ... + def __ne__(self, __value: GeoLocation) -> bool: ... + def __str__(self) -> str: ... + # endregion + + +class GnssMeasurement(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.""" + + # region Instance Variables + @property + def altitude(self) -> float: + """Height regarding ground level (meters).""" + ... + + @property + def latitude(self) -> float: + """North/South value of a point on the map (degrees).""" + ... + + @property + def longitude(self) -> float: + """West/East value of a point on the map (degrees).""" + ... + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class IMUMeasurement(SensorData): + """Class that defines the data registered by a `sensor.other.imu`, regarding the sensor's transformation according to the current `carla.World`. It essentially acts as accelerometer, gyroscope and compass.""" + + # region Instance Variables + @property + def accelerometer(self) -> Vector3D: + """Linear acceleration (m/s2).""" + ... + + @property + def compass(self) -> float: + """Orientation with regard to the North ([0.0, -1.0, 0.0] in Unreal Engine) (radians).""" + ... + + @property + def gyroscope(self) -> Vector3D: + """Angular velocity. (rad/s)""" + ... + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class Image(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. + + https://carla.readthedocs.io/en/latest/ref_sensors/""" + + # region Instance Variables + @property + def fov(self) -> float: + """Horizontal field of view of the image (degrees).""" + ... + + @property + def height(self) -> int: + """Image height in pixels.""" + ... + + @property + def width(self) -> int: + """Image width in pixels.""" + ... + + @property + def raw_data(self) -> bytes: + """Flattened array of pixel data, use reshape to create an image array.""" + ... + # endregion + + # region Methods + def convert(self, color_converter: ColorConverter): + """Converts the image following the `color_converter` pattern. + + Args: + `color_converter (ColorConverter)`\n + """ + + def save_to_disk(self, path: str, color_converter=ColorConverter.Raw): + """Saves the image to disk using a converter pattern stated as `color_converter`. The default conversion pattern is `Raw` that will make no changes to the image. + + Args: + `path (str)`:Path that will contain the image.\n + `color_converter (ColorConverter, optional)`: Default Raw will make no changes. Defaults to ColorConverter.Raw.\n + """ + # endregion + + # region Dunder Methods + def __getitem__(self, pos=int) -> Color: ... + + def __iter__(self) -> Iterator[Color]: + """Iterate over the `carla.Color` that form the image.""" + ... + + def __len__(self) -> int: ... + def __setitem__(self, pos: int, color: Color): ... + def __str__(self) -> str: ... + # endregion + + +class Junction(): + """Class that embodies the intersections on the road described in the OpenDRIVE file according to OpenDRIVE 1.4 standards.""" + + # region Instance Variables + @property + def id(self) -> int: + """Identifier found in the OpenDRIVE file.""" + ... + + @property + def bounding_box(self) -> BoundingBox: + """Bounding box encapsulating the junction lanes.""" + ... + # endregion + + # region Getters + def get_waypoints(self, lane_type: LaneType) -> list[tuple[Waypoint, Waypoint]]: + """Returns a list of pairs of waypoints. Every tuple on the list contains first an initial and then a final waypoint within the intersection boundaries that describe the beginning and the end of said lane along the junction. Lanes follow their OpenDRIVE definitions so there may be many different tuples with the same starting waypoint due to possible deviations, as this are considered different lanes. + + Args: + lane_type (LaneType): Type of lanes to get the waypoints. + + Returns: + list[tuple[Waypoint, Waypoint]] + """ + # endregion + + +class LabelledPoint(): + """Class that represent a position in space with a semantic label.""" + + # region Instance Variables + @property + def location(self) -> Location: + """Position in 3D space.""" + ... + + @property + def label(self) -> CityObjectLabel: + """Semantic tag of the point.""" + ... + # endregion + + +class Landmark(): + """Class that defines any type of traffic landmark or sign affecting a road. These class mediates between the OpenDRIVE 1.4 standard definition of the landmarks and their representation in the simulation. This class retrieves all the information defining a landmark in OpenDRIVE and facilitates information about which lanes does it affect and when. Landmarks will be accessed by `carla.Waypoint objects` trying to retrieve the regulation of their lane. Therefore some attributes depend on the waypoint that is consulting the landmark and so, creating the object.""" + + # region Instance Variables + @property + def road_id(self) -> 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.""" + ... + + @property + def distance(self) -> float: + """Distance between the landmark and the waypoint creating the object (querying `get_landmarks` or `get_landmarks_of_type`) (meters).""" + ... + + @property + def s(self) -> float: + """Distance where the landmark is positioned along the geometry of the road `road_id` (meters).""" + ... + + @property + def t(self) -> float: + """Lateral distance where the landmark is positioned from the edge of the road `road_id` (meters).""" + ... + + @property + def id(self) -> str: + """Unique ID of the landmark in the OpenDRIVE file.""" + ... + + @property + def name(self) -> str: + """Name of the landmark in the in the OpenDRIVE file.""" + ... + + @property + def is_dynamic(self) -> bool: + """Indicates if the landmark has state changes over time such as traffic lights.""" + ... + + @property + def orientation(self) -> LandmarkOrientation: + """Indicates which lanes the landmark is facing towards to (degrees).""" + ... + + @property + def z_offset(self) -> float: + """Height where the landmark is placed (meters).""" + ... + + @property + def country(self) -> str: + """Country code where the landmark is defined (default to OpenDRIVE is Germany 2017).""" + ... + + @property + def type(self) -> str: + """Type identifier of the landmark according to the country code.""" + ... + + @property + def sub_type(self) -> str: + """Subtype identifier of the landmark according to the country code.""" + + @property + def value(self) -> float: + """Value printed in the signal (e.g. speed limit, maximum weight, etc).""" + + @property + def unit(self) -> str: + """Units of measurement for the attribute `value`.""" + ... + + @property + def height(self) -> float: + """Total height of the signal (meters).""" + + @property + def width(self) -> float: + """Total width of the signal (meters).""" + + @property + def text(self) -> str: + """Additional text in the signal.""" + + @property + def h_offset(self) -> float: + """Orientation offset of the signal relative to the the definition of `road_id` at `s` in OpenDRIVE (meters).""" + ... + + @property + def pitch(self) -> float: + """Pitch rotation of the signal (Y-axis in UE coordinates system) (meters).""" + + @property + def roll(self) -> float: + """Roll rotation of the signal (X-axis in UE coordinates system) (meters).""" + + @property + def waypoint(self) -> 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.""" + + @property + def transform(self) -> Transform: + """The location and orientation of the landmark in the simulation.""" + # endregion + + # region Getters + def get_lane_validities(self) -> list[tuple[int, int]]: + """Returns which lanes the landmark is affecting to. As there may be specific lanes where the landmark is not effective, the return is a list of pairs containing ranges of the `lane_id` affected: + + Example: In a road with 5 lanes, being 3 not affected: [(from_lane1,to_lane2),(from_lane4,to_lane5)].""" + # endregion + + +class LandmarkOrientation(int, __CarlaEnum): + """Helper class to define the orientation of a landmark in the road. The definition is not directly translated from OpenDRIVE but converted for the sake of understanding.""" + + # region Instance Variables + Positive = 0 + """The landmark faces towards vehicles going on the same direction as the road's geometry definition (lanes 0 and negative in OpenDRIVE).""" + Negative = 1 + """The landmark faces towards vehicles going on the opposite direction to the road's geometry definition (positive lanes in OpenDRIVE).""" + Both = 2 + """Affects vehicles going in both directions of the road.""" + # endregion + + +class LandmarkType(Enum): + """Helper class containing a set of commonly used landmark types as defined by the default country code in the OpenDRIVE standard (Germany 2017). `carla.Landmark` does not reference this class. The landmark type is a string that varies greatly depending on the country code being used. This class only makes it easier to manage some of the most commonly used in the default set by describing them as an enum.""" + + # NOTE: Has no attributes for `values` and `names` + + # region Instance Variables + Danger = "101", + LanesMerging = "121", + CautionPedestrian = "133", + CautionBicycle = "138" + LevelCrossing = "150", + StopSign = "206", + YieldSign = "205", + MandatoryTurnDirection = "209", + MandatoryLeftRightDirection = "211", + TwoChoiceTurnDirection = "214", + Roundabout = "215", + PassRightLeft = "222", + AccessForbidden = "250", + AccessForbiddenMotorvehicles = "251", + AccessForbiddenTrucks = "253", + AccessForbiddenBicycle = "254", + AccessForbiddenWeight = "263", + AccessForbiddenWidth = "264", + AccessForbiddenHeight = "265", + AccessForbiddenWrongDirection = "267", + ForbiddenUTurn = "272", + MaximumSpeed = "274", + ForbiddenOvertakingMotorvehicles = "276", + ForbiddenOvertakingTrucks = "277", + AbsoluteNoStop = "283", + RestrictedStop = "286", + HasWayNextIntersection = "301", + PriorityWay = "306", + PriorityWayEnd = "307", + CityBegin = "310", + CityEnd = "311", + Highway = "330", + DeadEnd = "357", + RecomendedSpeed = "380", # NOTE: Wrong Spelling, but is named like this internally! + RecomendedSpeedEnd = "381", # NOTE: Wrong Spelling, but is named like this internally! + # endregion + + +class LaneChange(IntFlag, __CarlaEnum): + """Class that defines the permission to turn either left, right, both or none (meaning only going straight is allowed). This information is stored for every `carla.Waypoint` according to the OpenDRIVE file. The snippet in `carla.Map.get_waypoint` shows how a waypoint can be used to learn which turns are permitted.""" + + # region Instance Variables + NONE = 0 + """Traffic rules do not allow turning right or left, only going straight.""" + Right = 1 + """Traffic rules allow turning right.""" + Left = 2 + """Traffic rules allow turning left.""" + Both = 3 + """Traffic rules allow turning either right or left.""" + # endregion + + +class LaneInvasionEvent(SensorData): + """Class that defines lanes invasion for `sensor.other.lane_invasion`. It works only client-side and is dependant on OpenDRIVE to provide reliable information. The sensor creates one of this every time there is a lane invasion, which may be more than once per simulation step. Learn more about this here. + + https://carla.readthedocs.io/en/latest/ref_sensors/#lane-invasion-detector + """ + + # region Instance Variables + @property + def actor(self) -> Actor: + """Gets the actor the sensor is attached to, the one that invaded another lane.""" + + @property + def crossed_lane_markings(self) -> list[LaneMarking]: + """List of lane markings that have been crossed and detected by the sensor.""" + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class LaneMarking(): + """Class that gathers all the information regarding a lane marking according to OpenDRIVE 1.4 standard standard.""" + + # region Instance Variables + @property + def color(self) -> LaneMarkingColor: + """Actual color of the marking.""" + + @property + def lane_change(self) -> LaneChange: + """Permissions for said lane marking to be crossed.""" + + @property + def type(self) -> LaneMarkingType: + """Lane marking type.""" + + @property + def width(self) -> float: + """Horizontal lane marking thickness.""" + # endregion + + +class LaneMarkingColor(int, __CarlaEnum): + """Class that defines the lane marking colors according to OpenDRIVE 1.4.""" + + # region Instance Variables + White = 0 + Standard = 0 + """White by default.""" + Blue = 1 + Green = 2 + Red = 3 + Yellow = 4 + Other = 5 + # endregion + + +class LaneMarkingType(int, __CarlaEnum): + """Class that defines the lane marking types accepted by OpenDRIVE 1.4. The snippet in `carla.Map.get_waypoint` shows how a waypoint can be used to retrieve the information about adjacent lane markings. + + + Note on double types: Lane markings are defined under the OpenDRIVE standard that determines whereas a line will be considered "BrokenSolid" or "SolidBroken". For each road there is a center lane marking, defined from left to right regarding the lane's directions. The rest of the lane markings are defined in order from the center lane to the closest outside of the road. + """ + + # region Instance Variables + Other = 0 + Broken = 1 + Solid = 2 + SolidSolid = 3 + SolidBroken = 4 + BrokenSolid = 5 + BrokenBroken = 6 + BottsDots = 7 + Grass = 8 + Curb = 9 + NONE = 0 + # endregion + + +class LaneType(IntFlag, __CarlaEnum): + """ + Class that defines the possible lane types accepted by OpenDRIVE 1.4. + This standards define the road information. The snippet in `carla.Map.get_waypoint` + makes use of a waypoint to get the current and adjacent lane types. + """ + + # region Instance Variables + Any = -2 + NONE = 1 + """Every type except for `NONE`.""" + Driving = 2 + Stop = 4 + Shoulder = 8 + Biking = 16 + Sidewalk = 32 + Border = 64 + Restricted = 128 + Parking = 256 + Bidirectional = 512 + Median = 1024 + Special1 = 2048 + Special2 = 4096 + Special3 = 8192 + RoadWorks = 16384 + Tram = 32768 + Rail = 65536 + Entry = 131072 + Exit = 262144 + OffRamp = 524288 + OnRamp = 1048576 + # endregion + + +class LidarDetection(): + """Data contained inside a `carla.LidarMeasurement`. Each of these represents one of the points in the cloud with its location and its associated intensity.""" + # region Instance Variables + @property + def point(self) -> Location: + """Point in xyz coordinates (meters).""" + @property + def intensity(self) -> float: + """Computed intensity for this point as a scalar value between [0.0 , 1.0].""" + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class LidarMeasurement(SensorData): + """Class that defines the LIDAR data retrieved by a `sensor.lidar.ray_cast`. This essentially simulates a rotating LIDAR using ray-casting. Learn more about this here. + + https://carla.readthedocs.io/en/latest/ref_sensors/#lidar-raycast-sensor + """ + # region Instance Variables + @property + def channels(self) -> int: + """Number of lasers shot.""" + + @property + def horizontal_angle(self) -> float: + """Horizontal angle the LIDAR is rotated at the time of the measurement (radians).""" + + @property + def raw_data(self) -> bytes: + """Received list of 4D points. Each point consists of [x,y,z] coordinates plus the intensity computed for that point.""" + # endregion + + # region Methods + def save_to_disk(self, path: str): + """Saves the point cloud to disk as a `.ply` file describing data from 3D scanners. The files generated are ready to be used within `MeshLab`, an open source system for processing said files. Just take into account that axis may differ from Unreal Engine and so, need to be reallocated. + + Args: + path (str) + """ + # endregion + + # region Getters + def get_point_count(self, channel: int): + """Retrieves the number of points sorted by channel that are generated by this measure. Sorting by channel allows to identify the original channel for every point. + + Args: + channel (int) + """ + # endregion + + # region Dunder Methods + def __getitem__(self, pos: int) -> LidarDetection: ... + + def __iter__(self) -> Iterator[LidarDetection]: + """Iterate over the carla.LidarDetection retrieved as data.""" + ... + + def __len__(self): ... + def __setitem__(self, pos: int, detection: LidarDetection): ... + def __str__(self) -> str: ... + # endregion + + +class Light(): + """This class exposes the lights that exist in the scene, except for vehicle lights. The properties of a light can be queried and changed at will. Lights are automatically turned on when the simulator enters night mode (sun altitude is below zero).""" + + # region Instance Variables + @property + def color(self) -> Color: + """Color of the light.""" + ... + + @property + def id(self) -> int: + """Identifier of the light.""" + ... + + @property + def intensity(self) -> float: + """Intensity of the light. (lumens)""" + + @property + def is_on(self) -> bool: + """Switch of the light. It is `True` when the light is on. When the night mode starts, this is set to `True`.""" + ... + + @property + def location(self) -> Location: + """Position of the light (meters).""" + ... + + @property + def light_group(self) -> LightGroup: + """Group the light belongs to.""" + + @property + def light_state(self) -> LightState: + """State of the light. Summarizes its attributes, group, and if it is on/off.""" + # endregion + + # region Methods + def turn_off(self): + """Switches off the light.""" + ... + + def turn_on(self): + """Switches on the light.""" + ... + # endregion + + # region Setters + def set_color(self, color: Color): + """Changes the color of the light to color. + + Args: + color (Color) + """ + ... + + def set_intensity(self, intensity: float): + """Changes the intensity of the light to `intensity`. + + Args: + intensity (float): (lumens) + """ + + def set_light_group(self, light_group: LightGroup): + """Changes the light to the group `light_group`. + + Args: + light_group (LightGroup) + """ + + def set_light_state(self, light_state: LightState): + """Changes the state of the light to `light_state`. This may change attributes, group and turn the light on/off all at once. + + + Args: + light_state (LightState) + """ + # endregion + + +class LightGroup(int, __CarlaEnum): + """This class categorizes the lights on scene into different groups. These groups available are provided as a enum values that can be used as flags. + + + Note. So far, though there is a `vehicle` group, vehicle lights are not available as `carla.Light` objects. These have to be managed using `carla.Vehicle` and `carla.VehicleLightState`.""" + + NONE = 0 + """All lights.""" + Vehicle = 1 + Street = 2 + Building = 3 + Other = 4 + + +class LightManager(): + """This class handles the lights in the scene. Its main use is to get and set the state of groups or lists of lights in one call. An instance of this class can be retrieved by the `carla.World.get_lightmanager()`. + + + Note. So far, though there is a `vehicle` group, vehicle lights are not available as `carla.Light` objects. These have to be managed using `carla.Vehicle` and `carla.VehicleLightState`. + """ + + # region Methods + def is_active(self, lights: list[Light]) -> list[bool]: + """Returns a list with booleans stating if the elements in `lights` are switched on/off. + + Args: + `lights (list[Light])`: List of lights to be queried.\n + + Returns: + `list[bool]`\n + """ + + def turn_off(self, lights: list[Light]): + """Switches off all the lights in `lights`. + + + Args: + `lights (list[Light])`: List of lights to be switched off.\n + """ + + def turn_on(self, lights: list[Light]): + """Switches on all the lights in `lights`. + + + Args: + `lights (list[Light])`: List of lights to be switched on.\n + """ + # endregion + + # region Getters + def get_all_lights(self, light_group: LightGroup = LightGroup.NONE) -> list[Light]: + """Returns a list containing the lights in a certain group. By default, the group is None. + + Args: + `light_group (LightGroup, optional)`: Group to filter the lights returned. Defaults to LightGroup.NONE.\n + """ + + def get_color(self, lights: list[Light]) -> list[Color]: + """Returns a list with the colors of every element in `lights`. + + + Setter: `carla.LightManager.set_color` + + Args: + `lights (list[Light])`: List of lights to be queried.\n + + Returns: + `list[Color]`: _description_\n + """ + + def get_intensity(self, lights: list[Light]) -> list[float]: + """Returns a list with the intensity of every element in `lights`. + + Args: + `lights (list[Light])`: List of lights to be queried.\n + + Returns: + `list[float]`: (lumens)\n + """ + + def get_light_group(self, lights: list[Light]) -> list[LightGroup]: + """Returns a list with the group of every element in `lights`. + + + Setter: `carla.LightManager.set_light_group` + + Args: + `lights (list[Light])`: List of lights to be queried.\n + """ + + def get_light_state(self, lights: list[Light]) -> list[LightState]: + """Returns a list with the state of all the attributes of every element in `lights`. + + + Setter: `carla.LightManager.set_light_state` + + Args: + `lights (list[Light])`: List of lights to be queried.\n + """ + + def get_turned_off_lights(self, light_group: LightGroup) -> list[Light]: + """Returns a list containing lights switched off in the scene, filtered by group. + + Args: + `light_group (LightGroup)`: List of lights to be queried.\n + """ + + def get_turned_on_lights(self, light_group: LightGroup) -> list[Light]: + """Returns a list containing lights switched on in the scene, filtered by group. + + Args: + `light_group (LightGroup)`: List of lights to be queried.\n + """ + # endregion + + # region Setters + def set_active(self, lights: list[Light], active: list[bool]): + """Switches on/off the elements in lights. + + Args: + `lights (list[Light])`: List of lights to be switched on/off.\n + `active (list[bool])`: List of booleans to be applied.\n + """ + + def set_color(self, lights: list[Light], color: Color): + """Changes the color of the elements in `lights` to `color`. + + Args: + `lights (list[Light])`: List of lights to be changed.\n + `color (Color)`: Color to be applied.\n + """ + + def set_colors(self, lights: list[Light], colors: list[Color]): + """Changes the color of each element in lights to the corresponding in colors. + + Args: + `lights (list[Light])`: List of lights to be changed.\n + `colors (list[Color])`: List of colors to be applied.\n + """ + + def set_day_night_cycle(self, active: bool): + """All scene lights have a day-night cycle, automatically turning on and off with the altitude of the sun. This interferes in cases where full control of the scene lights is required, so setting this to `False` deactivates it. It can reactivated by setting it to `True`. + + + Args: + `active (bool)`: (De)activation of the day-night cycle.\n + """ + + def set_intensities(self, lights: list[Light], intensities: list[float]): + """Changes the intensity of each element in lights to the corresponding in intensities. + + Args: + `lights (list[Light])`: List of lights to be changed.\n + `intensities (list[float])`: Intensity to be applied (lumens).\n + """ + + def set_intensity(self, lights: list[Light], intensity: float): + """Changes the intensity of every element in `lights` to `intensity`. + + + Getter: `carla.LightManager.get_intensity` + + Args: + `lights (list[Light])`: List of lights to be changed.\n + `intensity (float)`: Intensity to be applied.\n + """ + + def set_light_group(self, lights: list[Light], light_group: LightGroup): + """Changes the group of every element in `lights` to `light_group`. + + + Getter: carla.LightManager.get_light_group + + Args: + `lights (list[Light])`: List of lights to be changed.\n + `light_group (LightGroup)`: Group to be applied.\n + """ + + def set_light_groups(self, lights: list[Light], light_groups: list[LightGroup]): + """Changes the group of each element in `lights` to the corresponding in `light_groups`. + + Args: + `lights (list[Light])`: List of lights to be changed.\n + `light_groups (list[LightGroup])`: List of groups to be applied.\n + """ + + def set_light_state(self, lights: list[Light], light_state: LightState): + """Changes the state of the attributes of every element in lights to light_state. + + + Getter: `carla.LightManager.get_light_state` + + Args: + `lights (list[Light])`: List of lights to be changed.\n + `light_state (LightState)`: State of the attributes to be applied.\n + """ + + def set_light_states(self, lights: list[Light], light_states: list[LightState]): + """Changes the state of the attributes of each element in lights to the corresponding in light_states. + + Args: + `lights (list[Light])`: List of lights to be changed.\n + `light_states (list[LightState])`: List of state of the attributes to be applied.\n + """ + # endregion + + +class LightState(): + """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. + """ + + # region Instance Variables + @property + def intensity(self) -> float: + """Intensity of a light.""" + + @property + def color(self) -> Color: + """Color of a light.""" + + @property + def group(self) -> LightGroup: + """Group a light belongs to.""" + + @property + def active(self) -> bool: + """Switch of a light. It is `True` when the light is on.""" + # endregion + + # region Methods + def __init__(self, intensity=0.0, color=Color, group=LightGroup.NONE, active=False): + """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. + + Args: + `intensity (float, optional)`: Intensity of a light (lumens). Defaults to 0.0.\n + `color (_type_, optional)`: Color of a light. Defaults to Color.\n + `group (_type_, optional)`: Group a light belongs to. Defaults to LightGroup.NONE.\n + `active (bool, optional)`: Switch of a light. It is True when the light is on. Defaults to False.\n + """ + # endregion + + +class Location(Vector3D): + """Represents a spot in the world.""" + # region Instance Variables + @property + def x(self) -> float: + """Distance from origin to spot on X axis (meter).""" + @property + def y(self) -> float: + """Distance from origin to spot on Y axis (meter).""" + @property + def z(self) -> float: + """Distance from origin to spot on Z axis. (meter)""" + # endregion + + # region Methods + @overload + def __init__(self, rhs: Vector3D): ... + + @overload + def __init__(self, x: float=0.0, y: float=0.0, z: float=0.0): ... + + def __init__(self, x: float=0.0, y: float=0.0, z: float=0.0): + """Represents a spot in the world. + + Args: + `x (float, optional)`: Distance from origin to spot on X axis (meter). Defaults to 0.0.\n + `y (float, optional)`: Distance from origin to spot on Y axis (meter). Defaults to 0.0.\n + `z (float, optional)`: Distance from origin to spot on Z axis (meter). Defaults to 0.0.\n + """ + ... + + def distance(self, location: Location) -> float: + """Returns Euclidean distance from this location to another one. + + Args: + `location (Location)`: The other point to compute the distance with.\n + + Returns: + `float`: (meters)\n + """ + # endregion + + # region Dunder Methods + def __abs__(self) -> Location: + """Returns a Location with the absolute value of the components x, y and z.""" + + def __eq__(self, __value: Location) -> bool: + """Returns `True` if both locations are the same point in space.""" + ... + + def __ne__(self, __value: object) -> bool: + """Returns `True` if both locations are different points in space.""" + ... + + def __str__(self) -> str: + """Parses the axis' values to string.""" + ... + # endregion + pass + + +class Map(): + """Class containing the road information and waypoint managing. Data is retrieved from an OpenDRIVE file that describes the road. A query system is defined which works hand in hand with `carla.Waypoint` to translate geometrical information from the .xodr to natural world points. CARLA is currently working with OpenDRIVE 1.4 standard.""" + + # region Instance Variables + @property + def name(self) -> str: + """The name of the map. It corresponds to the .umap from Unreal Engine that is loaded from a CARLA server, which then references to the .xodr road description.""" + # endregion + + # region Methods + def __init__(self, name: str, xodr_content: str): + """Constructor for this class. Though a map is automatically generated when initializing the world, using this method in no-rendering mode facilitates working with an .xodr without any CARLA server running. + + Args: + `name (str)`: Name of the current map.\n + `xodr_content (str)`: xodr content in string format.\n + """ + ... + + def cook_in_memory_map(self, path: str): + """Generates a binary file from the CARLA map containing information used by the Traffic Manager. This method is only used during the import process for maps. + + Args: + `path (str)`: Path to the intended location of the stored binary map file.\n + """ + + def generate_waypoints(self, distance: float) -> list[Waypoint]: + """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. + + Args: + `distance (float)`: Approximate distance between waypoints (meters).\n + + Returns: + `list[Waypoint]`\n + """ + + def save_to_disk(self, path: str): + """Saves the .xodr OpenDRIVE file of the current map to disk. + + Args: + `path (str)`: Path where the file will be saved.\n + """ + ... + + def to_opendrive(self) -> str: + """Returns the .xodr OpenDRIVe file of the current map as string. + + Returns: + `str`\n + """ + + def transform_to_geolocation(self, location: Location) -> GeoLocation: + """Converts a given `location`, a point in the simulation, to a `carla.GeoLocation`, which represents world coordinates. The geographical location of the map is defined inside OpenDRIVE within the tag . + + + Args: + `location (Location)`\n + + Returns: + `GeoLocation`\n + """ + ... + # endregion + + # region Getters + def get_all_landmarks(self) -> list[Landmark]: + """Returns all the landmarks in the map. Landmarks retrieved using this method have a `null` waypoint.""" + ... + + def get_all_landmarks_from_id(self, opendrive_id: str) -> list[Landmark]: + """Returns the landmarks with a certain OpenDRIVE ID. Landmarks retrieved using this method have a `null` waypoint. + + Args: + `opendrive_id (str)`: The OpenDRIVE ID of the landmarks.\n + """ + ... + + def get_all_landmarks_of_type(self, type: Union[str, LandmarkType]) -> list[Landmark]: + """Returns the landmarks of a specific type. Landmarks retrieved using this method have a null waypoint. + + Args: + `type (str)`: The type of the landmarks.\n + """ + ... + + def get_crosswalks(self) -> list[Location]: + """Returns a list of locations with all crosswalk zones in the form of closed polygons. The first point is repeated, symbolizing where the polygon begins and ends. + """ + ... + + def get_landmark_group(self, landmark: Landmark) -> list[Landmark]: + """Returns the landmarks in the same group as the specified landmark (including itself). Returns an empty list if the landmark does not belong to any group. + + Args: + `landmark (Landmark)`: A landmark that belongs to the group.\n + """ + ... + + def get_spawn_points(self) -> list[Transform]: + """Returns a list of recommendations made by the creators of the map to be used as spawning points for the vehicles. The list includes carla.Transform objects with certain location and orientation. Said locations are slightly on-air in order to avoid Z-collisions, so vehicles fall for a bit before starting their way. + """ + ... + + def get_topology(self) -> list[tuple[Waypoint, Waypoint]]: + """Returns a list of tuples describing a minimal graph of the topology of the OpenDRIVE file. The tuples contain pairs of waypoints located either at the point a road begins or ends. The first one is the origin and the second one represents another road end that can be reached. This graph can be loaded into NetworkX to work with. + + Output could look like this: `[(w0, w1), (w0, w2), (w1, w3), (w2, w3), (w0, w4)]`. + """ + ... + + @overload + def get_waypoint(self, location: Location, project_to_road: Literal[True]=True, lane_type: Literal[LaneType.Driving, LaneType.Any]=LaneType.Driving) -> Waypoint: + ... + + @overload + def get_waypoint(self, location: Location, project_to_road :bool | None=True, lane_type: LaneType=LaneType.Driving) -> Waypoint | None: + ... + + def get_waypoint(self, location: Location, project_to_road: bool | None=True, lane_type: LaneType=LaneType.Driving) -> Waypoint | None: + """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. + + Args: + `location (Location)`: Location used as reference for the carla.Waypoint (meters).\n + `project_to_road (bool, optional)`: If `True`, the waypoint will be at the center of the closest lane. If `False`, the waypoint will be exactly in location. `None` means said location does not belong to a road. Defaults to True.\n + `lane_type (_type_, optional)`: Limits the search for nearest lane to one or various lane types that can be flagged. Defaults to LaneType.Driving.\n + """ + ... + + def get_waypoint_xodr(self, road_id: int, lane_id: int, s: float) -> Waypoint | None: + """Returns a waypoint if all the parameters passed are correct. Otherwise, returns `None`. + + Args: + `road_id (int)`: ID of the road to get the waypoint.\n + `lane_id (int)`: ID of the lane to get the waypoint.\n + `s (float)`: Specify the length from the road start (meters).\n + """ + ... + # endregion + + +class MapLayer(Flag, __CarlaEnum): + """Class that represents each manageable layer of the map. Can be used as flags. + + + WARNING: Only "Opt" maps are able to work with map layers.""" + NONE = 0 + Buildings = 1 + Decals = 2 + Foliage = 4 + Ground = 8 + ParkedVehicles = 16 + Particles = 32 + Props = 64 + StreetLights = 128 + Walls = 256 + All = 65535 + """All layers selected.""" + + +class MaterialParameter(int, __CarlaEnum): + """Class that represents material parameters. Not all objects in the scene contain all parameters.""" + + # region Instance Variables + Normal = 0 + """The Normal map of the object. Present in all objects.""" + AO_Roughness_Metallic_Emissive = 1 + """A texture where each color channel represent a property of the material (R: Ambient occlusion, G: Roughness, B: Metallic, A: Emissive/Height map in some objects).""" + Diffuse = 2 + """The Diffuse texture of the object. Present in all objects.""" + Emissive = 3 + """Emissive texture. Present in a few objects.""" + # endregion + + +class ObstacleDetectionEvent(SensorData): + """Class that defines the obstacle data for `sensor.other.obstacle`. Learn more about this here. + + https://carla.readthedocs.io/en/latest/ref_sensors/#obstacle-detector + """ + # region Instance Variables + @property + def actor(self) -> Actor: + """The actor the sensor is attached to.""" + ... + + @property + def other_actor(self) -> Actor: + """The actor or object considered to be an obstacle.""" + ... + + @property + def distance(self) -> float: + """Distance between actor and other (meters).""" + ... + # endregion + + # region Dunder methods + def __str__(self) -> str: ... + # endregion + + +class OpendriveGenerationParameters(): + """This class defines the parameters used when generating a world using an OpenDRIVE file.""" + # region Instance Variables + @property + def vertex_distance(self) -> float: + """Distance between vertices of the mesh generated. Default is 2.0.""" + ... + + @property + def max_road_length(self) -> float: + """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.""" + ... + + @property + def wall_height(self) -> float: + """Height of walls created on the boundaries of the road. These prevent vehicles from falling off the road. Default is 1.0.""" + ... + + @property + def additional_width(self) -> float: + """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.""" + ... + + @property + def smooth_junctions(self) -> bool: + """If `True`, the mesh at junctions will be smoothed to prevent issues where roads blocked other roads. Default is `True`.""" + ... + + @property + def enable_mesh_visibility(self) -> bool: + """If `True`, the road mesh will be rendered. Setting this to False should reduce the rendering overhead. Default is True.""" + ... + + @property + def enable_pedestrian_navigation(self) -> bool: + """If `True`, Pedestrian navigation will be enabled using Recast tool. For very large maps it is recommended to disable this option. Default is `True`.""" + ... + # endregion + + # region Methods + def __init__(self, vertex_distance: float =2.0, + max_road_length:float = 50.0, + wall_height:float = 1.0, + additional_width: float=0.6, + smooth_junctions: bool =True, + enable_mesh_visibility: bool=True, + enable_pedestrian_navigation: bool=True): + """Constructor method""" + ... + + +class OpticalFlowImage(SensorData): + """Class that defines an optical flow image of 2-Dimension float (32-bit) vectors representing the optical flow detected in the field of view. The components of the vector represents the displacement of an object in the image plane. Each component outputs values in the normalized range [-2,2] which scales to [-2 size, 2 size] with size being the total resolution in the corresponding component.""" + # region Instance Variables + @property + def fov(self) -> float: + """Horizontal field of view of the image. (degrees)""" + ... + + @property + def height(self) -> int: + """Image height in pixels.""" + ... + + @property + def width(self) -> int: + """Image width in pixels.""" + ... + + @property + def raw_data(self) -> bytes: + """Flattened array of pixel data, use reshape to create an image array.""" + # endregion + + # region Getters + def get_color_coded_flow(self) -> Image: + """Visualization helper. Converts the optical flow image to an RGB image.""" + ... + # endregion + + # region Dunder Methods + def __getitem__(self, pos: int) -> OpticalFlowPixel: ... + + def __iter__(self) -> Iterator[OpticalFlowPixel]: + """Iterate over the `carla.OpticalFlowPixel `that form the image.""" + + def __len__(self) -> int: ... + def __setitem__(self, pos: int, color: Color): ... + def __str__(self) -> str: ... + # endregion + + +class OpticalFlowPixel(): + """Class that defines a 2 dimensional vector representing an optical flow pixel.""" + + # region Instance Variables + @property + def x(self) -> float: + """Optical flow in the x component.""" + ... + + @property + def y(self) -> float: + """Optical flow in the y component.""" + # endregion + + # region Methods + def __init__(self, x=.0, y=.0): + """Initializes the Optical Flow Pixel. Zero by default. + + Args: + `x (float, optional)`: Optical flow in the x component. Defaults to .0.\n + `y (float, optional)`: Optical flow in the y component. Defaults to .0.\n + """ + ... + # endregion + + # region Dunder Methods + def __eq__(self, __value: OpticalFlowPixel) -> bool: ... + def __ne__(self, __value: OpticalFlowPixel) -> bool: ... + def __str__(self) -> str: ... + # endregion + + +class Osm2Odr(): + """Class that converts an OpenStreetMap map to OpenDRIVE format, so that it can be loaded in CARLA. Find out more about this feature in the docs. + + https://carla.readthedocs.io/en/latest/tuto_G_openstreetmap/ + """ + # region Methods + @staticmethod + def convert(osm_file: str, settings: Osm2OdrSettings) -> str: + """Takes the content of an `.osm` file (OpenStreetMap format) and returns the content of the `.xodr` (OpenDRIVE format) describing said map. + + Args: + `osm_file (str)`: The content of the input OpenStreetMap file parsed as string.\n + `settings (Osm2OdrSettings)`: Parameterization for the conversion.\n + + Returns: + `str`\n + """ + # endregion + + +class Osm2OdrSettings(): + """Helper class that contains the parameterization that will be used by carla.Osm2Odr to convert an OpenStreetMap map to OpenDRIVE format. Find out more about this feature in the docs. + + https://carla.readthedocs.io/en/latest/tuto_G_openstreetmap/ + """ + + # region Instance Variables + @property + def use_offsets(self) -> bool: + """Enables the use of offset for the conversion. The offset will move the origin position of the map. Default value is False. + """ + ... + + @property + def offset_x(self) -> float: + """Offset in the X axis. Default value is 0.0 (meters).""" + ... + + @property + def offset_y(self) -> float: + """Offset in the Y axis. Default value is 0.0 (meters).""" + ... + + @property + def default_lane_width(self) -> float: + """Width of the lanes described in the resulting XODR map. Default value is 4.0 (meter).""" + ... + + @property + def elevation_layer_height(self) -> float: + """Defines the height separating two different OpenStreetMap layers. Default value is 0.0.""" + ... + + @property + def center_map(self) -> bool: + """When this option is enabled, the geometry of the map will be displaced so that the origin of coordinates matches the center of the bounding box of the entire road map.""" + ... + + @property + def proj_string(self) -> str: + """Defines the `proj4` string that will be used to compute the projection from geocoordinates to cartesian coordinates. This string will be written in the resulting OpenDRIVE unless the options `use_offsets` or `center_map` are enabled as these options override some of the definitions in the string.""" + ... + + @property + def generate_traffic_lights(self) -> bool: + """Indicates wether to generate traffic light data in the OpenDRIVE. Road types defined by `set_traffic_light_excluded_way_types(way_types)` will not generate traffic lights.""" + ... + + @property + def all_junctions_with_traffic_lights(self) -> bool: + """When disabled, the converter will generate traffic light data from the OpenStreetMaps data only. When enabled, all junctions will generate traffic lights.""" + # endregion + + # region Setters + def set_osm_way_types(self, way_types: list[str]): + """Defines the OpenStreetMaps road types that will be imported to OpenDRIVE. By default the road types imported are: + `motorway`, `motorway_link`, `trunk`, `trunk_link`, `primary`, `primary_link`, `secondary`, `secondary_link`, `tertiary`, `tertiary_link`, `unclassified`, `residential`. + For a full list of road types check here. + + https://wiki.openstreetmap.org/wiki/Main_Page + + Args: + `way_types (list[str])`: The list of road types.\n + """ + + def set_traffic_light_excluded_way_types(self, way_types: list[str]): + """Defines the OpenStreetMaps road types that will not generate traffic lights even if `generate_traffic_lights` is enabled. By default the road types excluded are + `motorway_link`, `primary_link`, `secondary_link`, `tertiary_link` + + Args: + `way_types (list[str])`: The list of road types.\n + """ + # endregion + + +class RadarDetection(): + """Data contained inside a `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.""" + + # region Instance Variables + @property + def altitude(self) -> float: + """Altitude angle of the detection (radians).""" + ... + + @property + def azimuth(self) -> float: + """Azimuth angle of the detection (radians).""" + ... + + @property + def depth(self) -> float: + """Distance from the sensor to the detection position (meters).""" + ... + + @property + def velocity(self) -> float: + """The velocity of the detected object towards the sensor (m/s).""" + ... + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class RadarMeasurement(SensorData): + """Class that defines and gathers the measures registered by a `sensor.other.radar`, representing a wall of points in front of the sensor with a distance, angle and velocity in relation to it. The data consists of a `carla.RadarDetection` array. Learn more about this here. + + https://carla.readthedocs.io/en/latest/ref_sensors/#radar-sensor + """ + + # region Instance Variables + @property + def raw_data(self) -> bytes: + """The complete information of the `carla.RadarDetection` the radar has registered. + """ + # endregion + + # region Getters + def get_detection_count(self) -> int: + """Retrieves the number of entries generated, same as `__str__()`.""" + # endregion + + # region Dunder Methods + def __getitem__(self, pos: int) -> RadarDetection: ... + + def __iter__(self) -> Iterator[RadarDetection]: + """Iterate over the `carla.RadarDetection` retrieved as data.""" + + def __len__(self) -> int: ... + def __setitem__(self, pos: int, detection: RadarDetection): ... + def __str__(self) -> str: ... + # endregion + + +class 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. + + The constructor method follows a specific order of declaration: `(pitch, yaw, roll)`, which corresponds to `(Y-rotation,Z-rotation,X-rotation)`. + """ + + # region Instance Variables + @property + def pitch(self) -> float: + """Y-axis rotation angle (degrees).""" + ... + + @property + def yaw(self) -> float: + """Z-axis rotation angle (degrees).""" + ... + + @property + def roll(self) -> float: + """X-axis rotation angle (degrees).""" + ... + # endregion + + # region Methods + def __init__(self, pitch=.0, yaw=.0, roll=.0): + """+ 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. + + Args: + `pitch (float, optional)`: Y-axis rotation angle (degrees). Defaults to .0.\n + `yaw (float, optional)`: Z-axis rotation angle (degrees). Defaults to .0.\n + `roll (float, optional)`: X-axis rotation angle (degrees). Defaults to .0.\n + """ + ... + # endregion + + # region Getters + def get_forward_vector(self) -> Vector3D: + """Computes the vector pointing forward according to the rotation of the object.""" + ... + + def get_right_vector(self) -> Vector3D: + """Computes the vector pointing to the right according to the rotation of the object.""" + ... + + def get_up_vector(self) -> Vector3D: + """Computes the vector pointing upwards according to the rotation of the object.""" + ... + # endregion + + # region Dunder Methods + def __eq__(self, __value: Rotation) -> bool: + """Returns `True` if both rotations represent the same orientation for every axis.""" + ... + + def __ne__(self, __value: Rotation) -> bool: + ... + + def __str__(self) -> str: ... + # endregion + + +class SemanticLidarDetection(): + """Data contained inside a `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.""" + + # region Instance Variables + @property + def point(self) -> Location: + """[x,y,z] coordinates of the point (meters).""" + @property + def cos_inc_angle(self) -> float: + """Cosine of the incident angle between the ray, and the normal of the hit object.""" + @property + def object_idx(self) -> int: + """ID of the actor hit by the ray.""" + @property + def object_tag(self) -> int: + """`Semantic tag` of the component hit by the ray.""" + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class SemanticLidarMeasurement(SensorData): + """Class that defines the semantic LIDAR data retrieved by a `sensor.lidar.ray_cast_semantic`. This essentially simulates a rotating LIDAR using ray-casting. Learn more about this here. + + https://carla.readthedocs.io/en/latest/ref_sensors/#semanticlidar-raycast-sensor + """ + + # region Instance Variables + @property + def channels(self) -> int: + """Number of lasers shot.""" + @property + def horizontal_angle(self) -> float: + """Horizontal angle the LIDAR is rotated at the time of the measurement (radians).""" + @property + def raw_data(self) -> 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.""" + # endregion + + # region Methods + def save_to_disk(self, path: str): + """Saves the point cloud to disk as a `.ply` file describing data from 3D scanners. The files generated are ready to be used within `MeshLab`, an open-source system for processing said files. Just take into account that axis may differ from Unreal Engine and so, need to be reallocated. + + Args: + `path (str)`\n + """ + # endregion + + # region Getters + def get_point_count(self, channel: int): + """Retrieves the number of points sorted by channel that are generated by this measure. Sorting by channel allows to identify the original channel for every point. + + Args: + `channel (int)`\n + """ + # endregion + + # region Dunder Methods + def __getitem__(self, pos: int) -> SemanticLidarDetection: ... + + def __iter__(self) -> Iterator[SemanticLidarDetection]: + """Iterate over the `carla.SemanticLidarDetection` retrieved as data.""" + ... + + def __len__(self): ... + def __setitem__(self, pos: int, detection: SemanticLidarDetection): ... + def __str__(self) -> str: ... + # endregion + + +class Sensor(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` 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, but the list of those available in CARLA so far goes as follow. + + https://carla.readthedocs.io/en/latest/ref_sensors/ + + Receive data on every tick. + - Depth camera. + - Gnss sensor. + - IMU sensor. + - Lidar raycast. + - SemanticLidar raycast. + - Radar. + - RGB camera. + - RSS sensor. + - Semantic Segmentation camera. + + Only receive data when triggered. + - Collision detector. + - Lane invasion detector. + - Obstacle detector. + """ + + # region Instance Variables + #@property + #def is_listening() -> bool: + # """When `True` the sensor will be waiting for data.""" + # endregion + + # region Methods + + def is_listening(self) -> bool: + """Returns whether the sensor is in a listening state.""" + + def is_listening_gbuffer(self, gbuffer_id: GBufferTextureID) -> bool: + """Returns whether the sensor is in a listening state for a specific GBuffer texture. + + Args: + `gbuffer_id (GBufferTextureID)`: The ID of the target Unreal Engine GBuffer texture.\n + """ + + def listen(self, callback: Callable[[__SensorData], Any]) -> None: + """ + The function the sensor will be calling to every time a new measurement is received. + This function needs for an argument containing an object type `carla.SensorData` to work with. + + Args: + `callback (Callable[[SensorData], Any])`: The called function with one argument containing the sensor data.\n + """ + + def listen_to_gbuffer(self, gbuffer_id: GBufferTextureID, callback: Callable[[__SensorData], Any]) -> None: + """ + The function the sensor will be calling to every time the desired GBuffer texture is received. + This function needs for an argument containing an object type `carla.SensorData` to work with. + + Args: + `gbuffer_id (GBufferTextureID)`: The ID of the target Unreal Engine GBuffer texture.\n + `callback (Callable[[SensorData], Any])`: The called function with one argument containing the received GBuffer texture.\n + """ + + def stop(self): + """Commands the sensor to stop listening for data.""" + + def stop_gbuffer(self, gbuffer_id: GBufferTextureID): + """Commands the sensor to stop listening for the specified GBuffer texture. + + Args: + `gbuffer_id (GBufferTextureID)`: The ID of the Unreal Engine GBuffer texture.\n + """ + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class SensorData(): + """ + 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`. + """ + # region Instance Variables + @property + def frame(self) -> int: + """Frame count when the data was generated.""" + ... + + @property + def timestamp(self) -> float: + """Simulation-time(seconds) when the data was generated.""" + ... + + @property + def transform(self) -> Transform: + """Sensor's transform when the data was generated.""" + # endregion + + +class TextureColor(): + """ + Class representing a texture object to be uploaded to the server. + Pixel format is RGBA, uint8 per channel. + """ + # region Instance Variables + @property + def width(self) -> int: + """X-coordinate size of the texture.""" + @property + def height(self) -> int: + """Y-coordinate size of the texture.""" + # endregion + + # region Methods + def __init__(self, width: int, height: int): + """Initializes a the texture with a `(width, height)` size. + + Args: + `width (int)`: X-coordinate size of the texture.\n + `height (int)`: Y-coordinate size of the texture.\n + """ + ... + # endregion + + # region Getters + def get(self, x: int, y: int) -> Color: + """Get the `(x,y)` pixel data.""" + + # endregion + + # region Setters + def set(self, x: int, y: int, value: Color): + """Sets the `(x,y)` pixel data with `value`.""" + + def set_dimensions(self, width: int, height: int): + """Resizes the texture to te specified dimensions.""" + # endregion + + +class TextureFloatColor(): + """ + Class representing a texture object to be uploaded to the server. + Pixel format is RGBA, float per channel. + """ + + # region Instance Variables + @property + def width(self) -> int: + """X-coordinate size of the texture.""" + @property + def height(self) -> int: + """Y-coordinate size of the texture.""" + # endregion + + # region Getters + def get(self, x: int, y: int) -> FloatColor: + """Get the `(x,y)` pixel data.""" + + # endregion + + # region Setters + def set(self, x: int, y: int, value: FloatColor): + """Sets the `(x,y)` pixel data with `value`.""" + + def set_dimensions(self, width: int, height: int): + """Resizes the texture to te specified dimensions.""" + # endregion + + +class Timestamp(): + """ + Class that contains time information for simulated data. This information is automatically + retrieved as part of the `carla.WorldSnapshot` the client gets on every frame, but might also + be used in many other situations such as a `carla.Sensor` retrieving data. + """ + + # region Instance Variables + @property + def frame(self) -> int: + """The number of frames elapsed since the simulator was launched.""" + @property + def elapsed_seconds(self) -> float: + """Simulated seconds elapsed since the beginning of the current episode (seconds).""" + @property + def delta_seconds(self) -> float: + """Simulated seconds elapsed since the previous frame (seconds).""" + + @property + def platform_timestamp(self) -> float: + """Time register of the frame at which this measurement was taken given by the OS in seconds (seconds).""" + # endregion + + # region Methods + def __init__(self, frame: int, elapsed_seconds: float, delta_seconds: float, platform_timestamp: float): ... + # endregion + + # region Dunder Methods + def __eq__(self, __value: Timestamp) -> bool: ... + def __ne__(self, __value: Timestamp) -> bool: ... + def __str__(self) -> str: ... + # endregion + + +class TrafficLight(TrafficSign): + """ traffic light actor, considered a specific type of traffic sign. As traffic lights will mostly appear at junctions, they belong to a group which contains the different traffic lights in it. Inside the group, traffic lights are differenciated by their pole index. + + Within a group the state of traffic lights is changed in a cyclic pattern: one index is chosen and it spends a few seconds in green, yellow and eventually red. The rest of the traffic lights remain frozen in red this whole time, meaning that there is a gap in the last seconds of the cycle where all the traffic lights are red. However, the state of a traffic light can be changed manually.""" + + # region Instance Variables + @property + def state(self) -> TrafficLightState: + """Current state of the traffic light.""" + # endregion + + # region Methods + def freeze(self, freeze: bool): + """Stops all the traffic lights in the scene at their current state.""" + + def is_frozen(self) -> bool: + """The client returns `True` if a traffic light is frozen according to last tick. The method does not call the simulator.""" + + def 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 method calls the simulator. + """ + # endregion + + # region Getters + def get_affected_lane_waypoints(self) -> list[Waypoint]: + """Returns a list of waypoints indicating the positions and lanes where the traffic light is having an effect.""" + + def get_elapsed_time(self) -> float: + """The client returns the time in seconds since current light state started according to last tick. The method does not call the simulator (seconds).""" + + def get_green_time(self) -> 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 (seconds). + + Setter: `carla.TrafficLight.set_green_time` + """ + + def get_group_traffic_lights(self) -> list[TrafficLight]: + """Returns all traffic lights in the group this one belongs to. + + + Note: This method calls the simulator. + """ + + def get_light_boxes(self) -> list[BoundingBox]: + """Returns a list of the bounding boxes encapsulating each light box of the traffic light.""" + + def get_opendrive_id(self) -> str: + """Returns the OpenDRIVE id of this traffic light.""" + + def get_pole_index(self) -> int: + """Returns the index of the pole that identifies it as part of the traffic light group of a junction.""" + + def get_red_time(self) -> 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 (seconds). + + Setter: `carla.TrafficLight.set_red_time` + """ + + def get_state(self) -> TrafficLightState: + """The client returns the state of the traffic light according to last tick. The method does not call the simulator. + + Setter: `carla.TrafficLight.set_state` + """ + + def get_stop_waypoints(self) -> list[Waypoint]: + """Returns a list of waypoints indicating the stop position for the traffic light. These waypoints are computed from the trigger boxes of the traffic light that indicate where a vehicle should stop.""" + + def get_yellow_time(self) -> 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 (seconds). + + Setter: `carla.TrafficLight.set_yellow_time` + """ + # endregion + + # region Setters + def set_green_time(self, green_time: float): + """Sets a given time for the green light to be active. + + Getter: `carla.TrafficLight.get_green_time` + + Args: + green_time (float): (seconds) + """ + + def set_red_time(self, red_time: float): + """Sets a given time for the red state to be active. + + Getter: carla.TrafficLight.get_red_time + + Args: + red_time (float): (seconds) + """ + + def set_state(self, state: TrafficLightState): + """Sets a given state to a traffic light actor. + + Getter: `carla.TrafficLight.get_state` + + Args: + state (TrafficLightState) + """ + + def set_yellow_time(self, yellow_time: float): + """Sets a given time for the yellow light to be active. + + Getter: `carla.TrafficLight.get_yellow_time` + + Args: + yellow_time (float): (seconds) + """ + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class TrafficLightState(int, __CarlaEnum): + """All possible states for traffic lights. These can either change at a specific time step or be changed manually. The snippet in `carla.TrafficLight.set_state` changes the state of a traffic light on the fly.""" + Red = 0 + Yellow = 1 + Green = 2 + Off = 3 + Unknown = 4 + + +class TrafficManager(): + """The traffic manager is a module built on top of the CARLA API in C++. It handles any group of vehicles set to autopilot mode to populate the simulation with realistic urban traffic conditions and give the chance to user to customize some behaviours. The architecture of the traffic manager is divided in five different goal-oriented stages and a PID controller where the information flows until eventually, a `carla.VehicleControl` is applied to every vehicle registered in a traffic manager. In order to learn more, visit the documentation regarding this module. + + https://carla.readthedocs.io/en/latest/adv_traffic_manager/ + """ + + # region Methods + def auto_lane_change(self, actor: Actor, enable: bool): + """Turns on or off lane changing behaviour for a vehicle. + + Args: + actor (Actor): The vehicle whose settings are changed. + enable (bool): `True` is default and enables lane changes. `False` will disable them. + """ + + def collision_detection(self, reference_actor: Actor, other_actor: Actor, detect_collision: bool): + """Turns on/off collisions between a vehicle and another specific actor. In order to ignore all other vehicles, traffic lights or walkers, use the specific `ignore` methods described in this same section. + + Args: + reference_actor (Actor): Vehicle that is going to ignore collisions. + other_actor (Actor): The actor that `reference_actor` is going to ignore collisions with. + detect_collision (bool): `True` is default and enables collisions. `False` will disable them. + """ + + def distance_to_leading_vehicle(self, actor: Actor, distance: float): + """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. + + Args: + actor (Actor): Vehicle whose minimum distance is being changed. + distance (float): Meters between both vehicles (meters). + """ + + def force_lane_change(self, actor: Actor, direction: bool): + """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. + + Args: + actor (Actor): Vehicle being forced to change lanes. + direction (bool): Destination lane. `True` is the one on the right and `False` is the left one. + """ + + def global_lane_offset(self, offset: float): + """Sets a global lane offset displacement from the center line. Positive values imply a right offset while negative ones mean a left one. Default is 0. Numbers high enough to cause the vehicle to drive through other lanes might break the controller. + + Args: + offset (float): Lane offset displacement from the center line. + """ + + def global_percentage_speed_difference(self, percentage: float): + """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. + + Args: + percentage (float): Percentage difference between intended speed and the current limit. + """ + + def ignore_lights_percentage(self, actor: Actor, perc: float): + """During the traffic light stage, which runs every frame, this method sets the percent chance that traffic lights will be ignored for a vehicle. + + Args: + actor (Actor): The actor that is going to ignore traffic lights. + perc (float): Between 0 and 100. Amount of times traffic lights will be ignored. + """ + + def ignore_signs_percentage(self, actor: Actor, perc: float): + """During the traffic light stage, which runs every frame, this method sets the percent chance that stop signs will be ignored for a vehicle. + + Args: + actor (Actor): The actor that is going to ignore stop signs. + perc (float): Between 0 and 100. Amount of times stop signs will be ignored. + """ + + def ignore_vehicles_percentage(self, actor: Actor, perc: float): + """During the collision detection stage, which runs every frame, this method sets a percent chance that collisions with another vehicle will be ignored for a vehicle. + + Args: + actor (Actor): The vehicle that is going to ignore other vehicles. + perc (float): Between 0 and 100. Amount of times collisions will be ignored. + """ + + def ignore_walkers_percentage(self, actor: Actor, perc: float): + """During the collision detection stage, which runs every frame, this method sets a percent chance that collisions with walkers will be ignored for a vehicle. + + Args: + actor (Actor): The vehicle that is going to ignore walkers on scene. + perc (float): Between 0 and 100. Amount of times collisions will be ignored. + """ + + def keep_right_rule_percentage(self, actor: Actor, perc: float): + """During the localization stage, this method sets a percent chance that vehicle will follow the keep right rule, and stay in the right lane. + + Args: + actor (Actor): Vehicle whose behaviour is being changed. + perc (float): Between 0 and 100. Amount of times the vehicle will follow the keep right rule. + """ + + def random_left_lanechange_percentage(self, actor: Actor, percentage: float): + """Adjust probability that in each timestep the actor will perform a left lane change, dependent on lane change availability. + + Args: + actor (Actor): The actor that you wish to query. + percentage (float): The probability of lane change in percentage units (between 0 and 100). + """ + + def random_right_lanechange_percentage(self, actor: Actor, percentage: float): + """Adjust probability that in each timestep the actor will perform a right lane change, dependent on lane change availability. + + Args: + actor (Actor): The actor that you wish to query. + percentage (float): The probability of lane change in percentage units (between 0 and 100). + """ + + def shut_down(self): + """Shuts down the traffic manager.""" + + def update_vehicle_lights(self, actor: Actor, do_update: bool): + """Sets if the Traffic Manager is responsible of updating the vehicle lights, or not. Default is False. The traffic manager will not change the vehicle light status of a vehicle, unless its auto_update_status is st to True. + + Args: + actor (Actor): Vehicle whose lights status is being changed. + do_update (bool): If `True` the traffic manager will manage the vehicle lights for the specified vehicle. + """ + + def vehicle_lane_offset(self, actor: Actor, offset: float): + """Sets a lane offset displacement from the center line. Positive values imply a right offset while negative ones mean a left one. Default is 0. Numbers high enough to cause the vehicle to drive through other lanes might break the controller. + + + Args: + actor (Actor): Vehicle whose lane offset behaviour is being changed. + offset (float): Lane offset displacement from the center line. + """ + + def vehicle_percentage_speed_difference(self, actor: Actor, percentage: float): + """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. + + + Args: + actor (Actor): Vehicle whose speed behaviour is being changed. + percentage (float): Percentage difference between intended speed and the current limit. + """ + # endregion + + # region Getters + def get_all_actions(self, actor: Actor) -> list[Waypoint]: + """Returns all known actions (i.e. road options and waypoints) that an actor controlled by the Traffic Manager will perform in its next steps. + + Args: + actor (Actor): The actor that you wish to query. + + Returns: + list[Waypoint]: list of lists with each element as follows - [Road option (string e.g. 'Left', 'Right', 'Straight'), Next waypoint (carla.Waypoint)] + """ + + def get_next_action(self, actor: Actor) -> list[Waypoint]: + """Returns the next known road option and waypoint that an actor controlled by the Traffic Manager will follow. + + Args: + actor (Actor): The actor that you wish to query. + + Returns: + list[Waypoint]: list of two elements - [Road option (string e.g. 'Left', 'Right', 'Straight'), Next waypoint (carla.Waypoint)] + """ + + def get_port(self) -> int: + """Returns the port where the Traffic Manager is connected. If the object is a TM-Client, it will return the port of its TM-Server. Read the documentation to learn the difference. + + https://carla.readthedocs.io/en/latest/python_api/#adv_traffic_manager.md#multiclient-and-multitm-management + """ + # endregion + + # region Setters + def set_boundaries_respawn_dormant_vehicles(self, lower_bound: Annotated[float, ">=25.0"], upper_bound: Annotated[float, "<= WorldSettings.actor_active_distance"]) -> None: + """Sets the upper and lower boundaries for dormant actors to be respawned near the hero vehicle. + + + Warning: The `upper_bound` cannot be higher than the `actor_active_distance`. The `lower_bound` cannot be less than `25`. + + Args: + lower_bound (float, optional): The minimum distance in meters from the hero vehicle that a dormant actor will be respawned. + upper_bound (float, optional): The maximum distance in meters from the hero vehicle that a dormant actor will be respawned. + """ + + def set_desired_speed(self, actor: Actor, speed: float) -> None: + """Sets the speed of a vehicle to the specified value. + + Args: + actor (Actor): Vehicle whose speed is being changed. + speed (float): Desired speed at which the vehicle will move. + """ + + def set_global_distance_to_leading_vehicle(self, distance: float) -> None: + """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. + + Args: + distance (float): Meters between vehicles (meters). + """ + + def set_hybrid_physics_mode(self, enabled=False): + """Enables or disables the hybrid physics mode. In this mode, vehicle's farther than a certain radius from the ego vehicle will have their physics disabled. Computation cost will be reduced by not calculating vehicle dynamics. Vehicles will be teleported. + + Args: + enabled (bool, optional): If `True`, enables the hybrid physics. Defaults to False. + """ + + def set_hybrid_physics_radius(self, r=50.0): + """With hybrid physics on, changes the radius of the area of influence where physics are enabled. + + Args: + r (float, optional): New radius where physics are enabled (meters). Defaults to 50.0. + """ + + def 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. 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. + + Args: + mode_switch (bool, optional): If True, the OSM mode is enabled. Defaults to True. + """ + + def set_path(self, actor: Actor, path: list[Location]): + """Sets a list of locations for a vehicle to follow while controlled by the Traffic Manager. + + Args: + actor (Actor): The actor that must follow the given path. + path (list[Location]): The list of carla.Locations for the actor to follow. + """ + + def set_random_device_seed(self, value: int): + """Sets a specific random seed for the Traffic Manager, thereby setting it to be deterministic. + + Args: + value (int): Seed value for the random number generation of the Traffic Manager. + """ + + def set_respawn_dormant_vehicles(self, mode_switch=False): + """If `True`, vehicles in large maps will respawn near the hero vehicle when they become dormant. Otherwise, they will stay dormant until they are within `actor_active_distance` of the hero vehicle again. + + + Args: + mode_switch (bool, optional) Defaults to False. + """ + + def set_route(self, actor: Actor, path: list[str]): + """Sets a list of route instructions for a vehicle to follow while controlled by the Traffic Manager. The possible route instructions are 'Left', 'Right', 'Straight'. + + + Warning: Ensure that the lane topology doesn't impede the given route. + + + Args: + actor (Actor): The actor that must follow the given route instructions. + path (list[str]): The list of route instructions (string) for the vehicle to follow. + """ + + def set_synchronous_mode(self, mode_switch=True): + """Sets the Traffic Manager to synchronous mode. In a multiclient situation, only the TM-Server can tick. Similarly, in a multiTM situation, only one TM-Server must tick. Use this method in the client that does the world tick, and right after setting the world to synchronous mode, to set which TM will be the master while in sync. + + + Warning: If the server is set to synchronous mode, the TM must be set to synchronous mode too in the same client that does the tick. + + Args: + mode_switch (bool, optional): If True, the TM synchronous mode is enabled.. Defaults to True. + """ + # endregion + + +class TrafficSign(Actor): + """Traffic signs appearing in the simulation except for traffic lights. These have their own class inherited from this in `carla.TrafficLight`. Right now, speed signs, stops and yields are mainly the ones implemented, but many others are borne in mind. + """ + + # region Instance Variables + @property + def trigger_volume(self) -> BoundingBox: + """A carla.BoundingBox situated near a traffic sign where the carla.Actor who is inside can know about it.""" + # endregion + + +class Transform(): + """Class that defines a transformation, a combination of location and rotation, without scaling. + """ + + # region Instance Variables + @property + def location(self) -> Location: + """Describes a point in the coordinate system.""" + @location.setter + def location(self, value: Location | Vector3D): + ... + + @property + def rotation(self) -> Rotation: + """Describes a rotation for an object according to Unreal Engine's axis system (degrees (pitch, yaw, roll)).""" + @rotation.setter + def rotation(self, value: Rotation | Vector3D): + ... + # endregion + + # region Methods + def __init__(self, location: Location = Location(0,0,0), rotation: Rotation = Rotation(0,0,0)): ... + + def transform(self, in_point: Vector3D) -> Vector3D: + """ + Translates a 3D point from local to global coordinates using the current + transformation as frame of reference. + + Args: + in_point (Location): Location in the space to which the transformation will be applied. + + Note: + This operation transforms `in_point` in place. + """ + + def inverse_transform(self, in_point: Vector3D) -> Vector3D: + """ + Applies the inverse of `transform` by translating a 3D point from global to local + coordinates using the current transformation as frame of reference. + + Args: + in_point (Vector3D): Vector to which the transformation will be applied. + + Note: + This operation transforms `in_point` in place. + """ + + def transform_vector(self, in_point: Vector3D) -> Vector3D: + """ + Rotates a vector using the current transformation as frame of reference, + without applying translation. Use this to transform, for example, a velocity. + + Args: + in_point (Vector3D): Vector to which the transformation will be applied. + + Note: + This operation transforms `in_point` in place. + """ + # endregion + + # region Getters + def get_forward_vector(self) -> Vector3D: + """Computes a forward vector using the rotation of the object.""" + + def get_inverse_matrix(self) -> list[list[float]]: + """Computes the 4-matrix representation of the inverse transformation.""" + + def get_matrix(self) -> list[list[float]]: + """Computes the 4-matrix representation of the transformation.""" + + def get_right_vector(self) -> Vector3D: + """Computes a right vector using the rotation of the object.""" + + def get_up_vector(self) -> Vector3D: + """Computes an up vector using the rotation of the object.""" + # endregion + + # region Dunder Methods + def __eq__(self, __value: Transform) -> bool: + """Returns `True` if both `location` and `rotation` are equal for this and `other`.""" + + def __ne__(self, __value: Transform) -> bool: + """Returns `True` if any `location` and `rotation` are not equal for this and `other`.""" + + def __str__(self) -> str: + """Parses both `location` and `rotation` to string.""" + # endregion + + +class Vector2D(): + """Helper class to perform 2D operations.""" + + # region Instance Variables + @property + def x(self) -> float: + """X-axis value.""" + @property + def y(self) -> float: + """Y-axis value.""" + # endregion + + # region Methods + def __init__(self, x=0.0, y=0.0): ... + + def length(self) -> float: + """Computes the length of the vector.""" + + def make_unit_vector(self) -> Vector3D: + """Returns a vector with the same direction and unitary length.""" + + def squared_length(self) -> float: + """Computes the squared length of the vector.""" + # endregion + + # region Dunder Methods + def __add__(self, other: Vector2D) -> Vector2D: ... + + def __eq__(self, other: Vector2D) -> bool: + """Returns `True` if values for every axis are equal.""" + + def __mul__(self, other: float) -> Vector2D: ... + + def __ne__(self, bool: Vector2D) -> bool: + """Returns `True` if the value for any axis is different.""" + + def __str__(self) -> str: + """Returns the axis values for the vector parsed as string.""" + ... + + def __sub__(self, other: Vector2D) -> Vector2D: ... + def __truediv__(self, other: float) -> Vector2D: ... + + # endregion + + +class Vector3D(): + """Helper class to perform 3D operations.""" + + # region Instance Variables + @property + def x(self) -> float: + """X-axis value.""" + @property + def y(self) -> float: + """Y-axis value.""" + @property + def z(self) -> float: + """Z-axis value.""" + # endregion + + # region Methods + def __init__(self, x=0.0, y=0.0, z=0.0): ... + + def cross(self, vector: Vector3D) -> Vector3D: + """Computes the cross product between two vectors.""" + + def distance(self, vector: Vector3D) -> float: + """Computes the distance between two vectors.""" + + def distance_2d(self, vector: Vector3D) -> Vector3D: + """Computes the 2-dimensional distance between two vectors.""" + + def distance_squared(self, vector: Vector3D) -> float: + """Computes the squared distance between two vectors.""" + + def distance_squared_2d(self, vector: Vector3D) -> float: + """Computes the 2-dimensional squared distance between two vectors.""" + + def dot(self, vector: Vector3D) -> float: + """Computes the dot product between two vectors.""" + + def dot_2d(self, vector: Vector3D) -> float: + """Computes the 2-dimensional dot product between two vectors.""" + + def length(self) -> float: + """Computes the length of the vector.""" + + def make_unit_vector(self) -> Vector3D: + """Returns a vector with the same direction and unitary length.""" + + def squared_length(self) -> float: + """Computes the squared length of the vector.""" + # endregion + + # region Getters + def get_vector_angle(self, vector: Vector3D) -> float: + """Computes the angle between a pair of 3D vectors in radians.""" + # endregion + + # region Dunder Methods + def __abs__(self) -> Vector3D: + """Returns a Vector3D with the absolute value of the components x, y and z.""" + + def __add__(self, other: Vector3D) -> Vector3D: ... + def __eq__(self, other: Vector3D) -> bool: ... + def __mul__(self, other: float) -> Vector3D: ... + def __ne__(self, other: Vector3D) -> bool: ... + def __str__(self) -> str: ... + def __sub__(self, other: Vector3D) -> Vector3D: ... + def __truediv__(self, other: float) -> Vector3D: ... + # endregion + + +class Vehicle(Actor): + """One of the most important groups of actors in CARLA. These include any type of vehicle from cars to trucks, motorbikes, vans, bycicles and also official vehicles such as police cars. A wide set of these actors is provided in `carla.BlueprintLibrary` to facilitate different requirements. Vehicles can be either manually controlled or set to an autopilot mode that will be conducted client-side by the `traffic manager`.""" + + # region Instance Variables + @property + def bounding_box(self) -> BoundingBox: + """Bounding box containing the geometry of the vehicle. Its location and rotation are relative to the vehicle it is attached to.""" + # endregion + + # region Methods + def apply_ackermann_control(self, control: VehicleAckermannControl): + """Applies an Ackermann control object on the next tick. + + Args: + `control (VehicleAckermannControl)`\n + """ + + def apply_ackermann_controller_settings(self, settings: VehicleAckermannControl): + """Applies a new Ackermann control settings to this vehicle in the next tick. + + + Warning: This method does call the simulator.""" + + def apply_control(self, control: VehicleControl) -> None: + """Applies a control object on the next tick, containing driving parameters such as throttle, steering or gear shifting.""" + + def apply_physics_control(self, physics_control: VehiclePhysicsControl): + """Applies a physics control object in the next tick containing the parameters that define the vehicle as a corporeal body. E.g.: moment of inertia, mass, drag coefficient and many more.""" + + def close_door(self, door_idx: VehicleDoor) -> None: + """Close the door `door_idx` if the vehicle has it. Use `carla.VehicleDoor.All` to close all available doors.""" + + def enable_carsim(self, simfile_path: str): + """Enables the CarSim physics solver for this particular vehicle. In order for this function to work, there needs to be a valid license manager running on the server side. The control inputs are redirected to CarSim which will provide the position and orientation of the vehicle for every frame. + + Args: + `simfile_path (str)`: Path to the `.simfile` file with the parameters of the simulation.\n + """ + + def enable_chrono_physics(self, max_substeps: int, max_substep_delta_time: int, vehicle_json: str, powertrain_json: str, tire_json: str, base_json_path: str): + """Enables Chrono physics on a spawned vehicle. + + + Note: Ensure that you have started the CARLA server with the ARGS="--chrono" flag. You will not be able to use Chrono physics without this flag set. + + Warning: Collisions are not supported. When a collision is detected, physics will revert to the default CARLA physics. + + Args: + `max_substeps (int)`: Max number of Chrono substeps.\n + `max_substep_delta_time (int)`: Max size of substep.\n + `vehicle_json (str)`: Path to vehicle json file relative to `base_json_path`.\n + `powertrain_json (str)`: Path to powertrain json file relative to `base_json_path`.\n + `tire_json (str)`: Path to tire json file relative to `base_json_path`.\n + `base_json_path (str)`: Path to `chrono/data/vehicle` folder. E.g., `/home/user/carla/Build/chrono-install/share/chrono/data/vehicle/` (the final / character is required).\n + """ + + def is_at_traffic_light(self) -> bool: + """Vehicles will be affected by a traffic light when the light is red and the vehicle is inside its bounding box. The client returns whether a traffic light is affecting this vehicle according to last tick (it does not call the simulator).""" + + def open_door(self, door_idx: VehicleDoor): + """Open the door `door_idx` if the vehicle has it. Use carla.VehicleDoor.All to open all available doors. + + Args: + `door_idx (VehicleDoor)`: door index.\n + """ + + def show_debug_telemetry(self, enabled=True): + """Enables or disables the telemetry on this vehicle. This shows information about the vehicles current state and forces applied to it in the spectator window. Only information for one vehicle can be shown so that, if you enable a second one, the previous will be automatically disabled. + """ + + def use_carsim_road(self, enabled: bool): + """Enables or disables the usage of CarSim vs terrain file specified in the `.simfile`. By default this option is disabled and CarSim uses unreal engine methods to process the geometry of the scene.""" + # endregion + + # region Getters + def get_ackermann_controller_settings(self) -> AckermannControllerSettings: + """Returns the last Ackermann control settings applied to this vehicle. + + + Warning: This method does call the simulator to retrieve the value. + """ + + def get_control(self) -> VehicleControl: + """The client returns the control applied in the last tick. The method does not call the simulator. + """ + + def get_failure_state(self) -> VehicleFailureState: + """Vehicle have failure states, to indicate that it is incapable of continuing its route. This function returns the vehicle's specific failure state, or in other words, the cause that resulted in it.""" + + def get_light_state(self) -> VehicleLightState: + """Returns a flag representing the vehicle light state, this represents which lights are active or not. + + + Setter: `carla.Vehicle.set_light_state` + """ + + def get_physics_control(self) -> VehiclePhysicsControl: + """The simulator returns the last physics control applied to this vehicle. + + + Warning: This method does call the simulator to retrieve the value. + """ + + def get_speed_limit(self) -> float: + """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. + + Returns: + `float`: (km/h)\n + """ + + def get_traffic_light(self) -> TrafficLight: + """Retrieves the traffic light actor affecting this vehicle (if any) according to last tick. The method does not call the simulator. + """ + + def get_traffic_light_state(self) -> TrafficLightState: + """The client returns the state of the traffic light affecting this vehicle according to last tick. The method does not call the simulator. If no traffic light is currently affecting the vehicle, returns `green`. + """ + + def get_wheel_steer_angle(self, wheel_location: VehicleWheelLocation) -> float: + """ + Returns the physics angle in degrees of a vehicle's wheel. + + + Note: Returns the angle based on the physics of the wheel, not the visual angle. + """ + # endregion + + # region Setters + def set_autopilot(self, enabled=True, port=8000) -> None: + """Registers or deletes the vehicle from a Traffic Manager's list. When `True`, the Traffic Manager passed as parameter will move the vehicle around. The autopilot takes place client-side. + + Args: + `enabled (bool, optional)`: Defaults to True.\n + `port (int, optional)`: The port of the TM-Server where the vehicle is to be registered or unlisted. Defaults to 8000.\n + """ + + def set_light_state(self, light_state: VehicleLightState) -> None: + """Sets the light state of a vehicle using a flag that represents the lights that are on and off. + + + Getter: `carla.Vehicle.get_light_state` + """ + + def set_wheel_steer_direction(self, wheel_location: VehicleWheelLocation, angle_in_deg: float): + """Sets the angle of a vehicle's wheel visually. + + + Warning: Does not affect the physics of the vehicle. + """ + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class VehicleAckermannControl(): + """Manages the basic movement of a vehicle using Ackermann driving controls.""" + + # region Instance Variables + @property + def steer(self) -> float: + """Desired steer (rad). Positive value is to the right. Default is 0.0.""" + @property + def steer_speed(self) -> float: + """Steering velocity (rad/s). Zero steering angle velocity means change the steering angle as quickly as possible. Default is 0.0.""" + + @property + def speed(self) -> float: + """Desired speed (m/s). Default is 0.0.""" + + @property + def acceleration(self) -> float: + """Desired acceleration (m/s2) Default is 0.0.""" + + @property + def jerk(self) -> float: + """Desired jerk (m/s3). Default is 0.0.""" + # endregion + + # region Methods + def __init__(self, steer=0.0, steer_speed=0.0, speed=0.0, acceleration=0.0, jerk=0.0): ... + # endregion + + # region Dunder Methods + def __eq__(self, other: VehicleAckermannControl) -> bool: ... + def __ne__(self, other: VehicleAckermannControl) -> bool: ... + def __str__(self) -> str: ... + # endregion + + +class VehicleControl(): + """Manages the basic movement of a vehicle using typical driving controls.""" + # region Instance Variables + + @property + def throttle(self) -> float: + """A scalar value to control the vehicle throttle [0.0, 1.0]. Default is 0.0.""" + @throttle.setter + def throttle(self, value: float):... + + @property + def steer(self) -> float: + """A scalar value to control the vehicle steering [-1.0, 1.0]. Default is 0.0.""" + @steer.setter + def steer(self, value: float): ... + + @property + def brake(self) -> float: + """A scalar value to control the vehicle brake [0.0, 1.0]. Default is 0.0.""" + @brake.setter + def brake(self, value: float): ... + + @property + def hand_brake(self) -> bool: + """Determines whether hand brake will be used. Default is `False`.""" + @hand_brake.setter + def hand_brake(self, value: bool): ... + + @property + def reverse(self) -> bool: + """Determines whether the vehicle will move backwards. Default is `False`.""" + @reverse.setter + def reverse(self, value: bool): ... + + @property + def manual_gear_shift(self) -> bool: + """Determines whether the vehicle will be controlled by changing gears manually. Default is `False`.""" + @manual_gear_shift.setter + def manual_gear_shift(self, value: bool): ... + + @property + def gear(self) -> int: + """States which gear is the vehicle running on.""" + @gear.setter + def gear(self, value: int): ... + # endregion + + # region Methods + def __init__(self, throttle=0.0, steer=0.0, brake=0.0, hand_brake=False, reverse=False, manual_gear_shift=False, gear=0): + """ + Args: + `throttle (float, optional)`: Scalar value between [0.0,1.0]. Defaults to 0.0.\n + `steer (float, optional)`: Scalar value between [0.0,1.0]. Defaults to 0.0.\n + `brake (float, optional)`: Scalar value between [0.0,1.0]. Defaults to 0.0.\n + `hand_brake (bool, optional)` Defaults to False.\n + `reverse (bool, optional)` Defaults to False.\n + `manual_gear_shift (bool, optional)` Defaults to False.\n + `gear (int, optional)` Defaults to 0.\n + """ + # endregion + + # region Dunder Methods + def __eq__(self, __value: VehicleControl) -> bool: ... + def __ne__(self, __value: VehicleControl) -> bool: ... + def __str__(self) -> str: ... + # endregion + + +class VehicleDoor(int, __CarlaEnum): + """Possible index representing the possible doors that can be open. Notice that not all possible doors are able to open in some vehicles.""" + FL = 0 + """Front left door.""" + FR = 1 + """Front right door.""" + RL = 2 + """Back left door.""" + RR = 3 + """Back right door.""" + All = 6 + """Represents all doors.""" + + +class VehicleFailureState(int, __CarlaEnum): + """Enum containing the different failure states of a vehicle, from which the it cannot recover. These are returned by get_failure_state() and only Rollover is currently implemented.""" + + NONE = 0 + Rollover = 1 + Engine = 2 + TirePuncture = 3 + + +class VehicleLightState(IntFlag, __CarlaEnum): + """Class that recaps the state of the lights of a vehicle, these can be used as a flags. + + E.g: `VehicleLightState.HighBeam & VehicleLightState.Brake` will return `True` when both are active. + + Lights are off by default in any situation and should be managed by the user via script. The blinkers blink automatically. + + + Warning: Right now, not all vehicles have been prepared to work with this functionality, this will be added to all of them in later updates.""" + NONE = 0 + """All lights off.""" + Position = 1 + LowBeam = 2 + HighBeam = 4 + Brake = 8 + RightBlinker = 16 + LeftBlinker = 32 + Reverse = 64 + Fog = 128 + Interior = 256 + Special1 = 512 + """This is reserved for certain vehicles that can have special lights, like a siren.""" + Special2 = 1024 + """This is reserved for certain vehicles that can have special lights, like a siren.""" + All = -1 + """All lights on.""" + + +class VehiclePhysicsControl(): + """Summarizes the parameters that will be used to simulate a carla.Vehicle as a physical object. The specific settings for the wheels though are stipulated using `carla.WheelPhysicsControl`.""" + + # region Instance Variables + @property + def torque_curve(self) -> list[Vector2D]: + """Curve that indicates the torque measured in Nm for a specific RPM of the vehicle's engine.""" + @property + def max_rpm(self) -> float: + """The maximum RPM of the vehicle's engine.""" + + @property + def moi(self) -> float: + """The moment of inertia of the vehicle's engine. (kg*m^2)""" + + @property + def damping_rate_full_throttle(self) -> float: + """Damping ratio when the throttle is maximum.""" + + @property + def damping_rate_zero_throttle_clutch_engaged(self) -> float: + """Damping ratio when the throttle is zero with clutch engaged.""" + + @property + def damping_rate_zero_throttle_clutch_disengaged(self) -> float: + """Damping ratio when the throttle is zero with clutch disengaged.""" + + @property + def use_gear_autobox(self) -> bool: + """If `True`, the vehicle will have an automatic transmission.""" + + @property + def gear_switch_time(self) -> float: + """Switching time between gears. (seconds)""" + + @property + def clutch_strength(self) -> float: + """Clutch strength of the vehicle (kg*m^2/s).""" + + @property + def final_ratio(self) -> float: + """Fixed ratio from transmission to wheels.""" + + @property + def forward_gears(self) -> list[GearPhysicsControl]: + """List of objects defining the vehicle's gears.""" + + @property + def mass(self) -> float: + """Mass of the vehicle (kilograms).""" + + @property + def drag_coefficient(self) -> float: + """Drag coefficient of the vehicle's chassis.""" + + @property + def center_of_mass(self) -> Vector3D: + """Center of mass of the vehicle (meters).""" + + @property + def steering_curve(self) -> list[Vector2D]: + """Curve that indicates the maximum steering for a specific forward speed.""" + + @property + def use_sweep_wheel_collision(self) -> bool: + """Enable the use of sweep for wheel collision. By default, it is disabled and it uses a simple raycast from the axis to the floor for each wheel. This option provides a better collision model in which the full volume of the wheel is checked against collisions.""" + + @property + def wheels(self) -> list[WheelPhysicsControl]: + """List of wheel physics objects. This list should have 4 elements, where index 0 corresponds to the front left wheel, index 1 corresponds to the front right wheel, index 2 corresponds to the back left wheel and index 3 corresponds to the back right wheel. For 2 wheeled vehicles, set the same values for both front and back wheels.""" + # endregion + + # region Methods + def __init__(self, + torque_curve=[[0.0, 500.0], [5000.0, 500.0]], + max_rpm=5000.0, + moi=1.0, + damping_rate_full_throttle=0.15, damping_rate_zero_throttle_clutch_engaged=2.0, damping_rate_zero_throttle_clutch_disengaged=0.35, use_gear_autobox=True, + gear_switch_time=0.5, + clutch_strength=10.0, + final_ratio=4.0, + forward_gears=list(), + drag_coefficient=0.3, + center_of_mass=[0.0, 0.0, 0.0], + steering_curve=[[0.0, 1.0], [10.0, 0.5]], + wheels=list(), + use_sweep_wheel_collision=False, + mass=1000.0): + """VehiclePhysicsControl constructor. + + Args: + `torque_curve (list, optional)`. Defaults to [[0.0, 500.0], [5000.0, 500.0]].\n + `max_rpm (float, optional)`. Defaults to 5000.0.\n + `moi (float, optional)`: (kg*m^2). Defaults to 1.0.\n + `damping_rate_full_throttle (float, optional)`. Defaults to 0.15.\n + `damping_rate_zero_throttle_clutch_engaged (float, optional)`: Defaults to 2.0.\n + `damping_rate_zero_throttle_clutch_disengaged (float, optional)`: Defaults to 0.35.\n + `use_gear_autobox (bool, optional)`: Defaults to True.\n + `gear_switch_time (float, optional)`: (seconds). Defaults to 0.5.\n + `clutch_strength (float, optional)`: (kg*m^2/s). Defaults to 10.0.\n + `final_ratio (float, optional)`: Defaults to 4.0.\n + `forward_gears (list[GearPhysicsControl] optional)`: Defaults to list().\n + `drag_coefficient (float, optional)`: Defaults to 0.3.\n + `center_of_mass (list, optional)`: Defaults to [0.0, 0.0, 0.0].\n + `steering_curve (list, optional)`: Defaults to [[0.0, 1.0], [10.0, 0.5]].\n + `wheels (_type_, optional)`: Defaults to list().\n + `use_sweep_wheel_collision (bool, optional)`: Defaults to False.\n + `mass (float, optional)`: (kilograms). Defaults to 1000.0.\n + """ + # endregion + + # region Dunder Methods + def __eq__(self, other: VehiclePhysicsControl) -> bool: ... + def __ne__(self, other: VehiclePhysicsControl) -> bool: ... + def __str__(self) -> str: ... + # endregion + + +class VehicleWheelLocation(int, __CarlaEnum): + """enum representing the position of each wheel on a vehicle. Used to identify the target wheel when setting an angle in `carla.Vehicle.set_wheel_steer_direction` or `carla.Vehicle.get_wheel_steer_angle`.""" + FL_Wheel = 0 + """Front left wheel of a 4 wheeled vehicle.""" + FR_Wheel = 1 + """Front right wheel of a 4 wheeled vehicle.""" + BL_Wheel = 2 + """Back left wheel of a 4 wheeled vehicle.""" + BR_Wheel = 3 + """Back right wheel of a 4 wheeled vehicle.""" + Front_Wheel = 0 + """Front wheel of a 2 wheeled vehicle.""" + Back_Wheel = 1 + """Back wheel of a 2 wheeled vehicle.""" + + +class Walker(Actor): + """This class inherits from the `carla.Actor` and defines pedestrians in the simulation. Walkers are a special type of actor that can be controlled either by an AI (`carla.WalkerAIController`) or manually via script, using a series of `carla.WalkerControl` to move these and their skeletons. + """ + + # region Methods + def apply_control(self, control: WalkerControl): + """On the next tick, the control will move the walker in a certain direction with a certain speed. Jumps can be commanded too.""" + + def blend_pose(self, blend_value: float): + """Set the blending value of the custom pose with the animation. The values can be: + + + 0: will show only the animation + + 1: will show only the custom pose (set by the user with set_bones()) + + any other: will interpolate all the bone positions between animation and the custom pose. + + Args: + `blend_value (float)`: value from 0 to 1 with the blend percentage\n + """ + + def hide_pose(self): + """Hide the custom pose and show the animation (same as calling `blend_pose(0)`). + """ + + def show_pose(self): + """Show the custom pose and hide the animation (same as calling `blend_pose(1)`). + """ + # endregion + + # region Getters + def get_bones(self) -> WalkerBoneControlOut: + """Return the structure with all the bone transformations from the actor. For each bone, we get the name and its transform in three different spaces: + + + name: bone name + + world: transform in world coordinates + + component: transform based on the pivot of the actor + + relative: transform based on the bone parent. + + + + Setter: `carla.Walker.set_bones` + + Returns: + `WalkerBoneControlOut`: _description_\n + """ + + def get_control(self) -> WalkerControl: + """The client returns the control applied to this walker during last tick. The method does not call the simulator. + """ + + def get_pose_from_animation(self): + """Make a copy of the current animation frame as the custom pose. Initially the custom pose is the neutral pedestrian pose.""" + + # endregion + + # region Setters + def set_bones(self, bones: list[WalkerBoneControlIn]): + """Set the bones of the actor. For each bone we want to set we use a relative transform. Only the bones in this list will be set. For each bone you need to setup this info: + + + name: bone name + + relative: transform based on the bone parent. + + + Getter: `carla.Walker.get_bones` + + Args: + `bones (WalkerBoneControlIn)`: list of pairs (bone_name, transform) for the bones that we want to set)\n + """ + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class WalkerAIController(Actor): + """Class that conducts AI control for a walker. The controllers are defined as actors, but they are quite different from the rest. They need to be attached to a parent actor during their creation, which is the walker they will be controlling (take a look at `carla.World` if you are yet to learn on how to spawn actors). They also need for a special blueprint (already defined in `carla.BlueprintLibrary` as "controller.ai.walker"). This is an empty blueprint, as the AI controller will be invisible in the simulation but will follow its parent around to dictate every step of the way. + """ + + # region Methods + def go_to_location(self, destination: Location): + """Sets the destination that the pedestrian will reach. + + Args: + `destination (Location)`: (meters)\n + """ + + def start(self): + """Enables AI control for its parent walker.""" + + def stop(self): + """Disables AI control for its parent walker.""" + # endregion + + # region Setters + def set_max_speed(self, speed=1.4): + """Sets a speed for the walker in meters per second. + + Args: + `speed (float, optional)`: An easy walking speed is set by default (m/s). Defaults to 1.4.\n + """ + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class WalkerBoneControlIn(): + """This class grants bone specific manipulation for walker. The skeletons of walkers have been unified for clarity and the transform applied to each bone are always relative to its parent. Take a look here to learn more on how to create a walker and define its movement. + + https://carla.readthedocs.io/en/latest/tuto_G_control_walker_skeletons/ + """ + + # region Instance Variables + @property + def bone_transforms(self) -> list[tuple[str, Transform]]: + """ + List with the data for each bone we want to set: + + name: bone name + + relative: transform based on the bone parent. + """ + # endregion + + # region Methods + def __init__(self, bone_transforms: list[tuple[str, Transform]]): + """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. + + Args: + `bone_transforms (list[tuple[str,Transform]])`\n + """ + ... + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class WalkerBoneControlOut(): + """This class is used to return all bone positions of a pedestrian. For each bone we get its name and its transform in three different spaces (world, actor and relative).""" + + # region Instance Variables + @property + def bone_transforms(self) -> list[tuple[str, Transform, Transform, Transform]]: + """ + List of one entry per bone with this information: + + + name: bone name + + world: transform in world coordinates + + component: transform based on the pivot of the actor + + relative: transform based on the bone parent. + """ + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class WalkerControl(): + """This class defines specific directions that can be commanded to a `carla.Walker` to control it via script. + + AI control can be settled for walkers, but the control used to do so is `carla.WalkerAIController`. + """ + + # region Instance Variables + @property + def direction(self) -> Vector3D: + """Vector using global coordinates that will correspond to the direction of the walker.""" + @property + def speed(self) -> float: + """A scalar value to control the walker's speed (m/s).""" + @property + def jump(self) -> bool: + """If `True`, the walker will perform a jump.""" + # endregion + + # region Methods + def __init__(self, direction=[1.0, 0.0, 0.0], speed=0.0, jump=False): + """This class defines specific directions that can be commanded to a `carla.Walker` to control it via script. + + Args: + `direction (list, optional)`: Vector using global coordinates that will correspond to the direction of the walker.. Defaults to [1.0, 0.0, 0.0].\n + `speed (float, optional)`: A scalar value to control the walker's speed (m/s). Defaults to 0.0.\n + `jump (bool, optional)`: If `True`, the walker will perform a jump. Defaults to False.\n + """ + # endregion + + # region Dunder Methods + def __eq__(self, __value: WalkerControl) -> bool: ... + def __ne__(self, __value: WalkerControl) -> bool: ... + def __str__(self) -> str: ... + # endregion + + +class Waypoint(): + """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 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. + """ + # region Instance Variables + @property + def id(self) -> int: + """The identifier is generated using a hash combination of the road, section, lane and s values that correspond to said point in the OpenDRIVE geometry. The s precision is set to 2 centimeters, so 2 waypoints closer than 2 centimeters in the same road, section and lane, will have the same identificator.""" + + @property + def transform(self) -> Transform: + """Position and orientation of the waypoint according to the current lane information. This data is computed the first time it is accessed. It is not created right away in order to ease computing costs when lots of waypoints are created but their specific transform is not needed.""" + + @property + def road_id(self) -> int: + """OpenDRIVE road's id.""" + + @property + def section_id(self) -> int: + """OpenDRIVE section's id, based on the order that they are originally defined.""" + + @property + def is_junction(self) -> bool: + """True if the current Waypoint is on a junction as defined by OpenDRIVE.""" + + @property + def junction_id(self) -> int: + """OpenDRIVE junction's id. For more information refer to OpenDRIVE documentation. + + http://www.opendrive.org/docs/OpenDRIVEFormatSpecRev1.4H.pdf#page=20 + """ + + @property + def lane_id(self) -> int: + """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.""" + + @property + def s(self) -> float: + """OpenDRIVE s value of the current position.""" + + @property + def lane_width(self) -> float: + """Horizontal size of the road at current `s`.""" + + @property + def lane_change(self) -> LaneChange: + """Lane change definition of the current Waypoint's location, based on the traffic rules defined in the OpenDRIVE file. It states if a lane change can be done and in which direction.""" + + @property + def lane_type(self) -> LaneType: + """The lane type of the current Waypoint, based on OpenDRIVE 1.4 standard.""" + + @property + def right_lane_marking(self) -> LaneMarking: + """The right lane marking information based on the direction of the Waypoint.""" + + @property + def left_lane_marking(self) -> LaneMarking: + """The left lane marking information based on the direction of the Waypoint.""" + # endregion + + # region Methods + def next(self, distance: float) -> list[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. + + Args: + `distance (float)`: The approximate distance where to get the next waypoints (meters).\n + + Returns: + `list[Waypoint]`\n + """ + + def next_until_lane_end(self, distance: float) -> list[Waypoint]: + """Returns a list of waypoints from this to the end of the lane separated by a certain `distance`."" + + Args: + `distance (float)`: The approximate distance between waypoints.(meters). + + Returns: + `list[Waypoint]`\n + """ + + def previous(self, distance: float) -> list[Waypoint]: + """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. + + Args: + `distance (float)`: The approximate distance where to get the previous waypoints (meters).\n + + Returns: + `list[Waypoint]`\n + """ + + def previous_until_lane_start(self, distance: float) -> list[Waypoint]: + """Returns a list of waypoints from this to the start of the lane separated by a certain distance. + + Args: + `distance (float)`: The approximate distance between waypoints (meters).\n + + Returns: + `list[Waypoint]`\n + """ + # endregion + # region Getters + + def get_junction(self) -> Junction: + """If the waypoint belongs to a junction this method returns the associated junction object. Otherwise returns `null`.""" + + def get_landmarks(self, distance: float, stop_at_junction=False) -> list[Landmark]: + """Returns a list of landmarks in the road from the current waypoint until the specified distance. + + Args: + `distance (float)`: The maximum distance to search for landmarks from the current waypoint (meters).\n + `stop_at_junction (bool, optional)`: Enables or disables the landmark search through junctions. Defaults to False.\n + """ + + def get_landmarks_of_type(self, distance: float, type: str, stop_at_junction=False) -> list[Landmark]: + """Returns a list of landmarks in the road of a specified type from the current waypoint until the specified distance. + + Args: + `distance (float)`: The maximum distance to search for landmarks from the current waypoint (meters).\n + `type (str)`: The type of landmarks to search.\n + `stop_at_junction (bool, optional)`: Enables or disables the landmark search through junctions. Defaults to False.\n + """ + + def get_left_lane(self) -> Waypoint | None: + """ + Generates a Waypoint at the center of the left lane based on the direction of the current + Waypoint, taking into account if the lane change is allowed in this location. + Will return `None` if the lane does not exist. + """ + + def get_right_lane(self) -> Waypoint | None: + """ + Generates a waypoint at the center of the right lane based on the direction of the current + waypoint, taking into account if the lane change is allowed in this location. + Will return `None` if the lane does not exist. + """ + # endregion + + # region Dunder Methods + def __str__(self) -> str: ... + # endregion + + +class WeatherParameters(): + """This class defines objects containing lighting and weather specifications that can later be applied in `carla.World`. So far, these conditions only intervene with `sensor.camera.rgb`. They neither affect the actor's physics nor other sensors. + + Each of these parameters acts independently from the rest. Increasing the rainfall will not automatically create puddles nor change the road's humidity. That makes for a better customization but means that realistic conditions need to be scripted. However an example of dynamic weather conditions working realistically can be found here. + + https://github.com/carla-simulator/carla/blob/master/PythonAPI/examples/dynamic_weather.py + """ + # region Instance Variables + @property + def cloudiness(self) -> float: + """Values range from 0 to 100, being 0 a clear sky and 100 one completely covered with clouds.""" + @property + def precipitation(self) -> float: + """Rain intensity values range from 0 to 100, being 0 none at all and 100 a heavy rain.""" + @property + def precipitation_deposits(self) -> float: + """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.""" + @property + def wind_intensity(self) -> float: + """Controls the strength 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.""" + @property + def sun_azimuth_angle(self) -> float: + """The azimuth angle of the sun. Values range from 0 to 360. Zero is an origin point in a sphere determined by Unreal Engine (degrees).""" + @property + def sun_altitude_angle(self) -> float: + """Altitude angle of the sun. Values range from -90 to 90 corresponding to midnight and midday each (degrees).""" + @property + def fog_density(self) -> float: + """Fog concentration or thickness. It only affects the RGB camera sensor. Values range from 0 to 100.""" + @property + def fog_distance(self) -> float: + """Fog start distance. Values range from 0 to infinite (meters).""" + @property + def wetness(self) -> float: + """Wetness intensity. It only affects the RGB camera sensor. Values range from 0 to 100.""" + @property + def fog_falloff(self) -> float: + """Density of the fog (as in specific mass) from 0 to infinity. The bigger the value, the more dense and heavy it will be, and the fog will reach smaller heights. Corresponds to `Fog Height Falloff` in the UE docs. + + If the value is 0, the fog will be lighter than air, and will cover the whole scene. + A value of 1 is approximately as dense as the air, and reaches normal-sized buildings. + + For values greater than 5, the air will be so dense that it will be compressed on ground level. + """ + @property + def scattering_intensity(self) -> float: + """Controls how much the light will contribute to volumetric fog. When set to 0, there is no contribution.""" + @property + def mie_scattering_scale(self) -> float: + """Controls interaction of light with large particles like pollen or air pollution resulting in a hazy sky with halos around the light sources. When set to 0, there is no contribution.""" + @property + def rayleigh_scattering_scale(self) -> float: + """Controls interaction of light with small particles like air molecules. Dependent on light wavelength, resulting in a blue sky in the day or red sky in the evening.""" + @property + def dust_storm(self) -> float: + """Determines the strength of the dust storm weather. Values range from 0 to 100.""" + # endregion + + # region Methods + def __init__(self, + cloudiness=0.0, + precipitation=0.0, + precipitation_deposits=0.0, + wind_intensity=0.0, + sun_azimuth_angle=0.0, + sun_altitude_angle=0.0, + fog_density=0.0, + fog_distance=0.0, + wetness=0.0, + fog_falloff=0.0, + scattering_intensity=0.0, + mie_scattering_scale=0.0, + rayleigh_scattering_scale=0.0331): + """Method to initialize an object defining weather conditions. This class has some presets for different noon and sunset conditions listed in a note below. + + + Note: ClearNoon, CloudyNoon, WetNoon, WetCloudyNoon, SoftRainNoon, MidRainyNoon, HardRainNoon, ClearSunset, CloudySunset, WetSunset, WetCloudySunset, SoftRainSunset, MidRainSunset, HardRainSunset. + + Args: + `cloudiness (float, optional)`: 0 is a clear sky, 100 complete overcast. Defaults to 0.0.\n + `precipitation (float, optional)`: 0 is no rain at all, 100 a heavy rain. Defaults to 0.0.\n + `precipitation_deposits (float, optional)`: 0 means no puddles on the road, 100 means roads completely capped by rain. Defaults to 0.0.\n + `wind_intensity (float, optional)`: 0 is calm, 100 a strong wind. Defaults to 0.0.\n + `sun_azimuth_angle (float, optional)`: 0 is an arbitrary North, 180 its corresponding South. Defaults to 0.0.\n + `sun_altitude_angle (float, optional)`: 90 is midday, -90 is midnight. Defaults to 0.0.\n + `fog_density (float, optional)`: Concentration or thickness of the fog, from 0 to 100. Defaults to 0.0.\n + `fog_distance (float, optional)`: Distance where the fog starts in meters. Defaults to 0.0.\n + `wetness (float, optional)`: Humidity percentages of the road, from 0 to 100. Defaults to 0.0.\n + `fog_falloff (float, optional)`: Density (specific mass) of the fog, from 0 to infinity. Defaults to 0.0.\n + `scattering_intensity (float, optional)`: Controls how much the light will contribute to volumetric fog. When set to 0, there is no contribution. Defaults to 0.0.\n + `mie_scattering_scale (float, optional)`: Controls interaction of light with large particles like pollen or air pollution resulting in a hazy sky with halos around the light sources. When set to 0, there is no contribution. Defaults to 0.0.\n + `rayleigh_scattering_scale (float, optional)`: Controls interaction of light with small particles like air molecules. Dependent on light wavelength, resulting in a blue sky in the day or red sky in the evening. Defaults to 0.0331.\n + """ + # endregion + + # region Dunder Methods + def __eq__(self, __value: WeatherParameters) -> bool: ... + def __ne__(self, __value: WeatherParameters) -> bool: ... + def __str__(self) -> str: ... + # endregion + + +class WheelPhysicsControl(): + """Class that defines specific physical parameters for wheel objects that will be part of a `carla.VehiclePhysicsControl` to simulate vehicle it as a material object.""" + + # region Instance Variables + @property + def tire_friction(self) -> float: + """A scalar value that indicates the friction of the wheel.""" + @property + def damping_rate(self) -> float: + """Damping rate of the wheel.""" + @property + def max_steer_angle(self) -> float: + """Maximum angle that the wheel can steer (degrees).""" + @property + def radius(self) -> float: + """Radius of the wheel (centimeters).""" + @property + def max_brake_torque(self) -> float: + """Maximum brake torque (N*m).""" + @property + def max_handbrake_torque(self) -> float: + """Maximum handbrake torque.""" + @property + def position(self) -> Vector3D: + """World position of the wheel. This is a read-only parameter.""" + @property + def long_stiff_value(self) -> float: + """Tire longitudinal stiffness per unit gravitational acceleration. Each vehicle has a custom value (kg/rad).""" + @property + def lat_stiff_max_load(self) -> float: + """Maximum normalized tire load at which the tire can deliver no more lateral stiffness no matter how much extra load is applied to the tire. Each vehicle has a custom value.""" + @property + def lat_stiff_value(self) -> float: + """Maximum stiffness per unit of lateral slip. Each vehicle has a custom value.""" + # endregion + + # region Methods + def __init__(self, + tire_friction=2.0, + damping_rate=0.25, + max_steer_angle=70.0, + radius=30.0, + max_brake_torque=1500.0, + max_handbrake_torque=3000.0, + position: Vector3D = Vector3D(0.0, 0.0, 0.0)): ... + # endregion + + # region Dunder Methods + def __eq__(self, __value: WheelPhysicsControl) -> bool: ... + def __ne__(self, __value: WheelPhysicsControl) -> bool: ... + def __str__(self) -> str: ... + # endregion + + +class World(): + """World objects are created by the client to have a place for the simulation to happen. The world contains the map we can see, meaning the asset, not the navigation map. Navigation maps are part of the `carla.Map` class. It also manages the weather and actors present in it. There can only be one world per simulation, but it can be changed anytime.""" + + # region Instance Variables + @property + def id(self) -> int: + """The ID of the episode associated with this world. Episodes are different sessions of a simulation. These change everytime a world is disabled or reloaded. Keeping track is useful to avoid possible issues.""" + @property + def debug(self) -> DebugHelper: + """Responsible for creating different shapes for debugging. Take a look at its class to learn more about it.""" + # endregion + + # region Methods + def apply_color_texture_to_object(self, object_name: str, material_parameter: MaterialParameter, texture: TextureColor): + """Applies a `texture` object in the field corresponding to `material_parameter` (normal, diffuse, etc) to the object in the scene corresponding to `object_name`.""" + + def apply_color_texture_to_objects(self, objects_name_list: list[str], material_parameter: MaterialParameter, texture: TextureColor): + """Applies a `texture` object in the field corresponding to `material_parameter` (normal, diffuse, etc) to the object in the scene corresponding to all objects in `objects_name_list`.""" + + def apply_float_color_texture_to_object(self, object_name: str, material_parameter: MaterialParameter, texture: TextureFloatColor): + """Applies a `texture` object in the field corresponding to `material_parameter` (normal, diffuse, etc) to the object in the scene corresponding to all objects in `objects_name_list`.""" + + def apply_float_color_texture_to_objects(self, objects_name_list: list[str], material_parameter: MaterialParameter, texture: TextureFloatColor): + """Applies a `texture` object in the field corresponding to `material_parameter` (normal, diffuse, etc) to the object in the scene corresponding to all objects in `objects_name_list`.""" + + def apply_settings(self, world_settings: WorldSettings) -> int: + """This method applies settings contained in an object to the simulation running and returns the ID of the frame they were implemented. + + + Warning: If synchronous mode is enabled, and there is a Traffic Manager running, this must be set to sync mode too. Read this to learn how to do it. + https://carla.readthedocs.io/en/latest/adv_traffic_manager/#synchronous-mode + """ + + def apply_textures_to_object(self, object_name: str, diffuse_texture: TextureColor, emissive_texture: TextureFloatColor, normal_texture: TextureFloatColor, ao_roughness_metallic_emissive_texture: TextureFloatColor): + """Applies all texture fields in `carla.MaterialParameter` to the object `object_name`. Empty textures here will not be applied. + """ + + def apply_textures_to_objects(self, objects_name_list: list[str], diffuse_texture: TextureColor, emissive_texture: TextureFloatColor, normal_texture: TextureFloatColor, ao_roughness_metallic_emissive_texture: TextureFloatColor): + """Applies all texture fields in `carla.MaterialParameter` to all objects in `objects_name_list`. Empty textures here will not be applied.""" + + def cast_ray(self, initial_location: Location, final_location: Location) -> list[LabelledPoint]: + """Casts a ray from the specified initial_location to final_location. The function then detects all geometries intersecting the ray and returns a list of `carla.LabelledPoint` in order. + + Args: + initial_location (Location): The initial position of the ray. + final_location (Location): The final position of the ray. + """ + + def enable_environment_objects(self, env_objects_ids: set[int], enable: bool): + """Enable or disable a set of EnvironmentObject identified by their id. These objects will appear or disappear from the level. + + Args: + env_objects_ids (set[int]): Set of EnvironmentObject ids to change. + enable (bool): State to be applied to all the EnvironmentObject of the set. + """ + + def freeze_all_traffic_lights(self, frozen: bool): + """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 ground_projection(self, location: Location, search_distance: float) -> LabelledPoint: + """Projects the specified point downwards in the scene. The functions casts a ray from location in the direction (0,0,-1) (downwards) and returns a `carla.LabelledPoint` object with the first geometry this ray intersects (usually the ground). If no geometry is found in the search_distance range the function returns `None`. + + Args: + location (Location): The point to be projected. + search_distance (float): The maximum distance to perform the projection. + """ + + def load_map_layer(self, map_layers: MapLayer): + """Loads the selected layers to the level. If the layer is already loaded the call has no effect. + + + Warning: This only affects "Opt" maps. The minimum layout includes roads, sidewalks, traffic lights and traffic signs. + + Args: + map_layers (MapLayer): Mask of level layers to be loaded. + """ + + def on_tick(self, callback: Callable[[WorldSnapshot], Any]) -> int: + """This method is used in `asynchronous mode`. It starts callbacks from the client for the function defined as `callback`, and returns the ID of the callback. The function will be called everytime the server ticks. It requires a `carla.WorldSnapshot` as argument, which can be retrieved from `wait_for_tick()`. Use `remove_on_tick()` to stop the callbacks. + + Args: + callback (Callable[[WorldSnapshot], Any]): Function with a `snapshot` as compulsory parameter that will be called when the client receives a tick. + """ + + def project_point(self, location: Location, direction: Vector3D, search_distance: float) -> LabelledPoint: + """Projects the specified point to the desired direction in the scene. The functions casts a ray from location in a direction and returns a carla.Labelled object with the first geometry this ray intersects. If no geometry is found in the search_distance range the function returns `None`. + + Args: + `location (Location)`: The point to be projected.\n + `direction (Vector3D)`: The direction of projection.\n + `search_distance (float)`: The maximum distance to perform the projection.\n + + Returns: + `LabelledPoint`\n + """ + + def remove_on_tick(self, callback_id: int): + """Stops the callback for callback_id started with `on_tick()`. + + Args: + `callback_id (int)`: The callback to be removed. The ID is returned when creating the callback.\n + """ + + def reset_all_traffic_lights(self): + """Resets the cycle of all traffic lights in the map to the initial state. + """ + + def spawn_actor(self, blueprint: ActorBlueprint, transform: Transform, attach_to: Optional[Actor] = None, attachment_type=AttachmentType.Rigid) -> Actor: + """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. + + Args: + `blueprint (ActorBlueprint)`: The reference from which the actor will be created.\n + `transform (Transform)`: Contains the location and orientation the actor will be spawned with.\n + `attach_to (Actor, optional)`: The parent object that the spawned actor will follow around. Defaults to None.\n + `attachment (AttachmentType, optional)`: Determines how fixed and rigorous should be the changes in position according to its parent object. Defaults to AttachmentType.Rigid.\n + + Returns: + `Actor`\n + """ + + def tick(self, seconds=10.0) -> int: + """This method is used in synchronous mode, when the server waits for a client tick before computing the next frame. This method will send the tick, and give way to the server. It returns the ID of the new frame computed by the server. + + + Note: If no tick is received in synchronous mode, the simulation will freeze. Also, if many ticks are received from different clients, there may be synchronization issues. Please read the docs about synchronous mode to learn more. + + Args: + `seconds (float, optional)`: Maximum time the server should wait for a tick. Defaults to 10.0.\n + + Returns: + `int`\n + """ + + def try_spawn_actor(self, blueprint: ActorBlueprint, transform: Transform, attach_to: Optional[Actor] = None, attachment_type=AttachmentType.Rigid) -> Actor: + """Same as `spawn_actor()` but returns `None` on failure instead of throwing an exception. + + Args: + `blueprint (ActorBlueprint)`: The reference from which the actor will be created.\n + `transform (Transform)`: Contains the location and orientation the actor will be spawned with.\n + `attach_to (Actor, optional)`: The parent object that the spawned actor will follow around. Defaults to None.\n + `attachment (AttachmentType, optional)`: Determines how fixed and rigorous should be the changes in position according to its parent object. Defaults to AttachmentType.Rigid.\n + + Returns: + `Actor`\n + """ + + def unload_map_layer(self, map_layers: MapLayer): + """Unloads the selected layers to the level. If the layer is already unloaded the call has no effect. + + + Warning: This only affects "Opt" maps. The minimum layout includes roads, sidewalks, traffic lights and traffic signs. + + Args: + `map_layers (MapLayer)`: Mask of level layers to be unloaded.\n + """ + + def wait_for_tick(self, seconds=10.0) -> WorldSnapshot: + """This method is used in asynchronous mode. It makes the client wait for a server tick. When the next frame is computed, the server will tick and return a snapshot describing the new state of the world. + + Args: + `seconds (float, optional)`: Maximum time the server should wait for a tick. Defaults to 10.0.\n + + Returns: + `WorldSnapshot`\n + """ + # endregion + + # region Getters + def get_actor(self, actor_id: int) -> Actor: + """Looks up for an actor by ID and returns `None` if not found.""" + + def get_actors(self, actor_ids: Optional[list[int]] = None) -> ActorList: + """ + Retrieves a list of `carla.Actor` elements, either using a list of IDs provided or just + listing everyone on stage. If an ID does not correspond with any actor, it will be excluded + from the list returned, meaning that both the list of IDs and the list of actors may have + different lengths. + + Args: + `actor_ids (list[int], optional)`: The IDs of the actors being searched. By default it is set to None and returns every actor on scene. + + Returns: + `ActorList` + """ + + def get_blueprint_library(self) -> BlueprintLibrary: + """Returns a list of actor blueprints available to ease the spawn of these into the world.""" + + def get_environment_objects(self, object_type: CityObjectLabel = CityObjectLabel.Any) -> list[EnvironmentObject]: + """Returns a list of EnvironmentObject with the requested semantic tag. The method returns all the EnvironmentObjects in the level by default, but the query can be filtered by semantic tags with the argument `object_type`. + + Args: + `object_type (CityObjectLabel, optional)`: Semantic tag of the EnvironmentObjects that are returned. Defaults to CityObjectLabel.Any.\n + """ + + def get_level_bbs(self, actor_type: CityObjectLabel = CityObjectLabel.Any) -> list[BoundingBox]: + """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`. + + Args: + `actor_type (CityObjectLabel, optional)`: Semantic tag of the elements contained in the bounding boxes that are returned. Defaults to CityObjectLabel.Any.\n + + Returns: + `list[BoundingBox]`\n + """ + + def get_lightmanager(self) -> LightManager: + """Returns an instance of carla.LightManager that can be used to handle the lights in the scene.""" + + def get_map(self) -> Map: + """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. It is expensive, and should only be called once. + + """ + + def get_names_of_all_objects(self) -> list[str]: + """Returns a list of the names of all objects in the scene that can be painted with the apply texture functions.""" + + def get_random_location_from_navigation(self) -> Location: + """This can only be used with walkers. It retrieves a random location to be used as a destination using the `go_to_location()` method in `carla.WalkerAIController`. This location will be part of a sidewalk. Roads, crosswalks and grass zones are excluded. The method does not take into consideration locations of existing actors so if a collision happens when trying to spawn an actor, it will return an error. Take a look at `generate_traffic.py` for an example.""" + + def get_settings(self) -> WorldSettings: + """Returns an object containing some data about the simulation such as synchrony between client and server or rendering mode.""" + + def get_snapshot(self) -> WorldSnapshot: + """Returns a snapshot of the world at a certain moment comprising all the information about the actors.""" + + def get_spectator(self) -> Actor: + """Returns the spectator actor. The spectator is a special type of actor created by Unreal Engine, usually with ID=0, that acts as a camera and controls the view in the simulator window.""" + + def get_traffic_light(self, landmark: Landmark) -> TrafficLight: + """Provided a landmark, returns the traffic light object it describes. + + Args: + `landmark (Landmark)`: The landmark object describing a traffic light.\n + """ + + def get_traffic_light_from_opendrive_id(self, traffic_light_id: str) -> TrafficLight: + """Returns the traffic light actor corresponding to the indicated OpenDRIVE id. + + Args: + `traffic_light_id (str)`: The OpenDRIVE id.\n + """ + + def get_traffic_lights_from_waypoint(self, waypoint: Waypoint, distance: float) -> list[TrafficLight]: + """This function performs a search along the road in front of the specified waypoint and returns a list of traffic light actors found in the specified search distance. + + Args: + `waypoint (Waypoint)`: The input waypoint.\n + `distance (float)`: Search distance.\n + """ + + def get_traffic_lights_in_junction(self, junction_id: int) -> list[TrafficLight]: + """Returns the list of traffic light actors affecting the junction indicated in `junction_id`. + + Args: + `junction_id (int)`: The id of the junction.\n + """ + + def get_traffic_sign(self, landmark: Landmark) -> TrafficSign: + """Provided a landmark, returns the traffic sign object it describes. + + Args: + `landmark (Landmark)`: The landmark object describing a traffic sign.\n + """ + + def get_vehicles_light_states(self) -> dict[int, VehicleLightState]: + """Returns a dict where the keys are `carla.Actor` IDs and the values are `carla.VehicleLightState` of that vehicle. + """ + + def get_weather(self) -> WeatherParameters: + """Retrieves an object containing weather parameters currently active in the simulation, mainly cloudiness, precipitation, wind and sun position. + + + Setter: `carla.World.set_weather` + """ + # endregion + + # region Setters + def set_pedestrians_cross_factor(self, percentage: float): + """Sets the percentage of pedestrians that can walk on the road or cross at any point on the road. + + + Note: Should be set before pedestrians are spawned. + + Args: + `percentage (float)`: Value should be between 0.0 and 1.0. For example, a value of 0.1 would allow 10% of pedestrians to walk on the road.\n + """ + + def set_pedestrians_seed(self, seed: int): + """ Sets the seed to use for any random number generated in relation to pedestrians. + + + Note: Should be set before pedestrians are spawned. If you want to repeat the same exact bodies (blueprint) for each pedestrian, then use the same seed in the Python code (where the blueprint is chosen randomly) and here, otherwise the pedestrians will repeat the same paths but the bodies will be different. + """ + + def set_weather(self, weather: WeatherParameters): + """Changes the weather parameters ruling the simulation to another ones defined in an object. + + + Getter: `carla.World.get_weather` + + Args: + `weather (WeatherParameters)`: New conditions to be applied.\n + """ + # endregion + + # region Dunder Methods + def __str__(self) -> str: + """The content of the world is parsed and printed as a brief report of its current state.""" + # endregion + + +class WorldSettings(): + """The simulation has some advanced configuration options that are contained in this class and can be managed using carla.World and its methods. These allow the user to choose between client-server synchrony/asynchrony, activation of "no rendering mode" and either if the simulation should run with a fixed or variable time-step. Check this out if you want to learn about it. + + https://carla.readthedocs.io/en/latest/adv_synchrony_timestep/ + """ + + # region description + @property + def synchronous_mode(self) -> bool: + """States the synchrony between client and server. When set to true, the server will wait for a client tick in order to move forward. It is `False` by default.""" + @synchronous_mode.setter + def synchronous_mode(self, value: bool): + ... + + @property + def no_rendering_mode(self) -> bool: + """When enabled, the simulation will run no rendering at all. This is mainly used to avoid overhead during heavy traffic simulations. It is `False` by default.""" + @no_rendering_mode.setter + def no_rendering_mode(self, value: bool): + ... + + @property + def fixed_delta_seconds(self) -> float | None: + """Ensures that the time elapsed between two steps of the simulation is fixed. Set this to `0.0` to work with a variable time-step, as happens by default.""" + @fixed_delta_seconds.setter + def fixed_delta_seconds(self, value: float | None): + ... + + @property + def substepping(self) -> bool: + """Enable the physics substepping. This option allows computing some physics substeps between two render frames. If synchronous mode is set, the number of substeps and its time interval are fixed and computed are so they fulfilled the requirements of `carla.WorldSettings.max_substep` and `carla.WorldSettings.max_substep_delta_time`. These last two parameters need to be compatible with c`arla.WorldSettings.fixed_delta_seconds`. Enabled by default.""" + @substepping.setter + def substepping(self, value: bool): + ... + + @property + def max_substep_delta_time(self) -> float: + """Maximum delta time of the substeps. If the carla.`WorldSettingsmax_substep` is high enough, the substep delta time would be always below or equal to this value. By default, the value is set to 0.01.""" + @max_substep_delta_time.setter + def max_substep_delta_time(self, value: float): + ... + + @property + def max_substeps(self) -> int: + """The maximum number of physics substepping that are allowed. By default, the value is set to 10.""" + @max_substeps.setter + def max_substeps(self, value: int): + ... + + @property + def max_culling_distance(self) -> float: + """Configure the max draw distance for each mesh of the level.""" + @max_culling_distance.setter + def max_culling_distance(self, value: float): + ... + + @property + def deterministic_ragdolls(self) -> bool: + """Defines wether to use deterministic physics for pedestrian death animations or physical ragdoll simulation. When enabled, pedestrians have less realistic death animation but ensures determinism. When disabled, pedestrians are simulated as ragdolls with more realistic simulation and collision but no determinsm can be ensured.""" + @deterministic_ragdolls.setter + def deterministic_ragdolls(self, value: bool): + ... + + @property + def tile_stream_distance(self) -> bool: + """Used for large maps only. Configures the maximum distance from the hero vehicle to stream tiled maps. Regions of the map within this range will be visible (and capable of simulating physics). Regions outside this region will not be loaded.""" + @tile_stream_distance.setter + def tile_stream_distance(self, value: bool): + ... + + @property + def actor_active_distance(self) -> float: + """Used for large maps only. Configures the distance from the hero vehicle to convert actors to dormant. Actors within this range will be active, and actors outside will become dormant.""" + @actor_active_distance.setter + def actor_active_distance(self, value: float): + ... + + @property + def spectator_as_ego(self) -> float: + """Used for large maps only. Defines the influence of the spectator on tile loading in Large Maps. By default, the spectator will provoke loading of neighboring tiles in the absence of an ego actor. This might be inconvenient for applications that immediately spawn an ego actor.""" + @spectator_as_ego.setter + def spectator_as_ego(self, value: float): + ... + + # region Methods + def __init__(self, + synchronous_mode=False, + no_rendering_mode=False, + fixed_delta_seconds=0.0, + max_culling_distance=0.0, + deterministic_ragdolls=False, + tile_stream_distance=3000, + actor_active_distance=2000, + spectator_as_ego=True): + """Creates an object containing desired settings that could later be applied through `carla.World` and its method `apply_settings()`. + + Args: + `synchronous_mode (bool, optional)`: Set this to true to enable client-server synchrony. Defaults to False.\n + `no_rendering_mode (bool, optional)`: Set this to true to completely disable rendering in the simulation. Defaults to False.\n + `fixed_delta_seconds (float, optional)`: Set a fixed time-step in between frames. 0.0 means variable time-step (seconds). Defaults to 0.0.\n + `max_culling_distance (float, optional)`: Configure the max draw distance for each mesh of the level (meters). Defaults to 0.0.\n + `deterministic_ragdolls (bool, optional)`: Defines wether to use deterministic physics or ragdoll simulation for pedestrian deaths. Defaults to False.\n + `tile_stream_distance (int, optional)`: Used for large maps only. Configures the maximum distance from the hero vehicle to stream tiled maps (meters). Defaults to 3000.\n + `actor_active_distance (int, optional)`: Used for large maps only. Configures the distance from the hero vehicle to convert actors to dormant (meters). Defaults to 2000.\n + `spectator_as_ego (bool, optional)`: Used for large maps only. Defines the influence of the spectator on tile loading in Large Maps. Defaults to True.\n + + Returns: + `WorldSettings`: _description_\n + """ + # endregion + + # region Dunder Methods + def __eq__(self, __value: WorldSettings) -> bool: ... + def __ne__(self, __value: WorldSettings) -> bool: ... + def __str__(self) -> str: ... + # endregion + + +class WorldSnapshot(): + """ + This snapshot comprises all the information for every actor on scene at a certain moment of time. + It creates and gives access to a data structure containing a series of `carla.ActorSnapshot`. + The client receives a new snapshot on every tick that cannot be stored. + """ + + # region Instance Variables + @property + def id(self) -> int: + """A value unique for every snapshot to differentiate them.""" + @property + def frame(self) -> int: + """Simulation frame in which the snapshot was taken.""" + @property + def timestamp(self) -> Timestamp: + """Precise moment in time when snapshot was taken. This class works in seconds as given by the operative system (seconds).""" + # endregion + + # region Methods + def find(self, actor_id: int) -> ActorSnapshot: + """Given a certain actor ID, returns its corresponding snapshot or `None` if it is not found. + """ + + def has_actor(self, actor_id: int) -> bool: + """Given a certain actor ID, checks if there is a snapshot corresponding it and so, if the actor was present at that moment.""" + # endregion + + # region Dunder Methods + def __eq__(self, __value: WorldSnapshot) -> bool: + """Returns True if both `timestamp` are the same.""" + + def __iter__(self) -> Iterator[ActorSnapshot]: + """Iterate over the `carla.ActorSnapshot` stored in the snapshot.""" + + def __len__(self) -> int: + """Returns the amount of `carla.ActorSnapshot` present in this snapshot.""" + + def __ne__(self, __value: WorldSnapshot) -> bool: + """Returns True if both `timestamp` are different.""" + # endregion + + +class command(): + """ + Submodule with commands that can be used with `carla.Client.apply_batch` + and `carla.Client.apply_batch_sync`. + """ + + class ApplyAngularImpulse(): + """Command adaptation of `add_angular_impulse()` in `carla.Actor`. Applies an angular impulse to an actor. + """ + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor affected by the command.""" + @property + def impulse(self) -> Vector3D: + """Angular impulse applied to the actor (degrees*s).""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], impulse: Vector3D): + """Applies an angular impulse to an actor. + + Args: + `actor (Union[Actor,int])`: Actor or its ID to whom the command will be applied to.\n + `impulse (Vector3D)`: (degrees*s)\n + """ + # endregion + + class ApplyForce(): + """Command adaptation of `add_force()` in `carla.Actor`. Applies a force to an actor.""" + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor affected by the command.""" + @property + def force(self) -> Vector3D: + """Force applied to the actor over time (N).""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], force: Vector3D): + """Applies a force to an actor. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + `force (Vector3D)`: (N)\n + """ + # endregion + + class ApplyImpulse(): + """Command adaptation of `add_impulse()` in `carla.Actor`. Applies an impulse to an actor.""" + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor affected by the command.""" + @property + def impulse(self) -> Vector3D: + """Impulse applied to the actor (N*s).""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], impulse: Vector3D): + """Applies an impulse to an actor. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + `impulse (Vector3D)`: (N*s)\n + """ + # endregion + + class ApplyTargetAngularVelocity(): + """Command adaptation of `set_target_angular_velocity()` in `carla.Actor`. Sets the actor's angular velocity vector. + """ + + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor affected by the command.""" + @property + def angular_velocity(self) -> Vector3D: + """The 3D angular velocity that will be applied to the actor (deg/s).""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], angular_velocity: Vector3D): + """Sets the actor's angular velocity vector. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + `angular_velocity (Vector3D)`: Angular velocity vector applied to the actor.\n + """ + # endregion + + class ApplyTargetVelocity(): + """Command adaptation of `set_target_velocity()` in `carla.Actor`. Sets the actor's target velocity vector. + """ + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor affected by the command.""" + @property + def velocity(self) -> Vector3D: + """The 3D velocity applied to the actor (m/s).""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], velocity: Vector3D): + """Sets the actor's target velocity vector. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + `velocity (Vector3D)`: Velocity vector applied to the actor.\n + """ + # endregion + + class ApplyTorque(): + """ + Command adaptation of `add_torque()` in carla.Actor. Applies a torque to an actor. + """ + + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor affected by the command.""" + + @property + def transform(self) -> Vector3D: + """Torque applied to the actor over time (degrees).""" + + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], torque: Vector3D): + """Sets a new transform to an actor. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + `torque (Vector3D)`: Torque vector in global coordinates (degrees). + """ + # endregion + + class ApplyTransform(): + """ + Command adaptation of `set_transform()` in `carla.Actor`. Sets a new transform to an actor. + """ + + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor affected by the command.""" + @property + def transform(self) -> Transform: + """Transformation to be applied.""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], transform: Transform): + """Sets a new transform to an actor. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + `transform (Transform)`\n + """ + # endregion + + class ApplyVehicleAckermannControl(): + """Command adaptation of `apply_ackermann_control()` in `carla.Vehicle`. Applies a certain akermann control to a vehicle. + """ + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor affected by the command.""" + @property + def control(self) -> AckermannControllerSettings: + """Vehicle ackermann control to be applied.""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], control: AckermannControllerSettings): + """Applies a certain akermann control to a vehicle. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + `control (AckermannControllerSettings)`: Vehicle ackermann control to be applied.\n + """ + # endregion + + class ApplyVehicleControl(): + """Command adaptation of `apply_control()` in `carla.Vehicle`. Applies a certain control to a vehicle.""" + + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor affected by the command.""" + @property + def control(self) -> VehicleControl: + """Vehicle control to be applied.""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], control: VehicleControl): + """Applies a certain control to a vehicle. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + `control (VehicleControl)`: Vehicle control to be applied.\n + """ + # endregion + + class ApplyVehiclePhysicsControl(): + """Command adaptation of `apply_physics_control()` in `carla.Vehicle`. Applies a new physics control to a vehicle, modifying its physical parameters.""" + + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor affected by the command.""" + @property + def control(self) -> VehiclePhysicsControl: + """Physics control to be applied.""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], control: VehicleControl): + """Applies a new physics control to a vehicle, modifying its physical parameters. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + `control (VehicleControl)`: Physics control to be applied.\n + """ + # endregion + + class ApplyWalkerControl(): + """Command adaptation of `apply_control()` in `carla.Walker`. Applies a control to a walker.""" + + # region Instance Variables + @property + def actor_id(self) -> int: + """Walker actor affected by the command.""" + @property + def control(self) -> VehiclePhysicsControl: + """Walker control to be applied.""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], control: VehicleControl): + """Applies a control to a walker. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + `control (VehicleControl)`: Walker control to be applied.\n + """ + # endregion + + class ApplyWalkerState(): + """Apply a state to the walker actor. Specially useful to initialize an actor them with a specific location, orientation and speed.""" + + # region Instance Variables + @property + def actor_id(self) -> int: + """Walker actor affected by the command.""" + @property + def transform(self) -> Transform: + """Transform to be applied.""" + @property + def speed(self) -> float: + """Speed to be applied (m/s).""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], transform: Transform, speed: float): + """Apply a state to the walker actor. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + `transform (Transform)`: Transform to be applied.\n + `speed (float)`: Speed to be applied (m/s).\n + """ + # endregion + + class DestroyActor(): + """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 c`arla.Client` there will be a `command.Response` that will return a boolean stating whether the actor was successfully destroyed.""" + + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor affected by the command.""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int]): + """Command adaptation of `destroy()` in `carla.Actor` that tells the simulator to destroy this actor. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + """ + # endregion + + class FutureActor(): + """A utility object used to reference an actor that will be created in the command in the previous step, it has no parameters or methods.""" + + class 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 c`arla.Client` returns a list of these to summarize the execution of a batch. + """ + + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor to whom the command was applied to. States that the command was successful.""" + @property + def error(self) -> str: + """A string stating the command has failed.""" + # endregion + + # region Methods + def has_error(self) -> bool: + """Returns `True` if the command execution fails, and `False` if it was successful.""" + # endregion + + class SetAutopilot(): + """Command adaptation of `set_autopilot()` in `carla.Vehicle`. Turns on/off the vehicle's autopilot mode.""" + + # region Instance Methods + @property + def actor_id(self) -> int: + """Actor that is affected by the command.""" + @property + def enabled(self) -> bool: + """If autopilot should be activated or not.""" + @property + def port(self) -> int: + """Port of the Traffic Manager where the vehicle is to be registered or unlisted.""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], enabled: bool, port=8000): + """Turns on/off the vehicle's autopilot mode. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + `enabled (bool)`: _description_\n + `port (int, optional)`: The Traffic Manager port where the vehicle is to be registered or unlisted. If None is passed, it will consider a TM at default port 8000. Defaults to 8000.\n + """ + # endregion + + class SetEnableGravity(): + """Command adaptation of `set_enable_gravity()` in `carla.Actor`. Enables or disables gravity on an actor.""" + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor that is affected by the command.""" + @property + def enabled(self) -> bool: + """If gravity should be activated or not.""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], enabled: bool): + """Enables or disables gravity on an actor. + + Args: + `actor (Union[Actor, int])`: Actor or Actor ID to which the command will be applied to.\n + `enabled (bool)`: If gravity should be activated or not.\n + """ + # endregion + + class SetSimulatePhysics(): + """Command adaptation of `set_simulate_physics()` in `carla.Actor`. Determines whether an actor will be affected by physics or not.""" + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor that is affected by the command.""" + @property + def enabled(self) -> bool: + """If physics should be activated or not.""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], enabled: bool): + """Determines whether an actor will be affected by physics or not. + + Args: + `actor (Union[Actor, int])`: Actor or Actor ID to which the command will be applied to.\n + `enabled (bool)`: If physics should be activated or not.\n + """ + # endregion + + class SetVehicleLightState(): + """Command adaptation of `set_light_state()` in `carla.Vehicle`. Sets the light state of a vehicle.""" + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor that is affected by the command.""" + @property + def light_state(self) -> VehicleLightState: + """Recaps the state of the lights of a vehicle, these can be used as a flags.""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], light_state: VehicleLightState): + """Sets the light state of a vehicle. + + Args: + `actor (Union[Actor, int])`: Actor or its ID to whom the command will be applied to.\n + `light_state (VehicleLightState)`: Recaps the state of the lights of a vehicle, these can be used as a flags.\n + """ + # endregion + + class ShowDebugTelemetry(): + """Command adaptation of `show_debug_telemetry()` in `carla.Actor`. Displays vehicle control telemetry data. + """ + # region Instance Variables + @property + def actor_id(self) -> int: + """Actor that is affected by the command.""" + @property + def enabled(self) -> bool: + """If debug should be activated or not.""" + # endregion + + # region Methods + def __init__(self, actor: Union[Actor, int], enabled: bool): + """Displays vehicle control telemetry data. + + Args: + `actor (Union[Actor, int])`: Actor or Actor ID to which the command will be applied to.\n + `enabled (bool)`: If debug should be activated or not.\n + """ + # endregion + + class SpawnActor(): + """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.""" + + # region Instance Variables + @property + def transform(self) -> Transform: + """Transform to be applied.""" + @property + def parent_id(self) -> int: + """Identificator of the parent actor.""" + # endregion + + # region Methods + @overload + def __init__(self): ... + @overload + def __init__(self, blueprint: ActorBlueprint, transform: Transform): ... + @overload + def __init__(self, blueprint: ActorBlueprint, transform: Transform, parent: Union[Actor, int]): ... + + def then(self, command: command): + """Links another command to be executed right after. It allows to ease very common flows such as spawning a set of vehicles by command and then using this method to set them to autopilot automatically. + + Args: + `command (command)`: a Carla command.\n + """ + # endregion diff --git a/PythonAPI/carla/source/libcarla/Geom.cpp b/PythonAPI/carla/source/libcarla/Geom.cpp index 57e3941cf64..45e1199a317 100644 --- a/PythonAPI/carla/source/libcarla/Geom.cpp +++ b/PythonAPI/carla/source/libcarla/Geom.cpp @@ -266,6 +266,7 @@ void export_geom() { .def_readwrite("location", &cg::BoundingBox::location) .def_readwrite("extent", &cg::BoundingBox::extent) .def_readwrite("rotation", &cg::BoundingBox::rotation) + .def_readonly("actor_id", &cg::BoundingBox::actor_id) .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/docs/geom.yml b/PythonAPI/docs/geom.yml index eb71836e4cf..7fc6180dc23 100644 --- a/PythonAPI/docs/geom.yml +++ b/PythonAPI/docs/geom.yml @@ -325,11 +325,13 @@ - 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.
- -
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* + 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)`. +
+ + *Unreal Engine's left handed coordinate system with rotations* # - PROPERTIES ------------------------- instance_variables: - var_name: pitch diff --git a/PythonAPI/docs/sensor.yml b/PythonAPI/docs/sensor.yml index 5885217cd0f..8a2f87baaf8 100644 --- a/PythonAPI/docs/sensor.yml +++ b/PythonAPI/docs/sensor.yml @@ -17,7 +17,6 @@ - [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)
@@ -111,154 +110,4 @@ - def_name: __str__ # -------------------------------------- - - class_name: RssSensor - parent: carla.Sensor - # - DESCRIPTION ------------------------ - doc: > - This sensor works a bit differently than the rest. Take look at the [specific documentation](adv_rss.md), and the [rss sensor reference](ref_sensors.md#rss-sensor) to gain full understanding of it. - - - The RSS sensor uses world information, and a [RSS library](https://github.com/intel/ad-rss-lib) to make safety checks on a vehicle. The output retrieved by the sensor is a carla.RssResponse. This will be used by a carla.RssRestrictor to modify a carla.VehicleControl before applying it to a vehicle. - # - PROPERTIES ------------------------- - instance_variables: - - var_name: ego_vehicle_dynamics - type: ad.rss.world.RssDynamics - doc: > - States the [RSS parameters](https://intel.github.io/ad-rss-lib/ad_rss/Appendix-ParameterDiscussion/) that the sensor will consider for the ego vehicle if no actor constellation callback is registered. - - var_name: other_vehicle_dynamics - type: ad.rss.world.RssDynamics - doc: > - States the [RSS parameters](https://intel.github.io/ad-rss-lib/ad_rss/Appendix-ParameterDiscussion/) that the sensor will consider for the rest of vehicles if no actor constellation callback is registered. - - var_name: pedestrian_dynamics - type: ad.rss.world.RssDynamics - doc: > - States the [RSS parameters](https://intel.github.io/ad-rss-lib/ad_rss/Appendix-ParameterDiscussion/) that the sensor will consider for pedestrians if no actor constellation callback is registered. - - var_name: road_boundaries_mode - type: carla.RssRoadBoundariesMode - doc: > - Switches the [stay on road](https://intel.github.io/ad-rss-lib/ad_rss_map_integration/HandleRoadBoundaries/) feature. By default is __Off__. - - var_name: routing_targets - type: vector - doc: > - The current list of targets considered to route the vehicle. If no routing targets are defined, a route is generated at random. - # - METHODS ---------------------------- - methods: - - def_name: append_routing_target - params: - - param_name: routing_target - type: carla.Transform - doc: > - New target point for the route. Choose these after the intersections to force the route to take the desired turn. - doc: > - Appends a new target position to the current route of the vehicle. - - def_name: reset_routing_targets - doc: > - Erases the targets that have been appended to the route. - - def_name: drop_route - doc: > - Discards the current route. If there are targets remaining in **routing_targets**, creates a new route using those. Otherwise, a new route is created at random. - - def_name: register_actor_constellation_callback - params: - - param_name: callback - doc: > - The function to be called whenever a RSS situation is about to be calculated. - doc: > - Register a callback to customize a carla.RssActorConstellationResult. By this callback the settings of RSS parameters are done per actor constellation and the settings (ego_vehicle_dynamics, other_vehicle_dynamics and pedestrian_dynamics) have no effect. - - def_name: set_log_level - params: - - param_name: log_level - type: carla.RssLogLevel - doc: > - New log level. - doc: > - Sets the log level. - - def_name: set_map_log_level - params: - - param_name: log_level - type: carla.RssLogLevel - doc: > - New map log level. - doc: > - Sets the map log level. - # -------------------------------------- - - def_name: __str__ - # -------------------------------------- - - - class_name: RssRestrictor - parent: - # - DESCRIPTION ------------------------ - doc: > - These objects apply restrictions to a carla.VehicleControl. It is part of the CARLA implementation of the [C++ Library for Responsibility Sensitive Safety](https://github.com/intel/ad-rss-lib). This class works hand in hand with a [rss sensor](ref_sensors.md#rss-sensor), which provides the data of the restrictions to be applied. - # - PROPERTIES ------------------------- - instance_variables: - - # - METHODS ---------------------------- - methods: - - def_name: restrict_vehicle_control - params: - - param_name: vehicle_control - type: carla.VehicleControl - doc: > - The input vehicle control to be restricted. - - param_name: proper_response - type: ad.rss.state.ProperResponse - doc: > - Part of the response generated by the sensor. Contains restrictions to be applied to the acceleration of the vehicle. - - param_name: ego_dynamics_on_route - type: carla.RssEgoDynamicsOnRoute - doc: > - Part of the response generated by the sensor. Contains dynamics and heading of the vehicle regarding its route. - - param_name: vehicle_physics - type: carla.VehiclePhysicsControl - doc: > - The current physics of the vehicle. Used to apply the restrictions properly. - return: - carla.VehicleControl - doc: > - Applies the safety restrictions given by a carla.RssSensor to a carla.VehicleControl. - - def_name: set_log_level - params: - - param_name: log_level - type: carla.RssLogLevel - doc: > - New log level. - doc: > - Sets the log level. - # -------------------------------------- - - - class_name: RssRoadBoundariesMode - # - DESCRIPTION ------------------------ - doc: > - Enum declaration used in carla.RssSensor to enable or disable the [stay on road](https://intel.github.io/ad-rss-lib/ad_rss_map_integration/HandleRoadBoundaries/) feature. In summary, this feature considers the road boundaries as virtual objects. The minimum safety distance check is applied to these virtual walls, in order to make sure the vehicle does not drive off the road. - # - PROPERTIES ------------------------- - instance_variables: - - var_name: 'On' - doc: > - Enables the _stay on road_ feature. - # -------------------------------------- - - var_name: 'Off' - doc: > - Disables the _stay on road_ feature. - # -------------------------------------- - - - class_name: RssLogLevel - # - DESCRIPTION ------------------------ - doc: > - Enum declaration used in carla.RssSensor to set the log level. - # - PROPERTIES ------------------------- - instance_variables: - - var_name: 'trace' - # -------------------------------------- - - var_name: 'debug' - # -------------------------------------- - - var_name: 'info' - # -------------------------------------- - - var_name: 'warn' - # -------------------------------------- - - var_name: 'err' - # -------------------------------------- - - var_name: 'critical' - # -------------------------------------- - - var_name: 'off' - # -------------------------------------- ... diff --git a/PythonAPI/docs/sensor_data.yml b/PythonAPI/docs/sensor_data.yml index cdd394a5698..68763bf4933 100644 --- a/PythonAPI/docs/sensor_data.yml +++ b/PythonAPI/docs/sensor_data.yml @@ -14,7 +14,6 @@ - LIDAR sensor: carla.LidarMeasurement.
- Obstacle detector: carla.ObstacleDetectionEvent.
- Radar sensor: carla.RadarMeasurement.
- - RSS sensor: carla.RssResponse.
- Semantic LIDAR sensor: carla.SemanticLidarMeasurement.
- Cooperative awareness messages V2X sensor: carla.CAMEvent.
- Custom V2X messages V2X sensor: carla.CustomV2XEvent. @@ -575,207 +574,6 @@ - def_name: __str__ # -------------------------------------- - - class_name: RssResponse - parent: carla.SensorData - # - DESCRIPTION ------------------------ - doc: > - Class that contains the output of a carla.RssSensor. This is the result of the RSS calculations performed for the parent vehicle of the sensor. - - - A carla.RssRestrictor will use the data to modify the carla.VehicleControl of the vehicle. - # - PROPERTIES ------------------------- - instance_variables: - - var_name: response_valid - type: bool - doc: > - States if the response is valid. It is __False__ if calculations failed or an exception occured. - # -------------------------------------- - - var_name: proper_response - type: ad.rss.state.ProperResponse - doc: > - The proper response that the RSS calculated for the vehicle. - # -------------------------------------- - - var_name: rss_state_snapshot - type: ad.rss.state.RssStateSnapshot - doc: > - Detailed RSS states at the current moment in time. - # -------------------------------------- - - var_name: ego_dynamics_on_route - type: carla.RssEgoDynamicsOnRoute - doc: > - Current ego vehicle dynamics regarding the route. - # -------------------------------------- - - var_name: world_model - type: ad.rss.world.WorldModel - doc: > - World model used for calculations. - # -------------------------------------- - - var_name: situation_snapshot - type: ad.rss.situation.SituationSnapshot - doc: > - Detailed RSS situations extracted from the world model. - # - METHODS ---------------------------- - methods: - - def_name: __str__ - # -------------------------------------- - - - class_name: RssEgoDynamicsOnRoute - # - DESCRIPTION ------------------------ - doc: > - Part of the data contained inside a carla.RssResponse describing the state of the vehicle. The parameters include its current dynamics, and how it is heading regarding the target route. - # - PROPERTIES ------------------------- - instance_variables: - ## ** Missing timestamp and time_since_epoch_check_start_ms - - var_name: ego_speed - type: ad.physics.Speed - doc: > - The ego vehicle's speed. - # -------------------------------------- - - var_name: min_stopping_distance - type: ad.physics.Distance - doc: > - The current minimum stopping distance. - # -------------------------------------- - - var_name: ego_center - type: ad.map.point.ENUPoint - doc: > - The considered enu position of the ego vehicle. - # -------------------------------------- - - var_name: ego_heading - type: ad.map.point.ENUHeading - doc: > - The considered heading of the ego vehicle. - # -------------------------------------- - - var_name: ego_center_within_route - type: bool - doc: > - States if the ego vehicle's center is within the route. - # -------------------------------------- - - var_name: crossing_border - type: bool - doc: > - States if the vehicle is already crossing one of the lane borders. - # -------------------------------------- - - var_name: route_heading - type: ad.map.point.ENUHeading - doc: > - The considered heading of the route. - # -------------------------------------- - - var_name: route_nominal_center - type: ad.map.point.ENUPoint - doc: > - The considered nominal center of the current route. - # -------------------------------------- - - var_name: heading_diff - type: ad.map.point.ENUHeading - doc: > - The considered heading diff towards the route. - # -------------------------------------- - - var_name: route_speed_lat - type: ad.physics.Speed - doc: > - The ego vehicle's speed component _lat_ regarding the route. - # -------------------------------------- - - var_name: route_speed_lon - type: ad.physics.Speed - doc: > - The ego vehicle's speed component _lon_ regarding the route. - # -------------------------------------- - - var_name: route_accel_lat - type: ad.physics.Acceleration - doc: > - The ego vehicle's acceleration component _lat_ regarding the route. - # -------------------------------------- - - var_name: route_accel_lon - type: ad.physics.Acceleration - doc: > - The ego vehicle's acceleration component _lon_ regarding the route. - # -------------------------------------- - - var_name: avg_route_accel_lat - type: ad.physics.Acceleration - doc: > - The ego vehicle's acceleration component _lat_ regarding the route smoothened by an average filter. - # -------------------------------------- - - var_name: avg_route_accel_lon - type: ad.physics.Acceleration - doc: > - The ego acceleration component _lon_ regarding the route smoothened by an average filter. - # - METHODS ---------------------------- - methods: - - def_name: __str__ - # -------------------------------------- - - - class_name: RssActorConstellationData - # - DESCRIPTION ------------------------ - doc: > - Data structure that is provided within the callback registered by RssSensor.register_actor_constellation_callback(). - # - PROPERTIES ------------------------- - instance_variables: - - var_name: ego_match_object - type: ad.map.match.Object - doc: > - The ego map matched information. - # -------------------------------------- - - var_name: ego_route - type: ad.map.route.FullRoute - doc: > - The ego route. - # -------------------------------------- - - var_name: ego_dynamics_on_route - type: carla.RssEgoDynamicsOnRoute - doc: > - Current ego vehicle dynamics regarding the route. - # -------------------------------------- - - var_name: other_match_object - type: ad.map.match.Object - doc: > - The other object's map matched information. This is only valid if 'other_actor' is not 'None'. - # -------------------------------------- - - var_name: other_actor - type: carla.Actor - doc: > - The other actor. This is 'None' in case of query of default parameters or articial objects of kind ad.rss.world.ObjectType.ArtificialObject - with no dedicated 'carla.Actor' (as e.g. for the [road boundaries](ref_sensors.md#rss-sensor) at the moment) - # - METHODS ---------------------------- - methods: - - def_name: __str__ - # -------------------------------------- - - - class_name: RssActorConstellationResult - # - DESCRIPTION ------------------------ - doc: > - Data structure that should be returned by the callback registered by RssSensor.register_actor_constellation_callback(). - # - PROPERTIES ------------------------- - instance_variables: - - var_name: rss_calculation_mode - type: ad.rss.map.RssMode - doc: > - The calculation mode to be applied with the actor. - # -------------------------------------- - - var_name: restrict_speed_limit_mode - type: ad.rss.map.RestrictSpeedLimitMode - doc: > - The mode for restricting speed limit. - # -------------------------------------- - - var_name: ego_vehicle_dynamics - type: ad.rss.world.RssDynamics - doc: > - The RSS dynamics to be applied for the ego vehicle. - # -------------------------------------- - - var_name: actor_object_type - type: ad.rss.world.ObjectType - doc: > - The RSS object type to be used for the actor. - # -------------------------------------- - - var_name: actor_dynamics - type: ad.rss.world.RssDynamics - doc: > - The RSS dynamics to be applied for the actor. - # - METHODS ---------------------------- - methods: - - def_name: __str__ - # -------------------------------------- - - class_name: DVSEvent # - DESCRIPTION ------------------------ doc: > diff --git a/PythonAPI/examples/invertedai_traffic.py b/PythonAPI/examples/invertedai_traffic.py new file mode 100644 index 00000000000..2214f87adc5 --- /dev/null +++ b/PythonAPI/examples/invertedai_traffic.py @@ -0,0 +1,666 @@ +#!/usr/bin/env python + +# Copyright (c) 2024 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 . + +""" +Example script to generate realistic traffic with the InvertedAI API +""" + +import os +import time +import carla +import argparse +import logging +import math +import random +import invertedai as iai +from invertedai.common import AgentProperties, AgentState, TrafficLightState + +SpawnActor = carla.command.SpawnActor + +#--------- +# CARLA Utils +#--------- + +# Argument parser +def argument_parser(): + + argparser = argparse.ArgumentParser( + description=__doc__) + argparser.add_argument( + '--host', + metavar='H', + default='127.0.0.1', + help='IP of the host server (default: 127.0.0.1)') + argparser.add_argument( + '-p', '--port', + metavar='P', + default=2000, + type=int, + help='TCP port to listen to (default: 2000)') + argparser.add_argument( + '-n', '--number-of-vehicles', + metavar='N', + default=30, + type=int, + help='Number of vehicles spawned by InvertedAI (default: 30)') + argparser.add_argument( + '-w', '--number-of-walkers', + metavar='W', + default=10, + type=int, + help='Number of walkers (default: 10)') + argparser.add_argument( + '--safe', + type=bool, + default=True, + help='Avoid spawning vehicles prone to accidents (default True)') + argparser.add_argument( + '--filterv', + metavar='PATTERN', + default='vehicle.*', + help='Filter vehicle model (default: "vehicle.*")') + argparser.add_argument( + '--generationv', + metavar='G', + default='All', + help='restrict to certain vehicle generation (default: "All")') + argparser.add_argument( + '--filterw', + metavar='PATTERN', + default='walker.pedestrian.*', + help='Filter pedestrian type (default: "walker.pedestrian.*")') + argparser.add_argument( + '--generationw', + metavar='G', + default='All', + help='restrict to certain pedestrian generation (default: "All")') + argparser.add_argument( + '-s', '--seed', + metavar='S', + type=int, + help='Set random seed') + argparser.add_argument( + '--hero', + action='store_true', + default=False, + help='Set one of the vehicles as hero') + argparser.add_argument( + '--iai-key', + type=str, + help="InvertedAI API key.") + argparser.add_argument( + '--record', + action='store_true', + help="Record the simulation using the CARLA recorder", + default=False) + argparser.add_argument( + '--sim-length', + type=int, + default=120, + help="Length of the simulation in seconds (default: 120)") + argparser.add_argument( + '--location', + type=str, + help=f"IAI formatted map on which to create simulate (default: carla:Town10HD, only tested there)", + default='carla:Town10HD') + argparser.add_argument( + '--capacity', + type=int, + help=f"The capacity parameter of a quadtree leaf before splitting (default: 100)", + default=100) + argparser.add_argument( + '--width', + type=int, + help=f"Full width of the area to initialize (default: 250)", + default=250) + argparser.add_argument( + '--height', + type=int, + help=f"Full height of the area to initialize (default: 250)", + default=250) + argparser.add_argument( + '--map-center', + type=int, + nargs='+', + help=f"Center of the area to initialize (default: [0,30])", + default=tuple([0,30])) + argparser.add_argument( + '--iai-async', + type=bool, + help=f"Whether to call drive asynchronously (default: True)", + default=True) + argparser.add_argument( + '--api-model', + type=str, + help=f"IAI API model version (default: bI5p)", + default="bI5p") + argparser.add_argument( + '--iai-log', + action="store_true", + help=f"Export a log file for the InvertedAI cosimulation, which can be replayed afterwards") + + args = argparser.parse_args() + + return args + +# Setup CARLA client and world +def setup_carla_environment(host, port): + + step_length = 0.1 # 0.1 is the only step length that is supported by invertedai so far + + client = carla.Client(host, port) + client.set_timeout(200.0) + + # Configure the simulation environment + world = client.get_world() + world_settings = carla.WorldSettings( + synchronous_mode=True, + fixed_delta_seconds=step_length, + ) + world.apply_settings(world_settings) + + return client, world + +# Set spectator view on a hero vehicle +def set_spectator(world, hero_v): + + spectator_offset_x = -6. + spectator_offset_z = 6. + spectator_offset_pitch = 20 + + hero_t = hero_v.get_transform() + + yaw = hero_t.rotation.yaw + spectator_l = hero_t.location + carla.Location( + spectator_offset_x * math.cos(math.radians(yaw)), + spectator_offset_x * math.sin(math.radians(yaw)), + spectator_offset_z, + ) + spectator_t = carla.Transform(spectator_l, hero_t.rotation) + spectator_t.rotation.pitch -= spectator_offset_pitch + world.get_spectator().set_transform(spectator_t) + +#--------- +# Initialize actors +#--------- + +# Initialize IAI agents from CARLA actors +def initialize_iai_agent(actor, agent_type): + + transf = actor.get_transform() + vel = actor.get_velocity() + speed = math.sqrt(vel.x**2. + vel.y**2. +vel.z**2.) + + agent_state = AgentState.fromlist([ + transf.location.x, + transf.location.y, + transf.rotation.yaw, + speed + ]) + + bb = actor.bounding_box + length, width = bb.extent.x*2, bb.extent.y*2 + + agent_properties = AgentProperties(length=length, width=width, agent_type=agent_type) + if agent_type=="car": + agent_properties.rear_axis_offset = length*0.38 # Empirical value fitted from InvertedAI initialization + + return agent_state, agent_properties + +# Initialize IAI pedestrians from CARLA actors +def initialize_pedestrians(pedestrians): + + iai_pedestrians_states, iai_pedestrians_properties = [], [] + for actor in pedestrians: + iai_ped_state, iai_ped_properties = initialize_iai_agent(actor,agent_type="pedestrian") + iai_pedestrians_states.append(iai_ped_state) + iai_pedestrians_properties.append(iai_ped_properties) + + return iai_pedestrians_states, iai_pedestrians_properties + +# Spawn pedestrians in the simulation, which are driven by CARLA controllers (not by invertedai) +def spawn_pedestrians(client, world, num_pedestrians, bps): + + batch = [] + + # Get spawn points for pedestrians + spawn_points = [] + for i in range(num_pedestrians): + + loc = world.get_random_location_from_navigation() + if (loc is not None): + spawn_point = carla.Transform(location=loc) + #Apply Offset in vertical to avoid collision spawning + spawn_point.location.z += 1 + spawn_points.append(spawn_point) + + pedestrians = [] + walkers_list = [] + + # Spawn pedestrians + for i in range(len(spawn_points)): + walker_bp = random.choice(bps) + if walker_bp.has_attribute('is_invincible'): + walker_bp.set_attribute('is_invincible', 'false') + spawn_point = spawn_points[i] + batch.append(SpawnActor(walker_bp, spawn_point)) + + results = client.apply_batch_sync(batch, True) + pedestrians = world.get_actors().filter('walker.*') + for i in range(len(results)): + if results[i].error: + logging.error(results[i].error) + else: + walkers_list.append({"id": results[i].actor_id}) + + # Spawn CARLA IA controllers for pedestrians + batch = [] + walker_controller_bp = world.get_blueprint_library().find('controller.ai.walker') + for i in range(len(walkers_list)): + batch.append(SpawnActor(walker_controller_bp, carla.Transform(), walkers_list[i]["id"])) + results = client.apply_batch_sync(batch, True) + + world.tick() + + for controller in world.get_actors().filter('controller.ai.walker'): + controller.start() + dest = world.get_random_location_from_navigation() + controller.go_to_location(dest) + controller.set_max_speed(0.5 + random.random()) + + return pedestrians + +# Get blueprints according to the given filters +def get_actor_blueprints(world, filter, generation): + bps = world.get_blueprint_library().filter(filter) + + if generation.lower() == "all": + return bps + + # If the filter returns only one bp, we assume that this one needed + # and therefore, we ignore the generation + if len(bps) == 1: + return bps + + try: + int_generation = int(generation) + # Check if generation is in available generations + if int_generation in [1, 2, 3, 4]: + bps = [x for x in bps if int(x.get_attribute('generation')) == int_generation] + return bps + else: + print(" Warning! Actor Generation is not valid. No actor will be spawned.") + return [] + except: + print(" Warning! Actor Generation is not valid. No actor will be spawned.") + return [] + +#--------- +# InvertedAI - CARLA synchronization routines +#--------- + +# Get CARLA transform from IAI transform +def transform_iai_to_carla(agent_state): + agent_transform = carla.Transform( + carla.Location( + agent_state.center.x, + agent_state.center.y, + 0. + ), + carla.Rotation( + yaw=math.degrees(agent_state.orientation) + ) + ) + + return agent_transform + +# Update transforms of CARLA agents driven by IAI and tick the world +def update_transforms(iai2carla,response): + """ + Tick the carla simulation forward one time step + Assume carla_actors is a list of carla actors controlled by IAI + """ + for agent_id in iai2carla.keys(): + agentdict = iai2carla[agent_id] + if agentdict["is_iai"]: + agent = response.agent_states[agent_id] + agent_transform = transform_iai_to_carla(agent) + try: + actor = agentdict["actor"] + actor.set_transform(agent_transform) + except: + pass + +# Assign existing IAI agents to CARLA vehicle blueprints and add these agents to the CARLA simulation +def assign_carla_blueprints_to_iai_agents(world,vehicle_blueprints,agent_properties,agent_states,recurrent_states,is_iai,noniai_actors): + + agent_properties_new = [] + agent_states_new = [] + recurrent_states_new = [] + new_agent_id = 0 + iai2carla = {} + + for agent_id, state in enumerate(agent_states): + + if not is_iai[agent_id]: + agent_properties_new.append(agent_properties[agent_id]) + agent_states_new.append(agent_states[agent_id]) + recurrent_states_new.append(recurrent_states[agent_id]) + actor = noniai_actors[agent_id] + new_agent_id += 1 + iai2carla[len(iai2carla)] = {"actor":actor, "is_iai":False, "type":agent_properties[agent_id].agent_type} + + else: + + blueprint = random.choice(vehicle_blueprints) + if blueprint.has_attribute('color'): + color = random.choice(blueprint.get_attribute('color').recommended_values) + blueprint.set_attribute('color', color) + agent_transform = transform_iai_to_carla(state) + + actor = world.try_spawn_actor(blueprint,agent_transform) + + if actor is not None: + bb = actor.bounding_box.extent + + agent_attr = agent_properties[agent_id] + + agent_attr.length = 2*bb.x + agent_attr.width = 2*bb.y + agent_attr.rear_axis_offset = 2*bb.x/3 + + new_agent_id += 1 + + agent_properties_new.append(agent_attr) + agent_states_new.append(agent_states[agent_id]) + recurrent_states_new.append(recurrent_states[agent_id]) + + actor.set_simulate_physics(False) + + iai2carla[len(iai2carla)] = {"actor":actor, "is_iai":True, "type":agent_properties[agent_id].agent_type} + + if len(agent_properties_new) == 0: + raise Exception("No vehicles could be placed in Carla environment.") + + return agent_properties_new, agent_states_new, recurrent_states_new, iai2carla + +# Initialize InvertedAI co-simulation +def initialize_simulation(args, world, agent_states=None, agent_properties=None): + + iai_seed = args.seed if args.seed is not None else random.randint(1,10000) + traffic_lights_states, carla2iai_tl = initialize_tl_states(world) + + ################################################################################################# + # Initialize IAI Agents + map_center = args.map_center + print(f"Call location info.") + location_info_response = iai.location_info( + location = args.location, + rendering_center = map_center + ) + print(f"Begin initialization.") + # Acquire a grid of 100x100m regions in which to initialize vehicles to be controlled by IAI. + regions = iai.get_regions_default( + location = args.location, + total_num_agents = args.number_of_vehicles, + area_shape = (int(args.width/2),int(args.height/2)), + map_center = map_center, + ) + # Place vehicles within the specified regions which will consider the relative states of nearby vehicles in neighbouring regions. + response = iai.large_initialize( + location = args.location, + regions = regions, + traffic_light_state_history = [traffic_lights_states], + agent_states = agent_states, + agent_properties = agent_properties, + random_seed = iai_seed + ) + + return response, carla2iai_tl, location_info_response + +#--------- +# Synchronize InvertedAI and CARLA traffic lights +#--------- + +# Mapping between CARLA and IAI traffic lights IDs +def get_traffic_lights_mapping(world): + tls = world.get_actors().filter('traffic.traffic_light*') + tl_ids = sorted([tl.id for tl in list(tls)]) + carla2iai_tl = {} + # ID for IAI traffic lights, only valid for Town10 for now (in both UE4 and UE5 versions of the map) + iai_tl_id = 4364 + for carla_tl_id in tl_ids: + carla2iai_tl[str(carla_tl_id)] = [str(iai_tl_id), str(iai_tl_id+1000)] + iai_tl_id+=1 + + return carla2iai_tl + +# Returns IAI traffic light state based on CARLA traffic light state +def get_traffic_light_state_from_carla(carla_tl_state): + + if carla_tl_state == carla.TrafficLightState.Red: + return TrafficLightState.red + + elif carla_tl_state == carla.TrafficLightState.Yellow: + return TrafficLightState.yellow + + elif carla_tl_state == carla.TrafficLightState.Green: + return TrafficLightState.green + + else: # Unknown state, turn off traffic light + return TrafficLightState.Off + +# Assign IAI traffic lights based on the CARLA ones +def assign_iai_traffic_lights_from_carla(world, iai_tl, carla2iai_tl): + + traffic_lights = world.get_actors().filter('traffic.traffic_light*') + + carla_tl_dict = {} + for tl in traffic_lights: + carla_tl_dict[str(tl.id)]=tl.state + + for carla_tl_id, carla_state in carla_tl_dict.items(): + iai_tl_id_pair = carla2iai_tl[carla_tl_id] + for iai_tl_id in iai_tl_id_pair: + iai_tl[iai_tl_id] = get_traffic_light_state_from_carla(carla_state) + + return iai_tl + +# Initialize traffic lights states +def initialize_tl_states(world): + carla2iai_tl = get_traffic_lights_mapping(world) + iai_tl_states = {} + for tlpair in carla2iai_tl.values(): + for tl in tlpair: + iai_tl_states[tl] = TrafficLightState.red # Initialize to given value + + iai_tl_states = assign_iai_traffic_lights_from_carla(world, iai_tl_states, carla2iai_tl) + return iai_tl_states, carla2iai_tl + +#--------- +# Main +#--------- +def main(): + + args = argument_parser() + + # Setup CARLA client and world + client, world = setup_carla_environment(args.host, args.port) + + # Specify the IAI API key + try: + iai.add_apikey(args.iai_key) + except: + print("\n\tYou need to indicate the InvertedAI API key with the argument --iai-key. To obtain one, please go to https://www.inverted.ai \n") + + num_pedestrians = args.number_of_walkers + + FPS = int(1./world.get_settings().fixed_delta_seconds) + + if args.record: + logfolder = os.getcwd()+"/logs/" + if not os.path.exists(logfolder): + os.system("mkdir "+logfolder) + logfile = logfolder+"carla_record.log" + client.start_recorder(logfile) + print("Recording on file: %s" % logfile) + + seed = args.seed + + if seed: + random.seed(seed) + + vehicle_blueprints = get_actor_blueprints(world, args.filterv, args.generationv) + if args.safe: + vehicle_blueprints = [x for x in vehicle_blueprints if x.get_attribute('base_type') == 'car'] + + agent_states, agent_properties = [], [] + is_iai = [] + noniai_actors = [] + + # Add pedestrians (not driven by IAI) + if num_pedestrians>0: + if seed: + world.set_pedestrians_seed(seed) + blueprintsWalkers = get_actor_blueprints(world, args.filterw, args.generationw) + if not blueprintsWalkers: + raise ValueError("Couldn't find any walkers with the specified filters") + pedestrians = spawn_pedestrians(client, world, num_pedestrians, blueprintsWalkers) + iai_pedestrians_states, iai_pedestrians_properties = initialize_pedestrians(pedestrians) + agent_states.extend(iai_pedestrians_states) + agent_properties.extend(iai_pedestrians_properties) + is_iai.extend( [False]*len(iai_pedestrians_states) ) + noniai_actors.extend(pedestrians) + + else: + pedestrians = [] + + num_noniai = len(agent_properties) + + # Initialize InvertedAI co-simulation + response, carla2iai_tl, location_info_response = initialize_simulation(args, world, agent_states=agent_states, agent_properties=agent_properties) + agent_properties = response.agent_properties + is_iai.extend( [True]*(len(agent_properties)-num_noniai) ) + + # Write InvertedAI log file, which can be opened afterwards to visualize a gif and further analysis + # See an example of usage here: https://github.com/inverted-ai/invertedai/blob/master/examples/scenario_log_example.py + if args.iai_log: + + log_writer = iai.LogWriter() + log_writer.initialize( + location=args.location, + location_info_response=location_info_response, + init_response=response + ) + iailog_path = os.path.join(os.getcwd(),f"iai_log.json") + + # Map IAI agents to CARLA actors and update response properties and states + agent_properties, agent_states_new, recurrent_states_new, iai2carla = assign_carla_blueprints_to_iai_agents(world,vehicle_blueprints,agent_properties,response.agent_states,response.recurrent_states,is_iai,noniai_actors) + traffic_lights_states = assign_iai_traffic_lights_from_carla(world,response.traffic_lights_states, carla2iai_tl) + response.agent_states = agent_states_new + response.recurrent_states = recurrent_states_new + response.traffic_lights_states = traffic_lights_states + + # Perform first CARLA simulation tick + world.tick() + + try: + + vehicles = world.get_actors().filter('vehicle.*') + print("Total number of agents:",len(agent_properties),"Vehicles",len(vehicles), "Pedestrians:",len(pedestrians)) + + # Get hero vehicle + hero_v = None + if args.hero: + hero_v = vehicles[0] + + for frame in range(args.sim_length * FPS): + + response.traffic_lights_states = assign_iai_traffic_lights_from_carla(world, response.traffic_lights_states, carla2iai_tl) + + # IAI update step + response = iai.large_drive( + location = args.location, + agent_states = response.agent_states, + agent_properties = agent_properties, + recurrent_states = response.recurrent_states, + traffic_lights_states = response.traffic_lights_states, + light_recurrent_states = None, + single_call_agent_limit = args.capacity, + async_api_calls = args.iai_async, + api_model_version = args.api_model, + random_seed = seed + ) + + if args.iai_log: + log_writer.drive(drive_response=response) + + # Update CARLA actors with new transforms from IAI agents + update_transforms(iai2carla,response) + + # Tick CARLA simulation + world.tick() + + # Update agents not driven by IAI in IAI cosimulation, like pedestrians + for agent_id in iai2carla.keys(): + agentdict = iai2carla[agent_id] + + if not agentdict["is_iai"]: + actor = agentdict["actor"] + state, properties = initialize_iai_agent(actor, agentdict["type"]) + response.agent_states[agent_id] = state + agent_properties[agent_id] = properties + + # Include possible new actors (vehicles) from other clients (using automatic_control.py or manual_control.py for instance) + actors_all = world.get_actors().filter('vehicle.*') + actsids = [act["actor"].id for act in iai2carla.values()] + for actor in actors_all: + if not (actor.id in actsids): + state, properties = initialize_iai_agent(actor, "car") + response.agent_states.append( state ) + agent_properties.append( properties ) + response.recurrent_states.append( response.recurrent_states[-1] ) # temporal fix + iai2carla[len(iai2carla)] = {"actor":actor, "is_iai":False, "type":properties.agent_type} + + # Update spectator view if there is hero vehicle + if hero_v is not None: + set_spectator(world, hero_v) + + + + finally: + + vehicles_list = world.get_actors().filter('vehicle.*') + print('\ndestroying %d vehicles' % len(vehicles_list)) + client.apply_batch([carla.command.DestroyActor(x) for x in vehicles_list]) + + walkercontrollers_list = world.get_actors().filter('controller.*') + for control in walkercontrollers_list: + control.stop() + control.destroy() + + walkers_list = world.get_actors().filter('walker.*') + print('\ndestroying %d walkers' % len(walkers_list)) + client.apply_batch([carla.command.DestroyActor(x) for x in walkers_list]) + + time.sleep(0.5) + + if args.record: + client.stop_recorder() + + if args.iai_log: + log_writer.export_to_file(log_path=iailog_path) + +if __name__ == '__main__': + + try: + main() + except KeyboardInterrupt: + pass + finally: + print('\ndone.') diff --git a/PythonAPI/examples/open3d_lidar.py b/PythonAPI/examples/open3d_lidar.py index f3fbe4418d2..e207207e5ee 100644 --- a/PythonAPI/examples/open3d_lidar.py +++ b/PythonAPI/examples/open3d_lidar.py @@ -6,7 +6,7 @@ # This work is licensed under the terms of the MIT license. # For a copy, see . -"""Open3D Lidar visuialization example for CARLA""" +"""Open3D Lidar visualization example for CARLA""" import glob import os diff --git a/PythonAPI/examples/requirements.txt b/PythonAPI/examples/requirements.txt index acb394d55fc..c10dae88ceb 100644 --- a/PythonAPI/examples/requirements.txt +++ b/PythonAPI/examples/requirements.txt @@ -5,3 +5,4 @@ pygame matplotlib open3d Pillow +invertedai@git+https://github.com/inverted-ai/invertedai.git@develop diff --git a/PythonAPI/examples/rss/__init__.py b/PythonAPI/examples/rss/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/PythonAPI/examples/rss/manual_control_rss.py b/PythonAPI/examples/rss/manual_control_rss.py deleted file mode 100755 index ff0b7e1c5b4..00000000000 --- a/PythonAPI/examples/rss/manual_control_rss.py +++ /dev/null @@ -1,921 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2019 Computer Vision Center (CVC) at the Universitat Autonoma de -# Barcelona (UAB). -# Copyright (c) 2019-2020 Intel Corporation -# -# This work is licensed under the terms of the MIT license. -# For a copy, see . - -# Allows controlling a vehicle with a keyboard. For a simpler and more -# documented example, please take a look at tutorial.py. - -""" -Welcome to CARLA manual control. - -Use ARROWS or WASD keys for control. - - W : throttle - S : brake - AD : steer - Q : toggle reverse - Space : hand-brake - P : toggle autopilot - - TAB : change view - Backspace : change vehicle - - R : toggle recording images to disk - - F2 : toggle RSS visualization mode - F3 : increase log level - F4 : decrease log level - F5 : increase map log level - F6 : decrease map log level - B : toggle RSS Road Boundaries Mode - G : RSS check drop current route - T : toggle RSS - N : pause simulation - - F1 : toggle HUD - H/? : toggle help - ESC : quit -""" - -from __future__ import print_function - - -# ============================================================================== -# -- find carla module --------------------------------------------------------- -# ============================================================================== - - -import glob -import os -import sys -import signal - -try: - sys.path.append(glob.glob(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + '/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 - - -# ============================================================================== -# -- imports ------------------------------------------------------------------- -# ============================================================================== - - -import carla - -from carla import ColorConverter as cc - -import argparse -import logging -import math -import random -import weakref -from rss_sensor import RssSensor # pylint: disable=relative-import -from rss_visualization import RssUnstructuredSceneVisualizer, RssBoundingBoxVisualizer, RssStateVisualizer # pylint: disable=relative-import - -try: - import pygame - from pygame.locals import KMOD_CTRL - from pygame.locals import KMOD_SHIFT - from pygame.locals import K_BACKSPACE - from pygame.locals import K_TAB - from pygame.locals import K_DOWN - from pygame.locals import K_ESCAPE - from pygame.locals import K_F1 - from pygame.locals import K_F2 - from pygame.locals import K_F3 - from pygame.locals import K_F4 - from pygame.locals import K_F5 - from pygame.locals import K_F6 - from pygame.locals import K_LEFT - from pygame.locals import K_RIGHT - from pygame.locals import K_SLASH - from pygame.locals import K_SPACE - from pygame.locals import K_UP - from pygame.locals import K_a - from pygame.locals import K_b - from pygame.locals import K_d - from pygame.locals import K_g - from pygame.locals import K_h - from pygame.locals import K_n - from pygame.locals import K_p - from pygame.locals import K_q - from pygame.locals import K_r - from pygame.locals import K_s - from pygame.locals import K_w - from pygame.locals import K_l - from pygame.locals import K_i - from pygame.locals import K_z - from pygame.locals import K_x - from pygame.locals import MOUSEBUTTONDOWN - from pygame.locals import MOUSEBUTTONUP -except ImportError: - raise RuntimeError('cannot import pygame, make sure pygame package is installed') - -try: - import numpy as np -except ImportError: - raise RuntimeError('cannot import numpy, make sure numpy package is installed') - - -# ============================================================================== -# -- World --------------------------------------------------------------------- -# ============================================================================== - - -class World(object): - - def __init__(self, carla_world, args): - self.world = carla_world - self.sync = args.sync - self.actor_role_name = args.rolename - self.dim = (args.width, args.height) - try: - self.map = self.world.get_map() - except RuntimeError as error: - print('RuntimeError: {}'.format(error)) - print(' The server could not send the OpenDRIVE (.xodr) file:') - print(' Make sure it exists, has the same name of your town, and is correct.') - sys.exit(1) - self.external_actor = args.externalActor - - self.hud = HUD(args.width, args.height, carla_world) - self.recording_frame_num = 0 - self.recording = False - self.recording_dir_num = 0 - self.player = None - self.actors = [] - self.rss_sensor = None - self.rss_unstructured_scene_visualizer = None - self.rss_bounding_box_visualizer = None - self._actor_filter = args.filter - if not self._actor_filter.startswith("vehicle."): - print('Error: RSS only supports vehicles as ego.') - sys.exit(1) - - self.restart() - self.world_tick_id = self.world.on_tick(self.hud.on_world_tick) - - def toggle_pause(self): - settings = self.world.get_settings() - self.pause_simulation(not settings.synchronous_mode) - - def pause_simulation(self, pause): - settings = self.world.get_settings() - if pause and not settings.synchronous_mode: - settings.synchronous_mode = True - settings.fixed_delta_seconds = 0.05 - self.world.apply_settings(settings) - elif not pause and settings.synchronous_mode: - settings.synchronous_mode = False - settings.fixed_delta_seconds = None - self.world.apply_settings(settings) - - def restart(self): - - if self.external_actor: - # Check whether there is already an actor with defined role name - for actor in self.world.get_actors(): - if actor.attributes.get('role_name') == self.actor_role_name: - self.player = actor - break - else: - # Get a random blueprint. - blueprint = random.choice(self.world.get_blueprint_library().filter(self._actor_filter)) - blueprint.set_attribute('role_name', self.actor_role_name) - if blueprint.has_attribute('color'): - color = random.choice(blueprint.get_attribute('color').recommended_values) - blueprint.set_attribute('color', color) - if blueprint.has_attribute('driver_id'): - driver_id = random.choice(blueprint.get_attribute('driver_id').recommended_values) - blueprint.set_attribute('driver_id', driver_id) - if blueprint.has_attribute('is_invincible'): - blueprint.set_attribute('is_invincible', 'true') - # Spawn the player. - if self.player is not None: - spawn_point = self.player.get_transform() - spawn_point.location.z += 2.0 - spawn_point.rotation.roll = 0.0 - spawn_point.rotation.pitch = 0.0 - self.destroy() - self.player = self.world.try_spawn_actor(blueprint, spawn_point) - while self.player is None: - if not self.map.get_spawn_points(): - print('There are no spawn points available in your map/town.') - print('Please add some Vehicle Spawn Point to your UE4 scene.') - sys.exit(1) - spawn_points = self.map.get_spawn_points() - spawn_point = random.choice(spawn_points) if spawn_points else carla.Transform() - self.player = self.world.try_spawn_actor(blueprint, spawn_point) - - if self.external_actor: - ego_sensors = [] - for actor in self.world.get_actors(): - if actor.parent == self.player: - ego_sensors.append(actor) - - for ego_sensor in ego_sensors: - if ego_sensor is not None: - ego_sensor.destroy() - - # Set up the sensors. - self.camera = Camera(self.player, self.dim) - self.rss_unstructured_scene_visualizer = RssUnstructuredSceneVisualizer(self.player, self.world, self.dim) - self.rss_bounding_box_visualizer = RssBoundingBoxVisualizer(self.dim, self.world, self.camera.sensor) - self.rss_sensor = RssSensor(self.player, self.world, - self.rss_unstructured_scene_visualizer, self.rss_bounding_box_visualizer, self.hud.rss_state_visualizer) - - if self.sync: - self.world.tick() - else: - self.world.wait_for_tick() - - def tick(self, clock): - self.hud.tick(self.player, clock) - - def toggle_recording(self): - if not self.recording: - dir_name = "_out%04d" % self.recording_dir_num - while os.path.exists(dir_name): - self.recording_dir_num += 1 - dir_name = "_out%04d" % self.recording_dir_num - self.recording_frame_num = 0 - os.mkdir(dir_name) - else: - self.hud.notification('Recording finished (folder: _out%04d)' % self.recording_dir_num) - - self.recording = not self.recording - - def render(self, display): - self.camera.render(display) - self.rss_bounding_box_visualizer.render(display, self.camera.current_frame) - self.rss_unstructured_scene_visualizer.render(display) - self.hud.render(display) - - if self.recording: - pygame.image.save(display, "_out%04d/%08d.bmp" % (self.recording_dir_num, self.recording_frame_num)) - self.recording_frame_num += 1 - - def destroy(self): - # stop from ticking - if self.world_tick_id: - self.world.remove_on_tick(self.world_tick_id) - - if self.camera: - self.camera.destroy() - if self.rss_sensor: - self.rss_sensor.destroy() - if self.rss_unstructured_scene_visualizer: - self.rss_unstructured_scene_visualizer.destroy() - if self.player: - self.player.destroy() - - -# ============================================================================== -# -- Camera -------------------------------------------------------------------- -# ============================================================================== - -class Camera(object): - - def __init__(self, parent_actor, display_dimensions): - self.surface = None - self._parent = parent_actor - self.current_frame = None - bp_library = self._parent.get_world().get_blueprint_library() - bp = bp_library.find('sensor.camera.rgb') - bp.set_attribute('image_size_x', str(display_dimensions[0])) - bp.set_attribute('image_size_y', str(display_dimensions[1])) - self.sensor = self._parent.get_world().spawn_actor(bp, carla.Transform(carla.Location( - x=-5.5, z=2.5), carla.Rotation(pitch=8.0)), attach_to=self._parent, attachment_type=carla.AttachmentType.SpringArmGhost) - - # We need to pass the lambda a weak reference to self to avoid - # circular reference. - weak_self = weakref.ref(self) - self.sensor.listen(lambda image: Camera._parse_image(weak_self, image)) - - def destroy(self): - self.sensor.stop() - self.sensor.destroy() - self.sensor = None - - def render(self, display): - if self.surface is not None: - display.blit(self.surface, (0, 0)) - - @staticmethod - def _parse_image(weak_self, image): - self = weak_self() - if not self: - return - self.current_frame = image.frame - image.convert(cc.Raw) - array = np.frombuffer(image.raw_data, dtype=np.dtype("uint8")) - array = np.reshape(array, (image.height, image.width, 4)) - array = array[:, :, :3] - array = array[:, :, ::-1] - self.surface = pygame.surfarray.make_surface(array.swapaxes(0, 1)) - -# ============================================================================== -# -- VehicleControl ----------------------------------------------------------- -# ============================================================================== - - -class VehicleControl(object): - - MOUSE_STEERING_RANGE = 200 - signal_received = False - - """Class that handles keyboard input.""" - - def __init__(self, world, start_in_autopilot): - self._autopilot_enabled = start_in_autopilot - self._world = world - self._control = carla.VehicleControl() - self._lights = carla.VehicleLightState.NONE - world.player.set_autopilot(self._autopilot_enabled) - self._restrictor = carla.RssRestrictor() - self._vehicle_physics = world.player.get_physics_control() - world.player.set_light_state(self._lights) - self._steer_cache = 0.0 - self._mouse_steering_center = None - - self._surface = pygame.Surface((self.MOUSE_STEERING_RANGE * 2, self.MOUSE_STEERING_RANGE * 2)) - self._surface.set_colorkey(pygame.Color('black')) - self._surface.set_alpha(60) - - line_width = 2 - pygame.draw.polygon(self._surface, - (0, 0, 255), - [ - (0, 0), - (0, self.MOUSE_STEERING_RANGE * 2 - line_width), - (self.MOUSE_STEERING_RANGE * 2 - line_width, - self.MOUSE_STEERING_RANGE * 2 - line_width), - (self.MOUSE_STEERING_RANGE * 2 - line_width, 0), - (0, 0) - ], line_width) - pygame.draw.polygon(self._surface, - (0, 0, 255), - [ - (0, self.MOUSE_STEERING_RANGE), - (self.MOUSE_STEERING_RANGE * 2, self.MOUSE_STEERING_RANGE) - ], line_width) - pygame.draw.polygon(self._surface, - (0, 0, 255), - [ - (self.MOUSE_STEERING_RANGE, 0), - (self.MOUSE_STEERING_RANGE, self.MOUSE_STEERING_RANGE * 2) - ], line_width) - - world.hud.notification("Press 'H' or '?' for help.", seconds=4.0) - - def render(self, display): - if self._mouse_steering_center: - display.blit( - self._surface, (self._mouse_steering_center[0] - self.MOUSE_STEERING_RANGE, self._mouse_steering_center[1] - self.MOUSE_STEERING_RANGE)) - - @staticmethod - def signal_handler(signum, _): - print('\nReceived signal {}. Trigger stopping...'.format(signum)) - VehicleControl.signal_received = True - - def parse_events(self, world, clock, sync_mode): - if VehicleControl.signal_received: - print('\nAccepted signal. Stopping loop...') - return True - if isinstance(self._control, carla.VehicleControl): - current_lights = self._lights - for event in pygame.event.get(): - if event.type == pygame.QUIT: - return True - elif event.type == pygame.KEYUP: - if self._is_quit_shortcut(event.key): - return True - elif event.key == K_BACKSPACE: - if self._autopilot_enabled: - world.player.set_autopilot(False) - world.restart() - world.player.set_autopilot(True) - else: - world.restart() - elif event.key == K_F1: - world.hud.toggle_info() - elif event.key == K_h or (event.key == K_SLASH and pygame.key.get_mods() & KMOD_SHIFT): - world.hud.help.toggle() - elif event.key == K_TAB: - world.rss_unstructured_scene_visualizer.toggle_camera() - elif event.key == K_n: - world.toggle_pause() - elif event.key == K_r: - world.toggle_recording() - elif event.key == K_F2: - if self._world and self._world.rss_sensor: - self._world.rss_sensor.toggle_debug_visualization_mode() - elif event.key == K_F3: - if self._world and self._world.rss_sensor: - self._world.rss_sensor.decrease_log_level() - self._restrictor.set_log_level(self._world.rss_sensor.log_level) - elif event.key == K_F4: - if self._world and self._world.rss_sensor: - self._world.rss_sensor.increase_log_level() - self._restrictor.set_log_level(self._world.rss_sensor.log_level) - elif event.key == K_F5: - if self._world and self._world.rss_sensor: - self._world.rss_sensor.decrease_map_log_level() - elif event.key == K_F6: - if self._world and self._world.rss_sensor: - self._world.rss_sensor.increase_map_log_level() - elif event.key == K_b: - if self._world and self._world.rss_sensor: - if self._world.rss_sensor.sensor.road_boundaries_mode == carla.RssRoadBoundariesMode.Off: - self._world.rss_sensor.sensor.road_boundaries_mode = carla.RssRoadBoundariesMode.On - print("carla.RssRoadBoundariesMode.On") - else: - self._world.rss_sensor.sensor.road_boundaries_mode = carla.RssRoadBoundariesMode.Off - print("carla.RssRoadBoundariesMode.Off") - elif event.key == K_g: - if self._world and self._world.rss_sensor: - self._world.rss_sensor.drop_route() - if isinstance(self._control, carla.VehicleControl): - if event.key == K_q: - self._control.gear = 1 if self._control.reverse else -1 - elif event.key == K_p and not pygame.key.get_mods() & KMOD_CTRL: - self._autopilot_enabled = not self._autopilot_enabled - world.player.set_autopilot(self._autopilot_enabled) - world.hud.notification( - 'Autopilot %s' % ('On' if self._autopilot_enabled else 'Off')) - elif event.key == K_l and pygame.key.get_mods() & KMOD_CTRL: - current_lights ^= carla.VehicleLightState.Special1 - elif event.key == K_l and pygame.key.get_mods() & KMOD_SHIFT: - current_lights ^= carla.VehicleLightState.HighBeam - elif event.key == K_l: - # Use 'L' key to switch between lights: - # closed -> position -> low beam -> fog - if not self._lights & carla.VehicleLightState.Position: - world.hud.notification("Position lights") - current_lights |= carla.VehicleLightState.Position - else: - world.hud.notification("Low beam lights") - current_lights |= carla.VehicleLightState.LowBeam - if self._lights & carla.VehicleLightState.LowBeam: - world.hud.notification("Fog lights") - current_lights |= carla.VehicleLightState.Fog - if self._lights & carla.VehicleLightState.Fog: - world.hud.notification("Lights off") - current_lights ^= carla.VehicleLightState.Position - current_lights ^= carla.VehicleLightState.LowBeam - current_lights ^= carla.VehicleLightState.Fog - elif event.key == K_i: - current_lights ^= carla.VehicleLightState.Interior - elif event.key == K_z: - current_lights ^= carla.VehicleLightState.LeftBlinker - elif event.key == K_x: - current_lights ^= carla.VehicleLightState.RightBlinker - elif event.type == MOUSEBUTTONDOWN: - # store current mouse position for mouse-steering - if event.button == 1: - self._mouse_steering_center = event.pos - elif event.type == MOUSEBUTTONUP: - if event.button == 1: - self._mouse_steering_center = None - if not self._autopilot_enabled: - prev_steer_cache = self._steer_cache - self._parse_vehicle_keys(pygame.key.get_pressed(), clock.get_time()) - if pygame.mouse.get_pressed()[0]: - self._parse_mouse(pygame.mouse.get_pos()) - self._control.reverse = self._control.gear < 0 - - vehicle_control = self._control - world.hud.original_vehicle_control = vehicle_control - world.hud.restricted_vehicle_control = vehicle_control - - # limit speed to 30kmh - v = self._world.player.get_velocity() - if (3.6 * math.sqrt(v.x**2 + v.y**2 + v.z**2)) > 30.0: - self._control.throttle = 0 - - # if self._world.rss_sensor and self._world.rss_sensor.ego_dynamics_on_route and not self._world.rss_sensor.ego_dynamics_on_route.ego_center_within_route: - # print ("Not on route!" + str(self._world.rss_sensor.ego_dynamics_on_route)) - if self._restrictor: - rss_proper_response = self._world.rss_sensor.proper_response if self._world.rss_sensor and self._world.rss_sensor.response_valid else None - if rss_proper_response: - if not (pygame.key.get_mods() & KMOD_CTRL): - vehicle_control = self._restrictor.restrict_vehicle_control( - vehicle_control, rss_proper_response, self._world.rss_sensor.ego_dynamics_on_route, self._vehicle_physics) - world.hud.restricted_vehicle_control = vehicle_control - world.hud.allowed_steering_ranges = self._world.rss_sensor.get_steering_ranges() - if world.hud.original_vehicle_control.steer != world.hud.restricted_vehicle_control.steer: - self._steer_cache = prev_steer_cache - - # Set automatic control-related vehicle lights - if vehicle_control.brake: - current_lights |= carla.VehicleLightState.Brake - else: # Remove the Brake flag - current_lights &= carla.VehicleLightState.All ^ carla.VehicleLightState.Brake - if vehicle_control.reverse: - current_lights |= carla.VehicleLightState.Reverse - else: # Remove the Reverse flag - current_lights &= carla.VehicleLightState.All ^ carla.VehicleLightState.Reverse - if current_lights != self._lights: # Change the light state only if necessary - self._lights = current_lights - world.player.set_light_state(carla.VehicleLightState(self._lights)) - - world.player.apply_control(vehicle_control) - - def _parse_vehicle_keys(self, keys, milliseconds): - if keys[K_UP] or keys[K_w]: - self._control.throttle = min(self._control.throttle + 0.2, 1) - else: - self._control.throttle = max(self._control.throttle - 0.2, 0) - - if keys[K_DOWN] or keys[K_s]: - self._control.brake = min(self._control.brake + 0.2, 1) - else: - self._control.brake = max(self._control.brake - 0.2, 0) - - steer_increment = 5e-4 * milliseconds - if keys[K_LEFT] or keys[K_a]: - if self._steer_cache > 0: - self._steer_cache = 0 - else: - self._steer_cache -= steer_increment - elif keys[K_RIGHT] or keys[K_d]: - if self._steer_cache < 0: - self._steer_cache = 0 - else: - self._steer_cache += steer_increment - elif self._steer_cache > 0: - self._steer_cache = max(self._steer_cache - steer_increment, 0.0) - elif self._steer_cache < 0: - self._steer_cache = min(self._steer_cache + steer_increment, 0.0) - else: - self._steer_cache = 0 - - self._steer_cache = min(1.0, max(-1.0, self._steer_cache)) - self._control.steer = round(self._steer_cache, 1) - self._control.hand_brake = keys[K_SPACE] - - def _parse_mouse(self, pos): - if not self._mouse_steering_center: - return - - lateral = float(pos[0] - self._mouse_steering_center[0]) - longitudinal = float(pos[1] - self._mouse_steering_center[1]) - max_val = self.MOUSE_STEERING_RANGE - lateral = -max_val if lateral < -max_val else max_val if lateral > max_val else lateral - longitudinal = -max_val if longitudinal < -max_val else max_val if longitudinal > max_val else longitudinal - self._control.steer = lateral / max_val - if longitudinal < 0.0: - self._control.throttle = -longitudinal / max_val - self._control.brake = 0.0 - elif longitudinal > 0.0: - self._control.throttle = 0.0 - self._control.brake = longitudinal / max_val - - @staticmethod - def _is_quit_shortcut(key): - return (key == K_ESCAPE) or (key == K_q and pygame.key.get_mods() & KMOD_CTRL) - - -# ============================================================================== -# -- HUD ----------------------------------------------------------------------- -# ============================================================================== - - -class HUD(object): - - def __init__(self, width, height, world): - self.dim = (width, height) - self._world = world - self.map_name = world.get_map().name - font = pygame.font.Font(pygame.font.get_default_font(), 20) - font_name = 'courier' if os.name == 'nt' else 'mono' - fonts = [x for x in pygame.font.get_fonts() if font_name in x] - default_font = 'ubuntumono' - mono = default_font if default_font in fonts else fonts[0] - mono = pygame.font.match_font(mono) - self._font_mono = pygame.font.Font(mono, 12 if os.name == 'nt' else 14) - self._notifications = FadingText(font, (width, 40), (0, height - 40)) - self.help = HelpText(pygame.font.Font(mono, 16), width, height) - self.server_fps = 0 - self.frame = 0 - self.simulation_time = 0 - self.original_vehicle_control = None - self.restricted_vehicle_control = None - self.allowed_steering_ranges = [] - self._show_info = True - self._info_text = [] - self._server_clock = pygame.time.Clock() - self.rss_state_visualizer = RssStateVisualizer(self.dim, self._font_mono, self._world) - - def on_world_tick(self, timestamp): - self._server_clock.tick() - self.server_fps = self._server_clock.get_fps() - self.frame = timestamp.frame - self.simulation_time = timestamp.elapsed_seconds - - def tick(self, player, clock): - self._notifications.tick(clock) - if not self._show_info: - return - t = player.get_transform() - v = player.get_velocity() - c = player.get_control() - - self._info_text = [ - 'Server: % 16.0f FPS' % self.server_fps, - 'Client: % 16.0f FPS' % clock.get_fps(), - 'Map: % 20s' % self.map_name, - '', - 'Speed: % 15.0f km/h' % (3.6 * math.sqrt(v.x**2 + v.y**2 + v.z**2)), - 'Location:% 20s' % ('(% 5.1f, % 5.1f)' % (t.location.x, t.location.y)), - 'Heading: % 20.2f' % math.radians(t.rotation.yaw), - ''] - if self.original_vehicle_control: - orig_control = self.original_vehicle_control - restricted_control = self.restricted_vehicle_control - allowed_steering_ranges = self.allowed_steering_ranges - self._info_text += [ - ('Throttle:', orig_control.throttle, 0.0, 1.0, restricted_control.throttle), - ('Steer:', orig_control.steer, -1.0, 1.0, restricted_control.steer, allowed_steering_ranges), - ('Brake:', orig_control.brake, 0.0, 1.0, restricted_control.brake)] - self._info_text += [ - ('Reverse:', c.reverse), - ''] - - def toggle_info(self): - self._show_info = not self._show_info - - def notification(self, text, seconds=2.0): - self._notifications.set_text(text, seconds=seconds) - - def error(self, text): - self._notifications.set_text('Error: %s' % text, (255, 0, 0)) - - def render(self, display): - if self._show_info: - info_surface = pygame.Surface((220, self.dim[1])) - info_surface.set_alpha(100) - display.blit(info_surface, (0, 0)) - v_offset = 4 - bar_h_offset = 100 - bar_width = 106 - for item in self._info_text: - text_color = (255, 255, 255) - if v_offset + 18 > self.dim[1]: - break - if isinstance(item, list): - if len(item) > 1: - points = [(x + 8, v_offset + 8 + (1.0 - y) * 30) for x, y in enumerate(item)] - pygame.draw.lines(display, (255, 136, 0), False, points, 2) - item = None - v_offset += 18 - elif isinstance(item, tuple): - if isinstance(item[1], bool): - rect = pygame.Rect((bar_h_offset, v_offset + 2), (10, 10)) - pygame.draw.rect(display, (255, 255, 255), rect, 0 if item[1] else 1) - else: - # draw allowed steering ranges - if len(item) == 6 and item[2] < 0.0: - for steering_range in item[5]: - starting_value = min(steering_range[0], steering_range[1]) - length = (max(steering_range[0], steering_range[1]) - - min(steering_range[0], steering_range[1])) / 2 - rect = pygame.Rect( - (bar_h_offset + (starting_value + 1) * (bar_width / 2), v_offset + 2), (length * bar_width, 14)) - pygame.draw.rect(display, (0, 255, 0), rect) - - # draw border - rect_border = pygame.Rect((bar_h_offset, v_offset + 2), (bar_width, 14)) - pygame.draw.rect(display, (255, 255, 255), rect_border, 1) - - # draw value / restricted value - input_value_rect_fill = 0 - if len(item) >= 5: - if item[1] != item[4]: - input_value_rect_fill = 1 - f = (item[4] - item[2]) / (item[3] - item[2]) - if item[2] < 0.0: - rect = pygame.Rect( - (bar_h_offset + 1 + f * (bar_width - 6), v_offset + 3), (12, 12)) - else: - rect = pygame.Rect((bar_h_offset + 1, v_offset + 3), (f * bar_width, 12)) - pygame.draw.rect(display, (255, 0, 0), rect) - - f = (item[1] - item[2]) / (item[3] - item[2]) - rect = None - if item[2] < 0.0: - rect = pygame.Rect((bar_h_offset + 2 + f * (bar_width - 14), v_offset + 4), (10, 10)) - else: - if item[1] != 0: - rect = pygame.Rect((bar_h_offset + 2, v_offset + 4), (f * (bar_width - 4), 10)) - if rect: - pygame.draw.rect(display, (255, 255, 255), rect, input_value_rect_fill) - item = item[0] - if item: # At this point has to be a str. - surface = self._font_mono.render(item, True, text_color) - display.blit(surface, (8, v_offset)) - v_offset += 18 - - self.rss_state_visualizer.render(display, v_offset) - self._notifications.render(display) - self.help.render(display) - - -# ============================================================================== -# -- FadingText ---------------------------------------------------------------- -# ============================================================================== - - -class FadingText(object): - - def __init__(self, font, dim, pos): - self.font = font - self.dim = dim - self.pos = pos - self.seconds_left = 0 - self.surface = pygame.Surface(self.dim) - - def set_text(self, text, color=(255, 255, 255), seconds=2.0): - text_texture = self.font.render(text, True, color) - self.surface = pygame.Surface(self.dim) - self.seconds_left = seconds - self.surface.fill((0, 0, 0, 0)) - self.surface.blit(text_texture, (10, 11)) - - def tick(self, clock): - delta_seconds = 1e-3 * clock.get_time() - self.seconds_left = max(0.0, self.seconds_left - delta_seconds) - self.surface.set_alpha(500.0 * self.seconds_left) - - def render(self, display): - display.blit(self.surface, self.pos) - - -# ============================================================================== -# -- HelpText ------------------------------------------------------------------ -# ============================================================================== - - -class HelpText(object): - - """Helper class to handle text output using pygame""" - - def __init__(self, font, width, height): - lines = __doc__.split('\n') - self.font = font - self.line_space = 18 - self.dim = (780, len(lines) * self.line_space + 12) - self.pos = (0.5 * width - 0.5 * self.dim[0], 0.5 * height - 0.5 * self.dim[1]) - self.seconds_left = 0 - self.surface = pygame.Surface(self.dim) - self.surface.fill((0, 0, 0, 0)) - for n, line in enumerate(lines): - text_texture = self.font.render(line, True, (255, 255, 255)) - self.surface.blit(text_texture, (22, n * self.line_space)) - self._render = False - self.surface.set_alpha(220) - - def toggle(self): - self._render = not self._render - - def render(self, display): - if self._render: - display.blit(self.surface, self.pos) - -# ============================================================================== -# -- game_loop() --------------------------------------------------------------- -# ============================================================================== - - -def game_loop(args): - pygame.init() - pygame.font.init() - world = None - - try: - client = carla.Client(args.host, args.port) - client.set_timeout(2.0) - - display = pygame.display.set_mode( - (args.width, args.height), - pygame.HWSURFACE | pygame.DOUBLEBUF) - - sim_world = client.get_world() - original_settings = sim_world.get_settings() - settings = sim_world.get_settings() - if args.sync != settings.synchronous_mode: - args.sync = True - settings.synchronous_mode = True - settings.fixed_delta_seconds = 0.05 - sim_world.apply_settings(settings) - - traffic_manager = client.get_trafficmanager() - traffic_manager.set_synchronous_mode(True) - - world = World(sim_world, args) - controller = VehicleControl(world, args.autopilot) - - clock = pygame.time.Clock() - while True: - if args.sync: - sim_world.tick() - clock.tick_busy_loop(60) - if controller.parse_events(world, clock, args.sync): - return - world.tick(clock) - world.render(display) - controller.render(display) - pygame.display.flip() - - finally: - - if world is not None: - print('Destroying the world...') - world.destroy() - print('Destroyed!') - - pygame.quit() - - -# ============================================================================== -# -- main() -------------------------------------------------------------------- -# ============================================================================== - -def main(): - argparser = argparse.ArgumentParser( - description='CARLA Manual Control Client RSS') - argparser.add_argument( - '-v', '--verbose', - action='store_true', - dest='debug', - help='print debug information') - argparser.add_argument( - '--host', - metavar='H', - default='127.0.0.1', - help='IP of the host server (default: 127.0.0.1)') - argparser.add_argument( - '-p', '--port', - metavar='P', - default=2000, - type=int, - help='TCP port to listen to (default: 2000)') - argparser.add_argument( - '-a', '--autopilot', - action='store_true', - help='enable autopilot') - argparser.add_argument( - '--res', - metavar='WIDTHxHEIGHT', - default='1280x720', - help='window resolution (default: 1280x720)') - argparser.add_argument( - '--filter', - metavar='PATTERN', - default='vehicle.*', - help='actor filter (default: "vehicle.*")') - argparser.add_argument( - '--rolename', - metavar='NAME', - default='hero', - help='actor role name (default: "hero")') - argparser.add_argument( - '--externalActor', - action='store_true', - help='attaches to externally created actor by role name') - argparser.add_argument( - '--sync', - action='store_true', - help='Activate synchronous mode execution') - args = argparser.parse_args() - - args.width, args.height = [int(x) for x in args.res.split('x')] - - log_level = logging.DEBUG if args.debug else logging.INFO - logging.basicConfig(format='%(levelname)s: %(message)s', level=log_level) - - logging.info('listening to server %s:%s', args.host, args.port) - - print(__doc__) - - signal.signal(signal.SIGINT, VehicleControl.signal_handler) - - try: - game_loop(args) - - except KeyboardInterrupt: - print('\nCancelled by user. Bye!') - - -if __name__ == '__main__': - - main() diff --git a/PythonAPI/examples/rss/rss_sensor.py b/PythonAPI/examples/rss/rss_sensor.py deleted file mode 100644 index 02266071897..00000000000 --- a/PythonAPI/examples/rss/rss_sensor.py +++ /dev/null @@ -1,457 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2020 Intel Corporation -# - -import glob -import os -import sys - -try: - sys.path.append(glob.glob(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + '/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 inspect -import carla -from carla import ad -import math -from rss_visualization import RssDebugVisualizer # pylint: disable=relative-import - - -# ============================================================================== -# -- RssSensor ----------------------------------------------------------------- -# ============================================================================== - - -class RssStateInfo(object): - - def __init__(self, rss_state, ego_dynamics_on_route, world_model): - self.rss_state = rss_state - self.distance = -1 - self.is_dangerous = ad.rss.state.isDangerous(rss_state) - if rss_state.situationType == ad.rss.situation.SituationType.Unstructured: - self.actor_calculation_mode = ad.rss.map.RssMode.Unstructured - else: - self.actor_calculation_mode = ad.rss.map.RssMode.Structured - - # calculate distance to other vehicle - object_state = None - for scene in world_model.scenes: - if scene.object.objectId == rss_state.objectId: - object_state = scene.object.state - break - - if object_state: - self.distance = math.sqrt((float(ego_dynamics_on_route.ego_center.x) - float(object_state.centerPoint.x))**2 + - (float(ego_dynamics_on_route.ego_center.y) - float(object_state.centerPoint.y))**2) - - self.longitudinal_margin = float(rss_state.longitudinalState.rssStateInformation.currentDistance - rss_state.longitudinalState.rssStateInformation.safeDistance) - self.margin = max(0, self.longitudinal_margin) - self.lateral_margin = None - if rss_state.lateralStateLeft.rssStateInformation.evaluator != "None": - self.lateral_margin = rss_state.lateralStateLeft.rssStateInformation.currentDistance - rss_state.lateralStateLeft.rssStateInformation.safeDistance - if rss_state.lateralStateRight.rssStateInformation.evaluator != "None": - lateral_margin_right = rss_state.lateralStateRight.rssStateInformation.currentDistance - rss_state.lateralStateRight.rssStateInformation.safeDistance - if self.lateral_margin==None or self.lateral_margin > lateral_margin_right: - self.lateral_margin=lateral_margin_right - if self.lateral_margin!=None and self.lateral_margin>0: - self.margin += self.lateral_margin - - def get_actor(self, world): - if self.rss_state.objectId == 18446744073709551614: - return None # "Border Left" - elif self.rss_state.objectId == 18446744073709551615: - return None # "Border Right" - else: - return world.get_actor(self.rss_state.objectId) - - def __str__(self): - return "RssStateInfo: object=" + str(self.rss_state.objectId) + " dangerous=" + str(self.is_dangerous) - - -class RssSensor(object): - - def __init__(self, parent_actor, world, unstructured_scene_visualizer, bounding_box_visualizer, state_visualizer, routing_targets=None): - self.sensor = None - self.unstructured_scene_visualizer = unstructured_scene_visualizer - self.bounding_box_visualizer = bounding_box_visualizer - self._parent = parent_actor - self.timestamp = None - self.response_valid = False - self.proper_response = None - self.rss_state_snapshot = None - self.situation_snapshot = None - self.world_model = None - self.individual_rss_states = [] - self._allowed_heading_ranges = [] - self.ego_dynamics_on_route = None - self.current_vehicle_parameters = self.get_default_parameters() - self.route = None - self.debug_visualizer = RssDebugVisualizer(parent_actor, world) - self.state_visualizer = state_visualizer - self.change_to_unstructured_position_map = dict() - - # get max steering angle - physics_control = parent_actor.get_physics_control() - self._max_steer_angle = 0.0 - for wheel in physics_control.wheels: - if wheel.max_steer_angle > self._max_steer_angle: - self._max_steer_angle = wheel.max_steer_angle - self._max_steer_angle = math.radians(self._max_steer_angle) - - world = self._parent.get_world() - bp = world.get_blueprint_library().find('sensor.other.rss') - self.sensor = world.spawn_actor(bp, carla.Transform(carla.Location(x=0.0, z=0.0)), attach_to=self._parent) - # We need to pass the lambda a weak reference to self to avoid circular - # reference. - - def check_rss_class(clazz): - return inspect.isclass(clazz) and "RssSensor" in clazz.__name__ - - if not inspect.getmembers(carla, check_rss_class): - raise RuntimeError('CARLA PythonAPI not compiled in RSS variant, please "make PythonAPI.rss"') - - self.log_level = carla.RssLogLevel.warn - self.map_log_level = carla.RssLogLevel.warn - - self.set_default_parameters() - - self.sensor.register_actor_constellation_callback(self._on_actor_constellation_request) - - self.sensor.listen(self._on_rss_response) - self.sensor.set_log_level(self.log_level) - self.sensor.set_map_log_level(self.map_log_level) - - # only relevant if actor constellation callback is not registered - # self.sensor.ego_vehicle_dynamics = self.current_vehicle_parameters - - self.sensor.road_boundaries_mode = carla.RssRoadBoundariesMode.Off - - self.sensor.reset_routing_targets() - if routing_targets: - for target in routing_targets: - self.sensor.append_routing_target(target) - - def _on_actor_constellation_request(self, actor_constellation_data): - # print("_on_actor_constellation_request: ", str(actor_constellation_data)) - - actor_constellation_result = carla.RssActorConstellationResult() - actor_constellation_result.rss_calculation_mode = ad.rss.map.RssMode.NotRelevant - actor_constellation_result.restrict_speed_limit_mode = ad.rss.map.RssSceneCreation.RestrictSpeedLimitMode.IncreasedSpeedLimit10 - actor_constellation_result.ego_vehicle_dynamics = self.current_vehicle_parameters - actor_constellation_result.actor_object_type = ad.rss.world.ObjectType.Invalid - actor_constellation_result.actor_dynamics = self.current_vehicle_parameters - - actor_id = -1 - # actor_type_id = "none" - if actor_constellation_data.other_actor != None: - actor_id = actor_constellation_data.other_actor.id - # actor_type_id = actor_constellation_data.other_actor.type_id - - ego_on_the_sidewalk = False - ego_on_routeable_road = False - for occupied_region in actor_constellation_data.ego_match_object.mapMatchedBoundingBox.laneOccupiedRegions: - lane = ad.map.lane.getLane(occupied_region.laneId) - if lane.type == ad.map.lane.LaneType.PEDESTRIAN: - # if not ego_on_the_sidewalk: - # print ( "ego-{} on lane of lane type {} => sidewalk".format(actor_id, lane.type)) - ego_on_the_sidewalk = True - elif ad.map.lane.isRouteable(lane): - # if not ego_on_routeable_road: - # print ( "ego-{} on lane of lane type {} => road".format(actor_id, lane.type)) - ego_on_routeable_road = True - - if 'walker.pedestrian' in actor_constellation_data.other_actor.type_id: - # determine if the pedestrian is walking on the sidewalk or on the road - pedestrian_on_the_road = False - pedestrian_on_the_sidewalk = False - for occupied_region in actor_constellation_data.other_match_object.mapMatchedBoundingBox.laneOccupiedRegions: - lane = ad.map.lane.getLane(occupied_region.laneId) - if lane.type == ad.map.lane.LaneType.PEDESTRIAN: - # if not pedestrian_on_the_sidewalk: - # print ( "pedestrian-{} on lane of lane type {} => sidewalk".format(actor_id, lane.type)) - pedestrian_on_the_sidewalk = True - else: - # if not pedestrian_on_the_road: - # print ( "pedestrian-{} on lane of lane type {} => road".format(actor_id, lane.type)) - pedestrian_on_the_road = True - if ego_on_routeable_road and not ego_on_the_sidewalk and not pedestrian_on_the_road and pedestrian_on_the_sidewalk: - # pedestrian is not on the road, but on the sidewalk: then common sense is that vehicle has priority - # This analysis can and should be done more detailed, but this is a basic starting point for the decision - # In addition, the road network has to be correct to work best - # (currently there are no sidewalks in intersection areas) - # print ( "pedestrian-{} Off".format(actor_id)) - actor_constellation_result.rss_calculation_mode = ad.rss.map.RssMode.NotRelevant - else: - # print ( "pedestrian-{} Unstructured".format(actor_id)) - actor_constellation_result.rss_calculation_mode = ad.rss.map.RssMode.Unstructured - actor_constellation_result.actor_object_type = ad.rss.world.ObjectType.Pedestrian - actor_constellation_result.actor_dynamics = self.get_pedestrian_parameters() - elif 'vehicle' in actor_constellation_data.other_actor.type_id: - actor_constellation_result.actor_object_type = ad.rss.world.ObjectType.OtherVehicle - - # set the response time of others vehicles to 2 seconds; the rest stays the same - actor_constellation_result.actor_dynamics.responseTime = 2.0 - - # per default, if ego is not on the road -> unstructured - if ego_on_routeable_road: - actor_constellation_result.rss_calculation_mode = ad.rss.map.RssMode.Structured - else: - # print("vehicle-{} unstructured: reason other ego not on routeable road".format(actor_id)) - actor_constellation_result.rss_calculation_mode = ad.rss.map.RssMode.Unstructured - - # special handling for vehicles standing still - actor_vel = actor_constellation_data.other_actor.get_velocity() - actor_speed = math.sqrt(actor_vel.x**2 + actor_vel.y**2 + actor_vel.z**2) - if actor_speed < 0.01: - # reduce response time - actor_constellation_result.actor_dynamics.responseTime = 1.0 - # still in structured? - if actor_constellation_result.rss_calculation_mode == ad.rss.map.RssMode.Structured: - - actor_distance = math.sqrt(float(actor_constellation_data.ego_match_object.enuPosition.centerPoint.x - - actor_constellation_data.other_match_object.enuPosition.centerPoint.x)**2 + - float(actor_constellation_data.ego_match_object.enuPosition.centerPoint.y - - actor_constellation_data.other_match_object.enuPosition.centerPoint.y)**2) - # print("vehicle-{} unstructured check: other distance {}".format(actor_id, actor_distance)) - - if actor_constellation_data.ego_dynamics_on_route.ego_speed < 0.01: - # both vehicles stand still, so we have to analyze in detail if we possibly want to use - # unstructured mode to cope with blockades on the road... - - if actor_distance < 10: - # the other has to be near enough to trigger a switch to unstructured - other_outside_routeable_road = False - for occupied_region in actor_constellation_data.other_match_object.mapMatchedBoundingBox.laneOccupiedRegions: - lane = ad.map.lane.getLane(occupied_region.laneId) - if not ad.map.lane.isRouteable(lane): - other_outside_routeable_road = True - - if other_outside_routeable_road: - # if the other is somewhat outside the standard routeable road (e.g. parked at the side, ...) - # we immediately decide for unstructured - # print("vehicle-{} unstructured: reason other outside routeable - # road".format(actor_id)) - actor_constellation_result.rss_calculation_mode = ad.rss.map.RssMode.Unstructured - else: - # otherwise we have to look in the orientation delta in addition to get some basic idea of the - # constellation (we don't want to go into unstructured if we both waiting - # behind a red light...) - heading_delta = abs(float(actor_constellation_data.ego_match_object.enuPosition.heading - - actor_constellation_data.other_match_object.enuPosition.heading)) - if heading_delta > 0.2: # around 11 degree - # print("vehicle-{} unstructured: reason heading delta - # {}".format(actor_id, heading_delta)) - actor_constellation_result.rss_calculation_mode = ad.rss.map.RssMode.Unstructured - self.change_to_unstructured_position_map[ - actor_id] = actor_constellation_data.other_match_object.enuPosition - else: - # ego moves - if actor_distance < 10: - # if the ego moves, the other actor doesn't move an the mode was - # previously set to unstructured, keep it - try: - if self.change_to_unstructured_position_map[actor_id] == actor_constellation_data.other_match_object.enuPosition: - heading_delta = abs(float(actor_constellation_data.ego_match_object.enuPosition.heading - - actor_constellation_data.other_match_object.enuPosition.heading)) - if heading_delta > 0.2: - actor_constellation_result.rss_calculation_mode = ad.rss.map.RssMode.Unstructured - else: - del self.change_to_unstructured_position_map[actor_id] - except (AttributeError, KeyError): - pass - else: - if actor_id in self.change_to_unstructured_position_map: - del self.change_to_unstructured_position_map[actor_id] - - # still in structured? - if actor_constellation_result.rss_calculation_mode == ad.rss.map.RssMode.Structured: - # in structured case we have to cope with not yet implemented lateral intersection checks in core RSS implementation - # if the other is standing still, we don't assume that he will accelerate - # otherwise if standing at the intersection the acceleration within reaction time - # will allow to enter the intersection which current RSS implementation will immediately consider - # as dangerous - # print("_on_actor_constellation_result({}) setting accelMax to - # zero".format(actor_constellation_data.other_actor.id)) - actor_constellation_result.actor_dynamics.alphaLon.accelMax = 0. - actor_constellation_result.actor_dynamics.alphaLat.accelMax = 0. - else: - # store route for debug drawings - self.route = actor_constellation_data.ego_route - # since the ego vehicle is controlled manually, it is easy possible that the ego vehicle - # accelerates far more in lateral direction than the ego_dynamics indicate - # in an automated vehicle this would be considered by the low-level controller when the RSS restriction - # is taken into account properly - # but the simple RSS restrictor within CARLA is not able to do so... - # So we should at least tell RSS about the fact that we acceleration more than this - # to be able to react on this - abs_avg_route_accel_lat = abs(float(actor_constellation_data.ego_dynamics_on_route.avg_route_accel_lat)) - if abs_avg_route_accel_lat > actor_constellation_result.ego_vehicle_dynamics.alphaLat.accelMax: - # print("!! Route lateral dynamics exceed expectations: route:{} expected:{} !!".format(abs_avg_route_accel_lat, - # actor_constellation_result.ego_vehicle_dynamics.alphaLat.accelMax)) - actor_constellation_result.ego_vehicle_dynamics.alphaLat.accelMax = min(20., abs_avg_route_accel_lat) - - # print("_on_actor_constellation_result({}-{}): ".format(actor_id, - # actor_type_id), str(actor_constellation_result)) - return actor_constellation_result - - def destroy(self): - if self.sensor: - print("Stopping RSS sensor") - self.sensor.stop() - print("Deleting Scene Visualizer") - self.unstructured_scene_visualizer = None - print("Destroying RSS sensor") - self.sensor.destroy() - print("Destroyed RSS sensor") - - def toggle_debug_visualization_mode(self): - self.debug_visualizer.toggleMode() - - def increase_log_level(self): - print("inccrease {}".format(self.log_level)) - if self.log_level < carla.RssLogLevel.off: - self.log_level = self.log_level+1 - self.sensor.set_log_level(self.log_level) - - def decrease_log_level(self): - print("decrease {}".format(self.log_level)) - if self.log_level > carla.RssLogLevel.trace: - self.log_level = self.log_level-1 - self.sensor.set_log_level(self.log_level) - - def increase_map_log_level(self): - if self.map_log_level < carla.RssLogLevel.off: - self.map_log_level = self.map_log_level+1 - self.sensor.set_map_log_level(self.map_log_level) - - def decrease_map_log_level(self): - if self.map_log_level > carla.RssLogLevel.trace: - self.map_log_level = self.map_log_level-1 - self.sensor.set_map_log_level(self.map_log_level) - - def drop_route(self): - self.sensor.drop_route() - - @staticmethod - def get_default_parameters(): - ego_dynamics = ad.rss.world.RssDynamics() - ego_dynamics.alphaLon.accelMax = 5 - ego_dynamics.alphaLon.brakeMax = -8 - ego_dynamics.alphaLon.brakeMin = -4 - ego_dynamics.alphaLon.brakeMinCorrect = -3 - ego_dynamics.alphaLat.accelMax = 0.2 - ego_dynamics.alphaLat.brakeMin = -0.8 - ego_dynamics.lateralFluctuationMargin = 0.1 - 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 = 1.3 - ego_dynamics.unstructuredSettings.vehicleMinRadius = 3.5 - ego_dynamics.unstructuredSettings.vehicleTrajectoryCalculationStep = 0.2 - ego_dynamics.unstructuredSettings.vehicleFrontIntermediateYawRateChangeRatioSteps = 4 - ego_dynamics.unstructuredSettings.vehicleBackIntermediateYawRateChangeRatioSteps = 0 - ego_dynamics.unstructuredSettings.vehicleContinueForwardIntermediateAccelerationSteps = 3 - ego_dynamics.unstructuredSettings.vehicleBrakeIntermediateAccelerationSteps = 3 - ego_dynamics.unstructuredSettings.pedestrianTurningRadius = 2.0 - ego_dynamics.unstructuredSettings.pedestrianContinueForwardIntermediateHeadingChangeRatioSteps = 3 - ego_dynamics.unstructuredSettings.pedestrianContinueForwardIntermediateAccelerationSteps = 0 - ego_dynamics.unstructuredSettings.pedestrianBrakeIntermediateAccelerationSteps = 3 - ego_dynamics.unstructuredSettings.pedestrianFrontIntermediateHeadingChangeRatioSteps = 4 - ego_dynamics.unstructuredSettings.pedestrianBackIntermediateHeadingChangeRatioSteps = 0 - return ego_dynamics - - def set_default_parameters(self): - print("Use 'default' RSS Parameters") - self.current_vehicle_parameters = self.get_default_parameters() - - @staticmethod - def get_pedestrian_parameters(): - pedestrian_dynamics = ad.rss.world.RssDynamics() - pedestrian_dynamics.alphaLon.accelMax = 2.0 - pedestrian_dynamics.alphaLon.brakeMax = -2.0 - pedestrian_dynamics.alphaLon.brakeMin = -2.0 - pedestrian_dynamics.alphaLon.brakeMinCorrect = -2.0 - pedestrian_dynamics.alphaLat.accelMax = 0.001 - pedestrian_dynamics.alphaLat.brakeMin = -0.001 - pedestrian_dynamics.lateralFluctuationMargin = 0.1 - pedestrian_dynamics.responseTime = 0.8 - pedestrian_dynamics.maxSpeedOnAcceleration = 10 - pedestrian_dynamics.unstructuredSettings.pedestrianTurningRadius = 2.0 - pedestrian_dynamics.unstructuredSettings.driveAwayMaxAngle = 2.4 - pedestrian_dynamics.unstructuredSettings.pedestrianContinueForwardIntermediateHeadingChangeRatioSteps = 3 - pedestrian_dynamics.unstructuredSettings.pedestrianContinueForwardIntermediateAccelerationSteps = 0 - pedestrian_dynamics.unstructuredSettings.pedestrianBrakeIntermediateAccelerationSteps = 3 - pedestrian_dynamics.unstructuredSettings.pedestrianFrontIntermediateHeadingChangeRatioSteps = 4 - pedestrian_dynamics.unstructuredSettings.pedestrianBackIntermediateHeadingChangeRatioSteps = 0 - - #not used: - pedestrian_dynamics.unstructuredSettings.vehicleYawRateChange = 1.3 - pedestrian_dynamics.unstructuredSettings.vehicleMinRadius = 3.5 - pedestrian_dynamics.unstructuredSettings.vehicleTrajectoryCalculationStep = 0.2 - pedestrian_dynamics.unstructuredSettings.vehicleFrontIntermediateYawRateChangeRatioSteps = 4 - pedestrian_dynamics.unstructuredSettings.vehicleBackIntermediateYawRateChangeRatioSteps = 0 - pedestrian_dynamics.unstructuredSettings.vehicleContinueForwardIntermediateAccelerationSteps = 3 - pedestrian_dynamics.unstructuredSettings.vehicleBrakeIntermediateAccelerationSteps = 3 - return pedestrian_dynamics - - def get_steering_ranges(self): - ranges = [] - for heading_range in self._allowed_heading_ranges: - ranges.append( - ( - (float(self.ego_dynamics_on_route.ego_heading) - float(heading_range.begin)) / self._max_steer_angle, - (float(self.ego_dynamics_on_route.ego_heading) - float(heading_range.end)) / self._max_steer_angle) - ) - return ranges - - def _on_rss_response(self, response): - if not self or not response: - return - delta_time = 0.1 - if self.timestamp: - delta_time = response.timestamp - self.timestamp - if delta_time > -0.05: - self.timestamp = response.timestamp - self.response_valid = response.response_valid - self.proper_response = response.proper_response - self.ego_dynamics_on_route = response.ego_dynamics_on_route - self.rss_state_snapshot = response.rss_state_snapshot - self.situation_snapshot = response.situation_snapshot - self.world_model = response.world_model - - # calculate the allowed heading ranges: - if response.proper_response.headingRanges: - heading = float(response.ego_dynamics_on_route.ego_heading) - heading_ranges = response.proper_response.headingRanges - steering_range = ad.rss.state.HeadingRange() - steering_range.begin = - self._max_steer_angle + heading - steering_range.end = self._max_steer_angle + heading - ad.rss.unstructured.getHeadingOverlap(steering_range, heading_ranges) - self._allowed_heading_ranges = heading_ranges - else: - self._allowed_heading_ranges = [] - - if self.unstructured_scene_visualizer: - self.unstructured_scene_visualizer.tick(response.frame, response, self._allowed_heading_ranges) - - new_states = [] - for rss_state in response.rss_state_snapshot.individualResponses: - new_states.append(RssStateInfo(rss_state, response.ego_dynamics_on_route, response.world_model)) - if len(new_states) > 0: - new_states.sort(key=lambda rss_states: rss_states.distance) - self.individual_rss_states = new_states - if self.bounding_box_visualizer: - self.bounding_box_visualizer.tick(response.frame, self.individual_rss_states) - if self.state_visualizer: - self.state_visualizer.tick(self.individual_rss_states) - self.debug_visualizer.tick(self.route, not response.proper_response.isSafe, - self.individual_rss_states, self.ego_dynamics_on_route) - - else: - print("ignore outdated response {}".format(delta_time)) diff --git a/PythonAPI/examples/rss/rss_visualization.py b/PythonAPI/examples/rss/rss_visualization.py deleted file mode 100644 index 564e1673244..00000000000 --- a/PythonAPI/examples/rss/rss_visualization.py +++ /dev/null @@ -1,738 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2020 Intel Corporation -# - -import glob -import os -import sys - -try: - sys.path.append(glob.glob(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + '/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 - -from enum import Enum -import math -import numpy as np -import pygame -import weakref -import carla -from carla import ad - - -class RssStateVisualizer(object): - - def __init__(self, display_dimensions, font, world): - self._surface = None - self._display_dimensions = display_dimensions - self._font = font - self._world = world - - def tick(self, individual_rss_states): - state_surface = pygame.Surface((220, self._display_dimensions[1])) - state_surface.set_colorkey(pygame.Color('black')) - v_offset = 0 - - if individual_rss_states: - surface = self._font.render('RSS States:', True, (255, 255, 255)) - state_surface.blit(surface, (8, v_offset)) - v_offset += 26 - for state in individual_rss_states: - object_name = "Obj" - if state.rss_state.objectId == 18446744073709551614: - object_name = "Border Left" - elif state.rss_state.objectId == 18446744073709551615: - object_name = "Border Right" - else: - other_actor = state.get_actor(self._world) - if other_actor: - li = list(other_actor.type_id.split(".")) - if li: - li.pop(0) - li = [element.capitalize() for element in li] - - object_name = " ".join(li).strip()[:15] - - mode = "?" - if state.actor_calculation_mode == ad.rss.map.RssMode.Structured: - mode = "S" - elif state.actor_calculation_mode == ad.rss.map.RssMode.Unstructured: - mode = "U" - elif state.actor_calculation_mode == ad.rss.map.RssMode.NotRelevant: - mode = "-" - item = '%4s % 2dm %8s' % (mode, state.distance, object_name) - - surface = self._font.render(item, True, (255, 255, 255)) - state_surface.blit(surface, (5, v_offset)) - color = (128, 128, 128) - if state.actor_calculation_mode != ad.rss.map.RssMode.NotRelevant: - if state.is_dangerous: - color = (255, 0, 0) - else: - color = (0, 255, 0) - pygame.draw.circle(state_surface, color, (12, v_offset + 7), 5) - xpos = 184 - if state.actor_calculation_mode == ad.rss.map.RssMode.Structured: - if not state.rss_state.longitudinalState.isSafe and ((state.rss_state.longitudinalState.rssStateInformation.evaluator == "LongitudinalDistanceSameDirectionOtherInFront") or (state.rss_state.longitudinalState.rssStateInformation.evaluator == "LongitudinalDistanceSameDirectionEgoFront")): - pygame.draw.polygon( - state_surface, ( - 255, 255, 255), ((xpos + 1, v_offset + 1 + 4), (xpos + 6, v_offset + 1 + 0), (xpos + 11, v_offset + 1 + 4), - (xpos + 7, v_offset + 1 + 4), (xpos + 7, v_offset + 1 + 12), (xpos + 5, v_offset + 1 + 12), (xpos + 5, v_offset + 1 + 4))) - xpos += 14 - - if not state.rss_state.longitudinalState.isSafe and ((state.rss_state.longitudinalState.rssStateInformation.evaluator == "LongitudinalDistanceOppositeDirectionEgoCorrectLane") or (state.rss_state.longitudinalState.rssStateInformation.evaluator == "LongitudinalDistanceOppositeDirection")): - pygame.draw.polygon( - state_surface, ( - 255, 255, 255), ((xpos + 2, v_offset + 1 + 8), (xpos + 6, v_offset + 1 + 12), (xpos + 10, v_offset + 1 + 8), - (xpos + 7, v_offset + 1 + 8), (xpos + 7, v_offset + 1 + 0), (xpos + 5, v_offset + 1 + 0), (xpos + 5, v_offset + 1 + 8))) - xpos += 14 - - if not state.rss_state.lateralStateRight.isSafe and not (state.rss_state.lateralStateRight.rssStateInformation.evaluator == "None"): - pygame.draw.polygon( - state_surface, ( - 255, 255, 255), ((xpos + 0, v_offset + 1 + 4), (xpos + 8, v_offset + 1 + 4), (xpos + 8, v_offset + 1 + 1), - (xpos + 12, v_offset + 1 + 6), (xpos + 8, v_offset + 1 + 10), (xpos + 8, v_offset + 1 + 8), (xpos + 0, v_offset + 1 + 8))) - xpos += 14 - if not state.rss_state.lateralStateLeft.isSafe and not (state.rss_state.lateralStateLeft.rssStateInformation.evaluator == "None"): - pygame.draw.polygon( - state_surface, ( - 255, 255, 255), ((xpos + 0, v_offset + 1 + 6), (xpos + 4, v_offset + 1 + 1), (xpos + 4, v_offset + 1 + 4), - (xpos + 12, v_offset + 1 + 4), (xpos + 12, v_offset + 1 + 8), (xpos + 4, v_offset + 1 + 8), (xpos + 4, v_offset + 1 + 10))) - xpos += 14 - elif state.actor_calculation_mode == ad.rss.map.RssMode.Unstructured: - text = "" - if state.rss_state.unstructuredSceneState.response == ad.rss.state.UnstructuredSceneResponse.DriveAway: - text = " D" - elif state.rss_state.unstructuredSceneState.response == ad.rss.state.UnstructuredSceneResponse.ContinueForward: - text = " C" - elif state.rss_state.unstructuredSceneState.response == ad.rss.state.UnstructuredSceneResponse.Brake: - text = " B" - surface = self._font.render(text, True, (255, 255, 255)) - state_surface.blit(surface, (xpos, v_offset)) - - v_offset += 14 - self._surface = state_surface - - def render(self, display, v_offset): - if self._surface: - display.blit(self._surface, (0, v_offset)) - - -def get_matrix(transform): - """ - Creates matrix from carla transform. - """ - - rotation = transform.rotation - location = transform.location - c_y = np.cos(np.radians(rotation.yaw)) - s_y = np.sin(np.radians(rotation.yaw)) - c_r = np.cos(np.radians(rotation.roll)) - s_r = np.sin(np.radians(rotation.roll)) - c_p = np.cos(np.radians(rotation.pitch)) - s_p = np.sin(np.radians(rotation.pitch)) - matrix = np.matrix(np.identity(4)) - matrix[0, 3] = location.x - matrix[1, 3] = location.y - matrix[2, 3] = location.z - matrix[0, 0] = c_p * c_y - matrix[0, 1] = c_y * s_p * s_r - s_y * c_r - matrix[0, 2] = -c_y * s_p * c_r - s_y * s_r - matrix[1, 0] = s_y * c_p - matrix[1, 1] = s_y * s_p * s_r + c_y * c_r - matrix[1, 2] = -s_y * s_p * c_r + c_y * s_r - matrix[2, 0] = s_p - matrix[2, 1] = -c_p * s_r - matrix[2, 2] = c_p * c_r - return matrix - -# ============================================================================== -# -- RssUnstructuredSceneVisualizer ------------------------------------------------ -# ============================================================================== - - -class RssUnstructuredSceneVisualizerMode(Enum): - disabled = 1 - window = 2 - fullscreen = 3 - - -class RssUnstructuredSceneVisualizer(object): - - def __init__(self, parent_actor, world, display_dimensions): - self._last_rendered_frame = -1 - self._surface = None - self._current_rss_surface = None - self.current_camera_surface = (0, None) - self._world = world - self._parent_actor = parent_actor - self._display_dimensions = display_dimensions - self._camera = None - self._mode = RssUnstructuredSceneVisualizerMode.disabled - - self.restart(RssUnstructuredSceneVisualizerMode.window) - - def destroy(self): - if self._camera: - self._camera.stop() - self._camera.destroy() - self._camera = None - - def restart(self, mode): - # setup up top down camera - self.destroy() - self._mode = mode - - spawn_sensor = False - if mode == RssUnstructuredSceneVisualizerMode.window: - self._dim = (self._display_dimensions[0] / 3, self._display_dimensions[1] / 2) - spawn_sensor = True - elif mode == RssUnstructuredSceneVisualizerMode.fullscreen: - self._dim = (self._display_dimensions[0], self._display_dimensions[1]) - spawn_sensor = True - else: - self._surface = None - - if spawn_sensor: - self._calibration = np.identity(3) - self._calibration[0, 2] = self._dim[0] / 2.0 - self._calibration[1, 2] = self._dim[1] / 2.0 - self._calibration[0, 0] = self._calibration[1, 1] = self._dim[0] / \ - (2.0 * np.tan(90.0 * np.pi / 360.0)) # fov default: 90.0 - - bp_library = self._world.get_blueprint_library() - bp = bp_library.find('sensor.camera.rgb') - bp.set_attribute('image_size_x', str(self._dim[0])) - bp.set_attribute('image_size_y', str(self._dim[1])) - - self._camera = self._world.spawn_actor( - bp, - carla.Transform(carla.Location(x=7.5, z=10), carla.Rotation(pitch=-90)), - attach_to=self._parent_actor) - # We need to pass the lambda a weak reference to self to avoid - # circular reference. - weak_self = weakref.ref(self) - self._camera.listen(lambda image: self._parse_image(weak_self, image)) - - def update_surface(self, cam_frame, rss_frame): - if self._mode == RssUnstructuredSceneVisualizerMode.disabled: - return - render = False - - if cam_frame and self._current_rss_surface and self._current_rss_surface[0] == cam_frame: - render = True - - if rss_frame and self.current_camera_surface and self.current_camera_surface[0] == rss_frame: - render = True - - if render: - surface = self.current_camera_surface[1] - surface.blit(self._current_rss_surface[1], (0, 0)) - rect = pygame.Rect((0, 0), (2, surface.get_height())) - pygame.draw.rect(surface, (0, 0, 0), rect, 0) - rect = pygame.Rect((0, 0), (surface.get_width(), 2)) - pygame.draw.rect(surface, (0, 0, 0), rect, 0) - rect = pygame.Rect((0, surface.get_height() - 2), (surface.get_width(), surface.get_height())) - pygame.draw.rect(surface, (0, 0, 0), rect, 0) - rect = pygame.Rect((surface.get_width() - 2, 0), (surface.get_width(), surface.get_width())) - pygame.draw.rect(surface, (0, 0, 0), rect, 0) - self._surface = surface - - def toggle_camera(self): - print("Toggle RssUnstructuredSceneVisualizer") - if self._mode == RssUnstructuredSceneVisualizerMode.window: - self.restart(RssUnstructuredSceneVisualizerMode.fullscreen) - elif self._mode == RssUnstructuredSceneVisualizerMode.fullscreen: - self.restart(RssUnstructuredSceneVisualizerMode.disabled) - elif self._mode == RssUnstructuredSceneVisualizerMode.disabled: - self.restart(RssUnstructuredSceneVisualizerMode.window) - - @staticmethod - def _parse_image(weak_self, image): - self = weak_self() - if not self: - return - image.convert(carla.ColorConverter.Raw) - array = np.frombuffer(image.raw_data, dtype=np.dtype("uint8")) - array = np.reshape(array, (image.height, image.width, 4)) - array = array[:, :, :3] - array = array[:, :, ::-1] - surface = pygame.surfarray.make_surface(array.swapaxes(0, 1)) - self.current_camera_surface = (image.frame, surface) - self.update_surface(image.frame, None) - - @staticmethod - def rotate_around_point(xy, radians, origin): - """Rotate a point around a given point. - """ - x, y = xy - offset_x, offset_y = origin - adjusted_x = (x - offset_x) - adjusted_y = (y - offset_y) - cos_rad = math.cos(radians) - sin_rad = math.sin(radians) - qx = offset_x + cos_rad * adjusted_x - sin_rad * adjusted_y - qy = offset_y + sin_rad * adjusted_x + cos_rad * adjusted_y - - return qx, qy - - def tick(self, frame, rss_response, allowed_heading_ranges): - if not self._camera: - return - surface = pygame.Surface(self._dim) - surface.set_colorkey(pygame.Color('black')) - surface.set_alpha(180) - try: - lines = RssUnstructuredSceneVisualizer.get_trajectory_sets( - rss_response.rss_state_snapshot, self._camera.get_transform(), self._calibration) - - polygons = [] - for heading_range in allowed_heading_ranges: - polygons.append((RssUnstructuredSceneVisualizer.transform_points( - RssUnstructuredSceneVisualizer._get_points_from_pairs( - RssUnstructuredSceneVisualizer.draw_heading_range( - heading_range, rss_response.ego_dynamics_on_route)), - self._camera.get_transform(), self._calibration), (0, 0, 255))) - - RssUnstructuredSceneVisualizer.draw_lines(surface, lines) - RssUnstructuredSceneVisualizer.draw_polygons(surface, polygons) - - except RuntimeError as e: - print("ERROR {}".format(e)) - self._current_rss_surface = (frame, surface) - self.update_surface(None, frame) - - def render(self, display): - if self._surface: - display.blit(self._surface, (display.get_width() - self._dim[0], 0)) - - @staticmethod - def draw_heading_range(heading_range, ego_dynamics_on_route): - line = [(float(ego_dynamics_on_route.ego_center.x), float(ego_dynamics_on_route.ego_center.y))] - length = 3.0 - current_angle = float(heading_range.begin) - max_angle = float(heading_range.end) - if heading_range.end < heading_range.begin: - max_angle += 2.0 * np.pi - - while current_angle < max_angle: - line.append((float(ego_dynamics_on_route.ego_center.x) + length * np.cos(current_angle), - float(ego_dynamics_on_route.ego_center.y) + length * np.sin(current_angle))) - current_angle += 0.2 - - if current_angle != max_angle: - line.append((float(ego_dynamics_on_route.ego_center.x) + length * np.cos(max_angle), - float(ego_dynamics_on_route.ego_center.y) + length * np.sin(max_angle))) - - line.append((float(ego_dynamics_on_route.ego_center.x), float(ego_dynamics_on_route.ego_center.y))) - return line - - @staticmethod - def get_trajectory_sets(rss_state_snapshot, camera_transform, calibration): - """ - Creates 3D bounding boxes based on carla vehicle list and camera. - """ - trajectory_sets = [] - - # ego - trajectory_sets.append((RssUnstructuredSceneVisualizer.transform_points(RssUnstructuredSceneVisualizer._get_trajectory_set_points( - rss_state_snapshot.unstructuredSceneEgoInformation.brakeTrajectorySet), camera_transform, calibration), (255, 0, 0))) - trajectory_sets.append((RssUnstructuredSceneVisualizer.transform_points(RssUnstructuredSceneVisualizer._get_trajectory_set_points( - rss_state_snapshot.unstructuredSceneEgoInformation.continueForwardTrajectorySet), camera_transform, calibration), (0, 255, 0))) - - # others - for state in rss_state_snapshot.individualResponses: - if state.unstructuredSceneState.rssStateInformation.brakeTrajectorySet: - trajectory_sets.append((RssUnstructuredSceneVisualizer.transform_points(RssUnstructuredSceneVisualizer._get_trajectory_set_points( - state.unstructuredSceneState.rssStateInformation.brakeTrajectorySet), camera_transform, calibration), (255, 0, 0))) - if state.unstructuredSceneState.rssStateInformation.continueForwardTrajectorySet: - trajectory_sets.append((RssUnstructuredSceneVisualizer.transform_points(RssUnstructuredSceneVisualizer._get_trajectory_set_points( - state.unstructuredSceneState.rssStateInformation.continueForwardTrajectorySet), camera_transform, calibration), (0, 255, 0))) - - return trajectory_sets - - @staticmethod - def draw_lines(surface, lines): - """ - Draws lines on pygame display. - """ - for line, color in lines: - if len(line) > 1: - pygame.draw.lines(surface, color, True, line, 2) - - @staticmethod - def draw_polygons(surface, polygons): - """ - Draws polygons on pygame display. - """ - for polygon, color in polygons: - if len(polygon) > 1: - pygame.draw.polygon(surface, color, polygon) - - @staticmethod - def transform_points(world_cords, camera_transform, calibration): - """ - Returns trajectory set projected to camera view - """ - world_cords = np.transpose(world_cords) - cords_x_y_z = RssUnstructuredSceneVisualizer._world_to_sensor(world_cords, camera_transform)[:3, :] - cords_y_minus_z_x = np.concatenate([cords_x_y_z[1, :], -cords_x_y_z[2, :], cords_x_y_z[0, :]]) - ts = np.transpose(np.dot(calibration, cords_y_minus_z_x)) - camera_ts = np.concatenate([ts[:, 0] / ts[:, 2], ts[:, 1] / ts[:, 2], ts[:, 2]], axis=1) - line_to_draw = [] - for point in camera_ts: - line_to_draw.append((int(point[0, 0]), int(point[0, 1]))) - return line_to_draw - - @staticmethod - def _get_trajectory_set_points(trajectory_set): - """ - """ - cords = np.zeros((len(trajectory_set), 4)) - i = 0 - for pt in trajectory_set: - cords[i, :] = np.array([pt.x, -pt.y, 0, 1]) - i += 1 - return cords - - @staticmethod - def _get_points_from_pairs(trajectory_set): - """ - """ - cords = np.zeros((len(trajectory_set), 4)) - i = 0 - for pt in trajectory_set: - cords[i, :] = np.array([pt[0], -pt[1], 0, 1]) - i += 1 - return cords - - @staticmethod - def _world_to_sensor(cords, camera_transform): - """ - Transforms world coordinates to sensor. - """ - sensor_world_matrix = get_matrix(camera_transform) - world_sensor_matrix = np.linalg.inv(sensor_world_matrix) - sensor_cords = np.dot(world_sensor_matrix, cords) - return sensor_cords - -# ============================================================================== -# -- RssBoundingBoxVisualizer ------------------------------------------------------ -# ============================================================================== - - -class RssBoundingBoxVisualizer(object): - - def __init__(self, display_dimensions, world, camera): - self._last_camera_frame = 0 - self._surface_for_frame = [] - self._world = world - self._dim = display_dimensions - self._calibration = np.identity(3) - self._calibration[0, 2] = self._dim[0] / 2.0 - self._calibration[1, 2] = self._dim[1] / 2.0 - self._calibration[0, 0] = self._calibration[1, 1] = self._dim[0] / \ - (2.0 * np.tan(90.0 * np.pi / 360.0)) # fov default: 90.0 - self._camera = camera - - def tick(self, frame, individual_rss_states): - if len(self._surface_for_frame) > 0: - try: - while self._surface_for_frame[0][0] < self._last_camera_frame: - self._surface_for_frame.pop(0) - except IndexError: - return - - # only render on new frame - if len(self._surface_for_frame) > 0: - if self._surface_for_frame[0][0] == frame: - return - - surface = pygame.Surface(self._dim) - surface.set_colorkey(pygame.Color('black')) - surface.set_alpha(80) - try: - bounding_boxes = RssBoundingBoxVisualizer.get_bounding_boxes( - individual_rss_states, self._camera.get_transform(), self._calibration, self._world) - RssBoundingBoxVisualizer.draw_bounding_boxes(surface, bounding_boxes) - self._surface_for_frame.append((frame, surface, len(bounding_boxes))) - except RuntimeError: - pass - - def render(self, display, current_camera_frame): - rendered = False - boxes_to_render = 0 - for frame, surface, box_count in self._surface_for_frame: - if frame == current_camera_frame: - display.blit(surface, (0, 0)) - boxes_to_render = box_count - rendered = True - break - if not rendered and boxes_to_render > 0: - print("Warning: {} bounding boxes were not drawn.".format(boxes_to_render)) - self._last_camera_frame = current_camera_frame - - @staticmethod - def get_bounding_boxes(individual_rss_states, camera_transform, calibration, world): - """ - Creates 3D bounding boxes based on carla vehicle list and camera. - """ - bounding_boxes = [] - for state in individual_rss_states: - if state.actor_calculation_mode != ad.rss.map.RssMode.NotRelevant and state.is_dangerous: - other_actor = state.get_actor(world) - if other_actor: - bounding_boxes.append(RssBoundingBoxVisualizer.get_bounding_box( - other_actor, camera_transform, calibration)) - # filter objects behind camera - bounding_boxes = [bb for bb in bounding_boxes if all(bb[:, 2] > 0)] - return bounding_boxes - - @staticmethod - def draw_bounding_boxes(surface, bounding_boxes, color=pygame.Color('red')): - """ - Draws bounding boxes on pygame display. - """ - for bbox in bounding_boxes: - points = [(int(bbox[i, 0]), int(bbox[i, 1])) for i in range(8)] - # draw lines - # base - polygon = [points[0], points[1], points[2], points[3]] - pygame.draw.polygon(surface, color, polygon) - # top - polygon = [points[4], points[5], points[6], points[7]] - pygame.draw.polygon(surface, color, polygon) - # base-top - polygon = [points[0], points[1], points[5], points[4]] - pygame.draw.polygon(surface, color, polygon) - polygon = [points[1], points[2], points[6], points[5]] - pygame.draw.polygon(surface, color, polygon) - polygon = [points[2], points[6], points[7], points[3]] - pygame.draw.polygon(surface, color, polygon) - polygon = [points[0], points[4], points[7], points[3]] - pygame.draw.polygon(surface, color, polygon) - - @staticmethod - def get_bounding_box(vehicle, camera_transform, calibration): - """ - Returns 3D bounding box for a vehicle based on camera view. - """ - - bb_cords = RssBoundingBoxVisualizer._create_bb_points(vehicle) - cords_x_y_z = RssBoundingBoxVisualizer._vehicle_to_sensor(bb_cords, vehicle, camera_transform)[:3, :] - cords_y_minus_z_x = np.concatenate([cords_x_y_z[1, :], -cords_x_y_z[2, :], cords_x_y_z[0, :]]) - bbox = np.transpose(np.dot(calibration, cords_y_minus_z_x)) - camera_bbox = np.concatenate([bbox[:, 0] / bbox[:, 2], bbox[:, 1] / bbox[:, 2], bbox[:, 2]], axis=1) - return camera_bbox - - @staticmethod - def _create_bb_points(vehicle): - """ - Returns 3D bounding box for a vehicle. - """ - - cords = np.zeros((8, 4)) - extent = vehicle.bounding_box.extent - cords[0, :] = np.array([extent.x, extent.y, -extent.z, 1]) - cords[1, :] = np.array([-extent.x, extent.y, -extent.z, 1]) - cords[2, :] = np.array([-extent.x, -extent.y, -extent.z, 1]) - cords[3, :] = np.array([extent.x, -extent.y, -extent.z, 1]) - cords[4, :] = np.array([extent.x, extent.y, extent.z, 1]) - cords[5, :] = np.array([-extent.x, extent.y, extent.z, 1]) - cords[6, :] = np.array([-extent.x, -extent.y, extent.z, 1]) - cords[7, :] = np.array([extent.x, -extent.y, extent.z, 1]) - return cords - - @staticmethod - def _vehicle_to_sensor(cords, vehicle, camera_transform): - """ - Transforms coordinates of a vehicle bounding box to sensor. - """ - - world_cord = RssBoundingBoxVisualizer._vehicle_to_world(cords, vehicle) - sensor_cord = RssBoundingBoxVisualizer._world_to_sensor(world_cord, camera_transform) - return sensor_cord - - @staticmethod - def _vehicle_to_world(cords, vehicle): - """ - Transforms coordinates of a vehicle bounding box to world. - """ - - bb_transform = carla.Transform(vehicle.bounding_box.location) - bb_vehicle_matrix = get_matrix(bb_transform) - vehicle_world_matrix = get_matrix(vehicle.get_transform()) - bb_world_matrix = np.dot(vehicle_world_matrix, bb_vehicle_matrix) - world_cords = np.dot(bb_world_matrix, np.transpose(cords)) - return world_cords - - @staticmethod - def _world_to_sensor(cords, camera_transform): - """ - Transforms world coordinates to sensor. - """ - - sensor_world_matrix = get_matrix(camera_transform) - world_sensor_matrix = np.linalg.inv(sensor_world_matrix) - sensor_cords = np.dot(world_sensor_matrix, cords) - return sensor_cords - -# ============================================================================== -# -- RssDebugVisualizer ------------------------------------------------------------ -# ============================================================================== - - -class RssDebugVisualizationMode(Enum): - Off = 1 - RouteOnly = 2 - VehicleStateOnly = 3 - VehicleStateAndRoute = 4 - All = 5 - - -class RssDebugVisualizer(object): - - def __init__(self, player, world): - self._world = world - self._player = player - self._visualization_mode = RssDebugVisualizationMode.Off - - def toggleMode(self): - if self._visualization_mode == RssDebugVisualizationMode.All: - self._visualization_mode = RssDebugVisualizationMode.Off - elif self._visualization_mode == RssDebugVisualizationMode.Off: - self._visualization_mode = RssDebugVisualizationMode.RouteOnly - elif self._visualization_mode == RssDebugVisualizationMode.RouteOnly: - self._visualization_mode = RssDebugVisualizationMode.VehicleStateOnly - elif self._visualization_mode == RssDebugVisualizationMode.VehicleStateOnly: - self._visualization_mode = RssDebugVisualizationMode.VehicleStateAndRoute - elif self._visualization_mode == RssDebugVisualizationMode.VehicleStateAndRoute: - self._visualization_mode = RssDebugVisualizationMode.All - print("New Debug Visualizer Mode {}".format(self._visualization_mode)) - - def tick(self, route, dangerous, individual_rss_states, ego_dynamics_on_route): - if self._visualization_mode == RssDebugVisualizationMode.RouteOnly or \ - self._visualization_mode == RssDebugVisualizationMode.VehicleStateAndRoute or \ - self._visualization_mode == RssDebugVisualizationMode.All: - self.visualize_route(dangerous, route) - - if self._visualization_mode == RssDebugVisualizationMode.VehicleStateOnly or \ - self._visualization_mode == RssDebugVisualizationMode.VehicleStateAndRoute or \ - self._visualization_mode == RssDebugVisualizationMode.All: - self.visualize_rss_results(individual_rss_states) - - if self._visualization_mode == RssDebugVisualizationMode.All: - self.visualize_ego_dynamics(ego_dynamics_on_route) - - def visualize_route(self, dangerous, route): - if not route: - return - right_lane_edges = dict() - left_lane_edges = dict() - - for road_segment in route.roadSegments: - right_most_lane = road_segment.drivableLaneSegments[0] - if right_most_lane.laneInterval.laneId not in right_lane_edges: - edge = ad.map.route.getRightProjectedENUEdge(right_most_lane.laneInterval) - right_lane_edges[right_most_lane.laneInterval.laneId] = edge - intersection_lane = ad.map.intersection.Intersection.isLanePartOfAnIntersection(right_most_lane.laneInterval.laneId) - - color = carla.Color(r=(128 if dangerous else 255)) - if intersection_lane: - color.b = 128 if dangerous else 255 - color = carla.Color(r=255, g=0, b=255) - self.visualize_enu_edge(edge, color, self._player.get_location().z) - - left_most_lane = road_segment.drivableLaneSegments[-1] - if left_most_lane.laneInterval.laneId not in left_lane_edges: - edge = ad.map.route.getLeftProjectedENUEdge(left_most_lane.laneInterval) - left_lane_edges[left_most_lane.laneInterval.laneId] = edge - intersection_lane = ad.map.intersection.Intersection.isLanePartOfAnIntersection(left_most_lane.laneInterval.laneId) - color = carla.Color(g=(128 if dangerous else 255)) - if intersection_lane: - color.b = 128 if dangerous else 255 - - self.visualize_enu_edge(edge, color, self._player.get_location().z) - - def visualize_enu_edge(self, edge, color, z_offset): - for point in edge: - carla_point = carla.Location(x=float(point.x), y=-1. * float(point.y), z=float(point.z) + z_offset) - self._world.debug.draw_point(carla_point, 0.1, color, 0.1, False) - - def visualize_rss_results(self, state_snapshot): - for state in state_snapshot: - other_actor = state.get_actor(self._world) - if not other_actor: - # print("Actor not found. Skip visualizing state {}".format(state)) - continue - ego_point = self._player.get_location() - ego_point.z += 0.05 - yaw = self._player.get_transform().rotation.yaw - cosine = math.cos(math.radians(yaw)) - sine = math.sin(math.radians(yaw)) - line_offset = carla.Location(-sine * 0.1, cosine * 0.1, 0.0) - - point = other_actor.get_location() - point.z += 0.05 - indicator_color = carla.Color(0, 255, 0) - dangerous = ad.rss.state.isDangerous(state.rss_state) - if dangerous: - indicator_color = carla.Color(255, 0, 0) - elif state.rss_state.situationType == ad.rss.situation.SituationType.NotRelevant: - indicator_color = carla.Color(150, 150, 150) - - if self._visualization_mode == RssDebugVisualizationMode.All: - # the connection lines are only visualized if All is requested - lon_color = indicator_color - lat_l_color = indicator_color - lat_r_color = indicator_color - if not state.rss_state.longitudinalState.isSafe: - lon_color.r = 255 - lon_color.g = 0 if dangerous else 255 - if not state.rss_state.lateralStateLeft.isSafe: - lat_l_color.r = 255 - lat_l_color.g = 0 if dangerous else 255 - if not state.rss_state.lateralStateRight.isSafe: - lat_r_color.r = 255 - lat_r_color.g = 0 if dangerous else 255 - self._world.debug.draw_line(ego_point, point, 0.1, lon_color, 0.02, False) - self._world.debug.draw_line(ego_point - line_offset, point - - line_offset, 0.1, lat_l_color, 0.02, False) - self._world.debug.draw_line(ego_point + line_offset, point + - line_offset, 0.1, lat_r_color, 0.02, False) - point.z += 3. - self._world.debug.draw_point(point, 0.2, indicator_color, 0.02, False) - - def visualize_ego_dynamics(self, ego_dynamics_on_route): - color = carla.Color(0, 0, 255) - - sin_heading = math.sin(float(ego_dynamics_on_route.route_heading)) - cos_heading = math.cos(float(ego_dynamics_on_route.route_heading)) - - heading_location_start = self._player.get_location() - heading_location_start.x -= cos_heading * 10. - heading_location_start.y += sin_heading * 10. - heading_location_start.z += 0.5 - heading_location_end = self._player.get_location() - heading_location_end.x += cos_heading * 10. - heading_location_end.y -= sin_heading * 10. - heading_location_end.z += 0.5 - - self._world.debug.draw_arrow(heading_location_start, heading_location_end, 0.1, 0.1, color, 0.02, False) - - sin_center = math.sin(float(ego_dynamics_on_route.route_heading) + math.pi / 2.) - cos_center = math.cos(float(ego_dynamics_on_route.route_heading) + math.pi / 2.) - center_location_start = self._player.get_location() - center_location_start.x -= cos_center * 2. - center_location_start.y += sin_center * 2. - center_location_start.z += 0.5 - center_location_end = self._player.get_location() - center_location_end.x += cos_center * 2. - center_location_end.y -= sin_center * 2. - center_location_end.z += 0.5 - - self._world.debug.draw_line(center_location_start, center_location_end, 0.1, color, 0.02, False) diff --git a/PythonAPI/examples/rss/scenarios/unstructured_blocked_road.xosc b/PythonAPI/examples/rss/scenarios/unstructured_blocked_road.xosc deleted file mode 100644 index 81556ba5b7d..00000000000 --- a/PythonAPI/examples/rss/scenarios/unstructured_blocked_road.xosc +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/PythonAPI/examples/rss/scenarios/unstructured_pedestrian_on_road.xosc b/PythonAPI/examples/rss/scenarios/unstructured_pedestrian_on_road.xosc deleted file mode 100644 index b8dbb2a1d20..00000000000 --- a/PythonAPI/examples/rss/scenarios/unstructured_pedestrian_on_road.xosc +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/PythonAPI/examples/vehicle_physics.py b/PythonAPI/examples/vehicle_physics.py index af1b23bf63a..059c53fc7c4 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 application methods to a vehicle. """ diff --git a/README.md b/README.md index 72f85a537dd..212c1eb04a0 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,14 @@ CARLA Simulator =============== -[![Documentation](https://readthedocs.org/projects/carla/badge/?version=latest)](http://carla.readthedocs.io) +[![Documentation](https://readthedocs.org/projects/carla/badge/?version=latest)](http://carla.readthedocs.io) [![carla.org](Docs/img/btn/web.png)](http://carla.org) [![download](Docs/img/btn/download.png)](https://github.com/carla-simulator/carla/blob/master/Docs/download.md) [![documentation](Docs/img/btn/docs.png)](http://carla.readthedocs.io) [![forum](Docs/img/btn/forum.png)](https://github.com/carla-simulator/carla/discussions) [![discord](Docs/img/btn/chat.png)](https://discord.gg/8kqACuC) +[![Gurubase](https://img.shields.io/badge/Gurubase-Ask%20CARLA%20Simulator%20Guru-006BFF)](https://gurubase.io/g/carla-simulator) CARLA is an open-source simulator for autonomous driving research. CARLA has been developed from the ground up to support development, training, and validation of autonomous driving systems. In addition to open-source code and protocols, CARLA provides open digital assets (urban layouts, buildings, @@ -16,6 +17,9 @@ environmental conditions. [![CARLA Video](Docs/img/0_9_15_thumbnail.webp)](https://www.youtube.com/watch?v=q4V9GYjA1pE ) +>[!NOTE] +>This is the development branch `ue4-dev` for the **Unreal Engine 4.26 version of CARLA**. This branch exists in parallel with the Unreal Engine 5.3 version of CARLA, in the `ue5-dev` branch. Please be sure that this version of CARLA is suitable for your needs as there are significant differences between the UE 4.26 and UE 5.3 versions of CARLA. + ### Download CARLA Linux: @@ -26,6 +30,9 @@ Windows: * [**Get CARLA overnight build**](https://tiny.carla.org/carla-latest-windows) * [**Get AdditionalMaps overnight build**](https://tiny.carla.org/additional-maps-latest-windows) +>[!WARNING] +>The CARLA package downloads are now provided using the BackBlaze CDN. The Amazon Web Service download links have been discontinued. Please ensure you update any relevant information in repositories using the CARLA simulator package versions. + ### Recommended system * Intel i7 gen 9th - 11th / Intel i9 gen 9th - 11th / AMD ryzen 7 / AMD ryzen 9 @@ -125,8 +132,6 @@ CARLA specific assets are distributed under CC-BY License. #### CARLA Dependency and Integration licenses -The ad-rss-lib library compiled and linked by the [RSS Integration build variant](Docs/adv_rss.md) introduces [LGPL-2.1-only License](https://opensource.org/licenses/LGPL-2.1). - Unreal Engine 4 follows its [own license terms](https://www.unrealengine.com/en-US/faq). CARLA uses three dependencies as part of the SUMO integration: diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorDispatcher.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorDispatcher.cpp index 74913060213..b4ddd32668c 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorDispatcher.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Actor/ActorDispatcher.cpp @@ -77,7 +77,7 @@ TPair UActorDispatcher::SpawnActor( } else { - ATagger::TagActor(*View->GetActor(), true); + ATagger::TagActor(*View->GetActor(), true, View->GetActorId()); } return MakeTuple(Result.Status, View); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Carla.Build.cs b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Carla.Build.cs index da9727d1e3f..b8a2fc2e874 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Carla.Build.cs +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Carla.Build.cs @@ -4,25 +4,17 @@ using System.IO; using UnrealBuildTool; -public class Carla : ModuleRules + +public class Carla : CarlaRules { bool UsingCarSim = false; bool UsingChrono = false; bool UsingPytorch = false; - bool UsingRos2 = false; - private bool IsWindows(ReadOnlyTargetRules Target) - { - return (Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32); - } - - public Carla(ReadOnlyTargetRules Target) : base(Target) + public Carla(ReadOnlyTargetRules Target) : base(Target, "../../CarlaDependencies") { PrivatePCHHeaderFile = "Carla.h"; - - if (IsWindows(Target)) - { - bEnableExceptions = true; - } + bEnableExceptions = true; + CppStandard = CppStandardVersion.Cpp20; // Read config about carsim string CarlaPluginPath = Path.GetFullPath( ModuleDirectory ); @@ -57,8 +49,12 @@ public Carla(ReadOnlyTargetRules Target) : base(Target) { Console.WriteLine("Enabling ros2"); UsingRos2 = true; - PublicDefinitions.Add("WITH_ROS2"); - PrivateDefinitions.Add("WITH_ROS2"); + } + + if (line.Contains("Debug ON")) + { + Console.WriteLine("Enabling debug build"); + Debug = true; } } @@ -91,10 +87,10 @@ public Carla(ReadOnlyTargetRules Target) : base(Target) PublicDependencyModuleNames.AddRange(new string[] { "CarSim" }); } - if (Target.Type == TargetType.Editor) - { - PublicDependencyModuleNames.AddRange(new string[] { "UnrealEd" }); - } + if (Target.Type == TargetType.Editor) + { + PublicDependencyModuleNames.AddRange(new string[] { "UnrealEd" }); + } PrivateDependencyModuleNames.AddRange( new string[] @@ -118,229 +114,143 @@ public Carla(ReadOnlyTargetRules Target) : base(Target) "PhysicsCore" // ... add private dependencies that you statically link with here ... } - ); + ); + if (UsingCarSim) { PrivateDependencyModuleNames.AddRange(new string[] { "CarSim" }); PrivateIncludePathModuleNames.AddRange(new string[] { "CarSim" }); } - DynamicallyLoadedModuleNames.AddRange( new string[] { // ... add any modules that your module loads dynamically here ... } - ); + ); - AddCarlaServerDependency(Target); + AddCarlaServerDependency(); } - private bool UseDebugLibs(ReadOnlyTargetRules Target) + private void AddCarlaServerDependency() { - if (IsWindows(Target)) + + // Link dependencies. + AddStaticLibrary( "rpc"); + if (UseDebugLibs()) { - // In Windows, Unreal uses the Release C++ Runtime (CRT) even in debug - // mode, so unless we recompile the engine we cannot link the debug - // libraries. - return false; + AddStaticLibrary("carla_server_debug"); } else { - return false; + AddStaticLibrary("carla_server"); } - } - - private void AddDynamicLibrary(string library) - { - PublicAdditionalLibraries.Add(library); - RuntimeDependencies.Add(library); - PublicDelayLoadDLLs.Add(library); - } - private void AddDllDependency(string PathToFolder, string DllName) - { - string Source = Path.Combine(PathToFolder, DllName); - string Destination = Path.Combine("$(BinaryOutputDir)", DllName); - RuntimeDependencies.Add(Destination, Source); - } - - delegate string ADelegate(string s); - - private void AddBoostLibs(string LibPath) - { - string [] files = Directory.GetFiles(LibPath, "*boost*.lib"); - foreach (string file in files) PublicAdditionalLibraries.Add(file); - } - - private void AddCarlaServerDependency(ReadOnlyTargetRules Target) - { - string LibCarlaInstallPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "../../CarlaDependencies")); - - ADelegate GetLibName = (string BaseName) => { - if (IsWindows(Target)) - { - return BaseName + ".lib"; - } - else - { - return "lib" + BaseName + ".a"; - } - }; - - // Link dependencies. - if (IsWindows(Target)) + if (IsWindows()) { - AddBoostLibs(Path.Combine(LibCarlaInstallPath, "lib")); - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("rpc"))); + PublicAdditionalLibraries.Add("shlwapi.lib"); - if (UseDebugLibs(Target)) - { - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("carla_server_debug"))); - } - else - { - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("carla_server"))); - } + AddBoostLibs(); if (UsingChrono) { - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("ChronoEngine"))); - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("ChronoEngine_vehicle"))); - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("ChronoModels_vehicle"))); - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("ChronoModels_robot"))); + AddStaticLibrary("ChronoEngine"); + AddStaticLibrary("ChronoEngine_vehicle"); + AddStaticLibrary("ChronoModels_vehicle"); + AddStaticLibrary("ChronoModels_robot"); AddDllDependency(Path.Combine(LibCarlaInstallPath, "dll"), "ChronoEngine.dll"); AddDllDependency(Path.Combine(LibCarlaInstallPath, "dll"), "ChronoEngine_vehicle.dll"); AddDllDependency(Path.Combine(LibCarlaInstallPath, "dll"), "ChronoModels_vehicle.dll"); AddDllDependency(Path.Combine(LibCarlaInstallPath, "dll"), "ChronoModels_robot.dll"); bUseRTTI = true; } - - //OsmToODR - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", "sqlite3.lib")); - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", "xerces-c_3.lib")); - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", "proj.lib")); - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", "osm2odr.lib")); - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", "zlibstatic.lib")); } else { - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("rpc"))); - if (UseDebugLibs(Target)) - { - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("carla_server_debug"))); - } - else - { - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("carla_server"))); - } if (UsingChrono) { - AddDynamicLibrary(Path.Combine(LibCarlaInstallPath, "lib", "libChronoEngine.so")); - AddDynamicLibrary(Path.Combine(LibCarlaInstallPath, "lib", "libChronoEngine_vehicle.so")); - AddDynamicLibrary(Path.Combine(LibCarlaInstallPath, "lib", "libChronoModels_vehicle.so")); - AddDynamicLibrary(Path.Combine(LibCarlaInstallPath, "lib", "libChronoModels_robot.so")); + AddStaticLibrary( "ChronoEngine"); + AddStaticLibrary( "ChronoEngine_vehicle"); + AddStaticLibrary( "ChronoModels_vehicle"); + AddStaticLibrary( "ChronoModels_robot"); bUseRTTI = true; } if (UsingPytorch) { - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("carla_pytorch"))); - - string LibTorchPath = LibCarlaInstallPath; - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libonnx_proto.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libfbgemm.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libgloo.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libXNNPACK.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libprotobuf-lite.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libprotobuf.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libasmjit.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libcpuinfo_internals.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libclog.a")); - // PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libbreakpad_common.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libbenchmark.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libtensorpipe.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libpytorch_qnnpack.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libtensorpipe_cuda.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libnnpack_reference_layers.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libgmock.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libdnnl.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libpthreadpool.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libcpuinfo.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libqnnpack.a")); - // PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libbreakpad.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libkineto.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libprotoc.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libgtest.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libgmock_main.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libgtest_main.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libbenchmark_main.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libfmt.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libtensorpipe_uv.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libfoxi_loader.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libgloo_cuda.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libnnpack.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libcaffe2_protos.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibTorchPath, "lib", "libonnx.a")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libtorch.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libnnapi_backend.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libbackend_with_compiler.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libcaffe2_nvrtc.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libtorch_cuda_cpp.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libc10_cuda.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libtorchbind_test.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libjitbackend_test.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libc10.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libtorch_cuda.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libtorch_global_deps.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libtorch_cpu.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libshm.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libtorch_cuda_cu.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libtorchscatter.so")); - AddDynamicLibrary(Path.Combine(LibTorchPath, "lib", "libtorchcluster.so")); - // AddDynamicLibrary("/usr/local/cuda/lib64/stubs/libcuda.so"); - // AddDynamicLibrary("/usr/local/cuda/lib64/libnvrtc.so"); - // AddDynamicLibrary("/usr/local/cuda/lib64/libnvToolsExt.so"); - // AddDynamicLibrary("/usr/local/cuda/lib64/libcudart.so"); - // AddDynamicLibrary("/usr/lib/llvm-10/lib/libgomp.so"); - PublicAdditionalLibraries.Add("/usr/local/cuda/lib64/stubs/libcuda.so"); - PublicAdditionalLibraries.Add("/usr/local/cuda/lib64/libnvrtc.so"); - PublicAdditionalLibraries.Add("/usr/local/cuda/lib64/libnvToolsExt.so"); - PublicAdditionalLibraries.Add("/usr/local/cuda/lib64/libcudart.so"); - PublicAdditionalLibraries.Add("/usr/lib/llvm-10/lib/libgomp.so"); - RuntimeDependencies.Add(Path.Combine(LibTorchPath, "lib", "libcudart-a7b20f20.so.11.0")); - RuntimeDependencies.Add(Path.Combine(LibTorchPath, "lib", "libgomp-a34b3233.so.1")); - RuntimeDependencies.Add(Path.Combine(LibTorchPath, "lib", "libnvrtc-builtins-4730a239.so.11.3")); - RuntimeDependencies.Add(Path.Combine(LibTorchPath, "lib", "libnvrtc-1ea278b5.so.11.2")); - RuntimeDependencies.Add(Path.Combine(LibTorchPath, "lib", "libnvToolsExt-24de1d56.so.1")); + AddStaticLibrary( "carla_pytorch"); + + AddStaticLibrary("onnx_proto"); + AddStaticLibrary("fbgemm"); + AddStaticLibrary("gloo"); + AddStaticLibrary("XNNPACK"); + AddStaticLibrary("protobuf-lite"); + AddStaticLibrary("protobuf"); + AddStaticLibrary("asmjit"); + AddStaticLibrary("cpuinfo_internals"); + AddStaticLibrary("clog"); + // AddStaticLibrary("breakpad_common"); + AddStaticLibrary("benchmark"); + AddStaticLibrary("tensorpipe"); + AddStaticLibrary("pytorch_qnnpack"); + AddStaticLibrary("tensorpipe_cuda"); + AddStaticLibrary("nnpack_reference_layers"); + AddStaticLibrary("gmock"); + AddStaticLibrary("dnnl"); + AddStaticLibrary("pthreadpool"); + AddStaticLibrary("cpuinfo"); + AddStaticLibrary("qnnpack"); + // AddStaticLibrary("breakpad")); + AddStaticLibrary("kineto"); + AddStaticLibrary("protoc"); + AddStaticLibrary("gtest"); + AddStaticLibrary("gmock_main"); + AddStaticLibrary("gtest_main"); + AddStaticLibrary("benchmark_main"); + AddStaticLibrary("fmt"); + AddStaticLibrary("tensorpipe_uv"); + AddStaticLibrary("foxi_loader"); + AddStaticLibrary("gloo_cuda"); + AddStaticLibrary("nnpack"); + AddStaticLibrary("caffe2_protos"); + AddStaticLibrary("onnx"); + AddDynamicLibrary("torch"); + AddDynamicLibrary("nnapi_backend"); + AddDynamicLibrary("backend_with_compiler"); + AddDynamicLibrary("caffe2_nvrtc"); + AddDynamicLibrary("torch_cuda_cpp"); + AddDynamicLibrary("c10_cuda"); + AddDynamicLibrary("torchbind_test"); + AddDynamicLibrary("jitbackend_test"); + AddDynamicLibrary("c10"); + AddDynamicLibrary("torch_cuda"); + AddDynamicLibrary("torch_global_deps"); + AddDynamicLibrary("torch_cpu"); + AddDynamicLibrary("shm"); + AddDynamicLibrary("torch_cuda_cu"); + AddDynamicLibrary("torchscatter"); + AddDynamicLibrary("torchcluster"); + AddDynamicLibrary("cuda", "/usr/local/cuda/lib64/stubs"); + AddDynamicLibrary("nvrtc", "/usr/local/cuda/lib64"); + AddDynamicLibrary("nvToolsExt", "/usr/local/cuda/lib64"); + AddDynamicLibrary("cudart", "/usr/local/cuda/lib64"); + AddDynamicLibrary("gomp", "/usr/lib/llvm-10/lib"); + RuntimeDependencies.Add(Path.Combine("libcudart-a7b20f20.so.11.0")); + RuntimeDependencies.Add(Path.Combine("libgomp-a34b3233.so.1")); + RuntimeDependencies.Add(Path.Combine("libnvrtc-builtins-4730a239.so.11.3")); + RuntimeDependencies.Add(Path.Combine("libnvrtc-1ea278b5.so.11.2")); + RuntimeDependencies.Add(Path.Combine("libnvToolsExt-24de1d56.so.1")); PublicAdditionalLibraries.Add("stdc++"); PublicAdditionalLibraries.Add("/usr/lib/x86_64-linux-gnu/libpython3.9.so"); } + } - if (UsingRos2) - { - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("carla_fastdds"))); - - string LibFastDDSPath = LibCarlaInstallPath; - AddDynamicLibrary(Path.Combine(LibFastDDSPath, "lib", "libfoonathan_memory-0.7.3.so")); - AddDynamicLibrary(Path.Combine(LibFastDDSPath, "lib", "libfastcdr.so")); - AddDynamicLibrary(Path.Combine(LibFastDDSPath, "lib", "libfastrtps.so")); - PublicAdditionalLibraries.Add("stdc++"); - } - + addOsmToODR(); - //OsmToODR - PublicAdditionalLibraries.Add("/usr/lib/x86_64-linux-gnu/libc.so"); - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", "libsqlite3.so")); - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", "libxerces-c.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", "libproj.a")); - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", "libosm2odr.a")); + addROS2(); - } - bEnableExceptions = true; // Include path. string LibCarlaIncludePath = Path.Combine(LibCarlaInstallPath, "include"); - PublicIncludePaths.Add(LibCarlaIncludePath); PrivateIncludePaths.Add(LibCarlaIncludePath); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/CarlaRules.Build.cs b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/CarlaRules.Build.cs new file mode 100644 index 00000000000..4a4206a67aa --- /dev/null +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/CarlaRules.Build.cs @@ -0,0 +1,179 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +using System; +using System.IO; +using UnrealBuildTool; + +public class CarlaRules : ModuleRules +{ + protected string LibCarlaInstallPath; + protected bool UsingRos2 = false; + protected bool Debug = false; + + public CarlaRules(ReadOnlyTargetRules Target, string LibCarlaInstallPathRelativeToModule) : base(Target) + { + LibCarlaInstallPath = Path.GetFullPath(Path.Combine(ModuleDirectory, LibCarlaInstallPathRelativeToModule)); + } + + protected bool IsWindows() + { + return (Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32); + } + + protected bool IsLinux() + { + return (Target.Platform == UnrealTargetPlatform.Linux) || (Target.Platform == UnrealTargetPlatform.LinuxAArch64); + } + + protected bool IsMac() + { + return (Target.Platform == UnrealTargetPlatform.Mac); + } + + protected bool UseDebugLibs() + { + if (IsWindows()) + { + // In Windows, Unreal uses the Release C++ Runtime (CRT) even in debug + // mode, so unless we recompile the engine we cannot link the debug + // libraries. + return false; + } + else + { + return Debug; + } + } + + protected void AddDllDependency(string PathToFolder, string DllName) + { + string Source = Path.Combine(PathToFolder, DllName); + string Destination = Path.Combine("$(BinaryOutputDir)", DllName); + RuntimeDependencies.Add(Destination, Source); + } + + protected void AddBoostLibs() + { + string [] files = Directory.GetFiles(Path.Combine(LibCarlaInstallPath, "lib"), "*boost*.lib"); + foreach (string file in files) PublicAdditionalLibraries.Add(file); + } + + protected void AddStaticLibrary(string LibBaseName, string LinkBasePath = "", string LibPrefix = "", string LibPostfix = "") { + string linkBasePath = LinkBasePath; + if ( linkBasePath == "" ) + { + linkBasePath = Path.GetFullPath(Path.Combine(LibCarlaInstallPath, "lib")); + } + + string libPrefix = LibPrefix; + if ( libPrefix == "" ) + { + if (IsWindows()) + { + libPrefix = ""; + } + else + { + libPrefix = "lib"; + } + } + + string libPostfix = LibPostfix; + if ( libPostfix == "" ) + { + if (IsWindows()) + { + libPostfix = ".lib"; + } + else + { + libPostfix = ".a"; + } + } + + string linkLibrary= Path.Combine(linkBasePath, libPrefix + LibBaseName + libPostfix); + PublicAdditionalLibraries.Add(linkLibrary); + } + protected void AddDynamicLibrary(string LibBaseName, string LinkBasePath = "", string LibPrefix = "", string LibPostfix = "") + { + string linkBasePath = LinkBasePath; + if ( linkBasePath == "" ) + { + linkBasePath = Path.GetFullPath(Path.Combine(LibCarlaInstallPath, "lib")); + } + + string libPrefix; + if (IsWindows()) + { + libPrefix = ""; + } + else + { + libPrefix = "lib"; + } + if ( LibPrefix != "" ) + { + libPrefix = LibPrefix; + } + + string libPostfix; + if (IsWindows()) + { + libPostfix = ".dll"; + } + else + { + libPostfix = ".so"; + } + if (LibPostfix != "") + { + libPostfix = LibPostfix; + } + + string linkLibrary= Path.Combine(linkBasePath, libPrefix + LibBaseName + libPostfix); + PublicAdditionalLibraries.Add(linkLibrary); + RuntimeDependencies.Add(linkLibrary); + if ( IsWindows() ) + { + PublicDelayLoadDLLs.Add(linkLibrary); + } + } + + protected void addOsmToODR() + { + AddStaticLibrary( "sqlite3"); + AddStaticLibrary( "proj"); + AddStaticLibrary( "osm2odr"); + if ( IsWindows() ) + { + AddStaticLibrary( "xerces-c_3"); + AddStaticLibrary( "zlibstatic"); + } + else + { + AddStaticLibrary( "xerces-c"); + } + } + + protected void addROS2() + { + if (UsingRos2) + { + AddStaticLibrary( "foonathan_memory-0.7.3"); + if ( IsWindows() ) + { + AddStaticLibrary( "libfastcdr-1.1"); + AddStaticLibrary( "libfastrtps-2.11"); + } + else + { + AddStaticLibrary( "fastcdr"); + AddStaticLibrary( "fastrtps"); + } + PublicIncludePaths.Add(Path.Combine(LibCarlaInstallPath, "include", "carla", "ros2", "ros_types")); + PrivateIncludePaths.Add(Path.Combine(LibCarlaInstallPath, "include", "carla", "ros2", "ros_types")); + PublicDefinitions.Add("WITH_ROS2"); + PrivateDefinitions.Add("WITH_ROS2"); + } + } +} diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp index 332b8ad076f..2e8fc3f3123 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp @@ -184,11 +184,6 @@ void ACarlaGameModeBase::BeginPlay() LoadMapLayer(GameInstance->GetCurrentMapLayer()); ReadyToRegisterObjects = true; - if (true) { /// @todo If semantic segmentation enabled. - ATagger::TagActorsInLevel(*World, true); - TaggerDelegate->SetSemanticSegmentationEnabled(); - } - // HACK: fix transparency see-through issues // The problem: transparent objects are visible through walls. // This is due to a weird interaction between the SkyAtmosphere component, @@ -205,6 +200,11 @@ void ACarlaGameModeBase::BeginPlay() Episode->InitializeAtBeginPlay(); GameInstance->NotifyBeginEpisode(*Episode); + if (true) { /// @todo If semantic segmentation enabled. + ATagger::TagActorsInLevel(*World, *Episode, true); + TaggerDelegate->SetSemanticSegmentationEnabled(); + } + if (Episode->Weather != nullptr) { Episode->Weather->ApplyWeather(carla::rpc::WeatherParameters::Default); @@ -630,10 +630,10 @@ TArray ACarlaGameModeBase::GetAllBBsOfLevel(uint8 TagQueried) cons UGameplayStatics::GetAllActorsOfClass(World, AActor::StaticClass(), FoundActors); TArray BoundingBoxes; - BoundingBoxes = UBoundingBoxCalculator::GetBoundingBoxOfActors(FoundActors, TagQueried); + BoundingBoxes = UBoundingBoxCalculator::GetBoundingBoxOfActors(FoundActors, &GetCarlaEpisode(), TagQueried); return BoundingBoxes; -} + } void ACarlaGameModeBase::RegisterEnvironmentObjects() { @@ -773,7 +773,7 @@ void ACarlaGameModeBase::OnLoadStreamLevel() if(ReadyToRegisterObjects && PendingLevelsToLoad == 0) { RegisterEnvironmentObjects(); - ATagger::TagActorsInLevel(*GetWorld(), true); + ATagger::TagActorsInLevel(*GetWorld(), *Episode, true); } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp index 45b9d6f357f..90d6bbbd372 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.cpp @@ -8,6 +8,8 @@ #include "Tagger.h" #include "TaggedComponent.h" #include "Vehicle/CarlaWheeledVehicle.h" +#include "Carla/Game/CarlaEpisode.h" +#include "Carla/Actor/CarlaActor.h" #include "Components/SkeletalMeshComponent.h" #include "Components/StaticMeshComponent.h" @@ -80,17 +82,16 @@ bool ATagger::IsThing(const crp::CityObjectLabel &Label) Label == crp::CityObjectLabel::TrafficLight); } -FLinearColor ATagger::GetActorLabelColor(const AActor &Actor, const crp::CityObjectLabel &Label) +FLinearColor ATagger::GetLabelColor(const uint32_t ActorID, const crp::CityObjectLabel &Label) { - uint32 id = Actor.GetUniqueID(); // TODO: Warn if id > 0xffff. // Encode label and id like semantic segmentation does // TODO: Steal bits from R channel and maybe A channel? FLinearColor Color(0.0f, 0.0f, 0.0f, 1.0f); Color.R = CastEnum(Label) / 255.0f; - Color.G = ((id & 0x00ff) >> 0) / 255.0f; - Color.B = ((id & 0xff00) >> 8) / 255.0f; + Color.G = ((ActorID & 0x000000ff) >> 0) / 255.0f; + Color.B = ((ActorID & 0x0000ff00) >> 8) / 255.0f; return Color; } @@ -100,10 +101,10 @@ FLinearColor ATagger::GetActorLabelColor(const AActor &Actor, const crp::CityObj // -- static ATagger functions ------------------------------------------------- // ============================================================================= -void ATagger::TagActor(const AActor &Actor, bool bTagForSemanticSegmentation) +void ATagger::TagActor(const AActor &Actor, bool bTagForSemanticSegmentation, uint32_t ActorID) { #ifdef CARLA_TAGGER_EXTRA_LOG - UE_LOG(LogCarla, Log, TEXT("Actor: %s"), *Actor.GetName()); + UE_LOG(LogCarla, Log, TEXT("Actor: %s %d %d"), *Actor.GetName(), Actor.GetUniqueID(), ActorID); #endif // CARLA_TAGGER_EXTRA_LOG // Iterate static meshes. @@ -152,7 +153,7 @@ void ATagger::TagActor(const AActor &Actor, bool bTagForSemanticSegmentation) } // Set tagged component color - FLinearColor Color = GetActorLabelColor(Actor, Label); + FLinearColor Color = GetLabelColor(ActorID, Label); #ifdef CARLA_TAGGER_EXTRA_LOG UE_LOG(LogCarla, Log, TEXT(" - Color: %s"), *Color.ToString()); #endif // CARLA_TAGGER_EXTRA_LOG @@ -207,7 +208,7 @@ void ATagger::TagActor(const AActor &Actor, bool bTagForSemanticSegmentation) } // Set tagged component color - FLinearColor Color = GetActorLabelColor(Actor, Label); + FLinearColor Color = GetLabelColor(ActorID, Label); #ifdef CARLA_TAGGER_EXTRA_LOG UE_LOG(LogCarla, Log, TEXT(" - Color: %s"), *Color.ToString()); #endif // CARLA_TAGGER_EXTRA_LOG @@ -219,17 +220,34 @@ void ATagger::TagActor(const AActor &Actor, bool bTagForSemanticSegmentation) } } +void ATagger::TagActorsInLevel(UWorld &World, const UCarlaEpisode &Episode, bool bTagForSemanticSegmentation) +{ + for (TActorIterator it(&World); it; ++it) { + uint32_t cActorId = (*it)->GetUniqueID(); + FCarlaActor* cActor = Episode.FindCarlaActor(*it); + if (cActor) { + cActorId = cActor->GetActorId(); + } + TagActor(**it, bTagForSemanticSegmentation, cActorId); + } +} + void ATagger::TagActorsInLevel(UWorld &World, bool bTagForSemanticSegmentation) { for (TActorIterator it(&World); it; ++it) { - TagActor(**it, bTagForSemanticSegmentation); + TagActor(**it, bTagForSemanticSegmentation, (*it)->GetUniqueID()); } } -void ATagger::TagActorsInLevel(ULevel &Level, bool bTagForSemanticSegmentation) +void ATagger::TagActorsInLevel(ULevel &Level, const UCarlaEpisode &Episode, bool bTagForSemanticSegmentation) { for (AActor * Actor : Level.Actors) { - TagActor(*Actor, bTagForSemanticSegmentation); + uint32_t cActorId = Actor->GetUniqueID(); + FCarlaActor* cActor = Episode.FindCarlaActor(Actor); + if (cActor) { + cActorId = cActor->GetActorId(); + } + TagActor(*Actor, bTagForSemanticSegmentation, cActorId); } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h index 049f90ef054..5c7d504b60e 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/Tagger.h @@ -17,6 +17,8 @@ namespace crp = carla::rpc; +class UCarlaEpisode; + /// Sets actors' custom depth stencil value for semantic segmentation according /// to their meshes. /// @@ -35,7 +37,7 @@ class CARLA_API ATagger : public AActor /// pass is necessary for rendering the semantic segmentation. However, it may /// add a performance penalty since occlusion doesn't seem to be applied to /// objects having this value active. - static void TagActor(const AActor &Actor, bool bTagForSemanticSegmentation); + static void TagActor(const AActor &Actor, bool bTagForSemanticSegmentation, uint32_t ActorId); /// Set the tag of every actor in level. @@ -44,9 +46,10 @@ class CARLA_API ATagger : public AActor /// pass is necessary for rendering the semantic segmentation. However, it may /// add a performance penalty since occlusion doesn't seem to be applied to /// objects having this value active. + static void TagActorsInLevel(UWorld &World, const UCarlaEpisode &Episode, bool bTagForSemanticSegmentation); static void TagActorsInLevel(UWorld &World, bool bTagForSemanticSegmentation); - static void TagActorsInLevel(ULevel &Level, bool bTagForSemanticSegmentation); + static void TagActorsInLevel(ULevel &Level, const UCarlaEpisode &Episode, bool bTagForSemanticSegmentation); /// Retrieve the tag of an already tagged component. static crp::CityObjectLabel GetTagOfTaggedComponent(const UPrimitiveComponent &Component) @@ -84,7 +87,7 @@ class CARLA_API ATagger : public AActor static void SetStencilValue(UPrimitiveComponent &Component, const crp::CityObjectLabel &Label, const bool bSetRenderCustomDepth); - static FLinearColor GetActorLabelColor(const AActor &Actor, const crp::CityObjectLabel &Label); + static FLinearColor GetLabelColor(const uint32_t ActorID, const crp::CityObjectLabel &Label); static bool IsThing(const crp::CityObjectLabel &Label); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/TaggerDelegate.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/TaggerDelegate.cpp index bfbc906f34b..795a0a58d5a 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/TaggerDelegate.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/TaggerDelegate.cpp @@ -22,6 +22,6 @@ void UTaggerDelegate::RegisterSpawnHandler(UWorld *InWorld) void UTaggerDelegate::OnActorSpawned(AActor* InActor) { if (InActor != nullptr) { - ATagger::TagActor(*InActor, bSemanticSegmentationEnabled); + ATagger::TagActor(*InActor, bSemanticSegmentationEnabled, InActor->GetUniqueID()); } } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/LargeMapManager.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/LargeMapManager.cpp index 71ba50d0876..4eb2717a619 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/LargeMapManager.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/LargeMapManager.cpp @@ -137,7 +137,8 @@ void ALargeMapManager::PostWorldOriginOffset(UWorld* InWorld, FIntVector InSrcOr void ALargeMapManager::OnLevelAddedToWorld(ULevel* InLevel, UWorld* InWorld) { LM_LOG(Warning, "OnLevelAddedToWorld"); - ATagger::TagActorsInLevel(*InLevel, true); + UCarlaEpisode* CarlaEpisode = UCarlaStatics::GetCurrentEpisode(InWorld); + ATagger::TagActorsInLevel(*InLevel, *CarlaEpisode, true); //FDebug::DumpStackTraceToLog(ELogVerbosity::Log); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp index 215780a270c..36144fa0d09 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Server/CarlaServer.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -1343,6 +1344,23 @@ BIND_SYNC(is_sensor_enabled_for_ros) << [this](carla::streaming::detail::stream_ return R::Success(); }; + BIND_SYNC(get_actor_bounding_box) << [this]( + cr::ActorId ActorId) -> R + { + REQUIRE_CARLA_EPISODE(); + FCarlaActor* CarlaActor = Episode->FindCarlaActor(ActorId); + if (!CarlaActor) + { + return RespondError( + "get_actor_bounding_box", + ECarlaServerResponse::ActorNotFound, + " Actor Id: " + FString::FromInt(ActorId)); + } + FBoundingBox bounding_box = UBoundingBoxCalculator::GetActorBoundingBox(CarlaActor->GetActor(), 0); + bounding_box.ActorId = CarlaActor->GetActorId(); + return cr::BoundingBox(bounding_box); + }; + BIND_SYNC(get_actor_component_world_transform) << [this]( cr::ActorId ActorId, const std::string componentName) -> R diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBox.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBox.h index 5fa68707144..6109d8de293 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBox.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBox.h @@ -24,4 +24,6 @@ struct CARLA_API FBoundingBox /// Rotation of the bounding box. UPROPERTY(EditAnywhere, BlueprintReadWrite) FRotator Rotation = {0.0f, 0.0f, 0.0f}; + + uint32_t ActorId = 0; }; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp index cdf29ca8cd9..f9f0ad9d556 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.cpp @@ -407,12 +407,21 @@ void UBoundingBoxCalculator::GetBBsOfSkeletalMeshComponents( TArray UBoundingBoxCalculator::GetBoundingBoxOfActors( const TArray& Actors, + const UCarlaEpisode* Episode, uint8 InTagQueried) { TArray Result; for(AActor* Actor : Actors) { + uint32_t ActorId = Actor->GetUniqueID(); + FCarlaActor* CarlaActor = Episode->FindCarlaActor(Actor); + if (CarlaActor) { + ActorId = CarlaActor->GetActorId(); + } TArray BBs = GetBBsOfActor(Actor, InTagQueried); + for (FBoundingBox& BB : BBs) { + BB.ActorId = ActorId; + } Result.Append(BBs.GetData(), BBs.Num()); } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h index 6d0282905ad..74fc611a90a 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Util/BoundingBoxCalculator.h @@ -77,6 +77,7 @@ class CARLA_API UBoundingBoxCalculator : public UBlueprintFunctionLibrary UFUNCTION(Category = "Carla Util", BlueprintCallable) static TArray GetBoundingBoxOfActors( const TArray& Actors, + const UCarlaEpisode* Episode, uint8 InTagQueried = 0xFF); UFUNCTION(Category = "Carla Util", BlueprintCallable) diff --git a/Unreal/CarlaUE4/Plugins/CarlaTools/Source/CarlaTools/CarlaTools.Build.cs b/Unreal/CarlaUE4/Plugins/CarlaTools/Source/CarlaTools/CarlaTools.Build.cs index a5181554adb..230f2ef15a2 100644 --- a/Unreal/CarlaUE4/Plugins/CarlaTools/Source/CarlaTools/CarlaTools.Build.cs +++ b/Unreal/CarlaUE4/Plugins/CarlaTools/Source/CarlaTools/CarlaTools.Build.cs @@ -4,21 +4,17 @@ using System.IO; using UnrealBuildTool; -public class CarlaTools : ModuleRules +public class CarlaTools : CarlaRules { bool bUsingOmniverseConnector = false; - private bool IsWindows(ReadOnlyTargetRules Target) - { - return (Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32); - } - public CarlaTools(ReadOnlyTargetRules Target) : base(Target) + public CarlaTools(ReadOnlyTargetRules Target) : base(Target, "../../../Carla/CarlaDependencies") { PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; // PrivatePCHHeaderFile = "Carla.h"; - if (IsWindows(Target)) + if (IsWindows()) { bEnableExceptions = true; } @@ -36,6 +32,13 @@ public CarlaTools(ReadOnlyTargetRules Target) : base(Target) PublicDefinitions.Add("WITH_OMNIVERSE"); PrivateDefinitions.Add("WITH_OMNIVERSE"); } + + if (line.Contains("Ros2 ON")) + { + Console.WriteLine("Enabling ros2"); + UsingRos2 = true; + } + } PublicIncludePaths.AddRange( @@ -112,78 +115,32 @@ public CarlaTools(ReadOnlyTargetRules Target) : base(Target) // ... add any modules that your module loads dynamically here ... } ); - AddCarlaServerDependency(Target); + AddCarlaServerDependency(); } - private bool UseDebugLibs(ReadOnlyTargetRules Target) - { - if (IsWindows(Target)) + + private void AddCarlaServerDependency() + { + + // Link dependencies. + if (IsWindows()) { - // In Windows, Unreal uses the Release C++ Runtime (CRT) even in debug - // mode, so unless we recompile the engine we cannot link the debug - // libraries. - return false; + AddBoostLibs(); } - else + AddStaticLibrary("rpc"); + if (UseDebugLibs()) { - return false; + AddStaticLibrary("carla_server_debug"); } - } - - delegate string ADelegate(string s); - - private void AddBoostLibs(string LibPath) - { - string [] files = Directory.GetFiles(LibPath, "*boost*.lib"); - foreach (string file in files) + else { - PublicAdditionalLibraries.Add(file); + AddStaticLibrary("carla_server"); } - } - - private void AddCarlaServerDependency(ReadOnlyTargetRules Target) - { - string LibCarlaInstallPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "../../../Carla/CarlaDependencies")); - - ADelegate GetLibName = (string BaseName) => { - if (IsWindows(Target)) - { - return BaseName + ".lib"; - } - else - { - return "lib" + BaseName + ".a"; - } - }; + addOsmToODR(); - // Link dependencies. - if (IsWindows(Target)) - { - AddBoostLibs(Path.Combine(LibCarlaInstallPath, "lib")); - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("rpc"))); + addROS2(); - if (UseDebugLibs(Target)) - { - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("carla_server_debug"))); - } - else - { - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("carla_server"))); - } - } - else - { - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("rpc"))); - if (UseDebugLibs(Target)) - { - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("carla_server_debug"))); - } - else - { - PublicAdditionalLibraries.Add(Path.Combine(LibCarlaInstallPath, "lib", GetLibName("carla_server"))); - } - } // Include path. string LibCarlaIncludePath = Path.Combine(LibCarlaInstallPath, "include"); @@ -192,7 +149,7 @@ private void AddCarlaServerDependency(ReadOnlyTargetRules Target) PublicDefinitions.Add("ASIO_NO_EXCEPTIONS"); PublicDefinitions.Add("BOOST_NO_EXCEPTIONS"); - // PublicDefinitions.Add("LIBCARLA_NO_EXCEPTIONS"); + PublicDefinitions.Add("LIBCARLA_NO_EXCEPTIONS"); PublicDefinitions.Add("PUGIXML_NO_EXCEPTIONS"); PublicDefinitions.Add("BOOST_DISABLE_ABI_HEADERS"); PublicDefinitions.Add("BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY"); diff --git a/Util/BuildTools/Ad-rss.sh b/Util/BuildTools/Ad-rss.sh index 3f7c7169544..f4c978e6093 100755 --- a/Util/BuildTools/Ad-rss.sh +++ b/Util/BuildTools/Ad-rss.sh @@ -22,6 +22,13 @@ done # ============================================================================== source $(dirname "$0")/Environment.sh + +UNREAL_SYSROOT="$UE4_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu" +export CC="${UNREAL_SYSROOT}/bin/clang" +export CXX="${UNREAL_SYSROOT}/bin/clang++" +export PATH="${UNREAL_SYSROOT}/bin:$PATH" + + # Convert comma-separated string to array of unique elements. IFS="," read -r -a PY_VERSION_LIST <<< "${PY_VERSION_LIST}" @@ -29,7 +36,7 @@ IFS="," read -r -a PY_VERSION_LIST <<< "${PY_VERSION_LIST}" # -- Get ad-rss ------------------------------------------- # ============================================================================== -ADRSS_VERSION=4.4.4 +ADRSS_VERSION=4.4.5 ADRSS_BASENAME=ad-rss-${ADRSS_VERSION} ADRSS_COLCON_WORKSPACE="${CARLA_BUILD_FOLDER}/${ADRSS_BASENAME}" ADRSS_SRC_DIR="${ADRSS_COLCON_WORKSPACE}/src" @@ -42,11 +49,8 @@ if [[ ! -d "${ADRSS_SRC_DIR}" ]]; then # clone ad-rss with all submodules, but remove proj, as CARLA already uses it pushd "${ADRSS_SRC_DIR}" >/dev/null - git clone -b v${ADRSS_VERSION} https://github.com/intel/ad-rss-lib.git && cd ad-rss-lib && git submodule update --init --recursive && rm -rf dependencies/map/dependencies/PROJ4 && cd .. + git clone -b v${ADRSS_VERSION} https://github.com/intel/ad-rss-lib.git && cd ad-rss-lib && git submodule update --init --recursive && cd .. - # ADRSS_VERSION is designed for older boost, update datatype from boost::array to std::array - grep -rl "boost::array" | xargs sed -i 's/boost::array/std::array/g' - grep -rl "find_package(Boost" | xargs sed -i 's/find_package(Boost/find_package(Boost 1.80/g' popd cat >"${ADRSS_COLCON_WORKSPACE}/colcon.meta" </dev/null if [[ "${CMAKE_PREFIX_PATH}" == "" ]]; then - CMAKE_PREFIX_PATH="${CARLA_BUILD_FOLDER}/boost-1.80.0-$CXX_TAG-install;${CARLA_BUILD_FOLDER}/proj-install" + CMAKE_PREFIX_PATH="${CARLA_BUILD_FOLDER}/boost-1.80.0-client-install;${CARLA_BUILD_FOLDER}/proj-client-install" else - CMAKE_PREFIX_PATH="${CARLA_BUILD_FOLDER}/boost-1.80.0-$CXX_TAG-install;${CARLA_BUILD_FOLDER}/proj-install;${CMAKE_PREFIX_PATH}" + CMAKE_PREFIX_PATH="${CARLA_BUILD_FOLDER}/boost-1.80.0-client-install;${CARLA_BUILD_FOLDER}/proj-client-install;${CMAKE_PREFIX_PATH}" fi # get the python version of the binding to be built, need to query the binary, @@ -120,7 +122,7 @@ for PY_VERSION in ${PY_VERSION_LIST[@]} ; do echo "PYTHON_BINDING_VERSIONS=${PYTHON_BINDING_VERSIONS}" # enforce sequential executor to reduce the required memory for compilation - colcon build --executor sequential --packages-up-to ad_rss_map_integration --cmake-args -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_TOOLCHAIN_FILE="${CARLA_BUILD_FOLDER}/LibStdCppToolChain.cmake" -DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" -DPYTHON_BINDING_VERSIONS="${PYTHON_BINDING_VERSIONS}" --build-base ${ADRSS_BUILD_DIR} --install-base ${ADRSS_INSTALL_DIR} + colcon build --executor sequential --packages-up-to ad_rss_map_integration --cmake-args -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_TOOLCHAIN_FILE="${CARLA_BUILD_FOLDER}/CarlaClientToolChain.cmake" -DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" -DPYTHON_BINDING_VERSIONS="${PYTHON_BINDING_VERSIONS}" --build-base ${ADRSS_BUILD_DIR} --install-base ${ADRSS_INSTALL_DIR} COLCON_RESULT=$? if (( COLCON_RESULT )); then diff --git a/Util/BuildTools/BuildCarlaUE4.sh b/Util/BuildTools/BuildCarlaUE4.sh index 4db570edb15..8212fa960a4 100755 --- a/Util/BuildTools/BuildCarlaUE4.sh +++ b/Util/BuildTools/BuildCarlaUE4.sh @@ -6,7 +6,7 @@ DOC_STRING="Build and launch CarlaUE4." -USAGE_STRING="Usage: $0 [-h|--help] [--build] [--rebuild] [--launch] [--clean] [--hard-clean] [--opengl]" +USAGE_STRING="Usage: $0 [-h|--help] [--build] [--rebuild] [--launch] [--clean] [--hard-clean] [--opengl] [--ros2]" REMOVE_INTERMEDIATE=false HARD_CLEAN=false @@ -17,11 +17,13 @@ USE_CHRONO=false USE_PYTORCH=false USE_UNITY=true USE_ROS2=false +EDITOR_ROS2_FLAGS="" EDITOR_FLAGS="" GDB= RHI="-vulkan" +DEBUG=false OPTS=`getopt -o h --long help,build,rebuild,launch,clean,hard-clean,gdb,opengl,carsim,pytorch,chrono,ros2,no-unity,editor-flags: -n 'parse-options' -- "$@"` @@ -35,6 +37,9 @@ while [[ $# -gt 0 ]]; do --gdb ) GDB="gdb --args"; shift ;; + --debug ) + DEBUG=true; + shift ;; --build ) BUILD_CARLAUE4=true; shift ;; @@ -66,6 +71,9 @@ while [[ $# -gt 0 ]]; do shift ;; --ros2 ) USE_ROS2=true; + # Due to continued segfaults in reallocations of MallocBinned2 enforce using AnsiMalloc calls + # (see https://forums.unrealengine.com/t/dealing-with-allocator-mismatches-with-external-libraries/1416830) + EDITOR_ROS2_FLAGS="-ansimalloc" shift ;; --no-unity ) USE_UNITY=false @@ -110,7 +118,7 @@ if ${HARD_CLEAN} ; then log "Doing a \"hard\" clean of the Unreal Engine project." - make CarlaUE4Editor ARGS=-clean + make CarlaUE4Editor ARGS="-clean" fi @@ -122,16 +130,16 @@ if ${REMOVE_INTERMEDIATE} ; then rm -Rf ${UE4_INTERMEDIATE_FOLDERS} + cd Plugins + rm -Rf HoudiniEngine + cd .. + rm -f Makefile pushd "${CARLAUE4_PLUGIN_ROOT_FOLDER}" >/dev/null rm -Rf ${UE4_INTERMEDIATE_FOLDERS} - cd Plugins - rm -Rf HoudiniEngine - cd .. - popd >/dev/null fi @@ -165,12 +173,16 @@ if ${BUILD_CARLAUE4} ; then else OPTIONAL_MODULES_TEXT="Ros2 OFF"$'\n'"${OPTIONAL_MODULES_TEXT}" fi + if ${DEBUG} ; then + OPTIONAL_MODULES_TEXT="Debug ON"$'\n'"${OPTIONAL_MODULES_TEXT}" + else + OPTIONAL_MODULES_TEXT="Debug OFF"$'\n'"${OPTIONAL_MODULES_TEXT}" + fi if ${USE_UNITY} ; then OPTIONAL_MODULES_TEXT="Unity ON"$'\n'"${OPTIONAL_MODULES_TEXT}" else OPTIONAL_MODULES_TEXT="Unity OFF"$'\n'"${OPTIONAL_MODULES_TEXT}" fi - OPTIONAL_MODULES_TEXT="Fast_dds ON"$'\n'"${OPTIONAL_MODULES_TEXT}" echo ${OPTIONAL_MODULES_TEXT} > ${PWD}/Config/OptionalModules.ini if [ ! -f Makefile ]; then @@ -200,7 +212,7 @@ fi if ${LAUNCH_UE4_EDITOR} ; then log "Launching UE4Editor..." - ${GDB} ${UE4_ROOT}/Engine/Binaries/Linux/UE4Editor "${PWD}/CarlaUE4.uproject" ${RHI} ${EDITOR_FLAGS} + ${GDB} ${UE4_ROOT}/Engine/Binaries/Linux/UE4Editor "${PWD}/CarlaUE4.uproject" ${RHI} ${EDITOR_FLAGS} ${EDITOR_ROS2_FLAGS} else diff --git a/Util/BuildTools/BuildLibCarla.bat b/Util/BuildTools/BuildLibCarla.bat index 710a5534a6a..b8aa6c58316 100644 --- a/Util/BuildTools/BuildLibCarla.bat +++ b/Util/BuildTools/BuildLibCarla.bat @@ -15,11 +15,13 @@ rem -- Parse arguments --------------------------------------------------------- rem ============================================================================ set DOC_STRING=Build LibCarla. -set USAGE_STRING=Usage: %FILE_N% [-h^|--help] [--rebuild] [--server] [--client] [--clean] +set USAGE_STRING=Usage: %FILE_N% [-h^|--help] [--rebuild] [--server] [--client] [--clean] [--ros2] set REMOVE_INTERMEDIATE=false set BUILD_SERVER=false set BUILD_CLIENT=false +set M_ROS2=OFF +set GENERATOR="" :arg-parse if not "%1"=="" ( @@ -34,6 +36,9 @@ if not "%1"=="" ( if "%1"=="--client" ( set BUILD_CLIENT=true ) + if "%1"=="--ros2" ( + set M_ROS2=ON + ) if "%1"=="--clean" ( set REMOVE_INTERMEDIATE=true ) @@ -73,7 +78,11 @@ rem set LIBCARLA_VSPROJECT_PATH=%INSTALLATION_DIR:/=\%libcarla-visualstudio\ if %GENERATOR% == "" set GENERATOR="Visual Studio 16 2019" - +echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( + set PLATFORM=-A x64 +) || ( + set PLATFORM= +) set LIBCARLA_SERVER_INSTALL_PATH=%ROOT_PATH:/=\%Unreal\CarlaUE4\Plugins\Carla\CarlaDependencies\ set LIBCARLA_CLIENT_INSTALL_PATH=%ROOT_PATH:/=\%PythonAPI\carla\dependencies\ @@ -104,12 +113,6 @@ if %REMOVE_INTERMEDIATE% == true ( if not exist "%LIBCARLA_VSPROJECT_PATH%" mkdir "%LIBCARLA_VSPROJECT_PATH%" cd "%LIBCARLA_VSPROJECT_PATH%" -echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( - set PLATFORM=-A x64 -) || ( - set PLATFORM= -) - rem For some reason the findstr above sets an errorlevel even if it finds the string in this batch file. set errorlevel=0 @@ -121,6 +124,7 @@ if %BUILD_SERVER% == true ( -DCMAKE_BUILD_TYPE=Server^ -DCMAKE_CXX_FLAGS_RELEASE="/MD /MP"^ -DCMAKE_INSTALL_PREFIX="%LIBCARLA_SERVER_INSTALL_PATH:\=/%"^ + -DLIBCARLA_USE_ROS="%M_ROS2%"^ "%ROOT_PATH%" if %errorlevel% neq 0 goto error_cmake diff --git a/Util/BuildTools/BuildLibCarla.sh b/Util/BuildTools/BuildLibCarla.sh index c9e2f13a009..149e65b9e36 100755 --- a/Util/BuildTools/BuildLibCarla.sh +++ b/Util/BuildTools/BuildLibCarla.sh @@ -125,28 +125,31 @@ function build_libcarla { CMAKE_EXTRA_OPTIONS='' + M_ROS=false if [ $1 == Server ] ; then - M_TOOLCHAIN=${LIBCPP_TOOLCHAIN_FILE} + M_TOOLCHAIN=${CARLA_SERVER_TOOLCHAIN_FILE} M_BUILD_FOLDER=${LIBCARLA_BUILD_SERVER_FOLDER}.$(echo "$2" | tr '[:upper:]' '[:lower:]') M_INSTALL_FOLDER=${LIBCARLA_INSTALL_SERVER_FOLDER} + elif [ $1 == ServerROS ] ; then + BUILD_TYPE='Server' + M_TOOLCHAIN=${CARLA_SERVER_TOOLCHAIN_FILE} + M_BUILD_FOLDER=${LIBCARLA_BUILD_SERVER_FOLDER}.ROS.$(echo "$2" | tr '[:upper:]' '[:lower:]') + M_INSTALL_FOLDER=${LIBCARLA_INSTALL_SERVER_FOLDER} + M_ROS=true elif [ $1 == Client ] ; then - M_TOOLCHAIN=${LIBSTDCPP_TOOLCHAIN_FILE} + M_TOOLCHAIN=${CARLA_CLIENT_TOOLCHAIN_FILE} M_BUILD_FOLDER=${LIBCARLA_BUILD_CLIENT_FOLDER}.$(echo "$2" | tr '[:upper:]' '[:lower:]') M_INSTALL_FOLDER=${LIBCARLA_INSTALL_CLIENT_FOLDER} elif [ $1 == Pytorch ] ; then - M_TOOLCHAIN=${LIBSTDCPP_TOOLCHAIN_FILE} + M_TOOLCHAIN=${CARLA_SERVER_TOOLCHAIN_FILE} M_BUILD_FOLDER=${LIBCARLA_BUILD_PYTORCH_FOLDER}.$(echo "$2" | tr '[:upper:]' '[:lower:]') M_INSTALL_FOLDER=${LIBCARLA_INSTALL_SERVER_FOLDER} - elif [ $1 == ros2 ] ; then - M_TOOLCHAIN=${LIBSTDCPP_TOOLCHAIN_FILE} - M_BUILD_FOLDER=${LIBCARLA_FASTDDS_FOLDER}.$(echo "$2" | tr '[:upper:]' '[:lower:]') - M_INSTALL_FOLDER=${LIBCARLA_INSTALL_SERVER_FOLDER} elif [ $1 == ClientRSS ] ; then BUILD_TYPE='Client' - M_TOOLCHAIN=${LIBSTDCPP_TOOLCHAIN_FILE} + M_TOOLCHAIN=${CARLA_CLIENT_TOOLCHAIN_FILE} M_BUILD_FOLDER=${LIBCARLA_BUILD_CLIENT_FOLDER}.rss.$(echo "$2" | tr '[:upper:]' '[:lower:]') M_INSTALL_FOLDER=${LIBCARLA_INSTALL_CLIENT_FOLDER} - CMAKE_EXTRA_OPTIONS="${CMAKE_EXTRA_OPTIONS:+${CMAKE_EXTRA_OPTIONS} }-DBUILD_RSS_VARIANT=ON -DADRSS_INSTALL_DIR=${CARLA_BUILD_FOLDER}/ad-rss-4.4.4/install" + CMAKE_EXTRA_OPTIONS="${CMAKE_EXTRA_OPTIONS:+${CMAKE_EXTRA_OPTIONS} }-DBUILD_RSS_VARIANT=ON -DADRSS_INSTALL_DIR=${CARLA_BUILD_FOLDER}/ad-rss-4.4.5/install" else fatal_error "Invalid build configuration \"$1\"" fi @@ -184,6 +187,7 @@ function build_libcarla { -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-$1} \ -DLIBCARLA_BUILD_DEBUG=${M_DEBUG} \ -DLIBCARLA_BUILD_RELEASE=${M_RELEASE} \ + -DLIBCARLA_USE_ROS=${M_ROS} \ -DCMAKE_TOOLCHAIN_FILE=${M_TOOLCHAIN} \ -DCMAKE_INSTALL_PREFIX=${M_INSTALL_FOLDER} \ -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ @@ -194,7 +198,7 @@ function build_libcarla { fi - ninja + ninja ninja install | grep -v "Up-to-date:" @@ -205,23 +209,22 @@ function build_libcarla { # -- Build all possible configurations ----------------------------------------- # ============================================================================== +SERVER_VARIANT='Server' +if ${USE_ROS2}; then + SERVER_VARIANT='ServerROS' +fi if { ${BUILD_SERVER} && ${BUILD_OPTION_DEBUG}; }; then - build_libcarla Server Debug + build_libcarla ${SERVER_VARIANT} Debug fi if { ${BUILD_SERVER} && ${BUILD_OPTION_RELEASE}; }; then - build_libcarla Server Release + build_libcarla ${SERVER_VARIANT} Release if ${USE_PYTORCH} ; then build_libcarla Pytorch Release fi - - if ${USE_ROS2} ; then - build_libcarla ros2 Release - fi - fi CLIENT_VARIANT='Client' diff --git a/Util/BuildTools/BuildOSM2ODR.bat b/Util/BuildTools/BuildOSM2ODR.bat index 77a4eff2bc7..c3ee9817c18 100644 --- a/Util/BuildTools/BuildOSM2ODR.bat +++ b/Util/BuildTools/BuildOSM2ODR.bat @@ -6,6 +6,7 @@ rem Run it through a cmd with the x64 Visual C++ Toolset enabled. set LOCAL_PATH=%~dp0 set FILE_N=-[%~n0]: +set GENERATOR="" rem Print batch params (debug purpose) echo %FILE_N% [Batch params]: %* @@ -57,6 +58,13 @@ if not "%1"=="" ( goto :arg-parse ) +if %GENERATOR% == "" set GENERATOR="Visual Studio 16 2019" +echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( + set PLATFORM=-A x64 +) || ( + set PLATFORM= +) + if %REMOVE_INTERMEDIATE% == false ( if %BUILD_OSM2ODR% == false ( echo Nothing selected to be done. @@ -76,8 +84,6 @@ set OSM2ODR_INSTALL_PATH=%ROOT_PATH:/=\%PythonAPI\carla\dependencies\ set OSM2ODR__SERVER_INSTALL_PATH=%ROOT_PATH:/=\%Unreal\CarlaUE4\Plugins\Carla\CarlaDependencies set CARLA_DEPENDENCIES_FOLDER=%ROOT_PATH:/=\%Unreal\CarlaUE4\Plugins\Carla\CarlaDependencies\ -if %GENERATOR% == "" set GENERATOR="Visual Studio 16 2019" - if %REMOVE_INTERMEDIATE% == true ( rem Remove directories for %%G in ( @@ -90,6 +96,7 @@ if %REMOVE_INTERMEDIATE% == true ( ) ) + rem Build OSM2ODR if %BUILD_OSM2ODR% == true ( cd "%INSTALLATION_DIR%" @@ -99,7 +106,7 @@ if %BUILD_OSM2ODR% == true ( del OSM2ODR.zip ren sumo-%CURRENT_OSM2ODR_COMMIT% osm2odr-source ) - + cd .. if not exist "%OSM2ODR_VSPROJECT_PATH%" mkdir "%OSM2ODR_VSPROJECT_PATH%" cd "%OSM2ODR_VSPROJECT_PATH%" diff --git a/Util/BuildTools/BuildOSM2ODR.sh b/Util/BuildTools/BuildOSM2ODR.sh index 6264c9a2f2d..d6ee51e6a65 100755 --- a/Util/BuildTools/BuildOSM2ODR.sh +++ b/Util/BuildTools/BuildOSM2ODR.sh @@ -14,7 +14,7 @@ END REMOVE_INTERMEDIATE=false BUILD_OSM2ODR=false GIT_PULL=true -CURRENT_OSM2ODR_COMMIT=1835e1e9538d0778971acc8b19b111834aae7261 +CURRENT_OSM2ODR_COMMIT=2a490962dc54da711ab09265393a4dc2f6d31813 OSM2ODR_BRANCH=aaron/defaultsidewalkwidth OSM2ODR_REPO=https://github.com/carla-simulator/sumo.git @@ -51,13 +51,15 @@ source $(dirname "$0")/Environment.sh function get_source_code_checksum { local EXCLUDE='*__pycache__*' - find "${OSM2ODR_SOURCE_FOLDER}"/* \! -path "${EXCLUDE}" -print0 | sha1sum | awk '{print $1}' + find "${OSM2ODR_BASENAME}-source"/* \! -path "${EXCLUDE}" -print0 | sha1sum | awk '{print $1}' } if ! { ${REMOVE_INTERMEDIATE} || ${BUILD_OSM2ODR}; }; then fatal_error "Nothing selected to be done." fi +OSM2ODR_BASENAME=${CARLA_BUILD_FOLDER}/osm2odr + # ============================================================================== # -- Clean intermediate files -------------------------------------------------- # ============================================================================== @@ -66,7 +68,8 @@ if ${REMOVE_INTERMEDIATE} ; then log "Cleaning intermediate files and folders." - rm -Rf ${OSM2ODR_BUILD_FOLDER}* + rm -Rf ${OSM2ODR_BASENAME}-client-build* ${OSM2ODR_BASENAME}-server-build* + rm -Rf ${OSM2ODR_BASENAME}-server-install* ${OSM2ODR_BASENAME}-client-install* fi @@ -75,75 +78,64 @@ fi # ============================================================================== if ${BUILD_OSM2ODR} ; then - log "Building OSM2ODR." - if [ ! -d ${OSM2ODR_SOURCE_FOLDER} ] ; then - cd ${CARLA_BUILD_FOLDER} - curl --retry 5 --retry-max-time 120 -L -o OSM2ODR.zip https://github.com/carla-simulator/sumo/archive/${CURRENT_OSM2ODR_COMMIT}.zip - unzip -qq OSM2ODR.zip - rm -f OSM2ODR.zip - mv sumo-${CURRENT_OSM2ODR_COMMIT} ${OSM2ODR_SOURCE_FOLDER} + + if [[ -d ${OSM2ODR_BASENAME}-client-install && -d ${OSM2ODR_BASENAME}-server-install ]] ; then + log "OSM2ODR already installed." + else + rm -Rf \ + ${OSM2ODR_BASENAME}-source \ + ${OSM2ODR_BASENAME}-server-build ${OSM2ODR_BASENAME}-client-build \ + ${OSM2ODR_BASENAME}-server-install ${OSM2ODR_BASENAME}-client-install + + log "Building OSM2ODR." + if [ ! -d ${OSM2ODR_BASENAME}-source ] ; then + cd ${CARLA_BUILD_FOLDER} + curl --retry 5 --retry-max-time 120 -L -o OSM2ODR.zip https://github.com/carla-simulator/sumo/archive/${CURRENT_OSM2ODR_COMMIT}.zip + unzip -qq OSM2ODR.zip + rm -f OSM2ODR.zip + mv sumo-${CURRENT_OSM2ODR_COMMIT} ${OSM2ODR_BASENAME}-source + fi + + mkdir -p ${OSM2ODR_BASENAME}-client-build + pushd ${OSM2ODR_BASENAME}-client-build >/dev/null + + cmake ${OSM2ODR_BASENAME}-source \ + -G "Eclipse CDT4 - Ninja" \ + -DCMAKE_INSTALL_PREFIX=${OSM2ODR_BASENAME}-client-install \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_CLIENT_TOOLCHAIN_FILE}" \ + -DOSM2ODR_INCLUDE_DIR=${CARLA_BUILD_FOLDER}/proj-client-install/include \ + -DOSM2ODR_LIBRARY=${CARLA_BUILD_FOLDER}/proj-client-install/lib/libproj.so \ + -DXercesC_INCLUDE_DIR=${CARLA_BUILD_FOLDER}/xerces-c-3.2.3-client-install/include \ + -DXercesC_LIBRARY=${CARLA_BUILD_FOLDER}/xerces-c-3.2.3-client-install/lib/libxerces-c.so + + ninja osm2odr + ninja install + popd >/dev/null + + mkdir -p ${OSM2ODR_BASENAME}-server-build + pushd ${OSM2ODR_BASENAME}-server-build >/dev/null + + cmake ${OSM2ODR_BASENAME}-source \ + -G "Eclipse CDT4 - Ninja" \ + -DCMAKE_INSTALL_PREFIX=${OSM2ODR_BASENAME}-server-install \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_SERVER_TOOLCHAIN_FILE}" \ + -DOSM2ODR_INCLUDE_DIR=${CARLA_BUILD_FOLDER}/proj-server-install/include \ + -DOSM2ODR_LIBRARY=${CARLA_BUILD_FOLDER}/proj-server-install/lib/libproj.a \ + -DXercesC_INCLUDE_DIR=${CARLA_BUILD_FOLDER}/xerces-c-3.2.3-server-install/include \ + -DXercesC_LIBRARY=${CARLA_BUILD_FOLDER}/xerces-c-3.2.3-server-install/lib/libxerces-c.a + + ninja osm2odr + ninja install + popd >/dev/null + + rm -Rf ${OSM2ODR_BASENAME}-server-build ${OSM2ODR_BASENAME}-client-build fi - mkdir -p ${OSM2ODR_BUILD_FOLDER} - cd ${OSM2ODR_BUILD_FOLDER} - - - export CC="$UE4_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu/bin/clang" - export CXX="$UE4_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu/bin/clang++" - export PATH="$UE4_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu/bin:$PATH" - - cmake ${OSM2ODR_SOURCE_FOLDER} \ - -G "Eclipse CDT4 - Ninja" \ - -DCMAKE_CXX_FLAGS="-stdlib=libstdc++" \ - -DCMAKE_INSTALL_PREFIX=${LIBCARLA_INSTALL_CLIENT_FOLDER} \ - -DPROJ_INCLUDE_DIR=${CARLA_BUILD_FOLDER}/proj-install/include \ - -DPROJ_LIBRARY=${CARLA_BUILD_FOLDER}/proj-install/lib/libproj.a \ - -DXercesC_INCLUDE_DIR=${CARLA_BUILD_FOLDER}/xerces-c-3.2.3-install/include \ - -DXercesC_LIBRARY=${CARLA_BUILD_FOLDER}/xerces-c-3.2.3-install/lib/libxerces-c.a - - ninja osm2odr - ninja install - - mkdir -p ${OSM2ODR_SERVER_BUILD_FOLDER} - cd ${OSM2ODR_SERVER_BUILD_FOLDER} - - LLVM_BASENAME=llvm-8.0 - LLVM_INCLUDE="$UE4_ROOT/Engine/Source/ThirdParty/Linux/LibCxx/include/c++/v1" - LLVM_LIBPATH="$UE4_ROOT/Engine/Source/ThirdParty/Linux/LibCxx/lib/Linux/x86_64-unknown-linux-gnu" - - echo $LLVM_INCLUDE - echo $LLVM_LIBPATH - - cmake ${OSM2ODR_SOURCE_FOLDER} \ - -G "Eclipse CDT4 - Ninja" \ - -DCMAKE_CXX_FLAGS="-fPIC -std=c++14 -stdlib=libc++ -I${LLVM_INCLUDE} -L${LLVM_LIBPATH}" \ - -DCMAKE_INSTALL_PREFIX=${LIBCARLA_INSTALL_SERVER_FOLDER} \ - -DPROJ_INCLUDE_DIR=${CARLA_BUILD_FOLDER}/proj-install-server/include \ - -DPROJ_LIBRARY=${CARLA_BUILD_FOLDER}/proj-install-server/lib/libproj.a \ - -DXercesC_INCLUDE_DIR=${CARLA_BUILD_FOLDER}/xerces-c-3.2.3-install-server/include \ - -DXercesC_LIBRARY=${CARLA_BUILD_FOLDER}/xerces-c-3.2.3-install-server/lib/libxerces-c.a - - ninja osm2odr - ninja install - - mkdir -p ${OSM2ODR_SERVER_BUILD_FOLDER} - cd ${OSM2ODR_SERVER_BUILD_FOLDER} - - LLVM_BASENAME=llvm-8.0 - LLVM_INCLUDE="$UE4_ROOT/Engine/Source/ThirdParty/Linux/LibCxx/include/c++/v1" - LLVM_LIBPATH="$UE4_ROOT/Engine/Source/ThirdParty/Linux/LibCxx/lib/Linux/x86_64-unknown-linux-gnu" - - cmake ${OSM2ODR_SOURCE_FOLDER} \ - -G "Eclipse CDT4 - Ninja" \ - -DCMAKE_CXX_FLAGS="-fPIC -std=c++14 -stdlib=libc++ -I${LLVM_INCLUDE} -L${LLVM_LIBPATH}" \ - -DCMAKE_INSTALL_PREFIX=${LIBCARLA_INSTALL_SERVER_FOLDER} \ - -DPROJ_INCLUDE_DIR=${CARLA_BUILD_FOLDER}/proj-install-server/include \ - -DPROJ_LIBRARY=${CARLA_BUILD_FOLDER}/proj-install-server/lib/libproj.a \ - -DXercesC_INCLUDE_DIR=${CARLA_BUILD_FOLDER}/xerces-c-3.2.3-install-server/include \ - -DXercesC_LIBRARY=${CARLA_BUILD_FOLDER}/xerces-c-3.2.3-install-server/lib/libxerces-c.a - - ninja osm2odr - ninja install + cp -p -r ${OSM2ODR_BASENAME}-server-install/include/* ${LIBCARLA_INSTALL_SERVER_FOLDER}/include/ + cp -p ${OSM2ODR_BASENAME}-server-install/lib/*.a ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib + + cp -p -r ${OSM2ODR_BASENAME}-client-install/include/* ${LIBCARLA_INSTALL_CLIENT_FOLDER}/include/ + cp -p ${OSM2ODR_BASENAME}-client-install/lib/*.a ${LIBCARLA_INSTALL_CLIENT_FOLDER}/lib fi diff --git a/Util/BuildTools/BuildOSMRenderer.bat b/Util/BuildTools/BuildOSMRenderer.bat index fbf8367e1e9..ca4e46045d9 100644 --- a/Util/BuildTools/BuildOSMRenderer.bat +++ b/Util/BuildTools/BuildOSMRenderer.bat @@ -75,7 +75,7 @@ if not exist "%OSM_RENDERER_VSPROJECT_PATH%" mkdir "%OSM_RENDERER_VSPROJECT_PATH cd "%OSM_RENDERER_VSPROJECT_PATH%" cmake -G "Visual Studio 16 2019" -A x64^ - -DCMAKE_CXX_FLAGS_RELEASE="/std:c++17 /wd4251 /I%INSTALLATION_DIR:/=\%boost-1.80.0-install\include"^ + -DCMAKE_CXX_FLAGS_RELEASE="/std:c++20 /wd4251 /I%INSTALLATION_DIR:/=\%boost-1.80.0-install\include"^ "%OSM_RENDERER_SOURCE%" cmake --build . --config Release diff --git a/Util/BuildTools/BuildOSMRenderer.sh b/Util/BuildTools/BuildOSMRenderer.sh index 0cb2287eba1..1fbaf7ef641 100755 --- a/Util/BuildTools/BuildOSMRenderer.sh +++ b/Util/BuildTools/BuildOSMRenderer.sh @@ -68,7 +68,7 @@ echo "Building osm-map-renderer" mkdir -p ${OSM_RENDERER_BUILD} cd ${OSM_RENDERER_BUILD} -cmake -DCMAKE_CXX_FLAGS="-std=c++17 -g -pthread -I${CARLA_BUILD_FOLDER}/boost-1.80.0-c10-install/include" \ +cmake -DCMAKE_TOOLCHAIN_FILE="${CARLA_CLIENT_TOOLCHAIN_FILE}" -DCMAKE_CXX_FLAGS="-g -I${CARLA_BUILD_FOLDER}/boost-1.80.0-install/include" \ ${OSM_RENDERER_SOURCE} make diff --git a/Util/BuildTools/BuildPythonAPI.bat b/Util/BuildTools/BuildPythonAPI.bat index 9812c8220ab..ba1e4d19578 100644 --- a/Util/BuildTools/BuildPythonAPI.bat +++ b/Util/BuildTools/BuildPythonAPI.bat @@ -96,7 +96,7 @@ rem ============================================================================ rem -- Check for py ------------------------------------------------------------ rem ============================================================================ -where py 1>nul +where python 1>nul if %errorlevel% neq 0 goto error_py rem Build for Python 2 diff --git a/Util/BuildTools/BuildPythonAPI.sh b/Util/BuildTools/BuildPythonAPI.sh index f5bbb5c61cc..a487f20d2c3 100755 --- a/Util/BuildTools/BuildPythonAPI.sh +++ b/Util/BuildTools/BuildPythonAPI.sh @@ -48,10 +48,10 @@ while [[ $# -gt 0 ]]; do esac done - -export CC="$UE4_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu/bin/clang" -export CXX="$UE4_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu/bin/clang++" -export PATH="$UE4_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu/bin:$PATH" +UNREAL_SYSROOT="$UE4_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu" +export CC="${UNREAL_SYSROOT}/bin/clang" +export CXX="${UNREAL_SYSROOT}/bin/clang++" +export PATH="${UNREAL_SYSROOT}/bin:$PATH" source $(dirname "$0")/Environment.sh @@ -75,7 +75,7 @@ if ${REMOVE_INTERMEDIATE} ; then rm -Rf build dist source/carla.egg-info find source -name "*.so" -delete - find source -name "__pycache__" -type d -exec rm -r "{}" \; + find source -name "__pycache__" -type d -exec rm -rf "{}" \; fi diff --git a/Util/BuildTools/BuildUtilsDocker.sh b/Util/BuildTools/BuildUtilsDocker.sh index 2c85a7b053c..ced4f4e9cae 100755 --- a/Util/BuildTools/BuildUtilsDocker.sh +++ b/Util/BuildTools/BuildUtilsDocker.sh @@ -37,7 +37,7 @@ mkdir -p "${FBX2OBJ_BUILD_FOLDER}" pushd "${FBX2OBJ_BUILD_FOLDER}" >/dev/null cmake -G "Ninja" \ - -DCMAKE_CXX_FLAGS="-fPIC -std=c++14" \ + -DCMAKE_CXX_FLAGS="-fPIC -std=c++20" \ .. # copy the shared object 'libfbxsdk.so' to 'dist' folder diff --git a/Util/BuildTools/Linux.mk b/Util/BuildTools/Linux.mk index 8e64f768963..286e6293fda 100644 --- a/Util/BuildTools/Linux.mk +++ b/Util/BuildTools/Linux.mk @@ -7,6 +7,10 @@ launch: LibCarla.server.release osm2odr downloadplugins @${CARLA_BUILD_TOOLS_FOLDER}/BuildUE4Plugins.sh --build $(ARGS) @${CARLA_BUILD_TOOLS_FOLDER}/BuildCarlaUE4.sh --build --launch $(ARGS) +launch.debug: LibCarla.server.debug osm2odr downloadplugins + @${CARLA_BUILD_TOOLS_FOLDER}/BuildUE4Plugins.sh --build $(ARGS) + @${CARLA_BUILD_TOOLS_FOLDER}/BuildCarlaUE4.sh --build --debug --launch $(ARGS) + launch-only: @${CARLA_BUILD_TOOLS_FOLDER}/BuildCarlaUE4.sh --launch $(ARGS) @@ -138,7 +142,7 @@ LibCarla.client.rss.release: setup ad-rss plugins: @${CARLA_BUILD_TOOLS_FOLDER}/Plugins.sh $(ARGS) -setup downloadplugins: +setup: downloadplugins @${CARLA_BUILD_TOOLS_FOLDER}/Setup.sh $(ARGS) ad-rss: diff --git a/Util/BuildTools/Package.sh b/Util/BuildTools/Package.sh index 0be72293a26..19974079491 100755 --- a/Util/BuildTools/Package.sh +++ b/Util/BuildTools/Package.sh @@ -6,7 +6,7 @@ DOC_STRING="Makes a packaged version of CARLA and other content packages ready for distribution." -USAGE_STRING="Usage: $0 [-h|--help] [--config={Debug,Development,Shipping}] [--no-zip] [--clean-intermediate] [--packages=Name1,Name2,...] [--target-archive=] [--archive-sufix=]" +USAGE_STRING="Usage: $0 [-h|--help] [--config={Debug,Development,Shipping}] [--no-zip] [--clean-intermediate] [--packages=Name1,Name2,...] [--target-archive=] [--archive-sufix=] [--ros2]" PACKAGES="Carla" DO_TARBALL=true @@ -17,7 +17,10 @@ USE_CARSIM=false SINGLE_PACKAGE=false ARCHIVE_SUFIX="" -OPTS=`getopt -o h --long help,config:,no-zip,clean-intermediate,carsim,packages:,python-version,target-archive:,archive-sufix:, -n 'parse-options' -- "$@"` +EDITOR_ROS2_FLAGS="" + + +OPTS=`getopt -o h --long help,config:,no-zip,clean-intermediate,carsim,packages:,python-version,target-archive:,archive-sufix:,ros2 -n 'parse-options' -- "$@"` eval set -- "$OPTS" @@ -42,6 +45,11 @@ while [[ $# -gt 0 ]]; do --archive-sufix ) ARCHIVE_SUFIX="$2" shift 2 ;; + --ros2 ) + # Due to continued segfaults in reallocations of MallocBinned2 enforce using AnsiMalloc calls + # (see https://forums.unrealengine.com/t/dealing-with-allocator-mismatches-with-external-libraries/1416830) + EDITOR_ROS2_FLAGS="-ansimalloc" + shift ;; --carsim ) USE_CARSIM=true; shift ;; @@ -182,12 +190,14 @@ if ${DO_CARLA_RELEASE} ; then fi if [ -d "./Unreal/CarlaUE4/Plugins/Carla/CarlaDependencies/lib" ] ; then - cp -r "./Unreal/CarlaUE4/Plugins/Carla/CarlaDependencies/lib" "${DESTINATION}/CarlaUE4/Plugins/Carla/CarlaDependencies" + cp -r "./Unreal/CarlaUE4/Plugins/Carla/CarlaDependencies/lib/" "${DESTINATION}/CarlaUE4/Plugins/Carla/CarlaDependencies" fi copy_if_changed "./Unreal/CarlaUE4/Content/Carla/HDMaps/*.pcd" "${DESTINATION}/HDMaps/" copy_if_changed "./Unreal/CarlaUE4/Content/Carla/HDMaps/Readme.md" "${DESTINATION}/HDMaps/README" + sed -i "s/CarlaUE4 /CarlaUE4 ${EDITOR_ROS2_FLAGS} /g" "${DESTINATION}/CarlaUE4.sh" + popd >/dev/null fi diff --git a/Util/BuildTools/Setup.bat b/Util/BuildTools/Setup.bat index 5a496a96640..5aa9be672ff 100644 --- a/Util/BuildTools/Setup.bat +++ b/Util/BuildTools/Setup.bat @@ -65,7 +65,7 @@ if not "%1"=="" ( rem If not defined, use Visual Studio 2019 as tool set if "%TOOLSET%" == "" set TOOLSET=msvc-14.2 -if %GENERATOR% == "" set GENERATOR="Visual Studio 16 2019" +if "%GENERATOR%" == "" set GENERATOR="Visual Studio 16 2019" rem If is not set, set the number of parallel jobs to the number of CPU threads if "%NUMBER_OF_ASYNC_JOBS%" == "" set NUMBER_OF_ASYNC_JOBS=%NUMBER_OF_PROCESSORS% @@ -81,14 +81,17 @@ echo %FILE_N% Boost toolset: %TOOLSET% echo %FILE_N% Generator: %GENERATOR% echo %FILE_N% Install directory: "%INSTALLATION_DIR%" -if not exist "%CONTENT_DIR%" ( - echo %FILE_N% Creating "%CONTENT_DIR%" folder... - mkdir "%CONTENT_DIR%" -) - -if not exist "%INSTALLATION_DIR%" ( - echo %FILE_N% Creating "%INSTALLATION_DIR%" folder... - mkdir "%INSTALLATION_DIR%" +rem creating some folders +for %%G in ( + "%CONTENT_DIR%", + "%INSTALLATION_DIR%", + "%CARLA_DEPENDENCIES_FOLDER%\include", + "%CARLA_DEPENDENCIES_FOLDER%\lib" +) do ( + if not exist %%G ( + echo %FILE_N% Creating "%%G" folder... + mkdir "%%G" + ) ) rem ============================================================================ @@ -141,6 +144,8 @@ if not defined install_rpclib ( echo %FILE_N% Failed while installing rpclib. goto failed ) +xcopy /Y /S /I %INSTALLATION_DIR%rpclib-install\include\rpc\* %CARLA_DEPENDENCIES_FOLDER%\include\rpc\* > NUL +copy %INSTALLATION_DIR%rpclib-install\lib\*.* %CARLA_DEPENDENCIES_FOLDER%\lib\ > NUL rem ============================================================================ rem -- Download and install Google Test ---------------------------------------- @@ -178,26 +183,6 @@ if not defined install_recast ( set RECAST_INSTALL_DIR=%install_recast:\=/% ) -rem ============================================================================ -rem -- Download and install Fast-DDS (for ROS2)--------------------------------- -rem ============================================================================ - -if %USE_ROS2% == true ( - echo %FILE_N% Installing "Fast-DDS"... - call "%INSTALLERS_DIR%install_fastDDS.bat"^ - --build-dir "%INSTALLATION_DIR%" - - if %errorlevel% neq 0 goto failed - - if not defined install_dds ( - - echo %FILE_N% Failed while installing "Fast-DDS". - goto failed - ) else ( - set FASTDDS_INSTALL_DIR=%install_dds:\=/% - ) -) - rem ============================================================================ rem -- Download and install Boost ---------------------------------------------- rem ============================================================================ @@ -216,6 +201,27 @@ if not defined install_boost ( goto failed ) +rem ============================================================================ +rem -- Download and install Fast-DDS (for ROS2)--------------------------------- +rem ============================================================================ + +if %USE_ROS2% == true ( + echo %FILE_N% Installing "Fast-DDS"... + call "%INSTALLERS_DIR%install_fastDDS.bat"^ + --boost-version %BOOST_VERSION%^ + --build-dir "%INSTALLATION_DIR%"^ + --install-dir "%INSTALLATION_DIR%fastDDS-install\" + + if %errorlevel% neq 0 goto failed + + if not defined install_dds ( + echo %FILE_N% Failed while installing "Fast-DDS". + goto failed + ) + copy %INSTALLATION_DIR%fastDDS-install\lib\*.lib %CARLA_DEPENDENCIES_FOLDER%\lib > NUL + xcopy /Y /S /I %INSTALLATION_DIR%fastDDS-install\include\* %CARLA_DEPENDENCIES_FOLDER%\include\* > NUL +) + rem ============================================================================ rem -- Download and install Xercesc -------------------------------------------- rem ============================================================================ @@ -285,81 +291,6 @@ if %USE_CHRONO% == true ( xcopy /Y /S /I "%INSTALLATION_DIR%eigen-install\include\*" "%CARLA_DEPENDENCIES_FOLDER%include\*" > NUL ) -REM ============================================================================== -REM -- Download Fast DDS and dependencies ---------------------------------------- -REM ============================================================================== - -SET FASTDDS_BASENAME=fast-dds -SET FASTDDS_INSTALL_DIR=%CD%\%FASTDDS_BASENAME%-install -SET FASTDDS_INCLUDE=%FASTDDS_INSTALL_DIR%\include -SET FASTDDS_LIB=%FASTDDS_INSTALL_DIR%\lib -IF "%USE_ROS2%"=="true" ( - - :build_fastdds_extension - SET LIB_SOURCE=%1 - SET LIB_REPO=%2 - SET CMAKE_FLAGS=%3 - - IF NOT EXIST "%LIB_SOURCE%" ( - mkdir "%LIB_SOURCE%" - echo %LIB_REPO% - git clone %LIB_REPO% %LIB_SOURCE% - mkdir "%LIB_SOURCE%\build" - ) - - IF NOT EXIST "%FASTDDS_INSTALL_DIR%" ( - mkdir "%FASTDDS_INSTALL_DIR%" - echo Build foonathan memory vendor - SET FOONATHAN_MEMORY_VENDOR_BASENAME=foonathan-memory-vendor - SET FOONATHAN_MEMORY_VENDOR_SOURCE_DIR=%CD%\%FOONATHAN_MEMORY_VENDOR_BASENAME%-source - SET FOONATHAN_MEMORY_VENDOR_REPO="https://github.com/eProsima/foonathan_memory_vendor.git" - SET FOONATHAN_MEMORY_VENDOR_CMAKE_FLAGS=-DBUILD_SHARED_LIBS=ON - CALL :build_fastdds_extension "%FOONATHAN_MEMORY_VENDOR_SOURCE_DIR%" "%FOONATHAN_MEMORY_VENDOR_REPO%" - pushd "%FOONATHAN_MEMORY_VENDOR_SOURCE_DIR%\build" >nul - cmake -G "Ninja" ^ - -DCMAKE_INSTALL_PREFIX="%FASTDDS_INSTALL_DIR%" ^ - -DBUILD_SHARED_LIBS=ON ^ - -DCMAKE_CXX_FLAGS_RELEASE="-D_GLIBCXX_USE_CXX11_ABI=0" ^ - -DFOONATHAN_MEMORY_FORCE_VENDORED_BUILD=ON ^ - .. - ninja - ninja install - popd >nul - rmdir /s /q "%FOONATHAN_MEMORY_VENDOR_SOURCE_DIR%" - - echo Build fast cdr - SET FAST_CDR_BASENAME=fast-cdr - SET FAST_CDR_SOURCE_DIR=%CD%\%FAST_CDR_BASENAME%-source - SET FAST_CDR_REPO="https://github.com/eProsima/Fast-CDR.git" - CALL :build_fastdds_extension "%FAST_CDR_SOURCE_DIR%" "%FAST_CDR_REPO%" - pushd "%FAST_CDR_SOURCE_DIR%\build" >nul - cmake -G "Ninja" ^ - -DCMAKE_INSTALL_PREFIX="%FASTDDS_INSTALL_DIR%" ^ - -DCMAKE_CXX_FLAGS_RELEASE="-D_GLIBCXX_USE_CXX11_ABI=0" ^ - .. - ninja - ninja install - popd >nul - rmdir /s /q "%FAST_CDR_SOURCE_DIR%" - - echo Build fast dds - SET FAST_DDS_LIB_BASENAME=fast-dds-lib - SET FAST_DDS_LIB_SOURCE_DIR=%CD%\%FAST_DDS_LIB_BASENAME%-source - SET FAST_DDS_LIB_REPO="https://github.com/eProsima/Fast-DDS.git" - CALL :build_fastdds_extension "%FAST_DDS_LIB_SOURCE_DIR%" "%FAST_DDS_LIB_REPO%" - pushd "%FAST_DDS_LIB_SOURCE_DIR%\build" >nul - cmake -G "Ninja" ^ - -DCMAKE_INSTALL_PREFIX="%FASTDDS_INSTALL_DIR%" ^ - -DCMAKE_CXX_FLAGS=-latomic ^ - -DCMAKE_CXX_FLAGS_RELEASE="-D_GLIBCXX_USE_CXX11_ABI=0" ^ - .. - ninja - ninja install - popd >nul - rmdir / - ) -) - rem ============================================================================ rem -- Assets download URL ----------------------------------------------------- rem ============================================================================ @@ -384,7 +315,7 @@ set CMAKE_CONFIG_FILE=%INSTALLATION_DIR%CMakeLists.txt.in >"%CMAKE_CONFIG_FILE%" echo # Automatically generated by Setup.bat >>"%CMAKE_CONFIG_FILE%" echo set(CARLA_VERSION %carla_version%) >>"%CMAKE_CONFIG_FILE%" echo. ->>"%CMAKE_CONFIG_FILE%" echo set(CMAKE_CXX_STANDARD 14) +>>"%CMAKE_CONFIG_FILE%" echo set(CMAKE_CXX_STANDARD 20) >>"%CMAKE_CONFIG_FILE%" echo set(CMAKE_CXX_STANDARD_REQUIRED ON) >>"%CMAKE_CONFIG_FILE%" echo. >>"%CMAKE_CONFIG_FILE%" echo add_definitions(-D_WIN32_WINNT=0x0600) @@ -400,6 +331,11 @@ set CMAKE_CONFIG_FILE=%INSTALLATION_DIR%CMakeLists.txt.in >>"%CMAKE_CONFIG_FILE%" echo set(RPCLIB_INCLUDE_PATH "%CMAKE_INSTALLATION_DIR%rpclib-install/include") >>"%CMAKE_CONFIG_FILE%" echo set(RPCLIB_LIB_PATH "%CMAKE_INSTALLATION_DIR%rpclib-install/lib") >>"%CMAKE_CONFIG_FILE%" echo. +>>"%CMAKE_CONFIG_FILE%" echo set(ROS2_MW_INCLUDE_PATH "%CMAKE_INSTALLATION_DIR%fastDDS-install/include") +>>"%CMAKE_CONFIG_FILE%" echo set(ROS2_MW_LIB_PATH "%CMAKE_INSTALLATION_DIR%fastDDS-install/lib") +>>"%CMAKE_CONFIG_FILE%" echo set(ROS2_MW_LINK_LIBRARIES "fastrtps;fastcdr") +>>"%CMAKE_CONFIG_FILE%" echo set(ROS2_MW_NAME "fastdds") +>>"%CMAKE_CONFIG_FILE%" echo. >>"%CMAKE_CONFIG_FILE%" echo if (CMAKE_BUILD_TYPE STREQUAL "Server") >>"%CMAKE_CONFIG_FILE%" echo # Prevent exceptions >>"%CMAKE_CONFIG_FILE%" echo add_definitions(-DBOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY) diff --git a/Util/BuildTools/Setup.sh b/Util/BuildTools/Setup.sh index 64774d01718..4d0a916162c 100755 --- a/Util/BuildTools/Setup.sh +++ b/Util/BuildTools/Setup.sh @@ -47,47 +47,133 @@ done source $(dirname "$0")/Environment.sh -export CC="$UE4_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu/bin/clang" -export CXX="$UE4_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu/bin/clang++" -export PATH="$UE4_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu/bin:$PATH" - -CXX_TAG=c10 - # Convert comma-separated string to array of unique elements. IFS="," read -r -a PY_VERSION_LIST <<< "${PY_VERSION_LIST}" mkdir -p ${CARLA_BUILD_FOLDER} pushd ${CARLA_BUILD_FOLDER} >/dev/null -LLVM_INCLUDE="$UE4_ROOT/Engine/Source/ThirdParty/Linux/LibCxx/include/c++/v1" -LLVM_LIBPATH="$UE4_ROOT/Engine/Source/ThirdParty/Linux/LibCxx/lib/Linux/x86_64-unknown-linux-gnu" -UNREAL_HOSTED_CFLAGS="--sysroot=$UE4_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu/" +LLVM_INCLUDE="${UE4_ROOT}/Engine/Source/ThirdParty/Linux/LibCxx/include/c++/v1" +LLVM_LIBPATH="${UE4_ROOT}/Engine/Source/ThirdParty/Linux/LibCxx/lib/Linux/x86_64-unknown-linux-gnu" +UNREAL_SYSROOT="$UE4_ROOT/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu" +UNREAL_HOSTED_CFLAGS="--sysroot=${UNREAL_SYSROOT} -isystem ${LLVM_INCLUDE}" +UNREAL_SYSTEM_LIBPATH="${UNREAL_SYSROOT}/usr/lib" +UNREAL_HOSTED_LINKER_FLAGS="--sysroot=${UNREAL_SYSROOT} -L${LLVM_LIBPATH} -L${UNREAL_SYSTEM_LIBPATH} -lc++ -lc++abi" + + +CARLA_CFLAGS="-fPIC -w" +CARLA_CXXFLAGS="-std=c++20 -DBOOST_ERROR_CODE_HEADER_ONLY" + +CARLA_SERVER_CFLAGS="${UNREAL_HOSTED_CFLAGS} ${CARLA_CFLAGS}" +CARLA_SERVER_CXXFLAGS="${CARLA_SERVER_CFLAGS} ${CARLA_CXXFLAGS} -stdlib=libc++ -DBOOST_NO_EXCEPTIONS -DASIO_NO_EXCEPTIONS" +CARLA_SERVER_LINKER_FLAGS="${UNREAL_HOSTED_LINKER_FLAGS} -L${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/" + +export CC="${UNREAL_SYSROOT}/bin/clang" +export CXX="${UNREAL_SYSROOT}/bin/clang++" +export PATH="${UNREAL_SYSROOT}/bin:$PATH" + +# ============================================================================== +# -- Generate Version.h -------------------------------------------------------- +# ============================================================================== + +CARLA_VERSION=$(get_git_repository_version) + +log "CARLA version ${CARLA_VERSION}." + +VERSION_H_FILE=${LIBCARLA_ROOT_FOLDER}/source/carla/Version.h +VERSION_H_FILE_GEN=${CARLA_BUILD_FOLDER}/Version.h + +sed -e "s|\${CARLA_VERSION}|${CARLA_VERSION}|g" ${VERSION_H_FILE}.in > ${VERSION_H_FILE_GEN} + +move_if_changed "${VERSION_H_FILE_GEN}" "${VERSION_H_FILE}" + +# ============================================================================== +# -- Generate CMake toolchains and config -------------------------------------- +# ============================================================================== + +log "Generating CMake configuration files." + +# -- CARLA_CLIENT_TOOLCHAIN_FILE -------------------------------------------------- + +cat >${CARLA_CLIENT_TOOLCHAIN_FILE}.gen <>${CARLA_SERVER_TOOLCHAIN_FILE}.gen <&1) LIB_NAME=$(cut -d . -f 1,2 <<< "$PYTHON_VERSION" | tr -d .) LIB_NAME=${LIB_NAME:7} - if [[ -d "${BOOST_BASENAME}-install" ]] ; then - if [ -f "${BOOST_BASENAME}-install/lib/libboost_python${LIB_NAME}.a" ] ; then + if [[ -d "${BOOST_BASENAME}-server-install" && -d "${BOOST_BASENAME}-client-install" ]] ; then + if [ -f "${BOOST_BASENAME}-server-install/lib/libboost_system.a" ] && [ -f "${BOOST_BASENAME}-client-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 + rm -Rf ${BOOST_BASENAME}-client-source ${BOOST_BASENAME}-server-source BOOST_PACKAGE_BASENAME=boost_${BOOST_VERSION//./_} @@ -116,20 +202,31 @@ for PY_VERSION in ${PY_VERSION_LIST[@]} ; do end=$(date +%s) echo "Elapsed Time Extracting boost for Python: $(($end-$start)) seconds" - mkdir -p ${BOOST_BASENAME}-install/include - mv ${BOOST_PACKAGE_BASENAME} ${BOOST_BASENAME}-source + mkdir -p ${BOOST_BASENAME}-client-install/include + mkdir -p ${BOOST_BASENAME}-server-install/include + cp -r ${BOOST_PACKAGE_BASENAME} ${BOOST_BASENAME}-client-source + mv ${BOOST_PACKAGE_BASENAME} ${BOOST_BASENAME}-server-source - pushd ${BOOST_BASENAME}-source >/dev/null + BOOST_TOOLSET="clang" + BOOST_CXXFLAGS="${CARLA_CFLAGS} ${CARLA_CXXFLAGS}" - BOOST_TOOLSET="clang-10.0" - BOOST_CFLAGS="-fPIC -std=c++14 -DBOOST_ERROR_CODE_HEADER_ONLY" + pushd ${BOOST_BASENAME}-server-source >/dev/null + ./bootstrap.sh \ + --prefix="../${BOOST_BASENAME}-server-install" \ + --with-toolset="clang" \ + --with-libraries=system + ./b2 toolset="${BOOST_TOOLSET}" cxxflags="${BOOST_CXXFLAGS} ${CARLA_SERVER_CXXFLAGS}" linkflags="${CARLA_SERVER_LINKER_FLAGS}" --with-system --prefix="../${BOOST_BASENAME}-server-install" -j ${CARLA_BUILD_CONCURRENCY} stage release install + popd >/dev/null + + pushd ${BOOST_BASENAME}-client-source >/dev/null 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 \ + --prefix="../${BOOST_BASENAME}-client-install" \ + --with-toolset="clang" \ --with-libraries=python,filesystem,system,program_options \ --with-python=${py3} --with-python-root=${py3_root} @@ -139,19 +236,16 @@ for PY_VERSION in ${PY_VERSION_LIST[@]} ; do 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 - ./b2 toolset="${BOOST_TOOLSET}" cxxflags="${BOOST_CFLAGS}" --prefix="../${BOOST_BASENAME}-install" -j ${CARLA_BUILD_CONCURRENCY} install + ./b2 toolset="${BOOST_TOOLSET}" cxxflags="${BOOST_CXXFLAGS}" --prefix="../${BOOST_BASENAME}-client-install" -j ${CARLA_BUILD_CONCURRENCY} stage release install popd >/dev/null - rm -Rf ${BOOST_BASENAME}-source - rm ${BOOST_PACKAGE_BASENAME}.tar.gz + rm -Rf ${BOOST_BASENAME}-client-source ${BOOST_BASENAME}-server-source + rm ${BOOST_PACKAGE_BASENAME}.tar.gz* # 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 + cp -rf ${BOOST_BASENAME}-client-install/include/* ${LIBCARLA_INSTALL_CLIENT_FOLDER}/include/system + cp -rf ${BOOST_BASENAME}-client-install/lib/* ${LIBCARLA_INSTALL_CLIENT_FOLDER}/lib fi @@ -159,25 +253,26 @@ done unset BOOST_BASENAME + # ============================================================================== -# -- Get rpclib and compile it with libc++ and libstdc++ ----------------------- +# -- Get rpclib and compile it for server and client ------ # ============================================================================== RPCLIB_PATCH=v2.2.1_c5 -RPCLIB_BASENAME=rpclib-${RPCLIB_PATCH}-${CXX_TAG} +RPCLIB_BASENAME=rpclib-${RPCLIB_PATCH} -RPCLIB_LIBCXX_INCLUDE=${PWD}/${RPCLIB_BASENAME}-libcxx-install/include -RPCLIB_LIBCXX_LIBPATH=${PWD}/${RPCLIB_BASENAME}-libcxx-install/lib -RPCLIB_LIBSTDCXX_INCLUDE=${PWD}/${RPCLIB_BASENAME}-libstdcxx-install/include -RPCLIB_LIBSTDCXX_LIBPATH=${PWD}/${RPCLIB_BASENAME}-libstdcxx-install/lib +RPCLIB_SERVER_INCLUDE=${PWD}/${RPCLIB_BASENAME}-server-install/include +RPCLIB_SERVER_LIBPATH=${PWD}/${RPCLIB_BASENAME}-server-install/lib +RPCLIB_CLIENT_INCLUDE=${PWD}/${RPCLIB_BASENAME}-client-install/include +RPCLIB_CLIENT_LIBPATH=${PWD}/${RPCLIB_BASENAME}-client-install/lib -if [[ -d "${RPCLIB_BASENAME}-libcxx-install" && -d "${RPCLIB_BASENAME}-libstdcxx-install" ]] ; then +if [[ -d "${RPCLIB_BASENAME}-server-install" && -d "${RPCLIB_BASENAME}-client-install" ]] ; then log "${RPCLIB_BASENAME} already installed." else rm -Rf \ ${RPCLIB_BASENAME}-source \ - ${RPCLIB_BASENAME}-libcxx-build ${RPCLIB_BASENAME}-libstdcxx-build \ - ${RPCLIB_BASENAME}-libcxx-install ${RPCLIB_BASENAME}-libstdcxx-install + ${RPCLIB_BASENAME}-server-build ${RPCLIB_BASENAME}-client-build \ + ${RPCLIB_BASENAME}-server-install ${RPCLIB_BASENAME}-client-install log "Retrieving rpclib." @@ -186,71 +281,61 @@ else git clone -b ${RPCLIB_PATCH} https://github.com/carla-simulator/rpclib.git ${RPCLIB_BASENAME}-source end_download_time=$(date +%s) - echo "Elapsed Time downloading rpclib: $(($end_download_time-$start_download_time)) seconds" - log "Building rpclib with libc++." + log "Building rpclib for server." # rpclib does not use any cmake 3.9 feature. # As cmake 3.9 is not standard in Ubuntu 16.04, change cmake version to 3.5 sed -i s/"3.9.0"/"3.5.0"/g ${RPCLIB_BASENAME}-source/CMakeLists.txt - mkdir -p ${RPCLIB_BASENAME}-libcxx-build - - pushd ${RPCLIB_BASENAME}-libcxx-build >/dev/null - + mkdir -p ${RPCLIB_BASENAME}-server-build + pushd ${RPCLIB_BASENAME}-server-build >/dev/null cmake -G "Ninja" \ - -DCMAKE_CXX_FLAGS="-fPIC -std=c++14 -stdlib=libc++ -I${LLVM_INCLUDE} -Wl,-L${LLVM_LIBPATH} -DBOOST_NO_EXCEPTIONS -DASIO_NO_EXCEPTIONS ${UNREAL_HOSTED_CFLAGS}" \ - -DCMAKE_INSTALL_PREFIX="../${RPCLIB_BASENAME}-libcxx-install" \ + -DCMAKE_INSTALL_PREFIX="../${RPCLIB_BASENAME}-server-install" \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_SERVER_TOOLCHAIN_FILE}" \ ../${RPCLIB_BASENAME}-source - ninja - ninja install - popd >/dev/null - log "Building rpclib with libstdc++." - - mkdir -p ${RPCLIB_BASENAME}-libstdcxx-build - - pushd ${RPCLIB_BASENAME}-libstdcxx-build >/dev/null - + log "Building rpclib for client." + mkdir -p ${RPCLIB_BASENAME}-client-build + pushd ${RPCLIB_BASENAME}-client-build >/dev/null cmake -G "Ninja" \ - -DCMAKE_CXX_FLAGS="-fPIC -std=c++14" \ - -DCMAKE_INSTALL_PREFIX="../${RPCLIB_BASENAME}-libstdcxx-install" \ + -DCMAKE_INSTALL_PREFIX="../${RPCLIB_BASENAME}-client-install" \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_CLIENT_TOOLCHAIN_FILE}" \ ../${RPCLIB_BASENAME}-source - ninja - ninja install - popd >/dev/null - rm -Rf ${RPCLIB_BASENAME}-source ${RPCLIB_BASENAME}-libcxx-build ${RPCLIB_BASENAME}-libstdcxx-build - + rm -Rf ${RPCLIB_BASENAME}-source ${RPCLIB_BASENAME}-server-build ${RPCLIB_BASENAME}-client-build fi unset RPCLIB_BASENAME +cp -p -r ${RPCLIB_SERVER_INCLUDE}/* ${LIBCARLA_INSTALL_SERVER_FOLDER}/include/ +cp -p ${RPCLIB_SERVER_LIBPATH}/*.a ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib + # ============================================================================== -# -- Get GTest and compile it with libc++ -------------------------------------- +# -- Get GTest and compile it for server -------------------------------------- # ============================================================================== GTEST_VERSION=1.8.1 -GTEST_BASENAME=gtest-${GTEST_VERSION}-${CXX_TAG} +GTEST_BASENAME=gtest-${GTEST_VERSION} -GTEST_LIBCXX_INCLUDE=${PWD}/${GTEST_BASENAME}-libcxx-install/include -GTEST_LIBCXX_LIBPATH=${PWD}/${GTEST_BASENAME}-libcxx-install/lib -GTEST_LIBSTDCXX_INCLUDE=${PWD}/${GTEST_BASENAME}-libstdcxx-install/include -GTEST_LIBSTDCXX_LIBPATH=${PWD}/${GTEST_BASENAME}-libstdcxx-install/lib +GTEST_SERVER_INCLUDE=${PWD}/${GTEST_BASENAME}-server-install/include +GTEST_SERVER_LIBPATH=${PWD}/${GTEST_BASENAME}-server-install/lib +GTEST_CLIENT_INCLUDE=${PWD}/${GTEST_BASENAME}-client-install/include +GTEST_CLIENT_LIBPATH=${PWD}/${GTEST_BASENAME}-client-install/lib -if [[ -d "${GTEST_BASENAME}-libcxx-install" && -d "${GTEST_BASENAME}-libstdcxx-install" ]] ; then +if [[ -d "${GTEST_BASENAME}-server-install" && -d "${GTEST_BASENAME}-client-install" ]] ; then log "${GTEST_BASENAME} already installed." else rm -Rf \ ${GTEST_BASENAME}-source \ - ${GTEST_BASENAME}-libcxx-build ${GTEST_BASENAME}-libstdcxx-build \ - ${GTEST_BASENAME}-libcxx-install ${GTEST_BASENAME}-libstdcxx-install + ${GTEST_BASENAME}-server-build ${GTEST_BASENAME}-client-build \ + ${GTEST_BASENAME}-server-install ${GTEST_BASENAME}-client-install log "Retrieving Google Test." @@ -261,63 +346,52 @@ else end_download_time=$(date +%s) echo "Elapsed Time downloading rpclib: $(($end_download_time-$start_download_time)) seconds" - log "Building Google Test with libc++." - - mkdir -p ${GTEST_BASENAME}-libcxx-build + log "Building Google Test for server." - pushd ${GTEST_BASENAME}-libcxx-build >/dev/null + mkdir -p ${GTEST_BASENAME}-server-build + pushd ${GTEST_BASENAME}-server-build >/dev/null cmake -G "Ninja" \ - -DCMAKE_CXX_FLAGS="-std=c++14 -stdlib=libc++ -I${LLVM_INCLUDE} -Wl,-L${LLVM_LIBPATH} -DBOOST_NO_EXCEPTIONS -fno-exceptions ${UNREAL_HOSTED_CFLAGS}" \ - -DCMAKE_INSTALL_PREFIX="../${GTEST_BASENAME}-libcxx-install" \ + -DCMAKE_INSTALL_PREFIX="../${GTEST_BASENAME}-server-install" \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_SERVER_TOOLCHAIN_FILE}" \ ../${GTEST_BASENAME}-source - ninja - ninja install - popd >/dev/null - log "Building Google Test with libstdc++." - - mkdir -p ${GTEST_BASENAME}-libstdcxx-build - - pushd ${GTEST_BASENAME}-libstdcxx-build >/dev/null - + log "Building Google Test for client." + mkdir -p ${GTEST_BASENAME}-client-build + pushd ${GTEST_BASENAME}-client-build >/dev/null cmake -G "Ninja" \ - -DCMAKE_CXX_FLAGS="-std=c++14" \ - -DCMAKE_INSTALL_PREFIX="../${GTEST_BASENAME}-libstdcxx-install" \ + -DCMAKE_INSTALL_PREFIX="../${GTEST_BASENAME}-client-install" \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_CLIENT_TOOLCHAIN_FILE}" \ ../${GTEST_BASENAME}-source - ninja - ninja install - popd >/dev/null - rm -Rf ${GTEST_BASENAME}-source ${GTEST_BASENAME}-libcxx-build ${GTEST_BASENAME}-libstdcxx-build - + rm -Rf ${GTEST_BASENAME}-source ${GTEST_BASENAME}-server-build ${GTEST_BASENAME}-client-build fi unset GTEST_BASENAME # ============================================================================== -# -- Get Recast&Detour and compile it with libc++ ------------------------------ +# -- Get Recast&Detour and compile it for client ------------------------------ # ============================================================================== -RECAST_BASENAME=recast-${CXX_TAG} +RECAST_BASENAME=recast -RECAST_INCLUDE=${PWD}/${RECAST_BASENAME}-install/include -RECAST_LIBPATH=${PWD}/${RECAST_BASENAME}-install/lib +RECAST_CLIENT_INCLUDE=${PWD}/${RECAST_BASENAME}-client-install/include +RECAST_CLIENT_LIBPATH=${PWD}/${RECAST_BASENAME}-client-install/lib -if [[ -d "${RECAST_BASENAME}-install" && - -f "${RECAST_BASENAME}-install/bin/RecastBuilder" ]] ; then +if [[ -d "${RECAST_BASENAME}-client-install" && + -f "${RECAST_BASENAME}-client-install/bin/RecastBuilder" ]] ; then log "${RECAST_BASENAME} already installed." else rm -Rf \ ${RECAST_BASENAME}-source \ - ${RECAST_BASENAME}-build \ - ${RECAST_BASENAME}-install + ${RECAST_BASENAME}-client-build \ + ${RECAST_BASENAME}-client-install log "Retrieving Recast & Detour" @@ -332,33 +406,26 @@ else popd >/dev/null - log "Building Recast & Detour with libc++." - - mkdir -p ${RECAST_BASENAME}-build - - pushd ${RECAST_BASENAME}-build >/dev/null - + log "Building Recast & Detour for client." + mkdir -p ${RECAST_BASENAME}-client-build + pushd ${RECAST_BASENAME}-client-build >/dev/null cmake -G "Ninja" \ - -DCMAKE_CXX_FLAGS="-std=c++14 -fPIC" \ - -DCMAKE_INSTALL_PREFIX="../${RECAST_BASENAME}-install" \ + -DCMAKE_INSTALL_PREFIX="../${RECAST_BASENAME}-client-install" \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_CLIENT_TOOLCHAIN_FILE}" \ -DRECASTNAVIGATION_DEMO=False \ -DRECASTNAVIGATION_TEST=False \ ../${RECAST_BASENAME}-source - ninja - ninja install - popd >/dev/null - rm -Rf ${RECAST_BASENAME}-source ${RECAST_BASENAME}-build - + rm -Rf ${RECAST_BASENAME}-source ${RECAST_BASENAME}-client-build fi # make sure the RecastBuilder is corrctly copied -RECAST_INSTALL_DIR="${CARLA_BUILD_FOLDER}/../Util/DockerUtils/dist" -if [[ ! -f "${RECAST_INSTALL_DIR}/RecastBuilder" ]]; then - cp "${RECAST_BASENAME}-install/bin/RecastBuilder" "${RECAST_INSTALL_DIR}/" +RECAST_INSTALL_CLIENT_DIR="${CARLA_BUILD_FOLDER}/../Util/DockerUtils/dist" +if [[ ! -f "${RECAST_INSTALL_CLIENT_DIR}/RecastBuilder" ]]; then + cp "${RECAST_BASENAME}-client-install/bin/RecastBuilder" "${RECAST_INSTALL_CLIENT_DIR}/" fi unset RECAST_BASENAME @@ -370,14 +437,18 @@ unset RECAST_BASENAME 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/ -LIBPNG_LIBPATH=${PWD}/${LIBPNG_BASENAME}-install/lib +LIBPNG_CLIENT_INCLUDE=${PWD}/${LIBPNG_BASENAME}-client-install/include/ +LIBPNG_CLIENT_LIBPATH=${PWD}/${LIBPNG_BASENAME}-client-install/lib -if [[ -d ${LIBPNG_INSTALL} ]] ; then +if [[ -d ${LIBPNG_BASENAME}-client-install ]] ; then log "Libpng already installed." else + rm -Rf \ + ${LIBPNG_BASENAME}-source \ + ${LIBPNG_BASENAME}-client-build \ + ${LIBPNG_BASENAME}-client-install + log "Retrieving libpng." start=$(date +%s) @@ -393,15 +464,16 @@ else mv ${LIBPNG_BASENAME} ${LIBPNG_BASENAME}-source - pushd ${LIBPNG_BASENAME}-source >/dev/null - ./configure --prefix=${CARLA_BUILD_FOLDER}/${LIBPNG_INSTALL} + mkdir ${LIBPNG_BASENAME}-client-build + pushd ${LIBPNG_BASENAME}-client-build >/dev/null + ../${LIBPNG_BASENAME}-source/configure --prefix=${PWD}/../${LIBPNG_BASENAME}-client-install/ + make make install - popd >/dev/null rm -Rf libpng-${LIBPNG_VERSION}.tar.xz - rm -Rf ${LIBPNG_BASENAME}-source + rm -Rf ${LIBPNG_BASENAME}-source ${LIBPNG_BASENAME}-client-build fi # ============================================================================== @@ -414,15 +486,17 @@ XERCESC_BASENAME=xerces-c-${XERCESC_VERSION} XERCESC_TEMP_FOLDER=${XERCESC_BASENAME} XERCESC_REPO=https://archive.apache.org/dist/xerces/c/3/sources/xerces-c-${XERCESC_VERSION}.tar.gz -XERCESC_SRC_DIR=${XERCESC_BASENAME}-source -XERCESC_INSTALL_DIR=${XERCESC_BASENAME}-install -XERCESC_INSTALL_SERVER_DIR=${XERCESC_BASENAME}-install-server -XERCESC_LIB=${XERCESC_INSTALL_DIR}/lib/libxerces-c.a -XERCESC_SERVER_LIB=${XERCESC_INSTALL_SERVER_DIR}/lib/libxerces-c.a +XERCESC_CLIENT_LIB=${XERCESC_BASENAME}-client-install/lib/libxerces-c.a +XERCESC_SERVER_LIB=${XERCESC_BASENAME}-server-install/lib/libxerces-c.a -if [[ -d ${XERCESC_INSTALL_DIR} && -d ${XERCESC_INSTALL_SERVER_DIR} ]] ; then +if [[ -d ${XERCESC_BASENAME}-client-install && -d ${XERCESC_BASENAME}-server-install ]] ; then log "Xerces-c already installed." else + rm -Rf \ + ${XERCESC_BASENAME}-source \ + ${XERCESC_BASENAME}-server-build ${XERCESC_BASENAME}-client-build \ + ${XERCESC_BASENAME}-server-install ${XERCESC_BASENAME}-client-install + log "Retrieving xerces-c." start=$(date +%s) wget ${XERCESC_REPO} @@ -444,50 +518,44 @@ else end=$(date +%s) echo "Elapsed Time Extracting xerces-c: $(($end-$start)) seconds" - mv ${XERCESC_BASENAME} ${XERCESC_SRC_DIR} - mkdir -p ${XERCESC_INSTALL_DIR} - mkdir -p ${XERCESC_SRC_DIR}/build - - pushd ${XERCESC_SRC_DIR}/build >/dev/null + mv ${XERCESC_BASENAME} ${XERCESC_BASENAME}-source + log "Building xerces-c for server." + mkdir -p ${XERCESC_BASENAME}-server-build + pushd ${XERCESC_BASENAME}-server-build >/dev/null cmake -G "Ninja" \ - -DCMAKE_CXX_FLAGS="-std=c++14 -fPIC -w" \ - -DCMAKE_INSTALL_PREFIX="../../${XERCESC_INSTALL_DIR}" \ + -DCMAKE_INSTALL_PREFIX="../${XERCESC_BASENAME}-server-install" \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_SERVER_TOOLCHAIN_FILE}" \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_SHARED_LIBS=OFF \ -Dtranscoder=gnuiconv \ -Dnetwork=OFF \ - .. + ../${XERCESC_BASENAME}-source ninja ninja install - popd >/dev/null - mkdir -p ${XERCESC_INSTALL_SERVER_DIR} - - pushd ${XERCESC_SRC_DIR}/build >/dev/null + log "Building xerces-c for client." + mkdir -p ${XERCESC_BASENAME}-client-build + pushd ${XERCESC_BASENAME}-client-build >/dev/null cmake -G "Ninja" \ - -DCMAKE_CXX_FLAGS="-std=c++14 -stdlib=libc++ -fPIC -w -I${LLVM_INCLUDE} -L${LLVM_LIBPATH}" \ - -DCMAKE_INSTALL_PREFIX="../../${XERCESC_INSTALL_SERVER_DIR}" \ + -DCMAKE_INSTALL_PREFIX="../${XERCESC_BASENAME}-client-install" \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_CLIENT_TOOLCHAIN_FILE}" \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_SHARED_LIBS=OFF \ -Dtranscoder=gnuiconv \ -Dnetwork=OFF \ - .. + ../${XERCESC_BASENAME}-source ninja ninja install - popd >/dev/null rm -Rf ${XERCESC_BASENAME}.tar.gz - rm -Rf ${XERCESC_SRC_DIR} + rm -Rf ${XERCESC_BASENAME}-source ${XERCESC_BASENAME}-client-build ${XERCESC_BASENAME}-server-build fi -mkdir -p ${LIBCARLA_INSTALL_CLIENT_FOLDER}/lib/ -cp ${XERCESC_LIB} ${LIBCARLA_INSTALL_CLIENT_FOLDER}/lib/ - -mkdir -p ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ +cp ${XERCESC_CLIENT_LIB} ${LIBCARLA_INSTALL_CLIENT_FOLDER}/lib/ cp -p ${XERCESC_SERVER_LIB} ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ # ============================================================================== @@ -498,12 +566,9 @@ EIGEN_VERSION=3.1.0 EIGEN_REPO=https://gitlab.com/libeigen/eigen/-/archive/${EIGEN_VERSION}/eigen-${EIGEN_VERSION}.tar.gz EIGEN_BASENAME=eigen-${EIGEN_VERSION} -EIGEN_SRC_DIR=eigen-${EIGEN_VERSION}-src -EIGEN_INSTALL_DIR=eigen-${EIGEN_VERSION}-install -EIGEN_INCLUDE=${EIGEN_INSTALL_DIR}/include +EIGEN_INCLUDE=${EIGEN_BASENAME}-server-install/include - -if [[ -d ${EIGEN_INSTALL_DIR} ]] ; then +if [[ -d ${EIGEN_BASENAME}-server-install ]] ; then log "Eigen already installed." else log "Retrieving Eigen." @@ -516,21 +581,31 @@ else log "Extracting Eigen." start=$(date +%s) tar -xzf ${EIGEN_BASENAME}.tar.gz + end=$(date +%s) echo "Elapsed Time Extracting EIGEN: $(($end-$start)) seconds" - mv ${EIGEN_BASENAME} ${EIGEN_SRC_DIR} + mv ${EIGEN_BASENAME} ${EIGEN_BASENAME}-source + # patch some files + cp $CARLA_ROOT_FOLDER/Util/Patches/Eigen${EIGEN_VERSION}/Functors.h "${EIGEN_BASENAME}-source/Eigen/src/Core/Functors.h" + cp $CARLA_ROOT_FOLDER/Util/Patches/Eigen${EIGEN_VERSION}/VectorBlock.h "${EIGEN_BASENAME}-source/Eigen/src/Core/VectorBlock.h" + cp $CARLA_ROOT_FOLDER/Util/Patches/Eigen${EIGEN_VERSION}/PacketMath.h "${EIGEN_BASENAME}-source/Eigen/src/Core/arch/SSE/PacketMath.h" + cp $CARLA_ROOT_FOLDER/Util/Patches/Eigen${EIGEN_VERSION}/SelfadjointMatrixVector.h "${EIGEN_BASENAME}-source/Eigen/src/Core/products/SelfadjointMatrixVector.h" + cp $CARLA_ROOT_FOLDER/Util/Patches/Eigen${EIGEN_VERSION}/Macros.h "${EIGEN_BASENAME}-source/Eigen/src/Core/util/Macros.h" + cp $CARLA_ROOT_FOLDER/Util/Patches/Eigen${EIGEN_VERSION}/ArrayCwiseUnaryOps.h "${EIGEN_BASENAME}-source/Eigen/src/plugins/ArrayCwiseUnaryOps.h" + cp $CARLA_ROOT_FOLDER/Util/Patches/Eigen${EIGEN_VERSION}/MatrixCwiseUnaryOps.h "${EIGEN_BASENAME}-source/Eigen/src/plugins/MatrixCwiseUnaryOps.h" + mkdir -p ${EIGEN_INCLUDE}/unsupported - mv ${EIGEN_SRC_DIR}/Eigen ${EIGEN_INCLUDE} - mv ${EIGEN_SRC_DIR}/unsupported/Eigen ${EIGEN_INCLUDE}/unsupported/Eigen + mv ${EIGEN_BASENAME}-source/Eigen ${EIGEN_INCLUDE} + mv ${EIGEN_BASENAME}-source/unsupported/Eigen ${EIGEN_INCLUDE}/unsupported/Eigen rm -Rf ${EIGEN_BASENAME}.tar.gz - rm -Rf ${EIGEN_SRC_DIR} + rm -Rf ${EIGEN_BASENAME}-source fi -mkdir -p ${LIBCARLA_INSTALL_SERVER_FOLDER}/include/ cp -p -r ${EIGEN_INCLUDE}/* ${LIBCARLA_INSTALL_SERVER_FOLDER}/include/ + if ${USE_CHRONO} ; then # ============================================================================== @@ -541,12 +616,9 @@ if ${USE_CHRONO} ; then EIGEN_REPO=https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.tar.gz EIGEN_BASENAME=eigen-${EIGEN_VERSION} - EIGEN_SRC_DIR=eigen-${EIGEN_VERSION}-src - EIGEN_INSTALL_DIR=eigen-${EIGEN_VERSION}-install - EIGEN_INCLUDE=${EIGEN_INSTALL_DIR}/include + EIGEN_INCLUDE=${EIGEN_BASENAME}-server-install/include - - if [[ -d ${EIGEN_INSTALL_DIR} ]] ; then + if [[ -d ${EIGEN_BASENAME}-server-install ]] ; then log "Eigen already installed." else log "Retrieving Eigen." @@ -563,61 +635,58 @@ if ${USE_CHRONO} ; then end=$(date +%s) echo "Elapsed Time Extracting for Eigen: $(($end-$start)) seconds" - mv ${EIGEN_BASENAME} ${EIGEN_SRC_DIR} + mv ${EIGEN_BASENAME} ${EIGEN_BASENAME}-source mkdir -p ${EIGEN_INCLUDE}/unsupported - mv ${EIGEN_SRC_DIR}/Eigen ${EIGEN_INCLUDE} - mv ${EIGEN_SRC_DIR}/unsupported/Eigen ${EIGEN_INCLUDE}/unsupported/Eigen + mv ${EIGEN_BASENAME}-source/Eigen ${EIGEN_INCLUDE} + mv ${EIGEN_BASENAME}-source/unsupported/Eigen ${EIGEN_INCLUDE}/unsupported/Eigen rm -Rf ${EIGEN_BASENAME}.tar.gz - rm -Rf ${EIGEN_SRC_DIR} + rm -Rf ${EIGEN_BASENAME}-source + + cp -p -r ${EIGEN_INCLUDE}/* ${LIBCARLA_INSTALL_SERVER_FOLDER}/include/ fi - mkdir -p ${LIBCARLA_INSTALL_SERVER_FOLDER}/include/ - cp -p -r ${EIGEN_INCLUDE}/* ${LIBCARLA_INSTALL_SERVER_FOLDER}/include/ # ============================================================================== - # -- Get Chrono and compile it with libc++ ------------------------------------- + # -- Get Chrono and compile it for server ------------------------------------- # ============================================================================== CHRONO_TAG=6.0.0 # CHRONO_TAG=develop CHRONO_REPO=https://github.com/projectchrono/chrono.git + CHRONO_BASENAME=chrono CHRONO_SRC_DIR=chrono-source - CHRONO_INSTALL_DIR=chrono-install + CHRONO_INSTALL_CLIENT_DIR=chrono-install - if [[ -d ${CHRONO_INSTALL_DIR} ]] ; then + if [[ -d ${CHRONO_BASENAME}-server-install ]] ; then log "chrono library already installed." else log "Retrieving chrono library." start=$(date +%s) - git clone --depth 1 --branch ${CHRONO_TAG} ${CHRONO_REPO} ${CHRONO_SRC_DIR} + git clone --depth 1 --branch ${CHRONO_TAG} ${CHRONO_REPO} ${CHRONO_BASENAME}-source end=$(date +%s) echo "Elapsed Time dowloading chrono: $(($end-$start)) seconds" - mkdir -p ${CHRONO_SRC_DIR}/build - - pushd ${CHRONO_SRC_DIR}/build >/dev/null - + mkdir -p ${CHRONO_BASENAME}-server-build + pushd ${CHRONO_SRC_DIR}/server-build >/dev/null cmake -G "Ninja" \ - -DCMAKE_CXX_FLAGS="-fPIC -std=c++14 -stdlib=libc++ -I${LLVM_INCLUDE} -L${LLVM_LIBPATH} -Wno-unused-command-line-argument ${UNREAL_HOSTED_CFLAGS}" \ - -DEIGEN3_INCLUDE_DIR="../../${EIGEN_INCLUDE}" \ - -DCMAKE_INSTALL_PREFIX="../../${CHRONO_INSTALL_DIR}" \ + -DCMAKE_CXX_FLAGS="-Wno-unused-command-line-argument" \ + -DCMAKE_INSTALL_PREFIX="../${CHRONO_BASENAME}-server-install" \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_SERVER_TOOLCHAIN_FILE}" \ -DCMAKE_BUILD_TYPE=Release \ -DENABLE_MODULE_VEHICLE=ON \ + -DEIGEN3_INCLUDE_DIR="../../${EIGEN_INCLUDE}" \ .. ninja ninja install - popd >/dev/null rm -Rf ${CHRONO_SRC_DIR} fi - mkdir -p ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ - mkdir -p ${LIBCARLA_INSTALL_SERVER_FOLDER}/include/ - cp -p ${CHRONO_INSTALL_DIR}/lib/*.so ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ - cp -p -r ${CHRONO_INSTALL_DIR}/include/* ${LIBCARLA_INSTALL_SERVER_FOLDER}/include/ + cp -p ${CHRONO_INSTALL_CLIENT_DIR}/lib/*.a ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ + cp -p -r ${CHRONO_INSTALL_CLIENT_DIR}/include/* ${LIBCARLA_INSTALL_SERVER_FOLDER}/include/ fi # ============================================================================== @@ -626,19 +695,24 @@ fi SQLITE_VERSION=sqlite-autoconf-3340100 SQLITE_REPO=https://www.sqlite.org/2021/${SQLITE_VERSION}.tar.gz - SQLITE_TAR=${SQLITE_VERSION}.tar.gz -SQLITE_SOURCE_DIR=sqlite-src -SQLITE_INSTALL_DIR=sqlite-install +SQLITE_BASENAME=sqlite -SQLITE_INCLUDE_DIR=${PWD}/${SQLITE_INSTALL_DIR}/include -SQLITE_LIB=${PWD}/${SQLITE_INSTALL_DIR}/lib/libsqlite3.a -SQLITE_FULL_LIB=${PWD}/${SQLITE_INSTALL_DIR}/lib/ -SQLITE_EXE=${PWD}/${SQLITE_INSTALL_DIR}/bin/sqlite3 +SQLITE_SERVER_INCLUDE_DIR=${PWD}/${SQLITE_BASENAME}-server-install/include +SQLITE_SERVER_LIB=${PWD}/${SQLITE_BASENAME}-server-install/lib/libsqlite3.a +SQLITE_CLIENT_INCLUDE_DIR=${PWD}/${SQLITE_BASENAME}-client-install/include +SQLITE_CLIENT_LIB=${PWD}/${SQLITE_BASENAME}-client-install/lib/libsqlite3.a +SQLITE_EXE=${PWD}/${SQLITE_BASENAME}-client-install/bin/sqlite3 -if [[ -d ${SQLITE_INSTALL_DIR} ]] ; then +if [[ -d ${SQLITE_BASENAME}-server-install && -d ${SQLITE_BASENAME}-client-install ]] ; then log "Sqlite already installed." else + rm -Rf \ + ${SQLITE_BASENAME}-source \ + ${SQLITE_BASENAME}-build \ + ${SQLITE_BASENAME}-client-install \ + ${SQLITE_BASENAME}-server-install + log "Retrieving Sqlite3" start=$(date +%s) @@ -653,108 +727,94 @@ else end=$(date +%s) echo "Elapsed Time Extracting for SQlite: $(($end-$start)) seconds" - mv ${SQLITE_VERSION} ${SQLITE_SOURCE_DIR} - - mkdir ${SQLITE_INSTALL_DIR} + mv ${SQLITE_VERSION} ${SQLITE_BASENAME}-source - pushd ${SQLITE_SOURCE_DIR} >/dev/null - - export CFLAGS="-fPIC -w" - ./configure --prefix=${PWD}/../sqlite-install/ - make + mkdir ${SQLITE_BASENAME}-client-build + pushd ${SQLITE_BASENAME}-client-build >/dev/null + ../${SQLITE_BASENAME}-source/configure CFLAGS="${CARLA_CFLAGS} -w" --prefix=${PWD}/../${SQLITE_BASENAME}-client-install/ make install + popd >/dev/null + mkdir ${SQLITE_BASENAME}-server-build + pushd ${SQLITE_BASENAME}-server-build >/dev/null + ../${SQLITE_BASENAME}-source/configure CFLAGS="${CARLA_SERVER_CFLAGS} -w" --prefix=${PWD}/../${SQLITE_BASENAME}-server-install/ + make install popd >/dev/null + rm -Rf ${SQLITE_TAR} - rm -Rf ${SQLITE_SOURCE_DIR} + rm -Rf ${SQLITE_BASENAME}-source ${SQLITE_BASENAME}-client-build ${SQLITE_BASENAME}-server-build fi -mkdir -p ${LIBCARLA_INSTALL_CLIENT_FOLDER}/lib/ -cp ${SQLITE_LIB} ${LIBCARLA_INSTALL_CLIENT_FOLDER}/lib/ - -mkdir -p ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ -cp -p -r ${SQLITE_FULL_LIB} ${LIBCARLA_INSTALL_SERVER_FOLDER} +cp ${SQLITE_CLIENT_LIB} ${LIBCARLA_INSTALL_CLIENT_FOLDER}/lib/ +cp -p -r ${SQLITE_SERVER_LIB}* ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ # ============================================================================== # -- Get and compile PROJ ------------------------------------------------------ # ============================================================================== -PROJ_VERSION=proj-7.2.1 -PROJ_REPO=https://download.osgeo.org/proj/${PROJ_VERSION}.tar.gz +PROJ_VERSION=7.2 +PROJ_REPO=https://github.com/OSGeo/PROJ -PROJ_TAR=${PROJ_VERSION}.tar.gz -PROJ_SRC_DIR=proj-src -PROJ_INSTALL_DIR=proj-install -PROJ_INSTALL_SERVER_DIR=proj-install-server -PROJ_INSTALL_DIR_FULL=${PWD}/${PROJ_INSTALL_DIR} -PROJ_INSTALL_SERVER_DIR_FULL=${PWD}/${PROJ_INSTALL_SERVER_DIR} -PROJ_LIB=${PROJ_INSTALL_DIR_FULL}/lib/libproj.a -PROJ_SERVER_LIB=${PROJ_INSTALL_SERVER_DIR_FULL}/lib/libproj.a +PROJ_BASENAME=proj +PROJ_CLIENT_LIBPATH=${PWD}/${PROJ_BASENAME}-client-install/lib +PROJ_CLIENT_LIB=${PROJ_CLIENT_LIBPATH}/libproj.a +PROJ_SERVER_LIB=${PWD}/${PROJ_BASENAME}-server-install/lib/libproj.a +PROJ_CLIENT_INCLUDE=${PWD}/${PROJ_BASENAME}-client-install/include -if [[ -d ${PROJ_INSTALL_DIR} && -d ${PROJ_INSTALL_SERVER_DIR_FULL} ]] ; then +if [[ -d ${PROJ_BASENAME}-client-install && -d ${PROJ_BASENAME}-server-install ]] ; then log "PROJ already installed." else + rm -Rf \ + ${PROJ_BASENAME}-source \ + ${PROJ_BASENAME}-server-build ${PROJ_BASENAME}-client-build \ + ${PROJ_BASENAME}-server-install ${PROJ_BASENAME}-client-install + log "Retrieving PROJ" start=$(date +%s) - wget ${PROJ_REPO} + git clone -b ${PROJ_VERSION} --depth 1 ${PROJ_REPO} ${PROJ_BASENAME}-source end=$(date +%s) echo "Elapsed Time: $(($end-$start)) seconds" - log "Extracting PROJ" - start=$(date +%s) - tar -xzf ${PROJ_TAR} - end=$(date +%s) - echo "Elapsed Time Extracting for PROJ: $(($end-$start)) seconds" - - mv ${PROJ_VERSION} ${PROJ_SRC_DIR} - - mkdir -p ${PROJ_SRC_DIR}/build - mkdir -p ${PROJ_INSTALL_DIR} - - pushd ${PROJ_SRC_DIR}/build >/dev/null - - cmake -G "Ninja" .. \ - -DCMAKE_CXX_FLAGS="-std=c++14 -fPIC" \ - -DSQLITE3_INCLUDE_DIR=${SQLITE_INCLUDE_DIR} -DSQLITE3_LIBRARY=${SQLITE_LIB} \ + mkdir -p ${PROJ_BASENAME}-client-build + pushd ${PROJ_BASENAME}-client-build >/dev/null + cmake -G "Ninja" \ + -DCMAKE_INSTALL_PREFIX=../${PROJ_BASENAME}-client-install \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_CLIENT_TOOLCHAIN_FILE}" \ + -DSQLITE3_INCLUDE_DIR=${SQLITE_CLIENT_INCLUDE_DIR} -DSQLITE3_LIBRARY=${SQLITE_CLIENT_LIB} \ -DEXE_SQLITE3=${SQLITE_EXE} \ -DENABLE_TIFF=OFF -DENABLE_CURL=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_PROJSYNC=OFF \ -DCMAKE_BUILD_TYPE=Release -DBUILD_PROJINFO=OFF \ -DBUILD_CCT=OFF -DBUILD_CS2CS=OFF -DBUILD_GEOD=OFF -DBUILD_GIE=OFF \ -DBUILD_PROJ=OFF -DBUILD_TESTING=OFF \ - -DCMAKE_INSTALL_PREFIX=${PROJ_INSTALL_DIR_FULL} + ../${PROJ_BASENAME}-source ninja ninja install - popd >/dev/null - mkdir -p ${PROJ_INSTALL_SERVER_DIR} - - pushd ${PROJ_SRC_DIR}/build >/dev/null - - cmake -G "Ninja" .. \ - -DCMAKE_CXX_FLAGS="-std=c++14 -fPIC -stdlib=libc++ -I${LLVM_INCLUDE} -Wl,-L${LLVM_LIBPATH}" \ - -DSQLITE3_INCLUDE_DIR=${SQLITE_INCLUDE_DIR} -DSQLITE3_LIBRARY=${SQLITE_LIB} \ + mkdir -p ${PROJ_BASENAME}-server-build + pushd ${PROJ_BASENAME}-server-build >/dev/null + cmake -G "Ninja" \ + -DCMAKE_INSTALL_PREFIX=../${PROJ_BASENAME}-server-install \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_SERVER_TOOLCHAIN_FILE}" \ + -DSQLITE3_INCLUDE_DIR=${SQLITE_SERVER_INCLUDE_DIR} -DSQLITE3_LIBRARY=${SQLITE_SERVER_LIB} \ -DEXE_SQLITE3=${SQLITE_EXE} \ -DENABLE_TIFF=OFF -DENABLE_CURL=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_PROJSYNC=OFF \ -DCMAKE_BUILD_TYPE=Release -DBUILD_PROJINFO=OFF \ -DBUILD_CCT=OFF -DBUILD_CS2CS=OFF -DBUILD_GEOD=OFF -DBUILD_GIE=OFF \ -DBUILD_PROJ=OFF -DBUILD_TESTING=OFF \ - -DCMAKE_INSTALL_PREFIX=${PROJ_INSTALL_SERVER_DIR_FULL} + ../${PROJ_BASENAME}-source ninja ninja install - popd >/dev/null rm -Rf ${PROJ_TAR} - rm -Rf ${PROJ_SRC_DIR} + rm -Rf ${PROJ_BASENAME}-source ${PROJ_BASENAME}-client-build ${PROJ_BASENAME}-server-build fi -cp ${PROJ_LIB} ${LIBCARLA_INSTALL_CLIENT_FOLDER}/lib/ - -mkdir -p ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ +cp ${PROJ_CLIENT_LIB} ${LIBCARLA_INSTALL_CLIENT_FOLDER}/lib/ cp -p ${PROJ_SERVER_LIB} ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ # ============================================================================== @@ -765,13 +825,13 @@ PATCHELF_VERSION=0.12 PATCHELF_REPO=https://github.com/NixOS/patchelf/archive/${PATCHELF_VERSION}.tar.gz PATCHELF_TAR=${PATCHELF_VERSION}.tar.gz -PATCHELF_SOURCE_DIR=patchelf-src -PATCHELF_INSTALL_DIR=patchelf-install +PATCHELF_SRC_DIR=patchelf-src +PATCHELF_INSTALL_CLIENT_DIR=patchelf-client-install -PATCHELF_INCLUDE_DIR=${PWD}/${PATCHELF_INSTALL_DIR}/include -PATCHELF_EXE=${PWD}/${PATCHELF_INSTALL_DIR}/bin/patchelf +PATCHELF_INCLUDE_DIR=${PWD}/${PATCHELF_INSTALL_CLIENT_DIR}/include +PATCHELF_EXE=${PWD}/${PATCHELF_INSTALL_CLIENT_DIR}/bin/patchelf -if [[ -d ${PATCHELF_INSTALL_DIR} ]] ; then +if [[ -d ${PATCHELF_INSTALL_CLIENT_DIR} ]] ; then log "Patchelf already installed." else log "Retrieving patchelf" @@ -787,24 +847,23 @@ else end=$(date +%s) echo "Elapsed Time Extracting patchelf: $(($end-$start)) seconds" - mv patchelf-${PATCHELF_VERSION} ${PATCHELF_SOURCE_DIR} + mv patchelf-${PATCHELF_VERSION} ${PATCHELF_SRC_DIR} - mkdir ${PATCHELF_INSTALL_DIR} + mkdir ${PATCHELF_INSTALL_CLIENT_DIR} - pushd ${PATCHELF_SOURCE_DIR} >/dev/null + pushd ${PATCHELF_SRC_DIR} >/dev/null ./bootstrap.sh - ./configure --prefix=${PWD}/../${PATCHELF_INSTALL_DIR} + ./configure --prefix=${PWD}/../${PATCHELF_INSTALL_CLIENT_DIR} make make install popd >/dev/null rm -Rf ${PATCHELF_TAR} - rm -Rf ${PATCHELF_SOURCE_DIR} + rm -Rf ${PATCHELF_SRC_DIR} fi -mkdir -p ${LIBCARLA_INSTALL_CLIENT_FOLDER}/bin/ cp ${PATCHELF_EXE} ${LIBCARLA_INSTALL_CLIENT_FOLDER}/bin/ # ============================================================================== @@ -815,7 +874,7 @@ if ${USE_PYTORCH} ; then LIBTORCH_BASENAME=libtorch - LIBTORCH_PATH=${PWD}/${LIBTORCH_BASENAME} + LIBTORCH_PATH=${PWD}/${LIBTORCH_BASENAME}-server-install LIBTORCH_INCLUDE=${LIBTORCH_PATH}/include LIBTORCH_LIB=${LIBTORCH_PATH}/lib LIBTORCH_ZIPFILE=libtorch-shared-with-deps-1.11.0+cu113.zip @@ -846,6 +905,7 @@ if ${USE_PYTORCH} ; then cmake -DCMAKE_PREFIX_PATH="${LIBTORCH_PATH}" \ -DCMAKE_CUDA_COMPILER="/usr/local/cuda/bin/nvcc" \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_SERVER_TOOLCHAIN_FILE}" \ -DCMAKE_INSTALL_PREFIX="${LIB_INSTALL}" \ -DCMAKE_CUDA_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_37,code=sm_37 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_52,code=sm_52 -gencode=arch=compute_53,code=sm_53 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_61,code=sm_61 -gencode=arch=compute_62,code=sm_62 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_72,code=sm_72 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_80,code=sm_80 -gencode=arch=compute_86,code=sm_86 -gencode=arch=compute_87,code=sm_87 -Wno-deprecated-gpu-targets" \ -DWITH_CUDA=ON \ @@ -860,29 +920,28 @@ if ${USE_PYTORCH} ; then log "Build libtorch scatter" #LibtorchScatter LIBTORCHSCATTER_BASENAME=libtorchscatter - LIBTORCHSCATTER_SOURCE_DIR=${PWD}/${LIBTORCHSCATTER_BASENAME}-source - LIBTORCHSCATTER_INSTALL_DIR=${PWD}/${LIBTORCHSCATTER_BASENAME}-install - LIBTORCHSCATTER_INCLUDE=${LIBTORCHSCATTER_INSTALL_DIR}/include - LIBTORCHSCATTER_LIB=${LIBTORCHSCATTER_INSTALL_DIR}/lib + LIBTORCHSCATTER_SRC_DIR=${PWD}/${LIBTORCHSCATTER_BASENAME}-source + LIBTORCHSCATTER_INSTALL_SERVER_DIR=${PWD}/${LIBTORCHSCATTER_BASENAME}-server-install + LIBTORCHSCATTER_INCLUDE=${LIBTORCHSCATTER_INSTALL_SERVER_DIR}/include + LIBTORCHSCATTER_LIB=${LIBTORCHSCATTER_INSTALL_SERVER_DIR}/lib LIBTORCHSCATTER_REPO="https://github.com/rusty1s/pytorch_scatter.git" - build_torch_extension ${LIBTORCHSCATTER_SOURCE_DIR} ${LIBTORCHSCATTER_INSTALL_DIR} "${LIBTORCHSCATTER_REPO}" + build_torch_extension ${LIBTORCHSCATTER_SRC_DIR} ${LIBTORCHSCATTER_INSTALL_SERVER_DIR} "${LIBTORCHSCATTER_REPO}" log "Build libtorch cluster" LIBTORCHCLUSTER_BASENAME=libtorchcluster - LIBTORCHCLUSTER_SOURCE_DIR=${PWD}/${LIBTORCHCLUSTER_BASENAME}-source - LIBTORCHCLUSTER_INSTALL_DIR=${PWD}/${LIBTORCHCLUSTER_BASENAME}-install - LIBTORCHCLUSTER_INCLUDE=${LIBTORCHCLUSTER_INSTALL_DIR}/include - LIBTORCHCLUSTER_LIB=${LIBTORCHCLUSTER_INSTALL_DIR}/lib + LIBTORCHCLUSTER_SRC_DIR=${PWD}/${LIBTORCHCLUSTER_BASENAME}-source + LIBTORCHCLUSTER_INSTALL_SERVER_DIR=${PWD}/${LIBTORCHCLUSTER_BASENAME}-server-install + LIBTORCHCLUSTER_INCLUDE=${LIBTORCHCLUSTER_INSTALL_SERVER_DIR}/include + LIBTORCHCLUSTER_LIB=${LIBTORCHCLUSTER_INSTALL_SERVER_DIR}/lib LIBTORCHCLUSTER_REPO="https://github.com/rusty1s/pytorch_cluster.git" - build_torch_extension ${LIBTORCHCLUSTER_SOURCE_DIR} ${LIBTORCHCLUSTER_INSTALL_DIR} "${LIBTORCHCLUSTER_REPO}" + build_torch_extension ${LIBTORCHCLUSTER_SRC_DIR} ${LIBTORCHCLUSTER_INSTALL_SERVER_DIR} "${LIBTORCHCLUSTER_REPO}" - mkdir -p ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ cp -p ${LIBTORCH_LIB}/*.a ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ cp -p ${LIBTORCH_LIB}/*.so* ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ - cp -p ${LIBTORCHSCATTER_LIB}/*.so ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ - cp -p ${LIBTORCHCLUSTER_LIB}/*.so ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ + cp -p ${LIBTORCHSCATTER_LIB}/*.so* ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ + cp -p ${LIBTORCHCLUSTER_LIB}/*.so* ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ mkdir -p ${CARLAUE4_PLUGIN_ROOT_FOLDER}/Binaries/Linux/ cp -p ${LIBTORCH_LIB}/*.so* ${CARLAUE4_PLUGIN_ROOT_FOLDER}/Binaries/Linux/ @@ -890,143 +949,108 @@ if ${USE_PYTORCH} ; then cp -p ${LIBTORCHCLUSTER_LIB}/*.so* ${CARLAUE4_PLUGIN_ROOT_FOLDER}/Binaries/Linux/ fi + # ============================================================================== # -- Download Fast DDS and dependencies ---------------------------------------- # ============================================================================== -FASTDDS_BASENAME=fast-dds -FASTDDS_INSTALL_DIR=${PWD}/${FASTDDS_BASENAME}-install -FASTDDS_INCLUDE=${FASTDDS_INSTALL_DIR}/include -FASTDDS_LIB=${FASTDDS_INSTALL_DIR}/lib +FASTDDS_BASENAME=${PWD}/fast-dds +FASTDDS_SERVER_INCLUDE=${FASTDDS_BASENAME}-server-install/include +FASTDDS_SERVER_LIB=${FASTDDS_BASENAME}-server-install/lib if ${USE_ROS2} ; then - function build_fastdds_extension { - LIB_SOURCE=$1 - LIB_REPO=$2 - LIB_BRANCH=$3 - if [[ ! -d ${LIB_SOURCE} ]] ; then - mkdir -p ${LIB_SOURCE} - log "${LIB_REPO}" - start=$(date +%s) - git clone --depth 1 --branch ${LIB_BRANCH} ${LIB_REPO} ${LIB_SOURCE} - end=$(date +%s) - echo "Elapsed Time dowloading fastdds extension: $(($end-$start)) seconds" - mkdir -p ${LIB_SOURCE}/build - fi - } - if [[ ! -d ${FASTDDS_INSTALL_DIR} ]] ; then - mkdir -p ${FASTDDS_INSTALL_DIR} - log "Build foonathan memory vendor" - FOONATHAN_MEMORY_VENDOR_BASENAME=foonathan-memory-vendor - FOONATHAN_MEMORY_VENDOR_SOURCE_DIR=${PWD}/${FOONATHAN_MEMORY_VENDOR_BASENAME}-source + if [[ -d ${FASTDDS_BASENAME}-server-install ]] ; then + log "FastDDS already installed." + else + rm -Rf \ + ${FASTDDS_BASENAME}-source \ + ${FASTDDS_BASENAME}-server-build \ + ${FASTDDS_BASENAME}-server-install + mkdir -p ${FASTDDS_BASENAME}-server-install/lib + + log "Build fast dds" + FAST_DDS_LIB_REPO="https://github.com/eProsima/Fast-DDS.git" + FAST_DDS_LIB_BRANCH=2.11.3 + # dependency foonath is not a submodule FOONATHAN_MEMORY_VENDOR_REPO="https://github.com/eProsima/foonathan_memory_vendor.git" FOONATHAN_MEMORY_VENDOR_BRANCH=master - build_fastdds_extension ${FOONATHAN_MEMORY_VENDOR_SOURCE_DIR} "${FOONATHAN_MEMORY_VENDOR_REPO}" "${FOONATHAN_MEMORY_VENDOR_BRANCH}" - pushd ${FOONATHAN_MEMORY_VENDOR_SOURCE_DIR}/build >/dev/null - cmake -G "Ninja" \ - -DCMAKE_INSTALL_PREFIX="${FASTDDS_INSTALL_DIR}" \ - -DBUILD_SHARED_LIBS=ON \ - -DCMAKE_CXX_FLAGS_RELEASE="-D_GLIBCXX_USE_CXX11_ABI=0" \ - -DFOONATHAN_MEMORY_FORCE_VENDORED_BUILD=ON \ - .. - ninja - ninja install + FOONATHAN_MEMORY_VENDOR_SRC_DIR=${FASTDDS_BASENAME}-source/thirdparty/foonathan-memory-vendor + + mkdir -p ${FASTDDS_BASENAME}-server-build + + log "Prepare fast dds sources" + git clone --depth 1 --branch ${FAST_DDS_LIB_BRANCH} ${FAST_DDS_LIB_REPO} ${FASTDDS_BASENAME}-source + pushd ${FASTDDS_BASENAME}-source >/dev/null + git submodule update --init + git clone --depth 1 --branch ${FOONATHAN_MEMORY_VENDOR_BRANCH} ${FOONATHAN_MEMORY_VENDOR_REPO} ${FOONATHAN_MEMORY_VENDOR_SRC_DIR} + + # we have to tweak the sources a bit to be able to compile with our boost version AND without exceptions + if [[ -e ${FASTDDS_BASENAME}-source/thirdparty/boost/include/boost ]]; then + # remove their boost includes, but keep their entry point + rm -rf ${FASTDDS_BASENAME}-source/thirdparty/boost/include/boost + # ensure the find boost compiles without exceptions + sed -i s/"CXX_STANDARD 11"/"CXX_STANDARD 11\n COMPILE_DEFINITIONS \"-DBOOST_NO_EXCEPTIONS\""/ ${FASTDDS_BASENAME}-source/cmake/modules/FindThirdpartyBoost.cmake + sed -i s/"class ThirdpartyBoostCompileTest"/"#ifdef BOOST_NO_EXCEPTIONS\nnamespace boost {void throw_exception(std::exception const \& e) {}}\n#endif\nclass ThirdpartyBoostCompileTest"/ ${FASTDDS_BASENAME}-source/thirdparty/boost/test/ThirdpartyBoostCompile_test.cpp + fi + popd >/dev/null + + log "fast dds: Build asio" + pushd ${FASTDDS_BASENAME}-source/thirdparty/asio/asio + ./autogen.sh popd >/dev/null - rm -Rf ${FOONATHAN_MEMORY_VENDOR_SOURCE_DIR} - - log "Build fast cdr" - FAST_CDR_BASENAME=fast-cdr - FAST_CDR_SOURCE_DIR=${PWD}/${FAST_CDR_BASENAME}-source - FAST_CDR_REPO="https://github.com/eProsima/Fast-CDR.git" - FAST_CDR_BRANCH=1.1.x - build_fastdds_extension ${FAST_CDR_SOURCE_DIR} "${FAST_CDR_REPO}" "${FAST_CDR_BRANCH}" - pushd ${FAST_CDR_SOURCE_DIR}/build >/dev/null + mkdir -p ${FASTDDS_BASENAME}-server-build/asio + pushd ${FASTDDS_BASENAME}-server-build/asio >/dev/null + # since ASIO is header only installation, we don't care about flags from CARLA_SERVER_TOOLCHAIN_FILE + ${FASTDDS_BASENAME}-source/thirdparty/asio/asio/configure --prefix="${FASTDDS_BASENAME}-server-install" + make -j 15 install-data + popd >/dev/null + + log "fast dds: Build foonathan memory vendor" + mkdir -p ${FASTDDS_BASENAME}-server-build/foonathan-memory-vendor + pushd ${FASTDDS_BASENAME}-server-build/foonathan-memory-vendor >/dev/null cmake -G "Ninja" \ - -DCMAKE_INSTALL_PREFIX="${FASTDDS_INSTALL_DIR}" \ - -DCMAKE_CXX_FLAGS_RELEASE="-D_GLIBCXX_USE_CXX11_ABI=0" \ - .. + -DCMAKE_INSTALL_PREFIX="${FASTDDS_BASENAME}-server-install" \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_SERVER_TOOLCHAIN_FILE}" \ + ${FASTDDS_BASENAME}-source/thirdparty/foonathan-memory-vendor ninja ninja install popd >/dev/null - rm -Rf ${FAST_CDR_SOURCE_DIR} - log "Build fast dds" - FAST_DDS_LIB_BASENAME=fast-dds-lib - FAST_DDS_LIB_SOURCE_DIR=${PWD}/${FAST_DDS_LIB_BASENAME}-source - FAST_DDS_LIB_REPO="https://github.com/eProsima/Fast-DDS.git" - FAST_DDS_LIB_BRANCH=2.11.2 - build_fastdds_extension ${FAST_DDS_LIB_SOURCE_DIR} "${FAST_DDS_LIB_REPO}" "${FAST_DDS_LIB_BRANCH}" - pushd ${FAST_DDS_LIB_SOURCE_DIR}/build >/dev/null + log "fast dds: Copy OpenSSL from UE4" + cp -r ${UE4_ROOT}/Engine/Source/ThirdParty/OpenSSL/1.1.1c/include/Linux/x86_64-unknown-linux-gnu/* ${FASTDDS_BASENAME}-server-install/include + cp -r ${UE4_ROOT}/Engine/Source/ThirdParty/OpenSSL/1.1.1c/lib/Linux/x86_64-unknown-linux-gnu/* ${FASTDDS_BASENAME}-server-install/lib + + log "fast dds: Build fast dds itself" + mkdir -p ${FASTDDS_BASENAME}-server-build/fastdds + pushd ${FASTDDS_BASENAME}-server-build/fastdds >/dev/null + cmake -G "Ninja" \ - -DCMAKE_INSTALL_PREFIX="${FASTDDS_INSTALL_DIR}" \ - -DCMAKE_CXX_FLAGS=-latomic \ - -DCMAKE_CXX_FLAGS_RELEASE="-D_GLIBCXX_USE_CXX11_ABI=0" \ + -DCMAKE_INSTALL_PREFIX="${FASTDDS_BASENAME}-server-install" \ + -DCMAKE_TOOLCHAIN_FILE="${CARLA_SERVER_TOOLCHAIN_FILE}" \ + -DCMAKE_MODULE_PATH="${FASTDDS_BASENAME}-server-install" \ + -DBUILD_TESTING=OFF \ + -DCOMPILE_EXAMPLES=OFF \ + -DCOMPILE_TOOLS=OFF \ -DTHIRDPARTY_Asio=FORCE \ + -DTHIRDPARTY_fastcdr=FORCE \ -DTHIRDPARTY_TinyXML2=FORCE \ - .. + -DOPENSSL_FOUND:BOOL=ON \ + -DOPENSSL_INCLUDE_DIR:FILEPATH=${FASTDDS_BASENAME}-server-install/include \ + -DOPENSSL_SSL_LIBRARY:FILEPATH=${FASTDDS_BASENAME}-server-install/lib/libssl.a \ + -DOPENSSL_CRYPTO_LIBRARY:FILEPATH=${FASTDDS_BASENAME}-server-install/lib/libcrypto.a \ + -DCMAKE_CXX_FLAGS="-latomic" \ + -DTHIRDPARTY_BOOST_INCLUDE_DIR="${BOOST_SERVER_INCLUDE};${FASTDDS_BASENAME}-source/thirdparty/boost/include" \ + ${FASTDDS_BASENAME}-source ninja ninja install popd >/dev/null - rm -Rf ${FAST_DDS_LIB_SOURCE_DIR} - mkdir -p ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ - cp -p ${FASTDDS_LIB}/*.so* ${LIBCARLA_INSTALL_SERVER_FOLDER}/lib/ + rm -Rf ${FASTDDS_BASENAME}-source ${FASTDDS_BASENAME}-server-build fi -fi - -# ============================================================================== -# -- Generate Version.h -------------------------------------------------------- -# ============================================================================== - -CARLA_VERSION=$(get_git_repository_version) - -log "CARLA version ${CARLA_VERSION}." - -VERSION_H_FILE=${LIBCARLA_ROOT_FOLDER}/source/carla/Version.h -VERSION_H_FILE_GEN=${CARLA_BUILD_FOLDER}/Version.h - -sed -e "s|\${CARLA_VERSION}|${CARLA_VERSION}|g" ${VERSION_H_FILE}.in > ${VERSION_H_FILE_GEN} - -move_if_changed "${VERSION_H_FILE_GEN}" "${VERSION_H_FILE}" - -# ============================================================================== -# -- Generate CMake toolchains and config -------------------------------------- -# ============================================================================== -log "Generating CMake configuration files." - -# -- LIBSTDCPP_TOOLCHAIN_FILE -------------------------------------------------- - -cat >${LIBSTDCPP_TOOLCHAIN_FILE}.gen <>${LIBCPP_TOOLCHAIN_FILE}.gen <> ${CMAKE_CONFIG_FILE}.gen fi -# -- Move files ---------------------------------------------------------------- - -move_if_changed "${LIBSTDCPP_TOOLCHAIN_FILE}.gen" "${LIBSTDCPP_TOOLCHAIN_FILE}" -move_if_changed "${LIBCPP_TOOLCHAIN_FILE}.gen" "${LIBCPP_TOOLCHAIN_FILE}" move_if_changed "${CMAKE_CONFIG_FILE}.gen" "${CMAKE_CONFIG_FILE}" # ============================================================================== @@ -1102,5 +1124,4 @@ move_if_changed "${CMAKE_CONFIG_FILE}.gen" "${CMAKE_CONFIG_FILE}" # ============================================================================== popd >/dev/null - log "Success!" diff --git a/Util/BuildTools/Vars.mk b/Util/BuildTools/Vars.mk index 3cfd5512578..17b5b7d61ef 100644 --- a/Util/BuildTools/Vars.mk +++ b/Util/BuildTools/Vars.mk @@ -16,7 +16,6 @@ CARLA_PYTHONAPI_SOURCE_FOLDER=${CARLA_PYTHONAPI_ROOT_FOLDER}/carla LIBCARLA_ROOT_FOLDER=${CURDIR}/LibCarla LIBCARLA_BUILD_SERVER_FOLDER=${CARLA_BUILD_FOLDER}/libcarla-server-build LIBCARLA_BUILD_PYTORCH_FOLDER=${CARLA_BUILD_FOLDER}/libcarla-pytorch-build -LIBCARLA_FASTDDS_FOLDER=${CARLA_BUILD_FOLDER}/libcarla-fastdds-install LIBCARLA_BUILD_CLIENT_FOLDER=${CARLA_BUILD_FOLDER}/libcarla-client-build LIBCARLA_INSTALL_SERVER_FOLDER=${CARLAUE4_PLUGIN_ROOT_FOLDER}/CarlaDependencies LIBCARLA_INSTALL_CLIENT_FOLDER=${CARLA_PYTHONAPI_SOURCE_FOLDER}/dependencies @@ -27,8 +26,8 @@ OSM2ODR_SOURCE_FOLDER=${CARLA_BUILD_FOLDER}/libosm2dr-source CARLAUE4_PLUGIN_DEPS_FOLDER=${CARLAUE4_PLUGIN_ROOT_FOLDER}/CarlaDependencies -LIBSTDCPP_TOOLCHAIN_FILE=${CARLA_BUILD_FOLDER}/LibStdCppToolChain.cmake -LIBCPP_TOOLCHAIN_FILE=${CARLA_BUILD_FOLDER}/LibCppToolChain.cmake +CARLA_CLIENT_TOOLCHAIN_FILE=${CARLA_BUILD_FOLDER}/CarlaClientToolChain.cmake +CARLA_SERVER_TOOLCHAIN_FILE=${CARLA_BUILD_FOLDER}/CarlaServerToolChain.cmake CMAKE_CONFIG_FILE=${CARLA_BUILD_FOLDER}/CMakeLists.txt.in LIBCARLA_TEST_CONTENT_FOLDER=${CARLA_BUILD_FOLDER}/test-content diff --git a/Util/BuildTools/Windows.mk b/Util/BuildTools/Windows.mk index 1728f1a724b..0a6fe1b7c96 100644 --- a/Util/BuildTools/Windows.mk +++ b/Util/BuildTools/Windows.mk @@ -62,14 +62,14 @@ PythonAPI: LibCarla osm2odr @"${CARLA_BUILD_TOOLS_FOLDER}/BuildPythonAPI.bat" --py3 server: setup - @"${CARLA_BUILD_TOOLS_FOLDER}/BuildLibCarla.bat" --server --generator "$(GENERATOR)" + @"${CARLA_BUILD_TOOLS_FOLDER}/BuildLibCarla.bat" --server --generator "$(GENERATOR)" $(ARGS) client: setup - @"${CARLA_BUILD_TOOLS_FOLDER}/BuildLibCarla.bat" --client --generator "$(GENERATOR)" + @"${CARLA_BUILD_TOOLS_FOLDER}/BuildLibCarla.bat" --client --generator "$(GENERATOR)" $(ARGS) .PHONY: LibCarla LibCarla: setup - @"${CARLA_BUILD_TOOLS_FOLDER}/BuildLibCarla.bat" --server --client --generator "$(GENERATOR)" + @"${CARLA_BUILD_TOOLS_FOLDER}/BuildLibCarla.bat" --server --client --generator "$(GENERATOR)" $(ARGS) setup: downloadplugin @"${CARLA_BUILD_TOOLS_FOLDER}/Setup.bat" --boost-toolset msvc-14.2 --generator "$(GENERATOR)" $(ARGS) diff --git a/Util/Formatting/codeformat.py b/Util/Formatting/codeformat.py index 11a753d1795..4c173aafd9b 100755 --- a/Util/Formatting/codeformat.py +++ b/Util/Formatting/codeformat.py @@ -1,15 +1,14 @@ #!/usr/bin/python # -# Copyright (c) 2017-2020 Intel Corporation +# Copyright (c) 2017-2024 Intel Corporation # -# Helper script for code formatting using clang-format-3.9 and autopep +# Helper script for code formatting using clang-format-14 and autopep import argparse import filecmp import os import re -import sets import subprocess import sys from termcolor import cprint @@ -31,9 +30,10 @@ def __init__(self, command, expectedVersion, formatCommandArguments, verifyComma def verifyFormatterVersion(self): try: - versionOutput = subprocess.check_output([self.command, "--version"]).rstrip('\r\n') + versionOutputByteString = subprocess.check_output([self.command, "--version"]) + versionOutput = versionOutputByteString.decode(encoding='UTF-8') if self.expectedVersion != "": - if versionOutput.startswith(self.expectedVersion): + if self.expectedVersion in versionOutput: print("[OK] Found formatter '" + versionOutput + "'") return else: @@ -41,8 +41,9 @@ def verifyFormatterVersion(self): cprint("[NOT OK] Version string does not start with '" + self.expectedVersion + "'", "red") else: return - except: + except subprocess.CalledProcessError as exc: cprint("[ERROR] Could not run " + self.command, "red") + cprint("[ERROR] '" + exc.output + "'", "red") cprint("[INFO] Please check if correct version is installed or install with '" + self.installCommand + "'", "blue") sys.exit(1) @@ -70,9 +71,9 @@ def performGitDiff(self, fileName, verifyOutput): try: diffProcess = subprocess.Popen( ["git", "diff", "--color=always", "--exit-code", "--no-index", "--", fileName, "-"], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) diffOutput, _ = diffProcess.communicate(verifyOutput) if diffProcess.returncode == 0: diffOutput = "" @@ -99,6 +100,8 @@ def verifyFile(self, fileName, printDiff): if status: return True + if not type(diffOutput) is str: + diffOutput = diffOutput.decode("utf-8") if diffOutput != "": cprint("[NOT OK] " + fileName, "red") if printDiff: @@ -108,6 +111,9 @@ def verifyFile(self, fileName, printDiff): print("[OK] " + fileName) return False + def setArgs(self, args): + self.args = args + class CodeFormatterClang(CodeFormatter): CLANG_FORMAT_FILE = ".clang-format" @@ -116,14 +122,14 @@ class CodeFormatterClang(CodeFormatter): def __init__(self): CodeFormatter.__init__(self, - command="clang-format-3.9", - expectedVersion="clang-format version 3.9", + command="clang-format-14", + expectedVersion="clang-format version 14", formatCommandArguments=["-style=file", "-fallback-style=none", "-i"], verifyCommandArguments=["-style=file", "-fallback-style=none"], verifyOutputIsDiff=False, fileEndings=["cpp", "hpp", "c", "h", "cc"], fileDescription="source and header", - installCommand="sudo apt-get install clang-format-3.9") + installCommand="sudo apt-get install clang-format-14") self.scriptPath = os.path.dirname(os.path.abspath(__file__)) self.checkedInClangFormatFile = os.path.join(self.scriptPath, CodeFormatterClang.CHECKED_IN_CLANG_FORMAT_FILE) @@ -142,13 +148,13 @@ def verifyCheckedInClangFormatFileExists(self): def confirmWithUserClangFormatFileCantBeVerified(self): if not self.args.yes: - answer = raw_input("Are you sure your .clang-format file is up-to-date and you want to continue? (y/N)") + answer = input("Are you sure your .clang-format file is up-to-date and you want to continue? (y/N)") if answer != "y": sys.exit(1) def verifyClangFormatFileExistsAndMatchesCheckedIn(self): self.verifyCheckedInClangFormatFileExists() - foundClangFormatFiles = sets.Set() + foundClangFormatFiles = set() for fileName in self.inputFiles: dirName = os.path.dirname(os.path.abspath(fileName)) if not self.findClangFormatFileStartingFrom(dirName, fileName, foundClangFormatFiles): @@ -219,6 +225,7 @@ def parseCommandLine(self): def addCodeFormatter(self, codeFormatterInstance): self.codeFormatterInstances.append(codeFormatterInstance) + codeFormatterInstance.setArgs(self.args) def scanForInputFiles(self): for formatterInstance in self.codeFormatterInstances: @@ -263,26 +270,26 @@ def isFileNotExcluded(self, fileName): def confirmWithUserFileIsOutsideGit(self, fileName): cprint("[WARN] File is not in a Git repo: " + fileName, "yellow") - answer = raw_input("Are you sure to code format it anyway? (y/Q)") + answer = input("Are you sure to code format it anyway? (y/Q)") if answer != "y": sys.exit(1) def confirmWithUserFileIsUntracked(self, fileName): cprint("[WARN] File is untracked in Git: " + fileName, "yellow") - answer = raw_input("Are you sure to code format it anyway? (y/Q)") + answer = input("Are you sure to code format it anyway? (y/Q)") if answer != "y": sys.exit(1) def confirmWithUserGitRepoIsNotClean(self, gitRepo): cprint("[WARN] Git repo is not clean: " + gitRepo, "yellow") - answer = raw_input("Are you sure to code format files in it anyway? (y/Q)") + answer = input("Are you sure to code format files in it anyway? (y/Q)") if answer != "y": sys.exit(1) def checkInputFilesAreInCleanGitReposAndAreTracked(self): if self.args.verify or self.args.yes: return - gitRepos = sets.Set() + gitRepos = set() for formatterInstance in self.codeFormatterInstances: for fileName in formatterInstance.inputFiles: gitRepo = self.getGitRepoForFile(fileName) @@ -308,7 +315,7 @@ def getGitRepoForFile(self, fileName): cwd=os.path.dirname(fileName)) gitOutput, _ = gitProcess.communicate() if gitProcess.returncode == 0: - return gitOutput.rstrip('\r\n') + return gitOutput.decode(encoding='UTF-8').rstrip('\r\n') except OSError: cprint("[ERROR] Failed to run 'git rev-parse --show-toplevel' for " + fileName, "red") return None @@ -322,7 +329,7 @@ def isInsideGitRepo(self, fileName): cwd=os.path.dirname(fileName)) gitOutput, _ = gitProcess.communicate() if gitProcess.returncode == 0: - return gitOutput.rstrip('\r\n') == "true" + return gitOutput.decode(encoding='UTF-8').rstrip('\r\n') == "true" except OSError: cprint("[ERROR] Failed to run 'git rev-parse --is-inside-work-tree' for " + fileName, "red") return False @@ -400,13 +407,19 @@ def confirmWithUser(self): elif (not self.args.verify) and (not self.args.yes) and self.numberOfInputFiles() > 1: for formatterInstance in self.codeFormatterInstances: formatterInstance.printInputFiles() - answer = raw_input("Are you sure to code format " + str(self.numberOfInputFiles()) + " files? (y/N)") + answer = input("Are you sure to code format " + str(self.numberOfInputFiles()) + " files? (y/N)") if answer != "y": sys.exit(1) + def checkPythonVersion(self): + if sys.version_info.major != 3: + cprint("[ERROR] Code Formatter runs in Python3 ", "red") + sys.exit(1) + def main(): codeFormat = CodeFormat() + codeFormat.checkPythonVersion() codeFormat.parseCommandLine() codeFormat.printMode() @@ -425,5 +438,6 @@ def main(): cprint("SUCCESS", "green") sys.exit(0) + if __name__ == "__main__": main() diff --git a/Util/InstallersWin/install_chrono.bat b/Util/InstallersWin/install_chrono.bat index 3c701a7ca9f..19dec8602e2 100644 --- a/Util/InstallersWin/install_chrono.bat +++ b/Util/InstallersWin/install_chrono.bat @@ -14,6 +14,7 @@ echo %FILE_N% [Batch params]: %* rem ============================================================================ rem -- Parse arguments --------------------------------------------------------- rem ============================================================================ +set GENERATOR="" :arg-parse if not "%1"=="" ( @@ -39,6 +40,11 @@ rem If not set set the build dir to the current dir if "%BUILD_DIR%" == "" set BUILD_DIR=%~dp0 if not "%BUILD_DIR:~-1%"=="\" set BUILD_DIR=%BUILD_DIR%\ if %GENERATOR% == "" set GENERATOR="Visual Studio 16 2019" +echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( + set PLATFORM=-A x64 +) || ( + set PLATFORM= +) rem ============================================================================ rem -- Get Eigen (Chrono dependency) ------------------------------------------- @@ -101,12 +107,6 @@ if not exist %CHRONO_INSTALL_DIR% ( cd "%CHRONO_BUILD_DIR%" - echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( - set PLATFORM=-A x64 - ) || ( - set PLATFORM= - ) - echo %FILE_N% Compiling Chrono. cmake -G %GENERATOR% %PLATFORM%^ -DCMAKE_BUILD_TYPE=Release^ diff --git a/Util/InstallersWin/install_eigen.bat b/Util/InstallersWin/install_eigen.bat index 23448f74a48..fc7b31a79ab 100644 --- a/Util/InstallersWin/install_eigen.bat +++ b/Util/InstallersWin/install_eigen.bat @@ -74,8 +74,18 @@ if not exist "%EIGEN_INSTALL_DIR%" ( xcopy /q /Y /S /I /d "%EIGEN_SRC_DIR%\Eigen" "%EIGEN_INCLUDE%\Eigen" xcopy /q /Y /S /I /d "%EIGEN_SRC_DIR%\unsupported\Eigen" "%EIGEN_INCLUDE%\unsupported\Eigen" -copy "%BUILD_DIR%..\Util\Patches\Eigen3.1.0\Macros.h" "%EIGEN_INCLUDE%\Eigen\src\Core\util\Macros.h" +copy "%BUILD_DIR%..\Util\Patches\Eigen3.1.0\Functors.h" "%EIGEN_INCLUDE%\Eigen\src\Core\Functors.h" copy "%BUILD_DIR%..\Util\Patches\Eigen3.1.0\VectorBlock.h" "%EIGEN_INCLUDE%\Eigen\src\Core\VectorBlock.h" +copy "%BUILD_DIR%..\Util\Patches\Eigen3.1.0\PacketMath.h" "%EIGEN_INCLUDE%\Eigen\src\Core\arch\SSE\PacketMath.h" +copy "%BUILD_DIR%..\Util\Patches\Eigen3.1.0\SelfadjointMatrixVector.h" "%EIGEN_INCLUDE%\Eigen\src\Core\products\SelfadjointMatrixVector.h" +copy "%BUILD_DIR%..\Util\Patches\Eigen3.1.0\Macros.h" "%EIGEN_INCLUDE%\Eigen\src\Core\util\Macros.h" +copy "%BUILD_DIR%..\Util\Patches\Eigen3.1.0\ArrayCwiseUnaryOps.h" "%EIGEN_INCLUDE%\Eigen\src\plugins\ArrayCwiseUnaryOps.h" +copy "%BUILD_DIR%..\Util\Patches\Eigen3.1.0\MatrixCwiseUnaryOps.h" "%EIGEN_INCLUDE%\Eigen\src\plugins\MatrixCwiseUnaryOps.h" + + cp $CARLA_ROOT_FOLDER/Util/Patches/Eigen${EIGEN_VERSION}/Macros.h "${EIGEN_BASENAME}-source/Eigen/src/Core/util/Macros.h" + cp $CARLA_ROOT_FOLDER/Util/Patches/Eigen${EIGEN_VERSION}/ArrayCwiseUnaryOps.h "${EIGEN_BASENAME}-source/Eigen/src/plugins/ArrayCwiseUnaryOps.h" + cp $CARLA_ROOT_FOLDER/Util/Patches/Eigen${EIGEN_VERSION}/MatrixCwiseUnaryOps.h "${EIGEN_BASENAME}-source/Eigen/src/plugins/MatrixCwiseUnaryOps.h" + goto success diff --git a/Util/InstallersWin/install_fastDDS.bat b/Util/InstallersWin/install_fastDDS.bat index 4bdc6a8bb6c..00dd82904ec 100644 --- a/Util/InstallersWin/install_fastDDS.bat +++ b/Util/InstallersWin/install_fastDDS.bat @@ -14,7 +14,11 @@ rem ============================================================================ rem -- Parse arguments --------------------------------------------------------- rem ============================================================================ + set DEL_SRC=false +set BOOST_VERSION="unknown" +set FASTDDS_INSTALL_DIR="" +set GENERATOR="" :arg-parse if not "%1"=="" ( @@ -27,20 +31,48 @@ if not "%1"=="" ( set DEL_SRC=true ) + if "%1"=="--boost-version" ( + set BOOST_VERSION=%2 + shift + ) + + if "%1"=="--install-dir" ( + set FASTDDS_INSTALL_DIR=%2 + shift + ) + + if "%1"=="--generator" ( + set GENERATOR=%2 + shift + ) + shift goto :arg-parse ) +if %GENERATOR% == "" set GENERATOR="Visual Studio 16 2019" +echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( + set PLATFORM=-A x64 +) || ( + set PLATFORM= +) +echo "%GENERATOR%" "%PLATFORM%" + rem If not set set the build dir to the current dir if "%BUILD_DIR%" == "" set BUILD_DIR=%~dp0 if not "%BUILD_DIR:~-1%"=="\" set BUILD_DIR=%BUILD_DIR%\ set FASTDDS_SRC=fastDDS-src set FASTDDS_SRC_DIR=%BUILD_DIR%%FASTDDS_SRC%\ -set FASTDDS_INSTALL=fastDDS-install -set FASTDDS_INSTALL_DIR=%BUILD_DIR%%FASTDDS_INSTALL%\ -set FASTDDS_BUILD_DIR=%FASTDDS_SRC_DIR%build\ +if "%FASTDDS_INSTALL_DIR%" == "" ( + set FASTDDS_INSTALL=fastDDS-install + set FASTDDS_INSTALL_DIR=%BUILD_DIR%%FASTDDS_INSTALL%\ +) +set FASTDDS_BUILD_DIR=%FASTDDS_SRC_DIR%build\fastdds set FASTDDS_BASENAME=%FASTDDS_SRC% +set FOONATHAN_MEMORY_VENDOR_BASENAME=foonathan-memory-vendor +set FOONATHAN_MEMORY_VENDOR_SOURCE_DIR=%FASTDDS_SRC_DIR%\thirdparty\foonathan-memory-vendor +set FOONATHAN_MEMORY_VENDOR_BUILD_DIR=%FASTDDS_SRC_DIR%build\foonathan-memory-vendor if exist "%FASTDDS_INSTALL_DIR%" ( goto already_build @@ -49,86 +81,86 @@ if exist "%FASTDDS_INSTALL_DIR%" ( if not exist "%FASTDDS_SRC_DIR%" ( echo %FILE_N% Cloning "Fast-DDS" - call git clone https://github.com/eProsima/Fast-DDS.git "%FASTDDS_SRC_DIR:~0,-1%" - call git submodule init - call git submodule update + git clone --depth 1 --branch 2.11.3 https://github.com/eProsima/Fast-DDS.git "%FASTDDS_SRC_DIR:~0,-1%" + if %errorlevel% neq 0 goto error_git + git submodule init if %errorlevel% neq 0 goto error_git + git submodule update + if %errorlevel% neq 0 goto error_git + git clone --depth 1 --branch master https://github.com/eProsima/foonathan_memory_vendor.git "%FOONATHAN_MEMORY_VENDOR_SOURCE_DIR%" ) else ( echo %FILE_N% Not cloning "Fast-DDS" because already exists a folder called "%FASTDDS_SRC%". ) -echo Compiling fastCDR dependency... - -if not exist "%FASTDDS_SRC_DIR%/thirdparty/fastcdr/build" ( - echo %FILE_N% Creating "%FASTDDS_SRC_DIR%/thirdparty/fastcdr/build" - cd "%FASTDDS_SRC_DIR%/thirdparty/fastcdr" - mkdir build - cd ../../ +if not exist "%FOONATHAN_MEMORY_VENDOR_BUILD_DIR%" ( + echo %FILE_N% Creating "%FOONATHAN_MEMORY_VENDOR_BUILD_DIR%" + mkdir "%FOONATHAN_MEMORY_VENDOR_BUILD_DIR%" ) +cd "%FOONATHAN_MEMORY_VENDOR_BUILD_DIR%" -cd "%FASTDDS_SRC_DIR%/thirdparty/fastcdr/build" -echo %FILE_N% Generating build... - -cmake .. -G "Visual Studio 16 2019" -A x64^ +echo %FILE_N% Generating build: foonathan memory vendor ... +cmake -G %GENERATOR% %PLATFORM%^ -DCMAKE_BUILD_TYPE=Release^ -DCMAKE_CXX_FLAGS_RELEASE="/MD /MP"^ -DCMAKE_INSTALL_PREFIX="%FASTDDS_INSTALL_DIR:\=/%"^ - -DCMAKE_CXX_FLAGS=/D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING + -DBUILD_STATIC_LIBS=ON^ + -DBUILD_SHARED_LIBS=OFF^ + -DCMAKE_CXX_FLAGS="/DBOOST_NO_EXCEPTIONS /DASIO_NO_EXCEPTIONS"^ + "%FOONATHAN_MEMORY_VENDOR_SOURCE_DIR%" if %errorlevel% neq 0 goto error_cmake -echo %FILE_N% Building... +echo %FILE_N% Building foonathan memory vendor... cmake --build . --config Release --target install -if errorlevel neq 0 goto error_install - -cd ../../.. - -@REM echo Compiling asio dependency... - -@REM if not exist "%FASTDDS_SRC_DIR%/thirdparty/asio/asio/build" ( -@REM echo %FILE_N% Creating "%FASTDDS_SRC_DIR%/thirdparty/asio/asio/build" -@REM cd "%FASTDDS_SRC_DIR%/thirdparty/asio/asio" -@REM mkdir build -@REM cd ../../ -@REM ) - -@REM cd "%FASTDDS_SRC_DIR%/thirdparty/asio/asio/build" -@REM echo %FILE_N% Generating build... - -@REM cmake .. -G "Visual Studio 16 2019" -A x64^ -@REM -DCMAKE_BUILD_TYPE=Release^ -@REM -DCMAKE_CXX_FLAGS_RELEASE="/MD /MP"^ -@REM -DCMAKE_INSTALL_PREFIX="%FASTDDS_INSTALL_DIR:\=/%"^ -@REM -DCMAKE_CXX_FLAGS=/D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING -@REM if %errorlevel% neq 0 goto error_cmake - -@REM echo %FILE_N% Building... -@REM cmake --build . --config Release --target install - -@REM if errorlevel neq 0 goto error_install +if exist "%FASTDDS_SRC_DIR%\thirdparty\boost\include\boost" ( + echo %FILE_N% Preparing fastdds boost ... + @REM remove their boost includes, but keep their entry point + rd /s /q "%FASTDDS_SRC_DIR%\thirdparty\boost\include\boost" + @REM ensure the find boost compiles without exceptions + sed -i s/"CXX_STANDARD 11"/"CXX_STANDARD 11\n COMPILE_DEFINITIONS \"-DBOOST_NO_EXCEPTIONS\""/ "%FASTDDS_SRC_DIR%\cmake\modules\FindThirdpartyBoost.cmake" + sed -i s/"class ThirdpartyBoostCompileTest"/"#ifdef BOOST_NO_EXCEPTIONS\nnamespace boost {void throw_exception(std::exception const \& e) {}}\n#endif\nclass ThirdpartyBoostCompileTest"/ "%FASTDDS_SRC_DIR%\thirdparty\boost\test\ThirdpartyBoostCompile_test.cpp" +) -@REM cd ../../../.. +if exist "%FASTDDS_SRC_DIR%\src\cpp\utils\StringMatching.cpp" ( + echo %FILE_N% Patching fastdds ... + sed -i s/"defined(__cplusplus_winrt)"/"(1)"/ "%FASTDDS_SRC_DIR%\src\cpp\utils\StringMatching.cpp" + sed -i s/"replace_all(pattern"/"replace_all(path"/ "%FASTDDS_SRC_DIR%\src\cpp\utils\StringMatching.cpp" +) if not exist "%FASTDDS_BUILD_DIR%" ( echo %FILE_N% Creating "%FASTDDS_BUILD_DIR%" mkdir "%FASTDDS_BUILD_DIR%" ) - cd "%FASTDDS_BUILD_DIR%" -echo %FILE_N% Generating build... +echo %FILE_N% Generating build: fastdds ... -cmake .. -G "Visual Studio 16 2019" -A x64^ +cmake -G %GENERATOR% %PLATFORM%^ -DCMAKE_BUILD_TYPE=Release^ -DCMAKE_CXX_FLAGS_RELEASE="/MD /MP"^ -DCMAKE_INSTALL_PREFIX="%FASTDDS_INSTALL_DIR:\=/%"^ - -DCMAKE_CXX_FLAGS=/D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING^ + -DCMAKE_MODULE_PATH="%FASTDDS_INSTALL_DIR:\=/%"^ + -DBUILD_STATIC_LIBS=ON^ + -DBUILD_SHARED_LIBS=OFF^ + -DBUILD_TESTING=OFF^ + -DCOMPILE_EXAMPLES=OFF^ + -DCOMPILE_TOOLS=OFF^ + -DTHIRDPARTY_Asio=FORCE^ + -DTHIRDPARTY_fastcdr=FORCE^ + -DTHIRDPARTY_TinyXML2=FORCE^ + -DTHIRDPARTY_BOOST_INCLUDE_DIR="%BUILD_DIR%boost-%BOOST_VERSION%-install\include;%FASTDDS_SRC_DIR%\thirdparty\boost\include"^ + -DCMAKE_CXX_FLAGS="/D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING /DBOOST_NO_EXCEPTIONS /DASIO_NO_EXCEPTIONS"^ "%FASTDDS_SRC_DIR%" if %errorlevel% neq 0 goto error_cmake -echo %FILE_N% Building... +echo %FILE_N% Building fastdds... cmake --build . --config Release --target install -if errorlevel neq 0 goto error_install +if %errorlevel% neq 0 goto error_install + +rem copy asio header files as they are not copied automatically by the above build, but we need those for handling the asio-exceptions +copy %FASTDDS_SRC_DIR%thirdparty\asio\asio\include\asio.hpp %INSTALLATION_DIR%fastDDS-install\include\ > NUL +xcopy /Y /S /I %FASTDDS_SRC_DIR%thirdparty\asio\asio\include\asio\* %INSTALLATION_DIR%fastDDS-install\include\asio\* > NUL +if %errorlevel% neq 0 goto error_install rem Remove the downloaded Fast-DDS source because is no more needed if %DEL_SRC% == true ( @@ -179,7 +211,7 @@ rem ============================================================================ :good_exit echo %FILE_N% Exiting... - endlocal & set install_recast=%FASTDDS_INSTALL_DIR% + endlocal & set install_dds=%FASTDDS_INSTALL_DIR% exit /b 0 :bad_exit diff --git a/Util/InstallersWin/install_gtest.bat b/Util/InstallersWin/install_gtest.bat index ae9fb7de350..0745e77b5fc 100644 --- a/Util/InstallersWin/install_gtest.bat +++ b/Util/InstallersWin/install_gtest.bat @@ -16,6 +16,7 @@ rem -- Parse arguments --------------------------------------------------------- rem ============================================================================ set DEL_SRC=false +set GENERATOR="" :arg-parse if not "%1"=="" ( @@ -36,6 +37,11 @@ if not "%1"=="" ( ) if %GENERATOR% == "" set GENERATOR="Visual Studio 16 2019" +echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( + set PLATFORM=-A x64 +) || ( + set PLATFORM= +) rem If not set set the build dir to the current dir if "%BUILD_DIR%" == "" set BUILD_DIR=%~dp0 @@ -69,12 +75,6 @@ if not exist "%GT_BUILD_DIR%" ( cd "%GT_BUILD_DIR%" echo %FILE_N% Generating build... -echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( - set PLATFORM=-A x64 -) || ( - set PLATFORM= -) - cmake .. -G %GENERATOR% %PLATFORM%^ -DCMAKE_BUILD_TYPE=Release^ -DCMAKE_CXX_FLAGS_RELEASE="/MD /MP"^ @@ -86,7 +86,7 @@ if %errorlevel% neq 0 goto error_cmake echo %FILE_N% Building... cmake --build . --config Release --target install -if errorlevel neq 0 goto error_install +if %errorlevel% neq 0 goto error_install rem Remove the downloaded Google Test source because is no more needed if %DEL_SRC% == true ( diff --git a/Util/InstallersWin/install_proj.bat b/Util/InstallersWin/install_proj.bat index a0c192ca2c4..6a6f2fb7459 100644 --- a/Util/InstallersWin/install_proj.bat +++ b/Util/InstallersWin/install_proj.bat @@ -15,6 +15,8 @@ rem ============================================================================ rem -- Parse arguments --------------------------------------------------------- rem ============================================================================ +set GENERATOR="" + :arg-parse if not "%1"=="" ( if "%1"=="--build-dir" ( @@ -36,6 +38,11 @@ if not "%1"=="" ( ) if %GENERATOR% == "" set GENERATOR="Visual Studio 16 2019" +echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( + set PLATFORM=-A x64 +) || ( + set PLATFORM= +) rem If not set set the build dir to the current dir if "%BUILD_DIR%" == "" set BUILD_DIR=%~dp0 @@ -79,12 +86,6 @@ move %BUILD_DIR%%PROJ_BASE_NAME% %PROJ_SRC_DIR% mkdir %PROJ_BUILD_DIR% cd %PROJ_BUILD_DIR% -echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( - set PLATFORM=-A x64 -) || ( - set PLATFORM= -) - cmake .. -G %GENERATOR% %PLATFORM%^ -DCMAKE_CXX_FLAGS_RELEASE="/MD /MP"^ -DCMAKE_CXX_FLAGS="/MD /MP"^ diff --git a/Util/InstallersWin/install_recast.bat b/Util/InstallersWin/install_recast.bat index 74257a91b7c..472bd706705 100644 --- a/Util/InstallersWin/install_recast.bat +++ b/Util/InstallersWin/install_recast.bat @@ -15,6 +15,7 @@ rem -- Parse arguments --------------------------------------------------------- rem ============================================================================ set DEL_SRC=false +set GENERATOR="" :arg-parse if not "%1"=="" ( @@ -35,6 +36,11 @@ if not "%1"=="" ( ) if %GENERATOR% == "" set GENERATOR="Visual Studio 16 2019" +echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( + set PLATFORM=-A x64 +) || ( + set PLATFORM= +) rem If not set set the build dir to the current dir if "%BUILD_DIR%" == "" set BUILD_DIR=%~dp0 @@ -71,12 +77,6 @@ if not exist "%RECAST_BUILD_DIR%" ( cd "%RECAST_BUILD_DIR%" echo %FILE_N% Generating build... -echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( - set PLATFORM=-A x64 -) || ( - set PLATFORM= -) - cmake .. -G %GENERATOR% %PLATFORM%^ -DCMAKE_BUILD_TYPE=Release^ -DCMAKE_CXX_FLAGS_RELEASE="/MD /MP"^ diff --git a/Util/InstallersWin/install_rpclib.bat b/Util/InstallersWin/install_rpclib.bat index 0925872eb1c..050de488f9b 100644 --- a/Util/InstallersWin/install_rpclib.bat +++ b/Util/InstallersWin/install_rpclib.bat @@ -16,6 +16,7 @@ rem -- Parse arguments --------------------------------------------------------- rem ============================================================================ set DEL_SRC=false +set GENERATOR="" :arg-parse if not "%1"=="" ( diff --git a/Util/InstallersWin/install_xercesc.bat b/Util/InstallersWin/install_xercesc.bat index a99bf1b47ad..8789be1c812 100644 --- a/Util/InstallersWin/install_xercesc.bat +++ b/Util/InstallersWin/install_xercesc.bat @@ -14,6 +14,7 @@ echo %FILE_N% [Batch params]: %* rem ============================================================================ rem -- Parse arguments --------------------------------------------------------- rem ============================================================================ +set GENERATOR="" :arg-parse if not "%1"=="" ( @@ -36,6 +37,11 @@ if not "%1"=="" ( ) if %GENERATOR% == "" set GENERATOR="Visual Studio 16 2019" +echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( + set PLATFORM=-A x64 +) || ( + set PLATFORM= +) rem If not set set the build dir to the current dir if "%BUILD_DIR%" == "" set BUILD_DIR=%~dp0 @@ -121,12 +127,6 @@ if not exist "%XERCESC_INSTALL_DIR%include" ( mkdir "%XERCESC_INSTALL_DIR%include" ) -echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && ( - set PLATFORM=-A x64 -) || ( - set PLATFORM= -) - cmake .. -G %GENERATOR% %PLATFORM%^ -DCMAKE_INSTALL_PREFIX="%XERCESC_INSTALL_DIR:\=/%"^ -DBUILD_SHARED_LIBS=OFF^ diff --git a/Util/Patches/Eigen3.1.0/ArrayCwiseUnaryOps.h b/Util/Patches/Eigen3.1.0/ArrayCwiseUnaryOps.h new file mode 100644 index 00000000000..c7dbcac944a --- /dev/null +++ b/Util/Patches/Eigen3.1.0/ArrayCwiseUnaryOps.h @@ -0,0 +1,205 @@ + + +/** \returns an expression of the coefficient-wise absolute value of \c *this + * + * Example: \include Cwise_abs.cpp + * Output: \verbinclude Cwise_abs.out + * + * \sa abs2() + */ +EIGEN_STRONG_INLINE const CwiseUnaryOp, const Derived> +abs() const +{ + return derived(); +} + +/** \returns an expression of the coefficient-wise squared absolute value of \c *this + * + * Example: \include Cwise_abs2.cpp + * Output: \verbinclude Cwise_abs2.out + * + * \sa abs(), square() + */ +EIGEN_STRONG_INLINE const CwiseUnaryOp, const Derived> +abs2() const +{ + return derived(); +} + +/** \returns an expression of the coefficient-wise exponential of *this. + * + * Example: \include Cwise_exp.cpp + * Output: \verbinclude Cwise_exp.out + * + * \sa pow(), log(), sin(), cos() + */ +inline const CwiseUnaryOp, const Derived> +exp() const +{ + return derived(); +} + +/** \returns an expression of the coefficient-wise logarithm of *this. + * + * Example: \include Cwise_log.cpp + * Output: \verbinclude Cwise_log.out + * + * \sa exp() + */ +inline const CwiseUnaryOp, const Derived> +log() const +{ + return derived(); +} + +/** \returns an expression of the coefficient-wise square root of *this. + * + * Example: \include Cwise_sqrt.cpp + * Output: \verbinclude Cwise_sqrt.out + * + * \sa pow(), square() + */ +inline const CwiseUnaryOp, const Derived> +sqrt() const +{ + return derived(); +} + +/** \returns an expression of the coefficient-wise cosine of *this. + * + * Example: \include Cwise_cos.cpp + * Output: \verbinclude Cwise_cos.out + * + * \sa sin(), acos() + */ +inline const CwiseUnaryOp, const Derived> +cos() const +{ + return derived(); +} + + +/** \returns an expression of the coefficient-wise sine of *this. + * + * Example: \include Cwise_sin.cpp + * Output: \verbinclude Cwise_sin.out + * + * \sa cos(), asin() + */ +inline const CwiseUnaryOp, const Derived> +sin() const +{ + return derived(); +} + +/** \returns an expression of the coefficient-wise arc cosine of *this. + * + * Example: \include Cwise_acos.cpp + * Output: \verbinclude Cwise_acos.out + * + * \sa cos(), asin() + */ +inline const CwiseUnaryOp, const Derived> +acos() const +{ + return derived(); +} + +/** \returns an expression of the coefficient-wise arc sine of *this. + * + * Example: \include Cwise_asin.cpp + * Output: \verbinclude Cwise_asin.out + * + * \sa sin(), acos() + */ +inline const CwiseUnaryOp, const Derived> +asin() const +{ + return derived(); +} + +/** \returns an expression of the coefficient-wise tan of *this. + * + * Example: \include Cwise_tan.cpp + * Output: \verbinclude Cwise_tan.out + * + * \sa cos(), sin() + */ +inline const CwiseUnaryOp, Derived> +tan() const +{ + return derived(); +} + + +/** \returns an expression of the coefficient-wise power of *this to the given exponent. + * + * Example: \include Cwise_pow.cpp + * Output: \verbinclude Cwise_pow.out + * + * \sa exp(), log() + */ +inline const CwiseUnaryOp, const Derived> +pow(const Scalar& exponent) const +{ + return CwiseUnaryOp, const Derived> + (derived(), internal::scalar_pow_op(exponent)); +} + + +/** \returns an expression of the coefficient-wise inverse of *this. + * + * Example: \include Cwise_inverse.cpp + * Output: \verbinclude Cwise_inverse.out + * + * \sa operator/(), operator*() + */ +inline const CwiseUnaryOp, const Derived> +inverse() const +{ + return derived(); +} + +/** \returns an expression of the coefficient-wise square of *this. + * + * Example: \include Cwise_square.cpp + * Output: \verbinclude Cwise_square.out + * + * \sa operator/(), operator*(), abs2() + */ +inline const CwiseUnaryOp, const Derived> +square() const +{ + return derived(); +} + +/** \returns an expression of the coefficient-wise cube of *this. + * + * Example: \include Cwise_cube.cpp + * Output: \verbinclude Cwise_cube.out + * + * \sa square(), pow() + */ +inline const CwiseUnaryOp, const Derived> +cube() const +{ + return derived(); +} + +#if __cplusplus < 201703L + +#define EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(METHOD_NAME,FUNCTOR) \ + inline const CwiseUnaryOp >, const Derived> \ + METHOD_NAME(const Scalar& s) const { \ + return CwiseUnaryOp >, const Derived> \ + (derived(), std::bind2nd(FUNCTOR(), s)); \ + } + +EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator==, std::equal_to) +EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator!=, std::not_equal_to) +EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator<, std::less) +EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator<=, std::less_equal) +EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator>, std::greater) +EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator>=, std::greater_equal) + +#endif diff --git a/Util/Patches/Eigen3.1.0/Functors.h b/Util/Patches/Eigen3.1.0/Functors.h new file mode 100644 index 00000000000..d2df20517c5 --- /dev/null +++ b/Util/Patches/Eigen3.1.0/Functors.h @@ -0,0 +1,1006 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2010 Gael Guennebaud +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see . + +#ifndef EIGEN_FUNCTORS_H +#define EIGEN_FUNCTORS_H + +namespace Eigen { + +namespace internal { + +// associative functors: + +/** \internal + * \brief Template functor to compute the sum of two scalars + * + * \sa class CwiseBinaryOp, MatrixBase::operator+, class VectorwiseOp, MatrixBase::sum() + */ +template struct scalar_sum_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op) + EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a + b; } + template + EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const + { return internal::padd(a,b); } + template + EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const + { return internal::predux(a); } +}; +template +struct functor_traits > { + enum { + Cost = NumTraits::AddCost, + PacketAccess = packet_traits::HasAdd + }; +}; + +/** \internal + * \brief Template functor to compute the product of two scalars + * + * \sa class CwiseBinaryOp, Cwise::operator*(), class VectorwiseOp, MatrixBase::redux() + */ +template struct scalar_product_op { + enum { + // TODO vectorize mixed product + Vectorizable = is_same::value && packet_traits::HasMul && packet_traits::HasMul + }; + typedef typename scalar_product_traits::ReturnType result_type; + EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op) + EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a * b; } + template + EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const + { return internal::pmul(a,b); } + template + EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const + { return internal::predux_mul(a); } +}; +template +struct functor_traits > { + enum { + Cost = (NumTraits::MulCost + NumTraits::MulCost)/2, // rough estimate! + PacketAccess = scalar_product_op::Vectorizable + }; +}; + +/** \internal + * \brief Template functor to compute the conjugate product of two scalars + * + * This is a short cut for conj(x) * y which is needed for optimization purpose; in Eigen2 support mode, this becomes x * conj(y) + */ +template struct scalar_conj_product_op { + + enum { + Conj = NumTraits::IsComplex + }; + + typedef typename scalar_product_traits::ReturnType result_type; + + EIGEN_EMPTY_STRUCT_CTOR(scalar_conj_product_op) + EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const + { return conj_helper().pmul(a,b); } + + template + EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const + { return conj_helper().pmul(a,b); } +}; +template +struct functor_traits > { + enum { + Cost = NumTraits::MulCost, + PacketAccess = internal::is_same::value && packet_traits::HasMul + }; +}; + +/** \internal + * \brief Template functor to compute the min of two scalars + * + * \sa class CwiseBinaryOp, MatrixBase::cwiseMin, class VectorwiseOp, MatrixBase::minCoeff() + */ +template struct scalar_min_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op) + EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { using std::min; return (min)(a, b); } + template + EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const + { return internal::pmin(a,b); } + template + EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const + { return internal::predux_min(a); } +}; +template +struct functor_traits > { + enum { + Cost = NumTraits::AddCost, + PacketAccess = packet_traits::HasMin + }; +}; + +/** \internal + * \brief Template functor to compute the max of two scalars + * + * \sa class CwiseBinaryOp, MatrixBase::cwiseMax, class VectorwiseOp, MatrixBase::maxCoeff() + */ +template struct scalar_max_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op) + EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { using std::max; return (max)(a, b); } + template + EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const + { return internal::pmax(a,b); } + template + EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const + { return internal::predux_max(a); } +}; +template +struct functor_traits > { + enum { + Cost = NumTraits::AddCost, + PacketAccess = packet_traits::HasMax + }; +}; + +/** \internal + * \brief Template functor to compute the hypot of two scalars + * + * \sa MatrixBase::stableNorm(), class Redux + */ +template struct scalar_hypot_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op) +// typedef typename NumTraits::Real result_type; + EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const + { + using std::max; + using std::min; + Scalar p = (max)(_x, _y); + Scalar q = (min)(_x, _y); + Scalar qp = q/p; + return p * sqrt(Scalar(1) + qp*qp); + } +}; +template +struct functor_traits > { + enum { Cost = 5 * NumTraits::MulCost, PacketAccess=0 }; +}; + +/** \internal + * \brief Template functor to compute the pow of two scalars + */ +template struct scalar_binary_pow_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_binary_pow_op) + inline Scalar operator() (const Scalar& a, const OtherScalar& b) const { return internal::pow(a, b); } +}; +template +struct functor_traits > { + enum { Cost = 5 * NumTraits::MulCost, PacketAccess = false }; +}; + +// other binary functors: + +/** \internal + * \brief Template functor to compute the difference of two scalars + * + * \sa class CwiseBinaryOp, MatrixBase::operator- + */ +template struct scalar_difference_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op) + EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a - b; } + template + EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const + { return internal::psub(a,b); } +}; +template +struct functor_traits > { + enum { + Cost = NumTraits::AddCost, + PacketAccess = packet_traits::HasSub + }; +}; + +/** \internal + * \brief Template functor to compute the quotient of two scalars + * + * \sa class CwiseBinaryOp, Cwise::operator/() + */ +template struct scalar_quotient_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op) + EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a / b; } + template + EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const + { return internal::pdiv(a,b); } +}; +template +struct functor_traits > { + enum { + Cost = 2 * NumTraits::MulCost, + PacketAccess = packet_traits::HasDiv + }; +}; + +/** \internal + * \brief Template functor to compute the and of two booleans + * + * \sa class CwiseBinaryOp, ArrayBase::operator&& + */ +struct scalar_boolean_and_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_and_op) + EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; } +}; +template<> struct functor_traits { + enum { + Cost = NumTraits::AddCost, + PacketAccess = false + }; +}; + +/** \internal + * \brief Template functor to compute the or of two booleans + * + * \sa class CwiseBinaryOp, ArrayBase::operator|| + */ +struct scalar_boolean_or_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_or_op) + EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; } +}; +template<> struct functor_traits { + enum { + Cost = NumTraits::AddCost, + PacketAccess = false + }; +}; + +// unary functors: + +/** \internal + * \brief Template functor to compute the opposite of a scalar + * + * \sa class CwiseUnaryOp, MatrixBase::operator- + */ +template struct scalar_opposite_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_opposite_op) + EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return -a; } + template + EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const + { return internal::pnegate(a); } +}; +template +struct functor_traits > +{ enum { + Cost = NumTraits::AddCost, + PacketAccess = packet_traits::HasNegate }; +}; + +/** \internal + * \brief Template functor to compute the absolute value of a scalar + * + * \sa class CwiseUnaryOp, Cwise::abs + */ +template struct scalar_abs_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_abs_op) + typedef typename NumTraits::Real result_type; + EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return internal::abs(a); } + template + EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const + { return internal::pabs(a); } +}; +template +struct functor_traits > +{ + enum { + Cost = NumTraits::AddCost, + PacketAccess = packet_traits::HasAbs + }; +}; + +/** \internal + * \brief Template functor to compute the squared absolute value of a scalar + * + * \sa class CwiseUnaryOp, Cwise::abs2 + */ +template struct scalar_abs2_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op) + typedef typename NumTraits::Real result_type; + EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return internal::abs2(a); } + template + EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const + { return internal::pmul(a,a); } +}; +template +struct functor_traits > +{ enum { Cost = NumTraits::MulCost, PacketAccess = packet_traits::HasAbs2 }; }; + +/** \internal + * \brief Template functor to compute the conjugate of a complex value + * + * \sa class CwiseUnaryOp, MatrixBase::conjugate() + */ +template struct scalar_conjugate_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op) + EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return internal::conj(a); } + template + EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); } +}; +template +struct functor_traits > +{ + enum { + Cost = NumTraits::IsComplex ? NumTraits::AddCost : 0, + PacketAccess = packet_traits::HasConj + }; +}; + +/** \internal + * \brief Template functor to cast a scalar to another type + * + * \sa class CwiseUnaryOp, MatrixBase::cast() + */ +template +struct scalar_cast_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_cast_op) + typedef NewType result_type; + EIGEN_STRONG_INLINE const NewType operator() (const Scalar& a) const { return cast(a); } +}; +template +struct functor_traits > +{ enum { Cost = is_same::value ? 0 : NumTraits::AddCost, PacketAccess = false }; }; + +/** \internal + * \brief Template functor to extract the real part of a complex + * + * \sa class CwiseUnaryOp, MatrixBase::real() + */ +template +struct scalar_real_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op) + typedef typename NumTraits::Real result_type; + EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::real(a); } +}; +template +struct functor_traits > +{ enum { Cost = 0, PacketAccess = false }; }; + +/** \internal + * \brief Template functor to extract the imaginary part of a complex + * + * \sa class CwiseUnaryOp, MatrixBase::imag() + */ +template +struct scalar_imag_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op) + typedef typename NumTraits::Real result_type; + EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::imag(a); } +}; +template +struct functor_traits > +{ enum { Cost = 0, PacketAccess = false }; }; + +/** \internal + * \brief Template functor to extract the real part of a complex as a reference + * + * \sa class CwiseUnaryOp, MatrixBase::real() + */ +template +struct scalar_real_ref_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op) + typedef typename NumTraits::Real result_type; + EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return internal::real_ref(*const_cast(&a)); } +}; +template +struct functor_traits > +{ enum { Cost = 0, PacketAccess = false }; }; + +/** \internal + * \brief Template functor to extract the imaginary part of a complex as a reference + * + * \sa class CwiseUnaryOp, MatrixBase::imag() + */ +template +struct scalar_imag_ref_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op) + typedef typename NumTraits::Real result_type; + EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return internal::imag_ref(*const_cast(&a)); } +}; +template +struct functor_traits > +{ enum { Cost = 0, PacketAccess = false }; }; + +/** \internal + * + * \brief Template functor to compute the exponential of a scalar + * + * \sa class CwiseUnaryOp, Cwise::exp() + */ +template struct scalar_exp_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_exp_op) + inline const Scalar operator() (const Scalar& a) const { return internal::exp(a); } + typedef typename packet_traits::type Packet; + inline Packet packetOp(const Packet& a) const { return internal::pexp(a); } +}; +template +struct functor_traits > +{ enum { Cost = 5 * NumTraits::MulCost, PacketAccess = packet_traits::HasExp }; }; + +/** \internal + * + * \brief Template functor to compute the logarithm of a scalar + * + * \sa class CwiseUnaryOp, Cwise::log() + */ +template struct scalar_log_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_log_op) + inline const Scalar operator() (const Scalar& a) const { return internal::log(a); } + typedef typename packet_traits::type Packet; + inline Packet packetOp(const Packet& a) const { return internal::plog(a); } +}; +template +struct functor_traits > +{ enum { Cost = 5 * NumTraits::MulCost, PacketAccess = packet_traits::HasLog }; }; + +/** \internal + * \brief Template functor to multiply a scalar by a fixed other one + * + * \sa class CwiseUnaryOp, MatrixBase::operator*, MatrixBase::operator/ + */ +/* NOTE why doing the pset1() in packetOp *is* an optimization ? + * indeed it seems better to declare m_other as a Packet and do the pset1() once + * in the constructor. However, in practice: + * - GCC does not like m_other as a Packet and generate a load every time it needs it + * - on the other hand GCC is able to moves the pset1() away the loop :) + * - simpler code ;) + * (ICC and gcc 4.4 seems to perform well in both cases, the issue is visible with y = a*x + b*y) + */ +template +struct scalar_multiple_op { + typedef typename packet_traits::type Packet; + // FIXME default copy constructors seems bugged with std::complex<> + EIGEN_STRONG_INLINE scalar_multiple_op(const scalar_multiple_op& other) : m_other(other.m_other) { } + EIGEN_STRONG_INLINE scalar_multiple_op(const Scalar& other) : m_other(other) { } + EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; } + EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const + { return internal::pmul(a, pset1(m_other)); } + typename add_const_on_value_type::Nested>::type m_other; +}; +template +struct functor_traits > +{ enum { Cost = NumTraits::MulCost, PacketAccess = packet_traits::HasMul }; }; + +template +struct scalar_multiple2_op { + typedef typename scalar_product_traits::ReturnType result_type; + EIGEN_STRONG_INLINE scalar_multiple2_op(const scalar_multiple2_op& other) : m_other(other.m_other) { } + EIGEN_STRONG_INLINE scalar_multiple2_op(const Scalar2& other) : m_other(other) { } + EIGEN_STRONG_INLINE result_type operator() (const Scalar1& a) const { return a * m_other; } + typename add_const_on_value_type::Nested>::type m_other; +}; +template +struct functor_traits > +{ enum { Cost = NumTraits::MulCost, PacketAccess = false }; }; + +template +struct scalar_quotient1_impl { + typedef typename packet_traits::type Packet; + // FIXME default copy constructors seems bugged with std::complex<> + EIGEN_STRONG_INLINE scalar_quotient1_impl(const scalar_quotient1_impl& other) : m_other(other.m_other) { } + EIGEN_STRONG_INLINE scalar_quotient1_impl(const Scalar& other) : m_other(static_cast(1) / other) {} + EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; } + EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const + { return internal::pmul(a, pset1(m_other)); } + const Scalar m_other; +}; +template +struct functor_traits > +{ enum { Cost = NumTraits::MulCost, PacketAccess = packet_traits::HasMul }; }; + +template +struct scalar_quotient1_impl { + // FIXME default copy constructors seems bugged with std::complex<> + EIGEN_STRONG_INLINE scalar_quotient1_impl(const scalar_quotient1_impl& other) : m_other(other.m_other) { } + EIGEN_STRONG_INLINE scalar_quotient1_impl(const Scalar& other) : m_other(other) {} + EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; } + typename add_const_on_value_type::Nested>::type m_other; +}; +template +struct functor_traits > +{ enum { Cost = 2 * NumTraits::MulCost, PacketAccess = false }; }; + +/** \internal + * \brief Template functor to divide a scalar by a fixed other one + * + * This functor is used to implement the quotient of a matrix by + * a scalar where the scalar type is not necessarily a floating point type. + * + * \sa class CwiseUnaryOp, MatrixBase::operator/ + */ +template +struct scalar_quotient1_op : scalar_quotient1_impl::IsInteger > { + EIGEN_STRONG_INLINE scalar_quotient1_op(const Scalar& other) + : scalar_quotient1_impl::IsInteger >(other) {} +}; +template +struct functor_traits > +: functor_traits::IsInteger> > +{}; + +// nullary functors + +template +struct scalar_constant_op { + typedef typename packet_traits::type Packet; + EIGEN_STRONG_INLINE scalar_constant_op(const scalar_constant_op& other) : m_other(other.m_other) { } + EIGEN_STRONG_INLINE scalar_constant_op(const Scalar& other) : m_other(other) { } + template + EIGEN_STRONG_INLINE const Scalar operator() (Index, Index = 0) const { return m_other; } + template + EIGEN_STRONG_INLINE const Packet packetOp(Index, Index = 0) const { return internal::pset1(m_other); } + const Scalar m_other; +}; +template +struct functor_traits > +// FIXME replace this packet test by a safe one +{ enum { Cost = 1, PacketAccess = packet_traits::Vectorizable, IsRepeatable = true }; }; + +template struct scalar_identity_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_identity_op) + template + EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const { return row==col ? Scalar(1) : Scalar(0); } +}; +template +struct functor_traits > +{ enum { Cost = NumTraits::AddCost, PacketAccess = false, IsRepeatable = true }; }; + +template struct linspaced_op_impl; + +// linear access for packet ops: +// 1) initialization +// base = [low, ..., low] + ([step, ..., step] * [-size, ..., 0]) +// 2) each step +// base += [size*step, ..., size*step] +template +struct linspaced_op_impl +{ + typedef typename packet_traits::type Packet; + + linspaced_op_impl(Scalar low, Scalar step) : + m_low(low), m_step(step), + m_packetStep(pset1(packet_traits::size*step)), + m_base(padd(pset1(low),pmul(pset1(step),plset(-packet_traits::size)))) {} + + template + EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; } + template + EIGEN_STRONG_INLINE const Packet packetOp(Index) const { return m_base = padd(m_base,m_packetStep); } + + const Scalar m_low; + const Scalar m_step; + const Packet m_packetStep; + mutable Packet m_base; +}; + +// random access for packet ops: +// 1) each step +// [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) ) +template +struct linspaced_op_impl +{ + typedef typename packet_traits::type Packet; + + linspaced_op_impl(Scalar low, Scalar step) : + m_low(low), m_step(step), + m_lowPacket(pset1(m_low)), m_stepPacket(pset1(m_step)), m_interPacket(plset(0)) {} + + template + EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; } + + template + EIGEN_STRONG_INLINE const Packet packetOp(Index i) const + { return internal::padd(m_lowPacket, pmul(m_stepPacket, padd(pset1(i),m_interPacket))); } + + const Scalar m_low; + const Scalar m_step; + const Packet m_lowPacket; + const Packet m_stepPacket; + const Packet m_interPacket; +}; + +// ----- Linspace functor ---------------------------------------------------------------- + +// Forward declaration (we default to random access which does not really give +// us a speed gain when using packet access but it allows to use the functor in +// nested expressions). +template struct linspaced_op; +template struct functor_traits< linspaced_op > +{ enum { Cost = 1, PacketAccess = packet_traits::HasSetLinear, IsRepeatable = true }; }; +template struct linspaced_op +{ + typedef typename packet_traits::type Packet; + linspaced_op(Scalar low, Scalar high, int num_steps) : impl((num_steps==1 ? high : low), (num_steps==1 ? Scalar() : (high-low)/(num_steps-1))) {} + + template + EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); } + + // We need this function when assigning e.g. a RowVectorXd to a MatrixXd since + // there row==0 and col is used for the actual iteration. + template + EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const + { + eigen_assert(col==0 || row==0); + return impl(col + row); + } + + template + EIGEN_STRONG_INLINE const Packet packetOp(Index i) const { return impl.packetOp(i); } + + // We need this function when assigning e.g. a RowVectorXd to a MatrixXd since + // there row==0 and col is used for the actual iteration. + template + EIGEN_STRONG_INLINE const Packet packetOp(Index row, Index col) const + { + eigen_assert(col==0 || row==0); + return impl.packetOp(col + row); + } + + // This proxy object handles the actual required temporaries, the different + // implementations (random vs. sequential access) as well as the + // correct piping to size 2/4 packet operations. + const linspaced_op_impl impl; +}; + +// all functors allow linear access, except scalar_identity_op. So we fix here a quick meta +// to indicate whether a functor allows linear access, just always answering 'yes' except for +// scalar_identity_op. +// FIXME move this to functor_traits adding a functor_default +template struct functor_has_linear_access { enum { ret = 1 }; }; +template struct functor_has_linear_access > { enum { ret = 0 }; }; + +// in CwiseBinaryOp, we require the Lhs and Rhs to have the same scalar type, except for multiplication +// where we only require them to have the same _real_ scalar type so one may multiply, say, float by complex. +// FIXME move this to functor_traits adding a functor_default +template struct functor_allows_mixing_real_and_complex { enum { ret = 0 }; }; +template struct functor_allows_mixing_real_and_complex > { enum { ret = 1 }; }; +template struct functor_allows_mixing_real_and_complex > { enum { ret = 1 }; }; + + +/** \internal + * \brief Template functor to add a scalar to a fixed other one + * \sa class CwiseUnaryOp, Array::operator+ + */ +/* If you wonder why doing the pset1() in packetOp() is an optimization check scalar_multiple_op */ +template +struct scalar_add_op { + typedef typename packet_traits::type Packet; + // FIXME default copy constructors seems bugged with std::complex<> + inline scalar_add_op(const scalar_add_op& other) : m_other(other.m_other) { } + inline scalar_add_op(const Scalar& other) : m_other(other) { } + inline Scalar operator() (const Scalar& a) const { return a + m_other; } + inline const Packet packetOp(const Packet& a) const + { return internal::padd(a, pset1(m_other)); } + const Scalar m_other; +}; +template +struct functor_traits > +{ enum { Cost = NumTraits::AddCost, PacketAccess = packet_traits::HasAdd }; }; + +/** \internal + * \brief Template functor to compute the square root of a scalar + * \sa class CwiseUnaryOp, Cwise::sqrt() + */ +template struct scalar_sqrt_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op) + inline const Scalar operator() (const Scalar& a) const { return internal::sqrt(a); } + typedef typename packet_traits::type Packet; + inline Packet packetOp(const Packet& a) const { return internal::psqrt(a); } +}; +template +struct functor_traits > +{ enum { + Cost = 5 * NumTraits::MulCost, + PacketAccess = packet_traits::HasSqrt + }; +}; + +/** \internal + * \brief Template functor to compute the cosine of a scalar + * \sa class CwiseUnaryOp, ArrayBase::cos() + */ +template struct scalar_cos_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op) + inline Scalar operator() (const Scalar& a) const { return internal::cos(a); } + typedef typename packet_traits::type Packet; + inline Packet packetOp(const Packet& a) const { return internal::pcos(a); } +}; +template +struct functor_traits > +{ + enum { + Cost = 5 * NumTraits::MulCost, + PacketAccess = packet_traits::HasCos + }; +}; + +/** \internal + * \brief Template functor to compute the sine of a scalar + * \sa class CwiseUnaryOp, ArrayBase::sin() + */ +template struct scalar_sin_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op) + inline const Scalar operator() (const Scalar& a) const { return internal::sin(a); } + typedef typename packet_traits::type Packet; + inline Packet packetOp(const Packet& a) const { return internal::psin(a); } +}; +template +struct functor_traits > +{ + enum { + Cost = 5 * NumTraits::MulCost, + PacketAccess = packet_traits::HasSin + }; +}; + + +/** \internal + * \brief Template functor to compute the tan of a scalar + * \sa class CwiseUnaryOp, ArrayBase::tan() + */ +template struct scalar_tan_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_tan_op) + inline const Scalar operator() (const Scalar& a) const { return internal::tan(a); } + typedef typename packet_traits::type Packet; + inline Packet packetOp(const Packet& a) const { return internal::ptan(a); } +}; +template +struct functor_traits > +{ + enum { + Cost = 5 * NumTraits::MulCost, + PacketAccess = packet_traits::HasTan + }; +}; + +/** \internal + * \brief Template functor to compute the arc cosine of a scalar + * \sa class CwiseUnaryOp, ArrayBase::acos() + */ +template struct scalar_acos_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_acos_op) + inline const Scalar operator() (const Scalar& a) const { return internal::acos(a); } + typedef typename packet_traits::type Packet; + inline Packet packetOp(const Packet& a) const { return internal::pacos(a); } +}; +template +struct functor_traits > +{ + enum { + Cost = 5 * NumTraits::MulCost, + PacketAccess = packet_traits::HasACos + }; +}; + +/** \internal + * \brief Template functor to compute the arc sine of a scalar + * \sa class CwiseUnaryOp, ArrayBase::asin() + */ +template struct scalar_asin_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op) + inline const Scalar operator() (const Scalar& a) const { return internal::asin(a); } + typedef typename packet_traits::type Packet; + inline Packet packetOp(const Packet& a) const { return internal::pasin(a); } +}; +template +struct functor_traits > +{ + enum { + Cost = 5 * NumTraits::MulCost, + PacketAccess = packet_traits::HasASin + }; +}; + +/** \internal + * \brief Template functor to raise a scalar to a power + * \sa class CwiseUnaryOp, Cwise::pow + */ +template +struct scalar_pow_op { + // FIXME default copy constructors seems bugged with std::complex<> + inline scalar_pow_op(const scalar_pow_op& other) : m_exponent(other.m_exponent) { } + inline scalar_pow_op(const Scalar& exponent) : m_exponent(exponent) {} + inline Scalar operator() (const Scalar& a) const { return internal::pow(a, m_exponent); } + const Scalar m_exponent; +}; +template +struct functor_traits > +{ enum { Cost = 5 * NumTraits::MulCost, PacketAccess = false }; }; + +/** \internal + * \brief Template functor to compute the quotient between a scalar and array entries. + * \sa class CwiseUnaryOp, Cwise::inverse() + */ +template +struct scalar_inverse_mult_op { + scalar_inverse_mult_op(const Scalar& other) : m_other(other) {} + inline Scalar operator() (const Scalar& a) const { return m_other / a; } + template + inline const Packet packetOp(const Packet& a) const + { return internal::pdiv(pset1(m_other),a); } + Scalar m_other; +}; + +/** \internal + * \brief Template functor to compute the inverse of a scalar + * \sa class CwiseUnaryOp, Cwise::inverse() + */ +template +struct scalar_inverse_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_inverse_op) + inline Scalar operator() (const Scalar& a) const { return Scalar(1)/a; } + template + inline const Packet packetOp(const Packet& a) const + { return internal::pdiv(pset1(Scalar(1)),a); } +}; +template +struct functor_traits > +{ enum { Cost = NumTraits::MulCost, PacketAccess = packet_traits::HasDiv }; }; + +/** \internal + * \brief Template functor to compute the square of a scalar + * \sa class CwiseUnaryOp, Cwise::square() + */ +template +struct scalar_square_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_square_op) + inline Scalar operator() (const Scalar& a) const { return a*a; } + template + inline const Packet packetOp(const Packet& a) const + { return internal::pmul(a,a); } +}; +template +struct functor_traits > +{ enum { Cost = NumTraits::MulCost, PacketAccess = packet_traits::HasMul }; }; + +/** \internal + * \brief Template functor to compute the cube of a scalar + * \sa class CwiseUnaryOp, Cwise::cube() + */ +template +struct scalar_cube_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_cube_op) + inline Scalar operator() (const Scalar& a) const { return a*a*a; } + template + inline const Packet packetOp(const Packet& a) const + { return internal::pmul(a,pmul(a,a)); } +}; +template +struct functor_traits > +{ enum { Cost = 2*NumTraits::MulCost, PacketAccess = packet_traits::HasMul }; }; + +// default functor traits for STL functors: + +template +struct functor_traits > +{ enum { Cost = NumTraits::MulCost, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = NumTraits::MulCost, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = NumTraits::AddCost, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = NumTraits::AddCost, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = NumTraits::AddCost, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = 1, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = 1, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = 1, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = 1, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = 1, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = 1, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = 1, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = 1, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = 1, PacketAccess = false }; }; + +#if __cplusplus < 201703L +template +struct functor_traits > +{ enum { Cost = functor_traits::Cost, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = functor_traits::Cost, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = 1 + functor_traits::Cost, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = 1 + functor_traits::Cost, PacketAccess = false }; }; +#endif + +#ifdef EIGEN_STDEXT_SUPPORT + +template +struct functor_traits > +{ enum { Cost = 0, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = 0, PacketAccess = false }; }; + +template +struct functor_traits > > +{ enum { Cost = 0, PacketAccess = false }; }; + +template +struct functor_traits > > +{ enum { Cost = 0, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = functor_traits::Cost + functor_traits::Cost, PacketAccess = false }; }; + +template +struct functor_traits > +{ enum { Cost = functor_traits::Cost + functor_traits::Cost + functor_traits::Cost, PacketAccess = false }; }; + +#endif // EIGEN_STDEXT_SUPPORT + +// allow to add new functors and specializations of functor_traits from outside Eigen. +// this macro is really needed because functor_traits must be specialized after it is declared but before it is used... +#ifdef EIGEN_FUNCTORS_PLUGIN +#include EIGEN_FUNCTORS_PLUGIN +#endif + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_FUNCTORS_H diff --git a/Util/Patches/Eigen3.1.0/MatrixCwiseUnaryOps.h b/Util/Patches/Eigen3.1.0/MatrixCwiseUnaryOps.h new file mode 100644 index 00000000000..297bfb5d326 --- /dev/null +++ b/Util/Patches/Eigen3.1.0/MatrixCwiseUnaryOps.h @@ -0,0 +1,85 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2009 Gael Guennebaud +// Copyright (C) 2006-2008 Benoit Jacob +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see . + +// This file is a base class plugin containing matrix specifics coefficient wise functions. + + +/** \returns an expression of the coefficient-wise absolute value of \c *this + * + * Example: \include MatrixBase_cwiseAbs.cpp + * Output: \verbinclude MatrixBase_cwiseAbs.out + * + * \sa cwiseAbs2() + */ +EIGEN_STRONG_INLINE const CwiseUnaryOp, const Derived> +cwiseAbs() const { return derived(); } + +/** \returns an expression of the coefficient-wise squared absolute value of \c *this + * + * Example: \include MatrixBase_cwiseAbs2.cpp + * Output: \verbinclude MatrixBase_cwiseAbs2.out + * + * \sa cwiseAbs() + */ +EIGEN_STRONG_INLINE const CwiseUnaryOp, const Derived> +cwiseAbs2() const { return derived(); } + +/** \returns an expression of the coefficient-wise square root of *this. + * + * Example: \include MatrixBase_cwiseSqrt.cpp + * Output: \verbinclude MatrixBase_cwiseSqrt.out + * + * \sa cwisePow(), cwiseSquare() + */ +inline const CwiseUnaryOp, const Derived> +cwiseSqrt() const { return derived(); } + +/** \returns an expression of the coefficient-wise inverse of *this. + * + * Example: \include MatrixBase_cwiseInverse.cpp + * Output: \verbinclude MatrixBase_cwiseInverse.out + * + * \sa cwiseProduct() + */ +inline const CwiseUnaryOp, const Derived> +cwiseInverse() const { return derived(); } + +#if __cplusplus < 201703L +/** \returns an expression of the coefficient-wise == operator of \c *this and a scalar \a s + * + * \warning this performs an exact comparison, which is generally a bad idea with floating-point types. + * In order to check for equality between two vectors or matrices with floating-point coefficients, it is + * generally a far better idea to use a fuzzy comparison as provided by isApprox() and + * isMuchSmallerThan(). + * + * \sa cwiseEqual(const MatrixBase &) const + */ +inline const CwiseUnaryOp >, const Derived> +cwiseEqual(const Scalar& s) const +{ + return CwiseUnaryOp >,const Derived> + (derived(), std::bind1st(std::equal_to(), s)); +} +#endif \ No newline at end of file diff --git a/Util/Patches/Eigen3.1.0/PacketMath.h b/Util/Patches/Eigen3.1.0/PacketMath.h new file mode 100644 index 00000000000..c618a2cc38e --- /dev/null +++ b/Util/Patches/Eigen3.1.0/PacketMath.h @@ -0,0 +1,647 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2009 Gael Guennebaud +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see . + +#ifndef EIGEN_PACKET_MATH_SSE_H +#define EIGEN_PACKET_MATH_SSE_H + +namespace Eigen { + +namespace internal { + +#ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD +#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 8 +#endif + +#ifndef EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS +#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS (2*sizeof(void*)) +#endif + +typedef __m128 Packet4f; +typedef __m128i Packet4i; +typedef __m128d Packet2d; + +template<> struct is_arithmetic<__m128> { enum { value = true }; }; +template<> struct is_arithmetic<__m128i> { enum { value = true }; }; +template<> struct is_arithmetic<__m128d> { enum { value = true }; }; + +#define vec4f_swizzle1(v,p,q,r,s) \ + (_mm_castsi128_ps(_mm_shuffle_epi32( _mm_castps_si128(v), ((s)<<6|(r)<<4|(q)<<2|(p))))) + +#define vec4i_swizzle1(v,p,q,r,s) \ + (_mm_shuffle_epi32( v, ((s)<<6|(r)<<4|(q)<<2|(p)))) + +#define vec2d_swizzle1(v,p,q) \ + (_mm_castsi128_pd(_mm_shuffle_epi32( _mm_castpd_si128(v), ((q*2+1)<<6|(q*2)<<4|(p*2+1)<<2|(p*2))))) + +#define vec4f_swizzle2(a,b,p,q,r,s) \ + (_mm_shuffle_ps( (a), (b), ((s)<<6|(r)<<4|(q)<<2|(p)))) + +#define vec4i_swizzle2(a,b,p,q,r,s) \ + (_mm_castps_si128( (_mm_shuffle_ps( _mm_castsi128_ps(a), _mm_castsi128_ps(b), ((s)<<6|(r)<<4|(q)<<2|(p)))))) + +#define _EIGEN_DECLARE_CONST_Packet4f(NAME,X) \ + const Packet4f p4f_##NAME = pset1(X) + +#define _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(NAME,X) \ + const Packet4f p4f_##NAME = _mm_castsi128_ps(pset1(X)) + +#define _EIGEN_DECLARE_CONST_Packet4i(NAME,X) \ + const Packet4i p4i_##NAME = pset1(X) + + +template<> struct packet_traits : default_packet_traits +{ + typedef Packet4f type; + enum { + Vectorizable = 1, + AlignedOnScalar = 1, + size=4, + + HasDiv = 1, + HasSin = EIGEN_FAST_MATH, + HasCos = EIGEN_FAST_MATH, + HasLog = 1, + HasExp = 1, + HasSqrt = 1 + }; +}; +template<> struct packet_traits : default_packet_traits +{ + typedef Packet2d type; + enum { + Vectorizable = 1, + AlignedOnScalar = 1, + size=2, + + HasDiv = 1 + }; +}; +template<> struct packet_traits : default_packet_traits +{ + typedef Packet4i type; + enum { + // FIXME check the Has* + Vectorizable = 1, + AlignedOnScalar = 1, + size=4 + }; +}; + +template<> struct unpacket_traits { typedef float type; enum {size=4}; }; +template<> struct unpacket_traits { typedef double type; enum {size=2}; }; +template<> struct unpacket_traits { typedef int type; enum {size=4}; }; + +#if defined(_MSC_VER) && (_MSC_VER==1500) +// Workaround MSVC 9 internal compiler error. +// TODO: It has been detected with win64 builds (amd64), so let's check whether it also happens in 32bits+SSE mode +// TODO: let's check whether there does not exist a better fix, like adding a pset0() function. (it crashed on pset1(0)). +template<> EIGEN_STRONG_INLINE Packet4f pset1(const float& from) { return _mm_set_ps(from,from,from,from); } +template<> EIGEN_STRONG_INLINE Packet2d pset1(const double& from) { return _mm_set_pd(from,from); } +template<> EIGEN_STRONG_INLINE Packet4i pset1(const int& from) { return _mm_set_epi32(from,from,from,from); } +#else +template<> EIGEN_STRONG_INLINE Packet4f pset1(const float& from) { return _mm_set1_ps(from); } +template<> EIGEN_STRONG_INLINE Packet2d pset1(const double& from) { return _mm_set1_pd(from); } +template<> EIGEN_STRONG_INLINE Packet4i pset1(const int& from) { return _mm_set1_epi32(from); } +#endif + +template<> EIGEN_STRONG_INLINE Packet4f plset(const float& a) { return _mm_add_ps(pset1(a), _mm_set_ps(3,2,1,0)); } +template<> EIGEN_STRONG_INLINE Packet2d plset(const double& a) { return _mm_add_pd(pset1(a),_mm_set_pd(1,0)); } +template<> EIGEN_STRONG_INLINE Packet4i plset(const int& a) { return _mm_add_epi32(pset1(a),_mm_set_epi32(3,2,1,0)); } + +template<> EIGEN_STRONG_INLINE Packet4f padd(const Packet4f& a, const Packet4f& b) { return _mm_add_ps(a,b); } +template<> EIGEN_STRONG_INLINE Packet2d padd(const Packet2d& a, const Packet2d& b) { return _mm_add_pd(a,b); } +template<> EIGEN_STRONG_INLINE Packet4i padd(const Packet4i& a, const Packet4i& b) { return _mm_add_epi32(a,b); } + +template<> EIGEN_STRONG_INLINE Packet4f psub(const Packet4f& a, const Packet4f& b) { return _mm_sub_ps(a,b); } +template<> EIGEN_STRONG_INLINE Packet2d psub(const Packet2d& a, const Packet2d& b) { return _mm_sub_pd(a,b); } +template<> EIGEN_STRONG_INLINE Packet4i psub(const Packet4i& a, const Packet4i& b) { return _mm_sub_epi32(a,b); } + +template<> EIGEN_STRONG_INLINE Packet4f pnegate(const Packet4f& a) +{ + const Packet4f mask = _mm_castsi128_ps(_mm_setr_epi32(0x80000000,0x80000000,0x80000000,0x80000000)); + return _mm_xor_ps(a,mask); +} +template<> EIGEN_STRONG_INLINE Packet2d pnegate(const Packet2d& a) +{ + const Packet2d mask = _mm_castsi128_pd(_mm_setr_epi32(0x0,0x80000000,0x0,0x80000000)); + return _mm_xor_pd(a,mask); +} +template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a) +{ + return psub(_mm_setr_epi32(0,0,0,0), a); +} + +template<> EIGEN_STRONG_INLINE Packet4f pmul(const Packet4f& a, const Packet4f& b) { return _mm_mul_ps(a,b); } +template<> EIGEN_STRONG_INLINE Packet2d pmul(const Packet2d& a, const Packet2d& b) { return _mm_mul_pd(a,b); } +template<> EIGEN_STRONG_INLINE Packet4i pmul(const Packet4i& a, const Packet4i& b) +{ +#ifdef EIGEN_VECTORIZE_SSE4_1 + return _mm_mullo_epi32(a,b); +#else + // this version is slightly faster than 4 scalar products + return vec4i_swizzle1( + vec4i_swizzle2( + _mm_mul_epu32(a,b), + _mm_mul_epu32(vec4i_swizzle1(a,1,0,3,2), + vec4i_swizzle1(b,1,0,3,2)), + 0,2,0,2), + 0,2,1,3); +#endif +} + +template<> EIGEN_STRONG_INLINE Packet4f pdiv(const Packet4f& a, const Packet4f& b) { return _mm_div_ps(a,b); } +template<> EIGEN_STRONG_INLINE Packet2d pdiv(const Packet2d& a, const Packet2d& b) { return _mm_div_pd(a,b); } +template<> EIGEN_STRONG_INLINE Packet4i pdiv(const Packet4i& /*a*/, const Packet4i& /*b*/) +{ eigen_assert(false && "packet integer division are not supported by SSE"); + return pset1(0); +} + +// for some weird raisons, it has to be overloaded for packet of integers +template<> EIGEN_STRONG_INLINE Packet4i pmadd(const Packet4i& a, const Packet4i& b, const Packet4i& c) { return padd(pmul(a,b), c); } + +template<> EIGEN_STRONG_INLINE Packet4f pmin(const Packet4f& a, const Packet4f& b) { return _mm_min_ps(a,b); } +template<> EIGEN_STRONG_INLINE Packet2d pmin(const Packet2d& a, const Packet2d& b) { return _mm_min_pd(a,b); } +template<> EIGEN_STRONG_INLINE Packet4i pmin(const Packet4i& a, const Packet4i& b) +{ + // after some bench, this version *is* faster than a scalar implementation + Packet4i mask = _mm_cmplt_epi32(a,b); + return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b)); +} + +template<> EIGEN_STRONG_INLINE Packet4f pmax(const Packet4f& a, const Packet4f& b) { return _mm_max_ps(a,b); } +template<> EIGEN_STRONG_INLINE Packet2d pmax(const Packet2d& a, const Packet2d& b) { return _mm_max_pd(a,b); } +template<> EIGEN_STRONG_INLINE Packet4i pmax(const Packet4i& a, const Packet4i& b) +{ + // after some bench, this version *is* faster than a scalar implementation + Packet4i mask = _mm_cmpgt_epi32(a,b); + return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b)); +} + +template<> EIGEN_STRONG_INLINE Packet4f pand(const Packet4f& a, const Packet4f& b) { return _mm_and_ps(a,b); } +template<> EIGEN_STRONG_INLINE Packet2d pand(const Packet2d& a, const Packet2d& b) { return _mm_and_pd(a,b); } +template<> EIGEN_STRONG_INLINE Packet4i pand(const Packet4i& a, const Packet4i& b) { return _mm_and_si128(a,b); } + +template<> EIGEN_STRONG_INLINE Packet4f por(const Packet4f& a, const Packet4f& b) { return _mm_or_ps(a,b); } +template<> EIGEN_STRONG_INLINE Packet2d por(const Packet2d& a, const Packet2d& b) { return _mm_or_pd(a,b); } +template<> EIGEN_STRONG_INLINE Packet4i por(const Packet4i& a, const Packet4i& b) { return _mm_or_si128(a,b); } + +template<> EIGEN_STRONG_INLINE Packet4f pxor(const Packet4f& a, const Packet4f& b) { return _mm_xor_ps(a,b); } +template<> EIGEN_STRONG_INLINE Packet2d pxor(const Packet2d& a, const Packet2d& b) { return _mm_xor_pd(a,b); } +template<> EIGEN_STRONG_INLINE Packet4i pxor(const Packet4i& a, const Packet4i& b) { return _mm_xor_si128(a,b); } + +template<> EIGEN_STRONG_INLINE Packet4f pandnot(const Packet4f& a, const Packet4f& b) { return _mm_andnot_ps(a,b); } +template<> EIGEN_STRONG_INLINE Packet2d pandnot(const Packet2d& a, const Packet2d& b) { return _mm_andnot_pd(a,b); } +template<> EIGEN_STRONG_INLINE Packet4i pandnot(const Packet4i& a, const Packet4i& b) { return _mm_andnot_si128(a,b); } + +template<> EIGEN_STRONG_INLINE Packet4f pload(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm_load_ps(from); } +template<> EIGEN_STRONG_INLINE Packet2d pload(const double* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm_load_pd(from); } +template<> EIGEN_STRONG_INLINE Packet4i pload(const int* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm_load_si128(reinterpret_cast(from)); } + +#if defined(_MSC_VER) + template<> EIGEN_STRONG_INLINE Packet4f ploadu(const float* from) { + EIGEN_DEBUG_UNALIGNED_LOAD + #if (_MSC_VER==1600) + // NOTE Some version of MSVC10 generates bad code when using _mm_loadu_ps + // (i.e., it does not generate an unaligned load!! + // TODO On most architectures this version should also be faster than a single _mm_loadu_ps + // so we could also enable it for MSVC08 but first we have to make this later does not generate crap when doing so... + __m128 res = _mm_loadl_pi(_mm_set1_ps(0.0f), (const __m64*)(from)); + res = _mm_loadh_pi(res, (const __m64*)(from+2)); + return res; + #else + return _mm_loadu_ps(from); + #endif + } + template<> EIGEN_STRONG_INLINE Packet2d ploadu(const double* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_pd(from); } + template<> EIGEN_STRONG_INLINE Packet4i ploadu(const int* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_si128(reinterpret_cast(from)); } +#else +// Fast unaligned loads. Note that here we cannot directly use intrinsics: this would +// require pointer casting to incompatible pointer types and leads to invalid code +// because of the strict aliasing rule. The "dummy" stuff are required to enforce +// a correct instruction dependency. +// TODO: do the same for MSVC (ICC is compatible) +// NOTE: with the code below, MSVC's compiler crashes! + +#if defined(__GNUC__) && defined(__i386__) + // bug 195: gcc/i386 emits weird x87 fldl/fstpl instructions for _mm_load_sd + #define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1 +#elif defined(__clang__) + // bug 201: Segfaults in __mm_loadh_pd with clang 2.8 + #define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1 +#else + #define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 0 +#endif + +template<> EIGEN_STRONG_INLINE Packet4f ploadu(const float* from) +{ + EIGEN_DEBUG_UNALIGNED_LOAD +#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS + return _mm_loadu_ps(from); +#else + __m128d res; + res = _mm_load_sd((const double*)(from)) ; + res = _mm_loadh_pd(res, (const double*)(from+2)) ; + return _mm_castpd_ps(res); +#endif +} +template<> EIGEN_STRONG_INLINE Packet2d ploadu(const double* from) +{ + EIGEN_DEBUG_UNALIGNED_LOAD +#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS + return _mm_loadu_pd(from); +#else + __m128d res; + res = _mm_load_sd(from) ; + res = _mm_loadh_pd(res,from+1); + return res; +#endif +} +template<> EIGEN_STRONG_INLINE Packet4i ploadu(const int* from) +{ + EIGEN_DEBUG_UNALIGNED_LOAD +#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS + return _mm_loadu_si128(reinterpret_cast(from)); +#else + __m128d res; + res = _mm_load_sd((const double*)(from)) ; + res = _mm_loadh_pd(res, (const double*)(from+2)) ; + return _mm_castpd_si128(res); +#endif +} +#endif + +template<> EIGEN_STRONG_INLINE Packet4f ploaddup(const float* from) +{ + return vec4f_swizzle1(_mm_castpd_ps(_mm_load_sd(reinterpret_cast(from))), 0, 0, 1, 1); +} +template<> EIGEN_STRONG_INLINE Packet2d ploaddup(const double* from) +{ return pset1(from[0]); } +template<> EIGEN_STRONG_INLINE Packet4i ploaddup(const int* from) +{ + Packet4i tmp; + tmp = _mm_loadl_epi64(reinterpret_cast(from)); + return vec4i_swizzle1(tmp, 0, 0, 1, 1); +} + +template<> EIGEN_STRONG_INLINE void pstore(float* to, const Packet4f& from) { EIGEN_DEBUG_ALIGNED_STORE _mm_store_ps(to, from); } +template<> EIGEN_STRONG_INLINE void pstore(double* to, const Packet2d& from) { EIGEN_DEBUG_ALIGNED_STORE _mm_store_pd(to, from); } +template<> EIGEN_STRONG_INLINE void pstore(int* to, const Packet4i& from) { EIGEN_DEBUG_ALIGNED_STORE _mm_store_si128(reinterpret_cast(to), from); } + +template<> EIGEN_STRONG_INLINE void pstoreu(double* to, const Packet2d& from) { + EIGEN_DEBUG_UNALIGNED_STORE + _mm_storel_pd((to), from); + _mm_storeh_pd((to+1), from); +} +template<> EIGEN_STRONG_INLINE void pstoreu(float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(reinterpret_cast(to), _mm_castps_pd(from)); } +template<> EIGEN_STRONG_INLINE void pstoreu(int* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(reinterpret_cast(to), _mm_castsi128_pd(from)); } + +// some compilers might be tempted to perform multiple moves instead of using a vector path. +template<> EIGEN_STRONG_INLINE void pstore1(float* to, const float& a) +{ + Packet4f pa = _mm_set_ss(a); + pstore(to, vec4f_swizzle1(pa,0,0,0,0)); +} +// some compilers might be tempted to perform multiple moves instead of using a vector path. +template<> EIGEN_STRONG_INLINE void pstore1(double* to, const double& a) +{ + Packet2d pa = _mm_set_sd(a); + pstore(to, vec2d_swizzle1(pa,0,0)); +} + +template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } + +#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER) +// The temporary variable fixes an internal compilation error in vs <= 2008 and a wrong-result bug in vs 2010 +// Direct of the struct members fixed bug #62. +template<> EIGEN_STRONG_INLINE float pfirst(const Packet4f& a) { return a.m128_f32[0]; } +template<> EIGEN_STRONG_INLINE double pfirst(const Packet2d& a) { return a.m128d_f64[0]; } +template<> EIGEN_STRONG_INLINE int pfirst(const Packet4i& a) { int x = _mm_cvtsi128_si32(a); return x; } +#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) +// The temporary variable fixes an internal compilation error in vs <= 2008 and a wrong-result bug in vs 2010 +template<> EIGEN_STRONG_INLINE float pfirst(const Packet4f& a) { float x = _mm_cvtss_f32(a); return x; } +template<> EIGEN_STRONG_INLINE double pfirst(const Packet2d& a) { double x = _mm_cvtsd_f64(a); return x; } +template<> EIGEN_STRONG_INLINE int pfirst(const Packet4i& a) { int x = _mm_cvtsi128_si32(a); return x; } +#else +template<> EIGEN_STRONG_INLINE float pfirst(const Packet4f& a) { return _mm_cvtss_f32(a); } +template<> EIGEN_STRONG_INLINE double pfirst(const Packet2d& a) { return _mm_cvtsd_f64(a); } +template<> EIGEN_STRONG_INLINE int pfirst(const Packet4i& a) { return _mm_cvtsi128_si32(a); } +#endif + +template<> EIGEN_STRONG_INLINE Packet4f preverse(const Packet4f& a) +{ return _mm_shuffle_ps(a,a,0x1B); } +template<> EIGEN_STRONG_INLINE Packet2d preverse(const Packet2d& a) +{ return _mm_shuffle_pd(a,a,0x1); } +template<> EIGEN_STRONG_INLINE Packet4i preverse(const Packet4i& a) +{ return _mm_shuffle_epi32(a,0x1B); } + + +template<> EIGEN_STRONG_INLINE Packet4f pabs(const Packet4f& a) +{ + const Packet4f mask = _mm_castsi128_ps(_mm_setr_epi32(0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF)); + return _mm_and_ps(a,mask); +} +template<> EIGEN_STRONG_INLINE Packet2d pabs(const Packet2d& a) +{ + const Packet2d mask = _mm_castsi128_pd(_mm_setr_epi32(0xFFFFFFFF,0x7FFFFFFF,0xFFFFFFFF,0x7FFFFFFF)); + return _mm_and_pd(a,mask); +} +template<> EIGEN_STRONG_INLINE Packet4i pabs(const Packet4i& a) +{ + #ifdef EIGEN_VECTORIZE_SSSE3 + return _mm_abs_epi32(a); + #else + Packet4i aux = _mm_srai_epi32(a,31); + return _mm_sub_epi32(_mm_xor_si128(a,aux),aux); + #endif +} + +EIGEN_STRONG_INLINE void punpackp(Packet4f* vecs) +{ + vecs[1] = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(vecs[0]), 0x55)); + vecs[2] = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(vecs[0]), 0xAA)); + vecs[3] = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(vecs[0]), 0xFF)); + vecs[0] = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(vecs[0]), 0x00)); +} + +#ifdef EIGEN_VECTORIZE_SSE3 +// TODO implement SSE2 versions as well as integer versions +template<> EIGEN_STRONG_INLINE Packet4f preduxp(const Packet4f* vecs) +{ + return _mm_hadd_ps(_mm_hadd_ps(vecs[0], vecs[1]),_mm_hadd_ps(vecs[2], vecs[3])); +} +template<> EIGEN_STRONG_INLINE Packet2d preduxp(const Packet2d* vecs) +{ + return _mm_hadd_pd(vecs[0], vecs[1]); +} +// SSSE3 version: +// EIGEN_STRONG_INLINE Packet4i preduxp(const Packet4i* vecs) +// { +// return _mm_hadd_epi32(_mm_hadd_epi32(vecs[0], vecs[1]),_mm_hadd_epi32(vecs[2], vecs[3])); +// } + +template<> EIGEN_STRONG_INLINE float predux(const Packet4f& a) +{ + Packet4f tmp0 = _mm_hadd_ps(a,a); + return pfirst(_mm_hadd_ps(tmp0, tmp0)); +} + +template<> EIGEN_STRONG_INLINE double predux(const Packet2d& a) { return pfirst(_mm_hadd_pd(a, a)); } + +// SSSE3 version: +// EIGEN_STRONG_INLINE float predux(const Packet4i& a) +// { +// Packet4i tmp0 = _mm_hadd_epi32(a,a); +// return pfirst(_mm_hadd_epi32(tmp0, tmp0)); +// } +#else +// SSE2 versions +template<> EIGEN_STRONG_INLINE float predux(const Packet4f& a) +{ + Packet4f tmp = _mm_add_ps(a, _mm_movehl_ps(a,a)); + return pfirst(_mm_add_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1))); +} +template<> EIGEN_STRONG_INLINE double predux(const Packet2d& a) +{ + return pfirst(_mm_add_sd(a, _mm_unpackhi_pd(a,a))); +} + +template<> EIGEN_STRONG_INLINE Packet4f preduxp(const Packet4f* vecs) +{ + Packet4f tmp0, tmp1, tmp2; + tmp0 = _mm_unpacklo_ps(vecs[0], vecs[1]); + tmp1 = _mm_unpackhi_ps(vecs[0], vecs[1]); + tmp2 = _mm_unpackhi_ps(vecs[2], vecs[3]); + tmp0 = _mm_add_ps(tmp0, tmp1); + tmp1 = _mm_unpacklo_ps(vecs[2], vecs[3]); + tmp1 = _mm_add_ps(tmp1, tmp2); + tmp2 = _mm_movehl_ps(tmp1, tmp0); + tmp0 = _mm_movelh_ps(tmp0, tmp1); + return _mm_add_ps(tmp0, tmp2); +} + +template<> EIGEN_STRONG_INLINE Packet2d preduxp(const Packet2d* vecs) +{ + return _mm_add_pd(_mm_unpacklo_pd(vecs[0], vecs[1]), _mm_unpackhi_pd(vecs[0], vecs[1])); +} +#endif // SSE3 + +template<> EIGEN_STRONG_INLINE int predux(const Packet4i& a) +{ + Packet4i tmp = _mm_add_epi32(a, _mm_unpackhi_epi64(a,a)); + return pfirst(tmp) + pfirst(_mm_shuffle_epi32(tmp, 1)); +} + +template<> EIGEN_STRONG_INLINE Packet4i preduxp(const Packet4i* vecs) +{ + Packet4i tmp0, tmp1, tmp2; + tmp0 = _mm_unpacklo_epi32(vecs[0], vecs[1]); + tmp1 = _mm_unpackhi_epi32(vecs[0], vecs[1]); + tmp2 = _mm_unpackhi_epi32(vecs[2], vecs[3]); + tmp0 = _mm_add_epi32(tmp0, tmp1); + tmp1 = _mm_unpacklo_epi32(vecs[2], vecs[3]); + tmp1 = _mm_add_epi32(tmp1, tmp2); + tmp2 = _mm_unpacklo_epi64(tmp0, tmp1); + tmp0 = _mm_unpackhi_epi64(tmp0, tmp1); + return _mm_add_epi32(tmp0, tmp2); +} + +// Other reduction functions: + +// mul +template<> EIGEN_STRONG_INLINE float predux_mul(const Packet4f& a) +{ + Packet4f tmp = _mm_mul_ps(a, _mm_movehl_ps(a,a)); + return pfirst(_mm_mul_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1))); +} +template<> EIGEN_STRONG_INLINE double predux_mul(const Packet2d& a) +{ + return pfirst(_mm_mul_sd(a, _mm_unpackhi_pd(a,a))); +} +template<> EIGEN_STRONG_INLINE int predux_mul(const Packet4i& a) +{ + // after some experiments, it is seems this is the fastest way to implement it + // for GCC (eg., reusing pmul is very slow !) + // TODO try to call _mm_mul_epu32 directly + EIGEN_ALIGN16 int aux[4]; + pstore(aux, a); + return (aux[0] * aux[1]) * (aux[2] * aux[3]);; +} + +// min +template<> EIGEN_STRONG_INLINE float predux_min(const Packet4f& a) +{ + Packet4f tmp = _mm_min_ps(a, _mm_movehl_ps(a,a)); + return pfirst(_mm_min_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1))); +} +template<> EIGEN_STRONG_INLINE double predux_min(const Packet2d& a) +{ + return pfirst(_mm_min_sd(a, _mm_unpackhi_pd(a,a))); +} +template<> EIGEN_STRONG_INLINE int predux_min(const Packet4i& a) +{ + // after some experiments, it is seems this is the fastest way to implement it + // for GCC (eg., it does not like using std::min after the pstore !!) + EIGEN_ALIGN16 int aux[4]; + pstore(aux, a); + int aux0 = aux[0] EIGEN_STRONG_INLINE float predux_max(const Packet4f& a) +{ + Packet4f tmp = _mm_max_ps(a, _mm_movehl_ps(a,a)); + return pfirst(_mm_max_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1))); +} +template<> EIGEN_STRONG_INLINE double predux_max(const Packet2d& a) +{ + return pfirst(_mm_max_sd(a, _mm_unpackhi_pd(a,a))); +} +template<> EIGEN_STRONG_INLINE int predux_max(const Packet4i& a) +{ + // after some experiments, it is seems this is the fastest way to implement it + // for GCC (eg., it does not like using std::min after the pstore !!) + EIGEN_ALIGN16 int aux[4]; + pstore(aux, a); + int aux0 = aux[0]>aux[1] ? aux[0] : aux[1]; + int aux2 = aux[2]>aux[3] ? aux[2] : aux[3]; + return aux0>aux2 ? aux0 : aux2; +} + +#if (defined __GNUC__) +// template <> EIGEN_STRONG_INLINE Packet4f pmadd(const Packet4f& a, const Packet4f& b, const Packet4f& c) +// { +// Packet4f res = b; +// asm("mulps %[a], %[b] \n\taddps %[c], %[b]" : [b] "+x" (res) : [a] "x" (a), [c] "x" (c)); +// return res; +// } +// EIGEN_STRONG_INLINE Packet4i _mm_alignr_epi8(const Packet4i& a, const Packet4i& b, const int i) +// { +// Packet4i res = a; +// asm("palignr %[i], %[a], %[b] " : [b] "+x" (res) : [a] "x" (a), [i] "i" (i)); +// return res; +// } +#endif + +#ifdef EIGEN_VECTORIZE_SSSE3 +// SSSE3 versions +template +struct palign_impl +{ + static EIGEN_STRONG_INLINE void run(Packet4f& first, const Packet4f& second) + { + if (Offset!=0) + first = _mm_castsi128_ps(_mm_alignr_epi8(_mm_castps_si128(second), _mm_castps_si128(first), Offset*4)); + } +}; + +template +struct palign_impl +{ + static EIGEN_STRONG_INLINE void run(Packet4i& first, const Packet4i& second) + { + if (Offset!=0) + first = _mm_alignr_epi8(second,first, Offset*4); + } +}; + +template +struct palign_impl +{ + static EIGEN_STRONG_INLINE void run(Packet2d& first, const Packet2d& second) + { + if (Offset==1) + first = _mm_castsi128_pd(_mm_alignr_epi8(_mm_castpd_si128(second), _mm_castpd_si128(first), 8)); + } +}; +#else +// SSE2 versions +template +struct palign_impl +{ + static EIGEN_STRONG_INLINE void run(Packet4f& first, const Packet4f& second) + { + if (Offset==1) + { + first = _mm_move_ss(first,second); + first = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(first),0x39)); + } + else if (Offset==2) + { + first = _mm_movehl_ps(first,first); + first = _mm_movelh_ps(first,second); + } + else if (Offset==3) + { + first = _mm_move_ss(first,second); + first = _mm_shuffle_ps(first,second,0x93); + } + } +}; + +template +struct palign_impl +{ + static EIGEN_STRONG_INLINE void run(Packet4i& first, const Packet4i& second) + { + if (Offset==1) + { + first = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(first),_mm_castsi128_ps(second))); + first = _mm_shuffle_epi32(first,0x39); + } + else if (Offset==2) + { + first = _mm_castps_si128(_mm_movehl_ps(_mm_castsi128_ps(first),_mm_castsi128_ps(first))); + first = _mm_castps_si128(_mm_movelh_ps(_mm_castsi128_ps(first),_mm_castsi128_ps(second))); + } + else if (Offset==3) + { + first = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(first),_mm_castsi128_ps(second))); + first = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(first),_mm_castsi128_ps(second),0x93)); + } + } +}; + +template +struct palign_impl +{ + static EIGEN_STRONG_INLINE void run(Packet2d& first, const Packet2d& second) + { + if (Offset==1) + { + first = _mm_castps_pd(_mm_movehl_ps(_mm_castpd_ps(first),_mm_castpd_ps(first))); + first = _mm_castps_pd(_mm_movelh_ps(_mm_castpd_ps(first),_mm_castpd_ps(second))); + } + } +}; +#endif + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_PACKET_MATH_SSE_H diff --git a/Util/Patches/Eigen3.1.0/SelfadjointMatrixVector.h b/Util/Patches/Eigen3.1.0/SelfadjointMatrixVector.h new file mode 100644 index 00000000000..2d07ddc340c --- /dev/null +++ b/Util/Patches/Eigen3.1.0/SelfadjointMatrixVector.h @@ -0,0 +1,289 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2009 Gael Guennebaud +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see . + +#ifndef EIGEN_SELFADJOINT_MATRIX_VECTOR_H +#define EIGEN_SELFADJOINT_MATRIX_VECTOR_H + +namespace Eigen { + +namespace internal { + +/* Optimized selfadjoint matrix * vector product: + * This algorithm processes 2 columns at onces that allows to both reduce + * the number of load/stores of the result by a factor 2 and to reduce + * the instruction dependency. + */ + +template +struct selfadjoint_matrix_vector_product; + +template +struct selfadjoint_matrix_vector_product + +{ +static EIGEN_DONT_INLINE void run( + Index size, + const Scalar* lhs, Index lhsStride, + const Scalar* _rhs, Index rhsIncr, + Scalar* res, + Scalar alpha) +{ + typedef typename packet_traits::type Packet; + typedef typename NumTraits::Real RealScalar; + const Index PacketSize = sizeof(Packet)/sizeof(Scalar); + + enum { + IsRowMajor = StorageOrder==RowMajor ? 1 : 0, + IsLower = UpLo == Lower ? 1 : 0, + FirstTriangular = IsRowMajor == IsLower + }; + + conj_helper::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, IsRowMajor), ConjugateRhs> cj0; + conj_helper::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, !IsRowMajor), ConjugateRhs> cj1; + conj_helper::IsComplex, ConjugateRhs> cjd; + + conj_helper::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, IsRowMajor), ConjugateRhs> pcj0; + conj_helper::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, !IsRowMajor), ConjugateRhs> pcj1; + + Scalar cjAlpha = ConjugateRhs ? conj(alpha) : alpha; + + // FIXME this copy is now handled outside product_selfadjoint_vector, so it could probably be removed. + // if the rhs is not sequentially stored in memory we copy it to a temporary buffer, + // this is because we need to extract packets + ei_declare_aligned_stack_constructed_variable(Scalar,rhs,size,rhsIncr==1 ? const_cast(_rhs) : 0); + if (rhsIncr!=1) + { + const Scalar* it = _rhs; + for (Index i=0; i(t0); + Scalar t1 = cjAlpha * rhs[j+1]; + Packet ptmp1 = pset1(t1); + + Scalar t2(0); + Packet ptmp2 = pset1(t2); + Scalar t3(0); + Packet ptmp3 = pset1(t3); + + size_t starti = FirstTriangular ? 0 : j+2; + size_t endi = FirstTriangular ? j : size; + size_t alignedStart = (starti) + internal::first_aligned(&res[starti], endi-starti); + size_t alignedEnd = alignedStart + ((endi-alignedStart)/(PacketSize))*(PacketSize); + + // TODO make sure this product is a real * complex and that the rhs is properly conjugated if needed + res[j] += cjd.pmul(internal::real(A0[j]), t0); + res[j+1] += cjd.pmul(internal::real(A1[j+1]), t1); + if(FirstTriangular) + { + res[j] += cj0.pmul(A1[j], t1); + t3 += cj1.pmul(A1[j], rhs[j]); + } + else + { + res[j+1] += cj0.pmul(A0[j+1],t0); + t2 += cj1.pmul(A0[j+1], rhs[j+1]); + } + + for (size_t i=starti; i huge speed up) + // gcc 4.2 does this optimization automatically. + const Scalar* EIGEN_RESTRICT a0It = A0 + alignedStart; + const Scalar* EIGEN_RESTRICT a1It = A1 + alignedStart; + const Scalar* EIGEN_RESTRICT rhsIt = rhs + alignedStart; + Scalar* EIGEN_RESTRICT resIt = res + alignedStart; + for (size_t i=alignedStart; i(a0It); a0It += PacketSize; + Packet A1i = ploadu(a1It); a1It += PacketSize; + Packet Bi = ploadu(rhsIt); rhsIt += PacketSize; // FIXME should be aligned in most cases + Packet Xi = pload (resIt); + + Xi = pcj0.pmadd(A0i,ptmp0, pcj0.pmadd(A1i,ptmp1,Xi)); + ptmp2 = pcj1.pmadd(A0i, Bi, ptmp2); + ptmp3 = pcj1.pmadd(A1i, Bi, ptmp3); + pstore(resIt,Xi); resIt += PacketSize; + } + for (size_t i=alignedEnd; i +struct traits > + : traits, Lhs, Rhs> > +{}; +} + +template +struct SelfadjointProductMatrix + : public ProductBase, Lhs, Rhs > +{ + EIGEN_PRODUCT_PUBLIC_INTERFACE(SelfadjointProductMatrix) + + enum { + LhsUpLo = LhsMode&(Upper|Lower) + }; + + SelfadjointProductMatrix(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {} + + template void scaleAndAddTo(Dest& dest, Scalar alpha) const + { + typedef typename Dest::Scalar ResScalar; + typedef typename Base::RhsScalar RhsScalar; + typedef Map, Aligned> MappedDest; + + eigen_assert(dest.rows()==m_lhs.rows() && dest.cols()==m_rhs.cols()); + + typename internal::add_const_on_value_type::type lhs = LhsBlasTraits::extract(m_lhs); + typename internal::add_const_on_value_type::type rhs = RhsBlasTraits::extract(m_rhs); + + Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(m_lhs) + * RhsBlasTraits::extractScalarFactor(m_rhs); + + enum { + EvalToDest = (Dest::InnerStrideAtCompileTime==1), + UseRhs = (_ActualRhsType::InnerStrideAtCompileTime==1) + }; + + internal::gemv_static_vector_if static_dest; + internal::gemv_static_vector_if static_rhs; + + ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(), + EvalToDest ? dest.data() : static_dest.data()); + + ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,rhs.size(), + UseRhs ? const_cast(rhs.data()) : static_rhs.data()); + + if(!EvalToDest) + { + #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN + int size = dest.size(); + EIGEN_DENSE_STORAGE_CTOR_PLUGIN + #endif + MappedDest(actualDestPtr, dest.size()) = dest; + } + + if(!UseRhs) + { + #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN + int size = rhs.size(); + EIGEN_DENSE_STORAGE_CTOR_PLUGIN + #endif + Map(actualRhsPtr, rhs.size()) = rhs; + } + + + internal::selfadjoint_matrix_vector_product::Flags&RowMajorBit) ? RowMajor : ColMajor, int(LhsUpLo), bool(LhsBlasTraits::NeedToConjugate), bool(RhsBlasTraits::NeedToConjugate)>::run + ( + lhs.rows(), // size + &lhs.coeffRef(0,0), lhs.outerStride(), // lhs info + actualRhsPtr, 1, // rhs info + actualDestPtr, // result info + actualAlpha // scale factor + ); + + if(!EvalToDest) + dest = MappedDest(actualDestPtr, dest.size()); + } +}; + +namespace internal { +template +struct traits > + : traits, Lhs, Rhs> > +{}; +} + +template +struct SelfadjointProductMatrix + : public ProductBase, Lhs, Rhs > +{ + EIGEN_PRODUCT_PUBLIC_INTERFACE(SelfadjointProductMatrix) + + enum { + RhsUpLo = RhsMode&(Upper|Lower) + }; + + SelfadjointProductMatrix(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {} + + template void scaleAndAddTo(Dest& dest, Scalar alpha) const + { + // let's simply transpose the product + Transpose destT(dest); + SelfadjointProductMatrix, int(RhsUpLo)==Upper ? Lower : Upper, false, + Transpose, 0, true>(m_rhs.transpose(), m_lhs.transpose()).scaleAndAddTo(destT, alpha); + } +}; + +} // end namespace Eigen + +#endif // EIGEN_SELFADJOINT_MATRIX_VECTOR_H diff --git a/mkdocs.yml b/mkdocs.yml index c2a5aae009d..801cfc4da80 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -44,7 +44,6 @@ nav: - 'NVIDIA SimReady': 'ecosys_simready.md' - 'ASAM OpenDRIVE': 'adv_opendrive.md' - 'PTV Vissim': 'adv_ptv.md' - - 'RSS': 'adv_rss.md' - 'ROS': https://carla.readthedocs.io/projects/ros-bridge/en/latest/ - 'Scenic': 'tuto_G_scenic.md' - 'SUMO': 'adv_sumo.md'