Compare commits

...

103 Commits

Author SHA1 Message Date
Blyron 9f6d68df04
Merge branch 'dev' into patch-2 2024-09-12 10:49:53 +02:00
AreopagX 9e94feb3a5 navigation information is now loaded when changing maps 2024-09-11 22:01:15 +02:00
MattRoweEAIF c097d7acf1
added digital twins video (#8090) 2024-08-29 14:58:48 +02:00
Daniel 334740ae53 Fixed Vector arithmetic 2024-08-28 12:58:24 +02:00
Daniel 7633334063 Corrections and additions
more setters
missing, wrong types corrected
spelling
2024-08-28 12:58:24 +02:00
Daniel 2b465bcd66 Improved Callable and callbacks signature 2024-08-28 12:58:24 +02:00
Daniel aec0b261af Added Transform.inverse_transform and corrected signature
parameter is called in_point not in_vector
2024-08-28 12:58:24 +02:00
Daniel 58e0374f4f Corrected [try_]spawn_actor keyword name 2024-08-28 12:58:24 +02:00
Daniel 26dc386724 Improved get_waypoints and Literal type hints 2024-08-28 12:58:24 +02:00
Daniel 798c9e144c Added setters for VehicleControl 2024-08-28 12:58:24 +02:00
Daniel 77856f467c Various fixes
- wrong signatures
- wrong names
2024-08-28 12:58:24 +02:00
Daniel ca81e35d59 Added self parameter to property signatures 2024-08-28 12:58:24 +02:00
Daniel da80757e27 Fixes for wrong stubs
- OpendriveGenerationParameter had no init
- missing @property
- wrong signatures
2024-08-28 12:58:24 +02:00
Daniel 453ceca112 Fix: Enum values were tuples. Added Flag or Int to Enums 2024-08-28 12:58:24 +02:00
Daniel a959577ccf Better usage of Enum if typing.Self is availiable
Using Self will not report an override / incompatible error.
2024-08-28 12:58:24 +02:00
Daniel b061f9e951 Fix spelling mistakes 2024-08-28 12:58:24 +02:00
Daniel f797e1593a Improved get_waypoint disambiguation
correctly added two overload function
2024-08-28 12:58:24 +02:00
Daniel 41e595c056 Corrected and more precise type-hints
- fixed carla.Waypoint.next_until_lane_end
2024-08-28 12:58:24 +02:00
Daniel d9c217ee3c Added stubs for HUD drawing
Functions from #7168
2024-08-28 12:58:24 +02:00
Daniel a089c3b800 Formatted some docstring to be shorter 2024-08-28 12:58:24 +02:00
Daniel 19b892f76b Fix missing @property 2024-08-28 12:58:24 +02:00
Daniel 8df99c0414 Fix intendation shadowing methods 2024-08-28 12:58:24 +02:00
Daniel 2935897950 Added type hints for `values` attribute on enums 2024-08-28 12:58:24 +02:00
Daniel ddb5834e38 Corrected Sensor.is_listening
Was changed to a function in 0.9.15. More info see: https://github.com/carla-simulator/carla/pull/7439
2024-08-28 12:58:24 +02:00
Daniel e765559384 Added undocumented variables
FutureActor
laod_world_if_different
2024-08-28 12:58:24 +02:00
Daniel df1eb25721 Disambiguated get_waypoint signature
Syntax fix (squased)
2024-08-28 12:58:24 +02:00
Daniel caac503fdb Fixed CityObjectLabels 2024-08-28 12:58:24 +02:00
Daniel 4c086ad7d9 ActorList.filter actually returns ActorList 2024-08-28 12:58:24 +02:00
Daniel 1d4450b026 Filled in missing information and types. 2024-08-28 12:58:24 +02:00
Daniel 0197e0ae5b FIX: added ApplyTransform, fixed ApplyTorque 2024-08-28 12:58:24 +02:00
Daniel de33210abd FIX: __init__ methods do not return 2024-08-28 12:58:24 +02:00
Daniel a0cff71434 Added missing return value to reload_world 2024-08-28 12:58:24 +02:00
Daniel 232cb8c250 Added missing -> World to load_world 2024-08-28 12:58:24 +02:00
Daniel 755c0d827d Removed wrong unit indication 2024-08-28 12:58:24 +02:00
Daniel 4c1104dc47 Fixed spelling misstakes 2024-08-28 12:58:24 +02:00
Daniel f275e47f4e Added missing type for Labelled Point 2024-08-28 12:58:24 +02:00
Daniel 7b2c1db39b Added DSVEventArray iterator 2024-08-28 12:58:24 +02:00
Daniel 251b293d61 Updated changelog
needs merge with dev version
2024-08-28 12:58:24 +02:00
Daniel bc6e7cd5ea Fixed missing return types 2024-08-28 12:58:24 +02:00
Daraan be8735fc28 Fixed Actor.parent
Can be None or an Actor
2024-08-28 12:58:24 +02:00
Daniel 951fcc4cc9 Fixes and missing Iterators 2024-08-28 12:58:24 +02:00
Minokori fd44ea0ca1 Add a `*.pyi` file for auto-completion & hints.
To enable auto-completion and hints in code editors such as VScode, create a `*.pyi` file. This feature is compatible with `python 3.9` and later versions.
2024-08-28 12:58:24 +02:00
MattRoweEAIF 1ef3f55c95
Docs/unit updates (#8007)
* fixed IMU units

* updated autitwheel version
2024-07-31 15:23:11 +02:00
Blyron f2695a17d1
Aaron/fixwheelchair (#8001)
* Fix OSM2ODR build

* Updated fix wheelchair default value
2024-07-31 13:10:11 +02:00
glopezdiest eeb507e585
Added inverse transform (#7999)
Co-authored-by: glopezdiest <glopez@cvc.uab.cat>
2024-07-31 10:37:32 +02:00
MattRoweEAIF 29fbcce198
Update README.md with new TinyURL links (#7988) 2024-07-25 16:02:13 +02:00
MattRoweEAIF 5c2d2978a8
fixed IMU units (#7960) 2024-07-17 12:33:47 +02:00
MattRoweEAIF 4952c74729
added cpp client build docs (#7942) 2024-07-11 14:40:52 +02:00
Blyron cf3cef936b Add control variable 2024-07-08 13:09:07 +02:00
Blyron 8ba08e1f7e Update size value 2024-07-08 13:09:07 +02:00
Blyron e349dc79c9 Add wheelchair variation 2024-07-08 13:09:07 +02:00
Daniel 4da0c74154 Rework of BasicAgent's set_destination.
Covers the 4 cases
start_location=[None (default)/ not None]
clean_queue = [True (default), False)
2024-06-21 12:46:37 +02:00
evilzs1 ec7d8fd037
Fixed fate error about number of wheels (#7800) 2024-06-18 12:04:40 +02:00
MattRoweEAIF 18035969fe
changed get_required_files docs (#7763)
* changed get_required_files docs

* fixed overwritten user data
2024-06-10 17:02:53 +02:00
Ruben Abad 2c85c528cc Merge branch 'ruben/jenkins_migration' of github.com:carla-simulator/carla into dev 2024-06-05 12:30:22 +02:00
Ruben Abad e2574609f9 doucmentation is pulled/pushed to "dev" branch 2024-06-05 12:29:36 +02:00
Ruben Abad 5287e239a3 reverting credentials 2024-06-04 15:41:49 +02:00
Ruben Abad 4fa9d42302 Merge branch 'dev' of github.com:carla-simulator/carla into dev 2024-06-04 15:26:22 +02:00
Ruben Abad dae1d58211 update credentials 2024-06-04 15:23:46 +02:00
MattRoweEAIF b69f892537
Docs/ue5 instructions (#7747)
* added UE5 build instructions

* added links in main build doc
2024-06-04 12:28:12 +02:00
Ruben Abad 76ccb9406c Merge branch 'ruben/jenkins_migration' of github.com:carla-simulator/carla into dev 2024-06-04 12:14:14 +02:00
Ruben Abad d6078abdbf reverting previous change: repo checkout is neccessary to have access to makefile 2024-06-04 12:12:57 +02:00
MattRoweEAIF 6898225f5d
added UE5 build instructions (#7743) 2024-06-04 11:56:30 +02:00
Ruben Abad 3654f6bb24 prevent test stages to download repo again 2024-06-03 16:06:15 +02:00
Ruben Abad 68ce217d26 master and dev branches do documentation upload on main branch 2024-06-03 13:40:18 +02:00
Ruben Abad 696d11f995 test only in gpu nodes 2024-06-03 13:39:34 +02:00
Daraan a06ab08c4c
Named and type-hint supporting detection results for the python agents. (#7174)
* Python agents: Created NamedTuple for Detection return types

* Python 2.7 and <3.6 compatible code

* Updated Changelog

* removed print

* Added file description

* removed unnecessary line

* Added Literal type hint for <3.8 Python

---------

Co-authored-by: glopezdiest <58212725+glopezdiest@users.noreply.github.com>
Co-authored-by: Blyron <53337103+Blyron@users.noreply.github.com>
2024-05-31 17:37:10 +02:00
joel-mb 01b1ede51a
Expose Telemetry Data (#5153)
* expose telemetry data to the client

* CHANGELOG updated

* minor fixes

* Added new telemetry parameters:

* Exposed omega instead of rpm
* Added tire_load, normalized_long_force, normalized_lat_force

---------

Co-authored-by: Blyron <53337103+Blyron@users.noreply.github.com>
2024-05-31 13:36:46 +02:00
Daraan d5c37f71b7
Corrected information that Sensor.is_listening is a method (#7439)
Co-authored-by: Blyron <53337103+Blyron@users.noreply.github.com>
2024-05-31 12:04:04 +02:00
LuisPovedaCano 6aed213f36 fixed lidar in replayer mode with vehicles and walkers 2024-05-31 11:42:31 +02:00
Blyron 317037a31e Removing useless code
Co-authored-by: Xavier Solé Nogués <xavisolesoft@gmail.com>
2024-05-31 10:56:02 +02:00
Blyron e7d13e6c0e Removed unused variable 2024-05-31 10:56:02 +02:00
Blyron e6ba65db21 Uses switches depending on line type 2024-05-31 10:56:02 +02:00
Blyron a2ae705126 hot fix ignore spectator variable on replayer 2024-05-28 13:43:20 +02:00
Aaron 7b2ff04496 Not tests V2X tick 2024-05-24 12:33:41 +02:00
joel-mb e2ccc3c519
revert patchelf version to 0.12 (#7681) 2024-05-21 15:05:12 +02:00
Blyron 6ffcdbeec9
Aaron/fix dt windows v2 (#7680)
* Fix OSM2ODR build

* Avoid remove to root in windows
2024-05-21 13:35:07 +02:00
Blyron 6886d25c13
Aaron/fixdigitaltwins windows (#7672)
* Fix OSM2ODR build

* Fixing UE4 DigitalTwins in Windows

* Deal windows specific code until find workaround on saving files

* Remove comments

---------

Co-authored-by: LuisPoveda <101111439+LuisPoveda@users.noreply.github.com>
2024-05-17 11:10:58 +02:00
Joel Moriana 22fd085f67 avoid using python system version to audit wheel 2024-05-16 17:57:48 +02:00
Joel Moriana 8774a16cb6 updated patchelf version 2024-05-16 17:57:48 +02:00
Daniel 142ae0f941 Fixed wrong sha check
sha256sum outputs <hash> <filename> failing the string check
2024-05-15 07:45:46 +02:00
Blyron 12f09009ab remove Houdini in Linux 2024-05-13 18:21:19 +02:00
Blyron 73d66006fa add removing houdini to be removed 2024-05-13 18:21:19 +02:00
Blyron 9037124f59 Fix compilation issue 2024-05-07 10:49:47 +02:00
Blyron 27b1490990 Fix OSM2ODR build 2024-05-07 10:49:47 +02:00
Daniel Grimm 7a540559a9 function name camel case 2024-05-03 12:23:02 +02:00
Daniel Grimm 441372b369 removed structs, simple calc 2024-05-03 12:23:02 +02:00
Daniel Grimm b3f0dbea66 remove doubled defs 2024-05-03 12:23:02 +02:00
Daniel Grimm bace2f1aab comments and formatting 2024-05-03 12:23:02 +02:00
Daniel Grimm 780234b9a6 add EOF 2024-05-03 12:23:02 +02:00
Daniel Grimm 52375d099b add changelog 2024-05-03 12:23:02 +02:00
Daniel Grimm 7be2803454 add EOFs 2024-05-03 12:23:02 +02:00
Daniel Grimm f9a49c50a4 remove ignore file 2024-05-03 12:23:02 +02:00
Daniel Grimm 079f822911 remove comment 2024-05-03 12:23:02 +02:00
Daniel Grimm c7cfdad9a3 v2x 2nd try 2024-05-03 12:23:02 +02:00
xavisolesoft 4da350ab2d Unzip quiet 2024-05-02 09:10:31 +02:00
xavisolesoft 1071001114 Fix windows 2024-05-02 09:10:31 +02:00
xavisolesoft a1fb7a9596 Implement OSM2ODR download retry for linux 2024-05-02 09:10:31 +02:00
Xavier Solé Nogués e351561eea Retry OSM2ODR download 2024-05-02 09:10:31 +02:00
Xavier Solé Nogués e9f6693f1e Disable use less CPU in background 2024-04-29 13:16:27 +02:00
KianBahasadri 3547112a44 fixed typo 2024-04-29 08:49:05 +02:00
KianBahasadri 1a05f25616 Update build_docker_unreal.md
Change docs from using Github password to use Github Access Token
2024-04-29 08:49:05 +02:00
luhongliang 9a75c16706 Possible null pointer access during master-slave synchronization 2024-04-29 08:48:30 +02:00
88 changed files with 13408 additions and 168 deletions

View File

@ -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

142
Docs/adv_cpp_client.md Normal file
View File

@ -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
```

View File

@ -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:

View File

@ -11,5 +11,8 @@ Build instructions are available for Linux and Windows. You can also build CARLA
* [__Updating CARLA__](build_update.md)
* [__Build system__](build_system.md)
* [__Linux build with Unreal Engine 5.3__](build_linux_ue5.md)
* [__Windows build with Unreal Engine 5.3__](build_windows_ue5.md)
* [__FAQ__](build_faq.md)

View File

@ -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.__

View File

@ -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
```
---

95
Docs/build_linux_ue5.md Normal file
View File

@ -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

79
Docs/build_windows_ue5.md Normal file
View File

@ -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

View File

@ -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.
---

View File

@ -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()
```

View File

@ -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 &rarr;</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_)

View File

@ -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>

View File

@ -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` |

7
Jenkinsfile vendored
View File

@ -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
'''
}
}

View File

@ -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);

View File

@ -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.

View File

@ -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);
}

View File

@ -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);

View File

@ -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,

View File

@ -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(

View File

@ -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
// =========================================================================

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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):
"""
@ -138,23 +140,30 @@ class BasicAgent(object):
"""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)
@ -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,

View File

@ -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

View File

@ -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)

View File

@ -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:

View File

@ -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))
;
}

View File

@ -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;

View File

@ -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))
;

View File

@ -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);
})
;
}

View File

@ -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;
}

View File

@ -216,6 +216,7 @@ static auto MakeCallback(boost::python::object callback) {
};
}
#include "V2XData.cpp"
#include "Geom.cpp"
#include "Actor.cpp"
#include "Blueprint.cpp"

View File

@ -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.
# --------------------------------------

View File

@ -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__
# --------------------------------------

View File

@ -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

View File

@ -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):

View File

@ -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()

View File

@ -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()

View File

@ -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

View File

@ -0,0 +1,2 @@
[/Script/UnrealEd.EditorPerformanceSettings]
bThrottleCPUWhenNotForeground=False

View File

@ -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

View File

@ -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);
};

View File

@ -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())

View File

@ -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;

View File

@ -55,4 +55,7 @@ struct CARLA_API FPedestrianParameters
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 Generation = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
bool bCanUseWheelChair = false;
};

View File

@ -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:

View File

@ -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;
}
}

View File

@ -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

View File

@ -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)
{

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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)));
}

View File

@ -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;
};

View File

@ -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);
}
}

View File

@ -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);
};

View File

@ -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>

View File

@ -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())

View File

@ -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);

View File

@ -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>();

View File

@ -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;
};

View File

@ -5,3 +5,9 @@
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "WalkerBase.h"
AWalkerBase::AWalkerBase(const FObjectInitializer &ObjectInitializer)
: Super(ObjectInitializer)
{
}

View File

@ -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()
{

View File

@ -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)

View File

@ -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
}
}

View File

@ -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 (

View File

@ -128,6 +128,10 @@ if ${REMOVE_INTERMEDIATE} ; then
rm -Rf ${UE4_INTERMEDIATE_FOLDERS}
cd Plugins
rm -Rf HoudiniEngine
cd ..
popd >/dev/null
fi

View File

@ -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^

View File

@ -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"

View File

@ -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

View File

@ -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"