Merge branch 'dev' into patch-2
This commit is contained in:
commit
9f6d68df04
|
@ -1,4 +1,5 @@
|
|||
## Latest Changes
|
||||
* 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
|
||||
|
@ -14,6 +15,12 @@
|
|||
* 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.
|
||||
* Added type-hint support for the PythonAPI
|
||||
|
||||
|
||||
## CARLA 0.9.15
|
||||
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
# C++ client example
|
||||
|
||||
To build the C++ client example you will need `make` installed. Before building a C++ client, you will need to build CARLA, follow the relevant [build instructions](build_carla.md) for your platform.
|
||||
|
||||
Navigate to the `Examples/CppClient` folder in the CARLA repository and open a terminal. You will find a Makefile in this directory. To build and run it in Linux execute `make run` at the command prompt. In Windows, create a file named `CMakeLists.txt` in the same directory and add the contents in [this file](cpp_client_cmake_windows.md), then run `cmake`.
|
||||
|
||||
This C++ example will connect to the server, spawn a vehicle and apply a command to the vehicle before destroying it and terminating.
|
||||
|
||||
### Include the relevant header files
|
||||
|
||||
For this example, we will be using several different CARLA classes, so we need to include the relevant header files from the CARLA library and include any standard libraries we will use:
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
|
||||
#include <carla/client/ActorBlueprint.h>
|
||||
#include <carla/client/BlueprintLibrary.h>
|
||||
#include <carla/client/Client.h>
|
||||
#include <carla/client/Map.h>
|
||||
#include <carla/client/Sensor.h>
|
||||
#include <carla/client/TimeoutException.h>
|
||||
#include <carla/client/World.h>
|
||||
#include <carla/geom/Transform.h>
|
||||
#include <carla/image/ImageIO.h>
|
||||
#include <carla/image/ImageView.h>
|
||||
#include <carla/sensor/data/Image.h>
|
||||
|
||||
```
|
||||
|
||||
### Connecting the C++ client to the server
|
||||
|
||||
Include `carla/client/Client.h` and then connect the client:
|
||||
|
||||
```cpp
|
||||
...
|
||||
#include <carla/client/Client.h>
|
||||
...
|
||||
int main(int argc, const char *argv[]) {
|
||||
|
||||
std::string host;
|
||||
uint16_t port;
|
||||
std::tie(host, port) = ParseArguments(argc, argv);
|
||||
...
|
||||
// Connect the client to the server
|
||||
auto client = cc::Client(host, port);
|
||||
client.SetTimeout(40s);
|
||||
```
|
||||
|
||||
### Load a map
|
||||
|
||||
Now let's load a randomly chosen map:
|
||||
|
||||
```cpp
|
||||
// Initialize random number generator
|
||||
std::mt19937_64 rng((std::random_device())());
|
||||
...
|
||||
auto town_name = RandomChoice(client.GetAvailableMaps(), rng);
|
||||
std::cout << "Loading world: " << town_name << std::endl;
|
||||
auto world = client.LoadWorld(town_name);
|
||||
```
|
||||
|
||||
### Spawn a randomly chosen vehicle
|
||||
|
||||
Next we will fetch the blueprint library, filter for vehicles and choose a random vehicle blueprint:
|
||||
|
||||
```cpp
|
||||
auto blueprint_library = world.GetBlueprintLibrary();
|
||||
auto vehicles = blueprint_library->Filter("vehicle");
|
||||
auto blueprint = RandomChoice(*vehicles, rng);
|
||||
```
|
||||
|
||||
Now we need to find a location to spawn the vehicle from a spawn point in the map. We will get a pointer reference to the map object and then choose a random spawn point (ensure you have initialized the random number generator):
|
||||
|
||||
```cpp
|
||||
auto map = world.GetMap();
|
||||
auto transform = RandomChoice(map->GetRecommendedSpawnPoints(), rng);
|
||||
```
|
||||
|
||||
Now we have the blueprint and spawn location, we can now spawn the vehicle using the `world.SpawnActor(...)` method:
|
||||
|
||||
```cpp
|
||||
auto actor = world.SpawnActor(blueprint, transform);
|
||||
std::cout << "Spawned " << actor->GetDisplayId() << '\n';
|
||||
// Retrieve a pointer to the vehicle object
|
||||
auto vehicle = boost::static_pointer_cast<cc::Vehicle>(actor);
|
||||
```
|
||||
|
||||
### Apply a control
|
||||
|
||||
Let's now apply some control to the vehicle to move it using the `ApplyControl(...)` method:
|
||||
|
||||
```cpp
|
||||
cc::Vehicle::Control control;
|
||||
control.throttle = 1.0f;
|
||||
vehicle->ApplyControl(control);
|
||||
```
|
||||
|
||||
Now we will relocate the spectator so that we can see our newly spawned vehicle in the map:
|
||||
|
||||
```cpp
|
||||
auto spectator = world.GetSpectator();
|
||||
// Adjust the transform to look
|
||||
transform.location += 32.0f * transform.GetForwardVector();
|
||||
transform.location.z += 2.0f;
|
||||
transform.rotation.yaw += 180.0f;
|
||||
transform.rotation.pitch = -15.0f;
|
||||
// Now set the spectator transform
|
||||
spectator->SetTransform(transform);
|
||||
```
|
||||
|
||||
We'll also sleep the process for 10 seconds to observe the simulation shortly, before the client closes:
|
||||
|
||||
|
||||
```cpp
|
||||
std::this_thread::sleep_for(10s);
|
||||
|
||||
```
|
||||
|
||||
If you wish to keep the client open while other commands are executed, create a game loop. Now you have loaded a map and spawned a vehicle. To further explore the C++ API [build the Doxygen documentation](ref_cpp.md#c-documentation) and open it in a browser.
|
||||
|
||||
To build the C++ client in another location outside of the CARLA repository, edit the first 5 lines of the Makefile to reference the correct locations for the `/build` directory and the CARLA build location:
|
||||
|
||||
```make
|
||||
CARLADIR=$(CURDIR)/../..
|
||||
BUILDDIR=$(CURDIR)/build
|
||||
BINDIR=$(CURDIR)/bin
|
||||
INSTALLDIR=$(CURDIR)/libcarla-install
|
||||
TOOLCHAIN=$(CURDIR)/ToolChain.cmake
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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.
|
||||
|
||||
<iframe width="100%" height="400px" src="https://www.youtube.com/embed/gTutXdS2UkQ?si=hssM3YRCAjSIzdXM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
||||
|
||||
## 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:
|
||||
|
|
|
@ -9,7 +9,10 @@ Build instructions are available for Linux and Windows. You can also build CARLA
|
|||
* [__Docker__](build_docker.md)
|
||||
* [__Docker with Unreal__](build_docker_unreal.md)
|
||||
* [__Updating CARLA__](build_update.md)
|
||||
* [__Build system__](build_system.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)
|
||||
|
||||
|
|
|
@ -52,10 +52,10 @@ The following steps will each take a long time.
|
|||
|
||||
__1. Build the CARLA prerequisites image.__
|
||||
|
||||
The following command will build an image called `carla-prerequisites` using `Prerequisites.Dockerfile`. In this build we install the compiler and required tools, download the Unreal Engine 4.26 fork and compile it. You will need to provide your login details as build arguments for the download of Unreal Engine to be successful:
|
||||
The following command will build an image called `carla-prerequisites` using `Prerequisites.Dockerfile`. In this build we install the compiler and required tools, download the Unreal Engine 4.26 fork and compile it. You will need to provide your login details (use a Github Personal Access Token instead of a password) as build arguments for the download of Unreal Engine to be successful:
|
||||
|
||||
```sh
|
||||
docker build --build-arg EPIC_USER=<GitHubUserName> --build-arg EPIC_PASS=<GitHubPassword> -t carla-prerequisites -f Prerequisites.Dockerfile .
|
||||
docker build --build-arg EPIC_USER=<GitHubUserName> --build-arg EPIC_PASS=<GitHubAccessToken> -t carla-prerequisites -f Prerequisites.Dockerfile .
|
||||
```
|
||||
|
||||
__2. Build the final CARLA image.__
|
||||
|
|
|
@ -129,7 +129,7 @@ pip3 install --user -Iv setuptools==47.3.1 &&
|
|||
pip install --user distro &&
|
||||
pip3 install --user distro &&
|
||||
pip install --user wheel &&
|
||||
pip3 install --user wheel auditwheel
|
||||
pip3 install --user wheel auditwheel==4.0.0
|
||||
```
|
||||
|
||||
---
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
!!! 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
|
|
@ -0,0 +1,79 @@
|
|||
!!! 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
|
|
@ -96,7 +96,8 @@ Sensor data differs a lot between sensor types. Take a look at the [sensors refe
|
|||
|
||||
|
||||
!!! Important
|
||||
`is_listening` is a __sensor attribute__ that enables/disables data listening at will.
|
||||
`is_listening()` is a __sensor method__ to check whether the sensor has a callback registered by `listen`.
|
||||
`stop()` is a __sensor method__ to stop the sensor from listening.
|
||||
`sensor_tick` is a __blueprint attribute__ that sets the simulation time between data received.
|
||||
|
||||
---
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
```make
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
project(example)
|
||||
|
||||
link_directories(
|
||||
${RPCLIB_LIB_PATH})
|
||||
|
||||
file(GLOB example_sources "*.cpp" "*.h")
|
||||
|
||||
file(GLOB example_client_sources "")
|
||||
|
||||
set(carla_config client)
|
||||
list(APPEND build_targets example_${carla_config}_debug)
|
||||
|
||||
# Create targets for debug and release in the same build type.
|
||||
foreach(target ${build_targets})
|
||||
|
||||
add_executable(${target} ${example_sources})
|
||||
|
||||
target_compile_definitions(${target} PUBLIC
|
||||
-DLIBCARLA_ENABLE_PROFILER)
|
||||
|
||||
target_include_directories(${target} SYSTEM PRIVATE
|
||||
"../../LibCarla/source"
|
||||
"../../Build/boost-1.80.0-install/include"
|
||||
"../../Build/rpclib-install/include/"
|
||||
"../../Build/recast-22dfcb-install/include/"
|
||||
"../../Build/zlib-install/include/"
|
||||
"../../Build/libpng-1.2.37-install/include/"
|
||||
"../../LibCarla/source/third-party/")
|
||||
|
||||
target_link_directories(${target} SYSTEM PRIVATE
|
||||
"../../Build/boost-1.80.0-install/lib"
|
||||
"../../Build/rpclib-install/lib/"
|
||||
"../../Build/recast-22dfcb-install/lib/"
|
||||
"../../Build/zlib-install/lib/"
|
||||
"../../Build/libcarla-visualstudio/LibCarla/cmake/client/Release/"
|
||||
"../../Build/libpng-1.2.37-install/lib/")
|
||||
|
||||
target_include_directories(${target} PRIVATE
|
||||
"${libcarla_source_path}/test")
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(${target} "rpc.lib")
|
||||
target_link_libraries(${target} "carla_client.lib")
|
||||
target_link_libraries(${target} "DebugUtils.lib")
|
||||
target_link_libraries(${target} "Detour.lib")
|
||||
target_link_libraries(${target} "DetourCrowd.lib")
|
||||
target_link_libraries(${target} "DetourTileCache.lib")
|
||||
target_link_libraries(${target} "Recast.lib")
|
||||
target_link_libraries(${target} "Shlwapi.lib")
|
||||
else()
|
||||
target_link_libraries(${target} "-lrpc")
|
||||
endif()
|
||||
|
||||
install(TARGETS ${target} DESTINATION test OPTIONAL)
|
||||
endforeach(target)
|
||||
|
||||
if (LIBCARLA_BUILD_DEBUG)
|
||||
# Specific options for debug.
|
||||
set_target_properties(example_${carla_config}_debug PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
target_link_libraries(example_${carla_config}_debug "carla_${carla_config}${carla_target_postfix}_debug")
|
||||
target_compile_definitions(example_${carla_config}_debug PUBLIC -DBOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Client")
|
||||
target_link_libraries(example_${carla_config}_debug "${BOOST_LIB_PATH}/libboost_filesystem.a")
|
||||
endif()
|
||||
endif()
|
||||
```
|
|
@ -419,6 +419,43 @@ Parses the location and extent of the bounding box to string.
|
|||
|
||||
---
|
||||
|
||||
## carla.CAMData<a name="carla.CAMData"></a>
|
||||
<small style="display:block;margin-top:-20px;">Inherited from _[carla.SensorData](#carla.SensorData)_</small></br>
|
||||
This is the data type for cooperative awareness message reception, contained in a [CAMEvent](#carlacamevent).
|
||||
|
||||
### Instance Variables
|
||||
- <a name="carla.CAMData.power"></a>**<font color="#f8805a">power</font>** (_float - dBm_)
|
||||
Received power.
|
||||
|
||||
### Methods
|
||||
- <a name="carla.CAMData.get"></a>**<font color="#7fb800">get</font>**(<font color="#00a6ed">**self**</font>)
|
||||
Get the CAM data. Returns a nested dictionary containing the message following the ETSI standard: - `Header`: dict - `Message`: dict.
|
||||
- **Return:** _dict_
|
||||
|
||||
##### Dunder methods
|
||||
- <a name="carla.CAMData.__str__"></a>**<font color="#7fb800">\__str__</font>**(<font color="#00a6ed">**self**</font>)
|
||||
|
||||
---
|
||||
|
||||
## carla.CAMEvent<a name="carla.CAMEvent"></a>
|
||||
<small style="display:block;margin-top:-20px;">Inherited from _[carla.SensorData](#carla.SensorData)_</small></br>
|
||||
Class that defines the data provided by a **sensor.other.v2x**. This is a collection type to combine returning several [CAMData](#carlacamdata).
|
||||
|
||||
### Methods
|
||||
|
||||
##### Getters
|
||||
- <a name="carla.CAMEvent.get_message_count"></a>**<font color="#7fb800">get_message_count</font>**(<font color="#00a6ed">**self**</font>)
|
||||
Get the number of received CAM's.
|
||||
- **Return:** _int_
|
||||
|
||||
##### Dunder methods
|
||||
- <a name="carla.CAMEvent.__get_item__"></a>**<font color="#7fb800">\__get_item__</font>**(<font color="#00a6ed">**self**</font>, <font color="#00a6ed">**pos**=int</font>)
|
||||
- <a name="carla.CAMEvent.__iter__"></a>**<font color="#7fb800">\__iter__</font>**(<font color="#00a6ed">**self**</font>)
|
||||
Iterate over the [CAMData](#carlacamdata) retrieved as data.
|
||||
- <a name="carla.CAMEvent.__len__"></a>**<font color="#7fb800">\__len__</font>**(<font color="#00a6ed">**self**</font>)
|
||||
|
||||
---
|
||||
|
||||
## carla.CityObjectLabel<a name="carla.CityObjectLabel"></a>
|
||||
Enum declaration that contains the different tags available to filter the bounding boxes returned by [carla.World.get_level_bbs](#carla.World.get_level_bbs)(). These values correspond to the [semantic tag](ref_sensors.md#semantic-segmentation-camera) that the elements in the scene have.
|
||||
|
||||
|
@ -576,8 +613,8 @@ Returns the client libcarla version by consulting it in the "Version.h" file. Bo
|
|||
- <a name="carla.Client.get_required_files"></a>**<font color="#7fb800">get_required_files</font>**(<font color="#00a6ed">**self**</font>, <font color="#00a6ed">**folder**</font>, <font color="#00a6ed">**download**=True</font>)
|
||||
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.
|
||||
- **Parameters:**
|
||||
- `folder` (_str_) - Folder where files required by the client will be downloaded to.
|
||||
- `download` (_bool_) - If True, downloads files that are not already in cache.
|
||||
- `folder` (_str_) - Specifies a folder to look through on the server maps. Leaving this blank will search recursively through all map folders in the server, which is recommended if you're unfamiliar with the server map folder structure.
|
||||
- `download` (_bool_) - If True, downloads files that are not already in cache. The cache can be found at "HOME\carlaCache" or "USERPROFILE\carlaCache", depending on OS.
|
||||
- <a name="carla.Client.get_server_version"></a>**<font color="#7fb800">get_server_version</font>**(<font color="#00a6ed">**self**</font>)
|
||||
Returns the server libcarla version by consulting it in the "Version.h" file. Both client and server should use the same libcarla version.
|
||||
- **Return:** _str_
|
||||
|
@ -669,6 +706,43 @@ No changes applied to the image. Used by the [RGB camera](ref_sensors.md#rgb-cam
|
|||
|
||||
---
|
||||
|
||||
## carla.CustomV2XData<a name="carla.CustomV2XData"></a>
|
||||
<small style="display:block;margin-top:-20px;">Inherited from _[carla.SensorData](#carla.SensorData)_</small></br>
|
||||
This is the data type defining a custom V2X message. Received as part of a [CustomV2XEvent](#carlacustomv2xevent).
|
||||
|
||||
### Instance Variables
|
||||
- <a name="carla.CustomV2XData.power"></a>**<font color="#f8805a">power</font>** (_float - dBm_)
|
||||
Received power.
|
||||
|
||||
### Methods
|
||||
- <a name="carla.CustomV2XData.get"></a>**<font color="#7fb800">get</font>**(<font color="#00a6ed">**self**</font>)
|
||||
Get the custom message. Returns a nested dictionary containing the message. It has two primary keys: - `Header` : dict - `Message`: str.
|
||||
- **Return:** _dict_
|
||||
|
||||
##### Dunder methods
|
||||
- <a name="carla.CustomV2XData.__str__"></a>**<font color="#7fb800">\__str__</font>**(<font color="#00a6ed">**self**</font>)
|
||||
|
||||
---
|
||||
|
||||
## carla.CustomV2XEvent<a name="carla.CustomV2XEvent"></a>
|
||||
<small style="display:block;margin-top:-20px;">Inherited from _[carla.SensorData](#carla.SensorData)_</small></br>
|
||||
Class that defines the data provided by a **sensor.other.v2x_custom**. This is a collection type to combine returning several [CustomV2XData](#carlacustomv2xdata).
|
||||
|
||||
### Methods
|
||||
|
||||
##### Getters
|
||||
- <a name="carla.CustomV2XEvent.get_message_count"></a>**<font color="#7fb800">get_message_count</font>**(<font color="#00a6ed">**self**</font>)
|
||||
Get the number of received CAM's.
|
||||
- **Return:** _int_
|
||||
|
||||
##### Dunder methods
|
||||
- <a name="carla.CustomV2XEvent.__get_item__"></a>**<font color="#7fb800">\__get_item__</font>**(<font color="#00a6ed">**self**</font>, <font color="#00a6ed">**pos**=int</font>)
|
||||
- <a name="carla.CustomV2XEvent.__iter__"></a>**<font color="#7fb800">\__iter__</font>**(<font color="#00a6ed">**self**</font>)
|
||||
Iterate over the [CustomV2XData](#carlacustomv2xdata) retrieved as data.
|
||||
- <a name="carla.CustomV2XEvent.__len__"></a>**<font color="#7fb800">\__len__</font>**(<font color="#00a6ed">**self**</font>)
|
||||
|
||||
---
|
||||
|
||||
## carla.DVSEvent<a name="carla.DVSEvent"></a>
|
||||
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](ref_sensors.md).
|
||||
|
||||
|
@ -857,7 +931,7 @@ Initializes a color, black by default.
|
|||
---
|
||||
|
||||
## carla.GBufferTextureID<a name="carla.GBufferTextureID"></a>
|
||||
Defines the identifiers of each GBuffer texture (See the method `[carla.Sensor.listen_to_gbuffer](#carla.Sensor.listen_to_gbuffer)`).
|
||||
Defines the of each GBuffer texture (See the method `[carla.Sensor.listen_to_gbuffer](#carla.Sensor.listen_to_gbuffer)`).
|
||||
|
||||
### Instance Variables
|
||||
- <a name="carla.GBufferTextureID.SceneColor"></a>**<font color="#f8805a">SceneColor</font>**
|
||||
|
@ -2230,25 +2304,26 @@ Iterate over the [carla.SemanticLidarDetection](#carla.SemanticLidarDetection) r
|
|||
<small style="display:block;margin-top:-20px;">Inherited from _[carla.Actor](#carla.Actor)_</small></br>
|
||||
Sensors compound a specific family of actors quite diverse and unique. They are normally spawned as attachment/sons of a vehicle (take a look at [carla.World](#carla.World) to learn about actor spawning). Sensors are thoroughly designed to retrieve different types of data that they are listening to. The data they receive is shaped as different subclasses inherited from [carla.SensorData](#carla.SensorData) (depending on the sensor).
|
||||
|
||||
Most sensors can be divided in two groups: those receiving data on every tick (cameras, point clouds and some specific sensors) and those who only receive under certain circumstances (trigger detectors). CARLA provides a specific set of sensors and their blueprint can be found in [carla.BlueprintLibrary](#carla.BlueprintLibrary). All the information on their preferences and settlement can be found [here](ref_sensors.md), but the list of those available in CARLA so far goes as follow.
|
||||
<br><b>Receive data on every tick.</b>
|
||||
- [Depth camera](ref_sensors.md#depth-camera).
|
||||
- [Gnss sensor](ref_sensors.md#gnss-sensor).
|
||||
- [IMU sensor](ref_sensors.md#imu-sensor).
|
||||
- [Lidar raycast](ref_sensors.md#lidar-raycast-sensor).
|
||||
- [SemanticLidar raycast](ref_sensors.md#semanticlidar-raycast-sensor).
|
||||
- [Radar](ref_sensors.md#radar-sensor).
|
||||
- [RGB camera](ref_sensors.md#rgb-camera).
|
||||
- [RSS sensor](ref_sensors.md#rss-sensor).
|
||||
- [Semantic Segmentation camera](ref_sensors.md#semantic-segmentation-camera).
|
||||
<br><b>Only receive data when triggered.</b>
|
||||
- [Collision detector](ref_sensors.md#collision-detector).
|
||||
- [Lane invasion detector](ref_sensors.md#lane-invasion-detector).
|
||||
- [Obstacle detector](ref_sensors.md#obstacle-detector).
|
||||
Most sensors can be divided in two groups: those receiving data on every tick (cameras, point clouds and some specific sensors) and those who only receive under certain circumstances (trigger detectors). CARLA provides a specific set of sensors and their blueprint can be found in [carla.BlueprintLibrary](#carla.BlueprintLibrary). All the information on their preferences and settlement can be found [here](ref_sensors.md), but the list of those available in CARLA so far goes as follows:<br>
|
||||
<br><b>Receive data on every tick</b><br>
|
||||
- [Depth camera](ref_sensors.md#depth-camera)<br>
|
||||
- [Gnss sensor](ref_sensors.md#gnss-sensor)<br>
|
||||
- [IMU sensor](ref_sensors.md#imu-sensor)<br>
|
||||
- [Lidar raycast](ref_sensors.md#lidar-raycast-sensor)<br>
|
||||
- [SemanticLidar raycast](ref_sensors.md#semanticlidar-raycast-sensor)<br>
|
||||
- [Radar](ref_sensors.md#radar-sensor)<br>
|
||||
- [RGB camera](ref_sensors.md#rgb-camera)<br>
|
||||
- [RSS sensor](ref_sensors.md#rss-sensor)<br>
|
||||
- [Semantic Segmentation camera](ref_sensors.md#semantic-segmentation-camera)<br>
|
||||
<br><b>Only receive data when triggered.</b><br>
|
||||
- [Collision detector](ref_sensors.md#collision-detector)<br>
|
||||
- [Lane invasion detector](ref_sensors.md#lane-invasion-detector)<br>
|
||||
- [Obstacle detector](ref_sensors.md#obstacle-detector)<br>
|
||||
- [V2X sensor](ref_sensors.md#v2x-sensor).
|
||||
|
||||
### Instance Variables
|
||||
- <a name="carla.Sensor.is_listening"></a>**<font color="#f8805a">is_listening</font>** (_boolean_)
|
||||
When <b>True</b> the sensor will be waiting for data.
|
||||
When **True** the sensor will be waiting for data.
|
||||
|
||||
### Methods
|
||||
- <a name="carla.Sensor.disable_for_ros"></a>**<font color="#7fb800">disable_for_ros</font>**(<font color="#00a6ed">**self**</font>)
|
||||
|
@ -2257,12 +2332,15 @@ Commands the sensor to not be processed for publishing in ROS2 if there is no an
|
|||
Commands the sensor to be processed to be able to publish in ROS2 without any listen to it.
|
||||
- <a name="carla.Sensor.is_enabled_for_ros"></a>**<font color="#7fb800">is_enabled_for_ros</font>**(<font color="#00a6ed">**self**</font>)
|
||||
Returns if the sensor is enabled or not to publish in ROS2 if there is no any listen to it.
|
||||
- **Return:** _bool_
|
||||
- <a name="carla.Sensor.is_listening"></a>**<font color="#7fb800">is_listening</font>**(<font color="#00a6ed">**self**</font>)
|
||||
Returns whether the sensor is in a listening state.
|
||||
- **Return:** _bool_
|
||||
- <a name="carla.Sensor.is_listening_gbuffer"></a>**<font color="#7fb800">is_listening_gbuffer</font>**(<font color="#00a6ed">**self**</font>, <font color="#00a6ed">**gbuffer_id**</font>)
|
||||
Returns whether the sensor is in a listening state for a specific GBuffer texture.
|
||||
- **Parameters:**
|
||||
- `gbuffer_id` (_[carla.GBufferTextureID](#carla.GBufferTextureID)_) - The ID of the target Unreal Engine GBuffer texture.
|
||||
- **Return:** _bool_
|
||||
- <a name="carla.Sensor.listen"></a>**<font color="#7fb800">listen</font>**(<font color="#00a6ed">**self**</font>, <font color="#00a6ed">**callback**</font>)<button class="SnipetButton" id="carla.Sensor.listen-snipet_button">snippet →</button>
|
||||
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](#carla.SensorData) to work with.
|
||||
- **Parameters:**
|
||||
|
@ -2272,6 +2350,10 @@ The function the sensor will be calling to every time the desired GBuffer textur
|
|||
- **Parameters:**
|
||||
- `gbuffer_id` (_[carla.GBufferTextureID](#carla.GBufferTextureID)_) - The ID of the target Unreal Engine GBuffer texture.
|
||||
- `callback` (_function_) - The called function with one argument containing the received GBuffer texture.
|
||||
- <a name="carla.Sensor.send"></a>**<font color="#7fb800">send</font>**(<font color="#00a6ed">**self**</font>, <font color="#00a6ed">**message**</font>)
|
||||
Instructs the sensor to send the string given by `message` to all other CustomV2XSensors on the next tick.
|
||||
- **Parameters:**
|
||||
- `message` (_string_) - The data to send. Note: maximum string length is 100 chars.
|
||||
- <a name="carla.Sensor.stop"></a>**<font color="#7fb800">stop</font>**(<font color="#00a6ed">**self**</font>)
|
||||
Commands the sensor to stop listening for data.
|
||||
- <a name="carla.Sensor.stop_gbuffer"></a>**<font color="#7fb800">stop_gbuffer</font>**(<font color="#00a6ed">**self**</font>, <font color="#00a6ed">**gbuffer_id**</font>)
|
||||
|
@ -2295,7 +2377,9 @@ Base class for all the objects containing data generated by a [carla.Sensor](#ca
|
|||
- Obstacle detector: [carla.ObstacleDetectionEvent](#carla.ObstacleDetectionEvent).<br>
|
||||
- Radar sensor: [carla.RadarMeasurement](#carla.RadarMeasurement).<br>
|
||||
- RSS sensor: [carla.RssResponse](#carla.RssResponse).<br>
|
||||
- Semantic LIDAR sensor: [carla.SemanticLidarMeasurement](#carla.SemanticLidarMeasurement).
|
||||
- Semantic LIDAR sensor: [carla.SemanticLidarMeasurement](#carla.SemanticLidarMeasurement).<br>
|
||||
- Cooperative awareness messages V2X sensor: [carla.CAMEvent](#carla.CAMEvent).<br>
|
||||
- Custom V2X messages V2X sensor: [carla.CustomV2XEvent](#carla.CustomV2XEvent).
|
||||
|
||||
### Instance Variables
|
||||
- <a name="carla.SensorData.frame"></a>**<font color="#f8805a">frame</font>** (_int_)
|
||||
|
|
|
@ -1,4 +1,15 @@
|
|||
# C++ Reference
|
||||
|
||||
## C++ client
|
||||
|
||||
The C++ client can be built with `make` on Linux and `cmake` in Windows. An C++ client example is provided in the repository in `CARLA_ROOT/Examples/CppClient/main.cpp`. This example shows how to connect the C++ client to the CARLA server and use the API for some simple tasks.
|
||||
|
||||
To build the example C++ client, open a terminal in the `CARLA_ROOT/Examples/CppClient` directory in the repository. Run `make` in this folder and then execute `./bin/cpp_client` to run the example. The example will choose a random map from those available then load it. It will then spawn a vehicle and apply a control to the vehicle.
|
||||
|
||||
Please see the [C++ client example](adv_cpp_client.md) for more details on this example script.
|
||||
|
||||
## C++ documentation
|
||||
|
||||
We use Doxygen to generate the documentation of our C++ code:
|
||||
|
||||
[Libcarla/Source](http://carla.org/Doxygen/html/dir_b9166249188ce33115fd7d5eed1849f2.html)<br>
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
- [__Instance segmentation camera__](#instance-segmentation-camera)
|
||||
- [__DVS camera__](#dvs-camera)
|
||||
- [__Optical Flow camera__](#optical-flow-camera)
|
||||
- [__V2X sensor__](#v2x-sensor)
|
||||
- [Cooperative awareness](#cooperative-awareness-message)
|
||||
- [Custom message](#custom-v2x-message)
|
||||
|
||||
!!! Important
|
||||
All the sensors use the UE coordinate system (__x__-*forward*, __y__-*right*, __z__-*up*), and return coordinates in local space. When using any visualization software, pay attention to its coordinate system. Many invert the Y-axis, so visualizing the sensor data directly may result in mirrored outputs.
|
||||
|
@ -183,10 +186,11 @@ Provides measures that accelerometer, gyroscope and compass would retrieve for t
|
|||
| `timestamp` | double | Simulation time of the measurement in seconds since the beginning of the episode. |
|
||||
| `transform` | [carla.Transform](<../python_api#carlatransform>) | Location and rotation in world coordinates of the sensor at the time of the measurement. |
|
||||
| `accelerometer` | [carla.Vector3D](<../python_api#carlavector3d>) | Measures linear acceleration in `m/s^2`. |
|
||||
| `gyroscope` | [carla.Vector3D](<../python_api#carlavector3d>) | Measures angular velocity in `rad/sec`. |
|
||||
| `compass` | float | Orientation in radians. North is `(0.0, -1.0, 0.0)` in UE. |
|
||||
|
||||
| `gyroscope` | [carla.Vector3D](<../python_api#carlavector3d>) | Measures angular velocity in `rad/s`. |
|
||||
| `compass` | float | Orientation in radians. North is 0 radians. |
|
||||
|
||||
!!! note
|
||||
For the compass, North is 0 radians. East is *pi*/2 radians, South is *pi* radians, West is 3*pi*/2 radians. North is in the direction of decreasing Y in CARLA's global coordinate system. East is in the direction of increasing X. The compass value converted to degrees is equal to 90 - yaw.
|
||||
|
||||
---
|
||||
## Lane invasion detector
|
||||
|
@ -904,3 +908,102 @@ The Optical Flow camera captures the motion perceived from the point of view of
|
|||
| `raw_data` | bytes | Array of BGRA 64-bit pixels containing two float values. |
|
||||
|
||||
<br>
|
||||
|
||||
---
|
||||
|
||||
## V2X sensor
|
||||
|
||||
Vehicle-to-everything (V2X) communication is an important aspect for future applications of cooperative intelligent transportation systems. In real vehicles, this requires a dedicated onboard unit (OBU) in each vehicle, that is able to send and receive information over wireless channels. Depending on the region (Europe, China, USA), different physical technologies, protocols and application messaging formats are used.
|
||||
|
||||
CARLA currently supports simulation of a simple broadcast wireless channel and two application messages. Protocols for network access and forwarding are not supported yet. The two implemented messages are the [*Cooperative Awarness Message*](#cooperative-awareness-message) according to the European standard ETSI, and a [*custom message*](#custom-v2x-message) type, that can be used to transmit arbitrary string data (e.g. JSON). There are two distinct sensors for V2X communication, that can be used separately, one for each application message type.
|
||||
|
||||
Basically, the wireless channel incorporates the following calculation for both sensors:
|
||||
|
||||
ReceivedPower = OtherTransmitPower + combined_antenna_gain - loss
|
||||
|
||||
IF (ReceivedPower >= receiver_sensitivity)
|
||||
THEN message is received
|
||||
|
||||
To simulate V2X communication, at least two V2X sensors of the same type need to be spawned (at least one sender-receiver pair). Because the received power is calculated on the receiver-side V2X sensor, only the antenna gain that is specified on the receiver-side sensor is incorporated in this calculation. Transmission power and receiver sensitivity can be configured (see [Blueprint attributes](#v2x-sensors-blueprint-attributes)).
|
||||
|
||||
The *loss* calculation depends on
|
||||
- the visbility condition between sender and receiver: line of sight (no obstacles), non-line of sight obstructed by buildings, or non-line of sight obstructed by vehicles, and
|
||||
- the scenario: highway, rural, or urban environment
|
||||
|
||||
While the visibility is simulated within CARLA, the scenario can be configured by the user (see [Blueprint attributes](#v2x-sensors-blueprint-attributes)), as well as several other attributes of the wireless channel.
|
||||
|
||||
### Sensor (sub)types
|
||||
|
||||
#### Cooperative Awareness Message
|
||||
|
||||
* __Blueprint:__ sensor.other.v2x
|
||||
* __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
|
||||
- Time elapsed > CAM Generation time (configurable)
|
||||
- Low Frequency Container Time Elapsed $> 500$ ms
|
||||
|
||||
For the CAM V2X sensor, additional blueprint attributes apply:
|
||||
|
||||
| Blueprint attribute | Type | Default | Description |
|
||||
|-------------------------|--------|-------------------------|------------------------------------|
|
||||
| <td colspan=4> 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) |
|
||||
| fixed\_rate | bool | false [true] | Generate a CAM in every CARLA tick (only for debug purposes, will result in slowdown) |
|
||||
| <td colspan=4> 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). |
|
||||
| `noise_accel_stddev_z` | float | 0\.0 | Standard deviation parameter in the noise model for acceleration (Z axis). |
|
||||
| `noise_yawrate_bias` | float | 0\.0 | Mean parameter in the noise model for yaw rate. |
|
||||
| `noise_yawrate_stddev` | float | 0\.0 | Standard deviation parameter in the noise model for yaw rate. |
|
||||
| `noise_alt_bias` | float | 0\.0 | Mean parameter in the noise model for altitude. |
|
||||
| `noise_alt_stddev` | float | 0\.0 | Standard deviation parameter in the noise model for altitude. |
|
||||
| `noise_lat_bias` | float | 0\.0 | Mean parameter in the noise model for latitude. |
|
||||
| `noise_lat_stddev` | float | 0\.0 | Standard deviation parameter in the noise model for latitude. |
|
||||
| `noise_lon_bias` | float | 0\.0 | Mean parameter in the noise model for longitude. |
|
||||
| `noise_lon_stddev` | float | 0\.0 | Standard deviation parameter in the noise model for longitude. |
|
||||
| `noise_head_bias` | float | 0\.0 | Mean parameter in the noise model for heading. |
|
||||
| `noise_head_stddev` | float | 0\.0 | Standard deviation parameter in the noise model for heading. |
|
||||
|
||||
#### Custom V2X Message
|
||||
|
||||
* __Blueprint:__ sensor.other.v2x_custom
|
||||
* __Output:__ [carla.CustomV2XData](python_api.md#carla.CustomV2XData), triggered with next tick after a *send()* was called
|
||||
|
||||
##### Methods
|
||||
- <a name="carla.Sensor.send"></a>**<font color="#7fb800">send</font>**(<font color="#00a6ed">**self**</font>, <font color="#00a6ed">**callback**</font>)
|
||||
The function the user has to call every time to send a message. This function needs for an argument containing an object type [carla.SensorData](#carla.SensorData) to work with.
|
||||
- **Parameters:**
|
||||
- `data` (_function_) - The called function with one argument containing the sensor data.
|
||||
|
||||
The custom V2X message sensor works a little bit different than other sensors, because it has the *send* function in addition to the *listen* function, that needs to be called, before another sensor of this type will receive anything. The transmission of a custom message is only triggered, when *send* is called. Each message given to the *send* function is only transmitted once to all Custom V2X Message sensors currently spawned.
|
||||
|
||||
Example:
|
||||
|
||||
bp = world.get_blueprint_library().find('sensor.other.v2x_custom')
|
||||
sensor = world.spawn_actor(bp, carla.Transform(), attach_to=parent)
|
||||
sensor.send("Hello CARLA")
|
||||
|
||||
### V2X sensors blueprint attributes
|
||||
|
||||
| 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 |
|
||||
| <td colspan=4> __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` |
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ pipeline
|
|||
//{
|
||||
stage('ubuntu')
|
||||
{
|
||||
agent { label "gpu" }
|
||||
agent { label "ubuntu_20_04" }
|
||||
environment
|
||||
{
|
||||
UE4_ROOT = '/home/jenkins/UnrealEngine_4.26'
|
||||
|
@ -132,7 +132,7 @@ pipeline
|
|||
dir('doc_repo')
|
||||
{
|
||||
checkout scmGit(
|
||||
branches: [[name: '*/master']],
|
||||
branches: [[name: '*/dev']],
|
||||
extensions: [
|
||||
cleanBeforeCheckout(),
|
||||
checkoutOption(120),
|
||||
|
@ -207,6 +207,7 @@ pipeline
|
|||
{
|
||||
stage('ubuntu smoke tests')
|
||||
{
|
||||
agent { label "gpu_20_04" }
|
||||
steps
|
||||
{
|
||||
unstash name: 'ubuntu_eggs'
|
||||
|
@ -315,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 ruben/jenkins_migration
|
||||
git push --set-upstream origin dev
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,16 @@ namespace client {
|
|||
listening_mask.reset(0);
|
||||
}
|
||||
|
||||
void ServerSideSensor::Send(std::string message) {
|
||||
log_debug("calling sensor Send() ", GetDisplayId());
|
||||
if (GetActorDescription().description.id != "sensor.other.v2x_custom")
|
||||
{
|
||||
log_warning("Send methods are not supported on non-V2x sensors (sensor.other.v2x_custom).");
|
||||
return;
|
||||
}
|
||||
GetEpisode().Lock()->Send(*this,message);
|
||||
}
|
||||
|
||||
void ServerSideSensor::ListenToGBuffer(uint32_t GBufferId, CallbackFunctionType callback) {
|
||||
log_debug(GetDisplayId(), ": subscribing to gbuffer stream");
|
||||
RELEASE_ASSERT(GBufferId < GBufferTextureCount);
|
||||
|
|
|
@ -56,6 +56,9 @@ namespace client {
|
|||
/// Return if the sensor is publishing for ROS2
|
||||
bool IsEnabledForROS();
|
||||
|
||||
/// Send data via this sensor
|
||||
void Send(std::string message);
|
||||
|
||||
/// @copydoc Actor::Destroy()
|
||||
///
|
||||
/// Additionally stop listening.
|
||||
|
|
|
@ -44,6 +44,10 @@ namespace client {
|
|||
}
|
||||
}
|
||||
|
||||
Vehicle::TelemetryData Vehicle::GetTelemetryData() const {
|
||||
return GetEpisode().Lock()->GetVehicleTelemetryData(*this);
|
||||
}
|
||||
|
||||
void Vehicle::ShowDebugTelemetry(bool enabled) {
|
||||
GetEpisode().Lock()->ShowVehicleDebugTelemetry(*this, enabled);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "carla/rpc/VehicleDoor.h"
|
||||
#include "carla/rpc/VehicleLightState.h"
|
||||
#include "carla/rpc/VehiclePhysicsControl.h"
|
||||
#include "carla/rpc/VehicleTelemetryData.h"
|
||||
#include "carla/rpc/VehicleWheels.h"
|
||||
#include "carla/trafficmanager/TrafficManager.h"
|
||||
|
||||
|
@ -35,6 +36,7 @@ namespace client {
|
|||
using Control = rpc::VehicleControl;
|
||||
using AckermannControl = rpc::VehicleAckermannControl;
|
||||
using PhysicsControl = rpc::VehiclePhysicsControl;
|
||||
using TelemetryData = rpc::VehicleTelemetryData;
|
||||
using LightState = rpc::VehicleLightState::LightState;
|
||||
using TM = traffic_manager::TrafficManager;
|
||||
using VehicleDoor = rpc::VehicleDoor;
|
||||
|
@ -46,6 +48,11 @@ namespace client {
|
|||
/// Switch on/off this vehicle's autopilot.
|
||||
void SetAutopilot(bool enabled = true, uint16_t tm_port = TM_DEFAULT_PORT);
|
||||
|
||||
/// Return the telemetry data for this vehicle.
|
||||
///
|
||||
/// @warning This function does call the simulator.
|
||||
TelemetryData GetTelemetryData() const;
|
||||
|
||||
/// Switch on/off this vehicle's autopilot.
|
||||
void ShowDebugTelemetry(bool enabled = true);
|
||||
|
||||
|
|
|
@ -481,6 +481,11 @@ namespace detail {
|
|||
_pimpl->AsyncCall("set_actor_autopilot", vehicle, enabled);
|
||||
}
|
||||
|
||||
rpc::VehicleTelemetryData Client::GetVehicleTelemetryData(
|
||||
rpc::ActorId vehicle) const {
|
||||
return _pimpl->CallAndWait<carla::rpc::VehicleTelemetryData>("get_telemetry_data", vehicle);
|
||||
}
|
||||
|
||||
void Client::ShowVehicleDebugTelemetry(rpc::ActorId vehicle, const bool enabled) {
|
||||
_pimpl->AsyncCall("show_vehicle_debug_telemetry", vehicle, enabled);
|
||||
}
|
||||
|
@ -670,6 +675,10 @@ namespace detail {
|
|||
return _pimpl->CallAndWait<bool>("is_sensor_enabled_for_ros", thisToken.get_stream_id());
|
||||
}
|
||||
|
||||
void Client::Send(rpc::ActorId ActorId, std::string message) {
|
||||
_pimpl->AsyncCall("send", ActorId, message);
|
||||
}
|
||||
|
||||
void Client::SubscribeToGBuffer(
|
||||
rpc::ActorId ActorId,
|
||||
uint32_t GBufferId,
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "carla/rpc/VehicleLightStateList.h"
|
||||
#include "carla/rpc/VehicleLightState.h"
|
||||
#include "carla/rpc/VehiclePhysicsControl.h"
|
||||
#include "carla/rpc/VehicleTelemetryData.h"
|
||||
#include "carla/rpc/VehicleWheels.h"
|
||||
#include "carla/rpc/WeatherParameters.h"
|
||||
#include "carla/rpc/Texture.h"
|
||||
|
@ -285,6 +286,8 @@ namespace detail {
|
|||
rpc::ActorId vehicle,
|
||||
bool enabled);
|
||||
|
||||
rpc::VehicleTelemetryData GetVehicleTelemetryData(rpc::ActorId vehicle) const;
|
||||
|
||||
void ShowVehicleDebugTelemetry(
|
||||
rpc::ActorId vehicle,
|
||||
bool enabled);
|
||||
|
@ -430,6 +433,8 @@ namespace detail {
|
|||
rpc::ActorId ActorId,
|
||||
uint32_t GBufferId);
|
||||
|
||||
void Send(rpc::ActorId ActorId, std::string message);
|
||||
|
||||
void DrawDebugShape(const rpc::DebugShape &shape);
|
||||
|
||||
void ApplyBatch(
|
||||
|
|
|
@ -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.
|
||||
|
@ -441,6 +447,10 @@ EpisodeProxy Simulator::GetCurrentEpisode() {
|
|||
_client.FreezeAllTrafficLights(frozen);
|
||||
}
|
||||
|
||||
void Simulator::Send(const Sensor &sensor, std::string message) {
|
||||
_client.Send(sensor.GetId(), message);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
/// -- Texture updating operations
|
||||
// =========================================================================
|
||||
|
|
|
@ -525,6 +525,10 @@ namespace detail {
|
|||
_client.SetActorAutopilot(vehicle.GetId(), enabled);
|
||||
}
|
||||
|
||||
rpc::VehicleTelemetryData GetVehicleTelemetryData(const Vehicle &vehicle) const {
|
||||
return _client.GetVehicleTelemetryData(vehicle.GetId());
|
||||
}
|
||||
|
||||
void ShowVehicleDebugTelemetry(Vehicle &vehicle, bool enabled = true) {
|
||||
_client.ShowVehicleDebugTelemetry(vehicle.GetId(), enabled);
|
||||
}
|
||||
|
@ -695,6 +699,8 @@ namespace detail {
|
|||
Actor & sensor,
|
||||
uint32_t gbuffer_id);
|
||||
|
||||
void Send(const Sensor &sensor, std::string message);
|
||||
|
||||
/// @}
|
||||
// =========================================================================
|
||||
/// @name Operations with traffic lights
|
||||
|
|
|
@ -206,23 +206,33 @@ namespace geom {
|
|||
size_t PosToAdd = it - redirections.begin();
|
||||
|
||||
Mesh out_mesh;
|
||||
if(lane_pair.second.GetType() == road::Lane::LaneType::Driving ){
|
||||
out_mesh += *GenerateTesselated(lane_pair.second);
|
||||
}else{
|
||||
out_mesh += *GenerateSidewalk(lane_pair.second);
|
||||
switch(lane_pair.second.GetType())
|
||||
{
|
||||
case road::Lane::LaneType::Driving:
|
||||
case road::Lane::LaneType::Parking:
|
||||
case road::Lane::LaneType::Bidirectional:
|
||||
{
|
||||
out_mesh += *GenerateTesselated(lane_pair.second);
|
||||
break;
|
||||
}
|
||||
case road::Lane::LaneType::Shoulder:
|
||||
case road::Lane::LaneType::Sidewalk:
|
||||
case road::Lane::LaneType::Biking:
|
||||
{
|
||||
out_mesh += *GenerateSidewalk(lane_pair.second);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
out_mesh += *GenerateTesselated(lane_pair.second);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( result[lane_pair.second.GetType()].size() <= PosToAdd ){
|
||||
result[lane_pair.second.GetType()].push_back(std::make_unique<Mesh>(out_mesh));
|
||||
} else {
|
||||
uint32_t verticesinwidth = 0;
|
||||
if(lane_pair.second.GetType() == road::Lane::LaneType::Driving) {
|
||||
verticesinwidth = vertices_in_width;
|
||||
}else if(lane_pair.second.GetType() == road::Lane::LaneType::Sidewalk){
|
||||
verticesinwidth = 6;
|
||||
}else{
|
||||
verticesinwidth = 2;
|
||||
}
|
||||
uint32_t verticesinwidth = SelectVerticesInWidth(vertices_in_width, lane_pair.second.GetType());
|
||||
(result[lane_pair.second.GetType()][PosToAdd])->ConcatMesh(out_mesh, verticesinwidth);
|
||||
}
|
||||
}
|
||||
|
@ -548,12 +558,28 @@ std::map<road::Lane::LaneType , std::vector<std::unique_ptr<Mesh>>> MeshFactory:
|
|||
|
||||
for (auto &&lane_pair : lane_section.GetLanes()) {
|
||||
Mesh lane_section_mesh;
|
||||
if(lane_pair.second.GetType() == road::Lane::LaneType::Driving ){
|
||||
lane_section_mesh += *GenerateTesselated(lane_pair.second, s_current, s_until);
|
||||
}else{
|
||||
lane_section_mesh += *GenerateSidewalk(lane_pair.second, s_current, s_until);
|
||||
switch(lane_pair.second.GetType())
|
||||
{
|
||||
case road::Lane::LaneType::Driving:
|
||||
case road::Lane::LaneType::Parking:
|
||||
case road::Lane::LaneType::Bidirectional:
|
||||
{
|
||||
lane_section_mesh += *GenerateTesselated(lane_pair.second, s_current, s_until);
|
||||
break;
|
||||
}
|
||||
case road::Lane::LaneType::Shoulder:
|
||||
case road::Lane::LaneType::Sidewalk:
|
||||
case road::Lane::LaneType::Biking:
|
||||
{
|
||||
lane_section_mesh += *GenerateSidewalk(lane_pair.second, s_current, s_until);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
lane_section_mesh += *GenerateTesselated(lane_pair.second, s_current, s_until);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto it = std::find(redirections.begin(), redirections.end(), lane_pair.first);
|
||||
if (it == redirections.end()) {
|
||||
redirections.push_back(lane_pair.first);
|
||||
|
@ -564,14 +590,7 @@ std::map<road::Lane::LaneType , std::vector<std::unique_ptr<Mesh>>> MeshFactory:
|
|||
if (mesh_uptr_list[lane_pair.second.GetType()].size() <= PosToAdd) {
|
||||
mesh_uptr_list[lane_pair.second.GetType()].push_back(std::make_unique<Mesh>(lane_section_mesh));
|
||||
} else {
|
||||
uint32_t verticesinwidth = 0;
|
||||
if(lane_pair.second.GetType() == road::Lane::LaneType::Driving) {
|
||||
verticesinwidth = vertices_in_width;
|
||||
}else if(lane_pair.second.GetType() == road::Lane::LaneType::Sidewalk){
|
||||
verticesinwidth = 6;
|
||||
}else{
|
||||
verticesinwidth = 2;
|
||||
}
|
||||
uint32_t verticesinwidth = SelectVerticesInWidth(vertices_in_width, lane_pair.second.GetType());
|
||||
(mesh_uptr_list[lane_pair.second.GetType()][PosToAdd])->ConcatMesh(lane_section_mesh, verticesinwidth);
|
||||
}
|
||||
}
|
||||
|
@ -580,10 +599,27 @@ std::map<road::Lane::LaneType , std::vector<std::unique_ptr<Mesh>>> MeshFactory:
|
|||
if (s_end - s_current > EPSILON) {
|
||||
for (auto &&lane_pair : lane_section.GetLanes()) {
|
||||
Mesh lane_section_mesh;
|
||||
if(lane_pair.second.GetType() == road::Lane::LaneType::Driving ){
|
||||
lane_section_mesh += *GenerateTesselated(lane_pair.second, s_current, s_end);
|
||||
}else{
|
||||
lane_section_mesh += *GenerateSidewalk(lane_pair.second, s_current, s_end);
|
||||
switch(lane_pair.second.GetType())
|
||||
{
|
||||
case road::Lane::LaneType::Driving:
|
||||
case road::Lane::LaneType::Parking:
|
||||
case road::Lane::LaneType::Bidirectional:
|
||||
{
|
||||
lane_section_mesh += *GenerateTesselated(lane_pair.second, s_current, s_end);
|
||||
break;
|
||||
}
|
||||
case road::Lane::LaneType::Shoulder:
|
||||
case road::Lane::LaneType::Sidewalk:
|
||||
case road::Lane::LaneType::Biking:
|
||||
{
|
||||
lane_section_mesh += *GenerateSidewalk(lane_pair.second, s_current, s_end);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
lane_section_mesh += *GenerateTesselated(lane_pair.second, s_current, s_end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto it = std::find(redirections.begin(), redirections.end(), lane_pair.first);
|
||||
|
@ -597,14 +633,6 @@ std::map<road::Lane::LaneType , std::vector<std::unique_ptr<Mesh>>> MeshFactory:
|
|||
if (mesh_uptr_list[lane_pair.second.GetType()].size() <= PosToAdd) {
|
||||
mesh_uptr_list[lane_pair.second.GetType()].push_back(std::make_unique<Mesh>(lane_section_mesh));
|
||||
} else {
|
||||
uint32_t verticesinwidth = 0;
|
||||
if(lane_pair.second.GetType() == road::Lane::LaneType::Driving) {
|
||||
verticesinwidth = vertices_in_width;
|
||||
}else if(lane_pair.second.GetType() == road::Lane::LaneType::Sidewalk){
|
||||
verticesinwidth = 6;
|
||||
}else{
|
||||
verticesinwidth = 2;
|
||||
}
|
||||
*(mesh_uptr_list[lane_pair.second.GetType()][PosToAdd]) += lane_section_mesh;
|
||||
}
|
||||
}
|
||||
|
@ -725,9 +753,16 @@ std::map<road::Lane::LaneType , std::vector<std::unique_ptr<Mesh>>> MeshFactory:
|
|||
for (auto&& lane_section : road.GetLaneSections()) {
|
||||
for (auto&& lane : lane_section.GetLanes()) {
|
||||
if (lane.first != 0) {
|
||||
if(lane.second.GetType() == road::Lane::LaneType::Driving ){
|
||||
GenerateLaneMarksForNotCenterLine(lane_section, lane.second, inout, outinfo);
|
||||
outinfo.push_back("white");
|
||||
switch(lane.second.GetType())
|
||||
{
|
||||
case road::Lane::LaneType::Driving:
|
||||
case road::Lane::LaneType::Parking:
|
||||
case road::Lane::LaneType::Bidirectional:
|
||||
{
|
||||
GenerateLaneMarksForNotCenterLine(lane_section, lane.second, inout, outinfo);
|
||||
outinfo.push_back("white");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(lane.second.GetType() == road::Lane::LaneType::None ){
|
||||
|
@ -1131,6 +1166,29 @@ std::map<road::Lane::LaneType , std::vector<std::unique_ptr<Mesh>>> MeshFactory:
|
|||
return std::make_unique<Mesh>(out_mesh);
|
||||
}
|
||||
|
||||
uint32_t MeshFactory::SelectVerticesInWidth(uint32_t default_num_vertices, road::Lane::LaneType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case road::Lane::LaneType::Driving:
|
||||
case road::Lane::LaneType::Parking:
|
||||
case road::Lane::LaneType::Bidirectional:
|
||||
{
|
||||
return default_num_vertices;
|
||||
}
|
||||
case road::Lane::LaneType::Shoulder:
|
||||
case road::Lane::LaneType::Sidewalk:
|
||||
case road::Lane::LaneType::Biking:
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<geom::Vector3D, geom::Vector3D> MeshFactory::ComputeEdgesForLanemark(
|
||||
const road::LaneSection& lane_section,
|
||||
const road::Lane& lane,
|
||||
|
|
|
@ -129,6 +129,7 @@ namespace geom {
|
|||
const road::Lane& lane,
|
||||
std::vector<std::unique_ptr<Mesh>>& inout,
|
||||
std::vector<std::string>& outinfo ) const;
|
||||
|
||||
// =========================================================================
|
||||
// -- Generation parameters ------------------------------------------------
|
||||
// =========================================================================
|
||||
|
@ -148,6 +149,12 @@ namespace geom {
|
|||
|
||||
RoadParameters road_param;
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// -- Helper functions ------------------------------------------------
|
||||
// =========================================================================
|
||||
|
||||
static uint32_t SelectVerticesInWidth(uint32_t default_num_vertices, road::Lane::LaneType type);
|
||||
private:
|
||||
|
||||
// Calculate the points on both sides of the lane mark for the specified s_current
|
||||
|
|
|
@ -12,11 +12,11 @@ namespace carla {
|
|||
namespace rpc {
|
||||
|
||||
enum class ActorAttributeType : uint8_t {
|
||||
Bool,
|
||||
Int,
|
||||
Float,
|
||||
String,
|
||||
RGBColor,
|
||||
Bool = 1u,
|
||||
Int = 2u,
|
||||
Float = 3u,
|
||||
String = 4u,
|
||||
RGBColor = 5u,
|
||||
|
||||
SIZE,
|
||||
INVALID
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
// 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 <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/MsgPack.h"
|
||||
#include "carla/rpc/WheelTelemetryData.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
class VehicleTelemetryData {
|
||||
public:
|
||||
|
||||
VehicleTelemetryData() = default;
|
||||
|
||||
VehicleTelemetryData(
|
||||
float speed,
|
||||
float steer,
|
||||
float throttle,
|
||||
float brake,
|
||||
float engine_rpm,
|
||||
int32_t gear,
|
||||
float drag,
|
||||
std::vector<WheelTelemetryData> wheels)
|
||||
: speed(speed),
|
||||
steer(steer),
|
||||
throttle(throttle),
|
||||
brake(brake),
|
||||
engine_rpm(engine_rpm),
|
||||
gear(gear),
|
||||
drag(drag),
|
||||
wheels(wheels) {}
|
||||
|
||||
const std::vector<WheelTelemetryData> &GetWheels() const {
|
||||
return wheels;
|
||||
}
|
||||
|
||||
void SetWheels(std::vector<WheelTelemetryData> &in_wheels) {
|
||||
wheels = in_wheels;
|
||||
}
|
||||
|
||||
float speed = 0.0f;
|
||||
float steer = 0.0f;
|
||||
float throttle = 0.0f;
|
||||
float brake = 0.0f;
|
||||
float engine_rpm = 0.0f;
|
||||
int32_t gear = 0.0f;
|
||||
float drag = 0.0f;
|
||||
std::vector<WheelTelemetryData> wheels;
|
||||
|
||||
bool operator!=(const VehicleTelemetryData &rhs) const {
|
||||
return
|
||||
speed != rhs.speed ||
|
||||
steer != rhs.steer ||
|
||||
throttle != rhs.throttle ||
|
||||
brake != rhs.brake ||
|
||||
engine_rpm != rhs.engine_rpm ||
|
||||
gear != rhs.gear ||
|
||||
drag != rhs.drag ||
|
||||
wheels != rhs.wheels;
|
||||
}
|
||||
|
||||
bool operator==(const VehicleTelemetryData &rhs) const {
|
||||
return !(*this != rhs);
|
||||
}
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
VehicleTelemetryData(const FVehicleTelemetryData &TelemetryData) {
|
||||
speed = TelemetryData.Speed;
|
||||
steer = TelemetryData.Steer;
|
||||
throttle = TelemetryData.Throttle;
|
||||
brake = TelemetryData.Brake;
|
||||
engine_rpm = TelemetryData.EngineRPM;
|
||||
gear = TelemetryData.Gear;
|
||||
drag = TelemetryData.Drag;
|
||||
|
||||
// Wheels Setup
|
||||
wheels = std::vector<WheelTelemetryData>();
|
||||
for (const auto &Wheel : TelemetryData.Wheels) {
|
||||
wheels.push_back(WheelTelemetryData(Wheel));
|
||||
}
|
||||
}
|
||||
|
||||
operator FVehicleTelemetryData() const {
|
||||
FVehicleTelemetryData TelemetryData;
|
||||
|
||||
TelemetryData.Speed = speed;
|
||||
TelemetryData.Steer = steer;
|
||||
TelemetryData.Throttle = throttle;
|
||||
TelemetryData.Brake = brake;
|
||||
TelemetryData.EngineRPM = engine_rpm;
|
||||
TelemetryData.Gear = gear;
|
||||
TelemetryData.Drag = drag;
|
||||
|
||||
TArray<FWheelTelemetryData> Wheels;
|
||||
for (const auto &wheel : wheels) {
|
||||
Wheels.Add(FWheelTelemetryData(wheel));
|
||||
}
|
||||
TelemetryData.Wheels = Wheels;
|
||||
|
||||
return TelemetryData;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(speed,
|
||||
steer,
|
||||
throttle,
|
||||
brake,
|
||||
engine_rpm,
|
||||
gear,
|
||||
drag,
|
||||
wheels);
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -0,0 +1,120 @@
|
|||
// 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 <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/MsgPack.h"
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
class WheelTelemetryData {
|
||||
public:
|
||||
|
||||
WheelTelemetryData() = default;
|
||||
|
||||
WheelTelemetryData(
|
||||
float tire_friction,
|
||||
float lat_slip,
|
||||
float long_slip,
|
||||
float omega,
|
||||
float tire_load,
|
||||
float normalized_tire_load,
|
||||
float torque,
|
||||
float long_force,
|
||||
float lat_force,
|
||||
float normalized_long_force,
|
||||
float normalized_lat_force)
|
||||
: tire_friction(tire_friction),
|
||||
lat_slip(lat_slip),
|
||||
long_slip(long_slip),
|
||||
omega(omega),
|
||||
tire_load(tire_load),
|
||||
normalized_tire_load(normalized_tire_load),
|
||||
torque(torque),
|
||||
long_force(long_force),
|
||||
lat_force(lat_force),
|
||||
normalized_long_force(normalized_long_force),
|
||||
normalized_lat_force(normalized_lat_force) {}
|
||||
|
||||
float tire_friction = 0.0f;
|
||||
float lat_slip = 0.0f;
|
||||
float long_slip = 0.0f;
|
||||
float omega = 0.0f;
|
||||
float tire_load = 0.0f;
|
||||
float normalized_tire_load = 0.0f;
|
||||
float torque = 0.0f;
|
||||
float long_force = 0.0f;
|
||||
float lat_force = 0.0f;
|
||||
float normalized_long_force = 0.0f;
|
||||
float normalized_lat_force = 0.0f;
|
||||
|
||||
bool operator!=(const WheelTelemetryData &rhs) const {
|
||||
return
|
||||
tire_friction != rhs.tire_friction ||
|
||||
lat_slip != rhs.lat_slip ||
|
||||
long_slip != rhs.long_slip ||
|
||||
omega != rhs.omega ||
|
||||
tire_load != rhs.tire_load ||
|
||||
normalized_tire_load != rhs.normalized_tire_load ||
|
||||
torque != rhs.torque ||
|
||||
long_force != rhs.long_force ||
|
||||
lat_force != rhs.lat_force ||
|
||||
normalized_long_force != rhs.normalized_long_force ||
|
||||
normalized_lat_force != rhs.normalized_lat_force;
|
||||
}
|
||||
|
||||
bool operator==(const WheelTelemetryData &rhs) const {
|
||||
return !(*this != rhs);
|
||||
}
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
WheelTelemetryData(const FWheelTelemetryData &TelemetryData)
|
||||
: tire_friction(TelemetryData.TireFriction),
|
||||
lat_slip(TelemetryData.LatSlip),
|
||||
long_slip(TelemetryData.LongSlip),
|
||||
omega(TelemetryData.Omega),
|
||||
tire_load(TelemetryData.TireLoad),
|
||||
normalized_tire_load(TelemetryData.NormalizedTireLoad),
|
||||
torque(TelemetryData.Torque),
|
||||
long_force(TelemetryData.LongForce),
|
||||
lat_force(TelemetryData.LatForce),
|
||||
normalized_long_force(TelemetryData.NormalizedLongForce),
|
||||
normalized_lat_force(TelemetryData.NormalizedLatForce) {}
|
||||
|
||||
operator FWheelTelemetryData() const {
|
||||
FWheelTelemetryData TelemetryData;
|
||||
TelemetryData.TireFriction = tire_friction;
|
||||
TelemetryData.LatSlip = lat_slip;
|
||||
TelemetryData.LongSlip = long_slip;
|
||||
TelemetryData.Omega = omega;
|
||||
TelemetryData.TireLoad = tire_load;
|
||||
TelemetryData.NormalizedTireLoad = normalized_tire_load;
|
||||
TelemetryData.Torque = torque;
|
||||
TelemetryData.LongForce = long_force;
|
||||
TelemetryData.LatForce = lat_force;
|
||||
TelemetryData.NormalizedLongForce = normalized_long_force;
|
||||
TelemetryData.NormalizedLatForce = normalized_lat_force;
|
||||
|
||||
return TelemetryData;
|
||||
}
|
||||
#endif
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(tire_friction,
|
||||
lat_slip,
|
||||
long_slip,
|
||||
omega,
|
||||
tire_load,
|
||||
normalized_tire_load,
|
||||
torque,
|
||||
long_force,
|
||||
lat_force,
|
||||
normalized_long_force,
|
||||
normalized_lat_force)
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -29,6 +29,7 @@
|
|||
#include "carla/sensor/s11n/SemanticLidarSerializer.h"
|
||||
#include "carla/sensor/s11n/GBufferUint8Serializer.h"
|
||||
#include "carla/sensor/s11n/GBufferFloatSerializer.h"
|
||||
#include "carla/sensor/s11n/V2XSerializer.h"
|
||||
|
||||
// 2. Add a forward-declaration of the sensor here.
|
||||
class ACollisionSensor;
|
||||
|
@ -50,6 +51,8 @@ class ARssSensor;
|
|||
class FWorldObserver;
|
||||
struct FCameraGBufferUint8;
|
||||
struct FCameraGBufferFloat;
|
||||
class AV2XSensor;
|
||||
class ACustomV2XSensor;
|
||||
|
||||
namespace carla {
|
||||
namespace sensor {
|
||||
|
@ -80,7 +83,11 @@ namespace sensor {
|
|||
std::pair<AInstanceSegmentationCamera *, s11n::ImageSerializer>,
|
||||
std::pair<FWorldObserver *, s11n::EpisodeStateSerializer>,
|
||||
std::pair<FCameraGBufferUint8 *, s11n::GBufferUint8Serializer>,
|
||||
std::pair<FCameraGBufferFloat *, s11n::GBufferFloatSerializer>
|
||||
std::pair<FCameraGBufferFloat *, s11n::GBufferFloatSerializer>,
|
||||
std::pair<AV2XSensor *, s11n::CAMDataSerializer>,
|
||||
std::pair<ACustomV2XSensor *, s11n::CustomV2XDataSerializer>
|
||||
|
||||
|
||||
>;
|
||||
|
||||
} // namespace sensor
|
||||
|
@ -108,5 +115,7 @@ namespace sensor {
|
|||
#include "Carla/Sensor/SemanticSegmentationCamera.h"
|
||||
#include "Carla/Sensor/InstanceSegmentationCamera.h"
|
||||
#include "Carla/Sensor/WorldObserver.h"
|
||||
#include "Carla/Sensor/V2XSensor.h"
|
||||
#include "Carla/Sensor/CustomV2XSensor.h"
|
||||
|
||||
#endif // LIBCARLA_SENSOR_REGISTRY_WITH_SENSOR_INCLUDES
|
||||
|
|
|
@ -0,0 +1,771 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
class ITSContainer
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
typedef bool OptionalValueAvailable_t;
|
||||
|
||||
/* Latitude Dependencies*/
|
||||
typedef enum Latitude
|
||||
{
|
||||
Latitude_oneMicroDegreeNorth = 10,
|
||||
Latitude_oneMicroDegreeSouth = -10,
|
||||
Latitude_unavailable = 900000001
|
||||
} e_Latitude;
|
||||
|
||||
/* Latitude */
|
||||
typedef long Latitude_t;
|
||||
|
||||
/* Longitude Dependencies */
|
||||
typedef enum Longitude
|
||||
{
|
||||
Longitude_oneMicroDegreeEast = 10,
|
||||
Longitude_oneMicroDegreeWest = -10,
|
||||
Longitude_unavailable = 1800000001
|
||||
} e_Longitude;
|
||||
|
||||
/* Longitude */
|
||||
typedef long Longitude_t;
|
||||
|
||||
/* SemiAxisLength Dependencies */
|
||||
typedef enum SemiAxisLength
|
||||
{
|
||||
SemiAxisLength_oneCentimeter = 1,
|
||||
SemiAxisLength_outOfRange = 4094,
|
||||
SemiAxisLength_unavailable = 4095
|
||||
} e_SemiAxisLength;
|
||||
|
||||
/* SemiAxisLength*/
|
||||
typedef long SemiAxisLength_t;
|
||||
|
||||
/* HeadingValue Dependencies */
|
||||
typedef enum HeadingValue
|
||||
{
|
||||
HeadingValue_wgs84North = 0,
|
||||
HeadingValue_wgs84East = 900,
|
||||
HeadingValue_wgs84South = 1800,
|
||||
HeadingValue_wgs84West = 2700,
|
||||
HeadingValue_unavailable = 3601
|
||||
} e_HeadingValue;
|
||||
|
||||
/* HeadingValue */
|
||||
typedef long HeadingValue_t;
|
||||
|
||||
/* HeadingConfidence Dependencies */
|
||||
typedef enum HeadingConfidence {
|
||||
HeadingConfidence_equalOrWithinZeroPointOneDegree = 1,
|
||||
HeadingConfidence_equalOrWithinOneDegree = 10,
|
||||
HeadingConfidence_outOfRange = 126,
|
||||
HeadingConfidence_unavailable = 127
|
||||
} e_HeadingConfidence;
|
||||
|
||||
/* HeadingConfidence */
|
||||
typedef long HeadingConfidence_t;
|
||||
|
||||
/* PosConfidenceEllipse*/
|
||||
typedef struct PosConfidenceEllipse
|
||||
{
|
||||
SemiAxisLength_t semiMajorConfidence;
|
||||
SemiAxisLength_t semiMinorConfidence;
|
||||
HeadingValue_t semiMajorOrientation;
|
||||
} PosConfidenceEllipse_t;
|
||||
|
||||
/* AltitudeValue Dependencies */
|
||||
typedef enum AltitudeValue
|
||||
{
|
||||
AltitudeValue_referenceEllipsoidSurface = 0,
|
||||
AltitudeValue_oneCentimeter = 1,
|
||||
AltitudeValue_unavailable = 800001
|
||||
} e_AltitudeValue;
|
||||
|
||||
/* AltitudeValue */
|
||||
typedef long AltitudeValue_t;
|
||||
|
||||
/* AltitudeConfidence Dependencies */
|
||||
typedef enum AltitudeConfidence
|
||||
{
|
||||
AltitudeConfidence_alt_000_01 = 0,
|
||||
AltitudeConfidence_alt_000_02 = 1,
|
||||
AltitudeConfidence_alt_000_05 = 2,
|
||||
AltitudeConfidence_alt_000_10 = 3,
|
||||
AltitudeConfidence_alt_000_20 = 4,
|
||||
AltitudeConfidence_alt_000_50 = 5,
|
||||
AltitudeConfidence_alt_001_00 = 6,
|
||||
AltitudeConfidence_alt_002_00 = 7,
|
||||
AltitudeConfidence_alt_005_00 = 8,
|
||||
AltitudeConfidence_alt_010_00 = 9,
|
||||
AltitudeConfidence_alt_020_00 = 10,
|
||||
AltitudeConfidence_alt_050_00 = 11,
|
||||
AltitudeConfidence_alt_100_00 = 12,
|
||||
AltitudeConfidence_alt_200_00 = 13,
|
||||
AltitudeConfidence_outOfRange = 14,
|
||||
AltitudeConfidence_unavailable = 15
|
||||
}e_AltitudeConfidence;
|
||||
|
||||
/* AltitudeConfidence */
|
||||
typedef long AltitudeConfidence_t;
|
||||
|
||||
/* Altitude */
|
||||
typedef struct Altitude
|
||||
{
|
||||
AltitudeValue_t altitudeValue;
|
||||
AltitudeConfidence_t altitudeConfidence;
|
||||
}Altitude_t;
|
||||
|
||||
/* ReferencePosition */
|
||||
typedef struct ReferencePosition
|
||||
{
|
||||
Latitude_t latitude;
|
||||
Longitude_t longitude;
|
||||
PosConfidenceEllipse_t positionConfidenceEllipse;
|
||||
Altitude_t altitude;
|
||||
} ReferencePosition_t;
|
||||
|
||||
/* StationType Dependencies */
|
||||
typedef enum StationType
|
||||
{
|
||||
StationType_unknown = 0,
|
||||
StationType_pedestrian = 1,
|
||||
StationType_cyclist = 2,
|
||||
StationType_moped = 3,
|
||||
StationType_motorcycle = 4,
|
||||
StationType_passengerCar = 5,
|
||||
StationType_bus = 6,
|
||||
StationType_lightTruck = 7,
|
||||
StationType_heavyTruck = 8,
|
||||
StationType_trailer = 9,
|
||||
StationType_specialVehicles = 10,
|
||||
StationType_tram = 11,
|
||||
StationType_roadSideUnit = 15
|
||||
} e_StationType;
|
||||
|
||||
/* StationType */
|
||||
typedef long StationType_t;
|
||||
|
||||
/* StationID*/
|
||||
typedef long StationID_t;
|
||||
// typedef unsigned long StationID_t;
|
||||
|
||||
/* Dependencies */
|
||||
typedef enum protocolVersion
|
||||
{
|
||||
protocolVersion_currentVersion = 1
|
||||
} e_protocolVersion;
|
||||
|
||||
typedef enum messageID
|
||||
{
|
||||
messageID_custom = 0,
|
||||
messageID_denm = 1,
|
||||
messageID_cam = 2,
|
||||
messageID_poi = 3,
|
||||
messageID_spat = 4,
|
||||
messageID_map = 5,
|
||||
messageID_ivi = 6,
|
||||
messageID_ev_rsr = 7
|
||||
} e_messageID;
|
||||
|
||||
typedef struct ItsPduHeader
|
||||
{
|
||||
long protocolVersion;
|
||||
long messageID;
|
||||
StationID_t stationID;
|
||||
} ItsPduHeader_t;
|
||||
|
||||
/* Heading */
|
||||
typedef struct Heading
|
||||
{
|
||||
HeadingValue_t headingValue;
|
||||
HeadingConfidence_t headingConfidence;
|
||||
} Heading_t;
|
||||
|
||||
/* SpeedValue Dependencies */
|
||||
typedef enum SpeedValue
|
||||
{
|
||||
SpeedValue_standstill = 0,
|
||||
SpeedValue_oneCentimeterPerSec = 1,
|
||||
SpeedValue_unavailable = 16383
|
||||
} e_SpeedValue;
|
||||
|
||||
/* SpeedValue */
|
||||
typedef long SpeedValue_t;
|
||||
|
||||
/* SpeedConfidence Dependencies */
|
||||
typedef enum SpeedConfidence
|
||||
{
|
||||
SpeedConfidence_equalOrWithInOneCentimerterPerSec = 1,
|
||||
SpeedConfidence_equalOrWithinOneMeterPerSec = 100,
|
||||
SpeedConfidence_outOfRange = 126,
|
||||
SpeedConfidence_unavailable = 127
|
||||
} e_SpeedConfidence;
|
||||
|
||||
/* SpeedConfidence */
|
||||
typedef long SpeedConfidence_t;
|
||||
|
||||
/* Speed */
|
||||
typedef struct speed
|
||||
{
|
||||
SpeedValue_t speedValue;
|
||||
SpeedConfidence_t speedConfidence;
|
||||
} Speed_t;
|
||||
|
||||
/* DriveDirection Dependencies */
|
||||
typedef enum DriveDirection
|
||||
{
|
||||
DriveDirection_forward = 0,
|
||||
DriveDirection_backward = 1,
|
||||
DriveDirection_unavailable = 2
|
||||
} e_DriveDirection;
|
||||
|
||||
/* DriveDirection */
|
||||
typedef long DriveDirection_t;
|
||||
|
||||
/* VehicleLength Dependencies */
|
||||
typedef enum VehicleLengthValue
|
||||
{
|
||||
VehicleLengthValue_tenCentimeters = 1,
|
||||
VehicleLengthValue_outOfRange = 1022,
|
||||
VehicleLengthValue_unavailable = 1023
|
||||
} e_VehicleLengthValue;
|
||||
|
||||
/* VehicleLengthValue */
|
||||
typedef long VehicleLengthValue_t;
|
||||
|
||||
/* VehicleLengthConfidenceIndication Dependencies */
|
||||
typedef enum VehicleLengthConfidenceIndication
|
||||
{
|
||||
VehicleLengthConfidenceIndication_noTrailerPresent = 0,
|
||||
VehicleLengthConfidenceIndication_trailerPresentWithKnownLength = 1,
|
||||
VehicleLengthConfidenceIndication_trailerPresentWithUnknownLength = 2,
|
||||
VehicleLengthConfidenceIndication_trailerPresenceIsUnknown = 3,
|
||||
VehicleLengthConfidenceIndication_unavailable = 4
|
||||
} e_VehicleLengthConfidenceIndication;
|
||||
|
||||
/* VehicleLengthConfidenceIndication */
|
||||
typedef long VehicleLengthConfidenceIndication_t;
|
||||
|
||||
/* VehicleLength */
|
||||
typedef struct VehicleLength
|
||||
{
|
||||
VehicleLengthValue_t vehicleLengthValue;
|
||||
VehicleLengthConfidenceIndication_t vehicleLengthConfidenceIndication;
|
||||
} VehicleLength_t;
|
||||
|
||||
/* VehicleWidth Dependencies */
|
||||
typedef enum VehicleWidth
|
||||
{
|
||||
VehicleWidth_tenCentimeters = 1,
|
||||
VehicleWidth_outOfRange = 61,
|
||||
VehicleWidth_unavailable = 62
|
||||
} e_VehicleWidth;
|
||||
|
||||
/* VehicleWidth */
|
||||
typedef long VehicleWidth_t;
|
||||
|
||||
/* LongitudinalAcceleration Dependencies */
|
||||
typedef enum LongitudinalAcceletationValue
|
||||
{
|
||||
LongitudinalAccelerationValue_pointOneMeterPerSecSquaredForward = 1,
|
||||
LongitudinalAccelerationValue_pointOneMeterPerSecSquaredBackWard = -1,
|
||||
LongitudinalAccelerationValue_unavailable = 161
|
||||
} e_LongitudinalAccelerationValue;
|
||||
|
||||
/* LongitudinalAcclerationValue */
|
||||
typedef long LongitudinalAccelerationValue_t;
|
||||
|
||||
/* AccelerationConfidence Dependencies */
|
||||
typedef enum AccelerationConfidence
|
||||
{
|
||||
AccelerationConfindence_pointOneMeterPerSecSquared = 1,
|
||||
AccelerationConfidence_outOfRange = 101,
|
||||
AccelerationConfidence_unavailable = 102
|
||||
} e_AccelerationConfidence;
|
||||
|
||||
/* AccelerationConfidence*/
|
||||
typedef long AccelerationConfidence_t;
|
||||
|
||||
/* LongitudinalAcceleration */
|
||||
typedef struct LongitudinalAcceleration
|
||||
{
|
||||
LongitudinalAccelerationValue_t longitudinalAccelerationValue;
|
||||
AccelerationConfidence_t longitudinalAccelerationConfidence;
|
||||
} LongitudinalAcceleration_t;
|
||||
|
||||
/* CurvatureValue Dependencies */
|
||||
typedef enum CurvatureValue
|
||||
{
|
||||
CurvatureValue_straight = 0,
|
||||
CurvatureValue_reciprocalOf1MeterRadiusToRight = -30000,
|
||||
CurvatureValue_reciprocalOf1MeterRadiusToLeft = 30000,
|
||||
CurvatureValue_unavailable = 30001
|
||||
} e_CurvatureValue;
|
||||
|
||||
/* CurvatureValue */
|
||||
typedef long CurvatureValue_t;
|
||||
|
||||
/* CurvatureConfidence Dependencies*/
|
||||
typedef enum CurvatureConfidence
|
||||
{
|
||||
CurvatureConfidence_onePerMeter_0_00002 = 0,
|
||||
CurvatureConfidence_onePerMeter_0_0001 = 1,
|
||||
CurvatureConfidence_onePerMeter_0_0005 = 2,
|
||||
CurvatureConfidence_onePerMeter_0_002 = 3,
|
||||
CurvatureConfidence_onePerMeter_0_01 = 4,
|
||||
CurvatureConfidence_onePerMeter_0_1 = 5,
|
||||
CurvatureConfidence_outOfRange = 6,
|
||||
CurvatureConfidence_unavailable = 7
|
||||
} e_CurvatureConfidence;
|
||||
|
||||
/* CurvatureConfidence */
|
||||
typedef long CurvatureConfidence_t;
|
||||
|
||||
/* Curvature */
|
||||
typedef struct Curvature
|
||||
{
|
||||
CurvatureValue_t curvatureValue;
|
||||
CurvatureConfidence_t curvatureConfidence;
|
||||
} Curvature_t;
|
||||
|
||||
/* CurvatureCalculationMode Dependencies */
|
||||
typedef enum CurvatureCalculationMode
|
||||
{
|
||||
CurvatureCalculationMode_yarRateUsed = 0,
|
||||
CurvatureCalculationMode_yarRateNotUsed = 1,
|
||||
CurvatureCalculationMode_unavailable = 2
|
||||
} e_CurvatureCalculationMode;
|
||||
|
||||
/* CurvatureCalculationMode */
|
||||
typedef long CurvatureCalculationMode_t;
|
||||
|
||||
/* YawRateValue Dependencies */
|
||||
typedef enum YawRateValue
|
||||
{
|
||||
YawRateValue_straight = 0,
|
||||
YawRateValue_degSec_000_01ToRight = -1,
|
||||
YawRateValue_degSec_000_01ToLeft = 1,
|
||||
YawRateValue_unavailable = 32767
|
||||
} e_YawRateValue;
|
||||
|
||||
/* YawRateValue */
|
||||
typedef long YawRateValue_t;
|
||||
|
||||
/* YawRateConfidence Dependencies */
|
||||
typedef enum YawRateConfidence {
|
||||
YawRateConfidence_degSec_000_01 = 0,
|
||||
YawRateConfidence_degSec_000_05 = 1,
|
||||
YawRateConfidence_degSec_000_10 = 2,
|
||||
YawRateConfidence_degSec_001_00 = 3,
|
||||
YawRateConfidence_degSec_005_00 = 4,
|
||||
YawRateConfidence_degSec_010_00 = 5,
|
||||
YawRateConfidence_degSec_100_00 = 6,
|
||||
YawRateConfidence_outOfRange = 7,
|
||||
YawRateConfidence_unavailable = 8
|
||||
} e_YawRateConfidence;
|
||||
|
||||
/* YawRateConfidence */
|
||||
typedef long YawRateConfidence_t;
|
||||
|
||||
/* YawRate */
|
||||
typedef struct YawRate
|
||||
{
|
||||
YawRateValue_t yawRateValue;
|
||||
YawRateConfidence_t yawRateConfidence;
|
||||
} YawRate_t;
|
||||
|
||||
/* AccelerationControl Dependencies */
|
||||
typedef enum AccelerationControl {
|
||||
AccelerationControl_brakePedalEngaged = 0,
|
||||
AccelerationControl_gasPedalEngaged = 1,
|
||||
AccelerationControl_emergencyBrakeEngaged = 2,
|
||||
AccelerationControl_collisionWarningEngaged = 3,
|
||||
AccelerationControl_accEngaged = 4,
|
||||
AccelerationControl_cruiseControlEngaged = 5,
|
||||
AccelerationControl_speedLimiterEngaged = 6
|
||||
} e_AccelerationControl;
|
||||
|
||||
/* AccelerationControl */
|
||||
typedef uint8_t AccelerationControl_t;
|
||||
|
||||
/* LanePosition Dependencies */
|
||||
typedef enum LanePosition {
|
||||
LanePosition_offTheRoad = -1,
|
||||
LanePosition_hardShoulder = 0,
|
||||
LanePosition_outermostDrivingLane = 1,
|
||||
LanePosition_secondLaneFromOutside = 2
|
||||
} e_LanePosition;
|
||||
|
||||
/* LanePosition */
|
||||
typedef long LanePosition_t;
|
||||
|
||||
/* SteeringWheelAngleValue Dependencies */
|
||||
typedef enum SteeringWheelAngleValue {
|
||||
SteeringWheelAngleValue_straight = 0,
|
||||
SteeringWheelAngleValue_onePointFiveDegreesToRight = -1,
|
||||
SteeringWheelAngleValue_onePointFiveDegreesToLeft = 1,
|
||||
SteeringWheelAngleValue_unavailable = 512
|
||||
} e_SteeringWheelAngleValue;
|
||||
|
||||
/* SteeringWheelAngleValue */
|
||||
typedef long SteeringWheelAngleValue_t;
|
||||
|
||||
/* SteeringWheelAngleConfidence Dependencies */
|
||||
typedef enum SteeringWheelAngleConfidence {
|
||||
SteeringWheelAngleConfidence_equalOrWithinOnePointFiveDegree = 1,
|
||||
SteeringWheelAngleConfidence_outOfRange = 126,
|
||||
SteeringWheelAngleConfidence_unavailable = 127
|
||||
} e_SteeringWheelAngleConfidence;
|
||||
|
||||
/* SteeringWheelAngleConfidence */
|
||||
typedef long SteeringWheelAngleConfidence_t;
|
||||
|
||||
/* SteeringWheelAngle */
|
||||
typedef struct SteeringWheelAngle
|
||||
{
|
||||
SteeringWheelAngleValue_t steeringWheelAngleValue;
|
||||
SteeringWheelAngleConfidence_t steeringWheelAngleConfidence;
|
||||
} SteeringWheelAngle_t;
|
||||
|
||||
/* LateralAccelerationValue Dependencies */
|
||||
typedef enum LateralAccelerationValue {
|
||||
LateralAccelerationValue_pointOneMeterPerSecSquaredToRight = -1,
|
||||
LateralAccelerationValue_pointOneMeterPerSecSquaredToLeft = 1,
|
||||
LateralAccelerationValue_unavailable = 161
|
||||
} e_LateralAccelerationValue;
|
||||
|
||||
/* LateralAccelerationValue */
|
||||
typedef long LateralAccelerationValue_t;
|
||||
|
||||
/* LateralAcceleration */
|
||||
typedef struct LateralAcceleration
|
||||
{
|
||||
LateralAccelerationValue_t lateralAccelerationValue;
|
||||
AccelerationConfidence_t lateralAccelerationConfidence;
|
||||
} LateralAcceleration_t;
|
||||
|
||||
/* VerticalAccelerationValue Dependencies */
|
||||
typedef enum VerticalAccelerationValue {
|
||||
VerticalAccelerationValue_pointOneMeterPerSecSquaredUp = 1,
|
||||
VerticalAccelerationValue_pointOneMeterPerSecSquaredDown = -1,
|
||||
VerticalAccelerationValue_unavailable = 161
|
||||
} e_VerticalAccelerationValue;
|
||||
|
||||
/* VerticalAccelerationValue */
|
||||
typedef long VerticalAccelerationValue_t;
|
||||
|
||||
/* VerticalAcceleration */
|
||||
typedef struct VerticalAcceleration
|
||||
{
|
||||
VerticalAccelerationValue_t verticalAccelerationValue;
|
||||
AccelerationConfidence_t verticalAccelerationConfidence;
|
||||
} VerticalAcceleration_t;
|
||||
|
||||
/* PerformanceClass Dependencies */
|
||||
typedef enum PerformanceClass {
|
||||
PerformanceClass_unavailable = 0,
|
||||
PerformanceClass_performanceClassA = 1,
|
||||
PerformanceClass_performanceClassB = 2
|
||||
} e_PerformanceClass;
|
||||
|
||||
/* PerformanceClass */
|
||||
typedef long PerformanceClass_t;
|
||||
|
||||
/* ProtectedZoneID */
|
||||
typedef long ProtectedZoneID_t;
|
||||
|
||||
/* CenDsrcTollingZoneID */
|
||||
typedef ProtectedZoneID_t CenDsrcTollingZoneID_t;
|
||||
|
||||
/* CenDsrcTollingZone */
|
||||
typedef struct CenDsrcTollingZone {
|
||||
Latitude_t protectedZoneLatitude;
|
||||
Longitude_t protectedZoneLongitude;
|
||||
CenDsrcTollingZoneID_t cenDsrcTollingZoneID; /* OPTIONAL */
|
||||
OptionalValueAvailable_t cenDsrcTollingZoneIDAvailable;
|
||||
} CenDsrcTollingZone_t;
|
||||
|
||||
/* ProtectedZoneType Dependencies */
|
||||
typedef enum ProtectedZoneType {
|
||||
ProtectedZoneType_cenDsrcTolling = 0
|
||||
|
||||
} e_ProtectedZoneType;
|
||||
|
||||
/* ProtectedZoneType */
|
||||
typedef long ProtectedZoneType_t;
|
||||
|
||||
/* TimestampIts Dependencies */
|
||||
typedef enum TimestampIts {
|
||||
TimestampIts_utcStartOf2004 = 0,
|
||||
TimestampIts_oneMillisecAfterUTCStartOf2004 = 1
|
||||
} e_TimestampIts;
|
||||
|
||||
|
||||
|
||||
/* TimestampIts */
|
||||
typedef long TimestampIts_t;
|
||||
|
||||
/* ProtectedZoneRadius Dependencies */
|
||||
typedef enum ProtectedZoneRadius {
|
||||
ProtectedZoneRadius_oneMeter = 1
|
||||
} e_ProtectedZoneRadius;
|
||||
|
||||
/* ProtectedZoneRadius */
|
||||
typedef long ProtectedZoneRadius_t;
|
||||
|
||||
/* ProtectedCommunicationZone */
|
||||
typedef struct ProtectedCommunicationZone {
|
||||
ProtectedZoneType_t protectedZoneType;
|
||||
TimestampIts_t expiryTime /* OPTIONAL */;
|
||||
OptionalValueAvailable_t expiryTimeAvailable;
|
||||
Latitude_t protectedZoneLatitude;
|
||||
Longitude_t protectedZoneLongitude;
|
||||
ProtectedZoneRadius_t protectedZoneRadius /* OPTIONAL */;
|
||||
OptionalValueAvailable_t protectedZoneRadiusAvailable;
|
||||
ProtectedZoneID_t protectedZoneID /* OPTIONAL */;
|
||||
OptionalValueAvailable_t protectedZoneIDAvailable;
|
||||
} ProtectedCommunicationZone_t;
|
||||
|
||||
/* ProtectedCommunicationZonesRSU */
|
||||
typedef struct ProtectedCommunicationZonesRSU {
|
||||
long ProtectedCommunicationZoneCount;
|
||||
std::vector<ProtectedCommunicationZone_t> list;
|
||||
} ProtectedCommunicationZonesRSU_t;
|
||||
|
||||
/* VehicleRole Dependencies */
|
||||
typedef enum VehicleRole {
|
||||
VehicleRole_default = 0,
|
||||
VehicleRole_publicTransport = 1,
|
||||
VehicleRole_specialTransport = 2,
|
||||
VehicleRole_dangerousGoods = 3,
|
||||
VehicleRole_roadWork = 4,
|
||||
VehicleRole_rescue = 5,
|
||||
VehicleRole_emergency = 6,
|
||||
VehicleRole_safetyCar = 7,
|
||||
VehicleRole_agriculture = 8,
|
||||
VehicleRole_commercial = 9,
|
||||
VehicleRole_military = 10,
|
||||
VehicleRole_roadOperator = 11,
|
||||
VehicleRole_taxi = 12,
|
||||
VehicleRole_reserved1 = 13,
|
||||
VehicleRole_reserved2 = 14,
|
||||
VehicleRole_reserved3 = 15
|
||||
} e_VehicleRole;
|
||||
|
||||
/* VehicleRole */
|
||||
typedef long VehicleRole_t;
|
||||
|
||||
/* ExteriorLights Dependencies */
|
||||
typedef enum ExteriorLights {
|
||||
ExteriorLights_lowBeamHeadlightsOn = 0,
|
||||
ExteriorLights_highBeamHeadlightsOn = 1,
|
||||
ExteriorLights_leftTurnSignalOn = 2,
|
||||
ExteriorLights_rightTurnSignalOn = 3,
|
||||
ExteriorLights_daytimeRunningLightsOn = 4,
|
||||
ExteriorLights_reverseLightOn = 5,
|
||||
ExteriorLights_fogLightOn = 6,
|
||||
ExteriorLights_parkingLightsOn = 7
|
||||
} e_ExteriorLights;
|
||||
|
||||
/* ExteriorLights */
|
||||
typedef uint8_t ExteriorLights_t;
|
||||
/* DeltaLatitude Dependencies */
|
||||
typedef enum DeltaLatitude {
|
||||
DeltaLatitude_oneMicrodegreeNorth = 10,
|
||||
DeltaLatitude_oneMicrodegreeSouth = -10,
|
||||
DeltaLatitude_unavailable = 131072
|
||||
} e_DeltaLatitude;
|
||||
|
||||
/* DeltaLatitude */
|
||||
typedef long DeltaLatitude_t;
|
||||
|
||||
/* DeltaLongitude Dependencies */
|
||||
typedef enum DeltaLongitude {
|
||||
DeltaLongitude_oneMicrodegreeEast = 10,
|
||||
DeltaLongitude_oneMicrodegreeWest = -10,
|
||||
DeltaLongitude_unavailable = 131072
|
||||
} e_DeltaLongitude;
|
||||
|
||||
/* DeltaLongitude */
|
||||
typedef long DeltaLongitude_t;
|
||||
|
||||
/* DeltaAltitude Dependencies */
|
||||
typedef enum DeltaAltitude {
|
||||
DeltaAltitude_oneCentimeterUp = 1,
|
||||
DeltaAltitude_oneCentimeterDown = -1,
|
||||
DeltaAltitude_unavailable = 12800
|
||||
} e_DeltaAltitude;
|
||||
|
||||
/* DeltaAltitude */
|
||||
typedef long DeltaAltitude_t;
|
||||
|
||||
/* DeltaReferencePosition */
|
||||
typedef struct DeltaReferencePosition {
|
||||
DeltaLatitude_t deltaLatitude;
|
||||
DeltaLongitude_t deltaLongitude;
|
||||
DeltaAltitude_t deltaAltitude;
|
||||
} DeltaReferencePosition_t;
|
||||
|
||||
/* PathDeltaTime Dependencies */
|
||||
typedef enum PathDeltaTime {
|
||||
PathDeltaTime_tenMilliSecondsInPast = 1
|
||||
} e_PathDeltaTime;
|
||||
|
||||
/* PathDeltaTime */
|
||||
typedef long PathDeltaTime_t;
|
||||
|
||||
/* PathPoint */
|
||||
typedef struct PathPoint {
|
||||
DeltaReferencePosition_t pathPosition;
|
||||
PathDeltaTime_t *pathDeltaTime /* OPTIONAL */;
|
||||
|
||||
} PathPoint_t;
|
||||
|
||||
/* PathHistory */
|
||||
typedef struct PathHistory {
|
||||
long NumberOfPathPoint;
|
||||
std::vector<PathPoint_t> data;
|
||||
} PathHistory_t;
|
||||
};
|
||||
|
||||
class CAMContainer
|
||||
{
|
||||
public:
|
||||
|
||||
/* GenerationDeltaTime Dependencies*/
|
||||
typedef enum GenerationDeltaTime
|
||||
{
|
||||
GenerationDeltaTime_oneMilliSec = 1
|
||||
} e_GenerationDeltaTime;
|
||||
|
||||
/* GenerationDeltaTime */
|
||||
typedef long GenerationDeltaTime_t;
|
||||
|
||||
/* BasicContainer */
|
||||
typedef struct BasicContainer
|
||||
{
|
||||
ITSContainer::StationType_t stationType;
|
||||
ITSContainer::ReferencePosition_t referencePosition;
|
||||
} BasicContainer_t;
|
||||
|
||||
/* HighFrequencyContainer Dependencies */
|
||||
typedef enum HighFrequencyContainer_PR : long
|
||||
{
|
||||
HighFrequencyContainer_PR_NOTHING, /* No components present */
|
||||
HighFrequencyContainer_PR_basicVehicleContainerHighFrequency,
|
||||
HighFrequencyContainer_PR_rsuContainerHighFrequency
|
||||
} HighFrequencyContainer_PR;
|
||||
|
||||
typedef bool OptionalStructAvailable_t;
|
||||
|
||||
/* BasicVehicleContainerHighFrequency*/
|
||||
typedef struct BasicVehicleContainerHighFrequency
|
||||
{
|
||||
ITSContainer::Heading_t heading;
|
||||
ITSContainer::Speed_t speed;
|
||||
ITSContainer::DriveDirection_t driveDirection;
|
||||
ITSContainer::VehicleLength_t vehicleLength;
|
||||
ITSContainer::VehicleWidth_t vehicleWidth;
|
||||
ITSContainer::LongitudinalAcceleration_t longitudinalAcceleration;
|
||||
ITSContainer::Curvature_t curvature;
|
||||
ITSContainer::CurvatureCalculationMode_t curvatureCalculationMode;
|
||||
ITSContainer::YawRate_t yawRate;
|
||||
|
||||
OptionalStructAvailable_t accelerationControlAvailable;
|
||||
ITSContainer::AccelerationControl_t accelerationControl /* OPTIONAL */;
|
||||
|
||||
OptionalStructAvailable_t lanePositionAvailable;
|
||||
ITSContainer::LanePosition_t lanePosition /* OPTIONAL */;
|
||||
|
||||
OptionalStructAvailable_t steeringWheelAngleAvailable;
|
||||
ITSContainer::SteeringWheelAngle_t steeringWheelAngle /* OPTIONAL */;
|
||||
|
||||
OptionalStructAvailable_t lateralAccelerationAvailable;
|
||||
ITSContainer::LateralAcceleration_t lateralAcceleration /* OPTIONAL */;
|
||||
|
||||
OptionalStructAvailable_t verticalAccelerationAvailable;
|
||||
ITSContainer::VerticalAcceleration_t verticalAcceleration /* OPTIONAL */;
|
||||
|
||||
OptionalStructAvailable_t performanceClassAvailable;
|
||||
ITSContainer::PerformanceClass_t performanceClass /* OPTIONAL */;
|
||||
|
||||
OptionalStructAvailable_t cenDsrcTollingZoneAvailable;
|
||||
ITSContainer::CenDsrcTollingZone_t cenDsrcTollingZone /* OPTIONAL */;
|
||||
|
||||
} BasicVehicleContainerHighFrequency_t;
|
||||
|
||||
/* RsuContainerHighFrequency */
|
||||
typedef struct RSUContainerHighFrequency
|
||||
{
|
||||
ITSContainer::ProtectedCommunicationZonesRSU_t protectedCommunicationZonesRSU;
|
||||
} RSUContainerHighFrequency_t;
|
||||
|
||||
/* HighFrequencyContainer */
|
||||
typedef struct HighFrequencyContainer
|
||||
{
|
||||
HighFrequencyContainer_PR present;
|
||||
|
||||
BasicVehicleContainerHighFrequency_t basicVehicleContainerHighFrequency;
|
||||
RSUContainerHighFrequency_t rsuContainerHighFrequency;
|
||||
|
||||
} HighFrequencyContainer_t;
|
||||
|
||||
/* Dependencies */
|
||||
typedef enum LowFrequencyContainer_PR : long
|
||||
{
|
||||
LowFrequencyContainer_PR_NOTHING, /* No components present */
|
||||
LowFrequencyContainer_PR_basicVehicleContainerLowFrequency,
|
||||
/* Extensions may appear below */
|
||||
|
||||
} LowFrequencyContainer_PR;
|
||||
|
||||
/* BasicVehicleContainerLowFrequency */
|
||||
typedef struct BasicVehicleContainerLowFrequency {
|
||||
ITSContainer::VehicleRole_t vehicleRole;
|
||||
ITSContainer::ExteriorLights_t exteriorLights;
|
||||
ITSContainer::PathHistory_t pathHistory;
|
||||
} BasicVehicleContainerLowFrequency_t;
|
||||
|
||||
/* LowFrequencyContainer */
|
||||
typedef struct LowFrequencyContainer
|
||||
{
|
||||
LowFrequencyContainer_PR present;
|
||||
// Since only option is available
|
||||
BasicVehicleContainerLowFrequency_t basicVehicleContainerLowFrequency;
|
||||
|
||||
} LowFrequencyContainer_t;
|
||||
|
||||
/* CamParameters */
|
||||
typedef struct CamParameters
|
||||
{
|
||||
BasicContainer_t basicContainer;
|
||||
HighFrequencyContainer_t highFrequencyContainer;
|
||||
LowFrequencyContainer_t lowFrequencyContainer; /* OPTIONAL */
|
||||
// Optional TODO: SpecialVehicleContainer *specialVehicleContainer
|
||||
} CamParameters_t;
|
||||
|
||||
/* CoopAwareness*/
|
||||
typedef struct CoopAwareness
|
||||
{
|
||||
GenerationDeltaTime_t generationDeltaTime;
|
||||
CamParameters_t camParameters;
|
||||
} CoopAwareness_t;
|
||||
|
||||
|
||||
};
|
||||
|
||||
/* CoopAwareness */
|
||||
typedef struct CAM
|
||||
{
|
||||
ITSContainer::ItsPduHeader_t header;
|
||||
CAMContainer::CoopAwareness_t cam;
|
||||
} CAM_t;
|
||||
|
||||
|
||||
typedef struct CustomV2XM
|
||||
{
|
||||
ITSContainer::ItsPduHeader_t header;
|
||||
char message[100];
|
||||
} CustomV2XM_t;
|
|
@ -0,0 +1,106 @@
|
|||
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
|
||||
// Karlsruhe Institute of Technology
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
#include "LibITS.h"
|
||||
|
||||
namespace carla
|
||||
{
|
||||
namespace sensor
|
||||
{
|
||||
|
||||
namespace s11n
|
||||
{
|
||||
class CAMDataSerializer;
|
||||
class CustomV2XDataSerializer;
|
||||
}
|
||||
|
||||
namespace data
|
||||
{
|
||||
class CAMData
|
||||
{
|
||||
public:
|
||||
float Power;
|
||||
CAM_t Message;
|
||||
};
|
||||
|
||||
class CustomV2XData
|
||||
{
|
||||
public:
|
||||
float Power;
|
||||
CustomV2XM Message;
|
||||
};
|
||||
|
||||
class CAMDataS
|
||||
{
|
||||
|
||||
public:
|
||||
explicit CAMDataS() = default;
|
||||
|
||||
CAMDataS &operator=(CAMDataS &&) = default;
|
||||
|
||||
// Returns the number of current received messages.
|
||||
size_t GetMessageCount() const
|
||||
{
|
||||
return MessageList.size();
|
||||
}
|
||||
|
||||
// Deletes the current messages.
|
||||
void Reset()
|
||||
{
|
||||
MessageList.clear();
|
||||
}
|
||||
|
||||
// Adds a new detection.
|
||||
void WriteMessage(CAMData message)
|
||||
{
|
||||
MessageList.push_back(message);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<CAMData> MessageList;
|
||||
|
||||
friend class s11n::CAMDataSerializer;
|
||||
};
|
||||
|
||||
class CustomV2XDataS
|
||||
{
|
||||
|
||||
public:
|
||||
explicit CustomV2XDataS() = default;
|
||||
|
||||
CustomV2XDataS &operator=(CustomV2XDataS &&) = default;
|
||||
|
||||
// Returns the number of current received messages.
|
||||
size_t GetMessageCount() const
|
||||
{
|
||||
return MessageList.size();
|
||||
}
|
||||
|
||||
// Deletes the current messages.
|
||||
void Reset()
|
||||
{
|
||||
MessageList.clear();
|
||||
}
|
||||
|
||||
// Adds a new detection.
|
||||
void WriteMessage(CustomV2XData message)
|
||||
{
|
||||
MessageList.push_back(message);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<CustomV2XData> MessageList;
|
||||
|
||||
friend class s11n::CustomV2XDataSerializer;
|
||||
};
|
||||
|
||||
} // namespace s11n
|
||||
} // namespace sensor
|
||||
} // namespace carla
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
|
||||
// Karlsruhe Institute of Technology
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/Debug.h"
|
||||
#include "carla/sensor/data/Array.h"
|
||||
#include "carla/sensor/s11n/V2XSerializer.h"
|
||||
#include "carla/sensor/data/V2XData.h"
|
||||
|
||||
namespace carla
|
||||
{
|
||||
namespace sensor
|
||||
{
|
||||
namespace data
|
||||
{
|
||||
|
||||
class CAMEvent : public Array<data::CAMData>
|
||||
{
|
||||
using Super = Array<data::CAMData>;
|
||||
|
||||
protected:
|
||||
using Serializer = s11n::CAMDataSerializer;
|
||||
|
||||
friend Serializer;
|
||||
|
||||
explicit CAMEvent(RawData &&data)
|
||||
: Super(0u, std::move(data)) {}
|
||||
|
||||
public:
|
||||
Super::size_type GetMessageCount() const
|
||||
{
|
||||
return Super::size();
|
||||
}
|
||||
};
|
||||
|
||||
class CustomV2XEvent : public Array<data::CustomV2XData>
|
||||
{
|
||||
using Super = Array<data::CustomV2XData>;
|
||||
|
||||
protected:
|
||||
using Serializer = s11n::CustomV2XDataSerializer;
|
||||
|
||||
friend Serializer;
|
||||
|
||||
explicit CustomV2XEvent(RawData &&data)
|
||||
: Super(0u, std::move(data)) {}
|
||||
|
||||
public:
|
||||
Super::size_type GetMessageCount() const
|
||||
{
|
||||
return Super::size();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace data
|
||||
} // namespace sensor
|
||||
} // namespace carla
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
|
||||
// Karlsruhe Institute of Technology
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/sensor/s11n/V2XSerializer.h"
|
||||
|
||||
#include "carla/sensor/data/V2XEvent.h"
|
||||
|
||||
namespace carla
|
||||
{
|
||||
namespace sensor
|
||||
{
|
||||
namespace s11n
|
||||
{
|
||||
|
||||
SharedPtr<SensorData> CAMDataSerializer::Deserialize(RawData &&data)
|
||||
{
|
||||
return SharedPtr<data::CAMEvent>(new data::CAMEvent(std::move(data)));
|
||||
}
|
||||
|
||||
SharedPtr<SensorData> CustomV2XDataSerializer::Deserialize(RawData &&data)
|
||||
{
|
||||
return SharedPtr<data::CustomV2XEvent>(new data::CustomV2XEvent(std::move(data)));
|
||||
}
|
||||
|
||||
} // namespace s11n
|
||||
} // namespace sensor
|
||||
} // namespace carla
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
|
||||
// Karlsruhe Institute of Technology
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/Memory.h"
|
||||
#include "carla/sensor/RawData.h"
|
||||
#include "carla/sensor/data/V2XData.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
class CAMContainer;
|
||||
namespace carla
|
||||
{
|
||||
namespace sensor
|
||||
{
|
||||
|
||||
class SensorData;
|
||||
|
||||
namespace s11n
|
||||
{
|
||||
|
||||
// ===========================================================================
|
||||
// -- V2XSerializer --------------------------------------------------------
|
||||
// ===========================================================================
|
||||
|
||||
/// Serializes the data generated by V2X sensors.
|
||||
// CAM
|
||||
class CAMDataSerializer
|
||||
{
|
||||
public:
|
||||
template <typename Sensor>
|
||||
static Buffer Serialize(
|
||||
const Sensor &sensor,
|
||||
const data::CAMDataS &data,
|
||||
Buffer &&output);
|
||||
|
||||
static SharedPtr<SensorData> Deserialize(RawData &&data);
|
||||
};
|
||||
|
||||
template <typename Sensor>
|
||||
inline Buffer CAMDataSerializer::Serialize(
|
||||
const Sensor &,
|
||||
const data::CAMDataS &data,
|
||||
Buffer &&output)
|
||||
{
|
||||
output.copy_from(data.MessageList);
|
||||
return std::move(output);
|
||||
}
|
||||
|
||||
// Custom message
|
||||
class CustomV2XDataSerializer
|
||||
{
|
||||
public:
|
||||
template <typename Sensor>
|
||||
static Buffer Serialize(
|
||||
const Sensor &sensor,
|
||||
const data::CustomV2XDataS &data,
|
||||
Buffer &&output);
|
||||
|
||||
static SharedPtr<SensorData> Deserialize(RawData &&data);
|
||||
};
|
||||
|
||||
template <typename Sensor>
|
||||
inline Buffer CustomV2XDataSerializer::Serialize(
|
||||
const Sensor &,
|
||||
const data::CustomV2XDataS &data,
|
||||
Buffer &&output)
|
||||
{
|
||||
output.copy_from(data.MessageList);
|
||||
return std::move(output);
|
||||
}
|
||||
|
||||
} // namespace s11n
|
||||
} // namespace sensor
|
||||
} // namespace carla
|
|
@ -18,6 +18,8 @@ from agents.tools.misc import (get_speed, is_within_distance,
|
|||
get_trafficlight_trigger_location,
|
||||
compute_distance)
|
||||
|
||||
from agents.tools.hints import ObstacleDetectionResult, TrafficLightDetectionResult
|
||||
|
||||
|
||||
class BasicAgent(object):
|
||||
"""
|
||||
|
@ -137,30 +139,37 @@ class BasicAgent(object):
|
|||
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):
|
||||
|
||||
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, 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 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.
|
||||
|
||||
:param end_location (carla.Location): final location of the route
|
||||
:param start_location (carla.Location): starting location of the route
|
||||
:param clean_queue (bool): Whether to clear or append to the currently planned route
|
||||
"""
|
||||
if not start_location:
|
||||
start_location = self._local_planner.target_waypoint.transform.location
|
||||
clean_queue = True
|
||||
else:
|
||||
start_location = self._vehicle.get_location()
|
||||
clean_queue = False
|
||||
|
||||
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
|
||||
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_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.
|
||||
|
@ -265,7 +274,7 @@ class BasicAgent(object):
|
|||
If None, the base threshold value is used
|
||||
"""
|
||||
if self._ignore_traffic_lights:
|
||||
return (False, None)
|
||||
return TrafficLightDetectionResult(False, None)
|
||||
|
||||
if not lights_list:
|
||||
lights_list = self._world.get_actors().filter("*traffic_light*")
|
||||
|
@ -277,7 +286,7 @@ class BasicAgent(object):
|
|||
if self._last_traffic_light.state != carla.TrafficLightState.Red:
|
||||
self._last_traffic_light = None
|
||||
else:
|
||||
return (True, self._last_traffic_light)
|
||||
return TrafficLightDetectionResult(True, self._last_traffic_light)
|
||||
|
||||
ego_vehicle_location = self._vehicle.get_location()
|
||||
ego_vehicle_waypoint = self._map.get_waypoint(ego_vehicle_location)
|
||||
|
@ -308,9 +317,9 @@ class BasicAgent(object):
|
|||
|
||||
if is_within_distance(trigger_wp.transform, self._vehicle.get_transform(), max_distance, [0, 90]):
|
||||
self._last_traffic_light = traffic_light
|
||||
return (True, traffic_light)
|
||||
return TrafficLightDetectionResult(True, traffic_light)
|
||||
|
||||
return (False, None)
|
||||
return TrafficLightDetectionResult(False, None)
|
||||
|
||||
def _vehicle_obstacle_detected(self, vehicle_list=None, max_distance=None, up_angle_th=90, low_angle_th=0, lane_offset=0):
|
||||
"""
|
||||
|
@ -347,12 +356,12 @@ class BasicAgent(object):
|
|||
return Polygon(route_bb)
|
||||
|
||||
if self._ignore_vehicles:
|
||||
return (False, None, -1)
|
||||
return ObstacleDetectionResult(False, None, -1)
|
||||
|
||||
if vehicle_list is None:
|
||||
vehicle_list = self._world.get_actors().filter("*vehicle*")
|
||||
if len(vehicle_list) == 0:
|
||||
return (False, None, -1)
|
||||
return ObstacleDetectionResult(False, None, -1)
|
||||
|
||||
if not max_distance:
|
||||
max_distance = self._base_vehicle_threshold
|
||||
|
@ -395,7 +404,7 @@ class BasicAgent(object):
|
|||
target_polygon = Polygon(target_list)
|
||||
|
||||
if route_polygon.intersects(target_polygon):
|
||||
return (True, target_vehicle, compute_distance(target_vehicle.get_location(), ego_location))
|
||||
return ObstacleDetectionResult(True, target_vehicle, compute_distance(target_vehicle.get_location(), ego_location))
|
||||
|
||||
# Simplified approach, using only the plan waypoints (similar to TM)
|
||||
else:
|
||||
|
@ -416,9 +425,9 @@ class BasicAgent(object):
|
|||
)
|
||||
|
||||
if is_within_distance(target_rear_transform, ego_front_transform, max_distance, [low_angle_th, up_angle_th]):
|
||||
return (True, target_vehicle, compute_distance(target_transform.location, ego_transform.location))
|
||||
return ObstacleDetectionResult(True, target_vehicle, compute_distance(target_transform.location, ego_transform.location))
|
||||
|
||||
return (False, None, -1)
|
||||
return ObstacleDetectionResult(False, None, -1)
|
||||
|
||||
def _generate_lane_change_path(self, waypoint, direction='left', distance_same_lane=10,
|
||||
distance_other_lane=25, lane_change_distance=25,
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
"""
|
||||
Module to add high-level semantic return types for obstacle and traffic light detection results via named tuples.
|
||||
|
||||
The code is compatible with Python 2.7, <3.6 and >=3.6. The later uses the typed version of named tuples.
|
||||
"""
|
||||
|
||||
|
||||
import sys
|
||||
if sys.version_info < (3, 6):
|
||||
from collections import namedtuple
|
||||
ObstacleDetectionResult = namedtuple('ObstacleDetectionResult', ['obstacle_was_found', 'obstacle', 'distance'])
|
||||
TrafficLightDetectionResult = namedtuple('TrafficLightDetectionResult', ['traffic_light_was_found', 'traffic_light'])
|
||||
else:
|
||||
from typing import NamedTuple, Union, TYPE_CHECKING
|
||||
from carla import Actor, TrafficLight
|
||||
"""
|
||||
# Python 3.6+, incompatible with Python 2.7 syntax
|
||||
class ObstacleDetectionResult(NamedTuple):
|
||||
obstacle_was_found : bool
|
||||
obstacle : Union[Actor, None]
|
||||
distance : float
|
||||
# distance : Union[float, Literal[-1]] # Python 3.8+ only
|
||||
|
||||
class TrafficLightDetectionResult(NamedTuple):
|
||||
traffic_light_was_found : bool
|
||||
traffic_light : Union[TrafficLight, None]
|
||||
"""
|
||||
if TYPE_CHECKING:
|
||||
from typing import Literal
|
||||
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])])
|
File diff suppressed because it is too large
Load Diff
|
@ -195,6 +195,7 @@ void export_actor() {
|
|||
.def("apply_ackermann_controller_settings", &cc::Vehicle::ApplyAckermannControllerSettings, (arg("settings")))
|
||||
.def("get_ackermann_controller_settings", CONST_CALL_WITHOUT_GIL(cc::Vehicle, GetAckermannControllerSettings))
|
||||
.def("set_autopilot", CALL_WITHOUT_GIL_2(cc::Vehicle, SetAutopilot, bool, uint16_t), (arg("enabled") = true, arg("tm_port") = ctm::TM_DEFAULT_PORT))
|
||||
.def("get_telemetry_data", CONST_CALL_WITHOUT_GIL(cc::Vehicle, GetTelemetryData))
|
||||
.def("show_debug_telemetry", &cc::Vehicle::ShowDebugTelemetry, (arg("enabled") = true))
|
||||
.def("get_speed_limit", &cc::Vehicle::GetSpeedLimit)
|
||||
.def("get_traffic_light_state", &cc::Vehicle::GetTrafficLightState)
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace client {
|
|||
|
||||
std::ostream &operator<<(std::ostream &out, const ActorAttribute &attr) {
|
||||
using Type = carla::rpc::ActorAttributeType;
|
||||
static_assert(static_cast<uint8_t>(Type::SIZE) == 5u, "Please update this function.");
|
||||
static_assert(static_cast<uint8_t>(Type::SIZE) == 6u, "Please update this function.");
|
||||
out << "ActorAttribute(id=" << attr.GetId();
|
||||
switch (attr.GetType()) {
|
||||
case Type::Bool:
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
#include <carla/rpc/VehicleAckermannControl.h>
|
||||
#include <carla/rpc/VehicleControl.h>
|
||||
#include <carla/rpc/VehiclePhysicsControl.h>
|
||||
#include <carla/rpc/VehicleTelemetryData.h>
|
||||
#include <carla/rpc/WheelPhysicsControl.h>
|
||||
#include <carla/rpc/WheelTelemetryData.h>
|
||||
#include <carla/rpc/WalkerControl.h>
|
||||
#include <carla/rpc/WalkerBoneControlIn.h>
|
||||
#include <carla/rpc/WalkerBoneControlOut.h>
|
||||
|
@ -116,6 +118,33 @@ namespace rpc {
|
|||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const WheelTelemetryData &telemetry) {
|
||||
out << "WheelTelemetryData(tire_friction=" << std::to_string(telemetry.tire_friction)
|
||||
<< ", lat_slip=" << std::to_string(telemetry.lat_slip)
|
||||
<< ", long_slip=" << std::to_string(telemetry.long_slip)
|
||||
<< ", omega=" << std::to_string(telemetry.omega)
|
||||
<< ", tire_load=" << std::to_string(telemetry.tire_load)
|
||||
<< ", normalized_tire_load=" << std::to_string(telemetry.normalized_tire_load)
|
||||
<< ", torque=" << std::to_string(telemetry.torque)
|
||||
<< ", long_force=" << std::to_string(telemetry.long_force)
|
||||
<< ", lat_force=" << std::to_string(telemetry.lat_force)
|
||||
<< ", normalized_long_force=" << std::to_string(telemetry.normalized_long_force)
|
||||
<< ", normalized_lat_force=" << std::to_string(telemetry.normalized_lat_force) << ')';
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const VehicleTelemetryData &telemetry) {
|
||||
out << "VehicleTelemetryData(speed=" << std::to_string(telemetry.speed)
|
||||
<< ", steer=" << std::to_string(telemetry.steer)
|
||||
<< ", throttle=" << std::to_string(telemetry.throttle)
|
||||
<< ", brake=" << std::to_string(telemetry.brake)
|
||||
<< ", engine_rpm=" << std::to_string(telemetry.engine_rpm)
|
||||
<< ", gear=" << std::to_string(telemetry.gear)
|
||||
<< ", drag=" << std::to_string(telemetry.drag)
|
||||
<< ", wheels=" << telemetry.wheels << ')';
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const AckermannControllerSettings &settings) {
|
||||
out << "AckermannControllerSettings(speed_kp=" << std::to_string(settings.speed_kp)
|
||||
<< ", speed_ki=" << std::to_string(settings.speed_ki)
|
||||
|
@ -264,6 +293,54 @@ boost::python::object VehiclePhysicsControl_init(boost::python::tuple args, boos
|
|||
return res;
|
||||
}
|
||||
|
||||
static auto GetWheelsTelemetry(const carla::rpc::VehicleTelemetryData &self) {
|
||||
const auto &wheels = self.GetWheels();
|
||||
boost::python::object get_iter = boost::python::iterator<std::vector<carla::rpc::WheelTelemetryData>>();
|
||||
boost::python::object iter = get_iter(wheels);
|
||||
return boost::python::list(iter);
|
||||
}
|
||||
|
||||
static void SetWheelsTelemetry(carla::rpc::VehicleTelemetryData &self, const boost::python::list &list) {
|
||||
std::vector<carla::rpc::WheelTelemetryData> wheels;
|
||||
auto length = boost::python::len(list);
|
||||
for (auto i = 0u; i < length; ++i) {
|
||||
wheels.push_back(boost::python::extract<carla::rpc::WheelTelemetryData &>(list[i]));
|
||||
}
|
||||
self.SetWheels(wheels);
|
||||
}
|
||||
|
||||
boost::python::object VehicleTelemetryData_init(boost::python::tuple args, boost::python::dict kwargs) {
|
||||
// Args names
|
||||
const uint32_t NUM_ARGUMENTS = 7;
|
||||
const char *args_names[NUM_ARGUMENTS] = {
|
||||
"speed",
|
||||
"steer",
|
||||
"throttle",
|
||||
"brake",
|
||||
"engine_rpm",
|
||||
"gear",
|
||||
"wheels"
|
||||
};
|
||||
|
||||
boost::python::object self = args[0];
|
||||
args = boost::python::tuple(args.slice(1, boost::python::_));
|
||||
|
||||
auto res = self.attr("__init__")();
|
||||
if (len(args) > 0) {
|
||||
for (unsigned int i = 0; i < len(args); ++i) {
|
||||
self.attr(args_names[i]) = args[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < NUM_ARGUMENTS; ++i) {
|
||||
if (kwargs.contains(args_names[i])) {
|
||||
self.attr(args_names[i]) = kwargs[args_names[i]];
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static auto GetBonesTransform(const carla::rpc::WalkerBoneControlIn &self) {
|
||||
const std::vector<carla::rpc::BoneTransformDataIn> &bone_transform_data = self.bone_transforms;
|
||||
boost::python::object get_iter =
|
||||
|
@ -507,4 +584,50 @@ void export_control() {
|
|||
.def("__ne__", &cr::VehiclePhysicsControl::operator!=)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<cr::WheelTelemetryData>("WheelTelemetryData")
|
||||
.def(init<float, float, float, float, float, float, float, float, float, float, float>(
|
||||
(arg("tire_friction")=0.0f,
|
||||
arg("lat_slip")=0.0f,
|
||||
arg("long_slip")=0.0f,
|
||||
arg("omega")=0.0f,
|
||||
arg("tire_load")=0.0f,
|
||||
arg("normalized_tire_load")=0.0f,
|
||||
arg("torque")=0.0f,
|
||||
arg("long_force")=0.0f,
|
||||
arg("lat_force")=0.0f,
|
||||
arg("normalized_long_force")=0.0f,
|
||||
arg("normalized_lat_force")=0.0f)))
|
||||
.def_readwrite("tire_friction", &cr::WheelTelemetryData::tire_friction)
|
||||
.def_readwrite("lat_slip", &cr::WheelTelemetryData::lat_slip)
|
||||
.def_readwrite("long_slip", &cr::WheelTelemetryData::long_slip)
|
||||
.def_readwrite("omega", &cr::WheelTelemetryData::omega)
|
||||
.def_readwrite("tire_load", &cr::WheelTelemetryData::tire_load)
|
||||
.def_readwrite("normalized_tire_load", &cr::WheelTelemetryData::normalized_tire_load)
|
||||
.def_readwrite("torque", &cr::WheelTelemetryData::torque)
|
||||
.def_readwrite("long_force", &cr::WheelTelemetryData::long_force)
|
||||
.def_readwrite("lat_force", &cr::WheelTelemetryData::lat_force)
|
||||
.def_readwrite("normalized_long_force", &cr::WheelTelemetryData::normalized_long_force)
|
||||
.def_readwrite("normalized_lat_force", &cr::WheelTelemetryData::normalized_lat_force)
|
||||
.def("__eq__", &cr::WheelTelemetryData::operator==)
|
||||
.def("__ne__", &cr::WheelTelemetryData::operator!=)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<cr::VehicleTelemetryData>("VehicleTelemetryData", no_init)
|
||||
.def("__init__", raw_function(VehicleTelemetryData_init))
|
||||
.def(init<>())
|
||||
.def_readwrite("speed", &cr::VehicleTelemetryData::speed)
|
||||
.def_readwrite("steer", &cr::VehicleTelemetryData::steer)
|
||||
.def_readwrite("throttle", &cr::VehicleTelemetryData::throttle)
|
||||
.def_readwrite("brake", &cr::VehicleTelemetryData::brake)
|
||||
.def_readwrite("engine_rpm", &cr::VehicleTelemetryData::engine_rpm)
|
||||
.def_readwrite("gear", &cr::VehicleTelemetryData::gear)
|
||||
.def_readwrite("drag", &cr::VehicleTelemetryData::drag)
|
||||
.add_property("wheels", &GetWheelsTelemetry, &SetWheelsTelemetry)
|
||||
.def("__eq__", &cr::VehicleTelemetryData::operator==)
|
||||
.def("__ne__", &cr::VehicleTelemetryData::operator!=)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
}
|
||||
|
|
|
@ -237,6 +237,10 @@ void export_geom() {
|
|||
self.TransformPoint(location);
|
||||
return location;
|
||||
}, arg("in_point"))
|
||||
.def("inverse_transform", +[](const cg::Transform &self, cg::Vector3D &location) {
|
||||
self.InverseTransformPoint(location);
|
||||
return location;
|
||||
}, arg("in_point"))
|
||||
.def("transform_vector", +[](const cg::Transform &self, cg::Vector3D &vector) {
|
||||
self.TransformVector(vector);
|
||||
return vector;
|
||||
|
|
|
@ -26,7 +26,6 @@ void export_sensor() {
|
|||
namespace cc = carla::client;
|
||||
|
||||
class_<cc::Sensor, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::Sensor>>("Sensor", no_init)
|
||||
.add_property("is_listening", &cc::Sensor::IsListening)
|
||||
.def("listen", &SubscribeToStream, (arg("callback")))
|
||||
.def("is_listening", &cc::Sensor::IsListening)
|
||||
.def("stop", &cc::Sensor::Stop)
|
||||
|
@ -41,6 +40,7 @@ void export_sensor() {
|
|||
.def("enable_for_ros", &cc::ServerSideSensor::EnableForROS)
|
||||
.def("disable_for_ros", &cc::ServerSideSensor::DisableForROS)
|
||||
.def("is_enabled_for_ros", &cc::ServerSideSensor::IsEnabledForROS)
|
||||
.def("send", &cc::ServerSideSensor::Send, (arg("message")))
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
#include <carla/sensor/data/GnssMeasurement.h>
|
||||
#include <carla/sensor/data/RadarMeasurement.h>
|
||||
#include <carla/sensor/data/DVSEventArray.h>
|
||||
#include <carla/sensor/data/V2XEvent.h>
|
||||
#include <carla/sensor/data/V2XData.h>
|
||||
#include <carla/sensor/data/LibITS.h>
|
||||
|
||||
#include <carla/sensor/data/RadarData.h>
|
||||
|
||||
|
@ -166,6 +169,40 @@ namespace data {
|
|||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const CAMEvent &data) {
|
||||
out << "CAMEvent(frame=" << std::to_string(data.GetFrame())
|
||||
<< ", timestamp=" << std::to_string(data.GetTimestamp())
|
||||
<< ", message_count=" << std::to_string(data.GetMessageCount())
|
||||
<< ')';
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const CustomV2XEvent &data) {
|
||||
out << "CustomV2XEvent(frame=" << std::to_string(data.GetFrame())
|
||||
<< ", timestamp=" << std::to_string(data.GetTimestamp())
|
||||
<< ", message_count=" << std::to_string(data.GetMessageCount())
|
||||
<< ')';
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const CAMData &data) {
|
||||
out << "CAMData(power=" << std::to_string(data.Power)
|
||||
<< ", stationId=" << std::to_string(data.Message.header.stationID)
|
||||
<< ", messageId=" << std::to_string(data.Message.header.messageID)
|
||||
<< ')';
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const CustomV2XData &data) {
|
||||
out << "CustomV2XData(power=" << std::to_string(data.Power)
|
||||
<< ", stationId=" << std::to_string(data.Message.header.stationID)
|
||||
<< ", messageId=" << std::to_string(data.Message.header.messageID)
|
||||
<< ')';
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace s11n
|
||||
} // namespace sensor
|
||||
} // namespace carla
|
||||
|
@ -356,6 +393,39 @@ static std::string SavePointCloudToDisk(T &self, std::string path) {
|
|||
return carla::pointcloud::PointCloudIO::SaveToDisk(std::move(path), self.begin(), self.end());
|
||||
}
|
||||
|
||||
static boost::python::dict GetCAMData(const carla::sensor::data::CAMData message)
|
||||
{
|
||||
boost::python::dict myDict;
|
||||
try
|
||||
{
|
||||
myDict["Power"] = message.Power;
|
||||
myDict["Message"] = GetCAMMessage(message);
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << '\n';
|
||||
}
|
||||
|
||||
return myDict;
|
||||
}
|
||||
|
||||
|
||||
static boost::python::dict GetCustomV2XData(const carla::sensor::data::CustomV2XData message)
|
||||
{
|
||||
boost::python::dict myDict;
|
||||
try
|
||||
{
|
||||
myDict["Power"] = message.Power;
|
||||
myDict["Message"] = GetCustomV2XMessage(message);
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << '\n';
|
||||
}
|
||||
|
||||
return myDict;
|
||||
}
|
||||
/**********************************************************************************************/
|
||||
void export_sensor_data() {
|
||||
using namespace boost::python;
|
||||
namespace cc = carla::client;
|
||||
|
@ -573,4 +643,34 @@ void export_sensor_data() {
|
|||
.def("to_array_pol", CALL_RETURNING_LIST(csd::DVSEventArray, ToArrayPol))
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<csd::CAMData>("CAMMessage")
|
||||
.def_readwrite("power", &csd::CAMData::Power)
|
||||
.def("get", GetCAMData)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<csd::CustomV2XData>("CustomV2XData")
|
||||
.def_readwrite("power", &csd::CustomV2XData::Power)
|
||||
.def("get", GetCustomV2XData)
|
||||
.def(self_ns::str(self_ns::self))
|
||||
;
|
||||
|
||||
class_<csd::CAMEvent, bases<cs::SensorData>, boost::noncopyable, boost::shared_ptr<csd::CAMEvent>>("CAMEvent", no_init)
|
||||
.def("get_message_count", &csd::CAMEvent::GetMessageCount)
|
||||
.def("__len__", &csd::CAMEvent::size)
|
||||
.def("__iter__", iterator<csd::CAMEvent>())
|
||||
.def("__getitem__", +[](const csd::CAMEvent &self, size_t pos) -> csd::CAMData {
|
||||
return self.at(pos);
|
||||
})
|
||||
;
|
||||
|
||||
class_<csd::CustomV2XEvent, bases<cs::SensorData>, boost::noncopyable, boost::shared_ptr<csd::CustomV2XEvent>>("CustomV2XEvent", no_init)
|
||||
.def("get_message_count", &csd::CustomV2XEvent::GetMessageCount)
|
||||
.def("__len__", &csd::CustomV2XEvent::size)
|
||||
.def("__iter__", iterator<csd::CustomV2XEvent>())
|
||||
.def("__getitem__", +[](const csd::CustomV2XEvent &self, size_t pos) -> csd::CustomV2XData {
|
||||
return self.at(pos);
|
||||
})
|
||||
;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,609 @@
|
|||
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
|
||||
// Karlsruhe Institute of Technology
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include <carla/sensor/data/V2XData.h>
|
||||
#include <carla/sensor/data/LibITS.h>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
/**********************************************************************************************/
|
||||
// Functions to convert CAM message from V2X sensor to python dict
|
||||
std::string GetStationTypeString(const ITSContainer::StationType_t stationType)
|
||||
{
|
||||
switch (stationType)
|
||||
{
|
||||
case ITSContainer::StationType_unknown:
|
||||
return "Uunknown";
|
||||
case ITSContainer::StationType_pedestrian:
|
||||
return "Pedestrian";
|
||||
case ITSContainer::StationType_cyclist:
|
||||
return "Cyclist";
|
||||
case ITSContainer::StationType_moped:
|
||||
return "Moped";
|
||||
case ITSContainer::StationType_motorcycle:
|
||||
return "Motorcycle";
|
||||
case ITSContainer::StationType_passengerCar:
|
||||
return "Passenger Car";
|
||||
case ITSContainer::StationType_bus:
|
||||
return "Bus";
|
||||
case ITSContainer::StationType_lightTruck:
|
||||
return "Light Truck";
|
||||
case ITSContainer::StationType_heavyTruck:
|
||||
return "HeavyTruck";
|
||||
case ITSContainer::StationType_trailer:
|
||||
return "Trailer";
|
||||
case ITSContainer::StationType_specialVehicles:
|
||||
return "Special Vehicle";
|
||||
case ITSContainer::StationType_tram:
|
||||
return "Tram";
|
||||
case ITSContainer::StationType_roadSideUnit:
|
||||
return "Road Side Unit";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
std::string GetSemiConfidenceString(const long confidence)
|
||||
{
|
||||
switch(confidence)
|
||||
{
|
||||
case ITSContainer::SemiAxisLength_oneCentimeter:
|
||||
return "Semi Axis Length One Centimeter";
|
||||
case ITSContainer::SemiAxisLength_outOfRange:
|
||||
return "Semi Axis Length Out Of Range";
|
||||
default:
|
||||
return "Semi Axis Length Unavailable";
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetSemiOrientationString(const long orientation)
|
||||
{
|
||||
switch(orientation)
|
||||
{
|
||||
case ITSContainer::HeadingValue_wgs84North:
|
||||
return "Heading wgs84 North";
|
||||
case ITSContainer::HeadingValue_wgs84East:
|
||||
return "Heading wgs84 East";
|
||||
case ITSContainer::HeadingValue_wgs84South:
|
||||
return "Heading wgs84 South";
|
||||
case ITSContainer::HeadingValue_wgs84West:
|
||||
return "Heading wgs84 West";
|
||||
default:
|
||||
return "Heading Unavailable";
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetAltitudeConfidenceString(ITSContainer::AltitudeConfidence_t altitudeConfidence)
|
||||
{
|
||||
switch(altitudeConfidence)
|
||||
{
|
||||
case ITSContainer::AltitudeConfidence_alt_000_01:
|
||||
return "AltitudeConfidence_alt_000_01";
|
||||
case ITSContainer::AltitudeConfidence_alt_000_02:
|
||||
return "AltitudeConfidence_alt_000_02";
|
||||
case ITSContainer::AltitudeConfidence_alt_000_05:
|
||||
return "AltitudeConfidence_alt_000_05";
|
||||
case ITSContainer::AltitudeConfidence_alt_000_10:
|
||||
return "AltitudeConfidence_alt_000_10";
|
||||
case ITSContainer::AltitudeConfidence_alt_000_20:
|
||||
return "AltitudeConfidence_alt_000_20";
|
||||
case ITSContainer::AltitudeConfidence_alt_000_50:
|
||||
return "AltitudeConfidence_alt_000_50";
|
||||
case ITSContainer::AltitudeConfidence_alt_001_00:
|
||||
return "AltitudeConfidence_alt_001_00";
|
||||
case ITSContainer::AltitudeConfidence_alt_002_00:
|
||||
return "AltitudeConfidence_alt_002_00";
|
||||
case ITSContainer::AltitudeConfidence_alt_005_00:
|
||||
return "AltitudeConfidence_alt_005_00";
|
||||
case ITSContainer::AltitudeConfidence_alt_010_00:
|
||||
return "AltitudeConfidence_alt_010_00";
|
||||
case ITSContainer::AltitudeConfidence_alt_020_00:
|
||||
return "AltitudeConfidence_alt_020_00";
|
||||
case ITSContainer::AltitudeConfidence_alt_050_00:
|
||||
return "AltitudeConfidence_alt_050_00";
|
||||
case ITSContainer::AltitudeConfidence_alt_100_00:
|
||||
return "AltitudeConfidence_alt_100_00";
|
||||
case ITSContainer::AltitudeConfidence_alt_200_00:
|
||||
return "AltitudeConfidence_alt_200_00";
|
||||
case ITSContainer::AltitudeConfidence_outOfRange:
|
||||
return "AltitudeConfidence_alt_outOfRange";
|
||||
default:
|
||||
return "AltitudeConfidence_unavailable";
|
||||
}
|
||||
}
|
||||
static boost::python::dict GetReferenceContainer(const CAM_t message)
|
||||
{
|
||||
boost::python::dict ReferencePosition;
|
||||
ITSContainer::ReferencePosition_t ref = message.cam.camParameters.basicContainer.referencePosition;
|
||||
ReferencePosition["Latitude"] = ref.latitude;
|
||||
ReferencePosition["Longitude"] = ref.longitude;
|
||||
boost::python::dict PosConfidence;
|
||||
PosConfidence["Semi Major Confidence"] = GetSemiConfidenceString(ref.positionConfidenceEllipse.semiMajorConfidence);
|
||||
PosConfidence["Semi Minor Confidence"] = GetSemiConfidenceString(ref.positionConfidenceEllipse.semiMinorConfidence);
|
||||
PosConfidence["Semi Major Orientation"] = GetSemiOrientationString(ref.positionConfidenceEllipse.semiMajorOrientation);
|
||||
ReferencePosition["Position Confidence Eliipse"] = PosConfidence;
|
||||
boost::python::dict Altitude;
|
||||
Altitude["Altitude Value"] = ref.altitude.altitudeValue;
|
||||
Altitude["Altitude Confidence"] = GetAltitudeConfidenceString(ref.altitude.altitudeConfidence);
|
||||
return ReferencePosition;
|
||||
}
|
||||
static boost::python::dict GetBasicContainer(const CAM_t message)
|
||||
{
|
||||
boost::python::dict BasicContainer;
|
||||
BasicContainer["Station Type"] = GetStationTypeString(message.cam.camParameters.basicContainer.stationType);
|
||||
BasicContainer["Reference Position"] = GetReferenceContainer(message);
|
||||
return BasicContainer;
|
||||
}
|
||||
|
||||
std::string GetHeadingConfidenceString(ITSContainer::HeadingConfidence_t confidence)
|
||||
{
|
||||
switch (confidence)
|
||||
{
|
||||
case ITSContainer::HeadingConfidence_equalOrWithinZeroPointOneDegree:
|
||||
return "Equal or With in Zero Point One Degree";
|
||||
case ITSContainer::HeadingConfidence_equalOrWithinOneDegree:
|
||||
return "Equal or With in One Degree";
|
||||
case ITSContainer::HeadingConfidence_outOfRange:
|
||||
return "Out of Range";
|
||||
default:
|
||||
return "Unavailable";
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetSpeedConfidenceString(ITSContainer::SpeedConfidence_t confidence)
|
||||
{
|
||||
switch (confidence)
|
||||
{
|
||||
case ITSContainer::SpeedConfidence_equalOrWithInOneCentimerterPerSec:
|
||||
return "Equal or With in One Centimeter per Sec";
|
||||
case ITSContainer::SpeedConfidence_equalOrWithinOneMeterPerSec:
|
||||
return "Equal or With in One Meter per Sec";
|
||||
case ITSContainer::SpeedConfidence_outOfRange:
|
||||
return "Out of Range";
|
||||
default:
|
||||
return "Unavailable";
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetVehicleLengthConfidenceString(ITSContainer::VehicleLengthConfidenceIndication_t confidence)
|
||||
{
|
||||
switch (confidence)
|
||||
{
|
||||
case ITSContainer::VehicleLengthConfidenceIndication_noTrailerPresent:
|
||||
return "No Trailer Present";
|
||||
case ITSContainer::VehicleLengthConfidenceIndication_trailerPresentWithKnownLength:
|
||||
return "Trailer Present With Known Length";
|
||||
case ITSContainer::VehicleLengthConfidenceIndication_trailerPresentWithUnknownLength:
|
||||
return "Trailer Present With Unknown Length";
|
||||
case ITSContainer::VehicleLengthConfidenceIndication_trailerPresenceIsUnknown:
|
||||
return "Trailer Presence Is Unknown";
|
||||
default:
|
||||
return "Unavailable";
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetAccelerationConfidenceString(ITSContainer::AccelerationConfidence_t confidence)
|
||||
{
|
||||
switch (confidence)
|
||||
{
|
||||
case ITSContainer::AccelerationConfindence_pointOneMeterPerSecSquared:
|
||||
return "Point One Meter Per Sec Squared";
|
||||
case ITSContainer::AccelerationConfidence_outOfRange:
|
||||
return "Out Of Range";
|
||||
default:
|
||||
return "Unavailable";
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetCurvatureConfidenceString(ITSContainer::CurvatureConfidence_t confidence)
|
||||
{
|
||||
switch (confidence)
|
||||
{
|
||||
case ITSContainer::CurvatureConfidence_onePerMeter_0_00002:
|
||||
return "One Per Meter 0_00002";
|
||||
case ITSContainer::CurvatureConfidence_onePerMeter_0_0001:
|
||||
return "One Per Meter 0_0001";
|
||||
case ITSContainer::CurvatureConfidence_onePerMeter_0_0005:
|
||||
return "One Per Meter 0_0005";
|
||||
case ITSContainer::CurvatureConfidence_onePerMeter_0_002:
|
||||
return "One Per Meter 0_002";
|
||||
case ITSContainer::CurvatureConfidence_onePerMeter_0_01:
|
||||
return "One Per Meter 0_01";
|
||||
case ITSContainer::CurvatureConfidence_onePerMeter_0_1:
|
||||
return "One Per Meter 0_1";
|
||||
case ITSContainer::CurvatureConfidence_outOfRange:
|
||||
return "Out Of Range";
|
||||
default:
|
||||
return "Unavailable";
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetYawRateConfidenceString(ITSContainer::YawRateConfidence_t confidence)
|
||||
{
|
||||
switch (confidence)
|
||||
{
|
||||
case ITSContainer::YawRateConfidence_degSec_000_01:
|
||||
return "degSec 000_01";
|
||||
case ITSContainer::YawRateConfidence_degSec_000_05:
|
||||
return "degSec 000_05";
|
||||
case ITSContainer::YawRateConfidence_degSec_000_10:
|
||||
return "degSec 000_10";
|
||||
case ITSContainer::YawRateConfidence_degSec_001_00:
|
||||
return "degSec 001_00";
|
||||
case ITSContainer::YawRateConfidence_degSec_005_00:
|
||||
return "degSec 005_00";
|
||||
case ITSContainer::YawRateConfidence_degSec_010_00:
|
||||
return "degSec 010_00";
|
||||
case ITSContainer::YawRateConfidence_degSec_100_00:
|
||||
return "degSec 100_00";
|
||||
case ITSContainer::YawRateConfidence_outOfRange:
|
||||
return "Out Of Range";
|
||||
default:
|
||||
return "Unavailable";
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetSteeringWheelConfidenceString(ITSContainer::SteeringWheelAngleConfidence_t confidence)
|
||||
{
|
||||
switch (confidence)
|
||||
{
|
||||
case ITSContainer::SteeringWheelAngleConfidence_equalOrWithinOnePointFiveDegree:
|
||||
return "Equal or With in 1.5 degree";
|
||||
case ITSContainer::SteeringWheelAngleConfidence_outOfRange:
|
||||
return "Out of Range";
|
||||
default:
|
||||
return "Unavailable";
|
||||
}
|
||||
}
|
||||
|
||||
static boost::python::dict GetBVCHighFrequency(const CAM_t message)
|
||||
{
|
||||
boost::python::dict BVCHighFrequency;
|
||||
CAMContainer::BasicVehicleContainerHighFrequency_t bvchf = message.cam.camParameters.highFrequencyContainer.basicVehicleContainerHighFrequency;
|
||||
boost::python::dict HeadingValueConfidence;
|
||||
HeadingValueConfidence["Value"] = bvchf.heading.headingValue;
|
||||
HeadingValueConfidence["Confidence"] = GetHeadingConfidenceString(bvchf.heading.headingConfidence);
|
||||
BVCHighFrequency["Heading"] = HeadingValueConfidence;
|
||||
boost::python::dict SpeedValueConfidence;
|
||||
SpeedValueConfidence["Value"] = bvchf.speed.speedValue;
|
||||
SpeedValueConfidence["Confidence"] = GetSpeedConfidenceString(bvchf.speed.speedConfidence);
|
||||
BVCHighFrequency["Speed"] = SpeedValueConfidence;
|
||||
|
||||
BVCHighFrequency["Drive Direction"] = bvchf.driveDirection;
|
||||
|
||||
boost::python::dict VehicleLengthValueConfidence;
|
||||
VehicleLengthValueConfidence["Value"] = bvchf.vehicleLength.vehicleLengthValue;
|
||||
VehicleLengthValueConfidence["Confidence"] = GetVehicleLengthConfidenceString(bvchf.vehicleLength.vehicleLengthConfidenceIndication);
|
||||
BVCHighFrequency["Vehicle Length"] = VehicleLengthValueConfidence;
|
||||
|
||||
BVCHighFrequency["Vehicle Width"] = bvchf.vehicleWidth;
|
||||
|
||||
boost::python::dict LongitudinalAccelerationValueConfidence;
|
||||
LongitudinalAccelerationValueConfidence["Value"] = bvchf.longitudinalAcceleration.longitudinalAccelerationValue;
|
||||
LongitudinalAccelerationValueConfidence["Confidence"] = GetAccelerationConfidenceString(bvchf.longitudinalAcceleration.longitudinalAccelerationConfidence);
|
||||
BVCHighFrequency["Longitudinal Acceleration"] = LongitudinalAccelerationValueConfidence;
|
||||
|
||||
boost::python::dict CurvatureValueConfidence;
|
||||
CurvatureValueConfidence["Value"] = bvchf.curvature.curvatureValue;
|
||||
CurvatureValueConfidence["Confidence"] = GetCurvatureConfidenceString(bvchf.curvature.curvatureConfidence);
|
||||
BVCHighFrequency["Curvature"] = CurvatureValueConfidence;
|
||||
BVCHighFrequency["Curvature Calculation Mode"] = bvchf.curvatureCalculationMode;
|
||||
|
||||
boost::python::dict YawValueConfidence;
|
||||
YawValueConfidence["Value"] = bvchf.yawRate.yawRateValue;
|
||||
YawValueConfidence["Confidence"] = GetYawRateConfidenceString(bvchf.yawRate.yawRateConfidence);
|
||||
BVCHighFrequency["Yaw Rate"] = YawValueConfidence;
|
||||
|
||||
boost::python::dict ValueConfidence;
|
||||
if (bvchf.accelerationControlAvailable)
|
||||
{
|
||||
BVCHighFrequency["Acceleration Control"] = bvchf.accelerationControl;
|
||||
}
|
||||
else
|
||||
{
|
||||
BVCHighFrequency["Acceleration Control"] = boost::python::object();
|
||||
}
|
||||
|
||||
if (bvchf.lanePositionAvailable)
|
||||
{
|
||||
BVCHighFrequency["Lane Position"] = bvchf.lanePosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
BVCHighFrequency["Lane Position"] = boost::python::object();
|
||||
}
|
||||
|
||||
if (bvchf.steeringWheelAngleAvailable)
|
||||
{
|
||||
boost::python::dict ValueConfidence;
|
||||
ValueConfidence["Value"] = bvchf.steeringWheelAngle.steeringWheelAngleValue;
|
||||
ValueConfidence["Confidence"] = GetSteeringWheelConfidenceString(bvchf.steeringWheelAngle.steeringWheelAngleConfidence);
|
||||
BVCHighFrequency["Steering Wheel Angle"] = ValueConfidence;
|
||||
}
|
||||
else
|
||||
{
|
||||
BVCHighFrequency["Steering Wheel Angle"] = boost::python::object();
|
||||
}
|
||||
|
||||
if (bvchf.lateralAccelerationAvailable)
|
||||
{
|
||||
boost::python::dict ValueConfidence;
|
||||
ValueConfidence["Value"] = bvchf.lateralAcceleration.lateralAccelerationValue;
|
||||
ValueConfidence["Confidence"] = GetAccelerationConfidenceString(bvchf.lateralAcceleration.lateralAccelerationConfidence);
|
||||
BVCHighFrequency["Lateral Acceleration"] = ValueConfidence;
|
||||
}
|
||||
else
|
||||
{
|
||||
BVCHighFrequency["Lateral Acceleration"] = boost::python::object();
|
||||
}
|
||||
|
||||
if (bvchf.verticalAccelerationAvailable)
|
||||
{
|
||||
boost::python::dict ValueConfidence;
|
||||
ValueConfidence["Value"] = bvchf.verticalAcceleration.verticalAccelerationValue;
|
||||
ValueConfidence["Confidence"] = GetAccelerationConfidenceString(bvchf.verticalAcceleration.verticalAccelerationConfidence);
|
||||
BVCHighFrequency["Vertical Acceleration"] = ValueConfidence;
|
||||
}
|
||||
else
|
||||
{
|
||||
BVCHighFrequency["Vertical Acceleration"] = boost::python::object();
|
||||
}
|
||||
|
||||
if (bvchf.performanceClassAvailable)
|
||||
{
|
||||
BVCHighFrequency["Performance class"] = bvchf.performanceClass;
|
||||
}
|
||||
else
|
||||
{
|
||||
BVCHighFrequency["Performance class"] = boost::python::object();
|
||||
}
|
||||
|
||||
if (bvchf.cenDsrcTollingZoneAvailable)
|
||||
{
|
||||
boost::python::dict ValueConfidence;
|
||||
ValueConfidence["Protected Zone Latitude"] = bvchf.cenDsrcTollingZone.protectedZoneLatitude;
|
||||
ValueConfidence["Protected Zone Longitude"] = bvchf.cenDsrcTollingZone.protectedZoneLongitude;
|
||||
if (bvchf.cenDsrcTollingZone.cenDsrcTollingZoneIDAvailable)
|
||||
{
|
||||
ValueConfidence["Cen DSRC Tolling Zone ID"] = bvchf.cenDsrcTollingZone.cenDsrcTollingZoneID;
|
||||
}
|
||||
BVCHighFrequency["Cen DSRC Tolling Zone"] = ValueConfidence;
|
||||
}
|
||||
else
|
||||
{
|
||||
BVCHighFrequency["Cen DSRC Tolling Zone"] = boost::python::object();
|
||||
}
|
||||
|
||||
return BVCHighFrequency;
|
||||
}
|
||||
|
||||
static boost::python::list GetProtectedCommunicationZone(const CAMContainer::RSUContainerHighFrequency_t rsuMessage)
|
||||
{
|
||||
boost::python::list PCZlist;
|
||||
|
||||
for (ITSContainer::ProtectedCommunicationZone_t data : rsuMessage.protectedCommunicationZonesRSU.list)
|
||||
{
|
||||
boost::python::dict PCZDict;
|
||||
PCZDict["Protected Zone Type"] = data.protectedZoneType;
|
||||
if (data.expiryTimeAvailable)
|
||||
{
|
||||
PCZDict["Expiry Time"] = data.expiryTime;
|
||||
}
|
||||
|
||||
PCZDict["Protected Zone Latitude"] = data.protectedZoneLatitude;
|
||||
PCZDict["Protected Zone Longitude"] = data.protectedZoneLongitude;
|
||||
|
||||
if (data.protectedZoneIDAvailable)
|
||||
{
|
||||
PCZDict["Protected Zone ID"] = data.protectedZoneID;
|
||||
}
|
||||
if (data.protectedZoneRadiusAvailable)
|
||||
{
|
||||
PCZDict["Protected Zone Radius"] = data.protectedZoneRadius;
|
||||
}
|
||||
|
||||
PCZlist.append(PCZDict);
|
||||
}
|
||||
return PCZlist;
|
||||
}
|
||||
static boost::python::dict GetRSUHighFrequency(const CAM_t message)
|
||||
{
|
||||
boost::python::dict RSU;
|
||||
CAMContainer::RSUContainerHighFrequency_t rsu = message.cam.camParameters.highFrequencyContainer.rsuContainerHighFrequency;
|
||||
RSU["Protected Communication Zone"] = GetProtectedCommunicationZone(rsu);
|
||||
return RSU;
|
||||
}
|
||||
|
||||
static boost::python::dict GetHighFrequencyContainer(const CAM_t message)
|
||||
{
|
||||
boost::python::dict HFC;
|
||||
CAMContainer::HighFrequencyContainer_t hfc = message.cam.camParameters.highFrequencyContainer;
|
||||
switch (hfc.present)
|
||||
{
|
||||
case CAMContainer::HighFrequencyContainer_PR_basicVehicleContainerHighFrequency:
|
||||
HFC["High Frequency Container Present"] = "Basic Vehicle Container High Frequency";
|
||||
HFC["Basic Vehicle Container High Frequency"] = GetBVCHighFrequency(message);
|
||||
break;
|
||||
case CAMContainer::HighFrequencyContainer_PR_rsuContainerHighFrequency:
|
||||
HFC["High Frequency Container Present"] = "RSU Container High Frequency";
|
||||
HFC["RSU Container High Frequency"] = GetRSUHighFrequency(message);
|
||||
break;
|
||||
default:
|
||||
HFC["High Frequency Container Present"] = "No container present";
|
||||
}
|
||||
return HFC;
|
||||
}
|
||||
std::string GetVehicleRoleString(ITSContainer::VehicleRole_t vehicleRole)
|
||||
{
|
||||
switch (vehicleRole)
|
||||
{
|
||||
case ITSContainer::VehicleRole_publicTransport:
|
||||
return "Public Transport";
|
||||
case ITSContainer::VehicleRole_specialTransport:
|
||||
return "Special Transport";
|
||||
case ITSContainer::VehicleRole_dangerousGoods:
|
||||
return "Dangerous Goods";
|
||||
case ITSContainer::VehicleRole_roadWork:
|
||||
return "Road Work";
|
||||
case ITSContainer::VehicleRole_rescue:
|
||||
return "Rescue";
|
||||
case ITSContainer::VehicleRole_emergency:
|
||||
return "Emergency";
|
||||
case ITSContainer::VehicleRole_safetyCar:
|
||||
return "Safety Car";
|
||||
case ITSContainer::VehicleRole_agriculture:
|
||||
return "Agriculture";
|
||||
case ITSContainer::VehicleRole_commercial:
|
||||
return "Commercial";
|
||||
case ITSContainer::VehicleRole_military:
|
||||
return "Military";
|
||||
case ITSContainer::VehicleRole_roadOperator:
|
||||
return "Road Operator";
|
||||
case ITSContainer::VehicleRole_taxi:
|
||||
return "Taxi";
|
||||
case ITSContainer::VehicleRole_reserved1:
|
||||
return "Reserved 1";
|
||||
case ITSContainer::VehicleRole_reserved2:
|
||||
return "Reserved 2";
|
||||
case ITSContainer::VehicleRole_reserved3:
|
||||
return "Reserved 3";
|
||||
default:
|
||||
return "Default";
|
||||
}
|
||||
}
|
||||
|
||||
boost::python::list GetPathHistory(const ITSContainer::PathHistory_t pathHistory)
|
||||
{
|
||||
|
||||
boost::python::list PathHistoryList;
|
||||
for (ITSContainer::PathPoint_t pathPoint : pathHistory.data)
|
||||
{
|
||||
boost::python::dict PathHistory;
|
||||
PathHistory["Delta Latitude"] = pathPoint.pathPosition.deltaLatitude;
|
||||
PathHistory["Delta Longitude"] = pathPoint.pathPosition.deltaLongitude;
|
||||
PathHistory["Delta Altitude"] = pathPoint.pathPosition.deltaAltitude;
|
||||
if (pathPoint.pathDeltaTime != nullptr)
|
||||
{
|
||||
PathHistory["Delta Time"] = *pathPoint.pathDeltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
PathHistory["Delta Time"] = boost::python::object();
|
||||
}
|
||||
PathHistoryList.append(PathHistory);
|
||||
}
|
||||
return PathHistoryList;
|
||||
}
|
||||
boost::python::dict GetBVCLowFrequency(const CAMContainer::BasicVehicleContainerLowFrequency_t bvc)
|
||||
{
|
||||
boost::python::dict BVC;
|
||||
BVC["Vehicle Role"] = GetVehicleRoleString(bvc.vehicleRole);
|
||||
BVC["Exterior Light"] = bvc.exteriorLights;
|
||||
if (bvc.pathHistory.NumberOfPathPoint != 0)
|
||||
{
|
||||
BVC["Path History"] = GetPathHistory(bvc.pathHistory);
|
||||
}
|
||||
else
|
||||
{
|
||||
BVC["Path History"] = boost::python::object();
|
||||
}
|
||||
return BVC;
|
||||
}
|
||||
|
||||
boost::python::dict GetLowFrequencyContainer(const CAM_t message)
|
||||
{
|
||||
boost::python::dict LFC = boost::python::dict();
|
||||
CAMContainer::LowFrequencyContainer_t lfc = message.cam.camParameters.lowFrequencyContainer;
|
||||
switch (lfc.present)
|
||||
{
|
||||
case CAMContainer::LowFrequencyContainer_PR_basicVehicleContainerLowFrequency:
|
||||
LFC["Low Frequency Container Present"] = "Basic Vehicle Container Low Frequency";
|
||||
LFC["Basic Vehicle Low Frequency"] = GetBVCLowFrequency(lfc.basicVehicleContainerLowFrequency);
|
||||
break;
|
||||
default:
|
||||
LFC["Low Frequency Container Present"] = "No Container Present";
|
||||
break;
|
||||
}
|
||||
return LFC;
|
||||
}
|
||||
static boost::python::dict GetCAMParameters(const CAM_t message)
|
||||
{
|
||||
boost::python::dict CAMParams;
|
||||
try
|
||||
{
|
||||
|
||||
CAMParams["Basic Container"] = GetBasicContainer(message);
|
||||
CAMParams["High Frequency Container"] = GetHighFrequencyContainer(message);
|
||||
CAMParams["Low Frequency Container"] = GetLowFrequencyContainer(message);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
std::cerr << e.what() << '\n';
|
||||
}
|
||||
return CAMParams;
|
||||
}
|
||||
|
||||
static boost::python::dict GetCoopAwarness(const CAM_t message)
|
||||
{
|
||||
|
||||
boost::python::dict Coop;
|
||||
CAMContainer::CoopAwareness_t coop = message.cam;
|
||||
Coop["Generation Delta Time"] = coop.generationDeltaTime;
|
||||
Coop["CAM Parameters"] = GetCAMParameters(message);
|
||||
return Coop;
|
||||
}
|
||||
|
||||
std::string GetMessageIDString(const long messageId)
|
||||
{
|
||||
switch (messageId)
|
||||
{
|
||||
case ITSContainer::messageID_custom:
|
||||
return "CUSTOM";
|
||||
case ITSContainer::messageID_denm:
|
||||
return "DENM";
|
||||
case ITSContainer::messageID_cam:
|
||||
return "CAM";
|
||||
case ITSContainer::messageID_poi:
|
||||
return "POI";
|
||||
case ITSContainer::messageID_spat:
|
||||
return "SPAT";
|
||||
case ITSContainer::messageID_map:
|
||||
return "MAP";
|
||||
case ITSContainer::messageID_ivi:
|
||||
return "IVI";
|
||||
case ITSContainer::messageID_ev_rsr:
|
||||
return "EV_RSR";
|
||||
default:
|
||||
return "Not Found";
|
||||
}
|
||||
}
|
||||
|
||||
static boost::python::dict GetMessageHeader(const ITSContainer::ItsPduHeader_t header)
|
||||
{
|
||||
boost::python::dict Header;
|
||||
Header["Protocol Version"] = header.protocolVersion;
|
||||
Header["Message ID"] = GetMessageIDString(header.messageID);
|
||||
Header["Station ID"] = header.stationID;
|
||||
return Header;
|
||||
}
|
||||
|
||||
boost::python::dict GetCAMMessage(const carla::sensor::data::CAMData message)
|
||||
{
|
||||
boost::python::dict CAM;
|
||||
CAM_t CAMMessage = message.Message;
|
||||
CAM["Header"] = GetMessageHeader(CAMMessage.header);
|
||||
CAM["Message"] = GetCoopAwarness(CAMMessage);
|
||||
return CAM;
|
||||
}
|
||||
|
||||
boost::python::dict GetCustomV2XMessage(const carla::sensor::data::CustomV2XData message)
|
||||
{
|
||||
boost::python::dict CustomV2X;
|
||||
CustomV2XM V2XMessage = message.Message;
|
||||
CustomV2X["Header"] = GetMessageHeader(V2XMessage.header);
|
||||
CustomV2X["Message"] = std::string(V2XMessage.message);
|
||||
return CustomV2X;
|
||||
}
|
|
@ -216,6 +216,7 @@ static auto MakeCallback(boost::python::object callback) {
|
|||
};
|
||||
}
|
||||
|
||||
#include "V2XData.cpp"
|
||||
#include "Geom.cpp"
|
||||
#include "Actor.cpp"
|
||||
#include "Blueprint.cpp"
|
||||
|
|
|
@ -352,12 +352,12 @@
|
|||
- param_name: folder
|
||||
type: str
|
||||
doc: >
|
||||
Folder where files required by the client will be downloaded to.
|
||||
Specifies a folder to look through on the server maps. Leaving this blank will search recursively through all map folders in the server, which is recommended if you're unfamiliar with the server map folder structure.
|
||||
- param_name: download
|
||||
type: bool
|
||||
default: True
|
||||
doc: >
|
||||
If True, downloads files that are not already in cache.
|
||||
If True, downloads files that are not already in cache. The cache can be found at "HOME\carlaCache" or "USERPROFILE\carlaCache", depending on OS.
|
||||
doc: >
|
||||
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.
|
||||
# --------------------------------------
|
||||
|
|
|
@ -8,28 +8,28 @@
|
|||
doc: >
|
||||
Sensors compound a specific family of actors quite diverse and unique. They are normally spawned as attachment/sons of a vehicle (take a look at carla.World to learn about actor spawning). Sensors are thoroughly designed to retrieve different types of data that they are listening to. The data they receive is shaped as different subclasses inherited from carla.SensorData (depending on the sensor).
|
||||
|
||||
Most sensors can be divided in two groups: those receiving data on every tick (cameras, point clouds and some specific sensors) and those who only receive under certain circumstances (trigger detectors). CARLA provides a specific set of sensors and their blueprint can be found in carla.BlueprintLibrary. All the information on their preferences and settlement can be found [here](ref_sensors.md), but the list of those available in CARLA so far goes as follow.
|
||||
<br><b>Receive data on every tick.</b>
|
||||
- [Depth camera](ref_sensors.md#depth-camera).
|
||||
- [Gnss sensor](ref_sensors.md#gnss-sensor).
|
||||
- [IMU sensor](ref_sensors.md#imu-sensor).
|
||||
- [Lidar raycast](ref_sensors.md#lidar-raycast-sensor).
|
||||
- [SemanticLidar raycast](ref_sensors.md#semanticlidar-raycast-sensor).
|
||||
- [Radar](ref_sensors.md#radar-sensor).
|
||||
- [RGB camera](ref_sensors.md#rgb-camera).
|
||||
- [RSS sensor](ref_sensors.md#rss-sensor).
|
||||
- [Semantic Segmentation camera](ref_sensors.md#semantic-segmentation-camera).
|
||||
<br><b>Only receive data when triggered.</b>
|
||||
- [Collision detector](ref_sensors.md#collision-detector).
|
||||
- [Lane invasion detector](ref_sensors.md#lane-invasion-detector).
|
||||
- [Obstacle detector](ref_sensors.md#obstacle-detector).
|
||||
|
||||
Most sensors can be divided in two groups: those receiving data on every tick (cameras, point clouds and some specific sensors) and those who only receive under certain circumstances (trigger detectors). CARLA provides a specific set of sensors and their blueprint can be found in carla.BlueprintLibrary. All the information on their preferences and settlement can be found [here](ref_sensors.md), but the list of those available in CARLA so far goes as follows:<br>
|
||||
<br><b>Receive data on every tick</b><br>
|
||||
- [Depth camera](ref_sensors.md#depth-camera)<br>
|
||||
- [Gnss sensor](ref_sensors.md#gnss-sensor)<br>
|
||||
- [IMU sensor](ref_sensors.md#imu-sensor)<br>
|
||||
- [Lidar raycast](ref_sensors.md#lidar-raycast-sensor)<br>
|
||||
- [SemanticLidar raycast](ref_sensors.md#semanticlidar-raycast-sensor)<br>
|
||||
- [Radar](ref_sensors.md#radar-sensor)<br>
|
||||
- [RGB camera](ref_sensors.md#rgb-camera)<br>
|
||||
- [RSS sensor](ref_sensors.md#rss-sensor)<br>
|
||||
- [Semantic Segmentation camera](ref_sensors.md#semantic-segmentation-camera)<br>
|
||||
<br><b>Only receive data when triggered.</b><br>
|
||||
- [Collision detector](ref_sensors.md#collision-detector)<br>
|
||||
- [Lane invasion detector](ref_sensors.md#lane-invasion-detector)<br>
|
||||
- [Obstacle detector](ref_sensors.md#obstacle-detector)<br>
|
||||
- [V2X sensor](ref_sensors.md#v2x-sensor)
|
||||
# - PROPERTIES -------------------------
|
||||
instance_variables:
|
||||
- var_name: is_listening
|
||||
type: boolean
|
||||
doc: >
|
||||
When <b>True</b> the sensor will be waiting for data.
|
||||
When **True** the sensor will be waiting for data.
|
||||
# - METHODS ----------------------------
|
||||
methods:
|
||||
- def_name: listen
|
||||
|
@ -44,6 +44,8 @@
|
|||
- def_name: is_listening
|
||||
doc: >
|
||||
Returns whether the sensor is in a listening state.
|
||||
return:
|
||||
bool
|
||||
# --------------------------------------
|
||||
- def_name: stop
|
||||
doc: >
|
||||
|
@ -60,6 +62,8 @@
|
|||
- def_name: is_enabled_for_ros
|
||||
doc: >
|
||||
Returns if the sensor is enabled or not to publish in ROS2 if there is no any listen to it.
|
||||
return:
|
||||
bool
|
||||
# --------------------------------------
|
||||
- def_name: listen_to_gbuffer
|
||||
params:
|
||||
|
@ -83,6 +87,8 @@
|
|||
The ID of the target Unreal Engine GBuffer texture.
|
||||
doc: >
|
||||
Returns whether the sensor is in a listening state for a specific GBuffer texture.
|
||||
return:
|
||||
bool
|
||||
# --------------------------------------
|
||||
- def_name: stop_gbuffer
|
||||
params:
|
||||
|
@ -93,6 +99,15 @@
|
|||
doc: >
|
||||
Commands the sensor to stop listening for the specified GBuffer texture.
|
||||
# --------------------------------------
|
||||
- def_name: send
|
||||
params:
|
||||
- param_name: message
|
||||
type: string
|
||||
doc: >
|
||||
The data to send. Note: maximum string length is 100 chars.
|
||||
doc: >
|
||||
Instructs the sensor to send the string given by `message` to all other CustomV2XSensors on the next tick.
|
||||
# --------------------------------------
|
||||
- def_name: __str__
|
||||
# --------------------------------------
|
||||
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
- Obstacle detector: carla.ObstacleDetectionEvent.<br>
|
||||
- Radar sensor: carla.RadarMeasurement.<br>
|
||||
- RSS sensor: carla.RssResponse.<br>
|
||||
- Semantic LIDAR sensor: carla.SemanticLidarMeasurement.
|
||||
- Semantic LIDAR sensor: carla.SemanticLidarMeasurement.<br>
|
||||
- Cooperative awareness messages V2X sensor: carla.CAMEvent.<br>
|
||||
- Custom V2X messages V2X sensor: carla.CustomV2XEvent.
|
||||
# - PROPERTIES -------------------------
|
||||
instance_variables:
|
||||
- var_name: frame
|
||||
|
@ -878,7 +880,7 @@
|
|||
- class_name: GBufferTextureID
|
||||
# - DESCRIPTION ------------------------
|
||||
doc: >
|
||||
Defines the identifiers of each GBuffer texture (See the method `carla.Sensor.listen_to_gbuffer`).
|
||||
Defines the of each GBuffer texture (See the method `carla.Sensor.listen_to_gbuffer`).
|
||||
# - PROPERTIES -------------------------
|
||||
instance_variables:
|
||||
- var_name: SceneColor
|
||||
|
@ -941,4 +943,110 @@
|
|||
The texture "CustomStencil" contains the Unreal Engine custom stencil data.
|
||||
# --------------------------------------
|
||||
|
||||
|
||||
- class_name: CAMData
|
||||
parent: carla.SensorData
|
||||
# - DESCRIPTION ------------------------
|
||||
doc: >
|
||||
This is the data type for cooperative awareness message reception, contained in a [CAMEvent](#carlacamevent)
|
||||
# - PROPERTIES -------------------------
|
||||
instance_variables:
|
||||
- var_name: power
|
||||
type: float - dBm
|
||||
doc: >
|
||||
Received power.
|
||||
|
||||
# - METHODS ----------------------------
|
||||
# --------------------------------------
|
||||
methods:
|
||||
- def_name: get
|
||||
return: dict
|
||||
doc: >
|
||||
Get the CAM data. Returns a nested dictionary containing the message following the ETSI standard: - `Header`: dict - `Message`: dict
|
||||
# --------------------------------------
|
||||
- def_name: __str__
|
||||
# --------------------------------------
|
||||
|
||||
- class_name: CAMEvent
|
||||
parent: carla.SensorData
|
||||
# - DESCRIPTION ------------------------
|
||||
doc: >
|
||||
Class that defines the data provided by a **sensor.other.v2x**. This is a collection type to combine returning several [CAMData](#carlacamdata).
|
||||
# - PROPERTIES -------------------------
|
||||
instance_variables:
|
||||
|
||||
# - METHODS ----------------------------
|
||||
# --------------------------------------
|
||||
methods:
|
||||
- def_name: get_message_count
|
||||
return: int
|
||||
doc: >
|
||||
Get the number of received CAM's.
|
||||
# --------------------------------------
|
||||
- def_name: __get_item__
|
||||
params:
|
||||
- param_name: pos
|
||||
type: int
|
||||
# --------------------------------------
|
||||
- def_name: __iter__
|
||||
doc: >
|
||||
Iterate over the [CAMData](#carlacamdata) retrieved as data.
|
||||
# --------------------------------------
|
||||
- def_name: __len__
|
||||
# --------------------------------------
|
||||
|
||||
|
||||
- class_name: CustomV2XEvent
|
||||
parent: carla.SensorData
|
||||
# - DESCRIPTION ------------------------
|
||||
doc: >
|
||||
Class that defines the data provided by a **sensor.other.v2x_custom**. This is a collection type to combine returning several [CustomV2XData](#carlacustomv2xdata).
|
||||
# - PROPERTIES -------------------------
|
||||
instance_variables:
|
||||
|
||||
# - METHODS ----------------------------
|
||||
# --------------------------------------
|
||||
methods:
|
||||
- def_name: get_message_count
|
||||
return: int
|
||||
doc: >
|
||||
Get the number of received CAM's.
|
||||
# --------------------------------------
|
||||
- def_name: __get_item__
|
||||
params:
|
||||
- param_name: pos
|
||||
type: int
|
||||
# --------------------------------------
|
||||
- def_name: __iter__
|
||||
doc: >
|
||||
Iterate over the [CustomV2XData](#carlacustomv2xdata) retrieved as data.
|
||||
# --------------------------------------
|
||||
- def_name: __len__
|
||||
# --------------------------------------
|
||||
|
||||
|
||||
- class_name: CustomV2XData
|
||||
parent: carla.SensorData
|
||||
# - DESCRIPTION ------------------------
|
||||
doc: >
|
||||
This is the data type defining a custom V2X message. Received as part of a [CustomV2XEvent](#carlacustomv2xevent).
|
||||
# - PROPERTIES -------------------------
|
||||
instance_variables:
|
||||
- var_name: power
|
||||
type: float - dBm
|
||||
doc: >
|
||||
Received power.
|
||||
|
||||
# - METHODS ----------------------------
|
||||
# --------------------------------------
|
||||
methods:
|
||||
- def_name: get
|
||||
return: dict
|
||||
doc: >
|
||||
Get the custom message. Returns a nested dictionary containing the message. It has two primary keys: - `Header` : dict - `Message`: str
|
||||
# --------------------------------------
|
||||
- def_name: __str__
|
||||
# --------------------------------------
|
||||
|
||||
|
||||
...
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -279,8 +279,11 @@ def main():
|
|||
for spawn_point in spawn_points:
|
||||
walker_bp = random.choice(blueprintsWalkers)
|
||||
# set as not invincible
|
||||
probability = random.randint(0,100 + 1);
|
||||
if walker_bp.has_attribute('is_invincible'):
|
||||
walker_bp.set_attribute('is_invincible', 'false')
|
||||
if walker_bp.has_attribute('can_use_wheelchair') and probability < 11:
|
||||
walker_bp.set_attribute('use_wheelchair', 'true')
|
||||
# set the max speed
|
||||
if walker_bp.has_attribute('speed'):
|
||||
if (random.random() > percentagePedestriansRunning):
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
import glob
|
||||
import os
|
||||
import sys
|
||||
|
||||
try:
|
||||
sys.path.append(glob.glob('../carla/dist/carla-0.9.15-py*%d.%d-%s.egg' % (
|
||||
sys.version_info.major,
|
||||
sys.version_info.minor,
|
||||
'win-amd64' if os.name == 'nt' else 'linux-x86_64'))[0])
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
import carla
|
||||
import random
|
||||
import weakref
|
||||
|
||||
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]:
|
||||
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 []
|
||||
|
||||
class V2XSensor(object):
|
||||
def __init__(self, parent_actor):
|
||||
self.sensor = None
|
||||
self._parent = parent_actor
|
||||
world = self._parent.get_world()
|
||||
#bp = world.get_blueprint_library().find('sensor.other.v2x_custom')
|
||||
bp = world.get_blueprint_library().find('sensor.other.v2x')
|
||||
self.sensor = world.spawn_actor(
|
||||
bp, carla.Transform(), attach_to=self._parent)
|
||||
# We need to pass the lambda a weak reference to self to avoid circular
|
||||
# reference.
|
||||
weak_self = weakref.ref(self)
|
||||
self.sensor.listen(
|
||||
lambda sensor_data: V2XSensor._V2X_callback(weak_self, sensor_data))
|
||||
|
||||
def destroy(self):
|
||||
self.sensor.stop()
|
||||
self.sensor.destroy()
|
||||
|
||||
@staticmethod
|
||||
def _V2X_callback(weak_self, sensor_data):
|
||||
self = weak_self()
|
||||
if not self:
|
||||
return
|
||||
for data in sensor_data:
|
||||
msg = data.get()
|
||||
# stationId = msg["Header"]["Station ID"]
|
||||
power = data.power
|
||||
print(msg)
|
||||
# print('Cam message received from %s ' % stationId)
|
||||
print('Cam message received with power %f ' % power)
|
||||
|
||||
client = carla.Client("localhost",2000)
|
||||
client.set_timeout(2000.0)
|
||||
|
||||
world = client.get_world()
|
||||
smap = world.get_map()
|
||||
# acl = world.get_actor(28)
|
||||
# acl.send("test")
|
||||
|
||||
|
||||
spawn_points = smap.get_spawn_points()
|
||||
spawn_point = random.choice(spawn_points) if spawn_points else carla.Transform()
|
||||
blueprint = random.choice(get_actor_blueprints(world, "vehicle.*", "2"))
|
||||
blueprint.set_attribute('role_name', "test")
|
||||
player = world.try_spawn_actor(blueprint, spawn_point)
|
||||
v2x_sensor = V2XSensor(player)
|
||||
|
||||
world.wait_for_tick()
|
||||
try:
|
||||
while True:
|
||||
world.wait_for_tick()
|
||||
finally:
|
||||
v2x_sensor.destroy()
|
||||
player.destroy()
|
|
@ -38,7 +38,9 @@ class TestSensorTickTime(SyncSmokeTest):
|
|||
"sensor.camera.semantic_segmentation",
|
||||
"sensor.camera.dvs",
|
||||
"sensor.other.obstacle",
|
||||
"sensor.camera.instance_segmentation"
|
||||
"sensor.camera.instance_segmentation",
|
||||
"sensor.other.v2x",
|
||||
"sensor.other.v2x_custom"
|
||||
}
|
||||
spawned_sensors = []
|
||||
sensor_tick = 1.0
|
||||
|
@ -64,5 +66,3 @@ class TestSensorTickTime(SyncSmokeTest):
|
|||
self.assertEqual(sensor.num_ticks, num_sensor_ticks,
|
||||
"\n\n {} does not match tick count".format(sensor.bp_sensor.id))
|
||||
sensor.destroy()
|
||||
|
||||
|
||||
|
|
|
@ -19,12 +19,12 @@ environmental conditions.
|
|||
### Download CARLA
|
||||
|
||||
Linux:
|
||||
* [**Get CARLA overnight build**](https://carla-releases.s3.us-east-005.backblazeb2.com/Linux/Dev/CARLA_Latest.tar.gz)
|
||||
* [**Get AdditionalMaps overnight build**](https://carla-releases.s3.us-east-005.backblazeb2.com/Linux/Dev/AdditionalMaps_Latest.tar.gz)
|
||||
* [**Get CARLA overnight build**](https://tiny.carla.org/carla-latest-linux)
|
||||
* [**Get AdditionalMaps overnight build**](https://tiny.carla.org/additional-maps-latest-linux)
|
||||
|
||||
Windows:
|
||||
* [**Get CARLA overnight build**](https://carla-releases.s3.us-east-005.backblazeb2.com/Windows/Dev/CARLA_Latest.zip)
|
||||
* [**Get AdditionalMaps overnight build**](https://carla-releases.s3.us-east-005.backblazeb2.com/Windows/Dev/AdditionalMaps_Latest.zip)
|
||||
* [**Get CARLA overnight build**](https://tiny.carla.org/carla-latest-windows)
|
||||
* [**Get AdditionalMaps overnight build**](https://tiny.carla.org/additional-maps-latest-windows)
|
||||
|
||||
### Recommended system
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[/Script/UnrealEd.EditorPerformanceSettings]
|
||||
bThrottleCPUWhenNotForeground=False
|
|
@ -10,6 +10,7 @@
|
|||
#include "Carla/Sensor/LidarDescription.h"
|
||||
#include "Carla/Sensor/SceneCaptureSensor.h"
|
||||
#include "Carla/Sensor/ShaderBasedSensor.h"
|
||||
#include "Carla/Sensor/V2X/PathLossModel.h"
|
||||
#include "Carla/Util/ScopedStack.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -1014,6 +1015,351 @@ void UActorBlueprintFunctionLibrary::MakeLidarDefinition(
|
|||
Success = CheckActorDefinition(Definition);
|
||||
}
|
||||
|
||||
FActorDefinition UActorBlueprintFunctionLibrary::MakeV2XDefinition()
|
||||
{
|
||||
FActorDefinition Definition;
|
||||
bool Success;
|
||||
MakeV2XDefinition(Success, Definition);
|
||||
check(Success);
|
||||
return Definition;
|
||||
}
|
||||
|
||||
void UActorBlueprintFunctionLibrary::MakeV2XDefinition(
|
||||
bool &Success,
|
||||
FActorDefinition &Definition)
|
||||
{
|
||||
FillIdAndTags(Definition, TEXT("sensor"), TEXT("other"), TEXT("v2x"));
|
||||
AddVariationsForSensor(Definition);
|
||||
|
||||
// - Noise seed --------------------------------
|
||||
FActorVariation NoiseSeed;
|
||||
NoiseSeed.Id = TEXT("noise_seed");
|
||||
NoiseSeed.Type = EActorAttributeType::Int;
|
||||
NoiseSeed.RecommendedValues = { TEXT("0") };
|
||||
NoiseSeed.bRestrictToRecommended = false;
|
||||
|
||||
//Frequency
|
||||
FActorVariation Frequency;
|
||||
Frequency.Id = TEXT("frequency_ghz");
|
||||
Frequency.Type = EActorAttributeType::Float;
|
||||
Frequency.RecommendedValues = { TEXT("5.9")};
|
||||
|
||||
//TransmitPower
|
||||
FActorVariation TransmitPower;
|
||||
TransmitPower.Id = TEXT("transmit_power");
|
||||
TransmitPower.Type = EActorAttributeType::Float;
|
||||
TransmitPower.RecommendedValues = { TEXT("21.5")};
|
||||
|
||||
//ReceiveSensitivity
|
||||
FActorVariation ReceiverSensitivity;
|
||||
ReceiverSensitivity.Id = TEXT("receiver_sensitivity");
|
||||
ReceiverSensitivity.Type = EActorAttributeType::Float;
|
||||
ReceiverSensitivity.RecommendedValues = { TEXT("-99.0")};
|
||||
|
||||
//Combined Antenna Gain in dBi
|
||||
FActorVariation CombinedAntennaGain;
|
||||
CombinedAntennaGain.Id = TEXT("combined_antenna_gain");
|
||||
CombinedAntennaGain.Type = EActorAttributeType::Float;
|
||||
CombinedAntennaGain.RecommendedValues = { TEXT("10.0")};
|
||||
|
||||
//Scenario
|
||||
FActorVariation Scenario;
|
||||
Scenario.Id = TEXT("scenario");
|
||||
Scenario.Type = EActorAttributeType::String;
|
||||
Scenario.RecommendedValues = { TEXT("highway"), TEXT("rural"), TEXT("urban")};
|
||||
Scenario.bRestrictToRecommended = true;
|
||||
|
||||
//Path loss exponent
|
||||
FActorVariation PLE;
|
||||
PLE.Id = TEXT("path_loss_exponent");
|
||||
PLE.Type = EActorAttributeType::Float;
|
||||
PLE.RecommendedValues = { TEXT("2.7")};
|
||||
|
||||
|
||||
//FSPL reference distance for LDPL calculation
|
||||
FActorVariation FSPL_RefDistance;
|
||||
FSPL_RefDistance.Id = TEXT("d_ref");
|
||||
FSPL_RefDistance.Type = EActorAttributeType::Float;
|
||||
FSPL_RefDistance.RecommendedValues = { TEXT("1.0")};
|
||||
|
||||
//filter distance to speed up calculation
|
||||
FActorVariation FilterDistance;
|
||||
FilterDistance.Id = TEXT("filter_distance");
|
||||
FilterDistance.Type = EActorAttributeType::Float;
|
||||
FilterDistance.RecommendedValues = { TEXT("500.0")};
|
||||
|
||||
//etsi fading
|
||||
FActorVariation EtsiFading;
|
||||
EtsiFading.Id = TEXT("use_etsi_fading");
|
||||
EtsiFading.Type = EActorAttributeType::Bool;
|
||||
EtsiFading.RecommendedValues = { TEXT("true")};
|
||||
|
||||
//custom fading std deviation
|
||||
FActorVariation CustomFadingStddev;
|
||||
CustomFadingStddev.Id = TEXT("custom_fading_stddev");
|
||||
CustomFadingStddev.Type = EActorAttributeType::Float;
|
||||
CustomFadingStddev.RecommendedValues = { TEXT("0.0")};
|
||||
|
||||
// Min Cam Generation
|
||||
FActorVariation GenCamMin;
|
||||
GenCamMin.Id = TEXT("gen_cam_min");
|
||||
GenCamMin.Type = EActorAttributeType::Float;
|
||||
GenCamMin.RecommendedValues = { TEXT("0.1")};
|
||||
|
||||
// Max Cam Generation
|
||||
FActorVariation GenCamMax;
|
||||
GenCamMax.Id = TEXT("gen_cam_max");
|
||||
GenCamMax.Type = EActorAttributeType::Float;
|
||||
GenCamMax.RecommendedValues = { TEXT("1.0")};
|
||||
|
||||
//Fixed Rate
|
||||
FActorVariation FixedRate;
|
||||
FixedRate.Id = TEXT("fixed_rate");
|
||||
FixedRate.Type = EActorAttributeType::Bool;
|
||||
FixedRate.RecommendedValues = { TEXT("false")};
|
||||
|
||||
//path loss model
|
||||
FActorVariation PLModel;
|
||||
PLModel.Id = TEXT("path_loss_model");
|
||||
PLModel.Type = EActorAttributeType::String;
|
||||
PLModel.RecommendedValues = { TEXT("winner"), TEXT("geometric")};
|
||||
PLModel.bRestrictToRecommended = true;
|
||||
|
||||
//V2x Sensor sends GNSS position in CAM messages
|
||||
// - Latitude ----------------------------------
|
||||
FActorVariation StdDevLat;
|
||||
StdDevLat.Id = TEXT("noise_lat_stddev");
|
||||
StdDevLat.Type = EActorAttributeType::Float;
|
||||
StdDevLat.RecommendedValues = { TEXT("0.0") };
|
||||
StdDevLat.bRestrictToRecommended = false;
|
||||
FActorVariation BiasLat;
|
||||
BiasLat.Id = TEXT("noise_lat_bias");
|
||||
BiasLat.Type = EActorAttributeType::Float;
|
||||
BiasLat.RecommendedValues = { TEXT("0.0") };
|
||||
BiasLat.bRestrictToRecommended = false;
|
||||
|
||||
// - Longitude ---------------------------------
|
||||
FActorVariation StdDevLong;
|
||||
StdDevLong.Id = TEXT("noise_lon_stddev");
|
||||
StdDevLong.Type = EActorAttributeType::Float;
|
||||
StdDevLong.RecommendedValues = { TEXT("0.0") };
|
||||
StdDevLong.bRestrictToRecommended = false;
|
||||
FActorVariation BiasLong;
|
||||
BiasLong.Id = TEXT("noise_lon_bias");
|
||||
BiasLong.Type = EActorAttributeType::Float;
|
||||
BiasLong.RecommendedValues = { TEXT("0.0") };
|
||||
BiasLong.bRestrictToRecommended = false;
|
||||
|
||||
// - Altitude ----------------------------------
|
||||
FActorVariation StdDevAlt;
|
||||
StdDevAlt.Id = TEXT("noise_alt_stddev");
|
||||
StdDevAlt.Type = EActorAttributeType::Float;
|
||||
StdDevAlt.RecommendedValues = { TEXT("0.0") };
|
||||
StdDevAlt.bRestrictToRecommended = false;
|
||||
FActorVariation BiasAlt;
|
||||
BiasAlt.Id = TEXT("noise_alt_bias");
|
||||
BiasAlt.Type = EActorAttributeType::Float;
|
||||
BiasAlt.RecommendedValues = { TEXT("0.0") };
|
||||
BiasAlt.bRestrictToRecommended = false;
|
||||
|
||||
// - Heading ----------------------------------
|
||||
FActorVariation StdDevHeading;
|
||||
StdDevHeading.Id = TEXT("noise_head_stddev");
|
||||
StdDevHeading.Type = EActorAttributeType::Float;
|
||||
StdDevHeading.RecommendedValues = { TEXT("0.0") };
|
||||
StdDevHeading.bRestrictToRecommended = false;
|
||||
FActorVariation BiasHeading;
|
||||
BiasHeading.Id = TEXT("noise_head_bias");
|
||||
BiasHeading.Type = EActorAttributeType::Float;
|
||||
BiasHeading.RecommendedValues = { TEXT("0.0") };
|
||||
BiasHeading.bRestrictToRecommended = false;
|
||||
|
||||
//V2x Sensor sends acceleration in CAM messages
|
||||
// - Accelerometer Standard Deviation ----------
|
||||
// X Component
|
||||
FActorVariation StdDevAccelX;
|
||||
StdDevAccelX.Id = TEXT("noise_accel_stddev_x");
|
||||
StdDevAccelX.Type = EActorAttributeType::Float;
|
||||
StdDevAccelX.RecommendedValues = { TEXT("0.0") };
|
||||
StdDevAccelX.bRestrictToRecommended = false;
|
||||
// Y Component
|
||||
FActorVariation StdDevAccelY;
|
||||
StdDevAccelY.Id = TEXT("noise_accel_stddev_y");
|
||||
StdDevAccelY.Type = EActorAttributeType::Float;
|
||||
StdDevAccelY.RecommendedValues = { TEXT("0.0") };
|
||||
StdDevAccelY.bRestrictToRecommended = false;
|
||||
// Z Component
|
||||
FActorVariation StdDevAccelZ;
|
||||
StdDevAccelZ.Id = TEXT("noise_accel_stddev_z");
|
||||
StdDevAccelZ.Type = EActorAttributeType::Float;
|
||||
StdDevAccelZ.RecommendedValues = { TEXT("0.0") };
|
||||
StdDevAccelZ.bRestrictToRecommended = false;
|
||||
|
||||
// Yaw rate
|
||||
FActorVariation StdDevYawrate;
|
||||
StdDevYawrate.Id = TEXT("noise_yawrate_stddev");
|
||||
StdDevYawrate.Type = EActorAttributeType::Float;
|
||||
StdDevYawrate.RecommendedValues = { TEXT("0.0") };
|
||||
StdDevYawrate.bRestrictToRecommended = false;
|
||||
FActorVariation BiasYawrate;
|
||||
BiasYawrate.Id = TEXT("noise_yawrate_bias");
|
||||
BiasYawrate.Type = EActorAttributeType::Float;
|
||||
BiasYawrate.RecommendedValues = { TEXT("0.0") };
|
||||
BiasYawrate.bRestrictToRecommended = false;
|
||||
|
||||
//V2x Sensor sends speed in CAM messages
|
||||
// X Component
|
||||
FActorVariation StdDevVelX;
|
||||
StdDevVelX.Id = TEXT("noise_vel_stddev_x");
|
||||
StdDevVelX.Type = EActorAttributeType::Float;
|
||||
StdDevVelX.RecommendedValues = { TEXT("0.0") };
|
||||
StdDevVelX.bRestrictToRecommended = false;
|
||||
|
||||
Definition.Variations.Append({
|
||||
NoiseSeed,
|
||||
TransmitPower,
|
||||
ReceiverSensitivity,
|
||||
Frequency,
|
||||
CombinedAntennaGain,
|
||||
Scenario,
|
||||
PLModel,
|
||||
PLE,
|
||||
FSPL_RefDistance,
|
||||
FilterDistance,
|
||||
EtsiFading,
|
||||
CustomFadingStddev,
|
||||
GenCamMin,
|
||||
GenCamMax,
|
||||
FixedRate,
|
||||
StdDevLat,
|
||||
BiasLat,
|
||||
StdDevLong,
|
||||
BiasLong,
|
||||
StdDevAlt,
|
||||
BiasAlt,
|
||||
StdDevHeading,
|
||||
BiasHeading,
|
||||
StdDevAccelX,
|
||||
StdDevAccelY,
|
||||
StdDevAccelZ,
|
||||
StdDevYawrate,
|
||||
BiasYawrate,
|
||||
StdDevVelX});
|
||||
Success = CheckActorDefinition(Definition);
|
||||
}
|
||||
|
||||
FActorDefinition UActorBlueprintFunctionLibrary::MakeCustomV2XDefinition()
|
||||
{
|
||||
FActorDefinition Definition;
|
||||
bool Success;
|
||||
MakeCustomV2XDefinition(Success, Definition);
|
||||
check(Success);
|
||||
return Definition;
|
||||
}
|
||||
|
||||
void UActorBlueprintFunctionLibrary::MakeCustomV2XDefinition(
|
||||
bool &Success,
|
||||
FActorDefinition &Definition)
|
||||
{
|
||||
FillIdAndTags(Definition, TEXT("sensor"), TEXT("other"), TEXT("v2x_custom"));
|
||||
AddVariationsForSensor(Definition);
|
||||
|
||||
// - Noise seed --------------------------------
|
||||
FActorVariation NoiseSeed;
|
||||
NoiseSeed.Id = TEXT("noise_seed");
|
||||
NoiseSeed.Type = EActorAttributeType::Int;
|
||||
NoiseSeed.RecommendedValues = { TEXT("0") };
|
||||
NoiseSeed.bRestrictToRecommended = false;
|
||||
|
||||
//TransmitPower
|
||||
FActorVariation TransmitPower;
|
||||
TransmitPower.Id = TEXT("transmit_power");
|
||||
TransmitPower.Type = EActorAttributeType::Float;
|
||||
TransmitPower.RecommendedValues = { TEXT("21.5")};
|
||||
|
||||
//ReceiveSensitivity
|
||||
FActorVariation ReceiverSensitivity;
|
||||
ReceiverSensitivity.Id = TEXT("receiver_sensitivity");
|
||||
ReceiverSensitivity.Type = EActorAttributeType::Float;
|
||||
ReceiverSensitivity.RecommendedValues = { TEXT("-99.0")};
|
||||
|
||||
//Frequency
|
||||
FActorVariation Frequency;
|
||||
Frequency.Id = TEXT("frequency_ghz");
|
||||
Frequency.Type = EActorAttributeType::Float;
|
||||
Frequency.RecommendedValues = { TEXT("5.9")};
|
||||
|
||||
//Combined Antenna Gain in dBi
|
||||
FActorVariation CombinedAntennaGain;
|
||||
CombinedAntennaGain.Id = TEXT("combined_antenna_gain");
|
||||
CombinedAntennaGain.Type = EActorAttributeType::Float;
|
||||
CombinedAntennaGain.RecommendedValues = { TEXT("10.0")};
|
||||
|
||||
//Scenario
|
||||
FActorVariation Scenario;
|
||||
Scenario.Id = TEXT("scenario");
|
||||
Scenario.Type = EActorAttributeType::String;
|
||||
Scenario.RecommendedValues = { TEXT("highway"), TEXT("rural"), TEXT("urban")};
|
||||
Scenario.bRestrictToRecommended = true;
|
||||
|
||||
//Path loss exponent
|
||||
FActorVariation PLE;
|
||||
PLE.Id = TEXT("path_loss_exponent");
|
||||
PLE.Type = EActorAttributeType::Float;
|
||||
PLE.RecommendedValues = { TEXT("2.7")};
|
||||
|
||||
|
||||
//FSPL reference distance for LDPL calculation
|
||||
FActorVariation FSPL_RefDistance;
|
||||
FSPL_RefDistance.Id = TEXT("d_ref");
|
||||
FSPL_RefDistance.Type = EActorAttributeType::Float;
|
||||
FSPL_RefDistance.RecommendedValues = { TEXT("1.0")};
|
||||
|
||||
//filter distance to speed up calculation
|
||||
FActorVariation FilterDistance;
|
||||
FilterDistance.Id = TEXT("filter_distance");
|
||||
FilterDistance.Type = EActorAttributeType::Float;
|
||||
FilterDistance.RecommendedValues = { TEXT("500.0")};
|
||||
|
||||
//etsi fading
|
||||
FActorVariation EtsiFading;
|
||||
EtsiFading.Id = TEXT("use_etsi_fading");
|
||||
EtsiFading.Type = EActorAttributeType::Bool;
|
||||
EtsiFading.RecommendedValues = { TEXT("true")};
|
||||
|
||||
//custom fading std deviation
|
||||
FActorVariation CustomFadingStddev;
|
||||
CustomFadingStddev.Id = TEXT("custom_fading_stddev");
|
||||
CustomFadingStddev.Type = EActorAttributeType::Float;
|
||||
CustomFadingStddev.RecommendedValues = { TEXT("0.0")};
|
||||
|
||||
//path loss model
|
||||
FActorVariation PLModel;
|
||||
PLModel.Id = TEXT("path_loss_model");
|
||||
PLModel.Type = EActorAttributeType::String;
|
||||
PLModel.RecommendedValues = { TEXT("winner"), TEXT("geometric")};
|
||||
PLModel.bRestrictToRecommended = true;
|
||||
|
||||
|
||||
Definition.Variations.Append({
|
||||
NoiseSeed,
|
||||
TransmitPower,
|
||||
ReceiverSensitivity,
|
||||
Frequency,
|
||||
CombinedAntennaGain,
|
||||
Scenario,
|
||||
PLModel,
|
||||
PLE,
|
||||
FSPL_RefDistance,
|
||||
FilterDistance,
|
||||
EtsiFading,
|
||||
CustomFadingStddev
|
||||
});
|
||||
|
||||
Success = CheckActorDefinition(Definition);
|
||||
}
|
||||
|
||||
|
||||
FActorDefinition UActorBlueprintFunctionLibrary::MakeGnssDefinition()
|
||||
{
|
||||
FActorDefinition Definition;
|
||||
|
@ -1247,6 +1593,12 @@ void UActorBlueprintFunctionLibrary::MakePedestrianDefinition(
|
|||
EActorAttributeType::String,
|
||||
GetAge(Parameters.Age)});
|
||||
|
||||
|
||||
Definition.Attributes.Emplace(FActorAttribute{
|
||||
TEXT("can_use_wheelchair"),
|
||||
EActorAttributeType::Bool,
|
||||
Parameters.bCanUseWheelChair ? TEXT("true") : TEXT("false") });
|
||||
|
||||
if (Parameters.Speed.Num() > 0)
|
||||
{
|
||||
FActorVariation Speed;
|
||||
|
@ -1260,6 +1612,8 @@ void UActorBlueprintFunctionLibrary::MakePedestrianDefinition(
|
|||
Definition.Variations.Emplace(Speed);
|
||||
}
|
||||
|
||||
bool bCanUseWheelChair = Parameters.bCanUseWheelChair;
|
||||
|
||||
FActorVariation IsInvincible;
|
||||
IsInvincible.Id = TEXT("is_invincible");
|
||||
IsInvincible.Type = EActorAttributeType::Bool;
|
||||
|
@ -1267,6 +1621,20 @@ void UActorBlueprintFunctionLibrary::MakePedestrianDefinition(
|
|||
IsInvincible.bRestrictToRecommended = false;
|
||||
Definition.Variations.Emplace(IsInvincible);
|
||||
|
||||
FActorVariation WheelChairVariation;
|
||||
WheelChairVariation.Id = TEXT("use_wheelchair");
|
||||
WheelChairVariation.Type = EActorAttributeType::Bool;
|
||||
if(bCanUseWheelChair)
|
||||
{
|
||||
WheelChairVariation.RecommendedValues = { TEXT("false"), TEXT("true") };
|
||||
}
|
||||
else
|
||||
{
|
||||
WheelChairVariation.RecommendedValues = { TEXT("false") };
|
||||
}
|
||||
WheelChairVariation.bRestrictToRecommended = true;
|
||||
Definition.Variations.Emplace(WheelChairVariation);
|
||||
|
||||
Success = CheckActorDefinition(Definition);
|
||||
}
|
||||
|
||||
|
@ -1763,4 +2131,136 @@ void UActorBlueprintFunctionLibrary::SetRadar(
|
|||
RetrieveActorAttributeToInt("points_per_second", Description.Variations, 1500));
|
||||
}
|
||||
|
||||
void UActorBlueprintFunctionLibrary::SetV2X(
|
||||
const FActorDescription &Description,
|
||||
AV2XSensor* V2X)
|
||||
{
|
||||
CARLA_ABFL_CHECK_ACTOR(V2X);
|
||||
if (Description.Variations.Contains("noise_seed"))
|
||||
{
|
||||
V2X->SetSeed(
|
||||
RetrieveActorAttributeToInt("noise_seed", Description.Variations, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
V2X->SetSeed(V2X->GetRandomEngine()->GenerateRandomSeed());
|
||||
}
|
||||
|
||||
V2X->SetPropagationParams(
|
||||
RetrieveActorAttributeToFloat("transmit_power", Description.Variations, 21.5),
|
||||
RetrieveActorAttributeToFloat("receiver_sensitivity", Description.Variations, -99.0),
|
||||
RetrieveActorAttributeToFloat("frequency_ghz", Description.Variations, 5.9),
|
||||
RetrieveActorAttributeToFloat("combined_antenna_gain", Description.Variations, 10.0),
|
||||
RetrieveActorAttributeToFloat("path_loss_exponent", Description.Variations, 2.7),
|
||||
RetrieveActorAttributeToFloat("d_ref", Description.Variations, 1.0),
|
||||
RetrieveActorAttributeToFloat("filter_distance", Description.Variations, 500.0),
|
||||
RetrieveActorAttributeToBool("use_etsi_fading", Description.Variations, true),
|
||||
RetrieveActorAttributeToFloat("custom_fading_stddev", Description.Variations, 0.0f)
|
||||
);
|
||||
|
||||
if (RetrieveActorAttributeToString("scenario", Description.Variations, "urban") == "urban")
|
||||
{
|
||||
V2X->SetScenario(EScenario::Urban);
|
||||
}
|
||||
else if (RetrieveActorAttributeToString("scenario", Description.Variations, "urban") == "rural")
|
||||
{
|
||||
V2X->SetScenario(EScenario::Rural);
|
||||
}
|
||||
else
|
||||
{
|
||||
V2X->SetScenario(EScenario::Highway);
|
||||
}
|
||||
|
||||
V2X->SetCaServiceParams(
|
||||
RetrieveActorAttributeToFloat("gen_cam_min", Description.Variations, 0.1),
|
||||
RetrieveActorAttributeToFloat("gen_cam_max", Description.Variations, 1.0),
|
||||
RetrieveActorAttributeToBool("fixed_rate", Description.Variations, false));
|
||||
|
||||
V2X->SetAccelerationStandardDeviation({
|
||||
RetrieveActorAttributeToFloat("noise_accel_stddev_x", Description.Variations, 0.0f),
|
||||
RetrieveActorAttributeToFloat("noise_accel_stddev_y", Description.Variations, 0.0f),
|
||||
RetrieveActorAttributeToFloat("noise_accel_stddev_z", Description.Variations, 0.0f)});
|
||||
|
||||
V2X->SetGNSSDeviation(
|
||||
RetrieveActorAttributeToFloat("noise_lat_stddev", Description.Variations, 0.0f),
|
||||
RetrieveActorAttributeToFloat("noise_lon_stddev", Description.Variations, 0.0f),
|
||||
RetrieveActorAttributeToFloat("noise_alt_stddev", Description.Variations, 0.0f),
|
||||
RetrieveActorAttributeToFloat("noise_head_stddev", Description.Variations, 0.0f),
|
||||
RetrieveActorAttributeToFloat("noise_lat_bias", Description.Variations, 0.0f),
|
||||
RetrieveActorAttributeToFloat("noise_lon_bias", Description.Variations, 0.0f),
|
||||
RetrieveActorAttributeToFloat("noise_alt_bias", Description.Variations, 0.0f),
|
||||
RetrieveActorAttributeToFloat("noise_head_bias", Description.Variations, 0.0f));
|
||||
|
||||
V2X->SetVelDeviation(
|
||||
RetrieveActorAttributeToFloat("noise_vel_stddev_x", Description.Variations, 0.0f)
|
||||
);
|
||||
V2X->SetYawrateDeviation(
|
||||
RetrieveActorAttributeToFloat("noise_yawrate_stddev", Description.Variations, 0.0f),
|
||||
RetrieveActorAttributeToFloat("noise_yawrate_bias", Description.Variations, 0.0f)
|
||||
);
|
||||
|
||||
if (RetrieveActorAttributeToString("path_loss_model", Description.Variations, "geometric") == "winner")
|
||||
{
|
||||
V2X->SetPathLossModel(EPathLossModel::Winner);
|
||||
}
|
||||
else if(RetrieveActorAttributeToString("path_loss_model", Description.Variations, "geometric") == "geometric")
|
||||
{
|
||||
V2X->SetPathLossModel(EPathLossModel::Geometric);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void UActorBlueprintFunctionLibrary::SetCustomV2X(
|
||||
const FActorDescription &Description,
|
||||
ACustomV2XSensor* V2X)
|
||||
{
|
||||
CARLA_ABFL_CHECK_ACTOR(V2X);
|
||||
if (Description.Variations.Contains("noise_seed"))
|
||||
{
|
||||
V2X->SetSeed(
|
||||
RetrieveActorAttributeToInt("noise_seed", Description.Variations, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
V2X->SetSeed(V2X->GetRandomEngine()->GenerateRandomSeed());
|
||||
}
|
||||
|
||||
V2X->SetPropagationParams(
|
||||
RetrieveActorAttributeToFloat("transmit_power", Description.Variations, 21.5),
|
||||
RetrieveActorAttributeToFloat("receiver_sensitivity", Description.Variations, -99.0),
|
||||
RetrieveActorAttributeToFloat("frequency_ghz", Description.Variations, 5.9),
|
||||
RetrieveActorAttributeToFloat("combined_antenna_gain", Description.Variations, 10.0),
|
||||
RetrieveActorAttributeToFloat("path_loss_exponent", Description.Variations, 2.7),
|
||||
RetrieveActorAttributeToFloat("d_ref", Description.Variations, 1.0),
|
||||
RetrieveActorAttributeToFloat("filter_distance", Description.Variations, 500.0),
|
||||
RetrieveActorAttributeToBool("use_etsi_fading", Description.Variations, true),
|
||||
RetrieveActorAttributeToFloat("custom_fading_stddev", Description.Variations, 0.0f)
|
||||
);
|
||||
|
||||
if (RetrieveActorAttributeToString("scenario", Description.Variations, "urban") == "urban")
|
||||
{
|
||||
V2X->SetScenario(EScenario::Urban);
|
||||
}
|
||||
else if (RetrieveActorAttributeToString("scenario", Description.Variations, "urban") == "rural")
|
||||
{
|
||||
V2X->SetScenario(EScenario::Rural);
|
||||
}
|
||||
else
|
||||
{
|
||||
V2X->SetScenario(EScenario::Highway);
|
||||
}
|
||||
|
||||
|
||||
if (RetrieveActorAttributeToString("path_loss_model", Description.Variations, "geometric") == "winner")
|
||||
{
|
||||
V2X->SetPathLossModel(EPathLossModel::Winner);
|
||||
}
|
||||
else if(RetrieveActorAttributeToString("path_loss_model", Description.Variations, "geometric") == "geometric")
|
||||
{
|
||||
V2X->SetPathLossModel(EPathLossModel::Geometric);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#undef CARLA_ABFL_CHECK_ACTOR
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
#include "Carla/Sensor/GnssSensor.h"
|
||||
#include "Carla/Sensor/Radar.h"
|
||||
#include "Carla/Sensor/InertialMeasurementUnit.h"
|
||||
#include "Carla/Sensor/V2XSensor.h"
|
||||
#include "Carla/Sensor/CustomV2XSensor.h"
|
||||
#include "Carla/Sensor/V2XSensor.h"
|
||||
#include "Carla/Sensor/CustomV2XSensor.h"
|
||||
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
|
||||
|
@ -108,6 +112,20 @@ public:
|
|||
bool &Success,
|
||||
FActorDefinition &Definition);
|
||||
|
||||
static FActorDefinition MakeV2XDefinition();
|
||||
|
||||
UFUNCTION(Category = "Carla Actor", BlueprintCallable)
|
||||
static void MakeV2XDefinition(
|
||||
bool &Success,
|
||||
FActorDefinition &Definition);
|
||||
|
||||
static FActorDefinition MakeCustomV2XDefinition();
|
||||
|
||||
UFUNCTION(Category = "Carla Actor", BlueprintCallable)
|
||||
static void MakeCustomV2XDefinition(
|
||||
bool &Success,
|
||||
FActorDefinition &Definition);
|
||||
|
||||
UFUNCTION(Category = "Carla Actor", BlueprintCallable)
|
||||
static void MakeVehicleDefinition(
|
||||
const FVehicleParameters &Parameters,
|
||||
|
@ -226,4 +244,7 @@ public:
|
|||
static void SetIMU(const FActorDescription &Description, AInertialMeasurementUnit *IMU);
|
||||
|
||||
static void SetRadar(const FActorDescription &Description, ARadar *Radar);
|
||||
|
||||
static void SetV2X(const FActorDescription &Description, AV2XSensor *V2X);
|
||||
static void SetCustomV2X(const FActorDescription &Description, ACustomV2XSensor *V2X);
|
||||
};
|
||||
|
|
|
@ -969,6 +969,25 @@ ECarlaServerResponse FVehicleActor::SetActorAutopilot(bool bEnabled, bool bKeepS
|
|||
return ECarlaServerResponse::Success;
|
||||
}
|
||||
|
||||
ECarlaServerResponse FVehicleActor::GetVehicleTelemetryData(FVehicleTelemetryData& TelemetryData)
|
||||
{
|
||||
if (IsDormant())
|
||||
{
|
||||
FVehicleTelemetryData EmptyTelemetryData;
|
||||
TelemetryData = EmptyTelemetryData;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto Vehicle = Cast<ACarlaWheeledVehicle>(GetActor());
|
||||
if (Vehicle == nullptr)
|
||||
{
|
||||
return ECarlaServerResponse::NotAVehicle;
|
||||
}
|
||||
TelemetryData = Vehicle->GetVehicleTelemetryData();
|
||||
}
|
||||
return ECarlaServerResponse::Success;
|
||||
}
|
||||
|
||||
ECarlaServerResponse FVehicleActor::ShowVehicleDebugTelemetry(bool bEnabled)
|
||||
{
|
||||
if (IsDormant())
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Carla/Actor/ActorInfo.h"
|
||||
#include "Carla/Actor/ActorData.h"
|
||||
#include "Carla/Vehicle/CarlaWheeledVehicle.h"
|
||||
#include "Carla/Vehicle/VehicleTelemetryData.h"
|
||||
#include "Carla/Walker/WalkerController.h"
|
||||
#include "Carla/Traffic/TrafficLightState.h"
|
||||
|
||||
|
@ -322,6 +323,11 @@ public:
|
|||
return ECarlaServerResponse::ActorTypeMismatch;
|
||||
}
|
||||
|
||||
virtual ECarlaServerResponse GetVehicleTelemetryData(FVehicleTelemetryData&)
|
||||
{
|
||||
return ECarlaServerResponse::ActorTypeMismatch;
|
||||
}
|
||||
|
||||
virtual ECarlaServerResponse ShowVehicleDebugTelemetry(bool)
|
||||
{
|
||||
return ECarlaServerResponse::ActorTypeMismatch;
|
||||
|
@ -527,6 +533,8 @@ public:
|
|||
|
||||
virtual ECarlaServerResponse SetActorAutopilot(bool bEnabled, bool bKeepState = false) final;
|
||||
|
||||
virtual ECarlaServerResponse GetVehicleTelemetryData(FVehicleTelemetryData&) final;
|
||||
|
||||
virtual ECarlaServerResponse ShowVehicleDebugTelemetry(bool bEnabled) final;
|
||||
|
||||
virtual ECarlaServerResponse EnableCarSim(const FString& SimfilePath) final;
|
||||
|
|
|
@ -55,4 +55,7 @@ struct CARLA_API FPedestrianParameters
|
|||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 Generation = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
bool bCanUseWheelChair = false;
|
||||
};
|
||||
|
|
|
@ -136,7 +136,11 @@ void FCarlaEngine::NotifyInitGame(const UCarlaSettings &Settings)
|
|||
case carla::multigpu::MultiGPUCommand::LOAD_MAP:
|
||||
{
|
||||
FString FinalPath((char *) Data.data());
|
||||
UGameplayStatics::OpenLevel(CurrentEpisode->GetWorld(), *FinalPath, true);
|
||||
if(GetCurrentEpisode())
|
||||
{
|
||||
UGameplayStatics::OpenLevel(GetCurrentEpisode()->GetWorld(), *FinalPath, true);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case carla::multigpu::MultiGPUCommand::GET_TOKEN:
|
||||
|
|
|
@ -37,12 +37,12 @@ void CarlaRecorderAnimWheels::Read(std::istream &InFile)
|
|||
ReadValue<uint32_t>(InFile, DatabaseId);
|
||||
uint32_t NumWheels = 0;
|
||||
ReadValue<uint32_t>(InFile, NumWheels);
|
||||
WheelValues.reserve(NumWheels);
|
||||
WheelValues.resize(NumWheels);
|
||||
for (size_t i = 0; i < NumWheels; ++i)
|
||||
{
|
||||
WheelInfo Wheel;
|
||||
Wheel.Read(InFile);
|
||||
WheelValues.push_back(Wheel);
|
||||
WheelValues[i] = Wheel;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -808,7 +808,7 @@ void CarlaReplayer::InterpolatePosition(
|
|||
double DeltaTime)
|
||||
{
|
||||
// call the callback
|
||||
Helper.ProcessReplayerPosition(Pos1, Pos2, Per, DeltaTime);
|
||||
Helper.ProcessReplayerPosition(Pos1, Pos2, Per, DeltaTime, IgnoreSpectator);
|
||||
}
|
||||
|
||||
// tick for the replayer
|
||||
|
|
|
@ -202,7 +202,7 @@ std::pair<int, uint32_t> CarlaReplayerHelper::ProcessReplayerEventAdd(
|
|||
}
|
||||
|
||||
// check to ignore Hero or Spectator
|
||||
if ((bIgnoreHero && IsHero) ||
|
||||
if ((bIgnoreHero && IsHero) ||
|
||||
(bIgnoreSpectator && ActorDesc.Id.StartsWith("spectator")))
|
||||
{
|
||||
return std::make_pair(3, 0);
|
||||
|
@ -227,7 +227,11 @@ std::pair<int, uint32_t> CarlaReplayerHelper::ProcessReplayerEventAdd(
|
|||
// disable physics
|
||||
SetActorSimulatePhysics(result.second, false);
|
||||
// disable collisions
|
||||
result.second->GetActor()->SetActorEnableCollision(false);
|
||||
result.second->GetActor()->SetActorEnableCollision(true);
|
||||
auto RootComponent = Cast<UPrimitiveComponent>(
|
||||
result.second->GetActor()->GetRootComponent());
|
||||
RootComponent->SetSimulatePhysics(false);
|
||||
RootComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||||
// disable autopilot for vehicles
|
||||
if (result.second->GetActorType() == FCarlaActor::ActorType::Vehicle)
|
||||
SetActorAutopilot(result.second, false, false);
|
||||
|
@ -296,7 +300,7 @@ bool CarlaReplayerHelper::ProcessReplayerEventParent(uint32_t ChildId, uint32_t
|
|||
}
|
||||
|
||||
// reposition actors
|
||||
bool CarlaReplayerHelper::ProcessReplayerPosition(CarlaRecorderPosition Pos1, CarlaRecorderPosition Pos2, double Per, double DeltaTime)
|
||||
bool CarlaReplayerHelper::ProcessReplayerPosition(CarlaRecorderPosition Pos1, CarlaRecorderPosition Pos2, double Per, double DeltaTime, bool bIgnoreSpectator)
|
||||
{
|
||||
check(Episode != nullptr);
|
||||
FCarlaActor* CarlaActor = Episode->FindCarlaActor(Pos1.DatabaseId);
|
||||
|
@ -304,6 +308,11 @@ bool CarlaReplayerHelper::ProcessReplayerPosition(CarlaRecorderPosition Pos1, Ca
|
|||
FRotator Rotation;
|
||||
if(CarlaActor)
|
||||
{
|
||||
//Hot fix to avoid spectator we should investigate why this case is possible here
|
||||
if(bIgnoreSpectator && CarlaActor->GetActor()->GetClass()->GetFName().ToString().Contains("Spectator"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// check to assign first position or interpolate between both
|
||||
if (Per == 0.0)
|
||||
{
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
bool ProcessReplayerEventParent(uint32_t ChildId, uint32_t ParentId);
|
||||
|
||||
// reposition actors
|
||||
bool ProcessReplayerPosition(CarlaRecorderPosition Pos1, CarlaRecorderPosition Pos2, double Per, double DeltaTime);
|
||||
bool ProcessReplayerPosition(CarlaRecorderPosition Pos1, CarlaRecorderPosition Pos2, double Per, double DeltaTime, bool bIgnoreSpectator);
|
||||
|
||||
// replay event for traffic light state
|
||||
bool ProcessReplayerStateTrafficLight(CarlaRecorderStateTrafficLight State);
|
||||
|
|
|
@ -0,0 +1,225 @@
|
|||
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
|
||||
// Karlsruhe Institute of Technology
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "Carla.h"
|
||||
#include "Carla/Actor/ActorBlueprintFunctionLibrary.h"
|
||||
#include "Carla/Game/CarlaEpisode.h"
|
||||
#include "Carla/Vehicle/CarlaWheeledVehicle.h"
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include "CustomV2XSensor.h"
|
||||
#include "V2X/PathLossModel.h"
|
||||
|
||||
std::list<AActor *> ACustomV2XSensor::mV2XActorContainer;
|
||||
ACustomV2XSensor::ActorV2XDataMap ACustomV2XSensor::mActorV2XDataMap;
|
||||
|
||||
ACustomV2XSensor::ACustomV2XSensor(const FObjectInitializer &ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
RandomEngine = CreateDefaultSubobject<URandomEngine>(TEXT("RandomEngine"));
|
||||
|
||||
// Init path loss model
|
||||
PathLossModelObj = new PathLossModel(RandomEngine);
|
||||
}
|
||||
|
||||
void ACustomV2XSensor::SetOwner(AActor *Owner)
|
||||
{
|
||||
UE_LOG(LogCarla, Warning, TEXT("CustomV2XSensor: called setowner with %p"), Owner);
|
||||
if (GetOwner() != nullptr)
|
||||
{
|
||||
ACustomV2XSensor::mV2XActorContainer.remove(GetOwner());
|
||||
UE_LOG(LogCarla, Warning, TEXT("CustomV2XSensor: removed old owner %p"), GetOwner());
|
||||
}
|
||||
|
||||
Super::SetOwner(Owner);
|
||||
|
||||
// Store the actor into the static list if the actor details are not available
|
||||
if(Owner != nullptr)
|
||||
{
|
||||
if (std::find(ACustomV2XSensor::mV2XActorContainer.begin(), ACustomV2XSensor::mV2XActorContainer.end(), Owner) == ACustomV2XSensor::mV2XActorContainer.end())
|
||||
{
|
||||
ACustomV2XSensor::mV2XActorContainer.push_back(Owner);
|
||||
UE_LOG(LogCarla, Warning, TEXT("CustomV2XSensor: added owner, length now %d"), ACustomV2XSensor::mV2XActorContainer.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PathLossModelObj->SetOwner(Owner);
|
||||
|
||||
UCarlaEpisode* CarlaEpisode = UCarlaStatics::GetCurrentEpisode(GetWorld());
|
||||
FCarlaActor* CarlaActor = CarlaEpisode->FindCarlaActor(Owner);
|
||||
if (CarlaActor != nullptr)
|
||||
{
|
||||
mStationId = static_cast<long>(CarlaActor->GetActorId());
|
||||
}
|
||||
}
|
||||
|
||||
FActorDefinition ACustomV2XSensor::GetSensorDefinition()
|
||||
{
|
||||
return UActorBlueprintFunctionLibrary::MakeCustomV2XDefinition();
|
||||
}
|
||||
|
||||
/* Function to add configurable parameters*/
|
||||
void ACustomV2XSensor::Set(const FActorDescription &ActorDescription)
|
||||
{
|
||||
UE_LOG(LogCarla, Warning, TEXT("CustomV2XSensor: Set function called"));
|
||||
Super::Set(ActorDescription);
|
||||
UActorBlueprintFunctionLibrary::SetCustomV2X(ActorDescription, this);
|
||||
}
|
||||
|
||||
void ACustomV2XSensor::SetPropagationParams(const float TransmitPower,
|
||||
const float ReceiverSensitivity,
|
||||
const float Frequency,
|
||||
const float combined_antenna_gain,
|
||||
const float path_loss_exponent,
|
||||
const float reference_distance_fspl,
|
||||
const float filter_distance,
|
||||
const bool use_etsi_fading,
|
||||
const float custom_fading_stddev)
|
||||
{
|
||||
// forward parameters to PathLossModel Obj
|
||||
PathLossModelObj->SetParams(TransmitPower, ReceiverSensitivity, Frequency, combined_antenna_gain, path_loss_exponent, reference_distance_fspl, filter_distance, use_etsi_fading, custom_fading_stddev);
|
||||
}
|
||||
|
||||
void ACustomV2XSensor::SetPathLossModel(const EPathLossModel path_loss_model){
|
||||
PathLossModelObj->SetPathLossModel(path_loss_model);
|
||||
}
|
||||
|
||||
void ACustomV2XSensor::SetScenario(EScenario scenario)
|
||||
{
|
||||
PathLossModelObj->SetScenario(scenario);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function stores the actor details in to the static list.
|
||||
* Calls the CaService object to generate CAM message
|
||||
* Stores the message in static map
|
||||
*/
|
||||
void ACustomV2XSensor::PrePhysTick(float DeltaSeconds)
|
||||
{
|
||||
Super::PrePhysTick(DeltaSeconds);
|
||||
// Clear the message created during the last sim cycle
|
||||
if (GetOwner())
|
||||
{
|
||||
ACustomV2XSensor::mActorV2XDataMap.erase(GetOwner());
|
||||
|
||||
// Step 0: Create message to send, if triggering conditions fulfilled
|
||||
// this needs to be done in pre phys tick to enable synchronous reception in all other v2x sensors
|
||||
// Check whether the message is generated
|
||||
if (mMessageDataChanged)
|
||||
{
|
||||
// If message is generated store it
|
||||
// make a pair of message and sending power
|
||||
// if different v2x sensors send with different power, we need to store that
|
||||
carla::sensor::data::CustomV2XData message_pw;
|
||||
message_pw.Message = CreateCustomV2XMessage();
|
||||
|
||||
message_pw.Power = PathLossModelObj->GetTransmitPower();
|
||||
ACustomV2XSensor::mActorV2XDataMap.insert({GetOwner(), message_pw});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CustomV2XM_t ACustomV2XSensor::CreateCustomV2XMessage()
|
||||
{
|
||||
CustomV2XM_t message = CustomV2XM_t();
|
||||
|
||||
CreateITSPduHeader(message);
|
||||
std::strcpy(message.message,mMessageData.c_str());
|
||||
mMessageDataChanged = false;
|
||||
return message;
|
||||
}
|
||||
|
||||
void ACustomV2XSensor::CreateITSPduHeader(CustomV2XM_t &message)
|
||||
{
|
||||
ITSContainer::ItsPduHeader_t& header = message.header;
|
||||
header.protocolVersion = mProtocolVersion;
|
||||
header.messageID = mMessageId;
|
||||
header.stationID = mStationId;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function takes care of sending messages to the current actor.
|
||||
* First simulates the communication by calling LOSComm object.
|
||||
* If there is a list present then messages from those list are sent to the current actor
|
||||
*/
|
||||
void ACustomV2XSensor::PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaTime)
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(ACustomV2XSensor::PostPhysTick);
|
||||
|
||||
// Step 1: Create an actor list which has messages to send targeting this v2x sensor instance
|
||||
std::vector<ActorPowerPair> ActorPowerList;
|
||||
for (const auto &pair : ACustomV2XSensor::mActorV2XDataMap)
|
||||
{
|
||||
if (pair.first != GetOwner())
|
||||
{
|
||||
ActorPowerPair actor_power_pair;
|
||||
actor_power_pair.first = pair.first;
|
||||
// actor sending with transmit power
|
||||
actor_power_pair.second = pair.second.Power;
|
||||
ActorPowerList.push_back(actor_power_pair);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Simulate the communication for the actors in actor list to current actor.
|
||||
if (!ActorPowerList.empty())
|
||||
{
|
||||
UCarlaEpisode *carla_episode = UCarlaStatics::GetCurrentEpisode(GetWorld());
|
||||
PathLossModelObj->Simulate(ActorPowerList, carla_episode, GetWorld());
|
||||
// Step 3: Get the list of actors who can send message to current actor, and the receive power of their messages.
|
||||
ActorPowerMap actor_receivepower_map = PathLossModelObj->GetReceiveActorPowerList();
|
||||
// Step 4: Retrieve the messages of the actors that are received
|
||||
|
||||
// get registry to retrieve carla actor IDs
|
||||
const FActorRegistry &Registry = carla_episode->GetActorRegistry();
|
||||
|
||||
ACustomV2XSensor::V2XDataList msg_received_power_list;
|
||||
for (const auto &pair : actor_receivepower_map)
|
||||
{
|
||||
carla::sensor::data::CustomV2XData send_msg_and_pw = ACustomV2XSensor::mActorV2XDataMap.at(pair.first);
|
||||
carla::sensor::data::CustomV2XData received_msg_and_pw;
|
||||
// sent CAM
|
||||
received_msg_and_pw.Message = send_msg_and_pw.Message;
|
||||
// receive power
|
||||
received_msg_and_pw.Power = pair.second;
|
||||
|
||||
msg_received_power_list.push_back(received_msg_and_pw);
|
||||
}
|
||||
|
||||
WriteMessageToV2XData(msg_received_power_list);
|
||||
}
|
||||
// Step 5: Send message
|
||||
|
||||
if (mV2XData.GetMessageCount() > 0)
|
||||
{
|
||||
auto DataStream = GetDataStream(*this);
|
||||
DataStream.SerializeAndSend(*this, mV2XData, DataStream.PopBufferFromPool());
|
||||
}
|
||||
mV2XData.Reset();
|
||||
}
|
||||
|
||||
/*
|
||||
* Function the store the message into the structure so it can be sent to python client
|
||||
*/
|
||||
void ACustomV2XSensor::WriteMessageToV2XData(const ACustomV2XSensor::V2XDataList &msg_received_power_list)
|
||||
{
|
||||
for (const auto &elem : msg_received_power_list)
|
||||
{
|
||||
mV2XData.WriteMessage(elem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ACustomV2XSensor::Send(const FString message)
|
||||
{
|
||||
//note: this is unsafe!
|
||||
//should be fixed to limit length somewhere
|
||||
mMessageData = TCHAR_TO_UTF8(*message);
|
||||
mMessageDataChanged = true;
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
|
||||
// Karlsruhe Institute of Technology
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Carla/Sensor/Sensor.h"
|
||||
#include "Carla/Actor/ActorDefinition.h"
|
||||
#include "Carla/Actor/ActorDescription.h"
|
||||
#include <carla/sensor/data/V2XData.h>
|
||||
#include "V2X/PathLossModel.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include "CustomV2XSensor.generated.h"
|
||||
|
||||
|
||||
UCLASS()
|
||||
class CARLA_API ACustomV2XSensor : public ASensor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
using FV2XData = carla::sensor::data::CustomV2XDataS;
|
||||
using V2XDataList = std::vector<carla::sensor::data::CustomV2XData>;
|
||||
using ActorV2XDataMap = std::map<AActor *, carla::sensor::data::CustomV2XData>;
|
||||
|
||||
public:
|
||||
ACustomV2XSensor(const FObjectInitializer &ObjectInitializer);
|
||||
|
||||
static FActorDefinition GetSensorDefinition();
|
||||
|
||||
void Set(const FActorDescription &ActorDescription) override;
|
||||
void SetPropagationParams(const float TransmitPower,
|
||||
const float ReceiverSensitivity,
|
||||
const float Frequency,
|
||||
const float combined_antenna_gain,
|
||||
const float path_loss_exponent,
|
||||
const float reference_distance_fspl,
|
||||
const float filter_distance,
|
||||
const bool use_etsi_fading,
|
||||
const float custom_fading_stddev);
|
||||
void SetScenario(EScenario scenario);
|
||||
void SetPathLossModel(const EPathLossModel path_loss_model);
|
||||
|
||||
virtual void PrePhysTick(float DeltaSeconds) override;
|
||||
virtual void PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaTime) override;
|
||||
void SetOwner(AActor *Owner) override;
|
||||
|
||||
void Send(const FString message);
|
||||
|
||||
private:
|
||||
static std::list<AActor *> mV2XActorContainer;
|
||||
PathLossModel *PathLossModelObj;
|
||||
|
||||
//store data
|
||||
static ACustomV2XSensor::ActorV2XDataMap mActorV2XDataMap;
|
||||
FV2XData mV2XData;
|
||||
|
||||
//write
|
||||
void WriteMessageToV2XData(const ACustomV2XSensor::V2XDataList &msg_received_power_list);
|
||||
|
||||
//msg gen
|
||||
void CreateITSPduHeader(CustomV2XM_t &message);
|
||||
CustomV2XM_t CreateCustomV2XMessage();
|
||||
const long mProtocolVersion = 2;
|
||||
const long mMessageId = ITSContainer::messageID_custom;
|
||||
long mStationId;
|
||||
std::string mMessageData;
|
||||
bool mMessageDataChanged = false;
|
||||
constexpr static uint16_t data_size = sizeof(CustomV2XM_t::message);
|
||||
|
||||
};
|
|
@ -0,0 +1,745 @@
|
|||
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
|
||||
// Karlsruhe Institute of Technology
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "Carla.h"
|
||||
#include "CaService.h"
|
||||
#include <boost/algorithm/clamp.hpp>
|
||||
#include "carla/rpc/String.h"
|
||||
#include "Carla/Util/BoundingBoxCalculator.h"
|
||||
#include <chrono>
|
||||
static const float scLowFrequencyContainerInterval = 0.5;
|
||||
|
||||
ITSContainer::SpeedValue_t CaService::BuildSpeedValue(const float vel)
|
||||
{
|
||||
static const float lower = 0.0; // meter_per_second
|
||||
static const float upper = 163.82; // meter_per_second
|
||||
|
||||
ITSContainer::SpeedValue_t speed = ITSContainer::SpeedValue_unavailable;
|
||||
if (vel >= upper)
|
||||
{
|
||||
speed = 16382; // see CDD A.74 (TS 102 894 v1.2.1)
|
||||
}
|
||||
else if (vel >= lower)
|
||||
{
|
||||
// to cm per second
|
||||
speed = std::round(vel * 100.0) * ITSContainer::SpeedValue_oneCentimeterPerSec;
|
||||
}
|
||||
return speed;
|
||||
}
|
||||
|
||||
CaService::CaService(URandomEngine *random_engine)
|
||||
{
|
||||
mRandomEngine = random_engine;
|
||||
// The starting point now
|
||||
std::chrono::system_clock::time_point start_Point = std::chrono::system_clock::now();
|
||||
// the reference point for ETSI (2004-01-01T00:00:00:000Z)
|
||||
std::chrono::system_clock::time_point ref_point = std::chrono::system_clock::from_time_t(1072915200); // Unix time for 2004-01-01
|
||||
|
||||
mGenerationDelta0 = std::chrono::duration_cast<std::chrono::milliseconds>(start_Point - ref_point);
|
||||
}
|
||||
|
||||
void CaService::SetOwner(UWorld *world, AActor *Owner)
|
||||
{
|
||||
UE_LOG(LogCarla, Warning, TEXT("CaService:SetOwner function called"));
|
||||
mWorld = world;
|
||||
mCarlaEpisode = UCarlaStatics::GetCurrentEpisode(world);
|
||||
|
||||
CurrentGeoReference = mCarlaEpisode->GetGeoReference();
|
||||
|
||||
mActorOwner = Owner;
|
||||
mCarlaEpisode = UCarlaStatics::GetCurrentEpisode(mWorld);
|
||||
mCarlaActor = mCarlaEpisode->FindCarlaActor(Owner);
|
||||
|
||||
if (mCarlaActor != nullptr)
|
||||
{
|
||||
mVehicle = Cast<ACarlaWheeledVehicle>(Owner);
|
||||
|
||||
if (mCarlaActor->GetActorType() == FCarlaActor::ActorType::Vehicle)
|
||||
{
|
||||
UE_LOG(LogCarla, Warning, TEXT("CaService:Initialize Vehicle type"));
|
||||
|
||||
mLastCamTimeStamp = mCarlaEpisode->GetElapsedGameTime() - mGenCamMax;
|
||||
mLastLowCamTimeStamp = mCarlaEpisode->GetElapsedGameTime() - scLowFrequencyContainerInterval;
|
||||
// Can add logic for this later
|
||||
mDccRestriction = false;
|
||||
|
||||
mElapsedTime = 0;
|
||||
VehicleSpeed = 0;
|
||||
VehiclePosition = {0, 0, 0};
|
||||
VehicleHeading = {0, 0, 0};
|
||||
mLastCamSpeed = 0;
|
||||
mLastCamPosition = {0, 0, 0};
|
||||
mLastCamHeading = {0, 0, 0};
|
||||
}
|
||||
else if ((mCarlaActor->GetActorType() == FCarlaActor::ActorType::TrafficLight) ||
|
||||
(mCarlaActor->GetActorType() == FCarlaActor::ActorType::TrafficSign))
|
||||
{
|
||||
mGenerationInterval = 0.5;
|
||||
mLastCamTimeStamp = -mGenerationInterval;
|
||||
UE_LOG(LogCarla, Warning, TEXT("CaService:Initialize RSU type"));
|
||||
}
|
||||
|
||||
mStationId = static_cast<long>(mCarlaActor->GetActorId());
|
||||
mStationType = GetStationType();
|
||||
}
|
||||
}
|
||||
|
||||
void CaService::SetParams(const float GenCamMin, const float GenCamMax, const bool FixedRate)
|
||||
{
|
||||
UE_LOG(LogCarla, Warning, TEXT("CaService:SetParams function called"));
|
||||
// Max and Min for generation rate
|
||||
|
||||
mGenCamMin = GenCamMin; // in second
|
||||
mGenCamMax = GenCamMax; // in second
|
||||
mGenCam = mGenCamMax;
|
||||
// If we want set a fix interval make this as true
|
||||
mFixedRate = FixedRate;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to check trigger condition for RSU
|
||||
*/
|
||||
bool CaService::Trigger(float DeltaSeconds)
|
||||
{
|
||||
|
||||
mElapsedTime = mCarlaEpisode->GetElapsedGameTime();
|
||||
bool Trigger = false;
|
||||
if (mStationType == ITSContainer::StationType_roadSideUnit)
|
||||
{
|
||||
if (mElapsedTime - mLastCamTimeStamp >= mGenerationInterval)
|
||||
{
|
||||
Trigger = true;
|
||||
mCAMMessage = CreateCooperativeAwarenessMessage(DeltaSeconds);
|
||||
mLastCamTimeStamp = mElapsedTime;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Trigger = CheckTriggeringConditions(DeltaSeconds);
|
||||
}
|
||||
return Trigger;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to provide CAM message to other objects if necessary
|
||||
*/
|
||||
CAM_t CaService::GetCamMessage()
|
||||
{
|
||||
return mCAMMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the trigger condition in case of vehicles and if trigger is true request
|
||||
* to generate CAM message
|
||||
*/
|
||||
bool CaService::CheckTriggeringConditions(float DeltaSeconds)
|
||||
{
|
||||
float &T_GenCam = mGenCam;
|
||||
const float T_GenCamMin = mGenCamMin;
|
||||
const float T_GenCamMax = mGenCamMax;
|
||||
const float T_GenCamDcc = mDccRestriction ? 0 : T_GenCamMin;
|
||||
const float T_elapsed = mElapsedTime - mLastCamTimeStamp;
|
||||
if (T_elapsed >= T_GenCamDcc)
|
||||
{
|
||||
// If message need to be generated every sim tick then set this to true.
|
||||
if (mFixedRate)
|
||||
{
|
||||
GenerateCamMessage(DeltaSeconds);
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (CheckHeadingDelta(DeltaSeconds) || CheckPositionDelta(DeltaSeconds) || CheckSpeedDelta(DeltaSeconds))
|
||||
{
|
||||
GenerateCamMessage(DeltaSeconds);
|
||||
T_GenCam = std::min(T_elapsed, T_GenCamMax);
|
||||
mGenCamLowDynamicsCounter = 0;
|
||||
return true;
|
||||
}
|
||||
else if (T_elapsed >= T_GenCam)
|
||||
{
|
||||
GenerateCamMessage(DeltaSeconds);
|
||||
if (++mGenCamLowDynamicsCounter >= mGenCamLowDynamicsLimit)
|
||||
{
|
||||
T_GenCam = T_GenCamMax;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CaService::CheckPositionDelta(float DeltaSeconds)
|
||||
{
|
||||
// If position change is more the 4m
|
||||
VehiclePosition = mVehicle->GetActorLocation();
|
||||
double Distance = FVector::Distance(VehiclePosition, mLastCamPosition) / 100.0f; // From cm to m
|
||||
if (Distance > 4.0f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CaService::CheckSpeedDelta(float DeltaSeconds)
|
||||
{
|
||||
VehicleSpeed = mVehicle->GetVehicleForwardSpeed() / 100.0f; // From cm/s to m/s
|
||||
float DeltaSpeed = std::abs(VehicleSpeed - mLastCamSpeed);
|
||||
|
||||
// Speed differance is greater than 0.5m/s
|
||||
if (DeltaSpeed > 0.5)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
double CaService::GetFVectorAngle(const FVector &a, const FVector &b)
|
||||
{
|
||||
double Dot = a.X * b.X + a.Y * b.Y + a.Z * b.Z;
|
||||
return std::acos(Dot / (a.Size() * b.Size()));
|
||||
}
|
||||
|
||||
void CaService::GenerateCamMessage(float DeltaTime)
|
||||
{
|
||||
mCAMMessage = CreateCooperativeAwarenessMessage(DeltaTime);
|
||||
mLastCamPosition = VehiclePosition;
|
||||
mLastCamSpeed = VehicleSpeed;
|
||||
mLastCamHeading = VehicleHeading;
|
||||
mLastCamTimeStamp = mElapsedTime;
|
||||
}
|
||||
|
||||
// Function to get the station type
|
||||
ITSContainer::StationType_t CaService::GetStationType()
|
||||
{
|
||||
check(mActorOwner != nullptr);
|
||||
mCarlaEpisode = UCarlaStatics::GetCurrentEpisode(mWorld);
|
||||
mCarlaActor = mCarlaEpisode->FindCarlaActor(mActorOwner);
|
||||
ITSContainer::StationType_t stationType = ITSContainer::StationType_unknown;
|
||||
// return unknown if carla actor is gone
|
||||
if (mCarlaActor == nullptr)
|
||||
{
|
||||
return static_cast<long>(stationType);
|
||||
}
|
||||
auto Tag = ATagger::GetTagOfTaggedComponent(*mVehicle->GetMesh());
|
||||
|
||||
switch (Tag)
|
||||
{
|
||||
case crp::CityObjectLabel::None:
|
||||
stationType = ITSContainer::StationType_unknown;
|
||||
break;
|
||||
case crp::CityObjectLabel::Pedestrians:
|
||||
stationType = ITSContainer::StationType_pedestrian;
|
||||
break;
|
||||
case crp::CityObjectLabel::Bicycle:
|
||||
stationType = ITSContainer::StationType_cyclist;
|
||||
break;
|
||||
case crp::CityObjectLabel::Motorcycle:
|
||||
stationType = ITSContainer::StationType_motorcycle;
|
||||
break;
|
||||
case crp::CityObjectLabel::Car:
|
||||
stationType = ITSContainer::StationType_passengerCar;
|
||||
break;
|
||||
case crp::CityObjectLabel::Bus:
|
||||
stationType = ITSContainer::StationType_bus;
|
||||
break;
|
||||
// TODO Modify this in future is CARLA adds difference truck
|
||||
case crp::CityObjectLabel::Truck:
|
||||
stationType = ITSContainer::StationType_lightTruck;
|
||||
break;
|
||||
case crp::CityObjectLabel::Buildings:
|
||||
case crp::CityObjectLabel::Walls:
|
||||
case crp::CityObjectLabel::Fences:
|
||||
case crp::CityObjectLabel::Poles:
|
||||
case crp::CityObjectLabel::TrafficLight:
|
||||
case crp::CityObjectLabel::TrafficSigns:
|
||||
stationType = ITSContainer::StationType_roadSideUnit;
|
||||
break;
|
||||
case crp::CityObjectLabel::Train:
|
||||
stationType = ITSContainer::StationType_tram;
|
||||
break;
|
||||
default:
|
||||
stationType = ITSContainer::StationType_unknown;
|
||||
}
|
||||
|
||||
// Can improve this later for different special vehicles once carla implements it
|
||||
FCarlaActor::ActorType Type = mCarlaActor->GetActorType();
|
||||
if (Type == FCarlaActor::ActorType::Vehicle)
|
||||
{
|
||||
if (mCarlaActor->GetActorInfo()->Description.Variations.Contains("special_type"))
|
||||
{
|
||||
std::string special_type = carla::rpc::FromFString(*mCarlaActor->GetActorInfo()->Description.Variations["special_type"].Value);
|
||||
if (special_type.compare("emergency") == 0)
|
||||
{
|
||||
stationType = ITSContainer::StationType_specialVehicles;
|
||||
}
|
||||
}
|
||||
}
|
||||
return static_cast<long>(stationType);
|
||||
}
|
||||
|
||||
FVector CaService::GetReferencePosition()
|
||||
{
|
||||
FVector RefPos;
|
||||
carla::geom::Location ActorLocation = mActorOwner->GetActorLocation();
|
||||
ALargeMapManager *LargeMap = UCarlaStatics::GetLargeMapManager(mWorld);
|
||||
if (LargeMap)
|
||||
{
|
||||
ActorLocation = LargeMap->LocalToGlobalLocation(ActorLocation);
|
||||
}
|
||||
carla::geom::Location Location = ActorLocation;
|
||||
carla::geom::GeoLocation CurrentLocation = CurrentGeoReference.Transform(Location);
|
||||
|
||||
// Compute the noise for the sensor
|
||||
const float LatError = mRandomEngine->GetNormalDistribution(0.0f, LatitudeDeviation);
|
||||
const float LonError = mRandomEngine->GetNormalDistribution(0.0f, LongitudeDeviation);
|
||||
const float AltError = mRandomEngine->GetNormalDistribution(0.0f, AltitudeDeviation);
|
||||
|
||||
// Apply the noise to the sensor
|
||||
double Latitude = CurrentLocation.latitude + LatitudeBias + LatError;
|
||||
double Longitude = CurrentLocation.longitude + LongitudeBias + LonError;
|
||||
double Altitude = CurrentLocation.altitude + AltitudeBias + AltError;
|
||||
|
||||
RefPos.X = Latitude;
|
||||
RefPos.Y = Longitude;
|
||||
RefPos.Z = Altitude;
|
||||
return RefPos;
|
||||
}
|
||||
|
||||
float CaService::GetHeading()
|
||||
{
|
||||
// Magnetometer: orientation with respect to the North in rad
|
||||
const FVector CarlaNorthVector = FVector(0.0f, -1.0f, 0.0f);
|
||||
const FVector ForwVect = mActorOwner->GetActorForwardVector().GetSafeNormal2D();
|
||||
const float DotProd = FVector::DotProduct(CarlaNorthVector, ForwVect);
|
||||
|
||||
// We check if the dot product is higher than 1.0 due to numerical error
|
||||
if (DotProd >= 1.00f)
|
||||
return 0.0f;
|
||||
|
||||
float Heading = std::acos(DotProd);
|
||||
// Keep the angle between [0, 2pi)
|
||||
if (FVector::CrossProduct(CarlaNorthVector, ForwVect).Z < 0.0f)
|
||||
Heading = carla::geom::Math::Pi2<float>() - Heading;
|
||||
|
||||
const double HeadingDegree = carla::geom::Math::ToDegrees(Heading);
|
||||
|
||||
// Compute the noise for the sensor
|
||||
const float HeadingError = mRandomEngine->GetNormalDistribution(0.0f, HeadingDeviation);
|
||||
|
||||
// add errors
|
||||
return HeadingDegree + HeadingBias + HeadingError;
|
||||
}
|
||||
|
||||
// Function to get the vehicle role
|
||||
long CaService::GetVehicleRole()
|
||||
{
|
||||
long VehicleRole = ITSContainer::VehicleRole_default;
|
||||
long StationType = GetStationType();
|
||||
switch (StationType)
|
||||
{
|
||||
case ITSContainer::StationType_cyclist:
|
||||
case ITSContainer::StationType_moped:
|
||||
case ITSContainer::StationType_motorcycle:
|
||||
VehicleRole = ITSContainer::VehicleRole_default;
|
||||
break;
|
||||
case ITSContainer::StationType_bus:
|
||||
case ITSContainer::StationType_tram:
|
||||
VehicleRole = ITSContainer::VehicleRole_publicTransport;
|
||||
break;
|
||||
case ITSContainer::StationType_specialVehicles:
|
||||
VehicleRole = ITSContainer::VehicleRole_emergency;
|
||||
break;
|
||||
default:
|
||||
VehicleRole = ITSContainer::VehicleRole_default;
|
||||
break;
|
||||
}
|
||||
return VehicleRole;
|
||||
}
|
||||
|
||||
CAM_t CaService::CreateCooperativeAwarenessMessage(float DeltaTime)
|
||||
{
|
||||
CAM_t message = CAM_t();
|
||||
|
||||
CreateITSPduHeader(message);
|
||||
AddCooperativeAwarenessMessage(message.cam, DeltaTime);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
void CaService::CreateITSPduHeader(CAM_t &message)
|
||||
{
|
||||
ITSContainer::ItsPduHeader_t &header = message.header;
|
||||
header.protocolVersion = mProtocolVersion;
|
||||
header.messageID = mMessageId;
|
||||
header.stationID = mStationId;
|
||||
}
|
||||
|
||||
void CaService::AddCooperativeAwarenessMessage(CAMContainer::CoopAwareness_t &CoopAwarenessMessage, float DeltaTime)
|
||||
{
|
||||
|
||||
/* GenerationDeltaTime */
|
||||
auto genDeltaTime = mGenerationDelta0 + std::chrono::milliseconds(static_cast<long long>(mCarlaEpisode->GetElapsedGameTime() * 1000));
|
||||
CoopAwarenessMessage.generationDeltaTime = genDeltaTime.count() % 65536 * CAMContainer::GenerationDeltaTime_oneMilliSec; // TODOCheck this logic
|
||||
AddBasicContainer(CoopAwarenessMessage.camParameters.basicContainer);
|
||||
if (CoopAwarenessMessage.camParameters.basicContainer.stationType == ITSContainer::StationType_roadSideUnit)
|
||||
{
|
||||
// TODO Future Implementation
|
||||
AddRSUContainerHighFrequency(CoopAwarenessMessage.camParameters.highFrequencyContainer);
|
||||
}
|
||||
else if (CoopAwarenessMessage.camParameters.basicContainer.stationType == ITSContainer::StationType_pedestrian)
|
||||
{
|
||||
// TODO no container available for Pedestrains
|
||||
}
|
||||
else
|
||||
{
|
||||
// BasicVehicleContainer
|
||||
AddBasicVehicleContainerHighFrequency(CoopAwarenessMessage.camParameters.highFrequencyContainer, DeltaTime);
|
||||
|
||||
if (mElapsedTime - mLastLowCamTimeStamp >= scLowFrequencyContainerInterval)
|
||||
{
|
||||
AddLowFrequencyContainer(CoopAwarenessMessage.camParameters.lowFrequencyContainer);
|
||||
mLastLowCamTimeStamp = mElapsedTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Store nothing if not used
|
||||
CoopAwarenessMessage.camParameters.lowFrequencyContainer.present = CAMContainer::LowFrequencyContainer_PR_NOTHING;
|
||||
}
|
||||
/*
|
||||
*TODO Add Special container if it a special vehicle
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
void CaService::AddBasicContainer(CAMContainer::BasicContainer_t &BasicContainer)
|
||||
{
|
||||
BasicContainer.stationType = mStationType;
|
||||
|
||||
/* CamParameters ReferencePosition */
|
||||
FVector RefPos = GetReferencePosition();
|
||||
BasicContainer.referencePosition.latitude = std::round(RefPos.X * 1e6) * ITSContainer::Latitude_oneMicroDegreeNorth;
|
||||
BasicContainer.referencePosition.longitude = std::round(RefPos.Y * 1e6) * ITSContainer::Longitude_oneMicroDegreeEast;
|
||||
BasicContainer.referencePosition.positionConfidenceEllipse.semiMajorConfidence = ITSContainer::SemiAxisLength_unavailable;
|
||||
BasicContainer.referencePosition.positionConfidenceEllipse.semiMinorConfidence = ITSContainer::SemiAxisLength_unavailable;
|
||||
BasicContainer.referencePosition.positionConfidenceEllipse.semiMajorOrientation = ITSContainer::HeadingValue_unavailable;
|
||||
BasicContainer.referencePosition.altitude.altitudeValue = std::round(RefPos.Z * 100.0) * ITSContainer::AltitudeValue_oneCentimeter;
|
||||
BasicContainer.referencePosition.altitude.altitudeConfidence = ITSContainer::AltitudeConfidence_unavailable;
|
||||
}
|
||||
|
||||
void CaService::SetAccelerationStandardDeviation(const FVector &Vec)
|
||||
{
|
||||
StdDevAccel = Vec;
|
||||
}
|
||||
|
||||
void CaService::SetGNSSDeviation(const float noise_lat_stddev,
|
||||
const float noise_lon_stddev,
|
||||
const float noise_alt_stddev,
|
||||
const float noise_head_stddev,
|
||||
const float noise_lat_bias,
|
||||
const float noise_lon_bias,
|
||||
const float noise_alt_bias,
|
||||
const float noise_head_bias)
|
||||
{
|
||||
LatitudeDeviation = noise_lat_stddev;
|
||||
LongitudeDeviation = noise_lon_stddev;
|
||||
AltitudeDeviation = noise_alt_stddev;
|
||||
HeadingDeviation = noise_head_stddev;
|
||||
LatitudeBias = noise_lat_bias;
|
||||
LongitudeBias = noise_lon_bias;
|
||||
AltitudeBias = noise_alt_bias;
|
||||
HeadingBias = noise_head_bias;
|
||||
}
|
||||
|
||||
void CaService::SetVelDeviation(const float noise_vel_stddev_x)
|
||||
{
|
||||
VelocityDeviation = noise_vel_stddev_x;
|
||||
}
|
||||
|
||||
void CaService::SetYawrateDeviation(const float noise_yawrate_stddev, const float noise_yawrate_bias)
|
||||
{
|
||||
YawrateDeviation = noise_yawrate_stddev;
|
||||
YawrateBias = noise_yawrate_bias;
|
||||
}
|
||||
|
||||
void CaService::AddBasicVehicleContainerHighFrequency(CAMContainer::HighFrequencyContainer_t &hfc, float DeltaTime)
|
||||
{
|
||||
hfc.present = CAMContainer::HighFrequencyContainer_PR_basicVehicleContainerHighFrequency;
|
||||
CAMContainer::BasicVehicleContainerHighFrequency_t &bvc = hfc.basicVehicleContainerHighFrequency;
|
||||
// heading
|
||||
bvc.heading.headingValue = std::round(GetHeading() * 10.0);
|
||||
bvc.heading.headingConfidence = ITSContainer::HeadingConfidence_equalOrWithinOneDegree; // TODO
|
||||
// speed
|
||||
// speed with noise
|
||||
bvc.speed.speedValue = BuildSpeedValue(ComputeSpeed());
|
||||
bvc.speed.speedConfidence = ITSContainer::SpeedConfidence_equalOrWithInOneCentimerterPerSec * 3; // TODO
|
||||
// direction
|
||||
bvc.driveDirection = (mVehicle->GetVehicleForwardSpeed() / 100.0f) >= 0.0 ? ITSContainer::DriveDirection_forward : ITSContainer::DriveDirection_backward;
|
||||
// length and width
|
||||
auto bb = UBoundingBoxCalculator::GetActorBoundingBox(mActorOwner); // cm
|
||||
float length = bb.Extent.X * 2.0; // half box
|
||||
float width = bb.Extent.Y * 2.0; // half box
|
||||
|
||||
bvc.vehicleLength.vehicleLengthValue = std::round(length * 10.0); // 0.1 meter
|
||||
bvc.vehicleLength.vehicleLengthConfidenceIndication = ITSContainer::VehicleLengthConfidenceIndication_unavailable;
|
||||
bvc.vehicleWidth = std::round(width * 10.0); // 0.1 meter
|
||||
|
||||
// acceleration
|
||||
carla::geom::Vector3D Accel = ComputeAccelerometer(DeltaTime);
|
||||
|
||||
const double lonAccelValue = Accel.x * 10.0; // m/s to 0.1 m/s
|
||||
// limit changes
|
||||
if (lonAccelValue >= -160.0 && lonAccelValue <= 161.0)
|
||||
{
|
||||
bvc.longitudinalAcceleration.longitudinalAccelerationValue = std::round(lonAccelValue) * ITSContainer::LongitudinalAccelerationValue_pointOneMeterPerSecSquaredForward;
|
||||
}
|
||||
else
|
||||
{
|
||||
bvc.longitudinalAcceleration.longitudinalAccelerationValue = ITSContainer::LongitudinalAccelerationValue_unavailable;
|
||||
}
|
||||
bvc.longitudinalAcceleration.longitudinalAccelerationConfidence = ITSContainer::AccelerationConfidence_unavailable; // TODO
|
||||
|
||||
// curvature TODO
|
||||
bvc.curvature.curvatureValue = ITSContainer::CurvatureValue_unavailable;
|
||||
bvc.curvature.curvatureConfidence = ITSContainer::CurvatureConfidence_unavailable;
|
||||
bvc.curvatureCalculationMode = ITSContainer::CurvatureCalculationMode_yarRateUsed;
|
||||
|
||||
// yaw rate is in rad/s --> to centidegree per second
|
||||
bvc.yawRate.yawRateValue = std::round(carla::geom::Math::ToDegrees(ComputeYawRate()) * 100.0) * ITSContainer::YawRateValue_degSec_000_01ToLeft;
|
||||
if (bvc.yawRate.yawRateValue < -32766 || bvc.yawRate.yawRateValue > 32766)
|
||||
{
|
||||
bvc.yawRate.yawRateValue = ITSContainer::YawRateValue_unavailable;
|
||||
}
|
||||
bvc.yawRate.yawRateConfidence = ITSContainer::YawRateConfidence_unavailable; // TODO
|
||||
|
||||
// optional lat and vertical accelerations
|
||||
bvc.lateralAccelerationAvailable = true;
|
||||
const double latAccelValue = Accel.y * 10.0; // m/s to 0.1 m/s
|
||||
if (latAccelValue >= -160.0 && latAccelValue <= 161.0)
|
||||
{
|
||||
bvc.lateralAcceleration.lateralAccelerationValue = std::round(latAccelValue) * ITSContainer::LateralAccelerationValue_pointOneMeterPerSecSquaredToLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
bvc.lateralAcceleration.lateralAccelerationValue = ITSContainer::LateralAccelerationValue_unavailable;
|
||||
}
|
||||
bvc.lateralAcceleration.lateralAccelerationConfidence = ITSContainer::AccelerationConfidence_unavailable; // TODO
|
||||
|
||||
bvc.verticalAccelerationAvailable = true;
|
||||
const double vertAccelValue = Accel.z * 10.0; // m/s to 0.1 m/s
|
||||
if (vertAccelValue >= -160.0 && vertAccelValue <= 161.0)
|
||||
{
|
||||
bvc.verticalAcceleration.verticalAccelerationValue = std::round(vertAccelValue) * ITSContainer::VerticalAccelerationValue_pointOneMeterPerSecSquaredUp;
|
||||
}
|
||||
else
|
||||
{
|
||||
bvc.verticalAcceleration.verticalAccelerationValue = ITSContainer::VerticalAccelerationValue_unavailable;
|
||||
}
|
||||
bvc.verticalAcceleration.verticalAccelerationConfidence = ITSContainer::AccelerationConfidence_unavailable; // TODO
|
||||
|
||||
// TODO
|
||||
bvc.accelerationControlAvailable = false;
|
||||
bvc.lanePositionAvailable = false;
|
||||
bvc.steeringWheelAngleAvailable = false;
|
||||
bvc.performanceClassAvailable = false;
|
||||
bvc.cenDsrcTollingZoneAvailable = false;
|
||||
}
|
||||
|
||||
const carla::geom::Vector3D CaService::ComputeAccelerometerNoise(
|
||||
const FVector &Accelerometer)
|
||||
{
|
||||
// Normal (or Gaussian or Gauss) distribution will be used as noise function.
|
||||
// A mean of 0.0 is used as a first parameter, the standard deviation is
|
||||
// determined by the client
|
||||
constexpr float Mean = 0.0f;
|
||||
return carla::geom::Vector3D{
|
||||
Accelerometer.X + mRandomEngine->GetNormalDistribution(Mean, StdDevAccel.X),
|
||||
Accelerometer.Y + mRandomEngine->GetNormalDistribution(Mean, StdDevAccel.Y),
|
||||
Accelerometer.Z + mRandomEngine->GetNormalDistribution(Mean, StdDevAccel.Z)};
|
||||
}
|
||||
|
||||
carla::geom::Vector3D CaService::ComputeAccelerometer(
|
||||
const float DeltaTime)
|
||||
{
|
||||
// Used to convert from UE4's cm to meters
|
||||
constexpr float TO_METERS = 1e-2;
|
||||
// Earth's gravitational acceleration is approximately 9.81 m/s^2
|
||||
constexpr float GRAVITY = 9.81f;
|
||||
|
||||
// 2nd derivative of the polynomic (quadratic) interpolation
|
||||
// using the point in current time and two previous steps:
|
||||
// d2[i] = -2.0*(y1/(h1*h2)-y2/((h2+h1)*h2)-y0/(h1*(h2+h1)))
|
||||
const FVector CurrentLocation = mVehicle->GetActorLocation();
|
||||
|
||||
const FVector Y2 = PrevLocation[0];
|
||||
const FVector Y1 = PrevLocation[1];
|
||||
const FVector Y0 = CurrentLocation;
|
||||
const float H1 = DeltaTime;
|
||||
const float H2 = PrevDeltaTime;
|
||||
|
||||
const float H1AndH2 = H2 + H1;
|
||||
const FVector A = Y1 / (H1 * H2);
|
||||
const FVector B = Y2 / (H2 * (H1AndH2));
|
||||
const FVector C = Y0 / (H1 * (H1AndH2));
|
||||
FVector FVectorAccelerometer = TO_METERS * -2.0f * (A - B - C);
|
||||
|
||||
// Update the previous locations
|
||||
PrevLocation[0] = PrevLocation[1];
|
||||
PrevLocation[1] = CurrentLocation;
|
||||
PrevDeltaTime = DeltaTime;
|
||||
|
||||
// Add gravitational acceleration
|
||||
FVectorAccelerometer.Z += GRAVITY;
|
||||
|
||||
FQuat ImuRotation = mActorOwner->GetRootComponent()->GetComponentTransform().GetRotation();
|
||||
FVectorAccelerometer = ImuRotation.UnrotateVector(FVectorAccelerometer);
|
||||
|
||||
// Cast from FVector to our Vector3D to correctly send the data in m/s^2
|
||||
// and apply the desired noise function, in this case a normal distribution
|
||||
const carla::geom::Vector3D Accelerometer =
|
||||
ComputeAccelerometerNoise(FVectorAccelerometer);
|
||||
|
||||
return Accelerometer;
|
||||
}
|
||||
|
||||
float CaService::ComputeSpeed()
|
||||
{
|
||||
|
||||
const float speed = mVehicle->GetVehicleForwardSpeed() / 100.0f;
|
||||
|
||||
// Normal (or Gaussian or Gauss) distribution and a bias will be used as
|
||||
// noise function.
|
||||
// A mean of 0.0 is used as a first parameter.The standard deviation and the
|
||||
// bias are determined by the client
|
||||
constexpr float Mean = 0.0f;
|
||||
return boost::algorithm::clamp(speed + mRandomEngine->GetNormalDistribution(Mean, VelocityDeviation), 0.0f, std::numeric_limits<float>::max());
|
||||
}
|
||||
|
||||
float CaService::ComputeYawRate()
|
||||
{
|
||||
check(mActorOwner != nullptr);
|
||||
const FVector AngularVelocity =
|
||||
FIMU_GetActorAngularVelocityInRadians(*mActorOwner);
|
||||
|
||||
const FQuat SensorLocalRotation =
|
||||
mActorOwner->GetRootComponent()->GetRelativeTransform().GetRotation();
|
||||
|
||||
const FVector FVectorGyroscope =
|
||||
SensorLocalRotation.RotateVector(AngularVelocity);
|
||||
|
||||
// Cast from FVector to our Vector3D to correctly send the data in rad/s
|
||||
// and apply the desired noise function, in this case a normal distribution
|
||||
float yawrate =
|
||||
ComputeYawNoise(FVectorGyroscope);
|
||||
|
||||
return yawrate; // rad/s
|
||||
}
|
||||
|
||||
const float CaService::ComputeYawNoise(
|
||||
const FVector &Gyroscope)
|
||||
{
|
||||
// Normal (or Gaussian or Gauss) distribution and a bias will be used as
|
||||
// noise function.
|
||||
// A mean of 0.0 is used as a first parameter.The standard deviation and the
|
||||
// bias are determined by the client
|
||||
constexpr float Mean = 0.0f;
|
||||
return Gyroscope.Z + YawrateBias + mRandomEngine->GetNormalDistribution(Mean, YawrateDeviation);
|
||||
}
|
||||
|
||||
long millisecondsSince2004()
|
||||
{
|
||||
// Define the epoch time (2004-01-01T00:00:00.000Z)
|
||||
std::tm epoch_time = {};
|
||||
epoch_time = {0, 0, 0, 1, 0, 104}; // January 1, 2004
|
||||
|
||||
// Convert epoch time to a std::chrono::time_point
|
||||
std::chrono::system_clock::time_point epoch = std::chrono::system_clock::from_time_t(std::mktime(&epoch_time));
|
||||
|
||||
// Get the current time
|
||||
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
|
||||
|
||||
// Calculate the duration since the epoch in milliseconds
|
||||
std::chrono::milliseconds duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - epoch);
|
||||
|
||||
// Return the number of milliseconds as a long
|
||||
return duration.count();
|
||||
}
|
||||
|
||||
void CaService::AddRSUContainerHighFrequency(CAMContainer::HighFrequencyContainer_t &hfc)
|
||||
{
|
||||
hfc.present = CAMContainer::HighFrequencyContainer_PR_rsuContainerHighFrequency;
|
||||
CAMContainer::RSUContainerHighFrequency_t &rsu = hfc.rsuContainerHighFrequency;
|
||||
// TODO For future implementation ITSContainer::ProtectedCommunicationZonesRSU_t PCZR
|
||||
|
||||
uint8_t ProtectedZoneDataLength = 16; // Maximum number of elements in path history
|
||||
|
||||
for (uint8_t i = 0; i <= ProtectedZoneDataLength; ++i)
|
||||
{
|
||||
ITSContainer::ProtectedCommunicationZone_t PCZ;
|
||||
PCZ.protectedZoneType = ITSContainer::ProtectedZoneType_cenDsrcTolling;
|
||||
PCZ.expiryTimeAvailable = false;
|
||||
PCZ.protectedZoneLatitude = 50;
|
||||
PCZ.protectedZoneLongitude = 50;
|
||||
PCZ.protectedZoneRadiusAvailable = false;
|
||||
PCZ.protectedZoneIDAvailable = false;
|
||||
rsu.protectedCommunicationZonesRSU.list.push_back(PCZ);
|
||||
rsu.protectedCommunicationZonesRSU.ProtectedCommunicationZoneCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CaService::AddLowFrequencyContainer(CAMContainer::LowFrequencyContainer_t &lfc)
|
||||
{
|
||||
lfc.present = CAMContainer::LowFrequencyContainer_PR_basicVehicleContainerLowFrequency;
|
||||
CAMContainer::BasicVehicleContainerLowFrequency_t &bvc = lfc.basicVehicleContainerLowFrequency;
|
||||
|
||||
/*Vehicle Role*/
|
||||
bvc.vehicleRole = GetVehicleRole();
|
||||
|
||||
/*Exterior Lights*/
|
||||
uint8_t *buf = &bvc.exteriorLights;
|
||||
FVehicleLightState LightStateData = mVehicle->GetVehicleLightState();
|
||||
if (LightStateData.LowBeam)
|
||||
{
|
||||
buf[0] |= 1 << (7 - ITSContainer::ExteriorLights_lowBeamHeadlightsOn);
|
||||
}
|
||||
if (LightStateData.HighBeam)
|
||||
{
|
||||
buf[0] |= 1 << (7 - ITSContainer::ExteriorLights_highBeamHeadlightsOn);
|
||||
}
|
||||
if (LightStateData.LeftBlinker)
|
||||
{
|
||||
buf[0] |= 1 << (7 - ITSContainer::ExteriorLights_leftTurnSignalOn);
|
||||
}
|
||||
if (LightStateData.RightBlinker)
|
||||
{
|
||||
buf[0] |= 1 << (7 - ITSContainer::ExteriorLights_rightTurnSignalOn);
|
||||
}
|
||||
if (LightStateData.Reverse)
|
||||
{
|
||||
buf[0] |= 1 << (7 - ITSContainer::ExteriorLights_reverseLightOn);
|
||||
}
|
||||
if (LightStateData.Fog)
|
||||
{
|
||||
buf[0] |= 1 << (7 - ITSContainer::ExteriorLights_fogLightOn);
|
||||
}
|
||||
if (LightStateData.Position)
|
||||
{
|
||||
buf[0] |= 1 << (7 - ITSContainer::ExteriorLights_parkingLightsOn);
|
||||
}
|
||||
bvc.pathHistory.NumberOfPathPoint = 0;
|
||||
}
|
||||
|
||||
bool CaService::CheckHeadingDelta(float DeltaSeconds)
|
||||
{
|
||||
// if heading diff is more than 4degree
|
||||
VehicleHeading = mVehicle->GetVehicleOrientation();
|
||||
double HeadingDelta = carla::geom::Math::ToDegrees(GetFVectorAngle(mLastCamHeading, VehicleHeading));
|
||||
if (HeadingDelta > 4.0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
|
||||
// Karlsruhe Institute of Technology
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Carla/Sensor/Sensor.h"
|
||||
|
||||
#include "Carla/Actor/ActorDefinition.h"
|
||||
#include "Carla/Actor/ActorDescription.h"
|
||||
#include "Carla/Vehicle/CarlaWheeledVehicle.h"
|
||||
#include "carla/geom/Math.h"
|
||||
#include "carla/geom/GeoLocation.h"
|
||||
#include <vector>
|
||||
#include "carla/sensor/data/LibITS.h"
|
||||
#include <chrono>
|
||||
|
||||
class CaService
|
||||
{
|
||||
public:
|
||||
CaService(URandomEngine *random_engine);
|
||||
void SetOwner(UWorld *world, AActor *Owner);
|
||||
|
||||
void SetParams(const float GenCamMin, const float GenCamMax, const bool FixedRate);
|
||||
void SetVelDeviation(const float noise_vel_stddev_x);
|
||||
void SetYawrateDeviation(const float noise_yawrate_stddev, const float noise_yawrate_bias);
|
||||
void SetAccelerationStandardDeviation(const FVector &Vec);
|
||||
void SetGNSSDeviation(const float noise_lat_stddev,
|
||||
const float noise_lon_stddev,
|
||||
const float noise_alt_stddev,
|
||||
const float noise_head_stddev,
|
||||
const float noise_lat_bias,
|
||||
const float noise_lon_bias,
|
||||
const float noise_alt_bias,
|
||||
const float noise_head_bias);
|
||||
bool Trigger(float DeltaSeconds);
|
||||
CAM_t GetCamMessage();
|
||||
|
||||
private:
|
||||
AActor *mActorOwner;
|
||||
FCarlaActor *mCarlaActor;
|
||||
UCarlaEpisode *mCarlaEpisode;
|
||||
UWorld *mWorld;
|
||||
ACarlaWheeledVehicle *mVehicle;
|
||||
float mLastCamTimeStamp;
|
||||
float mLastLowCamTimeStamp;
|
||||
float mGenCamMin;
|
||||
float mGenCamMax;
|
||||
float mGenCam;
|
||||
double mElapsedTime;
|
||||
float mGenDeltaTimeMod;
|
||||
bool mDccRestriction;
|
||||
bool mFixedRate;
|
||||
unsigned int mGenCamLowDynamicsCounter;
|
||||
unsigned int mGenCamLowDynamicsLimit;
|
||||
float mGenerationInterval;
|
||||
|
||||
float VehicleSpeed;
|
||||
FVector VehiclePosition;
|
||||
FVector VehicleHeading;
|
||||
|
||||
FVector mLastCamPosition;
|
||||
float mLastCamSpeed;
|
||||
FVector mLastCamHeading;
|
||||
std::chrono::milliseconds mGenerationDelta0;
|
||||
|
||||
bool CheckTriggeringConditions(float DeltaSeconds);
|
||||
bool CheckHeadingDelta(float DeltaSeconds);
|
||||
bool CheckPositionDelta(float DeltaSeconds);
|
||||
bool CheckSpeedDelta(float DeltaSeconds);
|
||||
double GetFVectorAngle(const FVector &a, const FVector &b);
|
||||
void GenerateCamMessage(float DeltaTime);
|
||||
ITSContainer::StationType_t GetStationType();
|
||||
|
||||
float GetHeading();
|
||||
long GetVehicleRole();
|
||||
|
||||
/* Constant values for message*/
|
||||
const long mProtocolVersion = 2;
|
||||
const long mMessageId = ITSContainer::messageID_cam;
|
||||
long mStationId;
|
||||
long mStationType;
|
||||
|
||||
carla::geom::Vector3D ComputeAccelerometer(const float DeltaTime);
|
||||
const carla::geom::Vector3D ComputeAccelerometerNoise(const FVector &Accelerometer);
|
||||
/// Standard deviation for acceleration settings.
|
||||
FVector StdDevAccel;
|
||||
|
||||
/// Used to compute the acceleration
|
||||
std::array<FVector, 2> PrevLocation;
|
||||
|
||||
/// Used to compute the acceleration
|
||||
float PrevDeltaTime;
|
||||
|
||||
// GNSS reference position and heading
|
||||
FVector GetReferencePosition();
|
||||
carla::geom::GeoLocation CurrentGeoReference;
|
||||
float LatitudeDeviation;
|
||||
float LongitudeDeviation;
|
||||
float AltitudeDeviation;
|
||||
float HeadingDeviation;
|
||||
|
||||
float LatitudeBias;
|
||||
float LongitudeBias;
|
||||
float AltitudeBias;
|
||||
float HeadingBias;
|
||||
|
||||
// Velocity
|
||||
float ComputeSpeed();
|
||||
float VelocityDeviation;
|
||||
|
||||
// Yaw rate
|
||||
const float ComputeYawNoise(const FVector &Gyroscope);
|
||||
float ComputeYawRate();
|
||||
float YawrateDeviation;
|
||||
float YawrateBias;
|
||||
|
||||
CAM_t CreateCooperativeAwarenessMessage(float DeltaTime);
|
||||
void CreateITSPduHeader(CAM_t &message);
|
||||
void AddCooperativeAwarenessMessage(CAMContainer::CoopAwareness_t &CoopAwarenessMessage, float DeltaTime);
|
||||
void AddBasicContainer(CAMContainer::BasicContainer_t &BasicContainer);
|
||||
void AddBasicVehicleContainerHighFrequency(CAMContainer::HighFrequencyContainer_t &hfc, float DeltaTime);
|
||||
void AddRSUContainerHighFrequency(CAMContainer::HighFrequencyContainer_t &hfc);
|
||||
void AddLowFrequencyContainer(CAMContainer::LowFrequencyContainer_t &lfc);
|
||||
CAM_t mCAMMessage;
|
||||
|
||||
// random for noise
|
||||
URandomEngine *mRandomEngine;
|
||||
ITSContainer::SpeedValue_t BuildSpeedValue(const float vel);
|
||||
};
|
|
@ -0,0 +1,571 @@
|
|||
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
|
||||
// Karlsruhe Institute of Technology
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "Carla.h"
|
||||
#include "Carla/Game/CarlaEpisode.h"
|
||||
#include "Math/UnrealMathUtility.h"
|
||||
|
||||
#include "PathLossModel.h"
|
||||
#include <random>
|
||||
#include <limits>
|
||||
|
||||
double PathLossModel::Frequency_GHz = 5.9f;
|
||||
double PathLossModel::Frequency = 5.9f * std::pow(10, 9);
|
||||
double PathLossModel::lambda = PathLossModel::c_speedoflight / (5.9f * std::pow(10, 9));
|
||||
|
||||
PathLossModel::PathLossModel(URandomEngine *random_engine)
|
||||
{
|
||||
mRandomEngine = random_engine;
|
||||
}
|
||||
|
||||
void PathLossModel::SetOwner(AActor *Owner)
|
||||
{
|
||||
mActorOwner = Owner;
|
||||
}
|
||||
|
||||
void PathLossModel::SetParams(const float TransmitPower,
|
||||
const float ReceiverSensitivity,
|
||||
const float Frequency,
|
||||
const float combined_antenna_gain,
|
||||
const float path_loss_exponent,
|
||||
const float reference_distance_fspl,
|
||||
const float filter_distance,
|
||||
const bool use_etsi_fading,
|
||||
const float custom_fading_stddev)
|
||||
{
|
||||
this->TransmitPower = TransmitPower;
|
||||
this->ReceiverSensitivity = ReceiverSensitivity;
|
||||
this->path_loss_exponent = path_loss_exponent;
|
||||
this->reference_distance_fspl = reference_distance_fspl;
|
||||
this->filter_distance = filter_distance;
|
||||
this->use_etsi_fading = use_etsi_fading;
|
||||
this->custom_fading_stddev = custom_fading_stddev;
|
||||
this->combined_antenna_gain = combined_antenna_gain;
|
||||
PathLossModel::Frequency_GHz = Frequency;
|
||||
PathLossModel::Frequency = PathLossModel::Frequency_GHz * std::pow(10, 9);
|
||||
PathLossModel::lambda = PathLossModel::c_speedoflight / PathLossModel::Frequency;
|
||||
// when reference distance is set, we prepare the FSPL for the reference distance to be used in LDPL
|
||||
CalculateFSPL_d0();
|
||||
}
|
||||
|
||||
void PathLossModel::SetScenario(EScenario scenario)
|
||||
{
|
||||
this->scenario = scenario;
|
||||
}
|
||||
|
||||
std::map<AActor *, float> PathLossModel::GetReceiveActorPowerList()
|
||||
{
|
||||
return mReceiveActorPowerList;
|
||||
}
|
||||
|
||||
void PathLossModel::Simulate(const std::vector<ActorPowerPair> ActorList, UCarlaEpisode *CarlaEpisode, UWorld *World)
|
||||
{
|
||||
// Set current world and episode
|
||||
mWorld = World;
|
||||
mCarlaEpisode = CarlaEpisode;
|
||||
|
||||
CurrentActorLocation = mActorOwner->GetTransform().GetLocation();
|
||||
FVector OtherActorLocation;
|
||||
mReceiveActorPowerList.clear();
|
||||
float ReceivedPower = 0;
|
||||
// Logic to get height of the vehicle
|
||||
// TODO: make that thing use the actual attachment and transform of the sensor
|
||||
|
||||
double tx_height_local = (mActorOwner->GetSimpleCollisionHalfHeight() * 2.0f) + 2.0;
|
||||
|
||||
const FActorRegistry &Registry = mCarlaEpisode->GetActorRegistry();
|
||||
|
||||
for (auto &actor_power_pair : ActorList)
|
||||
{
|
||||
const FCarlaActor *view = Registry.FindCarlaActor(actor_power_pair.first);
|
||||
// ensure other actor is still alive
|
||||
if (!view)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
OtherActorLocation = actor_power_pair.first->GetTransform().GetLocation();
|
||||
double rx_height_local = (actor_power_pair.first->GetSimpleCollisionHalfHeight() * 2.0) + 2.0;
|
||||
|
||||
// calculate relative ht and hr respecting slope and elevation
|
||||
// cm
|
||||
// if objects are on a slope, minimum Z height of both is the reference to calculate transmitter height
|
||||
double ref0 = std::min(CurrentActorLocation.Z, OtherActorLocation.Z);
|
||||
// cm
|
||||
double ht = CurrentActorLocation.Z + tx_height_local - ref0;
|
||||
double hr = OtherActorLocation.Z + rx_height_local - ref0;
|
||||
// localize to common ref0 as ground
|
||||
FVector source_rel = CurrentActorLocation;
|
||||
source_rel.Z += tx_height_local;
|
||||
FVector dest_rel = OtherActorLocation;
|
||||
dest_rel.Z += rx_height_local;
|
||||
|
||||
double Distance3d = FVector::Distance(source_rel, dest_rel) / 100.0f; // From cm to m
|
||||
// to meters
|
||||
ht = ht / 100.0f;
|
||||
hr = hr / 100.0f;
|
||||
|
||||
if (Distance3d < filter_distance) // maybe change this for highway
|
||||
{
|
||||
float OtherTransmitPower = actor_power_pair.second;
|
||||
ReceivedPower = CalculateReceivedPower(actor_power_pair.first,
|
||||
OtherTransmitPower,
|
||||
CurrentActorLocation,
|
||||
OtherActorLocation,
|
||||
Distance3d,
|
||||
ht,
|
||||
tx_height_local,
|
||||
hr,
|
||||
rx_height_local,
|
||||
ref0);
|
||||
if (ReceivedPower > -1.0 * std::numeric_limits<float>::max())
|
||||
{
|
||||
mReceiveActorPowerList.insert(std::make_pair(actor_power_pair.first, ReceivedPower));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float PathLossModel::CalculateReceivedPower(AActor *OtherActor,
|
||||
const float OtherTransmitPower,
|
||||
const FVector Source,
|
||||
const FVector Destination,
|
||||
const double Distance3d,
|
||||
const double ht,
|
||||
const double ht_local,
|
||||
const double hr,
|
||||
const double hr_local,
|
||||
const double reference_z)
|
||||
{
|
||||
// hr in m
|
||||
// ht in m
|
||||
// reference_z in cm
|
||||
// distance3d in m
|
||||
bool ret = false;
|
||||
FCollisionObjectQueryParams ObjectParams;
|
||||
// Channels to check for collision with different object types
|
||||
ObjectParams.AddObjectTypesToQuery(ECollisionChannel::ECC_WorldStatic);
|
||||
ObjectParams.AddObjectTypesToQuery(ECollisionChannel::ECC_PhysicsBody);
|
||||
ObjectParams.AddObjectTypesToQuery(ECollisionChannel::ECC_Vehicle);
|
||||
ObjectParams.AddObjectTypesToQuery(ECollisionChannel::ECC_WorldDynamic);
|
||||
HitResult.Reset();
|
||||
|
||||
FVector tx = Source;
|
||||
tx.Z += ht_local;
|
||||
FVector rx = Destination;
|
||||
rx.Z += hr_local;
|
||||
mWorld->LineTraceMultiByObjectType(HitResult, tx, rx, ObjectParams);
|
||||
|
||||
// all losses
|
||||
float loss = ComputeLoss(OtherActor, Source, Destination, Distance3d, ht, hr, reference_z);
|
||||
|
||||
// we incorporate the tx power of the sender (the other actor), not our own
|
||||
// NOTE: combined antenna gain is parametrized for each sensor. Better solution would be to parametrize individual antenna gain
|
||||
// and combine at the receiver. This would allow to better account for antenna characteristics.
|
||||
float ReceivedPower = OtherTransmitPower + combined_antenna_gain - loss;
|
||||
|
||||
if (ReceivedPower >= ReceiverSensitivity)
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
float deltaPercentage = loss / (OtherTransmitPower - ReceiverSensitivity);
|
||||
|
||||
// Works only when run in debug mode
|
||||
DrawDebugLine(
|
||||
mWorld,
|
||||
tx,
|
||||
rx,
|
||||
FColor::Cyan,
|
||||
false, 0.05f, 0,
|
||||
30);
|
||||
if (deltaPercentage < 0.65)
|
||||
{
|
||||
DrawDebugLine(
|
||||
mWorld,
|
||||
tx,
|
||||
rx,
|
||||
FColor::Green,
|
||||
false, 0.1f, 0,
|
||||
30);
|
||||
}
|
||||
else if (deltaPercentage < 0.8)
|
||||
{
|
||||
DrawDebugLine(
|
||||
mWorld,
|
||||
tx,
|
||||
rx,
|
||||
FColor::Orange,
|
||||
false, 0.1f, 0,
|
||||
30);
|
||||
}
|
||||
else if (ReceivedPower >= ReceiverSensitivity)
|
||||
{
|
||||
DrawDebugLine(
|
||||
mWorld,
|
||||
tx,
|
||||
rx,
|
||||
FColor::Red,
|
||||
false, 0.1f, 0,
|
||||
30);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
{
|
||||
return ReceivedPower;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1.0 * std::numeric_limits<float>::max();
|
||||
}
|
||||
}
|
||||
|
||||
void PathLossModel::EstimatePathStateAndVehicleObstacles(AActor *OtherActor,
|
||||
FVector CurrentActorLocation,
|
||||
double TxHeight,
|
||||
double RxHeight,
|
||||
double reference_z,
|
||||
EPathState &state,
|
||||
std::vector<FVector> &vehicle_obstacles)
|
||||
{
|
||||
// CurrentActorLocation in cm original
|
||||
// TxHeight in m
|
||||
// RxHeight in m
|
||||
// reference_z in cm
|
||||
|
||||
// init with LOS
|
||||
state = EPathState::LOS;
|
||||
if (HitResult.Num() == 0)
|
||||
{
|
||||
// no hits --> LOS
|
||||
return;
|
||||
}
|
||||
|
||||
// check all hits
|
||||
for (const FHitResult &HitInfo : HitResult)
|
||||
{
|
||||
|
||||
FVector location;
|
||||
if (HitIsSelfOrOther(HitInfo, OtherActor))
|
||||
{
|
||||
// the current hit is either Tx or Rx, so we can skip it, no obstacle
|
||||
continue;
|
||||
}
|
||||
|
||||
// cal by ref
|
||||
if (GetLocationIfVehicle(CurrentActorLocation, HitInfo, reference_z, location))
|
||||
{
|
||||
// we found a vehicle
|
||||
// Note: we may set this several times if we have several vehicles in between
|
||||
state = EPathState::NLOSv;
|
||||
// z (height) is gonna be in m in relation to reference height
|
||||
// x,y also in meters
|
||||
// call by reference
|
||||
vehicle_obstacles.emplace_back(location);
|
||||
|
||||
// alternative (cf Etsi): statistical model
|
||||
// vehicle_blockage_loss += MakeVehicleBlockageLoss(TxHeight, RxHeight, obj_height, obj_dist);
|
||||
}
|
||||
// but if we hit a building, we stop and switch to NLOSb
|
||||
else
|
||||
{
|
||||
state = EPathState::NLOSb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double PathLossModel::CalcVehicleLoss(const double d1, const double d2, const double h)
|
||||
{
|
||||
double V = h * sqrt(2.0 * (d1 + d2) / (lambda * d1 * d2));
|
||||
if (V >= -0.78) {
|
||||
double T = std::pow(V - 0.1, 2);
|
||||
return 6.9 + 20.0 * log10(sqrt(T + 1.0) + V - 0.1);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double PathLossModel::CalculateNLOSvLoss(const FVector Source,
|
||||
const FVector Destination,
|
||||
const double TxHeight,
|
||||
const double RxHeight,
|
||||
const double RxDistance3d,
|
||||
std::vector<FVector> &vehicle_obstacles)
|
||||
{
|
||||
|
||||
// convert all positions to meters
|
||||
FVector pos_tx = Source;
|
||||
pos_tx.X /= 100.0f;
|
||||
pos_tx.Y /= 100.0f;
|
||||
pos_tx.Z = TxHeight;
|
||||
|
||||
FVector pos_rx = Destination;
|
||||
pos_rx.X /= 100.0f;
|
||||
pos_rx.Y /= 100.0f;
|
||||
pos_rx.Z = RxHeight;
|
||||
|
||||
double max_loss = 0.0;
|
||||
for(auto veh_it = vehicle_obstacles.begin(); veh_it != vehicle_obstacles.end(); veh_it++)
|
||||
{
|
||||
double dist_tx_veh = sqrt(std::pow(veh_it->X - pos_tx.X, 2) + std::pow(veh_it->Y - pos_tx.Y, 2));
|
||||
double dist_veh_rx = sqrt(std::pow(pos_rx.X - veh_it->X, 2) + std::pow(pos_rx.Y - veh_it->Y, 2));
|
||||
double cur_loss = CalcVehicleLoss(dist_tx_veh,dist_veh_rx,veh_it->Z);
|
||||
if(cur_loss >= max_loss)
|
||||
{
|
||||
max_loss = cur_loss;
|
||||
}
|
||||
}
|
||||
|
||||
return max_loss;
|
||||
}
|
||||
|
||||
void PathLossModel::SetPathLossModel(const EPathLossModel path_loss_model)
|
||||
{
|
||||
model = path_loss_model;
|
||||
}
|
||||
|
||||
float PathLossModel::ComputeLoss(AActor *OtherActor, FVector Source, FVector Destination, double Distance3d, double TxHeight, double RxHeight, double reference_z)
|
||||
{
|
||||
// TxHeight in m
|
||||
// RxHeight in m
|
||||
// reference_z in cm
|
||||
// distance3d in m
|
||||
EPathState state;
|
||||
|
||||
float PathLoss = 0.0;
|
||||
double VehicleBlockageLoss = 0.0;
|
||||
float ShadowFadingLoss = 0.0;
|
||||
|
||||
// state and vehicle obstacles are call-by-reference
|
||||
std::vector<FVector> vehicle_obstacles;
|
||||
EstimatePathStateAndVehicleObstacles(OtherActor, Source, TxHeight, RxHeight, reference_z, state, vehicle_obstacles);
|
||||
|
||||
if (model == EPathLossModel::Winner)
|
||||
{
|
||||
// calculate pure path loss depending on state and scenario
|
||||
PathLoss = CalculatePathLoss_WINNER(state, Distance3d);
|
||||
// in nlosv case, add multi knife edge
|
||||
if (state == EPathState::NLOSv)
|
||||
{
|
||||
PathLoss = PathLoss + CalculateNLOSvLoss(Source, Destination, TxHeight, RxHeight, Distance3d, vehicle_obstacles);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state == EPathState::LOS)
|
||||
{
|
||||
// full two ray path loss
|
||||
PathLoss = CalculateTwoRayPathLoss(Distance3d, TxHeight, RxHeight);
|
||||
}
|
||||
else if (state == EPathState::NLOSb)
|
||||
{
|
||||
// log distance path loss
|
||||
PathLoss = (m_fspl_d0 + 10.0 * path_loss_exponent * log10(Distance3d / reference_distance_fspl));
|
||||
}
|
||||
else
|
||||
{
|
||||
// fspl + knife edge
|
||||
// fspl
|
||||
double free_space_loss = 20.0 * log10(Distance3d) + 20.0 * log10(4.0 * PI / lambda);
|
||||
// add the knife edge vehicle blockage loss
|
||||
PathLoss = free_space_loss + CalculateNLOSvLoss(Source, Destination, TxHeight, RxHeight, Distance3d, vehicle_obstacles);
|
||||
}
|
||||
}
|
||||
|
||||
// add random shadows
|
||||
ShadowFadingLoss = CalculateShadowFading(state);
|
||||
return PathLoss + ShadowFadingLoss;
|
||||
}
|
||||
|
||||
bool PathLossModel::IsVehicle(const FHitResult &HitInfo)
|
||||
{
|
||||
bool Vehicle = false;
|
||||
const FActorRegistry &Registry = mCarlaEpisode->GetActorRegistry();
|
||||
|
||||
const AActor *actor = HitInfo.Actor.Get();
|
||||
|
||||
if (actor != nullptr)
|
||||
{
|
||||
|
||||
const FCarlaActor *view = Registry.FindCarlaActor(actor);
|
||||
if (view)
|
||||
{
|
||||
if (view->GetActorType() == FCarlaActor::ActorType::Vehicle)
|
||||
{
|
||||
Vehicle = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Vehicle;
|
||||
}
|
||||
|
||||
bool PathLossModel::HitIsSelfOrOther(const FHitResult &HitInfo, AActor *OtherActor)
|
||||
{
|
||||
const AActor *actor = HitInfo.Actor.Get();
|
||||
if (actor != nullptr)
|
||||
{
|
||||
if (actor == mActorOwner)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (actor == OtherActor)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PathLossModel::GetLocationIfVehicle(const FVector CurrentActorLocation, const FHitResult &HitInfo, const double reference_z, FVector &location)
|
||||
{
|
||||
// reference_z in cm
|
||||
bool Vehicle = false;
|
||||
const FActorRegistry &Registry = mCarlaEpisode->GetActorRegistry();
|
||||
|
||||
const AActor *actor = HitInfo.Actor.Get();
|
||||
|
||||
if (actor != nullptr)
|
||||
{
|
||||
|
||||
const FCarlaActor *view = Registry.FindCarlaActor(actor);
|
||||
if (view)
|
||||
{
|
||||
if (view->GetActorType() == FCarlaActor::ActorType::Vehicle)
|
||||
{
|
||||
Vehicle = true;
|
||||
location = actor->GetTransform().GetLocation();
|
||||
location.Z = location.Z - reference_z + (actor->GetSimpleCollisionHalfHeight() * 2.0) + 2.0;
|
||||
location.Z = location.Z / 100.0f;
|
||||
// cm to m
|
||||
location.X /= 100.0f;
|
||||
location.Y /= 100.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Vehicle;
|
||||
}
|
||||
|
||||
void PathLossModel::CalculateFSPL_d0()
|
||||
{
|
||||
m_fspl_d0 = 20.0 * log10(reference_distance_fspl) + 20.0 * log10(Frequency) + 20.0 * log10(4.0 * PI / c_speedoflight);
|
||||
}
|
||||
|
||||
// Following ETSI TR 103 257-1 V1.1.1 (2019-05: from WINNER Project Board: "D5.3 - WINNER+ Final Channel Models", 30 06 2010.
|
||||
float PathLossModel::CalculatePathLoss_WINNER(EPathState state, double Distance)
|
||||
{
|
||||
|
||||
if (state == EPathState::NLOSb)
|
||||
{
|
||||
// Distance should be euclidean here.
|
||||
return 36.85f + 30.0f * log10(Distance) + 18.9f * log10(Frequency_GHz);
|
||||
}
|
||||
else // LOS, NLOSv
|
||||
{
|
||||
if (scenario == EScenario::Highway)
|
||||
{
|
||||
return 32.4f + 20.0f * log10(Distance) + 20.0f * log10(Frequency_GHz);
|
||||
}
|
||||
else // Rural or Urban
|
||||
{
|
||||
return 38.77f + 16.7f * log10(Distance) + 18.2f * log10(Frequency_GHz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Following ETSI TR 103 257-1 V1.1.1 Table 6: Shadow-fading parameter σ for V2V
|
||||
float PathLossModel::CalculateShadowFading(EPathState state)
|
||||
{
|
||||
const float Mean = 0.0f;
|
||||
float std_dev_dB; // = 5.2;
|
||||
if (use_etsi_fading)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case EPathState::LOS:
|
||||
switch (scenario)
|
||||
{
|
||||
case EScenario::Highway:
|
||||
std_dev_dB = 3.3f;
|
||||
break;
|
||||
case EScenario::Urban:
|
||||
std_dev_dB = 5.2f;
|
||||
break;
|
||||
case EScenario::Rural:
|
||||
// no known values in ETSI Standard, take middle of Highway and Urban
|
||||
std_dev_dB = 4.25f;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EPathState::NLOSb:
|
||||
switch (scenario)
|
||||
{
|
||||
// Note: according to ETSI, NLOSb is not applicable in Highway scenario, only Urban
|
||||
// we use the same std_dev for all three scenarios if in NLOSb
|
||||
case EScenario::Highway:
|
||||
std_dev_dB = 6.8f;
|
||||
break;
|
||||
case EScenario::Urban:
|
||||
std_dev_dB = 6.8f;
|
||||
break;
|
||||
case EScenario::Rural:
|
||||
std_dev_dB = 6.8f;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EPathState::NLOSv:
|
||||
switch (scenario)
|
||||
{
|
||||
case EScenario::Highway:
|
||||
std_dev_dB = 3.8f;
|
||||
break;
|
||||
case EScenario::Urban:
|
||||
std_dev_dB = 5.3f;
|
||||
break;
|
||||
case EScenario::Rural:
|
||||
// no known values in ETSI Standard, take middle of Highway and Urban
|
||||
std_dev_dB = 4.55f;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// custom fading param
|
||||
std_dev_dB = custom_fading_stddev;
|
||||
}
|
||||
|
||||
// in dB
|
||||
return mRandomEngine->GetNormalDistribution(Mean, std_dev_dB);
|
||||
}
|
||||
|
||||
float PathLossModel::CalculateTwoRayPathLossSimple(double Distance3d, double TxHeight, double RxHeight)
|
||||
{
|
||||
// simplified Two Ray Path Loss (https://en.wikipedia.org/wiki/Two-ray_ground-reflection_model)
|
||||
// is only a valid assumption, if distance >> 4 pi TxHeight * RxHeight / lambda
|
||||
// with f=5.9 Ghz -> lambda = c/ f = 0.05m
|
||||
// and with average antenna height 2m: distance >> 1000m
|
||||
return 40 * log10(Distance3d) - 10 * log10(TxHeight * TxHeight * RxHeight * RxHeight);
|
||||
}
|
||||
|
||||
double PathLossModel::CalculateTwoRayPathLoss(double Distance3d, double TxHeight, double RxHeight)
|
||||
{
|
||||
// tx and rx height in m
|
||||
// distance 3d is LOS in m
|
||||
double d_ground = sqrt(std::pow(Distance3d, 2) - std::pow(TxHeight - RxHeight, 2));
|
||||
|
||||
// reflected path
|
||||
// d_reflection = sqrt(d_ground^2+(ht+hr)^2) -> with d_ground = sqrt(d_los^2 - (ht-hr)^2):
|
||||
double d_refl = sqrt(std::pow(Distance3d, 2) + 4.0 * TxHeight * RxHeight);
|
||||
|
||||
// Sine and cosine of incident angle
|
||||
double sin_theta = (TxHeight + RxHeight) / d_refl;
|
||||
double cos_theta = d_ground / d_refl;
|
||||
|
||||
double gamma = (sin_theta - sqrt(epsilon_r - std::pow(cos_theta, 2))) / (sin_theta + sqrt(epsilon_r - std::pow(cos_theta, 2)));
|
||||
|
||||
double phi = (2.0 * PI / lambda * (Distance3d - d_refl));
|
||||
|
||||
return 20 * log10(4.0 * PI * d_ground / lambda * 1.0 / sqrt(std::pow(1 + gamma * cos(phi), 2) + std::pow(gamma, 2) * std::pow(sin(phi), 2)));
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
|
||||
// Karlsruhe Institute of Technology
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
using ActorPowerMap = std::map<AActor *, float>;
|
||||
using ActorPowerPair = std::pair<AActor *, float>;
|
||||
|
||||
enum EPathState
|
||||
{
|
||||
LOS,
|
||||
NLOSb,
|
||||
NLOSv
|
||||
};
|
||||
|
||||
enum EPathLossModel
|
||||
{
|
||||
Winner,
|
||||
Geometric,
|
||||
};
|
||||
|
||||
enum EScenario
|
||||
{
|
||||
Highway,
|
||||
Rural,
|
||||
Urban
|
||||
};
|
||||
|
||||
class PathLossModel
|
||||
{
|
||||
public:
|
||||
PathLossModel(URandomEngine *random_engine);
|
||||
void SetOwner(AActor *Owner);
|
||||
void SetScenario(EScenario scenario);
|
||||
void Simulate(const std::vector<ActorPowerPair> ActorList, UCarlaEpisode *CarlaEpisode, UWorld *World);
|
||||
ActorPowerMap GetReceiveActorPowerList();
|
||||
void SetParams(const float TransmitPower,
|
||||
const float ReceiverSensitivity,
|
||||
const float Frequency,
|
||||
const float combined_antenna_gain,
|
||||
const float path_loss_exponent,
|
||||
const float reference_distance_fspl,
|
||||
const float filter_distance,
|
||||
const bool use_etsi_fading,
|
||||
const float custom_fading_stddev);
|
||||
float GetTransmitPower() { return TransmitPower; }
|
||||
void SetPathLossModel(const EPathLossModel path_loss_model);
|
||||
|
||||
private:
|
||||
// diffraction for NLOSv
|
||||
double CalcVehicleLoss(const double d1, const double d2, const double h);
|
||||
// powers
|
||||
float CalculateReceivedPower(AActor *OtherActor,
|
||||
const float OtherTransmitPower,
|
||||
const FVector Source,
|
||||
const FVector Destination,
|
||||
const double Distance3d,
|
||||
const double ht,
|
||||
const double ht_local,
|
||||
const double hr,
|
||||
const double hr_local,
|
||||
const double reference_z);
|
||||
void EstimatePathStateAndVehicleObstacles(AActor *OtherActor, FVector Source, double TxHeight, double RxHeight, double reference_z, EPathState &state, std::vector<FVector> &vehicle_obstacles);
|
||||
double MakeVehicleBlockageLoss(double TxHeight, double RxHeight, double obj_height, double obj_distance);
|
||||
// variables
|
||||
AActor *mActorOwner;
|
||||
UCarlaEpisode *mCarlaEpisode;
|
||||
UWorld *mWorld;
|
||||
URandomEngine *mRandomEngine;
|
||||
|
||||
ActorPowerMap mReceiveActorPowerList;
|
||||
FVector CurrentActorLocation;
|
||||
|
||||
// constants
|
||||
constexpr static float c_speedoflight = 299792458.0; // m/s
|
||||
|
||||
// full two ray path loss
|
||||
const double epsilon_r = 1.02;
|
||||
|
||||
// params
|
||||
static double Frequency_GHz; // 5.9f;//5.9 GHz
|
||||
static double Frequency; // Frequency_GHz * std::pow(10,9);
|
||||
static double lambda; // c_speedoflight/Frequency;
|
||||
float reference_distance_fspl; // m
|
||||
float TransmitPower; // dBm
|
||||
float ReceiverSensitivity; // dBm
|
||||
EScenario scenario;
|
||||
float path_loss_exponent; // no unit, default 2.7;
|
||||
float filter_distance; // in meters default 500.0
|
||||
EPathLossModel model;
|
||||
bool use_etsi_fading;
|
||||
float custom_fading_stddev;
|
||||
float combined_antenna_gain; // 10.0 dBi
|
||||
|
||||
// dependent params that are precalculated on setting of params
|
||||
float m_fspl_d0;
|
||||
|
||||
protected:
|
||||
/// Method that allow to preprocess if the rays will be traced.
|
||||
|
||||
float ComputeLoss(AActor *OtherActor, FVector Source, FVector Destination, double Distance3d, double TxHeight, double RxHeight, double reference_z);
|
||||
bool IsVehicle(const FHitResult &HitInfo);
|
||||
bool GetLocationIfVehicle(const FVector CurrentActorLocation, const FHitResult &HitInfo, const double reference_z, FVector &location);
|
||||
bool HitIsSelfOrOther(const FHitResult &HitInfo, AActor *OtherActor);
|
||||
float CalculatePathLoss_WINNER(EPathState state, double Distance);
|
||||
double CalculateNLOSvLoss(const FVector Source, const FVector Destination, const double TxHeight, const double RxHeight, const double RxDistance3d, std::vector<FVector> &vehicle_obstacles);
|
||||
|
||||
float CalculateShadowFading(EPathState state);
|
||||
|
||||
// full two ray model
|
||||
double CalculateTwoRayPathLoss(double Distance3d, double TxHeight, double RxHeight);
|
||||
// simplified two ray model
|
||||
float CalculateTwoRayPathLossSimple(double Distance3d, double TxHeight, double RxHeight);
|
||||
|
||||
// functions for precalculation
|
||||
void CalculateFSPL_d0();
|
||||
TArray<FHitResult> HitResult;
|
||||
};
|
|
@ -0,0 +1,234 @@
|
|||
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
|
||||
// Karlsruhe Institute of Technology
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "Carla.h"
|
||||
#include "Carla/Sensor/V2XSensor.h"
|
||||
#include "Carla/Actor/ActorBlueprintFunctionLibrary.h"
|
||||
#include "Carla/Game/CarlaEpisode.h"
|
||||
#include "Carla/Vehicle/CarlaWheeledVehicle.h"
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include "V2X/CaService.h"
|
||||
#include "V2XSensor.h"
|
||||
#include "V2X/PathLossModel.h"
|
||||
std::list<AActor *> AV2XSensor::mV2XActorContainer;
|
||||
AV2XSensor::ActorV2XDataMap AV2XSensor::mActorV2XDataMap;
|
||||
|
||||
AV2XSensor::AV2XSensor(const FObjectInitializer &ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
RandomEngine = CreateDefaultSubobject<URandomEngine>(TEXT("RandomEngine"));
|
||||
|
||||
// Init path loss model
|
||||
PathLossModelObj = new PathLossModel(RandomEngine);
|
||||
CaServiceObj = new CaService(RandomEngine);
|
||||
}
|
||||
|
||||
void AV2XSensor::SetOwner(AActor *Owner)
|
||||
{
|
||||
UE_LOG(LogCarla, Warning, TEXT("V2XSensor: called setowner with %p"), Owner);
|
||||
if (GetOwner() != nullptr)
|
||||
{
|
||||
AV2XSensor::mV2XActorContainer.remove(GetOwner());
|
||||
UE_LOG(LogCarla, Warning, TEXT("V2XSensor: removed old owner %p"), GetOwner());
|
||||
}
|
||||
|
||||
Super::SetOwner(Owner);
|
||||
|
||||
// Store the actor into the static list if the actor details are not available
|
||||
if (Owner != nullptr)
|
||||
{
|
||||
if (std::find(AV2XSensor::mV2XActorContainer.begin(), AV2XSensor::mV2XActorContainer.end(), Owner) == AV2XSensor::mV2XActorContainer.end())
|
||||
{
|
||||
AV2XSensor::mV2XActorContainer.push_back(Owner);
|
||||
UE_LOG(LogCarla, Warning, TEXT("V2XSensor: added owner, length now %d"), AV2XSensor::mV2XActorContainer.size());
|
||||
}
|
||||
UWorld *world = GetWorld();
|
||||
CaServiceObj->SetOwner(world, Owner);
|
||||
PathLossModelObj->SetOwner(Owner);
|
||||
}
|
||||
}
|
||||
|
||||
FActorDefinition AV2XSensor::GetSensorDefinition()
|
||||
{
|
||||
return UActorBlueprintFunctionLibrary::MakeV2XDefinition();
|
||||
}
|
||||
|
||||
/* Function to add configurable parameters*/
|
||||
void AV2XSensor::Set(const FActorDescription &ActorDescription)
|
||||
{
|
||||
UE_LOG(LogCarla, Warning, TEXT("V2XSensor: Set function called"));
|
||||
Super::Set(ActorDescription);
|
||||
UActorBlueprintFunctionLibrary::SetV2X(ActorDescription, this);
|
||||
}
|
||||
|
||||
void AV2XSensor::SetCaServiceParams(const float GenCamMin, const float GenCamMax, const bool FixedRate)
|
||||
{
|
||||
// forward parameters to CaService Obj
|
||||
CaServiceObj->SetParams(GenCamMin, GenCamMax, FixedRate);
|
||||
}
|
||||
|
||||
void AV2XSensor::SetPropagationParams(const float TransmitPower,
|
||||
const float ReceiverSensitivity,
|
||||
const float Frequency,
|
||||
const float combined_antenna_gain,
|
||||
const float path_loss_exponent,
|
||||
const float reference_distance_fspl,
|
||||
const float filter_distance,
|
||||
const bool use_etsi_fading,
|
||||
const float custom_fading_stddev)
|
||||
{
|
||||
// forward parameters to PathLossModel Obj
|
||||
PathLossModelObj->SetParams(TransmitPower, ReceiverSensitivity, Frequency, combined_antenna_gain, path_loss_exponent, reference_distance_fspl, filter_distance, use_etsi_fading, custom_fading_stddev);
|
||||
}
|
||||
|
||||
void AV2XSensor::SetPathLossModel(const EPathLossModel path_loss_model)
|
||||
{
|
||||
PathLossModelObj->SetPathLossModel(path_loss_model);
|
||||
}
|
||||
|
||||
void AV2XSensor::SetScenario(EScenario scenario)
|
||||
{
|
||||
PathLossModelObj->SetScenario(scenario);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function stores the actor details in to the static list.
|
||||
* Calls the CaService object to generate CAM message
|
||||
* Stores the message in static map
|
||||
*/
|
||||
void AV2XSensor::PrePhysTick(float DeltaSeconds)
|
||||
{
|
||||
Super::PrePhysTick(DeltaSeconds);
|
||||
// Clear the message created during the last sim cycle
|
||||
if (GetOwner())
|
||||
{
|
||||
AV2XSensor::mActorV2XDataMap.erase(GetOwner());
|
||||
|
||||
// Step 0: Create message to send, if triggering conditions fulfilled
|
||||
// this needs to be done in pre phys tick to enable synchronous reception in all other v2x sensors
|
||||
// Check whether the message is generated
|
||||
if (CaServiceObj->Trigger(DeltaSeconds))
|
||||
{
|
||||
// If message is generated store it
|
||||
// make a pair of message and sending power
|
||||
// if different v2x sensors send with different power, we need to store that
|
||||
carla::sensor::data::CAMData cam_pw;
|
||||
cam_pw.Message = CaServiceObj->GetCamMessage();
|
||||
cam_pw.Power = PathLossModelObj->GetTransmitPower();
|
||||
AV2XSensor::mActorV2XDataMap.insert({GetOwner(), cam_pw});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AV2XSensor::SetAccelerationStandardDeviation(const FVector &Vec)
|
||||
{
|
||||
CaServiceObj->SetAccelerationStandardDeviation(Vec);
|
||||
}
|
||||
|
||||
void AV2XSensor::SetGNSSDeviation(const float noise_lat_stddev,
|
||||
const float noise_lon_stddev,
|
||||
const float noise_alt_stddev,
|
||||
const float noise_head_stddev,
|
||||
const float noise_lat_bias,
|
||||
const float noise_lon_bias,
|
||||
const float noise_alt_bias,
|
||||
const float noise_head_bias)
|
||||
{
|
||||
CaServiceObj->SetGNSSDeviation(noise_lat_stddev,
|
||||
noise_lon_stddev,
|
||||
noise_alt_stddev,
|
||||
noise_head_stddev,
|
||||
noise_lat_bias,
|
||||
noise_lon_bias,
|
||||
noise_alt_bias,
|
||||
noise_head_bias);
|
||||
}
|
||||
|
||||
void AV2XSensor::SetVelDeviation(const float noise_vel_stddev)
|
||||
{
|
||||
CaServiceObj->SetVelDeviation(noise_vel_stddev);
|
||||
}
|
||||
|
||||
void AV2XSensor::SetYawrateDeviation(const float noise_yawrate_stddev, const float noise_yawrate_bias)
|
||||
{
|
||||
CaServiceObj->SetYawrateDeviation(noise_yawrate_stddev, noise_yawrate_bias);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function takes care of sending messages to the current actor.
|
||||
* First simulates the communication by calling LOSComm object.
|
||||
* If there is a list present then messages from those list are sent to the current actor
|
||||
*/
|
||||
void AV2XSensor::PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaTime)
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(AV2XSensor::PostPhysTick);
|
||||
if (GetOwner())
|
||||
{
|
||||
// Step 1: Create an actor list which has messages to send targeting this v2x sensor instance
|
||||
std::vector<ActorPowerPair> ActorPowerList;
|
||||
for (const auto &pair : AV2XSensor::mActorV2XDataMap)
|
||||
{
|
||||
if (pair.first != GetOwner())
|
||||
{
|
||||
ActorPowerPair actor_power_pair;
|
||||
actor_power_pair.first = pair.first;
|
||||
// actor sending with transmit power
|
||||
actor_power_pair.second = pair.second.Power;
|
||||
ActorPowerList.push_back(actor_power_pair);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Simulate the communication for the actors in actor list to current actor.
|
||||
if (!ActorPowerList.empty())
|
||||
{
|
||||
UCarlaEpisode *carla_episode = UCarlaStatics::GetCurrentEpisode(GetWorld());
|
||||
PathLossModelObj->Simulate(ActorPowerList, carla_episode, GetWorld());
|
||||
// Step 3: Get the list of actors who can send message to current actor, and the receive power of their messages.
|
||||
ActorPowerMap actor_receivepower_map = PathLossModelObj->GetReceiveActorPowerList();
|
||||
// Step 4: Retrieve the messages of the actors that are received
|
||||
|
||||
// get registry to retrieve carla actor IDs
|
||||
const FActorRegistry &Registry = carla_episode->GetActorRegistry();
|
||||
|
||||
AV2XSensor::V2XDataList msg_received_power_list;
|
||||
for (const auto &pair : actor_receivepower_map)
|
||||
{
|
||||
// Note: AActor* sender_actor = pair.first;
|
||||
carla::sensor::data::CAMData send_msg_and_pw = AV2XSensor::mActorV2XDataMap.at(pair.first);
|
||||
carla::sensor::data::CAMData received_msg_and_pw;
|
||||
// sent CAM
|
||||
received_msg_and_pw.Message = send_msg_and_pw.Message;
|
||||
// receive power
|
||||
received_msg_and_pw.Power = pair.second;
|
||||
|
||||
msg_received_power_list.push_back(received_msg_and_pw);
|
||||
}
|
||||
|
||||
WriteMessageToV2XData(msg_received_power_list);
|
||||
}
|
||||
// Step 5: Send message
|
||||
|
||||
if (mV2XData.GetMessageCount() > 0)
|
||||
{
|
||||
auto DataStream = GetDataStream(*this);
|
||||
DataStream.SerializeAndSend(*this, mV2XData, DataStream.PopBufferFromPool());
|
||||
}
|
||||
mV2XData.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Function the store the message into the structure so it can be sent to python client
|
||||
*/
|
||||
void AV2XSensor::WriteMessageToV2XData(const AV2XSensor::V2XDataList &msg_received_power_list)
|
||||
{
|
||||
for (const auto &elem : msg_received_power_list)
|
||||
{
|
||||
mV2XData.WriteMessage(elem);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
|
||||
// Karlsruhe Institute of Technology
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Carla/Sensor/Sensor.h"
|
||||
|
||||
#include "Carla/Actor/ActorDefinition.h"
|
||||
#include "Carla/Actor/ActorDescription.h"
|
||||
#include <carla/sensor/data/V2XData.h>
|
||||
#include "V2X/CaService.h"
|
||||
#include "V2X/PathLossModel.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include "V2XSensor.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class CARLA_API AV2XSensor : public ASensor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
using FV2XData = carla::sensor::data::CAMDataS;
|
||||
using ActorV2XDataMap = std::map<AActor *, carla::sensor::data::CAMData>;
|
||||
using V2XDataList = std::vector<carla::sensor::data::CAMData>;
|
||||
|
||||
public:
|
||||
AV2XSensor(const FObjectInitializer &ObjectInitializer);
|
||||
|
||||
static FActorDefinition GetSensorDefinition();
|
||||
|
||||
void Set(const FActorDescription &ActorDescription) override;
|
||||
|
||||
void SetCaServiceParams(const float GenCamMin, const float GenCamMax, const bool FixedRate);
|
||||
void SetPropagationParams(const float TransmitPower,
|
||||
const float ReceiverSensitivity,
|
||||
const float Frequency,
|
||||
const float combined_antenna_gain,
|
||||
const float path_loss_exponent,
|
||||
const float reference_distance_fspl,
|
||||
const float filter_distance,
|
||||
const bool use_etsi_fading,
|
||||
const float custom_fading_stddev);
|
||||
void SetScenario(EScenario scenario);
|
||||
|
||||
// CAM params
|
||||
void SetAccelerationStandardDeviation(const FVector &Vec);
|
||||
void SetGNSSDeviation(const float noise_lat_stddev,
|
||||
const float noise_lon_stddev,
|
||||
const float noise_alt_stddev,
|
||||
const float noise_head_stddev,
|
||||
const float noise_lat_bias,
|
||||
const float noise_lon_bias,
|
||||
const float noise_alt_bias,
|
||||
const float noise_head_bias);
|
||||
void SetVelDeviation(const float noise_vel_stddev);
|
||||
void SetYawrateDeviation(const float noise_yawrate_stddev, const float noise_yawrate_bias);
|
||||
void SetPathLossModel(const EPathLossModel path_loss_model);
|
||||
|
||||
virtual void PrePhysTick(float DeltaSeconds) override;
|
||||
virtual void PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaTime) override;
|
||||
void SetOwner(AActor *Owner) override;
|
||||
|
||||
private:
|
||||
static std::list<AActor *> mV2XActorContainer;
|
||||
CaService *CaServiceObj;
|
||||
PathLossModel *PathLossModelObj;
|
||||
|
||||
// store data
|
||||
static ActorV2XDataMap mActorV2XDataMap;
|
||||
FV2XData mV2XData;
|
||||
|
||||
// write
|
||||
void WriteMessageToV2XData(const V2XDataList &msg_received_power_list);
|
||||
};
|
|
@ -20,6 +20,7 @@
|
|||
#include "Carla/Util/NavigationMesh.h"
|
||||
#include "Carla/Util/RayTracer.h"
|
||||
#include "Carla/Vehicle/CarlaWheeledVehicle.h"
|
||||
#include "Carla/Sensor/CustomV2XSensor.h"
|
||||
#include "Carla/Walker/WalkerController.h"
|
||||
#include "Carla/Walker/WalkerBase.h"
|
||||
#include "GameFramework/CharacterMovementComponent.h"
|
||||
|
@ -64,6 +65,7 @@
|
|||
#include <carla/rpc/VehiclePhysicsControl.h>
|
||||
#include <carla/rpc/VehicleLightState.h>
|
||||
#include <carla/rpc/VehicleLightStateList.h>
|
||||
#include <carla/rpc/VehicleTelemetryData.h>
|
||||
#include <carla/rpc/WalkerBoneControlIn.h>
|
||||
#include <carla/rpc/WalkerBoneControlOut.h>
|
||||
#include <carla/rpc/WalkerControl.h>
|
||||
|
@ -964,6 +966,41 @@ BIND_SYNC(is_sensor_enabled_for_ros) << [this](carla::streaming::detail::stream_
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
BIND_SYNC(send) << [this](
|
||||
cr::ActorId ActorId,
|
||||
std::string message) -> R<void>
|
||||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
FCarlaActor* CarlaActor = Episode->FindCarlaActor(ActorId);
|
||||
if (!CarlaActor)
|
||||
{
|
||||
return RespondError(
|
||||
"send",
|
||||
ECarlaServerResponse::ActorNotFound,
|
||||
" Actor Id: " + FString::FromInt(ActorId));
|
||||
}
|
||||
|
||||
if (CarlaActor->IsDormant())
|
||||
{
|
||||
return RespondError(
|
||||
"send",
|
||||
ECarlaServerResponse::FunctionNotAvailiableWhenDormant,
|
||||
" Actor Id: " + FString::FromInt(ActorId));
|
||||
}
|
||||
ACustomV2XSensor* Sensor = Cast<ACustomV2XSensor>(CarlaActor->GetActor());
|
||||
if (!Sensor)
|
||||
{
|
||||
return RespondError(
|
||||
"send",
|
||||
ECarlaServerResponse::ActorTypeMismatch,
|
||||
" Actor Id: " + FString::FromInt(ActorId));
|
||||
}
|
||||
|
||||
Sensor->Send(cr::ToFString(message));
|
||||
return R<void>::Success();
|
||||
};
|
||||
|
||||
// ~~ Actor physics ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
BIND_SYNC(set_actor_location) << [this](
|
||||
|
@ -2209,6 +2246,31 @@ BIND_SYNC(is_sensor_enabled_for_ros) << [this](carla::streaming::detail::stream_
|
|||
return R<void>::Success();
|
||||
};
|
||||
|
||||
BIND_SYNC(get_telemetry_data) << [this](
|
||||
cr::ActorId ActorId) -> R<cr::VehicleTelemetryData>
|
||||
{
|
||||
REQUIRE_CARLA_EPISODE();
|
||||
FCarlaActor* CarlaActor = Episode->FindCarlaActor(ActorId);
|
||||
if (!CarlaActor)
|
||||
{
|
||||
return RespondError(
|
||||
"get_telemetry_data",
|
||||
ECarlaServerResponse::ActorNotFound,
|
||||
" Actor Id: " + FString::FromInt(ActorId));
|
||||
}
|
||||
FVehicleTelemetryData TelemetryData;
|
||||
ECarlaServerResponse Response =
|
||||
CarlaActor->GetVehicleTelemetryData(TelemetryData);
|
||||
if (Response != ECarlaServerResponse::Success)
|
||||
{
|
||||
return RespondError(
|
||||
"get_telemetry_data",
|
||||
Response,
|
||||
" Actor Id: " + FString::FromInt(ActorId));
|
||||
}
|
||||
return cr::VehicleTelemetryData(TelemetryData);
|
||||
};
|
||||
|
||||
BIND_SYNC(show_vehicle_debug_telemetry) << [this](
|
||||
cr::ActorId ActorId,
|
||||
bool bEnabled) -> R<void>
|
||||
|
|
|
@ -814,6 +814,56 @@ void ACarlaWheeledVehicle::DeactivateVelocityControl()
|
|||
VelocityControl->Deactivate();
|
||||
}
|
||||
|
||||
FVehicleTelemetryData ACarlaWheeledVehicle::GetVehicleTelemetryData() const
|
||||
{
|
||||
FVehicleTelemetryData TelemetryData;
|
||||
|
||||
auto *MovementComponent = GetVehicleMovement();
|
||||
|
||||
// Vehicle telemetry data
|
||||
TelemetryData.Speed = GetVehicleForwardSpeed() / 100.0f; // From cm/s to m/s
|
||||
TelemetryData.Steer = LastAppliedControl.Steer;
|
||||
TelemetryData.Throttle = LastAppliedControl.Throttle;
|
||||
TelemetryData.Brake = LastAppliedControl.Brake;
|
||||
TelemetryData.EngineRPM = MovementComponent->GetEngineRotationSpeed();
|
||||
TelemetryData.Gear = GetVehicleCurrentGear();
|
||||
TelemetryData.Drag = MovementComponent->DebugDragMagnitude / 100.0f; // kg*cm/s2 to Kg*m/s2
|
||||
|
||||
// Wheels telemetry data
|
||||
FPhysXVehicleManager* MyVehicleManager = FPhysXVehicleManager::GetVehicleManagerFromScene(GetWorld()->GetPhysicsScene());
|
||||
|
||||
SCOPED_SCENE_READ_LOCK(MyVehicleManager->GetScene());
|
||||
PxWheelQueryResult* WheelsStates = MyVehicleManager->GetWheelsStates_AssumesLocked(MovementComponent);
|
||||
check(WheelsStates);
|
||||
|
||||
TArray<FWheelTelemetryData> Wheels;
|
||||
for (uint32 w = 0; w < MovementComponent->PVehicle->mWheelsSimData.getNbWheels(); ++w)
|
||||
{
|
||||
FWheelTelemetryData WheelTelemetryData;
|
||||
|
||||
WheelTelemetryData.TireFriction = WheelsStates[w].tireFriction;
|
||||
WheelTelemetryData.LatSlip = FMath::RadiansToDegrees(WheelsStates[w].lateralSlip);
|
||||
WheelTelemetryData.LongSlip = WheelsStates[w].longitudinalSlip;
|
||||
WheelTelemetryData.Omega = MovementComponent->PVehicle->mWheelsDynData.getWheelRotationSpeed(w);
|
||||
|
||||
UVehicleWheel* Wheel = MovementComponent->Wheels[w];
|
||||
WheelTelemetryData.TireLoad = Wheel->DebugTireLoad / 100.0f;
|
||||
WheelTelemetryData.NormalizedTireLoad = Wheel->DebugNormalizedTireLoad;
|
||||
WheelTelemetryData.Torque = Wheel->DebugWheelTorque / (100.0f * 100.0f); // From cm2 to m2
|
||||
WheelTelemetryData.LongForce = Wheel->DebugLongForce / 100.f;
|
||||
WheelTelemetryData.LatForce = Wheel->DebugLatForce / 100.f;
|
||||
WheelTelemetryData.NormalizedLongForce = (FMath::Abs(WheelTelemetryData.LongForce)*WheelTelemetryData.NormalizedTireLoad) / (WheelTelemetryData.TireLoad);
|
||||
WheelTelemetryData.NormalizedLatForce = (FMath::Abs(WheelTelemetryData.LatForce)*WheelTelemetryData.NormalizedTireLoad) / (WheelTelemetryData.TireLoad);
|
||||
|
||||
Wheels.Add(WheelTelemetryData);
|
||||
}
|
||||
|
||||
TelemetryData.Wheels = Wheels;
|
||||
|
||||
return TelemetryData;
|
||||
|
||||
}
|
||||
|
||||
void ACarlaWheeledVehicle::ShowDebugTelemetry(bool Enabled)
|
||||
{
|
||||
if (GetWorld()->GetFirstPlayerController())
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "Vehicle/VehicleLightState.h"
|
||||
#include "Vehicle/VehicleInputPriority.h"
|
||||
#include "Vehicle/VehiclePhysicsControl.h"
|
||||
#include "Vehicle/VehicleTelemetryData.h"
|
||||
#include "VehicleVelocityControl.h"
|
||||
#include "WheeledVehicleMovementComponent4W.h"
|
||||
#include "WheeledVehicleMovementComponentNW.h"
|
||||
|
@ -240,6 +241,9 @@ public:
|
|||
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
|
||||
void DeactivateVelocityControl();
|
||||
|
||||
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
|
||||
FVehicleTelemetryData GetVehicleTelemetryData() const;
|
||||
|
||||
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
|
||||
void ShowDebugTelemetry(bool Enabled);
|
||||
|
||||
|
|
|
@ -1310,13 +1310,13 @@ void UCustomTerrainPhysicsComponent::BeginPlay()
|
|||
SparseMap.SavePath = SavePath;
|
||||
// Creating the FileManager
|
||||
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
|
||||
if( FileManager.CreateDirectory(*SavePath)){
|
||||
/*if( FileManager.CreateDirectory(*SavePath)){
|
||||
UE_LOG(LogCarla, Warning,
|
||||
TEXT("Folder was created at %s"), *SavePath);
|
||||
}else{
|
||||
UE_LOG(LogCarla, Error,
|
||||
TEXT("Folder was not created at %s"), *SavePath);
|
||||
}
|
||||
}*/
|
||||
|
||||
if(bUseDeformationPlane){
|
||||
DeformationPlaneActor = GetWorld()->SpawnActor<AStaticMeshActor>();
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
// 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 <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VehicleTelemetryData.generated.h"
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FWheelTelemetryData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(Category = "Wheel Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float TireFriction = 0.0f;
|
||||
|
||||
UPROPERTY(Category = "Wheel Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float LatSlip = 0.0f; // degrees
|
||||
|
||||
UPROPERTY(Category = "Wheel Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float LongSlip = 0.0f;
|
||||
|
||||
UPROPERTY(Category = "Wheel Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float Omega = 0.0f;
|
||||
|
||||
UPROPERTY(Category = "Wheel Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float TireLoad = 0.0f;
|
||||
|
||||
UPROPERTY(Category = "Wheel Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float NormalizedTireLoad = 0.0f;
|
||||
|
||||
UPROPERTY(Category = "Wheel Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float Torque = 0.0f; // [Nm]
|
||||
|
||||
UPROPERTY(Category = "Wheel Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float LongForce = 0.0f; // [N]
|
||||
|
||||
UPROPERTY(Category = "Wheel Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float LatForce = 0.0f; // [N]
|
||||
|
||||
UPROPERTY(Category = "Wheel Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float NormalizedLongForce = 0.0f;
|
||||
|
||||
UPROPERTY(Category = "Wheel Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float NormalizedLatForce = 0.0f;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct CARLA_API FVehicleTelemetryData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(Category = "Vehicle Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float Speed = 0.0f; // [m/s]
|
||||
|
||||
UPROPERTY(Category = "Vehicle Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float Steer = 0.0f;
|
||||
|
||||
UPROPERTY(Category = "Vehicle Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float Throttle = 0.0f;
|
||||
|
||||
UPROPERTY(Category = "Vehicle Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float Brake = 0.0f;
|
||||
|
||||
UPROPERTY(Category = "Vehicle Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float EngineRPM = 0.0f;
|
||||
|
||||
UPROPERTY(Category = "Vehicle Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
int32 Gear = 0.0f;
|
||||
|
||||
UPROPERTY(Category = "Vehicle Telemetry Data", EditAnywhere, BlueprintReadWrite)
|
||||
float Drag = 0.0f; // [N]
|
||||
|
||||
UPROPERTY(Category = "Vehicle Engine Physics Control", EditAnywhere, BlueprintReadWrite)
|
||||
TArray<FWheelTelemetryData> Wheels;
|
||||
};
|
|
@ -5,3 +5,9 @@
|
|||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "WalkerBase.h"
|
||||
|
||||
|
||||
AWalkerBase::AWalkerBase(const FObjectInitializer &ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
}
|
|
@ -16,6 +16,7 @@ class CARLA_API AWalkerBase : public ACharacter
|
|||
|
||||
GENERATED_BODY()
|
||||
|
||||
AWalkerBase(const FObjectInitializer &ObjectInitializer);
|
||||
public:
|
||||
|
||||
UPROPERTY(Category="Walker Base", BlueprintReadWrite, EditAnywhere)
|
||||
|
@ -24,6 +25,9 @@ public:
|
|||
UPROPERTY(Category="Walker Base", BlueprintReadWrite, EditAnywhere)
|
||||
float AfterLifeSpan = 10.0f;
|
||||
|
||||
UPROPERTY(Category="Walker Base", BlueprintReadWrite, EditAnywhere)
|
||||
bool bUsesWheelChair = false;
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void StartDeathLifeSpan()
|
||||
{
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -30,9 +30,10 @@ if os.name == "nt":
|
|||
editor_path = "%s/Engine/Binaries/%s/UE4Editor" % (ue4_path, sys_name)
|
||||
command = [editor_path, uproject_path, run]
|
||||
command.extend(arguments)
|
||||
full_command = editor_path + " " + uproject_path + " " + run + " " + arguments
|
||||
print("Commandlet:", command)
|
||||
print("Arguments:", arguments)
|
||||
subprocess.check_call(command, shell=True)
|
||||
subprocess.check_call(full_command, shell=True)
|
||||
elif os.name == "posix":
|
||||
sys_name = "Linux"
|
||||
editor_path = "%s/Engine/Binaries/%s/UE4Editor" % (ue4_path, sys_name)
|
||||
|
|
|
@ -293,11 +293,13 @@ AActor* UOpenDriveToMap::SpawnActorWithCheckNoCollisions(UClass* ActorClassToSpa
|
|||
void UOpenDriveToMap::GenerateTileStandalone(){
|
||||
UE_LOG(LogCarlaToolsMapGenerator, Log, TEXT("UOpenDriveToMap::GenerateTileStandalone Function called"));
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
GenerateTile();
|
||||
#else
|
||||
ExecuteTileCommandlet();
|
||||
|
||||
#endif
|
||||
UEditorLoadingAndSavingUtils::SaveDirtyPackages(true, true);
|
||||
UEditorLevelLibrary::SaveCurrentLevel();
|
||||
|
||||
}
|
||||
|
||||
void UOpenDriveToMap::GenerateTile(){
|
||||
|
@ -361,7 +363,10 @@ void UOpenDriveToMap::GenerateTile(){
|
|||
|
||||
UEditorLoadingAndSavingUtils::SaveDirtyPackages(true, true);
|
||||
UEditorLevelLibrary::SaveCurrentLevel();
|
||||
#if PLATFORM_LINUX
|
||||
RemoveFromRoot();
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ if %REMOVE_INTERMEDIATE% == true (
|
|||
"%UE4_PROJECT_FOLDER%Intermediate",
|
||||
"%UE4_PROJECT_FOLDER%Plugins\Carla\Binaries",
|
||||
"%UE4_PROJECT_FOLDER%Plugins\Carla\Intermediate",
|
||||
"%UE4_PROJECT_FOLDER%Plugins\HoudiniEngine\",
|
||||
"%UE4_PROJECT_FOLDER%.vs"
|
||||
) do (
|
||||
if exist %%G (
|
||||
|
|
|
@ -128,6 +128,10 @@ if ${REMOVE_INTERMEDIATE} ; then
|
|||
|
||||
rm -Rf ${UE4_INTERMEDIATE_FOLDERS}
|
||||
|
||||
cd Plugins
|
||||
rm -Rf HoudiniEngine
|
||||
cd ..
|
||||
|
||||
popd >/dev/null
|
||||
|
||||
fi
|
||||
|
|
|
@ -71,7 +71,7 @@ rem ============================================================================
|
|||
rem Set the visual studio solution directory
|
||||
rem
|
||||
set OSM2ODR_VSPROJECT_PATH=%INSTALLATION_DIR:/=\%osm2odr-visualstudio\
|
||||
set OSM2ODR_SOURCE_PATH=%INSTALLATION_DIR:/=\%om2odr-source\
|
||||
set OSM2ODR_SOURCE_PATH=%INSTALLATION_DIR:/=\%osm2odr-source\
|
||||
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\
|
||||
|
@ -92,24 +92,19 @@ if %REMOVE_INTERMEDIATE% == true (
|
|||
|
||||
rem Build OSM2ODR
|
||||
if %BUILD_OSM2ODR% == true (
|
||||
|
||||
if %GIT_PULL% == true (
|
||||
if not exist "%OSM2ODR_SOURCE_PATH%" git clone -b %OSM2ODR_BRANCH% %OSM2ODR_REPO% %OSM2ODR_SOURCE_PATH%
|
||||
cd "%OSM2ODR_SOURCE_PATH%"
|
||||
git fetch
|
||||
git checkout %CURRENT_OSM2ODR_COMMIT%
|
||||
cd "%INSTALLATION_DIR%"
|
||||
if not exist "%OSM2ODR_SOURCE_PATH%" (
|
||||
curl --retry 5 --retry-max-time 120 -L -o OSM2ODR.zip https://github.com/carla-simulator/sumo/archive/%CURRENT_OSM2ODR_COMMIT%.zip
|
||||
tar -xf OSM2ODR.zip
|
||||
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%"
|
||||
|
||||
echo.%GENERATOR% | findstr /C:"Visual Studio" >nul && (
|
||||
set PLATFORM=-A x64
|
||||
) || (
|
||||
set PLATFORM=
|
||||
)
|
||||
|
||||
cmake -G %GENERATOR% %PLATFORM%^
|
||||
cmake -G %GENERATOR% -A x64^
|
||||
-DCMAKE_CXX_FLAGS_RELEASE="/MD /MP"^
|
||||
-DCMAKE_INSTALL_PREFIX="%OSM2ODR_INSTALL_PATH:\=/%"^
|
||||
-DPROJ_INCLUDE_DIR=%INSTALLATION_DIR:/=\%\proj-install\include^
|
||||
|
|
|
@ -76,19 +76,18 @@ fi
|
|||
|
||||
if ${BUILD_OSM2ODR} ; then
|
||||
log "Building OSM2ODR."
|
||||
# [ ! -d ${OSM2ODR_BUILD_FOLDER} ] && mkdir ${OSM2ODR_BUILD_FOLDER}
|
||||
if ${GIT_PULL} ; then
|
||||
if [ ! -d ${OSM2ODR_SOURCE_FOLDER} ] ; then
|
||||
git clone -b ${OSM2ODR_BRANCH} ${OSM2ODR_REPO} ${OSM2ODR_SOURCE_FOLDER}
|
||||
fi
|
||||
cd ${OSM2ODR_SOURCE_FOLDER}
|
||||
git fetch
|
||||
git checkout ${CURRENT_OSM2ODR_COMMIT}
|
||||
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}
|
||||
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"
|
||||
|
|
|
@ -105,7 +105,7 @@ if ${BUILD_PYTHONAPI} ; then
|
|||
cp dist/.tmp/$(ls dist/.tmp | grep .whl) dist
|
||||
else
|
||||
/usr/bin/env python${PY_VERSION} setup.py bdist_egg bdist_wheel --dist-dir dist/.tmp --plat ${TARGET_WHEEL_PLATFORM}
|
||||
/usr/bin/env python3 -m auditwheel repair --plat ${TARGET_WHEEL_PLATFORM} --wheel-dir dist dist/.tmp/$(ls dist/.tmp | grep .whl)
|
||||
/usr/bin/env python${PY_VERSION} -m auditwheel repair --plat ${TARGET_WHEEL_PLATFORM} --wheel-dir dist dist/.tmp/$(ls dist/.tmp | grep .whl)
|
||||
fi
|
||||
|
||||
rm -rf dist/.tmp
|
||||
|
|
|
@ -94,16 +94,16 @@ for PY_VERSION in ${PY_VERSION_LIST[@]} ; do
|
|||
log "Retrieving boost."
|
||||
|
||||
start=$(date +%s)
|
||||
wget "https://archives.boost.io/release/${BOOST_VERSION}/source/${BOOST_PACKAGE_BASENAME}.tar.gz" || true
|
||||
wget "https://archives.boost.io/release/${BOOST_VERSION}/source/${BOOST_PACKAGE_BASENAME}.tar.gz" -O ${BOOST_PACKAGE_BASENAME}.tar.gz || true
|
||||
end=$(date +%s)
|
||||
echo "Elapsed Time downloading from boost webpage: $(($end-$start)) seconds"
|
||||
|
||||
# try to use the backup boost we have in Jenkins
|
||||
if [ ! -f "${BOOST_PACKAGE_BASENAME}.tar.gz" ] || [[ $(sha256sum "${BOOST_PACKAGE_BASENAME}.tar.gz") != "${BOOST_SHA256SUM}" ]] ; then
|
||||
if [ ! -f "${BOOST_PACKAGE_BASENAME}.tar.gz" ] || [[ $(sha256sum "${BOOST_PACKAGE_BASENAME}.tar.gz" | cut -d " " -f 1 ) != "${BOOST_SHA256SUM}" ]] ; then
|
||||
log "Using boost backup"
|
||||
|
||||
start=$(date +%s)
|
||||
wget "https://carla-releases.s3.us-east-005.backblazeb2.com/Backup/${BOOST_PACKAGE_BASENAME}.tar.gz" || true
|
||||
wget "https://carla-releases.s3.us-east-005.backblazeb2.com/Backup/${BOOST_PACKAGE_BASENAME}.tar.gz" -O ${BOOST_PACKAGE_BASENAME}.tar.gz || true
|
||||
end=$(date +%s)
|
||||
echo "Elapsed Time downloading from boost carla backup in backblaze: $(($end-$start)) seconds"
|
||||
|
||||
|
|
Loading…
Reference in New Issue