This commit is contained in:
Blyron 2024-07-08 08:36:42 +02:00
commit 7c47e7db37
32 changed files with 1134 additions and 154 deletions

View File

@ -14,7 +14,11 @@
* 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.
## CARLA 0.9.15

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)

91
Docs/build_linux_ue5.md Normal file
View File

@ -0,0 +1,91 @@
!!! 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
```

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

@ -421,20 +421,17 @@ 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)
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<small> - dBm</small>_)
- <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.
- <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_
Returns a nested dictionary containing the message following the ETSI standard:
- `"Header"`: _dict_
- `"Message"`: _dict_
##### Dunder methods
- <a name="carla.CAMData.__str__"></a>**<font color="#7fb800">\__str__</font>**(<font color="#00a6ed">**self**</font>)
@ -442,25 +439,23 @@ Get the CAM data.
## 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 <b>sensor.other.v2x</b>. This is a collection type to combine returning several [CAMData](#carlacamdata).
### Instance Variables
Class that defines the data provided by a **sensor.other.v2x**. This is a collection type to combine returning several [CAMData](#carlacamdata).
### Methods
- <a name="carla.CAMEvent.get_message_count()"></a>**<font color="#7fb800">get_message_count</font>**(<font color="#00a6ed">**self**</font>)
##### 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.__getitem__"></a>**<font color="#7fb800">\__getitem__</font>**(<font color="#00a6ed">**self**</font>, <font color="#00a6ed">**pos**=int</font>)
- <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 [carla.CAMData](#carla.CAMData) retrieved as data.
- <a name="carla.DVSEventArray.__len__"></a>**<font color="#7fb800">\__len__</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.
@ -618,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_
@ -710,23 +705,19 @@ Converts the image to a depth map using a logarithmic scale, leading to better p
No changes applied to the image. Used by the [RGB camera](ref_sensors.md#rgb-camera).
---
## 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](#carla.CustomV2XEvent).
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<small> - dBm</small>_)
- <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.
- **Return:** _dict_.
Returns a nested dictionary containing the message. It has two primary keys:
- `"Header"` : _dict_
- `"Message"`: _str_
- <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>)
@ -735,25 +726,23 @@ Get the custom message.
## 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 <b>sensor.other.v2x_custom</b>. This is a collection type to combine returning several [CustomV2XData](#carla.CustomV2XData).
### Instance Variables
Class that defines the data provided by a **sensor.other.v2x_custom**. This is a collection type to combine returning several [CustomV2XData](#carlacustomv2xdata).
### Methods
- <a name="carla.CustomV2XEvent.get_message_count()"></a>**<font color="#7fb800">get_message_count</font>**(<font color="#00a6ed">**self**</font>)
##### 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.__getitem__"></a>**<font color="#7fb800">\__getitem__</font>**(<font color="#00a6ed">**self**</font>, <font color="#00a6ed">**pos**=int</font>)
- <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 [carla.CustomV2XData](#carla.CustomV2XData) retrieved as data.
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).
@ -942,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>**
@ -2315,26 +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>)
@ -2343,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:**
@ -2361,7 +2353,7 @@ The function the sensor will be calling to every time the desired GBuffer textur
- <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.
- `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>)
@ -2385,8 +2377,8 @@ 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).
- Cooperative awareness messages V2X sensor: [carla.CAMEvent](#carla.CAMEvent).
- 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

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

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

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

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

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 ){
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);
}else{
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 ){
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);
}else{
lane_section_mesh += *GenerateSidewalk(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 ){
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);
}else{
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 ){
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

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

@ -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:
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
clean_queue = True
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()
clean_queue = False
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])])

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

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

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

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

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

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

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

View File

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

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