Merge branch 'master' into windows_build
This commit is contained in:
commit
b0e06c2ffa
|
@ -26,4 +26,5 @@ Util/Build
|
|||
__pycache__
|
||||
_benchmarks_results
|
||||
_images*
|
||||
_out
|
||||
core
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
{
|
||||
"name": "CARLA - make CarlaUE4",
|
||||
"working_dir": "${project_path}/Unreal/CarlaUE4",
|
||||
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"file_regex": "Unreal\\/CarlaUE4\\/([^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"syntax": "Packages/Makefile/Make Output.sublime-syntax",
|
||||
"linux":
|
||||
{
|
||||
|
@ -86,7 +86,7 @@
|
|||
{
|
||||
"name": "CARLA - make CarlaUE4 ARGS=-clean",
|
||||
"working_dir": "${project_path}/Unreal/CarlaUE4",
|
||||
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"file_regex": "Unreal\\/CarlaUE4\\/([^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"syntax": "Packages/Makefile/Make Output.sublime-syntax",
|
||||
"linux":
|
||||
{
|
||||
|
@ -96,7 +96,7 @@
|
|||
{
|
||||
"name": "CARLA - make CarlaUE4Editor",
|
||||
"working_dir": "${project_path}/Unreal/CarlaUE4",
|
||||
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"file_regex": "Unreal\\/CarlaUE4\\/([^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"syntax": "Packages/Makefile/Make Output.sublime-syntax",
|
||||
"linux":
|
||||
{
|
||||
|
@ -106,7 +106,7 @@
|
|||
{
|
||||
"name": "CARLA - make CarlaUE4Editor ARGS=-clean",
|
||||
"working_dir": "${project_path}/Unreal/CarlaUE4",
|
||||
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"file_regex": "Unreal\\/CarlaUE4\\/([^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"syntax": "Packages/Makefile/Make Output.sublime-syntax",
|
||||
"linux":
|
||||
{
|
||||
|
|
|
@ -63,6 +63,17 @@ please contact one of us (or send an email to carla.simulator@gmail.com).
|
|||
|
||||
[projectslink]: https://github.com/carla-simulator/carla/projects/1
|
||||
|
||||
#### Where can I learn more about Unreal Engine?
|
||||
|
||||
A basic introduction to C++ programming with UE4 can be found at Unreal's
|
||||
[C++ Programming Tutorials][ue4tutorials]. Then, if you want to dive into UE4
|
||||
C++ development there are few paying options online. The
|
||||
[Unreal C++ Course at Udemy][ue4course] it's pretty complete and there are
|
||||
usually offers that make it very affordable.
|
||||
|
||||
[ue4tutorials]: https://docs.unrealengine.com/latest/INT/Programming/Tutorials/
|
||||
[ue4course]: https://www.udemy.com/unrealcourse/
|
||||
|
||||
#### What should I know before I get started?
|
||||
|
||||
Check out the ["CARLA Design"](carla_design.md) document to get an idea on the
|
||||
|
@ -71,6 +82,27 @@ the new feature. We are aware the developers documentation is still scarce,
|
|||
please ask us in case of doubt, and of course don't hesitate to improve the
|
||||
current documentation if you feel confident enough.
|
||||
|
||||
#### Are there any examples in CARLA to see how Unreal programming works?
|
||||
|
||||
You can find an example of how C++ classes work in UE4 in
|
||||
[`ASceneCaptureToDiskCamera`][capturelink] (and its parent class
|
||||
`ASceneCaptureCamera`). This class creates an actor that can be dropped into the
|
||||
scene. In the editor, type _"Scene Capture To Disk"_ in the Modes tab, and drag
|
||||
and drop the actor into the scene. Now searching for its detail tab you can find
|
||||
all the `UPROPERTY` members reflected. This shows the basic mechanism to use C++
|
||||
classes in Unreal Editor.
|
||||
|
||||
For a more advanced example on how to extend C++ classes with blueprints, you
|
||||
can take a look at the _"VehicleSpawner"_ blueprint. It derives from the C++
|
||||
class `AVehicleSpawnerBase`. The C++ class decides where and when it spawns a
|
||||
vehicle, then calls the function `SpawnVehicle()`, which is implemented in the
|
||||
blueprint. The blueprint then decides model and color of the vehicle being
|
||||
spawned. Note that the blueprint can call back C++ functions, for instance for
|
||||
getting the random engine. This way there is a back-and-forth communication
|
||||
between C++ code and blueprints.
|
||||
|
||||
[capturelink]: https://github.com/carla-simulator/carla/blob/master/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/SceneCaptureToDiskCamera.h
|
||||
|
||||
#### Coding standard
|
||||
|
||||
Please follow the current [coding standard](coding_standard.md) when submitting
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
; Example of settings file for CARLA.
|
||||
;
|
||||
; Use it with `./CarlaUE4.sh -carla-settings=Path/To/This/File`.
|
||||
; This file can be loaded with the Python client to be sent to the server. It
|
||||
; defines the parameters to be used when requesting a new episode.
|
||||
;
|
||||
; Note that server specific variables are loaded in server only. Use it with
|
||||
; `./CarlaUE4.sh -carla-settings=Path/To/This/File`.
|
||||
|
||||
[CARLA/Server]
|
||||
; If set to false, a mock controller will be used instead of waiting for a real
|
||||
; client to connect.
|
||||
; client to connect. (Server only)
|
||||
UseNetworking=true
|
||||
; Ports to use for the server-client communication. This can be overridden by
|
||||
; the command-line switch `-world-port=N`, write and read ports will be set to
|
||||
; N+1 and N+2 respectively.
|
||||
; N+1 and N+2 respectively. (Server only)
|
||||
WorldPort=2000
|
||||
; Time-out in milliseconds for the networking operations.
|
||||
; Time-out in milliseconds for the networking operations. (Server only)
|
||||
ServerTimeOut=10000
|
||||
; In synchronous mode, CARLA waits every frame until the control from the client
|
||||
; is received.
|
||||
|
@ -36,16 +40,26 @@ WeatherId=1
|
|||
SeedVehicles=123456789
|
||||
SeedPedestrians=123456789
|
||||
|
||||
[CARLA/SceneCapture]
|
||||
; Names of the cameras to be attached to the player, comma-separated, each of
|
||||
; them should be defined in its own subsection. E.g., Uncomment next line to add
|
||||
; a camera called MyCamera to the vehicle
|
||||
[CARLA/Sensor]
|
||||
; Names of the sensors to be attached to the player, comma-separated, each of
|
||||
; them should be defined in its own subsection.
|
||||
|
||||
; Cameras=MyCamera
|
||||
; Uncomment next line to add a camera called MyCamera to the vehicle
|
||||
; Sensors=MyCamera
|
||||
|
||||
; or uncomment next line to add a camera and a LiDAR
|
||||
; Sensors=MyCamera,MyLidar
|
||||
|
||||
; or uncomment next line to add a regular camera and a depth camera
|
||||
; Sensors=MyCamera,MyCamera/Depth
|
||||
|
||||
; Now, every camera we added needs to be defined it in its own subsection.
|
||||
[CARLA/SceneCapture/MyCamera]
|
||||
; Post-processing effect to be applied. Valid values:
|
||||
[CARLA/Sensor/MyCamera]
|
||||
; Type of the sensor. The available types are:
|
||||
; * CAMERA A scene capture camera.
|
||||
; * LIDAR_RAY_TRACE A LiDAR implementation based on ray-tracing.
|
||||
SensorType=CAMERA
|
||||
; Post-processing effect to be applied to this camera. Valid values:
|
||||
; * None No effects applied.
|
||||
; * SceneFinal Post-processing present at scene (bloom, fog, etc).
|
||||
; * Depth Depth map ground-truth only.
|
||||
|
@ -55,42 +69,39 @@ PostProcessing=SceneFinal
|
|||
ImageSizeX=800
|
||||
ImageSizeY=600
|
||||
; Camera (horizontal) field of view in degrees.
|
||||
CameraFOV=90
|
||||
FOV=90
|
||||
; Position of the camera relative to the car in centimeters.
|
||||
CameraPositionX=15
|
||||
CameraPositionY=0
|
||||
CameraPositionZ=123
|
||||
PositionX=15
|
||||
PositionY=0
|
||||
PositionZ=123
|
||||
; Rotation of the camera relative to the car in degrees.
|
||||
CameraRotationPitch=8
|
||||
CameraRotationRoll=0
|
||||
CameraRotationYaw=0
|
||||
RotationPitch=8
|
||||
RotationRoll=0
|
||||
RotationYaw=0
|
||||
|
||||
; Stereo setup example:
|
||||
;
|
||||
; [CARLA/SceneCapture]
|
||||
; Cameras=CameraStereoLeft/RGB,CameraStereoLeft/Depth,CameraStereoRight/RGB,CameraStereoRight/Depth
|
||||
; ImageSizeX=720
|
||||
; ImageSizeY=512
|
||||
; CameraFOV=90
|
||||
; [CARLA/SceneCapture/CameraStereoLeft]
|
||||
; CameraPositionX=170
|
||||
; CameraPositionY=-30
|
||||
; CameraPositionZ=150
|
||||
; CameraRotationPitch=0
|
||||
; CameraRotationRoll=0
|
||||
; CameraRotationYaw=0
|
||||
; [CARLA/SceneCapture/CameraStereoLeft/RGB]
|
||||
; PostProcessing=SceneFinal
|
||||
; [CARLA/SceneCapture/CameraStereoLeft/Depth]
|
||||
; PostProcessing=Depth
|
||||
; [CARLA/SceneCapture/CameraStereoRight]
|
||||
; CameraPositionX=170
|
||||
; CameraPositionY=30
|
||||
; CameraPositionZ=150
|
||||
; CameraRotationPitch=0
|
||||
; CameraRotationRoll=0
|
||||
; CameraRotationYaw=0
|
||||
; [CARLA/SceneCapture/CameraStereoRight/RGB]
|
||||
; PostProcessing=SceneFinal
|
||||
; [CARLA/SceneCapture/CameraStereoRight/Depth]
|
||||
; PostProcessing=Depth
|
||||
[CARLA/Sensor/MyCamera/Depth]
|
||||
; The sensor can be defined in a subsection of MyCamera so it inherits the
|
||||
; values in MyCamera. This adds a camera similar to MyCamera but generating
|
||||
; depth map images instead.
|
||||
PostProcessing=Depth
|
||||
|
||||
[CARLA/Sensor/MyLidar]
|
||||
SensorType=LIDAR_RAY_TRACE
|
||||
; Number of lasers.
|
||||
Channels=32
|
||||
; Measure distance in centimeters.
|
||||
Range=5000
|
||||
; Points generated by all lasers per second.
|
||||
PointsPerSecond=100000
|
||||
; Lidar rotation frequency.
|
||||
RotationFrequency=10
|
||||
; Upper and lower laser angles, positive values means above horizontal line.
|
||||
UpperFOVLimit=10
|
||||
LowerFOVLimit=-30
|
||||
; Position and rotation relative to the vehicle.
|
||||
PositionX=0
|
||||
PositionY=0
|
||||
PositionZ=140
|
||||
RotationPitch=0
|
||||
RotationYaw=0
|
||||
RotationRoll=0
|
||||
|
|
|
@ -2,20 +2,20 @@ Cameras and sensors
|
|||
===================
|
||||
|
||||
Cameras and sensors can be added to the player vehicle by defining them in the
|
||||
settings file sent by the client on every new episode. Check out the examples at
|
||||
[CARLA Settings example][settingslink].
|
||||
settings sent by the client on every new episode. This can be done either by
|
||||
filling a `CarlaSettings` Python class ([client_example.py][clientexamplelink])
|
||||
or by loading an INI settings file ([CARLA Settings example][settingslink]).
|
||||
|
||||
This document describes the details of the different cameras/sensors currently
|
||||
available as well as the resulting images produced by them.
|
||||
|
||||
Although we plan to extend the sensor suite of CARLA in the near future, at the
|
||||
moment there are three different sensors available. These three sensors are
|
||||
implemented as different post-processing effects applied to scene capture
|
||||
cameras.
|
||||
moment there are four different sensors available.
|
||||
|
||||
* [Scene final](#scene-final)
|
||||
* [Depth map](#depth-map)
|
||||
* [Semantic segmentation](#semantic-segmentation)
|
||||
* [Camera: Scene final](#camera-scene-final)
|
||||
* [Camera: Depth map](#camera-depth-map)
|
||||
* [Camera: Semantic segmentation](#camera-semantic-segmentation)
|
||||
* [Ray-trace based lidar](#ray-trace-based-lidar)
|
||||
|
||||
!!! note
|
||||
The images are sent by the server as a BGRA array of bytes. The provided
|
||||
|
@ -23,24 +23,27 @@ cameras.
|
|||
parse the images and convert them to the desired format. There are some
|
||||
examples in the PythonClient folder showing how to parse the images.
|
||||
|
||||
There is a fourth post-processing effect available, _None_, which provides a
|
||||
view with of the scene with no effect, not even lens effects like flares or
|
||||
depth of field; we will skip this one in the following descriptions.
|
||||
There is a fourth post-processing effect available for cameras, _None_, which
|
||||
provides a view with of the scene with no effect, not even scene lighting; we
|
||||
will skip this one in the following descriptions.
|
||||
|
||||
We provide a tool to convert raw depth and semantic segmentation images to a
|
||||
more human readable palette of colors. It can be found at
|
||||
["Util/ImageConverter"][imgconvlink].
|
||||
We provide a tool to convert raw depth and semantic segmentation images in bulk
|
||||
to a more human readable palette of colors. It can be found at
|
||||
["Util/ImageConverter"][imgconvlink]. Alternatively, they can also be converted
|
||||
using the functions at `carla.image_converter` Python module.
|
||||
|
||||
[clientexamplelink]: https://github.com/carla-simulator/carla/blob/master/PythonClient/client_example.py
|
||||
[settingslink]: https://github.com/carla-simulator/carla/blob/master/Docs/Example.CarlaSettings.ini
|
||||
|
||||
[imgconvlink]: https://github.com/carla-simulator/carla/tree/master/Util/ImageConverter
|
||||
|
||||
Scene final
|
||||
-----------
|
||||
Camera: Scene final
|
||||
-------------------
|
||||
|
||||
<br>
|
||||
|
||||
The "scene final" camera provides a view of the scene after applying some
|
||||
post-processing effects to create a more realistic feel. These are actually
|
||||
stored on the Level, in an actor called [PostProcessVolume][postprolink] and not
|
||||
stored in the Level, in an actor called [PostProcessVolume][postprolink] and not
|
||||
in the Camera. We use the following post process effects:
|
||||
|
||||
* **Vignette** Darkens the border of the screen.
|
||||
|
@ -52,8 +55,39 @@ in the Camera. We use the following post process effects:
|
|||
|
||||
[postprolink]: https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/
|
||||
|
||||
Depth map
|
||||
---------
|
||||
###### Python
|
||||
|
||||
```py
|
||||
camera = carla.sensor.Camera('MyCamera', PostProcessing='SceneFinal')
|
||||
camera.set(FOV=90.0)
|
||||
camera.set_image_size(800, 600)
|
||||
camera.set_position(x=30, y=0, z=130)
|
||||
camera.set_rotation(pitch=0, yaw=0, roll=0)
|
||||
|
||||
carla_settings.add_sensor(camera)
|
||||
```
|
||||
|
||||
###### CarlaSettings.ini
|
||||
|
||||
```ini
|
||||
[CARLA/Sensor/MyCamera]
|
||||
SensorType=CAMERA
|
||||
PostProcessing=SceneFinal
|
||||
ImageSizeX=800
|
||||
ImageSizeY=600
|
||||
FOV=90
|
||||
PositionX=30
|
||||
PositionY=0
|
||||
PositionZ=130
|
||||
RotationPitch=0
|
||||
RotationRoll=0
|
||||
RotationYaw=0
|
||||
```
|
||||
|
||||
Camera: Depth map
|
||||
-----------------
|
||||
|
||||

|
||||
|
||||
The "depth map" camera provides an image with 24 bit floating precision point
|
||||
codified in the 3 channels of the RGB color space. The order from less to more
|
||||
|
@ -78,15 +112,50 @@ Our max render distance (far) is 1km.
|
|||
|
||||
Ans * far
|
||||
|
||||
Semantic segmentation
|
||||
---------------------
|
||||
The generated "depth map" images are usually converted to a logarithmic
|
||||
grayscale for display. A point cloud can also be extracted from depth images as
|
||||
seen in "PythonClient/point_cloud_example.py".
|
||||
|
||||
###### Python
|
||||
|
||||
```py
|
||||
camera = carla.sensor.Camera('MyCamera', PostProcessing='Depth')
|
||||
camera.set(FOV=90.0)
|
||||
camera.set_image_size(800, 600)
|
||||
camera.set_position(x=30, y=0, z=130)
|
||||
camera.set_rotation(pitch=0, yaw=0, roll=0)
|
||||
|
||||
carla_settings.add_sensor(camera)
|
||||
```
|
||||
|
||||
###### CarlaSettings.ini
|
||||
|
||||
```ini
|
||||
[CARLA/Sensor/MyCamera]
|
||||
SensorType=CAMERA
|
||||
PostProcessing=Depth
|
||||
ImageSizeX=800
|
||||
ImageSizeY=600
|
||||
FOV=90
|
||||
PositionX=30
|
||||
PositionY=0
|
||||
PositionZ=130
|
||||
RotationPitch=0
|
||||
RotationRoll=0
|
||||
RotationYaw=0
|
||||
```
|
||||
|
||||
Camera: Semantic segmentation
|
||||
-----------------------------
|
||||
|
||||

|
||||
|
||||
The "semantic segmentation" camera classifies every object in the view by
|
||||
displaying it in a different color according to the object class. E.g.,
|
||||
pedestrians appear in a different color than vehicles.
|
||||
|
||||
The server provides an image with the tag information encoded in the red
|
||||
channel. A pixel with a red value of x displays an object with tag x. The
|
||||
The server provides an image with the tag information **encoded in the red
|
||||
channel**. A pixel with a red value of x displays an object with tag x. The
|
||||
following tags are currently available
|
||||
|
||||
Value | Tag
|
||||
|
@ -106,6 +175,102 @@ Value | Tag
|
|||
12 | TrafficSigns
|
||||
|
||||
This is implemented by tagging every object in the scene before hand (either at
|
||||
begin play or on spawn). The objects are classified by their relative file
|
||||
system path in the project. E.g., every mesh stored in the "pedestrians" folder
|
||||
it's tagged as pedestrian.
|
||||
begin play or on spawn). The objects are classified by their relative file path
|
||||
in the project. E.g., every mesh stored in the
|
||||
_"Unreal/CarlaUE4/Content/Static/Pedestrians"_ folder it's tagged as pedestrian.
|
||||
|
||||
!!! note
|
||||
**Adding new tags**:
|
||||
At the moment adding new tags is not very flexible and requires to modify
|
||||
the C++ code. Add a new label to the `ECityObjectLabel` enum in "Tagger.h",
|
||||
and its corresponding filepath check inside `GetLabelByFolderName()`
|
||||
function in "Tagger.cpp".
|
||||
|
||||
###### Python
|
||||
|
||||
```py
|
||||
camera = carla.sensor.Camera('MyCamera', PostProcessing='SemanticSegmentation')
|
||||
camera.set(FOV=90.0)
|
||||
camera.set_image_size(800, 600)
|
||||
camera.set_position(x=30, y=0, z=130)
|
||||
camera.set_rotation(pitch=0, yaw=0, roll=0)
|
||||
|
||||
carla_settings.add_sensor(camera)
|
||||
```
|
||||
|
||||
###### CarlaSettings.ini
|
||||
|
||||
```ini
|
||||
[CARLA/Sensor/MyCamera]
|
||||
SensorType=CAMERA
|
||||
PostProcessing=SemanticSegmentation
|
||||
ImageSizeX=800
|
||||
ImageSizeY=600
|
||||
FOV=90
|
||||
PositionX=30
|
||||
PositionY=0
|
||||
PositionZ=130
|
||||
RotationPitch=0
|
||||
RotationRoll=0
|
||||
RotationYaw=0
|
||||
```
|
||||
|
||||
Ray-trace based Lidar
|
||||
---------------------
|
||||
|
||||

|
||||
|
||||
A rotating Lidar implemented with ray-tracing. The points are computed by adding
|
||||
a laser for each channel distributed in the vertical FOV, then the rotation is
|
||||
simulated computing the horizontal angle that the Lidar rotated this frame, and
|
||||
doing a ray-cast for each point that each laser was supposed to generate this
|
||||
frame; `PointsPerSecond / (FPS * Channels)`.
|
||||
|
||||
Each frame the server sends a packet with all the points generated during a
|
||||
`1/FPS` interval. During the interval the physics wasn’t updated so all the
|
||||
points in a packet reflect the same "static picture" of the scene.
|
||||
|
||||
The received `LidarMeasurement` object contains the following information
|
||||
|
||||
Key | Type | Description
|
||||
-------------------------- | ---------- | ------------
|
||||
horizontal_angle | float | Angle in XY plane of the lidar this frame
|
||||
channels | uint32 | Number of channels (lasers) of the lidar
|
||||
point_count_by_channel | uint32 | Number of points per channel captured this frame
|
||||
point_cloud | PointCloud | Captured points this frame
|
||||
|
||||
###### Python
|
||||
|
||||
```py
|
||||
lidar = carla.sensor.Lidar('MyLidar')
|
||||
lidar.set(
|
||||
Channels=32,
|
||||
Range=5000,
|
||||
PointsPerSecond=100000,
|
||||
RotationFrequency=10,
|
||||
UpperFovLimit=10,
|
||||
LowerFovLimit=-30)
|
||||
lidar.set_position(x=0, y=0, z=140)
|
||||
lidar.set_rotation(pitch=0, yaw=0, roll=0)
|
||||
|
||||
carla_settings.add_sensor(lidar)
|
||||
```
|
||||
|
||||
###### CarlaSettings.ini
|
||||
|
||||
```ini
|
||||
[CARLA/Sensor/MyLidar]
|
||||
SensorType=LIDAR_RAY_TRACE
|
||||
Channels=32
|
||||
Range=5000
|
||||
PointsPerSecond=100000
|
||||
RotationFrequency=10
|
||||
UpperFOVLimit=10
|
||||
LowerFOVLimit=-30
|
||||
PositionX=0
|
||||
PositionY=0
|
||||
PositionZ=140
|
||||
RotationPitch=0
|
||||
RotationYaw=0
|
||||
RotationRoll=0
|
||||
```
|
||||
|
|
|
@ -12,6 +12,10 @@ CARLA is composed by the following modules
|
|||
- Carla plugin for Unreal Engine: "Unreal/CarlaUE4/Plugins/Carla"
|
||||
- CarlaServer: "Util/CarlaServer"
|
||||
|
||||
!!! tip
|
||||
Documentation for the C++ code can be generated by running
|
||||
[Doxygen](http://www.doxygen.org) in the main folder of CARLA project.
|
||||
|
||||
Python client API
|
||||
-----------------
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
Running CARLA without Display and Selecting GPUs
|
||||
------
|
||||
|
||||
|
||||
This tutorial is designed for:
|
||||
- Remote server users that have several nvidia graphical cards and want to effectively use CARLA on all GPUs.
|
||||
- Desktop users who want to use the GPU that is not plugged on the screen for rendering CARLA.
|
||||
|
||||
|
||||
On this tutorial you will learn.
|
||||
- How to configure your server to have nvidia working on rendering without a display attached.
|
||||
- How to use VNC + VGL to simulate a display connected to any GPU you have in your machine.
|
||||
- And Finally, how to run CARLA in this environment
|
||||
|
||||
This tutorial was tested in Ubuntu 16.04 and using NVIDIA 384.11 drivers.
|
||||
## Preliminaries
|
||||
|
||||
A few things need to be working in your server before.
|
||||
Latest NVIDIA Drivers, OpenGL, VirtualGL(VGL), TurboVNC 2.11, ,
|
||||
#### NVIDIA Drivers
|
||||
Download and install NVIDIA-drivers with typical tutorials
|
||||
http://www.nvidia.es/Download/index.aspx
|
||||
#### OpenGL
|
||||
Openg GL is necessary for Virtual GL. Normally OpenGL
|
||||
can be installed through apt.
|
||||
|
||||
sudo apt-get install freeglut3-dev mesa-utils
|
||||
#### VGL
|
||||
Follow this tutorial and install vgl: <br>
|
||||
[Installing VGL](https://virtualgl.org/vgldoc/2_2_1/#hd004001)
|
||||
|
||||
#### TurboVNC
|
||||
Follow the tutorial below to install TurboVNC 2.11:<br>
|
||||
[Installing TurboVNC](https://cdn.rawgit.com/TurboVNC/turbovnc/2.1.1/doc/index.html#hd005001)
|
||||
|
||||
WARNING: Take care on which VNC you install as it may not be compatible with Unreal. The one above was the only one that worked for me.
|
||||
#### Extra Packages
|
||||
These extra packages were necessary to make unreal to work.
|
||||
|
||||
sudo apt install x11-xserver-utils libxrandr-dev
|
||||
|
||||
|
||||
|
||||
|
||||
#### Configure your X
|
||||
|
||||
You must generate a X compatible with your nvdia and compatible to run without display. For that, the following command worked:
|
||||
|
||||
sudo nvidia-xconfig -a --use-display-device=None --virtual=1280x1024
|
||||
|
||||
|
||||
|
||||
## Emulating The Virtual Display
|
||||
|
||||
|
||||
Run your own Xorg. Here I use number 7, but it could be labeled with any free number.
|
||||
|
||||
sudo nohup Xorg :7 &
|
||||
|
||||
Run an auxiliary remote VNC-Xserver. This will create a
|
||||
virtual display "8".
|
||||
|
||||
/opt/TurboVNC/bin/vncserver :8
|
||||
|
||||
If everything is working fine the following command
|
||||
should run smoothly.
|
||||
|
||||
DISPLAY=:8 vglrun -d :7.0 glxinfo
|
||||
Note. This will run glxinfo on Xserver 7, device 0. This means you are selecting the GPU 0 on your machine. To run on other GPU, such as GPU 1 run:
|
||||
|
||||
DISPLAY=:8 vglrun -d :7.1 glxinfo
|
||||
|
||||
#### Extra
|
||||
|
||||
If you want disable the need of sudo when creating the 'nohup Xorg'
|
||||
go to the '/etc/X11/Xwrapper.config' file and change 'allowed_users=console' to 'allowed_users=anybody'
|
||||
|
||||
It may be needed to stop all Xorg servers before running nohup Xorg.
|
||||
The command for that could change depending on your system. Generally for Ubuntu 16.04
|
||||
you should use:
|
||||
|
||||
sudo service lightdm stop
|
||||
|
||||
|
||||
## Running CARLA
|
||||
|
||||
Now, finally, to run CARLA on a certain gpu_number placed in a certain $CARLA_PATH, run.
|
||||
|
||||
DISPLAY=:8 vglrun -d :7.<gpu_number> $CARLA_PATH/CarlaUE4/Binaries/Linux/CarlaUE4
|
|
@ -48,10 +48,11 @@ Server only writes, first measurements message then the bulk of raw images.
|
|||
|
||||
Every image is an array of uint32's
|
||||
|
||||
[width, height, type, color[0], color[1],...]
|
||||
[width, height, type, FOV, color[0], color[1],...]
|
||||
|
||||
where each color is an [FColor][fcolorlink] (BGRA) as stored in Unreal Engine,
|
||||
and the possible types of images are
|
||||
where FOV is the horizontal field of view of the camera as float, each color is
|
||||
an [FColor][fcolorlink] (BGRA) as stored in Unreal Engine, and the possible
|
||||
types of images are
|
||||
|
||||
type = 0 None (RGB without any post-processing)
|
||||
type = 1 SceneFinal (RGB with post-processing present at the scene)
|
||||
|
|
49
Docs/faq.md
49
Docs/faq.md
|
@ -152,3 +152,52 @@ rebuild of all the project files with
|
|||
It takes a long time but fixes the issue. Sometimes a reboot is also needed.
|
||||
|
||||
</details>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<details>
|
||||
<summary><h5 style="display:inline">
|
||||
Fatal error: 'carla/carla_server.h' file not found.
|
||||
</h4></summary>
|
||||
|
||||
This indicates that the CarlaServer dependency failed to compile.
|
||||
|
||||
Please follow the instructions at
|
||||
[How to build on Linux](http://carla.readthedocs.io/en/latest/how_to_build_on_linux/).
|
||||
|
||||
Make sure that the Setup script does print _"Success!"_ at the end
|
||||
|
||||
$ ./Setup.sh
|
||||
...
|
||||
...
|
||||
****************
|
||||
*** Success! ***
|
||||
****************
|
||||
|
||||
Then check if CarlaServer compiles without errors running make
|
||||
|
||||
$ make
|
||||
|
||||
It should end printing something like
|
||||
|
||||
```
|
||||
[1/1] Install the project...
|
||||
-- Install configuration: "Release"
|
||||
-- Installing: Unreal/CarlaUE4/Plugins/Carla/CarlaServer/shared/libc++abi.so.1
|
||||
-- Installing: Unreal/CarlaUE4/Plugins/Carla/CarlaServer/shared/libc++abi.so.1.0
|
||||
-- Installing: Unreal/CarlaUE4/Plugins/Carla/CarlaServer/shared/libc++.so.1
|
||||
-- Installing: Unreal/CarlaUE4/Plugins/Carla/CarlaServer/shared/libc++.so.1.0
|
||||
-- Installing: Unreal/CarlaUE4/Plugins/Carla/CarlaServer/shared/libc++.so
|
||||
-- Installing: Unreal/CarlaUE4/Plugins/Carla/CarlaServer/shared/libc++abi.so
|
||||
-- Installing: Unreal/CarlaUE4/Plugins/Carla/CarlaServer/lib/libc++abi.a
|
||||
-- Installing: Unreal/CarlaUE4/Plugins/Carla/CarlaServer/lib/libboost_system.a
|
||||
-- Installing: Unreal/CarlaUE4/Plugins/Carla/CarlaServer/lib/libprotobuf.a
|
||||
-- Installing: Unreal/CarlaUE4/Plugins/Carla/CarlaServer/include/carla
|
||||
-- Installing: Unreal/CarlaUE4/Plugins/Carla/CarlaServer/include/carla/carla_server.h
|
||||
-- Installing: Unreal/CarlaUE4/Plugins/Carla/CarlaServer/lib/libcarlaserver.a
|
||||
-- Installing: Unreal/CarlaUE4/Plugins/Carla/CarlaServer/bin/test_carlaserver
|
||||
-- Set runtime path of "Unreal/CarlaUE4/Plugins/Carla/CarlaServer/bin/test_carlaserver" to ""
|
||||
```
|
||||
|
||||
If so you can safely run Rebuild.sh.
|
||||
|
||||
</details>
|
||||
|
|
|
@ -20,15 +20,17 @@ change your default clang version to compile Unreal
|
|||
Build Unreal Engine
|
||||
-------------------
|
||||
|
||||
Download and compile Unreal Engine 4.17. Here we will assume you install it at
|
||||
"~/UnrealEngine_4.17", but you can install it anywhere, just replace the path
|
||||
!!! note
|
||||
Unreal Engine repositories are set to private. In order to gain access you
|
||||
need to add your GitHub username when you sign up at
|
||||
[www.unrealengine.com](https://www.unrealengine.com).
|
||||
|
||||
Download and compile Unreal Engine 4.18. Here we will assume you install it at
|
||||
"~/UnrealEngine_4.18", but you can install it anywhere, just replace the path
|
||||
where necessary.
|
||||
|
||||
Unreal Engine repositories are set to private. In order to gain access you need
|
||||
to add your GitHub username when you sign up at https://unrealengine.com.
|
||||
|
||||
$ git clone --depth=1 -b 4.17 https://github.com/EpicGames/UnrealEngine.git ~/UnrealEngine_4.17
|
||||
$ cd ~/UnrealEngine_4.17
|
||||
$ git clone --depth=1 -b 4.18 https://github.com/EpicGames/UnrealEngine.git ~/UnrealEngine_4.18
|
||||
$ cd ~/UnrealEngine_4.18
|
||||
$ ./Setup.sh && ./GenerateProjectFiles.sh && make
|
||||
|
||||
Check Unreal's documentation
|
||||
|
@ -59,7 +61,7 @@ To build CARLA, use the rebuild script. This script deletes all intermediate
|
|||
files, rebuilds whole CARLA, and launches the editor. Use it too for making a
|
||||
clean rebuild of CARLA
|
||||
|
||||
$ UE4_ROOT=~/UnrealEngine_4.17 ./Rebuild.sh
|
||||
$ UE4_ROOT=~/UnrealEngine_4.18 ./Rebuild.sh
|
||||
|
||||
It looks at the environment variable `UE4_ROOT` to find the right version of
|
||||
Unreal Engine. You can also add this variable to your "~/.bashrc" or similar.
|
||||
|
@ -89,7 +91,7 @@ Launching the editor
|
|||
To open the editor once the project is already built
|
||||
|
||||
$ cd Unreal/CarlaUE4
|
||||
$ ~/UnrealEngine_4.17/Engine/Binaries/Linux/UE4Editor "$PWD/CarlaUE4.uproject"
|
||||
$ ~/UnrealEngine_4.18/Engine/Binaries/Linux/UE4Editor "$PWD/CarlaUE4.uproject"
|
||||
|
||||
Test (Optional)
|
||||
---------------
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 142 KiB |
Binary file not shown.
After Width: | Height: | Size: 128 KiB |
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
|
@ -0,0 +1,268 @@
|
|||
// =============================================================================
|
||||
// -- Unreal classes -----------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
* @opt nodefillcolor gray
|
||||
*/
|
||||
class UObject {}
|
||||
|
||||
/** @opt nodefillcolor gray */ class AAIController extends AController {}
|
||||
/** @opt nodefillcolor gray */ class AActor extends UObject {}
|
||||
/** @opt nodefillcolor gray */ class ACharacter extends APawn {}
|
||||
/** @opt nodefillcolor gray */ class AController extends AActor {}
|
||||
/** @opt nodefillcolor gray */ class AGameModeBase extends AActor {}
|
||||
/** @opt nodefillcolor gray */ class AHUD extends AActor {}
|
||||
/** @opt nodefillcolor gray */ class AInfo extends AActor {}
|
||||
/** @opt nodefillcolor gray */ class APawn extends AActor {}
|
||||
/** @opt nodefillcolor gray */ class APlayerController extends AController {}
|
||||
/** @opt nodefillcolor gray */ class APlayerState extends AInfo {}
|
||||
/** @opt nodefillcolor gray */ class AWheeledVehicle extends APawn {}
|
||||
/** @opt nodefillcolor gray */ class UActorComponent extends UObject {}
|
||||
/** @opt nodefillcolor gray */ class UCameraComponent extends USceneComponent {}
|
||||
/** @opt nodefillcolor gray */ class UGameInstance extends UObject {}
|
||||
/** @opt nodefillcolor gray */ class USceneComponent extends UActorComponent {}
|
||||
|
||||
// =============================================================================
|
||||
// -- Agent --------------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
class UAgentComponent extends USceneComponent {}
|
||||
|
||||
class UTrafficSignAgentComponent extends UAgentComponent {}
|
||||
|
||||
class UVehicleAgentComponent extends UAgentComponent {}
|
||||
|
||||
class UWalkerAgentComponent extends UAgentComponent {}
|
||||
|
||||
// =============================================================================
|
||||
// -- Game ---------------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @has - - - FDataRouter
|
||||
*/
|
||||
class ICarlaGameControllerBase {}
|
||||
|
||||
/**
|
||||
* @composed - - - ICarlaGameControllerBase
|
||||
* @composed - - - FDataRouter
|
||||
* @composed - - - UCarlaSettings
|
||||
*/
|
||||
class UCarlaGameInstance extends UGameInstance {}
|
||||
|
||||
// * @has - Player - ACarlaVehicleController
|
||||
|
||||
/**
|
||||
* @depend - - - UCarlaGameInstance
|
||||
* @composed - - - UTaggerDelegate
|
||||
* @composed - - - ADynamicWeather
|
||||
* @composed - - - AVehicleSpawnerBase
|
||||
* @composed - - - AWalkerSpawnerBase
|
||||
*/
|
||||
class ACarlaGameModeBase extends AGameModeBase {}
|
||||
|
||||
class ACarlaHUD extends AHUD {}
|
||||
|
||||
class ACarlaPlayerState extends APlayerState {}
|
||||
|
||||
/**
|
||||
* @depend - - - UAgentComponent
|
||||
* @depend - - - ACarlaVehicleController
|
||||
* @composed - - - ISensorDataSink
|
||||
*/
|
||||
class FDataRouter {}
|
||||
|
||||
/**
|
||||
* @composed - - - FMockSensorDataSink
|
||||
*/
|
||||
class MockGameController extends ICarlaGameControllerBase {}
|
||||
|
||||
class FMockSensorDataSink extends ISensorDataSink {}
|
||||
|
||||
/**
|
||||
* @depend - - - ATagger
|
||||
*/
|
||||
class UTaggerDelegate extends UObject {}
|
||||
|
||||
class ATagger /*extends AActor*/ {}
|
||||
|
||||
// =============================================================================
|
||||
// -- MapGen -------------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
// MapGen is ignored here.
|
||||
|
||||
// =============================================================================
|
||||
// -- Sensor -------------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
class ALidar extends ASensor {}
|
||||
|
||||
class ASceneCaptureCamera extends ASensor {}
|
||||
|
||||
/**
|
||||
* @depend - - - ISensorDataSink
|
||||
*/
|
||||
class ASensor extends AActor {}
|
||||
|
||||
class ISensorDataSink {}
|
||||
|
||||
// =============================================================================
|
||||
// -- Server -------------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @depend - - - CarlaServerAPI
|
||||
*/
|
||||
class FCarlaServer {}
|
||||
|
||||
/**
|
||||
* @composed - - - FCarlaServer
|
||||
* @has - - - FServerSensorDataSink
|
||||
*/
|
||||
class FServerGameController extends ICarlaGameControllerBase {}
|
||||
|
||||
/**
|
||||
* @depend - - - FCarlaServer
|
||||
*/
|
||||
class FServerSensorDataSink extends ISensorDataSink {}
|
||||
|
||||
/**
|
||||
* CarlaServer
|
||||
* Library API
|
||||
* @opt commentname
|
||||
* @opt nodefillcolor #fdf6e3
|
||||
*/
|
||||
class CarlaServerAPI {}
|
||||
|
||||
// =============================================================================
|
||||
// -- Settings -----------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
class UCameraDescription extends USensorDescription {}
|
||||
|
||||
/**
|
||||
* @composed - - - USensorDescription
|
||||
*/
|
||||
class UCarlaSettings extends UObject {}
|
||||
|
||||
class ULidarDescription extends USensorDescription {}
|
||||
|
||||
class USensorDescription extends UObject {}
|
||||
|
||||
// =============================================================================
|
||||
// -- Traffic ------------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
class ATrafficLightBase extends ATrafficSignBase {}
|
||||
|
||||
/**
|
||||
* @composed - - - UTrafficSignAgentComponent
|
||||
*/
|
||||
class ATrafficSignBase extends AActor {}
|
||||
|
||||
// =============================================================================
|
||||
// -- Util ---------------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
class AActorWithRandomEngine extends AActor {}
|
||||
|
||||
// =============================================================================
|
||||
// -- Vehicle ------------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @has - - - ACarlaPlayerState
|
||||
* @has - - - ACarlaHUD
|
||||
*/
|
||||
class ACarlaVehicleController extends AWheeledVehicleController {}
|
||||
|
||||
/**
|
||||
* @composed - - - UVehicleAgentComponent
|
||||
*/
|
||||
class ACarlaWheeledVehicle extends AWheeledVehicle {}
|
||||
|
||||
/**
|
||||
* @has - - - ACarlaWheeledVehicle
|
||||
*/
|
||||
class AVehicleSpawnerBase extends AActorWithRandomEngine {}
|
||||
|
||||
/**
|
||||
* @has - - - ACarlaWheeledVehicle
|
||||
*/
|
||||
class AWheeledVehicleAIController extends APlayerController {}
|
||||
|
||||
/**
|
||||
* @composed - - - UCameraComponent
|
||||
*/
|
||||
class AWheeledVehicleController extends AWheeledVehicleAIController {}
|
||||
|
||||
// =============================================================================
|
||||
// -- Walker -------------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @has - - - ACharacter
|
||||
*/
|
||||
class AWalkerAIController extends AAIController {}
|
||||
|
||||
/**
|
||||
* @has - - - ACharacter
|
||||
*/
|
||||
class AWalkerSpawnerBase extends AActorWithRandomEngine {}
|
||||
|
||||
// =============================================================================
|
||||
// -- Blueprints ---------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Carla Game Mode
|
||||
* @opt commentname
|
||||
* @opt nodefillcolor #bfe4ff
|
||||
*/
|
||||
class CarlaGameMode extends ACarlaGameModeBase {}
|
||||
|
||||
/**
|
||||
* Speed Limit Sign
|
||||
* @opt commentname
|
||||
* @opt nodefillcolor #bfe4ff
|
||||
*/
|
||||
class SpeedLimitSignBlueprint extends ATrafficSignBase {}
|
||||
|
||||
/**
|
||||
* Traffic Light
|
||||
* @opt commentname
|
||||
* @opt nodefillcolor #bfe4ff
|
||||
*/
|
||||
class TrafficLightBlueprint extends ATrafficLightBase {}
|
||||
|
||||
/**
|
||||
* Vehicle Blueprints
|
||||
* @opt commentname
|
||||
* @opt nodefillcolor #bfe4ff
|
||||
*/
|
||||
class VehicleBlueprints extends ACarlaWheeledVehicle {}
|
||||
|
||||
/**
|
||||
* Vehicle Spawner
|
||||
* @opt commentname
|
||||
* @opt nodefillcolor #bfe4ff
|
||||
*/
|
||||
class VehicleSpawnerBlueprint extends AVehicleSpawnerBase {}
|
||||
|
||||
/**
|
||||
* Walker Blueprints
|
||||
* @opt commentname
|
||||
* @opt nodefillcolor #bfe4ff
|
||||
* @composed - - - UWalkerAgentComponent
|
||||
*/
|
||||
class WalkerBlueprints extends ACharacter {}
|
||||
|
||||
/**
|
||||
* Walker Spawner
|
||||
* @opt commentname
|
||||
* @opt nodefillcolor #bfe4ff
|
||||
*/
|
||||
class WalkerSpawnerBlueprint extends AWalkerSpawnerBase {}
|
Binary file not shown.
After Width: | Height: | Size: 248 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.8 MiB |
|
@ -7,6 +7,7 @@ CARLA Documentation
|
|||
* [CARLA settings](carla_settings.md)
|
||||
* [Measurements](measurements.md)
|
||||
* [Cameras and sensors](cameras_and_sensors.md)
|
||||
* [CARLA without Display and Selecting GPUs](carla_headless.md)
|
||||
* [Benchmark](benchmark.md)
|
||||
* [F.A.Q.](faq.md)
|
||||
|
||||
|
|
|
@ -6,4 +6,7 @@ If you are asking a question please make sure your question was not asked before
|
|||
by searching among the existing issues. Also make sure you have read our
|
||||
documentation and FAQ at carla.readthedocs.io.
|
||||
|
||||
If you are reporting an issue, please provide the CARLA version number you are
|
||||
using and your Platform/OS.
|
||||
|
||||
-->
|
||||
|
|
4
Makefile
4
Makefile
|
@ -88,9 +88,9 @@ run_test_release:
|
|||
|
||||
launch_test_clients:
|
||||
@echo "Launch echo client"
|
||||
@python3 $(PYTHON_CLIENT_FOLDER)/test_client.py --echo -p 4000 --log echo_client.log & echo $$! > echo_client.pid
|
||||
@python3 $(PYTHON_CLIENT_FOLDER)/test_client.py --echo -v -p 4000 --log echo_client.log & echo $$! > echo_client.pid
|
||||
@echo "Launch carla client"
|
||||
@python3 $(PYTHON_CLIENT_FOLDER)/test_client.py -p 2000 --log carla_client.log & echo $$! > carla_client.pid
|
||||
@python3 $(PYTHON_CLIENT_FOLDER)/test_client.py -v -p 2000 --log carla_client.log & echo $$! > carla_client.pid
|
||||
|
||||
kill_test_clients:
|
||||
@echo "Kill echo client"
|
||||
|
|
|
@ -120,9 +120,15 @@ if $DO_COPY_FILES ; then
|
|||
cp -v ./Docs/Example.CarlaSettings.ini ${DESTINATION}/Example.CarlaSettings.ini
|
||||
|
||||
rsync -vhr --delete --delete-excluded \
|
||||
--exclude "__pycache__" \
|
||||
--exclude "*.egg-info" \
|
||||
--exclude "*.log" \
|
||||
--exclude "*.pyc" \
|
||||
--exclude ".*" \
|
||||
--exclude ".tags*" \
|
||||
--exclude "__pycache__" \
|
||||
--exclude "_benchmarks_results*" \
|
||||
--exclude "_images*" \
|
||||
--exclude "_out*" \
|
||||
PythonClient/ ${DESTINATION}/PythonClient
|
||||
|
||||
echo
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[TYPECHECK]
|
||||
ignore=carla_server_pb2.py
|
||||
ignored-modules=ConfigParser,numpy,numpy.random,pygame,shutil
|
||||
ignored-classes=_socketobject,EpisodeReady
|
||||
ignored-classes=_socketobject,EpisodeReady,SceneDescription,Sensor
|
||||
|
|
|
@ -138,7 +138,7 @@ class CoRL2017(Benchmark):
|
|||
# This single RGB camera is used on every experiment
|
||||
|
||||
camera = Camera('CameraRGB')
|
||||
camera.set(CameraFOV=100)
|
||||
camera.set(FOV=100)
|
||||
|
||||
camera.set_image_size(800, 600)
|
||||
|
||||
|
|
|
@ -19,11 +19,37 @@ DESCRIPTOR = _descriptor.FileDescriptor(
|
|||
name='carla_server.proto',
|
||||
package='carla_server',
|
||||
syntax='proto3',
|
||||
serialized_pb=_b('\n\x12\x63\x61rla_server.proto\x12\x0c\x63\x61rla_server\"+\n\x08Vector3D\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\x12\t\n\x01z\x18\x03 \x01(\x02\"6\n\nRotation3D\x12\r\n\x05pitch\x18\x01 \x01(\x02\x12\x0b\n\x03yaw\x18\x02 \x01(\x02\x12\x0c\n\x04roll\x18\x03 \x01(\x02\"\x92\x01\n\tTransform\x12(\n\x08location\x18\x01 \x01(\x0b\x32\x16.carla_server.Vector3D\x12/\n\x0borientation\x18\x02 \x01(\x0b\x32\x16.carla_server.Vector3DB\x02\x18\x01\x12*\n\x08rotation\x18\x03 \x01(\x0b\x32\x18.carla_server.Rotation3D\"x\n\x07Vehicle\x12*\n\ttransform\x18\x01 \x01(\x0b\x32\x17.carla_server.Transform\x12*\n\nbox_extent\x18\x02 \x01(\x0b\x32\x16.carla_server.Vector3D\x12\x15\n\rforward_speed\x18\x03 \x01(\x02\"{\n\nPedestrian\x12*\n\ttransform\x18\x01 \x01(\x0b\x32\x17.carla_server.Transform\x12*\n\nbox_extent\x18\x02 \x01(\x0b\x32\x16.carla_server.Vector3D\x12\x15\n\rforward_speed\x18\x03 \x01(\x02\"\x94\x01\n\x0cTrafficLight\x12*\n\ttransform\x18\x01 \x01(\x0b\x32\x17.carla_server.Transform\x12/\n\x05state\x18\x02 \x01(\x0e\x32 .carla_server.TrafficLight.State\"\'\n\x05State\x12\t\n\x05GREEN\x10\x00\x12\n\n\x06YELLOW\x10\x01\x12\x07\n\x03RED\x10\x02\"Q\n\x0eSpeedLimitSign\x12*\n\ttransform\x18\x01 \x01(\x0b\x32\x17.carla_server.Transform\x12\x13\n\x0bspeed_limit\x18\x02 \x01(\x02\"\xe5\x01\n\x05\x41gent\x12\n\n\x02id\x18\x01 \x01(\x07\x12(\n\x07vehicle\x18\x02 \x01(\x0b\x32\x15.carla_server.VehicleH\x00\x12.\n\npedestrian\x18\x03 \x01(\x0b\x32\x18.carla_server.PedestrianH\x00\x12\x33\n\rtraffic_light\x18\x04 \x01(\x0b\x32\x1a.carla_server.TrafficLightH\x00\x12\x38\n\x10speed_limit_sign\x18\x05 \x01(\x0b\x32\x1c.carla_server.SpeedLimitSignH\x00\x42\x07\n\x05\x61gent\"%\n\x11RequestNewEpisode\x12\x10\n\x08ini_file\x18\x01 \x01(\t\"G\n\x10SceneDescription\x12\x33\n\x12player_start_spots\x18\x01 \x03(\x0b\x32\x17.carla_server.Transform\"/\n\x0c\x45pisodeStart\x12\x1f\n\x17player_start_spot_index\x18\x01 \x01(\r\"\x1d\n\x0c\x45pisodeReady\x12\r\n\x05ready\x18\x01 \x01(\x08\"^\n\x07\x43ontrol\x12\r\n\x05steer\x18\x01 \x01(\x02\x12\x10\n\x08throttle\x18\x02 \x01(\x02\x12\r\n\x05\x62rake\x18\x03 \x01(\x02\x12\x12\n\nhand_brake\x18\x04 \x01(\x08\x12\x0f\n\x07reverse\x18\x05 \x01(\x08\"\x8a\x04\n\x0cMeasurements\x12\x1a\n\x12platform_timestamp\x18\x01 \x01(\r\x12\x16\n\x0egame_timestamp\x18\x02 \x01(\r\x12J\n\x13player_measurements\x18\x03 \x01(\x0b\x32-.carla_server.Measurements.PlayerMeasurements\x12.\n\x11non_player_agents\x18\x04 \x03(\x0b\x32\x13.carla_server.Agent\x1a\xc9\x02\n\x12PlayerMeasurements\x12*\n\ttransform\x18\x01 \x01(\x0b\x32\x17.carla_server.Transform\x12,\n\x0c\x61\x63\x63\x65leration\x18\x03 \x01(\x0b\x32\x16.carla_server.Vector3D\x12\x15\n\rforward_speed\x18\x04 \x01(\x02\x12\x1a\n\x12\x63ollision_vehicles\x18\x05 \x01(\x02\x12\x1d\n\x15\x63ollision_pedestrians\x18\x06 \x01(\x02\x12\x17\n\x0f\x63ollision_other\x18\x07 \x01(\x02\x12\x1e\n\x16intersection_otherlane\x18\x08 \x01(\x02\x12\x1c\n\x14intersection_offroad\x18\t \x01(\x02\x12\x30\n\x11\x61utopilot_control\x18\n \x01(\x0b\x32\x15.carla_server.ControlB\x03\xf8\x01\x01\x62\x06proto3')
|
||||
serialized_pb=_b('\n\x12\x63\x61rla_server.proto\x12\x0c\x63\x61rla_server\"+\n\x08Vector3D\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\x12\t\n\x01z\x18\x03 \x01(\x02\"6\n\nRotation3D\x12\r\n\x05pitch\x18\x01 \x01(\x02\x12\x0b\n\x03yaw\x18\x02 \x01(\x02\x12\x0c\n\x04roll\x18\x03 \x01(\x02\"\x92\x01\n\tTransform\x12(\n\x08location\x18\x01 \x01(\x0b\x32\x16.carla_server.Vector3D\x12/\n\x0borientation\x18\x02 \x01(\x0b\x32\x16.carla_server.Vector3DB\x02\x18\x01\x12*\n\x08rotation\x18\x03 \x01(\x0b\x32\x18.carla_server.Rotation3D\"\x81\x01\n\x06Sensor\x12\n\n\x02id\x18\x01 \x01(\x07\x12\'\n\x04type\x18\x02 \x01(\x0e\x32\x19.carla_server.Sensor.Type\x12\x0c\n\x04name\x18\x03 \x01(\t\"4\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06\x43\x41MERA\x10\x01\x12\x13\n\x0fLIDAR_RAY_TRACE\x10\x02\"x\n\x07Vehicle\x12*\n\ttransform\x18\x01 \x01(\x0b\x32\x17.carla_server.Transform\x12*\n\nbox_extent\x18\x02 \x01(\x0b\x32\x16.carla_server.Vector3D\x12\x15\n\rforward_speed\x18\x03 \x01(\x02\"{\n\nPedestrian\x12*\n\ttransform\x18\x01 \x01(\x0b\x32\x17.carla_server.Transform\x12*\n\nbox_extent\x18\x02 \x01(\x0b\x32\x16.carla_server.Vector3D\x12\x15\n\rforward_speed\x18\x03 \x01(\x02\"\x94\x01\n\x0cTrafficLight\x12*\n\ttransform\x18\x01 \x01(\x0b\x32\x17.carla_server.Transform\x12/\n\x05state\x18\x02 \x01(\x0e\x32 .carla_server.TrafficLight.State\"\'\n\x05State\x12\t\n\x05GREEN\x10\x00\x12\n\n\x06YELLOW\x10\x01\x12\x07\n\x03RED\x10\x02\"Q\n\x0eSpeedLimitSign\x12*\n\ttransform\x18\x01 \x01(\x0b\x32\x17.carla_server.Transform\x12\x13\n\x0bspeed_limit\x18\x02 \x01(\x02\"\xe5\x01\n\x05\x41gent\x12\n\n\x02id\x18\x01 \x01(\x07\x12(\n\x07vehicle\x18\x02 \x01(\x0b\x32\x15.carla_server.VehicleH\x00\x12.\n\npedestrian\x18\x03 \x01(\x0b\x32\x18.carla_server.PedestrianH\x00\x12\x33\n\rtraffic_light\x18\x04 \x01(\x0b\x32\x1a.carla_server.TrafficLightH\x00\x12\x38\n\x10speed_limit_sign\x18\x05 \x01(\x0b\x32\x1c.carla_server.SpeedLimitSignH\x00\x42\x07\n\x05\x61gent\"%\n\x11RequestNewEpisode\x12\x10\n\x08ini_file\x18\x01 \x01(\t\"n\n\x10SceneDescription\x12\x33\n\x12player_start_spots\x18\x01 \x03(\x0b\x32\x17.carla_server.Transform\x12%\n\x07sensors\x18\x02 \x03(\x0b\x32\x14.carla_server.Sensor\"/\n\x0c\x45pisodeStart\x12\x1f\n\x17player_start_spot_index\x18\x01 \x01(\r\"\x1d\n\x0c\x45pisodeReady\x12\r\n\x05ready\x18\x01 \x01(\x08\"^\n\x07\x43ontrol\x12\r\n\x05steer\x18\x01 \x01(\x02\x12\x10\n\x08throttle\x18\x02 \x01(\x02\x12\r\n\x05\x62rake\x18\x03 \x01(\x02\x12\x12\n\nhand_brake\x18\x04 \x01(\x08\x12\x0f\n\x07reverse\x18\x05 \x01(\x08\"\x8a\x04\n\x0cMeasurements\x12\x1a\n\x12platform_timestamp\x18\x01 \x01(\r\x12\x16\n\x0egame_timestamp\x18\x02 \x01(\r\x12J\n\x13player_measurements\x18\x03 \x01(\x0b\x32-.carla_server.Measurements.PlayerMeasurements\x12.\n\x11non_player_agents\x18\x04 \x03(\x0b\x32\x13.carla_server.Agent\x1a\xc9\x02\n\x12PlayerMeasurements\x12*\n\ttransform\x18\x01 \x01(\x0b\x32\x17.carla_server.Transform\x12,\n\x0c\x61\x63\x63\x65leration\x18\x03 \x01(\x0b\x32\x16.carla_server.Vector3D\x12\x15\n\rforward_speed\x18\x04 \x01(\x02\x12\x1a\n\x12\x63ollision_vehicles\x18\x05 \x01(\x02\x12\x1d\n\x15\x63ollision_pedestrians\x18\x06 \x01(\x02\x12\x17\n\x0f\x63ollision_other\x18\x07 \x01(\x02\x12\x1e\n\x16intersection_otherlane\x18\x08 \x01(\x02\x12\x1c\n\x14intersection_offroad\x18\t \x01(\x02\x12\x30\n\x11\x61utopilot_control\x18\n \x01(\x0b\x32\x15.carla_server.ControlB\x03\xf8\x01\x01\x62\x06proto3')
|
||||
)
|
||||
|
||||
|
||||
|
||||
_SENSOR_TYPE = _descriptor.EnumDescriptor(
|
||||
name='Type',
|
||||
full_name='carla_server.Sensor.Type',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
values=[
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='UNKNOWN', index=0, number=0,
|
||||
options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='CAMERA', index=1, number=1,
|
||||
options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='LIDAR_RAY_TRACE', index=2, number=2,
|
||||
options=None,
|
||||
type=None),
|
||||
],
|
||||
containing_type=None,
|
||||
options=None,
|
||||
serialized_start=364,
|
||||
serialized_end=416,
|
||||
)
|
||||
_sym_db.RegisterEnumDescriptor(_SENSOR_TYPE)
|
||||
|
||||
_TRAFFICLIGHT_STATE = _descriptor.EnumDescriptor(
|
||||
name='State',
|
||||
full_name='carla_server.TrafficLight.State',
|
||||
|
@ -45,8 +71,8 @@ _TRAFFICLIGHT_STATE = _descriptor.EnumDescriptor(
|
|||
],
|
||||
containing_type=None,
|
||||
options=None,
|
||||
serialized_start=643,
|
||||
serialized_end=682,
|
||||
serialized_start=775,
|
||||
serialized_end=814,
|
||||
)
|
||||
_sym_db.RegisterEnumDescriptor(_TRAFFICLIGHT_STATE)
|
||||
|
||||
|
@ -186,6 +212,52 @@ _TRANSFORM = _descriptor.Descriptor(
|
|||
)
|
||||
|
||||
|
||||
_SENSOR = _descriptor.Descriptor(
|
||||
name='Sensor',
|
||||
full_name='carla_server.Sensor',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='id', full_name='carla_server.Sensor.id', index=0,
|
||||
number=1, type=7, cpp_type=3, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='type', full_name='carla_server.Sensor.type', index=1,
|
||||
number=2, type=14, cpp_type=8, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='name', full_name='carla_server.Sensor.name', index=2,
|
||||
number=3, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
_SENSOR_TYPE,
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=287,
|
||||
serialized_end=416,
|
||||
)
|
||||
|
||||
|
||||
_VEHICLE = _descriptor.Descriptor(
|
||||
name='Vehicle',
|
||||
full_name='carla_server.Vehicle',
|
||||
|
@ -226,8 +298,8 @@ _VEHICLE = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=286,
|
||||
serialized_end=406,
|
||||
serialized_start=418,
|
||||
serialized_end=538,
|
||||
)
|
||||
|
||||
|
||||
|
@ -271,8 +343,8 @@ _PEDESTRIAN = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=408,
|
||||
serialized_end=531,
|
||||
serialized_start=540,
|
||||
serialized_end=663,
|
||||
)
|
||||
|
||||
|
||||
|
@ -310,8 +382,8 @@ _TRAFFICLIGHT = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=534,
|
||||
serialized_end=682,
|
||||
serialized_start=666,
|
||||
serialized_end=814,
|
||||
)
|
||||
|
||||
|
||||
|
@ -348,8 +420,8 @@ _SPEEDLIMITSIGN = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=684,
|
||||
serialized_end=765,
|
||||
serialized_start=816,
|
||||
serialized_end=897,
|
||||
)
|
||||
|
||||
|
||||
|
@ -410,8 +482,8 @@ _AGENT = _descriptor.Descriptor(
|
|||
name='agent', full_name='carla_server.Agent.agent',
|
||||
index=0, containing_type=None, fields=[]),
|
||||
],
|
||||
serialized_start=768,
|
||||
serialized_end=997,
|
||||
serialized_start=900,
|
||||
serialized_end=1129,
|
||||
)
|
||||
|
||||
|
||||
|
@ -441,8 +513,8 @@ _REQUESTNEWEPISODE = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=999,
|
||||
serialized_end=1036,
|
||||
serialized_start=1131,
|
||||
serialized_end=1168,
|
||||
)
|
||||
|
||||
|
||||
|
@ -460,6 +532,13 @@ _SCENEDESCRIPTION = _descriptor.Descriptor(
|
|||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='sensors', full_name='carla_server.SceneDescription.sensors', index=1,
|
||||
number=2, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
|
@ -472,8 +551,8 @@ _SCENEDESCRIPTION = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1038,
|
||||
serialized_end=1109,
|
||||
serialized_start=1170,
|
||||
serialized_end=1280,
|
||||
)
|
||||
|
||||
|
||||
|
@ -503,8 +582,8 @@ _EPISODESTART = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1111,
|
||||
serialized_end=1158,
|
||||
serialized_start=1282,
|
||||
serialized_end=1329,
|
||||
)
|
||||
|
||||
|
||||
|
@ -534,8 +613,8 @@ _EPISODEREADY = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1160,
|
||||
serialized_end=1189,
|
||||
serialized_start=1331,
|
||||
serialized_end=1360,
|
||||
)
|
||||
|
||||
|
||||
|
@ -593,8 +672,8 @@ _CONTROL = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1191,
|
||||
serialized_end=1285,
|
||||
serialized_start=1362,
|
||||
serialized_end=1456,
|
||||
)
|
||||
|
||||
|
||||
|
@ -680,8 +759,8 @@ _MEASUREMENTS_PLAYERMEASUREMENTS = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1481,
|
||||
serialized_end=1810,
|
||||
serialized_start=1652,
|
||||
serialized_end=1981,
|
||||
)
|
||||
|
||||
_MEASUREMENTS = _descriptor.Descriptor(
|
||||
|
@ -731,13 +810,15 @@ _MEASUREMENTS = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1288,
|
||||
serialized_end=1810,
|
||||
serialized_start=1459,
|
||||
serialized_end=1981,
|
||||
)
|
||||
|
||||
_TRANSFORM.fields_by_name['location'].message_type = _VECTOR3D
|
||||
_TRANSFORM.fields_by_name['orientation'].message_type = _VECTOR3D
|
||||
_TRANSFORM.fields_by_name['rotation'].message_type = _ROTATION3D
|
||||
_SENSOR.fields_by_name['type'].enum_type = _SENSOR_TYPE
|
||||
_SENSOR_TYPE.containing_type = _SENSOR
|
||||
_VEHICLE.fields_by_name['transform'].message_type = _TRANSFORM
|
||||
_VEHICLE.fields_by_name['box_extent'].message_type = _VECTOR3D
|
||||
_PEDESTRIAN.fields_by_name['transform'].message_type = _TRANSFORM
|
||||
|
@ -763,6 +844,7 @@ _AGENT.oneofs_by_name['agent'].fields.append(
|
|||
_AGENT.fields_by_name['speed_limit_sign'])
|
||||
_AGENT.fields_by_name['speed_limit_sign'].containing_oneof = _AGENT.oneofs_by_name['agent']
|
||||
_SCENEDESCRIPTION.fields_by_name['player_start_spots'].message_type = _TRANSFORM
|
||||
_SCENEDESCRIPTION.fields_by_name['sensors'].message_type = _SENSOR
|
||||
_MEASUREMENTS_PLAYERMEASUREMENTS.fields_by_name['transform'].message_type = _TRANSFORM
|
||||
_MEASUREMENTS_PLAYERMEASUREMENTS.fields_by_name['acceleration'].message_type = _VECTOR3D
|
||||
_MEASUREMENTS_PLAYERMEASUREMENTS.fields_by_name['autopilot_control'].message_type = _CONTROL
|
||||
|
@ -772,6 +854,7 @@ _MEASUREMENTS.fields_by_name['non_player_agents'].message_type = _AGENT
|
|||
DESCRIPTOR.message_types_by_name['Vector3D'] = _VECTOR3D
|
||||
DESCRIPTOR.message_types_by_name['Rotation3D'] = _ROTATION3D
|
||||
DESCRIPTOR.message_types_by_name['Transform'] = _TRANSFORM
|
||||
DESCRIPTOR.message_types_by_name['Sensor'] = _SENSOR
|
||||
DESCRIPTOR.message_types_by_name['Vehicle'] = _VEHICLE
|
||||
DESCRIPTOR.message_types_by_name['Pedestrian'] = _PEDESTRIAN
|
||||
DESCRIPTOR.message_types_by_name['TrafficLight'] = _TRAFFICLIGHT
|
||||
|
@ -806,6 +889,13 @@ Transform = _reflection.GeneratedProtocolMessageType('Transform', (_message.Mess
|
|||
))
|
||||
_sym_db.RegisterMessage(Transform)
|
||||
|
||||
Sensor = _reflection.GeneratedProtocolMessageType('Sensor', (_message.Message,), dict(
|
||||
DESCRIPTOR = _SENSOR,
|
||||
__module__ = 'carla_server_pb2'
|
||||
# @@protoc_insertion_point(class_scope:carla_server.Sensor)
|
||||
))
|
||||
_sym_db.RegisterMessage(Sensor)
|
||||
|
||||
Vehicle = _reflection.GeneratedProtocolMessageType('Vehicle', (_message.Message,), dict(
|
||||
DESCRIPTOR = _VEHICLE,
|
||||
__module__ = 'carla_server_pb2'
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
|
||||
"""CARLA Client."""
|
||||
|
||||
import logging
|
||||
import struct
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
from . import sensor
|
||||
from . import settings
|
||||
from . import tcp
|
||||
from . import util
|
||||
|
||||
|
@ -20,6 +20,11 @@ try:
|
|||
except ImportError:
|
||||
raise RuntimeError('cannot import "carla_server_pb2.py", run the protobuf compiler to generate this file')
|
||||
|
||||
try:
|
||||
import numpy
|
||||
except ImportError:
|
||||
raise RuntimeError('cannot import numpy, make sure numpy package is installed.')
|
||||
|
||||
|
||||
VehicleControl = carla_protocol.Control
|
||||
|
||||
|
@ -40,7 +45,7 @@ class CarlaClient(object):
|
|||
self._control_client = tcp.TCPClient(host, world_port + 2, timeout)
|
||||
self._current_settings = None
|
||||
self._is_episode_requested = False
|
||||
self._sensor_names = []
|
||||
self._sensors = {}
|
||||
|
||||
def connect(self, connection_attempts=10):
|
||||
"""
|
||||
|
@ -69,7 +74,6 @@ class CarlaClient(object):
|
|||
self._current_settings = carla_settings
|
||||
return self._request_new_episode(carla_settings)
|
||||
|
||||
|
||||
def start_episode(self, player_start_index):
|
||||
"""
|
||||
Start the new episode at the player start given by the
|
||||
|
@ -120,8 +124,7 @@ class CarlaClient(object):
|
|||
pb_message = carla_protocol.Measurements()
|
||||
pb_message.ParseFromString(data)
|
||||
# Read sensor data.
|
||||
raw_sensor_data = self._stream_client.read()
|
||||
return pb_message, self._parse_raw_sensor_data(raw_sensor_data)
|
||||
return pb_message, dict(x for x in self._read_sensor_data())
|
||||
|
||||
def send_control(self, *args, **kwargs):
|
||||
"""
|
||||
|
@ -159,30 +162,66 @@ class CarlaClient(object):
|
|||
raise RuntimeError('failed to read data from server')
|
||||
pb_message = carla_protocol.SceneDescription()
|
||||
pb_message.ParseFromString(data)
|
||||
self._sensor_names = settings.get_sensor_names(carla_settings)
|
||||
self._sensors = dict((sensor.id, sensor) \
|
||||
for sensor in _make_sensor_parsers(pb_message.sensors))
|
||||
self._is_episode_requested = True
|
||||
return pb_message
|
||||
|
||||
def _parse_raw_sensor_data(self, raw_data):
|
||||
"""Return a dict of {'sensor_name': sensor_data, ...}."""
|
||||
return dict((name, data) for name, data in zip(
|
||||
self._sensor_names,
|
||||
self._iterate_sensor_data(raw_data)))
|
||||
def _read_sensor_data(self):
|
||||
while True:
|
||||
data = self._stream_client.read()
|
||||
if not data:
|
||||
raise StopIteration
|
||||
yield self._parse_sensor_data(data)
|
||||
|
||||
@staticmethod
|
||||
def _iterate_sensor_data(raw_data):
|
||||
# At this point the only sensors available are images, the raw_data
|
||||
# consists of images only.
|
||||
image_types = ['None', 'SceneFinal', 'Depth', 'SemanticSegmentation']
|
||||
gettype = lambda id: image_types[id] if len(image_types) > id else 'Unknown'
|
||||
getval = lambda index: struct.unpack('<L', raw_data[index*4:index*4+4])[0]
|
||||
total_size = len(raw_data) / 4
|
||||
index = 0
|
||||
while index < total_size:
|
||||
width = getval(index)
|
||||
height = getval(index + 1)
|
||||
image_type = gettype(getval(index + 2))
|
||||
begin = index + 3
|
||||
end = begin + width * height
|
||||
index = end
|
||||
yield sensor.Image(width, height, image_type, raw_data[begin*4:end*4])
|
||||
def _parse_sensor_data(self, data):
|
||||
sensor_id = struct.unpack('<L', data[0:4])[0]
|
||||
parser = self._sensors[sensor_id]
|
||||
return parser.name, parser.parse_raw_data(data[4:])
|
||||
|
||||
|
||||
def _make_sensor_parsers(sensors):
|
||||
image_types = ['None', 'SceneFinal', 'Depth', 'SemanticSegmentation']
|
||||
getimgtype = lambda id: image_types[id] if len(image_types) > id else 'Unknown'
|
||||
getint = lambda data, index: struct.unpack('<L', data[index*4:index*4+4])[0]
|
||||
getfloat = lambda data, index: struct.unpack('<f', data[index*4:index*4+4])[0]
|
||||
|
||||
def parse_image(data):
|
||||
width = getint(data, 0)
|
||||
height = getint(data, 1)
|
||||
image_type = getimgtype(getint(data, 2))
|
||||
fov = getfloat(data, 3)
|
||||
return sensor.Image(width, height, image_type, fov, data[16:])
|
||||
|
||||
def parse_lidar(data):
|
||||
horizontal_angle = getfloat(data, 0)
|
||||
channels = getint(data, 1)
|
||||
point_count_by_channel = numpy.frombuffer(
|
||||
data[8:8+channels*4],
|
||||
dtype=numpy.dtype('uint32'))
|
||||
points = numpy.frombuffer(
|
||||
data[8+channels*4:],
|
||||
dtype=numpy.dtype('f4'))
|
||||
points = numpy.reshape(points, (int(points.shape[0]/3), 3))
|
||||
return sensor.LidarMeasurement(
|
||||
horizontal_angle,
|
||||
channels,
|
||||
point_count_by_channel,
|
||||
sensor.PointCloud(points))
|
||||
|
||||
class SensorDefinition(object):
|
||||
def __init__(self, s):
|
||||
self.id = s.id
|
||||
self.name = s.name
|
||||
self.type = s.type
|
||||
self.parse_raw_data = lambda x: x
|
||||
|
||||
for s in sensors:
|
||||
sensor_def = SensorDefinition(s)
|
||||
if sensor_def.type == carla_protocol.Sensor.CAMERA:
|
||||
sensor_def.parse_raw_data = parse_image
|
||||
elif sensor_def.type == carla_protocol.Sensor.LIDAR_RAY_TRACE:
|
||||
sensor_def.parse_raw_data = parse_lidar
|
||||
else:
|
||||
logging.error('unknown sensor type %s', sensor_def.type)
|
||||
yield sensor_def
|
||||
|
|
|
@ -13,9 +13,11 @@ them afterwards with the C++ implementation at "Util/ImageConverter" as it
|
|||
provides considerably better performance.
|
||||
"""
|
||||
|
||||
import math
|
||||
|
||||
try:
|
||||
import numpy
|
||||
from numpy.matlib import repmat
|
||||
except ImportError:
|
||||
raise RuntimeError('cannot import numpy, make sure numpy package is installed')
|
||||
|
||||
|
@ -55,19 +57,19 @@ def labels_to_cityscapes_palette(image):
|
|||
Cityscapes palette.
|
||||
"""
|
||||
classes = {
|
||||
0: [0, 0, 0], # None
|
||||
1: [70, 70, 70], # Buildings
|
||||
2: [190, 153, 153], # Fences
|
||||
3: [72, 0, 90], # Other
|
||||
4: [220, 20, 60], # Pedestrians
|
||||
5: [153, 153, 153], # Poles
|
||||
6: [157, 234, 50], # RoadLines
|
||||
7: [128, 64, 128], # Roads
|
||||
8: [244, 35, 232], # Sidewalks
|
||||
9: [107, 142, 35], # Vegetation
|
||||
10: [0, 0, 255], # Vehicles
|
||||
11: [102, 102, 156], # Walls
|
||||
12: [220, 220, 0] # TrafficSigns
|
||||
0: [0, 0, 0], # None
|
||||
1: [70, 70, 70], # Buildings
|
||||
2: [190, 153, 153], # Fences
|
||||
3: [72, 0, 90], # Other
|
||||
4: [220, 20, 60], # Pedestrians
|
||||
5: [153, 153, 153], # Poles
|
||||
6: [157, 234, 50], # RoadLines
|
||||
7: [128, 64, 128], # Roads
|
||||
8: [244, 35, 232], # Sidewalks
|
||||
9: [107, 142, 35], # Vegetation
|
||||
10: [0, 0, 255], # Vehicles
|
||||
11: [102, 102, 156], # Walls
|
||||
12: [220, 220, 0] # TrafficSigns
|
||||
}
|
||||
array = labels_to_array(image)
|
||||
result = numpy.zeros((array.shape[0], array.shape[1], 3))
|
||||
|
@ -84,20 +86,74 @@ def depth_to_array(image):
|
|||
array = to_bgra_array(image)
|
||||
array = array.astype(numpy.float32)
|
||||
# Apply (R + G * 256 + B * 256 * 256) / (256 * 256 * 256 - 1).
|
||||
grayscale = numpy.dot(array[:, :, :3], [256.0 * 256.0, 256.0, 1.0])
|
||||
grayscale /= (256.0 * 256.0 * 256.0 - 1.0)
|
||||
return grayscale
|
||||
normalized_depth = numpy.dot(array[:, :, :3], [65536.0, 256.0, 1.0])
|
||||
normalized_depth /= 16777215.0 # (256.0 * 256.0 * 256.0 - 1.0)
|
||||
return normalized_depth
|
||||
|
||||
|
||||
def depth_to_logarithmic_grayscale(image):
|
||||
"""
|
||||
Convert an image containing CARLA encoded depth-map to a logarithmic
|
||||
grayscale image array.
|
||||
"max_depth" is used to omit the points that are far enough.
|
||||
"""
|
||||
grayscale = depth_to_array(image)
|
||||
normalized_depth = depth_to_array(image)
|
||||
# Convert to logarithmic depth.
|
||||
logdepth = numpy.ones(grayscale.shape) + (numpy.log(grayscale) / 5.70378)
|
||||
logdepth = numpy.ones(normalized_depth.shape) + \
|
||||
(numpy.log(normalized_depth) / 5.70378)
|
||||
logdepth = numpy.clip(logdepth, 0.0, 1.0)
|
||||
logdepth *= 255.0
|
||||
# Expand to three colors.
|
||||
return numpy.repeat(logdepth[:, :, numpy.newaxis], 3, axis=2)
|
||||
|
||||
|
||||
def depth_to_local_point_cloud(image, color=None, max_depth=0.9):
|
||||
"""
|
||||
Convert an image containing CARLA encoded depth-map to a 2D array containing
|
||||
the 3D position (relative to the camera) of each pixel and its corresponding
|
||||
RGB color of an array.
|
||||
"max_depth" is used to omit the points that are far enough.
|
||||
"""
|
||||
far = 100000.0 # max depth in centimeters
|
||||
normalized_depth = depth_to_array(image)
|
||||
|
||||
# (Intrinsic) K Matrix
|
||||
k = numpy.identity(3)
|
||||
k[0, 2] = image.width / 2.0
|
||||
k[1, 2] = image.height / 2.0
|
||||
k[0, 0] = k[1, 1] = image.width / \
|
||||
(2.0 * math.tan(image.fov * math.pi / 360.0))
|
||||
|
||||
# 2d pixel coordinates
|
||||
pixel_length = image.width * image.height
|
||||
u_coord = repmat(numpy.r_[image.width-1:-1:-1],
|
||||
image.height, 1).reshape(pixel_length)
|
||||
v_coord = repmat(numpy.c_[image.height-1:-1:-1],
|
||||
1, image.width).reshape(pixel_length)
|
||||
if color is not None:
|
||||
color = color.reshape(pixel_length, 3)
|
||||
normalized_depth = numpy.reshape(normalized_depth, pixel_length)
|
||||
|
||||
# Search for pixels where the depth is greater than max_depth to
|
||||
# delete them
|
||||
max_depth_indexes = numpy.where(normalized_depth > max_depth)
|
||||
normalized_depth = numpy.delete(normalized_depth, max_depth_indexes)
|
||||
u_coord = numpy.delete(u_coord, max_depth_indexes)
|
||||
v_coord = numpy.delete(v_coord, max_depth_indexes)
|
||||
if color is not None:
|
||||
color = numpy.delete(color, max_depth_indexes, axis=0)
|
||||
|
||||
# pd2 = [u,v,1]
|
||||
p2d = numpy.array([u_coord, v_coord, numpy.ones_like(u_coord)])
|
||||
|
||||
# P = [X,Y,Z]
|
||||
p3d = numpy.dot(numpy.linalg.inv(k), p2d)
|
||||
p3d *= normalized_depth * far
|
||||
|
||||
# Formating the output to:
|
||||
# [[X1,Y1,Z1,R1,G1,B1],[X2,Y2,Z2,R2,G2,B2], ... [Xn,Yn,Zn,Rn,Gn,Bn]]
|
||||
if color is not None:
|
||||
# numpy.concatenate((numpy.transpose(p3d), color), axis=1)
|
||||
return sensor.PointCloud(numpy.transpose(p3d), color_array=color)
|
||||
# [[X1,Y1,Z1],[X2,Y2,Z2], ... [Xn,Yn,Zn]]
|
||||
return sensor.PointCloud(numpy.transpose(p3d))
|
||||
|
|
|
@ -9,6 +9,32 @@
|
|||
|
||||
import os
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
try:
|
||||
import numpy
|
||||
except ImportError:
|
||||
raise RuntimeError('cannot import numpy, make sure numpy package is installed.')
|
||||
|
||||
from .transform import Transform, Translation, Rotation, Scale
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# -- Helpers -------------------------------------------------------------------
|
||||
# ==============================================================================
|
||||
|
||||
|
||||
Color = namedtuple('Color', 'r g b')
|
||||
Color.__new__.__defaults__ = (0, 0, 0)
|
||||
|
||||
|
||||
Point = namedtuple('Point', 'x y z color')
|
||||
Point.__new__.__defaults__ = (0.0, 0.0, 0.0, None)
|
||||
|
||||
|
||||
def _append_extension(filename, ext):
|
||||
return filename if filename.lower().endswith(ext.lower()) else filename + ext
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# -- Sensor --------------------------------------------------------------------
|
||||
|
@ -19,7 +45,51 @@ class Sensor(object):
|
|||
"""
|
||||
Base class for sensor descriptions. Used to add sensors to CarlaSettings.
|
||||
"""
|
||||
pass
|
||||
|
||||
def __init__(self, name, sensor_type):
|
||||
self.SensorName = name
|
||||
self.SensorType = sensor_type
|
||||
self.PositionX = 140.0
|
||||
self.PositionY = 0.0
|
||||
self.PositionZ = 140.0
|
||||
self.RotationPitch = 0.0
|
||||
self.RotationRoll = 0.0
|
||||
self.RotationYaw = 0.0
|
||||
|
||||
def set(self, **kwargs):
|
||||
for key, value in kwargs.items():
|
||||
if not hasattr(self, key):
|
||||
raise ValueError('sensor.Sensor: no key named %r' % key)
|
||||
setattr(self, key, value)
|
||||
|
||||
def set_position(self, x, y, z):
|
||||
self.PositionX = x
|
||||
self.PositionY = y
|
||||
self.PositionZ = z
|
||||
|
||||
def set_rotation(self, pitch, yaw, roll):
|
||||
self.RotationPitch = pitch
|
||||
self.RotationYaw = yaw
|
||||
self.RotationRoll = roll
|
||||
|
||||
def get_transform(self):
|
||||
'''
|
||||
Returns the camera to [whatever the camera is attached to]
|
||||
transformation.
|
||||
'''
|
||||
return Transform(
|
||||
Translation(self.PositionX, self.PositionY, self.PositionZ),
|
||||
Rotation(self.RotationPitch, self.RotationYaw, self.RotationRoll))
|
||||
|
||||
def get_unreal_transform(self):
|
||||
'''
|
||||
Returns the camera to [whatever the camera is attached to]
|
||||
transformation with the Unreal necessary corrections applied.
|
||||
|
||||
@todo Do we need to expose this?
|
||||
'''
|
||||
to_unreal_transform = Transform(Rotation(roll=-90, yaw=90), Scale(x=-1))
|
||||
return self.get_transform() * to_unreal_transform
|
||||
|
||||
|
||||
class Camera(Sensor):
|
||||
|
@ -29,45 +99,41 @@ class Camera(Sensor):
|
|||
"""
|
||||
|
||||
def __init__(self, name, **kwargs):
|
||||
self.CameraName = name
|
||||
super(Camera, self).__init__(name, sensor_type="CAMERA")
|
||||
self.PostProcessing = 'SceneFinal'
|
||||
self.ImageSizeX = 800
|
||||
self.ImageSizeY = 600
|
||||
self.CameraFOV = 90
|
||||
self.CameraPositionX = 140
|
||||
self.CameraPositionY = 0
|
||||
self.CameraPositionZ = 140
|
||||
self.CameraRotationPitch = 0
|
||||
self.CameraRotationRoll = 0
|
||||
self.CameraRotationYaw = 0
|
||||
self.ImageSizeX = 720
|
||||
self.ImageSizeY = 512
|
||||
self.FOV = 90.0
|
||||
self.set(**kwargs)
|
||||
|
||||
def set(self, **kwargs):
|
||||
for key, value in kwargs.items():
|
||||
if not hasattr(self, key):
|
||||
raise ValueError('CarlaSettings.Camera: no key named %r' % key)
|
||||
setattr(self, key, value)
|
||||
|
||||
def set_image_size(self, pixels_x, pixels_y):
|
||||
'''Sets the image size in pixels'''
|
||||
self.ImageSizeX = pixels_x
|
||||
self.ImageSizeY = pixels_y
|
||||
|
||||
def set_position(self, x, y, z):
|
||||
self.CameraPositionX = x
|
||||
self.CameraPositionY = y
|
||||
self.CameraPositionZ = z
|
||||
|
||||
def set_rotation(self, pitch, roll, yaw):
|
||||
self.CameraRotationPitch = pitch
|
||||
self.CameraRotationRoll = roll
|
||||
self.CameraRotationYaw = yaw
|
||||
class Lidar(Sensor):
|
||||
"""
|
||||
Lidar description. This class can be added to a CarlaSettings object to add
|
||||
a Lidar to the player vehicle.
|
||||
"""
|
||||
|
||||
def __init__(self, name, **kwargs):
|
||||
super(Lidar, self).__init__(name, sensor_type="LIDAR_RAY_TRACE")
|
||||
self.Channels = 32
|
||||
self.Range = 5000.0
|
||||
self.PointsPerSecond = 56000
|
||||
self.RotationFrequency = 10.0
|
||||
self.UpperFovLimit = 10.0
|
||||
self.LowerFovLimit = -30.0
|
||||
self.ShowDebugPoints = False
|
||||
self.set(**kwargs)
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# -- SensorData ----------------------------------------------------------------
|
||||
# ==============================================================================
|
||||
|
||||
|
||||
class SensorData(object):
|
||||
"""Base class for sensor data returned from the server."""
|
||||
pass
|
||||
|
@ -76,11 +142,12 @@ class SensorData(object):
|
|||
class Image(SensorData):
|
||||
"""Data generated by a Camera."""
|
||||
|
||||
def __init__(self, width, height, image_type, raw_data):
|
||||
def __init__(self, width, height, image_type, fov, raw_data):
|
||||
assert len(raw_data) == 4 * width * height
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.type = image_type
|
||||
self.fov = fov
|
||||
self.raw_data = raw_data
|
||||
self._converted_data = None
|
||||
|
||||
|
@ -103,20 +170,160 @@ class Image(SensorData):
|
|||
|
||||
def save_to_disk(self, filename):
|
||||
"""Save this image to disk (requires PIL installed)."""
|
||||
filename = _append_extension(filename, '.png')
|
||||
|
||||
try:
|
||||
from PIL import Image as PImage
|
||||
except ImportError:
|
||||
raise RuntimeError('cannot import PIL, make sure pillow package is installed')
|
||||
raise RuntimeError(
|
||||
'cannot import PIL, make sure pillow package is installed')
|
||||
|
||||
image = PImage.frombytes(
|
||||
mode='RGBA',
|
||||
size=(self.width, self.height),
|
||||
data=self.raw_data,
|
||||
decoder_name='raw')
|
||||
b, g, r, _ = image.split()
|
||||
image = PImage.merge("RGB", (r, g, b))
|
||||
color = image.split()
|
||||
image = PImage.merge("RGB", color[2::-1])
|
||||
|
||||
folder = os.path.dirname(filename)
|
||||
if not os.path.isdir(folder):
|
||||
os.makedirs(folder)
|
||||
image.save(filename)
|
||||
|
||||
|
||||
class PointCloud(SensorData):
|
||||
"""A list of points."""
|
||||
|
||||
def __init__(self, array, color_array=None):
|
||||
self._array = array
|
||||
self._color_array = color_array
|
||||
self._has_colors = color_array is not None
|
||||
|
||||
@property
|
||||
def array(self):
|
||||
"""The numpy array holding the point-cloud.
|
||||
|
||||
3D points format for n elements:
|
||||
[ [X0,Y0,Z0],
|
||||
...,
|
||||
[Xn,Yn,Zn] ]
|
||||
"""
|
||||
return self._array
|
||||
|
||||
@property
|
||||
def color_array(self):
|
||||
"""The numpy array holding the colors corresponding to each point.
|
||||
It is None if there are no colors.
|
||||
|
||||
Colors format for n elements:
|
||||
[ [R0,G0,B0],
|
||||
...,
|
||||
[Rn,Gn,Bn] ]
|
||||
"""
|
||||
return self._color_array
|
||||
|
||||
def has_colors(self):
|
||||
"""Return whether the points have color."""
|
||||
return self._has_colors
|
||||
|
||||
def apply_transform(self, transformation):
|
||||
"""Modify the PointCloud instance transforming its points"""
|
||||
self._array = transformation.transform_points(self._array)
|
||||
|
||||
def save_to_disk(self, filename):
|
||||
"""Save this point-cloud to disk as PLY format."""
|
||||
filename = _append_extension(filename, '.ply')
|
||||
|
||||
def construct_ply_header():
|
||||
"""Generates a PLY header given a total number of 3D points and
|
||||
coloring property if specified
|
||||
"""
|
||||
points = len(self) # Total point number
|
||||
header = ['ply',
|
||||
'format ascii 1.0',
|
||||
'element vertex {}',
|
||||
'property float32 x',
|
||||
'property float32 y',
|
||||
'property float32 z',
|
||||
'property uchar diffuse_red',
|
||||
'property uchar diffuse_green',
|
||||
'property uchar diffuse_blue',
|
||||
'end_header']
|
||||
if not self._has_colors:
|
||||
return '\n'.join(header[0:6] + [header[-1]]).format(points)
|
||||
return '\n'.join(header).format(points)
|
||||
|
||||
if not self._has_colors:
|
||||
ply = '\n'.join(['{:.2f} {:.2f} {:.2f}'.format(
|
||||
*p) for p in self._array.tolist()])
|
||||
else:
|
||||
points_3d = numpy.concatenate(
|
||||
(self._array, self._color_array), axis=1)
|
||||
ply = '\n'.join(['{:.2f} {:.2f} {:.2f} {:.0f} {:.0f} {:.0f}'
|
||||
.format(*p) for p in points_3d.tolist()])
|
||||
|
||||
# Create folder to save if does not exist.
|
||||
folder = os.path.dirname(filename)
|
||||
if not os.path.isdir(folder):
|
||||
os.makedirs(folder)
|
||||
|
||||
# Open the file and save with the specific PLY format.
|
||||
with open(filename, 'w+') as ply_file:
|
||||
ply_file.write('\n'.join([construct_ply_header(), ply]))
|
||||
|
||||
def __len__(self):
|
||||
return len(self.array)
|
||||
|
||||
def __getitem__(self, key):
|
||||
color = None if self._color_array is None else Color(
|
||||
*self._color_array[key])
|
||||
return Point(*self._array[key], color=color)
|
||||
|
||||
def __iter__(self):
|
||||
class PointIterator(object):
|
||||
"""Iterator class for PointCloud"""
|
||||
|
||||
def __init__(self, point_cloud):
|
||||
self.point_cloud = point_cloud
|
||||
self.index = -1
|
||||
|
||||
def __next__(self):
|
||||
self.index += 1
|
||||
if self.index >= len(self.point_cloud):
|
||||
raise StopIteration
|
||||
return self.point_cloud[self.index]
|
||||
|
||||
def next(self):
|
||||
return self.__next__()
|
||||
|
||||
return PointIterator(self)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.array)
|
||||
|
||||
|
||||
class LidarMeasurement(SensorData):
|
||||
"""Data generated by a Lidar."""
|
||||
|
||||
def __init__(self, horizontal_angle, channels, point_count_by_channel, point_cloud):
|
||||
assert numpy.sum(point_count_by_channel) == len(point_cloud.array)
|
||||
self.horizontal_angle = horizontal_angle
|
||||
self.channels = channels
|
||||
self.point_count_by_channel = point_count_by_channel
|
||||
self.point_cloud = point_cloud
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
"""The numpy array holding the point-cloud.
|
||||
|
||||
3D points format for n elements:
|
||||
[ [X0,Y0,Z0],
|
||||
...,
|
||||
[Xn,Yn,Zn] ]
|
||||
"""
|
||||
return self.point_cloud.array
|
||||
|
||||
def save_to_disk(self, filename):
|
||||
"""Save point-cloud to disk as PLY format."""
|
||||
self.point_cloud.save_to_disk(filename)
|
||||
|
|
|
@ -40,12 +40,11 @@ class CarlaSettings(object):
|
|||
self.PlayerVehicle = None
|
||||
self.NumberOfVehicles = 20
|
||||
self.NumberOfPedestrians = 30
|
||||
self.WeatherId = -1
|
||||
self.WeatherId = 1
|
||||
self.SeedVehicles = None
|
||||
self.SeedPedestrians = None
|
||||
self.randomize_weather()
|
||||
self.set(**kwargs)
|
||||
self._cameras = []
|
||||
self._sensors = []
|
||||
|
||||
def set(self, **kwargs):
|
||||
for key, value in kwargs.items():
|
||||
|
@ -67,18 +66,20 @@ class CarlaSettings(object):
|
|||
|
||||
def add_sensor(self, sensor):
|
||||
"""Add a sensor to the player vehicle (see sensor.py)."""
|
||||
if isinstance(sensor, carla_sensor.Camera):
|
||||
self._cameras.append(sensor)
|
||||
else:
|
||||
if not isinstance(sensor, carla_sensor.Sensor):
|
||||
raise ValueError('Sensor not supported')
|
||||
self._sensors.append(sensor)
|
||||
|
||||
def __str__(self):
|
||||
"""Converts this object to an INI formatted string."""
|
||||
ini = ConfigParser()
|
||||
ini.optionxform=str
|
||||
ini.optionxform = str
|
||||
S_SERVER = 'CARLA/Server'
|
||||
S_LEVEL = 'CARLA/LevelSettings'
|
||||
S_CAPTURE = 'CARLA/SceneCapture'
|
||||
S_SENSOR = 'CARLA/Sensor'
|
||||
|
||||
def get_attribs(obj):
|
||||
return [a for a in dir(obj) if not a.startswith('_') and not callable(getattr(obj, a))]
|
||||
|
||||
def add_section(section, obj, keys):
|
||||
for key in keys:
|
||||
|
@ -97,21 +98,12 @@ class CarlaSettings(object):
|
|||
'SeedVehicles',
|
||||
'SeedPedestrians'])
|
||||
|
||||
ini.add_section(S_CAPTURE)
|
||||
ini.set(S_CAPTURE, 'Cameras', ','.join(c.CameraName for c in self._cameras))
|
||||
ini.add_section(S_SENSOR)
|
||||
ini.set(S_SENSOR, 'Sensors', ','.join(s.SensorName for s in self._sensors))
|
||||
|
||||
for camera in self._cameras:
|
||||
add_section(S_CAPTURE + '/' + camera.CameraName, camera, [
|
||||
'PostProcessing',
|
||||
'ImageSizeX',
|
||||
'ImageSizeY',
|
||||
'CameraFOV',
|
||||
'CameraPositionX',
|
||||
'CameraPositionY',
|
||||
'CameraPositionZ',
|
||||
'CameraRotationPitch',
|
||||
'CameraRotationRoll',
|
||||
'CameraRotationYaw'])
|
||||
for sensor_def in self._sensors:
|
||||
section = S_SENSOR + '/' + sensor_def.SensorName
|
||||
add_section(section, sensor_def, get_attribs(sensor_def))
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
text = io.StringIO()
|
||||
|
@ -120,28 +112,3 @@ class CarlaSettings(object):
|
|||
|
||||
ini.write(text)
|
||||
return text.getvalue().replace(' = ', '=')
|
||||
|
||||
|
||||
def get_sensor_names(settings):
|
||||
"""
|
||||
Return a list with the names of the sensors defined in the settings object.
|
||||
The settings object can be a CarlaSettings or an INI formatted string.
|
||||
"""
|
||||
if isinstance(settings, CarlaSettings):
|
||||
# pylint: disable=protected-access
|
||||
return [camera.CameraName for camera in settings._cameras]
|
||||
ini = ConfigParser()
|
||||
if sys.version_info >= (3, 2):
|
||||
ini.read_string(settings)
|
||||
elif sys.version_info >= (3, 0):
|
||||
ini.readfp(io.StringIO(settings)) # pylint: disable=deprecated-method
|
||||
else:
|
||||
ini.readfp(io.BytesIO(settings)) # pylint: disable=deprecated-method
|
||||
|
||||
section_name = 'CARLA/SceneCapture'
|
||||
option_name = 'Cameras'
|
||||
|
||||
if ini.has_section(section_name) and ini.has_option(section_name, option_name):
|
||||
cameras = ini.get(section_name, option_name)
|
||||
return cameras.split(',')
|
||||
return []
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
import math
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
try:
|
||||
import numpy
|
||||
except ImportError:
|
||||
raise RuntimeError(
|
||||
'cannot import numpy, make sure numpy package is installed.')
|
||||
|
||||
try:
|
||||
from . import carla_server_pb2 as carla_protocol
|
||||
except ImportError:
|
||||
raise RuntimeError('cannot import "carla_server_pb2.py", run '
|
||||
'the protobuf compiler to generate this file')
|
||||
|
||||
|
||||
Translation = namedtuple('Translation', 'x y z')
|
||||
Translation.__new__.__defaults__ = (0.0, 0.0, 0.0)
|
||||
|
||||
Rotation = namedtuple('Rotation', 'pitch yaw roll')
|
||||
Rotation.__new__.__defaults__ = (0.0, 0.0, 0.0)
|
||||
|
||||
Scale = namedtuple('Scale', 'x y z')
|
||||
Scale.__new__.__defaults__ = (1.0, 1.0, 1.0)
|
||||
|
||||
|
||||
class Transform(object):
|
||||
"""A 3D transformation.
|
||||
|
||||
The transformation is applied in the order: scale, rotation, translation.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if 'matrix' in kwargs:
|
||||
self.matrix = kwargs['matrix']
|
||||
return
|
||||
if isinstance(args[0], carla_protocol.Transform):
|
||||
args = [
|
||||
Translation(
|
||||
args[0].location.x,
|
||||
args[0].location.y,
|
||||
args[0].location.z),
|
||||
Rotation(
|
||||
args[0].rotation.pitch,
|
||||
args[0].rotation.yaw,
|
||||
args[0].rotation.roll)
|
||||
]
|
||||
self.matrix = numpy.matrix(numpy.identity(4))
|
||||
self.set(*args, **kwargs)
|
||||
|
||||
def set(self, *args):
|
||||
"""Builds the transform matrix given a Translate, Rotation
|
||||
and Scale.
|
||||
"""
|
||||
translation = Translation()
|
||||
rotation = Rotation()
|
||||
scale = Scale()
|
||||
|
||||
if len(args) > 3:
|
||||
raise ValueError("'Transform' accepts 3 values as maximum.")
|
||||
|
||||
def get_single_obj_type(obj_type):
|
||||
"""Returns the unique object contained in the
|
||||
arguments lists that is instance of 'obj_type'.
|
||||
"""
|
||||
obj = [x for x in args if isinstance(x, obj_type)]
|
||||
if len(obj) > 1:
|
||||
raise ValueError("Transform only accepts one instances of " +
|
||||
str(obj_type) + " as a parameter")
|
||||
elif not obj:
|
||||
# Create an instance of the type that is 'obj_type'
|
||||
return obj_type()
|
||||
return obj[0]
|
||||
|
||||
translation = get_single_obj_type(Translation)
|
||||
rotation = get_single_obj_type(Rotation)
|
||||
scale = get_single_obj_type(Scale)
|
||||
|
||||
for param in args:
|
||||
if not isinstance(param, Translation) and \
|
||||
not isinstance(param, Rotation) and \
|
||||
not isinstance(param, Scale):
|
||||
raise TypeError(
|
||||
"'" + str(type(param)) + "' type not match with \
|
||||
'Translation', 'Rotation' or 'Scale'")
|
||||
|
||||
# Transformation matrix
|
||||
cy = math.cos(numpy.radians(rotation.yaw))
|
||||
sy = math.sin(numpy.radians(rotation.yaw))
|
||||
cr = math.cos(numpy.radians(rotation.roll))
|
||||
sr = math.sin(numpy.radians(rotation.roll))
|
||||
cp = math.cos(numpy.radians(rotation.pitch))
|
||||
sp = math.sin(numpy.radians(rotation.pitch))
|
||||
self.matrix[0, 3] = translation.x
|
||||
self.matrix[1, 3] = translation.y
|
||||
self.matrix[2, 3] = translation.z
|
||||
self.matrix[0, 0] = scale.x * (cp * cy)
|
||||
self.matrix[0, 1] = scale.y * (cy * sp * sr - sy * cr)
|
||||
self.matrix[0, 2] = -scale.z * (cy * sp * cr + sy * sr)
|
||||
self.matrix[1, 0] = scale.x * (sy * cp)
|
||||
self.matrix[1, 1] = scale.y * (sy * sp * sr + cy * cr)
|
||||
self.matrix[1, 2] = scale.z * (cy * sr - sy * sp * cr)
|
||||
self.matrix[2, 0] = scale.x * (sp)
|
||||
self.matrix[2, 1] = -scale.y * (cp * sr)
|
||||
self.matrix[2, 2] = scale.z * (cp * cr)
|
||||
|
||||
def inverse(self):
|
||||
"""Return the inverse transform."""
|
||||
return Transform(matrix=numpy.linalg.inv(self.matrix))
|
||||
|
||||
def transform_points(self, points):
|
||||
"""
|
||||
Given a 4x4 transformation matrix, transform an array of 3D points.
|
||||
Expected point foramt: [[X0,Y0,Z0],..[Xn,Yn,Zn]]
|
||||
"""
|
||||
# Needed foramt: [[X0,..Xn],[Z0,..Zn],[Z0,..Zn]]. So let's transpose
|
||||
# the point matrix.
|
||||
points = points.transpose()
|
||||
# Add 0s row: [[X0..,Xn],[Y0..,Yn],[Z0..,Zn],[0,..0]]
|
||||
points = numpy.append(points, numpy.ones((1, points.shape[1])), axis=0)
|
||||
# Point transformation
|
||||
points = self.matrix * points
|
||||
# Return all but last row
|
||||
return points[0:3].transpose()
|
||||
|
||||
def __mul__(self, other):
|
||||
return Transform(matrix=numpy.dot(self.matrix, other.matrix))
|
||||
|
||||
def __str__(self):
|
||||
return str(self.matrix)
|
|
@ -31,8 +31,11 @@ class StopWatch(object):
|
|||
def stop(self):
|
||||
self.end = datetime.datetime.now()
|
||||
|
||||
def seconds(self):
|
||||
return (self.end - self.start).total_seconds()
|
||||
|
||||
def milliseconds(self):
|
||||
return 1000.0 * (self.end - self.start).total_seconds()
|
||||
return 1000.0 * self.seconds()
|
||||
|
||||
|
||||
def to_hex_str(header):
|
||||
|
|
|
@ -16,13 +16,13 @@ import random
|
|||
import time
|
||||
|
||||
from carla.client import make_carla_client
|
||||
from carla.sensor import Camera
|
||||
from carla.sensor import Camera, Lidar
|
||||
from carla.settings import CarlaSettings
|
||||
from carla.tcp import TCPConnectionError
|
||||
from carla.util import print_over_same_line
|
||||
|
||||
|
||||
def run_carla_client(host, port, autopilot_on, save_images_to_disk, image_filename_format, settings_filepath):
|
||||
def run_carla_client(args):
|
||||
# Here we will run 3 episodes with 300 frames each.
|
||||
number_of_episodes = 3
|
||||
frames_per_episode = 300
|
||||
|
@ -32,13 +32,13 @@ def run_carla_client(host, port, autopilot_on, save_images_to_disk, image_filena
|
|||
# context manager, it creates a CARLA client object and starts the
|
||||
# connection. It will throw an exception if something goes wrong. The
|
||||
# context manager makes sure the connection is always cleaned up on exit.
|
||||
with make_carla_client(host, port) as client:
|
||||
with make_carla_client(args.host, args.port) as client:
|
||||
print('CarlaClient connected')
|
||||
|
||||
for episode in range(0, number_of_episodes):
|
||||
# Start a new episode.
|
||||
|
||||
if settings_filepath is None:
|
||||
if args.settings_filepath is None:
|
||||
|
||||
# Create a CarlaSettings object. This object is a wrapper around
|
||||
# the CarlaSettings.ini file. Here we set the configuration we
|
||||
|
@ -70,10 +70,23 @@ def run_carla_client(host, port, autopilot_on, save_images_to_disk, image_filena
|
|||
camera1.set_position(30, 0, 130)
|
||||
settings.add_sensor(camera1)
|
||||
|
||||
if args.lidar:
|
||||
lidar = Lidar('Lidar32')
|
||||
lidar.set_position(0, 0, 250)
|
||||
lidar.set_rotation(0, 0, 0)
|
||||
lidar.set(
|
||||
Channels=32,
|
||||
Range=5000,
|
||||
PointsPerSecond=100000,
|
||||
RotationFrequency=10,
|
||||
UpperFovLimit=10,
|
||||
LowerFovLimit=-30)
|
||||
settings.add_sensor(lidar)
|
||||
|
||||
else:
|
||||
|
||||
# Alternatively, we can load these settings from a file.
|
||||
with open(settings_filepath, 'r') as fp:
|
||||
with open(args.settings_filepath, 'r') as fp:
|
||||
settings = fp.read()
|
||||
|
||||
# Now we load these settings into the server. The server replies
|
||||
|
@ -102,9 +115,10 @@ def run_carla_client(host, port, autopilot_on, save_images_to_disk, image_filena
|
|||
print_measurements(measurements)
|
||||
|
||||
# Save the images to disk if requested.
|
||||
if save_images_to_disk:
|
||||
for name, image in sensor_data.items():
|
||||
image.save_to_disk(image_filename_format.format(episode, name, frame))
|
||||
if args.save_images_to_disk:
|
||||
for name, measurement in sensor_data.items():
|
||||
filename = args.out_filename_format.format(episode, name, frame)
|
||||
measurement.save_to_disk(filename)
|
||||
|
||||
# We can access the encoded data of a given image as numpy
|
||||
# array using its "data" property. For instance, to get the
|
||||
|
@ -118,7 +132,7 @@ def run_carla_client(host, port, autopilot_on, save_images_to_disk, image_filena
|
|||
# If we are in synchronous mode the server will pause the
|
||||
# simulation until we send this control.
|
||||
|
||||
if not autopilot_on:
|
||||
if not args.autopilot:
|
||||
|
||||
client.send_control(
|
||||
steer=random.uniform(-1.0, 1.0),
|
||||
|
@ -183,13 +197,19 @@ def main():
|
|||
'-a', '--autopilot',
|
||||
action='store_true',
|
||||
help='enable autopilot')
|
||||
argparser.add_argument(
|
||||
'-l', '--lidar',
|
||||
action='store_true',
|
||||
help='enable Lidar')
|
||||
argparser.add_argument(
|
||||
'-i', '--images-to-disk',
|
||||
action='store_true',
|
||||
help='save images to disk')
|
||||
dest='save_images_to_disk',
|
||||
help='save images (and Lidar data if active) to disk')
|
||||
argparser.add_argument(
|
||||
'-c', '--carla-settings',
|
||||
metavar='PATH',
|
||||
dest='settings_filepath',
|
||||
default=None,
|
||||
help='Path to a "CarlaSettings.ini" file')
|
||||
|
||||
|
@ -200,16 +220,12 @@ def main():
|
|||
|
||||
logging.info('listening to server %s:%s', args.host, args.port)
|
||||
|
||||
args.out_filename_format = '_out/episode_{:0>4d}/{:s}/{:0>6d}'
|
||||
|
||||
while True:
|
||||
try:
|
||||
|
||||
run_carla_client(
|
||||
host=args.host,
|
||||
port=args.port,
|
||||
autopilot_on=args.autopilot,
|
||||
save_images_to_disk=args.images_to_disk,
|
||||
image_filename_format='_images/episode_{:0>3d}/{:s}/image_{:0>5d}.png',
|
||||
settings_filepath=args.carla_settings)
|
||||
run_carla_client(args)
|
||||
|
||||
print('Done.')
|
||||
return
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
# Keyboard controlling for carla. Please refer to client_example for a simpler
|
||||
# Keyboard controlling for CARLA. Please refer to client_example.py for a simpler
|
||||
# and more documented example.
|
||||
|
||||
"""
|
||||
|
@ -68,7 +68,7 @@ MINI_WINDOW_WIDTH = 320
|
|||
MINI_WINDOW_HEIGHT = 180
|
||||
|
||||
|
||||
def make_carla_settings():
|
||||
def make_carla_settings(enable_lidar):
|
||||
"""Make a CarlaSettings object with the settings we need."""
|
||||
settings = CarlaSettings()
|
||||
settings.set(
|
||||
|
@ -93,6 +93,18 @@ def make_carla_settings():
|
|||
camera2.set_position(200, 0, 140)
|
||||
camera2.set_rotation(0.0, 0.0, 0.0)
|
||||
settings.add_sensor(camera2)
|
||||
if enable_lidar:
|
||||
lidar = sensor.Lidar('Lidar32')
|
||||
lidar.set_position(0, 0, 250)
|
||||
lidar.set_rotation(0, 0, 0)
|
||||
lidar.set(
|
||||
Channels=32,
|
||||
Range=5000,
|
||||
PointsPerSecond=100000,
|
||||
RotationFrequency=10,
|
||||
UpperFovLimit=10,
|
||||
LowerFovLimit=-30)
|
||||
settings.add_sensor(lidar)
|
||||
return settings
|
||||
|
||||
|
||||
|
@ -117,13 +129,15 @@ class Timer(object):
|
|||
|
||||
|
||||
class CarlaGame(object):
|
||||
def __init__(self, carla_client, city_name=None):
|
||||
def __init__(self, carla_client, enable_lidar=False, city_name=None):
|
||||
self.client = carla_client
|
||||
self._timer = None
|
||||
self._display = None
|
||||
self._main_image = None
|
||||
self._mini_view_image1 = None
|
||||
self._mini_view_image2 = None
|
||||
self._enable_lidar = enable_lidar
|
||||
self._lidar_measurement = None
|
||||
self._map_view = None
|
||||
self._is_on_reverse = False
|
||||
self._city_name = city_name
|
||||
|
@ -161,7 +175,7 @@ class CarlaGame(object):
|
|||
self._on_new_episode()
|
||||
|
||||
def _on_new_episode(self):
|
||||
scene = self.client.load_settings(make_carla_settings())
|
||||
scene = self.client.load_settings(make_carla_settings(self._enable_lidar))
|
||||
number_of_player_starts = len(scene.player_start_spots)
|
||||
player_start = np.random.randint(number_of_player_starts)
|
||||
print('Starting new episode...')
|
||||
|
@ -177,6 +191,8 @@ class CarlaGame(object):
|
|||
self._main_image = sensor_data['CameraRGB']
|
||||
self._mini_view_image1 = sensor_data['CameraDepth']
|
||||
self._mini_view_image2 = sensor_data['CameraSemSeg']
|
||||
if self._enable_lidar:
|
||||
self._lidar_measurement = sensor_data['Lidar32']
|
||||
|
||||
# Print measurements every second.
|
||||
if self._timer.elapsed_seconds_since_lap() > 1.0:
|
||||
|
@ -207,9 +223,9 @@ class CarlaGame(object):
|
|||
# Set the player position
|
||||
if self._city_name is not None:
|
||||
self._position = self._map.convert_to_pixel([
|
||||
measurements.player_measurements.transform.location.x,
|
||||
measurements.player_measurements.transform.location.y,
|
||||
measurements.player_measurements.transform.location.z])
|
||||
measurements.player_measurements.transform.location.x,
|
||||
measurements.player_measurements.transform.location.y,
|
||||
measurements.player_measurements.transform.location.z])
|
||||
self._agent_positions = measurements.non_player_agents
|
||||
|
||||
if control is None:
|
||||
|
@ -246,7 +262,8 @@ class CarlaGame(object):
|
|||
map_position,
|
||||
lane_orientation):
|
||||
message = 'Step {step} ({fps:.1f} FPS): '
|
||||
message += 'Map Position ({map_x:.1f},{map_y:.1f}) Lane Orientation ({ori_x:.1f},{ori_y:.1f}) '
|
||||
message += 'Map Position ({map_x:.1f},{map_y:.1f}) '
|
||||
message += 'Lane Orientation ({ori_x:.1f},{ori_y:.1f}) '
|
||||
message += '{speed:.2f} km/h, '
|
||||
message += '{other_lane:.0f}% other lane, {offroad:.0f}% off-road'
|
||||
message = message.format(
|
||||
|
@ -295,17 +312,33 @@ class CarlaGame(object):
|
|||
self._display.blit(
|
||||
surface, (2 * gap_x + MINI_WINDOW_WIDTH, mini_image_y))
|
||||
|
||||
if self._lidar_measurement is not None:
|
||||
lidar_data = np.array(self._lidar_measurement.data[:, :2])
|
||||
lidar_data /= 50.0
|
||||
lidar_data += 100.0
|
||||
lidar_data = np.fabs(lidar_data)
|
||||
lidar_data = lidar_data.astype(np.int32)
|
||||
lidar_data = np.reshape(lidar_data, (-1, 2))
|
||||
#draw lidar
|
||||
lidar_img_size = (200, 200, 3)
|
||||
lidar_img = np.zeros(lidar_img_size)
|
||||
lidar_img[tuple(lidar_data.T)] = (255, 255, 255)
|
||||
surface = pygame.surfarray.make_surface(lidar_img)
|
||||
self._display.blit(surface, (10, 10))
|
||||
|
||||
if self._map_view is not None:
|
||||
array = self._map_view
|
||||
array = array[:, :, :3]
|
||||
|
||||
new_window_width =(float(WINDOW_HEIGHT)/float(self._map_shape[0]))*float(self._map_shape[1])
|
||||
new_window_width = \
|
||||
(float(WINDOW_HEIGHT) / float(self._map_shape[0])) * \
|
||||
float(self._map_shape[1])
|
||||
surface = pygame.surfarray.make_surface(array.swapaxes(0, 1))
|
||||
|
||||
w_pos = int(self._position[0]*(float(WINDOW_HEIGHT)/float(self._map_shape[0])))
|
||||
h_pos = int(self._position[1] *(new_window_width/float(self._map_shape[1])))
|
||||
|
||||
pygame.draw.circle(surface, [255, 0, 0, 255], (w_pos,h_pos), 6, 0)
|
||||
pygame.draw.circle(surface, [255, 0, 0, 255], (w_pos, h_pos), 6, 0)
|
||||
for agent in self._agent_positions:
|
||||
if agent.HasField('vehicle'):
|
||||
agent_position = self._map.convert_to_pixel([
|
||||
|
@ -316,7 +349,7 @@ class CarlaGame(object):
|
|||
w_pos = int(agent_position[0]*(float(WINDOW_HEIGHT)/float(self._map_shape[0])))
|
||||
h_pos = int(agent_position[1] *(new_window_width/float(self._map_shape[1])))
|
||||
|
||||
pygame.draw.circle(surface, [255, 0, 255, 255], (w_pos ,h_pos), 4, 0)
|
||||
pygame.draw.circle(surface, [255, 0, 255, 255], (w_pos, h_pos), 4, 0)
|
||||
|
||||
self._display.blit(surface, (WINDOW_WIDTH, 0))
|
||||
|
||||
|
@ -342,11 +375,16 @@ def main():
|
|||
default=2000,
|
||||
type=int,
|
||||
help='TCP port to listen to (default: 2000)')
|
||||
argparser.add_argument(
|
||||
'-l', '--lidar',
|
||||
action='store_true',
|
||||
help='enable Lidar')
|
||||
argparser.add_argument(
|
||||
'-m', '--map-name',
|
||||
metavar='M',
|
||||
default=None,
|
||||
help='plot the map of the current city (needs to match active map in server, options: Town01 or Town02)')
|
||||
help='plot the map of the current city (needs to match active map in '
|
||||
'server, options: Town01 or Town02)')
|
||||
args = argparser.parse_args()
|
||||
|
||||
log_level = logging.DEBUG if args.debug else logging.INFO
|
||||
|
@ -360,7 +398,7 @@ def main():
|
|||
try:
|
||||
|
||||
with make_carla_client(args.host, args.port) as client:
|
||||
game = CarlaGame(client, args.map_name)
|
||||
game = CarlaGame(client, args.lidar, args.map_name)
|
||||
game.execute()
|
||||
break
|
||||
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
"""Basic CARLA client to generate point cloud in PLY format that you
|
||||
can visualize with MeshLab (meshlab.net) for instance. Please
|
||||
refer to client_example.py for a simpler and more documented example."""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import time
|
||||
|
||||
from carla.client import make_carla_client
|
||||
from carla.sensor import Camera
|
||||
from carla.settings import CarlaSettings
|
||||
from carla.tcp import TCPConnectionError
|
||||
from carla.util import print_over_same_line, StopWatch
|
||||
from carla.image_converter import depth_to_local_point_cloud, to_rgb_array
|
||||
from carla.transform import Transform
|
||||
|
||||
|
||||
def run_carla_client(host, port, far):
|
||||
# Here we will run a single episode with 300 frames.
|
||||
number_of_frames = 3000
|
||||
frame_step = 100 # Save one image every 100 frames
|
||||
output_folder = '_out'
|
||||
image_size = [800, 600]
|
||||
camera_local_pos = [30, 0, 130] # [X, Y, Z]
|
||||
camera_local_rotation = [0, 0, 0] # [pitch(Y), yaw(Z), roll(X)]
|
||||
fov = 70
|
||||
|
||||
# Connect with the server
|
||||
with make_carla_client(host, port) as client:
|
||||
print('CarlaClient connected')
|
||||
|
||||
# Here we load the settings.
|
||||
settings = CarlaSettings()
|
||||
settings.set(
|
||||
SynchronousMode=True,
|
||||
SendNonPlayerAgentsInfo=False,
|
||||
NumberOfVehicles=20,
|
||||
NumberOfPedestrians=40,
|
||||
WeatherId=random.choice([1, 3, 7, 8, 14]))
|
||||
settings.randomize_seeds()
|
||||
|
||||
camera1 = Camera('CameraDepth', PostProcessing='Depth', FOV=fov)
|
||||
camera1.set_image_size(*image_size)
|
||||
camera1.set_position(*camera_local_pos)
|
||||
camera1.set_rotation(*camera_local_rotation)
|
||||
settings.add_sensor(camera1)
|
||||
|
||||
camera2 = Camera('CameraRGB', PostProcessing='SceneFinal', FOV=fov)
|
||||
camera2.set_image_size(*image_size)
|
||||
camera2.set_position(*camera_local_pos)
|
||||
camera2.set_rotation(*camera_local_rotation)
|
||||
settings.add_sensor(camera2)
|
||||
|
||||
client.load_settings(settings)
|
||||
|
||||
# Start at location index id '0'
|
||||
client.start_episode(0)
|
||||
|
||||
# Compute the camera transform matrix
|
||||
camera_to_car_transform = camera2.get_unreal_transform()
|
||||
|
||||
# Iterate every frame in the episode except for the first one.
|
||||
for frame in range(1, number_of_frames):
|
||||
# Read the data produced by the server this frame.
|
||||
measurements, sensor_data = client.read_data()
|
||||
|
||||
# Save one image every 'frame_step' frames
|
||||
if not frame % frame_step:
|
||||
# Start transformations time mesure.
|
||||
timer = StopWatch()
|
||||
|
||||
# RGB image [[[r,g,b],..[r,g,b]],..[[r,g,b],..[r,g,b]]]
|
||||
image_RGB = to_rgb_array(sensor_data['CameraRGB'])
|
||||
|
||||
# 2d to (camera) local 3d
|
||||
# We use the image_RGB to colorize each 3D point, this is optional.
|
||||
# "max_depth" is used to keep only the points that are near to the
|
||||
# camera, meaning 1.0 the farest points (sky)
|
||||
point_cloud = depth_to_local_point_cloud(
|
||||
sensor_data['CameraDepth'],
|
||||
image_RGB,
|
||||
max_depth=far
|
||||
)
|
||||
|
||||
# (Camera) local 3d to world 3d.
|
||||
# Get the transform from the player protobuf transformation.
|
||||
world_transform = Transform(
|
||||
measurements.player_measurements.transform
|
||||
)
|
||||
|
||||
# Compute the final transformation matrix.
|
||||
car_to_world_transform = world_transform * camera_to_car_transform
|
||||
|
||||
# Car to World transformation given the 3D points and the
|
||||
# transformation matrix.
|
||||
point_cloud.apply_transform(car_to_world_transform)
|
||||
|
||||
# End transformations time mesure.
|
||||
timer.stop()
|
||||
|
||||
# Save PLY to disk
|
||||
# This generates the PLY string with the 3D points and the RGB colors
|
||||
# for each row of the file.
|
||||
point_cloud.save_to_disk(os.path.join(
|
||||
output_folder, '{:0>5}.ply'.format(frame))
|
||||
)
|
||||
|
||||
print_message(timer.milliseconds(), len(point_cloud), frame)
|
||||
|
||||
client.send_control(
|
||||
measurements.player_measurements.autopilot_control
|
||||
)
|
||||
|
||||
|
||||
def print_message(elapsed_time, point_n, frame):
|
||||
message = ' '.join([
|
||||
'Transformations took {:>3.0f} ms.',
|
||||
'Saved {:>6} points to "{:0>5}.ply".'
|
||||
]).format(elapsed_time, point_n, frame)
|
||||
print_over_same_line(message)
|
||||
|
||||
|
||||
def check_far(value):
|
||||
fvalue = float(value)
|
||||
if fvalue < 0.0 or fvalue > 1.0:
|
||||
raise argparse.ArgumentTypeError(
|
||||
"{} must be a float between 0.0 and 1.0")
|
||||
return fvalue
|
||||
|
||||
|
||||
def main():
|
||||
argparser = argparse.ArgumentParser(description=__doc__)
|
||||
argparser.add_argument(
|
||||
'-v', '--verbose',
|
||||
action='store_true',
|
||||
dest='debug',
|
||||
help='print debug information')
|
||||
argparser.add_argument(
|
||||
'--host',
|
||||
metavar='H',
|
||||
default='localhost',
|
||||
help='IP of the host server (default: localhost)')
|
||||
argparser.add_argument(
|
||||
'-p', '--port',
|
||||
metavar='P',
|
||||
default=2000,
|
||||
type=int,
|
||||
help='TCP port to listen to (default: 2000)')
|
||||
argparser.add_argument(
|
||||
'-f', '--far',
|
||||
default=0.2,
|
||||
type=check_far,
|
||||
help='The maximum save distance of camera-point '
|
||||
'[0.0 (near), 1.0 (far)] (default: 0.2)')
|
||||
|
||||
args = argparser.parse_args()
|
||||
|
||||
log_level = logging.DEBUG if args.debug else logging.INFO
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s', level=log_level)
|
||||
|
||||
logging.info('listening to server %s:%s', args.host, args.port)
|
||||
|
||||
while True:
|
||||
try:
|
||||
run_carla_client(host=args.host, port=args.port, far=args.far)
|
||||
print('\nDone!')
|
||||
return
|
||||
|
||||
except TCPConnectionError as error:
|
||||
logging.error(error)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print('\nClient stoped by user.')
|
|
@ -19,8 +19,8 @@ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
|||
|
||||
import carla
|
||||
|
||||
from carla import sensor
|
||||
from carla.client import CarlaClient
|
||||
from carla.sensor import Camera, Image
|
||||
from carla.settings import CarlaSettings
|
||||
from carla.tcp import TCPClient
|
||||
from carla.util import make_connection
|
||||
|
@ -31,17 +31,19 @@ import console
|
|||
def run_carla_client(args):
|
||||
with make_connection(CarlaClient, args.host, args.port, timeout=15) as client:
|
||||
logging.info('CarlaClient connected')
|
||||
filename = '_images/episode_{:0>3d}/image_{:0>5d}.png'
|
||||
filename = '_out/test_episode_{:0>4d}/{:s}/{:0>6d}'
|
||||
frames_per_episode = 300
|
||||
episode = 0
|
||||
while True:
|
||||
episode += 1
|
||||
settings = CarlaSettings()
|
||||
settings.set(SendNonPlayerAgentsInfo=True,SynchronousMode=args.synchronous)
|
||||
settings.set(SendNonPlayerAgentsInfo=True, SynchronousMode=args.synchronous)
|
||||
settings.randomize_seeds()
|
||||
camera = Camera('DefaultCamera')
|
||||
camera = sensor.Camera('DefaultCamera')
|
||||
camera.set_image_size(300, 200) # Do not change this, hard-coded in test.
|
||||
settings.add_sensor(camera)
|
||||
lidar = sensor.Lidar('DefaultLidar')
|
||||
settings.add_sensor(lidar)
|
||||
|
||||
logging.debug('sending CarlaSettings:\n%s', settings)
|
||||
logging.info('new episode requested')
|
||||
|
@ -64,14 +66,15 @@ def run_carla_client(args):
|
|||
for frame in range(0, frames_per_episode):
|
||||
logging.debug('reading measurements...')
|
||||
measurements, sensor_data = client.read_data()
|
||||
images = [x for x in sensor_data.values() if isinstance(x, Image)]
|
||||
images = [x for x in sensor_data.values() if isinstance(x, sensor.Image)]
|
||||
|
||||
logging.debug('received data of %d agents', len(measurements.non_player_agents))
|
||||
assert len(images) == 1
|
||||
assert (images[0].width, images[0].height) == (camera.ImageSizeX, camera.ImageSizeY)
|
||||
if len(images) > 0:
|
||||
assert (images[0].width, images[0].height) == (camera.ImageSizeX, camera.ImageSizeY)
|
||||
|
||||
if args.images_to_disk:
|
||||
images[0].save_to_disk(filename.format(episode, frame))
|
||||
for name, data in sensor_data.items():
|
||||
data.save_to_disk(filename.format(episode, name, frame))
|
||||
|
||||
logging.debug('sending control...')
|
||||
control = measurements.player_measurements.autopilot_control
|
||||
|
|
|
@ -13,6 +13,7 @@ import carla
|
|||
|
||||
from carla.client import CarlaClient
|
||||
from carla.sensor import Camera, Image
|
||||
from carla.sensor import Lidar, LidarMeasurement
|
||||
from carla.settings import CarlaSettings
|
||||
from carla.util import make_connection
|
||||
|
||||
|
@ -45,8 +46,8 @@ class _BasicTestBase(unit_tests.CarlaServerTest):
|
|||
number_of_agents = len(measurements.non_player_agents)
|
||||
logging.debug('received data of %d agents', number_of_agents)
|
||||
logging.debug('received %d images', len(images))
|
||||
if len(images) != len(carla_settings._cameras):
|
||||
raise RuntimeError('received %d images, expected %d' % (len(images), len(carla_settings._cameras)))
|
||||
if len(sensor_data) != len(carla_settings._sensors):
|
||||
raise RuntimeError('received %d, expected %d' % (len(sensor_data), len(carla_settings._sensors)))
|
||||
logging.debug('sending control...')
|
||||
control = measurements.player_measurements.autopilot_control
|
||||
if not use_autopilot_control:
|
||||
|
@ -80,7 +81,7 @@ class TwoCameras(_BasicTestBase):
|
|||
settings = CarlaSettings()
|
||||
settings.add_sensor(Camera('DefaultCamera'))
|
||||
camera2 = Camera('Camera2')
|
||||
camera2.set(PostProcessing='Depth', CameraFOV=120)
|
||||
camera2.set(PostProcessing='Depth', FOV=120)
|
||||
camera2.set_image_size(1924, 1028)
|
||||
settings.add_sensor(camera2)
|
||||
self.run_carla_client(settings, 3, 100)
|
||||
|
@ -110,3 +111,10 @@ class LongEpisode(_BasicTestBase):
|
|||
settings = CarlaSettings()
|
||||
settings.add_sensor(Camera('DefaultCamera'))
|
||||
self.run_carla_client(settings, 1, 2000, use_autopilot_control=True)
|
||||
|
||||
|
||||
class LidarTest(_BasicTestBase):
|
||||
def run(self):
|
||||
settings = CarlaSettings()
|
||||
settings.add_sensor(Lidar('DefaultLidar'))
|
||||
self.run_carla_client(settings, 3, 100)
|
||||
|
|
11
README.md
11
README.md
|
@ -2,6 +2,8 @@ CARLA Simulator
|
|||
===============
|
||||
|
||||
[](https://travis-ci.org/carla-simulator/carla)
|
||||
[](http://carla.readthedocs.io)
|
||||
[](https://waffle.io/carla-simulator/carla)
|
||||
|
||||
CARLA is an open-source simulator for autonomous driving research. CARLA has
|
||||
been developed from the ground up to support development, training, and
|
||||
|
@ -25,8 +27,8 @@ paper, check out
|
|||
News
|
||||
----
|
||||
|
||||
- 05.02.2018 CARLA 0.7.1 available for Windows too, [release](https://github.com/carla-simulator/carla/releases/tag/0.7.1).
|
||||
- 25.01.2018 CARLA 0.7.1 released: [change log](https://github.com/carla-simulator/carla/blob/master/CHANGELOG.md#carla-071), [release](https://github.com/carla-simulator/carla/releases/tag/0.7.1).
|
||||
- 22.01.2018 Job opening: [C++ (UE4) Programmer](https://drive.google.com/open?id=1Hx0eUgpXl95d4IL9meEGhJECgSRos1T1).
|
||||
- 28.11.2017 CARLA 0.7.0 released: [change log](https://github.com/carla-simulator/carla/blob/master/CHANGELOG.md#carla-070), [release](https://github.com/carla-simulator/carla/releases/tag/0.7.0).
|
||||
- 15.11.2017 CARLA 0.6.0 released: [change log](https://github.com/carla-simulator/carla/blob/master/CHANGELOG.md#carla-060), [release](https://github.com/carla-simulator/carla/releases/tag/0.6.0).
|
||||
|
||||
|
@ -92,13 +94,6 @@ F.A.Q.
|
|||
If you run into problems, check our
|
||||
[FAQ](http://carla.readthedocs.io/en/latest/faq/).
|
||||
|
||||
Jobs
|
||||
----
|
||||
|
||||
We are currently looking for a new programmer to join our team
|
||||
|
||||
* [C++ (UE4) Programmer](https://drive.google.com/open?id=1Hx0eUgpXl95d4IL9meEGhJECgSRos1T1)
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ function log {
|
|||
|
||||
if [ ! -d "${UE4_ROOT}" ]; then
|
||||
fatal_error "UE4_ROOT is not defined, or points to a non-existant directory, please set this environment variable."
|
||||
else
|
||||
echo "Using Unreal Engine at '$UE4_ROOT'"
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
|
@ -94,7 +96,7 @@ pushd "$UNREAL_PROJECT_FOLDER" >/dev/null
|
|||
# This command usually fails but normally we can continue anyway.
|
||||
set +e
|
||||
log "Generate Unreal project files..."
|
||||
${UE4_ROOT}/GenerateProjectFiles.sh -project="${PWD}/CarlaUE4.uproject" -game -engine
|
||||
${UE4_ROOT}/GenerateProjectFiles.sh -project="${PWD}/CarlaUE4.uproject" -game -engine -makefiles
|
||||
set -e
|
||||
|
||||
log "Build CarlaUE4 project..."
|
||||
|
|
|
@ -17,3 +17,4 @@ Config/CarlaSettings.ini
|
|||
|
||||
CMakeLists.txt
|
||||
Makefile
|
||||
.vscode
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"FileVersion": 3,
|
||||
"EngineAssociation": "4.17",
|
||||
"EngineAssociation": "4.18",
|
||||
"Category": "",
|
||||
"Description": "",
|
||||
"Modules": [
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,22 +0,0 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "Carla.h"
|
||||
#include "TrafficSignBase.h"
|
||||
|
||||
#include "Game/CarlaGameState.h"
|
||||
|
||||
ATrafficSignBase::ATrafficSignBase() : Super() {}
|
||||
|
||||
void ATrafficSignBase::BeginPlay()
|
||||
{
|
||||
auto *GameState = GetWorld()->GetGameState<ACarlaGameState>();
|
||||
if (GameState != nullptr) {
|
||||
GameState->RegisterTrafficSign(this);
|
||||
} else {
|
||||
UE_LOG(LogCarla, Error, TEXT("Missing CARLA game state!"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Carla.h"
|
||||
#include "AgentComponent.h"
|
||||
|
||||
#include "Game/CarlaGameModeBase.h"
|
||||
#include "Game/DataRouter.h"
|
||||
|
||||
static FDataRouter &GetDataRouter(UWorld *World)
|
||||
{
|
||||
check(World != nullptr);
|
||||
auto *GameMode = Cast<ACarlaGameModeBase>(World->GetAuthGameMode());
|
||||
check(GameMode != nullptr);
|
||||
return GameMode->GetDataRouter();
|
||||
}
|
||||
|
||||
UAgentComponent::UAgentComponent(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
bVisible = false;
|
||||
bHiddenInGame = true;
|
||||
bShouldUpdatePhysicsVolume = false;
|
||||
PrimaryComponentTick.bCanEverTick = false;
|
||||
}
|
||||
|
||||
void UAgentComponent::AcceptVisitor(IAgentComponentVisitor &Visitor) const
|
||||
{
|
||||
unimplemented();
|
||||
}
|
||||
|
||||
void UAgentComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
GetDataRouter(GetWorld()).RegisterAgent(this);
|
||||
}
|
||||
|
||||
void UAgentComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
GetDataRouter(GetWorld()).DeregisterAgent(this);
|
||||
Super::EndPlay(EndPlayReason);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Agent/AgentComponentVisitor.h"
|
||||
|
||||
#include "Components/SceneComponent.h"
|
||||
#include "Templates/SharedPointer.h"
|
||||
|
||||
#include "AgentComponent.generated.h"
|
||||
|
||||
/// Actors with an UAgentComponent are registered as agents in the scene and
|
||||
/// their status is sent to the client each frame (if requested by the client).
|
||||
UCLASS(Abstract)
|
||||
class CARLA_API UAgentComponent : public USceneComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UAgentComponent(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
uint32 GetId() const
|
||||
{
|
||||
return GetTypeHash(this);
|
||||
}
|
||||
|
||||
virtual void AcceptVisitor(IAgentComponentVisitor &Visitor) const;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void EndPlay(EEndPlayReason::Type EndPlayReason) override;
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
class UAgentComponent;
|
||||
class UTrafficSignAgentComponent;
|
||||
class UVehicleAgentComponent;
|
||||
class UWalkerAgentComponent;
|
||||
|
||||
class IAgentComponentVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void Visit(const UTrafficSignAgentComponent &) = 0;
|
||||
|
||||
virtual void Visit(const UVehicleAgentComponent &) = 0;
|
||||
|
||||
virtual void Visit(const UWalkerAgentComponent &) = 0;
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Carla.h"
|
||||
#include "TrafficSignAgentComponent.h"
|
||||
|
||||
#include "Traffic/TrafficSignBase.h"
|
||||
|
||||
UTrafficSignAgentComponent::UTrafficSignAgentComponent(const FObjectInitializer &ObjectInitializer)
|
||||
: Super(ObjectInitializer) {}
|
||||
|
||||
void UTrafficSignAgentComponent::BeginPlay()
|
||||
{
|
||||
TrafficSign = Cast<ATrafficSignBase>(GetOwner());
|
||||
checkf(TrafficSign != nullptr, TEXT("UTrafficSignAgentComponent can only be attached to ATrafficSignBase"));
|
||||
|
||||
Super::BeginPlay();
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Agent/AgentComponent.h"
|
||||
|
||||
#include "TrafficSignAgentComponent.generated.h"
|
||||
|
||||
class ATrafficSignBase;
|
||||
|
||||
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
|
||||
class CARLA_API UTrafficSignAgentComponent : public UAgentComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UTrafficSignAgentComponent(const FObjectInitializer &ObjectInitializer);
|
||||
|
||||
const ATrafficSignBase &GetTrafficSign() const
|
||||
{
|
||||
check(TrafficSign != nullptr);
|
||||
return *TrafficSign;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void AcceptVisitor(IAgentComponentVisitor &Visitor) const final
|
||||
{
|
||||
Visitor.Visit(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY()
|
||||
ATrafficSignBase *TrafficSign = nullptr;
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Carla.h"
|
||||
#include "VehicleAgentComponent.h"
|
||||
|
||||
#include "Vehicle/CarlaWheeledVehicle.h"
|
||||
|
||||
UVehicleAgentComponent::UVehicleAgentComponent(const FObjectInitializer &ObjectInitializer)
|
||||
: Super(ObjectInitializer) {}
|
||||
|
||||
void UVehicleAgentComponent::BeginPlay()
|
||||
{
|
||||
WheeledVehicle = Cast<ACarlaWheeledVehicle>(GetOwner());
|
||||
checkf(WheeledVehicle != nullptr, TEXT("UVehicleAgentComponent can only be attached to ACarlaWheeledVehicle"));
|
||||
|
||||
Super::BeginPlay();
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Agent/AgentComponent.h"
|
||||
|
||||
#include "VehicleAgentComponent.generated.h"
|
||||
|
||||
class ACarlaWheeledVehicle;
|
||||
|
||||
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
|
||||
class CARLA_API UVehicleAgentComponent : public UAgentComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UVehicleAgentComponent(const FObjectInitializer &ObjectInitializer);
|
||||
|
||||
ACarlaWheeledVehicle &GetVehicle() const
|
||||
{
|
||||
check(WheeledVehicle != nullptr);
|
||||
return *WheeledVehicle;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void AcceptVisitor(IAgentComponentVisitor &Visitor) const final
|
||||
{
|
||||
Visitor.Visit(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
ACarlaWheeledVehicle *WheeledVehicle = nullptr;
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Carla.h"
|
||||
#include "WalkerAgentComponent.h"
|
||||
|
||||
#include "GameFramework/Character.h"
|
||||
|
||||
UWalkerAgentComponent::UWalkerAgentComponent(const FObjectInitializer &ObjectInitializer)
|
||||
: Super(ObjectInitializer) {}
|
||||
|
||||
float UWalkerAgentComponent::GetForwardSpeed() const
|
||||
{
|
||||
/// @todo Is it necessary to compute this speed every tick?
|
||||
return FVector::DotProduct(Walker->GetVelocity(), Walker->GetActorRotation().Vector()) * 0.036f;
|
||||
}
|
||||
|
||||
void UWalkerAgentComponent::BeginPlay()
|
||||
{
|
||||
Walker = Cast<ACharacter>(GetOwner());
|
||||
checkf(Walker != nullptr, TEXT("UWalkerAgentComponent can only be attached to ACharacter"));
|
||||
|
||||
Super::BeginPlay();
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Agent/AgentComponent.h"
|
||||
|
||||
#include "WalkerAgentComponent.generated.h"
|
||||
|
||||
class ACharacter;
|
||||
|
||||
/// This component can be added to any ACharacter to be added as agent.
|
||||
/// See UAgentComponent.
|
||||
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
|
||||
class CARLA_API UWalkerAgentComponent : public UAgentComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UWalkerAgentComponent(const FObjectInitializer &ObjectInitializer);
|
||||
|
||||
/// Return forward speed in km/h.
|
||||
float GetForwardSpeed() const;
|
||||
|
||||
FVector GetBoundingBoxExtent() const
|
||||
{
|
||||
/// @todo Perhaps the box it is not the same for every walker...
|
||||
return {45.0f, 35.0f, 100.0f};
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void AcceptVisitor(IAgentComponentVisitor &Visitor) const final
|
||||
{
|
||||
Visitor.Visit(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY()
|
||||
ACharacter *Walker = nullptr;
|
||||
};
|
|
@ -9,18 +9,39 @@
|
|||
|
||||
#include "MapGen/GraphGenerator.h"
|
||||
#include "MapGen/RoadMap.h"
|
||||
#include "Tagger.h"
|
||||
#include "Game/Tagger.h"
|
||||
|
||||
#include "Components/InstancedStaticMeshComponent.h"
|
||||
#include "Engine/World.h"
|
||||
#include "Paths.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
#ifdef CARLA_ROAD_GENERATOR_EXTRA_LOG
|
||||
#include <sstream>
|
||||
#endif // CARLA_ROAD_GENERATOR_EXTRA_LOG
|
||||
|
||||
// =============================================================================
|
||||
// -- Private types ------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
class FHalfEdgeCounter {
|
||||
public:
|
||||
|
||||
using HalfEdge = MapGen::DoublyConnectedEdgeList::HalfEdge;
|
||||
|
||||
bool Insert(const HalfEdge &InHalfEdge)
|
||||
{
|
||||
return Set.insert(&InHalfEdge).second &&
|
||||
Set.insert(&MapGen::DoublyConnectedEdgeList::GetPair(InHalfEdge)).second;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::unordered_set<const HalfEdge *> Set;
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// -- Constructor and destructor -----------------------------------------------
|
||||
// =============================================================================
|
||||
|
@ -135,35 +156,39 @@ void ACityMapGenerator::GenerateRoads()
|
|||
|
||||
const uint32 margin = CityMapMeshTag::GetRoadIntersectionSize() / 2u;
|
||||
|
||||
FHalfEdgeCounter HalfEdgeCounter;
|
||||
|
||||
// For each edge add road segment.
|
||||
for (auto &edge : graph.GetHalfEdges()) {
|
||||
auto source = Graph::GetSource(edge).GetPosition();
|
||||
auto target = Graph::GetTarget(edge).GetPosition();
|
||||
if (HalfEdgeCounter.Insert(edge)) {
|
||||
auto source = Graph::GetSource(edge).GetPosition();
|
||||
auto target = Graph::GetTarget(edge).GetPosition();
|
||||
|
||||
if (source.x == target.x) {
|
||||
// vertical
|
||||
auto y = 1u + margin + std::min(source.y, target.y);
|
||||
auto end = std::max(source.y, target.y) - margin;
|
||||
for (; y < end; ++y) {
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_LaneLeft, source.x, y, HALF_PI);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_LaneRight, source.x, y, HALF_PI);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_SidewalkLeft, source.x, y, HALF_PI);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_SidewalkRight, source.x, y, HALF_PI);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_LaneMarkingBroken, source.x, y, HALF_PI);
|
||||
if (source.x == target.x) {
|
||||
// vertical
|
||||
auto y = 1u + margin + std::min(source.y, target.y);
|
||||
auto end = std::max(source.y, target.y) - margin;
|
||||
for (; y < end; ++y) {
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_LaneLeft, source.x, y, HALF_PI);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_LaneRight, source.x, y, HALF_PI);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_SidewalkLeft, source.x, y, HALF_PI);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_SidewalkRight, source.x, y, HALF_PI);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_LaneMarkingBroken, source.x, y, HALF_PI);
|
||||
}
|
||||
} else if (source.y == target.y) {
|
||||
// horizontal
|
||||
auto x = 1u + margin + std::min(source.x, target.x);
|
||||
auto end = std::max(source.x, target.x) - margin;
|
||||
for (; x < end; ++x) {
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_LaneLeft, x, source.y);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_LaneRight, x, source.y);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_SidewalkLeft, x, source.y);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_SidewalkRight, x, source.y);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_LaneMarkingBroken, x, source.y);
|
||||
}
|
||||
} else {
|
||||
UE_LOG(LogCarla, Warning, TEXT("Diagonal edge ignored"));
|
||||
}
|
||||
} else if (source.y == target.y) {
|
||||
// horizontal
|
||||
auto x = 1u + margin + std::min(source.x, target.x);
|
||||
auto end = std::max(source.x, target.x) - margin;
|
||||
for (; x < end; ++x) {
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_LaneLeft, x, source.y);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_LaneRight, x, source.y);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_SidewalkLeft, x, source.y);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_SidewalkRight, x, source.y);
|
||||
AddInstance(ECityMapMeshTag::RoadTwoLanes_LaneMarkingBroken, x, source.y);
|
||||
}
|
||||
} else {
|
||||
UE_LOG(LogCarla, Warning, TEXT("Diagonal edge ignored"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,7 +316,7 @@ void ACityMapGenerator::GenerateRoadMap()
|
|||
#endif // WITH_EDITOR
|
||||
|
||||
if (bSaveRoadMapToDisk) {
|
||||
RoadMap->SaveAsPNG(FPaths::GameSavedDir(), World->GetMapName());
|
||||
RoadMap->SaveAsPNG(FPaths::ProjectSavedDir(), World->GetMapName());
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "MapGen/CityMapMeshHolder.h"
|
||||
|
||||
#include "MapGen/DoublyConnectedEdgeList.h"
|
||||
#include "MapGen/GraphParser.h"
|
||||
|
||||
#include "CityMapGenerator.generated.h"
|
||||
|
||||
class URoadMap;
|
||||
|
|
|
@ -21,7 +21,7 @@ static FString GetIniFileName(const FString &MapName = TEXT(""))
|
|||
|
||||
static bool GetWeatherIniFilePath(const FString &FileName, FString &FilePath)
|
||||
{
|
||||
FilePath = FPaths::Combine(FPaths::GameConfigDir(), FileName);
|
||||
FilePath = FPaths::Combine(FPaths::ProjectConfigDir(), FileName);
|
||||
const bool bFileExists = FPaths::FileExists(FilePath);
|
||||
if (!bFileExists) {
|
||||
UE_LOG(LogCarla, Warning, TEXT("\"%s\" not found"), *FilePath);
|
||||
|
@ -46,7 +46,7 @@ void ADynamicWeather::LoadWeatherDescriptionsFromFile(
|
|||
FString DefaultFilePath;
|
||||
if (GetWeatherIniFilePath(GetIniFileName(), DefaultFilePath)) {
|
||||
UE_LOG(LogCarla, Log, TEXT("Loading weather description from %s"), *DefaultFilePath);
|
||||
IniFile ConfigFile(DefaultFilePath);
|
||||
FIniFile ConfigFile(DefaultFilePath);
|
||||
|
||||
{ // Override map specific presets.
|
||||
FString MapOverridesFilePath;
|
||||
|
@ -190,7 +190,7 @@ bool ADynamicWeather::LoadFromConfigFile()
|
|||
{
|
||||
FString FilePath;
|
||||
if (GetWeatherIniFilePath(FileName, FilePath) && CheckWeatherValidity(Weather)) {
|
||||
IniFile ConfigFile(FilePath);
|
||||
FIniFile ConfigFile(FilePath);
|
||||
if (!ConfigFile.HasSection(Weather.Name)) {
|
||||
UE_LOG(LogCarla, Error, TEXT("Weather \"%s\" is not present in config file"), *Weather.Name);
|
||||
return false;
|
||||
|
@ -206,7 +206,7 @@ bool ADynamicWeather::SaveToConfigFile() const
|
|||
{
|
||||
FString FilePath;
|
||||
if (GetWeatherIniFilePath(FileName, FilePath) && CheckWeatherValidity(Weather)) {
|
||||
IniFile ConfigFile(FilePath);
|
||||
FIniFile ConfigFile(FilePath);
|
||||
Weather.WriteToConfigFile(ConfigFile);
|
||||
return ConfigFile.Write(FilePath);
|
||||
} else {
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "GameFramework/Actor.h"
|
||||
|
||||
#include "Settings/WeatherDescription.h"
|
||||
|
||||
#include "DynamicWeather.generated.h"
|
||||
|
||||
class UArrowComponent;
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Settings/PostProcessEffect.h"
|
||||
#include "CapturedImage.generated.h"
|
||||
|
||||
/// Bitmap and meta info of a scene capture.
|
||||
///
|
||||
/// The bitmap may be empty if the capture failed.
|
||||
USTRUCT()
|
||||
struct FCapturedImage
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
uint32 SizeX = 0u;
|
||||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
uint32 SizeY = 0u;
|
||||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
EPostProcessEffect PostProcessEffect = EPostProcessEffect::INVALID;
|
||||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
TArray<FColor> BitMap;
|
||||
};
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CarlaGameControllerBase.h"
|
||||
|
||||
class ACarlaGameState;
|
||||
class ACarlaVehicleController;
|
||||
class CarlaServer;
|
||||
|
||||
/// Implements remote control of game and player.
|
||||
class CARLA_API CarlaGameController : public CarlaGameControllerBase
|
||||
{
|
||||
public:
|
||||
|
||||
explicit CarlaGameController();
|
||||
|
||||
~CarlaGameController();
|
||||
|
||||
virtual void Initialize(UCarlaSettings &CarlaSettings) override;
|
||||
|
||||
virtual APlayerStart *ChoosePlayerStart(const TArray<APlayerStart *> &AvailableStartSpots) override;
|
||||
|
||||
virtual void RegisterPlayer(AController &NewPlayer) override;
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void Tick(float DeltaSeconds) override;
|
||||
|
||||
private:
|
||||
|
||||
void RestartLevel();
|
||||
|
||||
TUniquePtr<CarlaServer> Server;
|
||||
|
||||
ACarlaVehicleController *Player = nullptr;
|
||||
|
||||
const ACarlaGameState *GameState = nullptr;
|
||||
|
||||
UCarlaSettings *CarlaSettings = nullptr;
|
||||
};
|
|
@ -6,18 +6,21 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Array.h"
|
||||
#include "Containers/Array.h"
|
||||
|
||||
class AController;
|
||||
class APlayerStart;
|
||||
class FDataRouter;
|
||||
class UCarlaSettings;
|
||||
|
||||
/// Base class for a CARLA game controller.
|
||||
class CARLA_API CarlaGameControllerBase
|
||||
class ICarlaGameControllerBase
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~CarlaGameControllerBase() {}
|
||||
ICarlaGameControllerBase(FDataRouter &DataRouter) : DataRouter(DataRouter) {}
|
||||
|
||||
virtual ~ICarlaGameControllerBase() {}
|
||||
|
||||
virtual void Initialize(UCarlaSettings &CarlaSettings) = 0;
|
||||
|
||||
|
@ -28,4 +31,8 @@ public:
|
|||
virtual void BeginPlay() = 0;
|
||||
|
||||
virtual void Tick(float DeltaSeconds) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
FDataRouter &DataRouter;
|
||||
};
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
#include "Carla.h"
|
||||
#include "CarlaGameInstance.h"
|
||||
|
||||
#include "CarlaGameController.h"
|
||||
#include "MockGameController.h"
|
||||
#include "Game/MockGameController.h"
|
||||
#include "Server/ServerGameController.h"
|
||||
#include "Settings/CarlaSettings.h"
|
||||
|
||||
UCarlaGameInstance::UCarlaGameInstance() {
|
||||
|
@ -25,9 +25,9 @@ void UCarlaGameInstance::InitializeGameControllerIfNotPresent(
|
|||
{
|
||||
if (GameController == nullptr) {
|
||||
if (CarlaSettings->bUseNetworking) {
|
||||
GameController = MakeUnique<CarlaGameController>();
|
||||
GameController = MakeUnique<FServerGameController>(DataRouter);
|
||||
} else {
|
||||
GameController = MakeUnique<MockGameController>(MockControllerSettings);
|
||||
GameController = MakeUnique<MockGameController>(DataRouter, MockControllerSettings);
|
||||
UE_LOG(LogCarla, Log, TEXT("Using mock CARLA controller"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "Engine/GameInstance.h"
|
||||
#include "CarlaGameControllerBase.h"
|
||||
|
||||
#include "Game/CarlaGameControllerBase.h"
|
||||
#include "Game/DataRouter.h"
|
||||
|
||||
#include "CarlaGameInstance.generated.h"
|
||||
|
||||
class UCarlaSettings;
|
||||
|
@ -29,7 +32,7 @@ public:
|
|||
void InitializeGameControllerIfNotPresent(
|
||||
const FMockGameControllerSettings &MockControllerSettings);
|
||||
|
||||
CarlaGameControllerBase &GetGameController()
|
||||
ICarlaGameControllerBase &GetGameController()
|
||||
{
|
||||
check(GameController != nullptr);
|
||||
return *GameController;
|
||||
|
@ -54,10 +57,17 @@ public:
|
|||
return CarlaSettings;
|
||||
}
|
||||
|
||||
FDataRouter &GetDataRouter()
|
||||
{
|
||||
return DataRouter;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY(Category = "CARLA Settings", EditAnywhere)
|
||||
UCarlaSettings *CarlaSettings;
|
||||
|
||||
TUniquePtr<CarlaGameControllerBase> GameController;
|
||||
FDataRouter DataRouter;
|
||||
|
||||
TUniquePtr<ICarlaGameControllerBase> GameController;
|
||||
};
|
||||
|
|
|
@ -7,21 +7,23 @@
|
|||
#include "Carla.h"
|
||||
#include "CarlaGameModeBase.h"
|
||||
|
||||
#include "Game/CarlaGameInstance.h"
|
||||
#include "Game/CarlaHUD.h"
|
||||
#include "Game/CarlaPlayerState.h"
|
||||
#include "Game/Tagger.h"
|
||||
#include "Game/TaggerDelegate.h"
|
||||
#include "Sensor/Sensor.h"
|
||||
#include "Sensor/SensorFactory.h"
|
||||
#include "Settings/CarlaSettings.h"
|
||||
#include "Util/RandomEngine.h"
|
||||
#include "Vehicle/CarlaVehicleController.h"
|
||||
|
||||
#include "ConstructorHelpers.h"
|
||||
#include "Engine/PlayerStartPIE.h"
|
||||
#include "EngineUtils.h"
|
||||
#include "GameFramework/PlayerStart.h"
|
||||
#include "SceneViewport.h"
|
||||
|
||||
#include "CarlaGameInstance.h"
|
||||
#include "CarlaGameState.h"
|
||||
#include "CarlaHUD.h"
|
||||
#include "CarlaPlayerState.h"
|
||||
#include "CarlaVehicleController.h"
|
||||
#include "Settings/CarlaSettings.h"
|
||||
#include "Tagger.h"
|
||||
#include "TaggerDelegate.h"
|
||||
|
||||
ACarlaGameModeBase::ACarlaGameModeBase(const FObjectInitializer& ObjectInitializer) :
|
||||
Super(ObjectInitializer),
|
||||
GameController(nullptr),
|
||||
|
@ -32,7 +34,6 @@ ACarlaGameModeBase::ACarlaGameModeBase(const FObjectInitializer& ObjectInitializ
|
|||
bAllowTickBeforeBeginPlay = false;
|
||||
|
||||
PlayerControllerClass = ACarlaVehicleController::StaticClass();
|
||||
GameStateClass = ACarlaGameState::StaticClass();
|
||||
PlayerStateClass = ACarlaPlayerState::StaticClass();
|
||||
HUDClass = ACarlaHUD::StaticClass();
|
||||
|
||||
|
@ -129,17 +130,6 @@ void ACarlaGameModeBase::BeginPlay()
|
|||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
auto CarlaGameState = Cast<ACarlaGameState>(GameState);
|
||||
checkf(
|
||||
CarlaGameState != nullptr,
|
||||
TEXT("GameState is not a ACarlaGameState, did you forget to set it in the project settings?"));
|
||||
if (WalkerSpawner != nullptr) {
|
||||
CarlaGameState->WalkerSpawner = WalkerSpawner;
|
||||
}
|
||||
if (VehicleSpawner != nullptr) {
|
||||
CarlaGameState->VehicleSpawner = VehicleSpawner;
|
||||
}
|
||||
|
||||
const auto &CarlaSettings = GameInstance->GetCarlaSettings();
|
||||
|
||||
// Setup semantic segmentation if necessary.
|
||||
|
@ -204,26 +194,34 @@ void ACarlaGameModeBase::RegisterPlayer(AController &NewPlayer)
|
|||
{
|
||||
check(GameController != nullptr);
|
||||
AddTickPrerequisiteActor(&NewPlayer);
|
||||
GameController->RegisterPlayer(NewPlayer);
|
||||
PlayerController = Cast<ACarlaVehicleController>(&NewPlayer);
|
||||
AttachCaptureCamerasToPlayer();
|
||||
if (PlayerController != nullptr) {
|
||||
GetDataRouter().RegisterPlayer(*PlayerController);
|
||||
GameController->RegisterPlayer(*PlayerController);
|
||||
AttachSensorsToPlayer();
|
||||
} else {
|
||||
UE_LOG(LogCarla, Error, TEXT("ACarlaGameModeBase: Player is not a ACarlaVehicleController"));
|
||||
}
|
||||
}
|
||||
|
||||
void ACarlaGameModeBase::AttachCaptureCamerasToPlayer()
|
||||
void ACarlaGameModeBase::AttachSensorsToPlayer()
|
||||
{
|
||||
if (PlayerController == nullptr) {
|
||||
UE_LOG(LogCarla, Warning, TEXT("Trying to add capture cameras but player is not a ACarlaVehicleController"));
|
||||
return;
|
||||
}
|
||||
check(PlayerController != nullptr);
|
||||
const auto &Settings = GameInstance->GetCarlaSettings();
|
||||
const auto *Weather = Settings.GetActiveWeatherDescription();
|
||||
const FCameraPostProcessParameters *OverridePostProcessParameters = nullptr;
|
||||
if ((Weather != nullptr) && (Weather->bOverrideCameraPostProcessParameters)) {
|
||||
OverridePostProcessParameters = &Weather->CameraPostProcessParameters;
|
||||
}
|
||||
|
||||
for (const auto &Item : Settings.CameraDescriptions) {
|
||||
PlayerController->AddSceneCaptureCamera(Item.Value, OverridePostProcessParameters);
|
||||
for (auto &Item : Settings.SensorDescriptions)
|
||||
{
|
||||
check(Item.Value != nullptr);
|
||||
auto &SensorDescription = *Item.Value;
|
||||
if (Weather != nullptr)
|
||||
{
|
||||
SensorDescription.AdjustToWeather(*Weather);
|
||||
}
|
||||
auto *Sensor = FSensorFactory::Make(SensorDescription, *GetWorld());
|
||||
check(Sensor != nullptr);
|
||||
Sensor->AttachToActor(PlayerController->GetPawn());
|
||||
GetDataRouter().RegisterSensor(*Sensor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,21 +7,22 @@
|
|||
#pragma once
|
||||
|
||||
#include "GameFramework/GameModeBase.h"
|
||||
#include "AI/VehicleSpawnerBase.h"
|
||||
#include "AI/WalkerSpawnerBase.h"
|
||||
#include "CarlaGameControllerBase.h"
|
||||
|
||||
#include "DynamicWeather.h"
|
||||
#include "MockGameControllerSettings.h"
|
||||
#include "Game/CarlaGameControllerBase.h"
|
||||
#include "Game/CarlaGameInstance.h"
|
||||
#include "Game/MockGameControllerSettings.h"
|
||||
#include "Vehicle/VehicleSpawnerBase.h"
|
||||
#include "Walker/WalkerSpawnerBase.h"
|
||||
|
||||
#include "CarlaGameModeBase.generated.h"
|
||||
|
||||
class ACarlaVehicleController;
|
||||
class APlayerStart;
|
||||
class ASceneCaptureCamera;
|
||||
class UCarlaGameInstance;
|
||||
class UTaggerDelegate;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(HideCategories=(ActorTick))
|
||||
class CARLA_API ACarlaGameModeBase : public AGameModeBase
|
||||
{
|
||||
|
@ -39,6 +40,12 @@ public:
|
|||
|
||||
virtual void Tick(float DeltaSeconds) override;
|
||||
|
||||
FDataRouter &GetDataRouter()
|
||||
{
|
||||
check(GameInstance != nullptr);
|
||||
return GameInstance->GetDataRouter();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/** Used only when networking is disabled. */
|
||||
|
@ -61,7 +68,7 @@ private:
|
|||
|
||||
void RegisterPlayer(AController &NewPlayer);
|
||||
|
||||
void AttachCaptureCamerasToPlayer();
|
||||
void AttachSensorsToPlayer();
|
||||
|
||||
void TagActorsForSemanticSegmentation();
|
||||
|
||||
|
@ -73,7 +80,7 @@ private:
|
|||
AController *Player,
|
||||
TArray<APlayerStart *> &UnOccupiedStartPoints);
|
||||
|
||||
CarlaGameControllerBase *GameController;
|
||||
ICarlaGameControllerBase *GameController;
|
||||
|
||||
UPROPERTY()
|
||||
UCarlaGameInstance *GameInstance;
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GameFramework/GameStateBase.h"
|
||||
#include "AI/TrafficSignBase.h"
|
||||
#include "AI/VehicleSpawnerBase.h"
|
||||
#include "AI/WalkerSpawnerBase.h"
|
||||
#include "CarlaGameState.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class CARLA_API ACarlaGameState : public AGameStateBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
const AVehicleSpawnerBase *GetVehicleSpawner() const
|
||||
{
|
||||
return VehicleSpawner;
|
||||
}
|
||||
|
||||
const AWalkerSpawnerBase *GetWalkerSpawner() const
|
||||
{
|
||||
return WalkerSpawner;
|
||||
}
|
||||
|
||||
const TArray<ATrafficSignBase *> &GetTrafficSigns() const
|
||||
{
|
||||
return TrafficSigns;
|
||||
}
|
||||
|
||||
void RegisterTrafficSign(ATrafficSignBase *TrafficSign)
|
||||
{
|
||||
TrafficSigns.Add(TrafficSign);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class ACarlaGameModeBase;
|
||||
|
||||
UPROPERTY()
|
||||
AVehicleSpawnerBase *VehicleSpawner = nullptr;
|
||||
|
||||
UPROPERTY()
|
||||
AWalkerSpawnerBase *WalkerSpawner = nullptr;
|
||||
|
||||
UPROPERTY()
|
||||
TArray<ATrafficSignBase *> TrafficSigns;
|
||||
};
|
|
@ -7,7 +7,8 @@
|
|||
#include "Carla.h"
|
||||
#include "CarlaHUD.h"
|
||||
|
||||
#include "CarlaVehicleController.h"
|
||||
#include "Vehicle/CarlaVehicleController.h"
|
||||
|
||||
#include "CommandLine.h"
|
||||
#include "ConstructorHelpers.h"
|
||||
#include "Engine/Canvas.h"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
class FTexture;
|
||||
|
||||
UCLASS()
|
||||
class ACarlaHUD : public AHUD
|
||||
class CARLA_API ACarlaHUD : public AHUD
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ void ACarlaPlayerState::Reset()
|
|||
CollisionIntensityCars = 0.0f;
|
||||
CollisionIntensityPedestrians = 0.0f;
|
||||
CollisionIntensityOther = 0.0f;
|
||||
Images.Empty();
|
||||
}
|
||||
|
||||
void ACarlaPlayerState::CopyProperties(APlayerState *PlayerState)
|
||||
|
@ -44,7 +43,6 @@ void ACarlaPlayerState::CopyProperties(APlayerState *PlayerState)
|
|||
CollisionIntensityOther = Other->CollisionIntensityOther;
|
||||
OtherLaneIntersectionFactor = Other->OtherLaneIntersectionFactor;
|
||||
OffRoadIntersectionFactor = Other->OffRoadIntersectionFactor;
|
||||
Images = Other->Images;
|
||||
UE_LOG(LogCarla, Log, TEXT("Copied properties of ACarlaPlayerState"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "GameFramework/PlayerState.h"
|
||||
#include "AI/TrafficLightState.h"
|
||||
#include "CapturedImage.h"
|
||||
|
||||
#include "Traffic/TrafficLightState.h"
|
||||
|
||||
#include "CarlaPlayerState.generated.h"
|
||||
|
||||
/// Current state of the player, updated every frame by ACarlaVehicleController.
|
||||
|
@ -183,29 +184,6 @@ public:
|
|||
return OffRoadIntersectionFactor;
|
||||
}
|
||||
|
||||
/// @}
|
||||
// ===========================================================================
|
||||
/// @name Images
|
||||
// ===========================================================================
|
||||
/// @{
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
int32 GetNumberOfImages() const
|
||||
{
|
||||
return Images.Num();
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
bool HasImages() const
|
||||
{
|
||||
return GetNumberOfImages() > 0;
|
||||
}
|
||||
|
||||
const TArray<FCapturedImage> &GetImages() const
|
||||
{
|
||||
return Images;
|
||||
}
|
||||
|
||||
/// @}
|
||||
// ===========================================================================
|
||||
// -- Modifiers --------------------------------------------------------------
|
||||
|
@ -283,7 +261,4 @@ private:
|
|||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
float OffRoadIntersectionFactor = 0.0f;
|
||||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
TArray<FCapturedImage> Images;
|
||||
};
|
||||
|
|
|
@ -1,350 +0,0 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "Carla.h"
|
||||
#include "CarlaServer.h"
|
||||
|
||||
#include "GameFramework/PlayerStart.h"
|
||||
|
||||
#include "CarlaPlayerState.h"
|
||||
#include "CarlaVehicleController.h"
|
||||
#include "CarlaWheeledVehicle.h"
|
||||
#include "SceneCaptureCamera.h"
|
||||
#include "Settings/CarlaSettings.h"
|
||||
|
||||
#include <carla/carla_server.h>
|
||||
|
||||
// =============================================================================
|
||||
// -- Static local methods -----------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
static CarlaServer::ErrorCode ParseErrorCode(const uint32 ErrorCode)
|
||||
{
|
||||
if (ErrorCode == CARLA_SERVER_SUCCESS) {
|
||||
return CarlaServer::Success;
|
||||
} else if (ErrorCode == CARLA_SERVER_TRY_AGAIN) {
|
||||
return CarlaServer::TryAgain;
|
||||
} else {
|
||||
return CarlaServer::Error;
|
||||
}
|
||||
}
|
||||
|
||||
static int32 GetTimeOut(uint32 TimeOut, const bool bBlocking)
|
||||
{
|
||||
return (bBlocking ? TimeOut : 0u);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// -- Set functions ------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
static inline void Set(bool &lhs, bool rhs)
|
||||
{
|
||||
lhs = rhs;
|
||||
}
|
||||
|
||||
static inline void Set(float &lhs, float rhs)
|
||||
{
|
||||
lhs = rhs;
|
||||
}
|
||||
|
||||
static inline void Set(carla_vector3d &lhs, const FVector &rhs)
|
||||
{
|
||||
lhs = {rhs.X, rhs.Y, rhs.Z};
|
||||
}
|
||||
|
||||
static inline void Set(carla_rotation3d &lhs, const FRotator &rhs)
|
||||
{
|
||||
lhs.pitch = rhs.Pitch;
|
||||
lhs.roll = rhs.Roll;
|
||||
lhs.yaw = rhs.Yaw;
|
||||
}
|
||||
|
||||
static inline void Set(carla_transform &lhs, const FTransform &rhs)
|
||||
{
|
||||
Set(lhs.location, rhs.GetLocation());
|
||||
Set(lhs.orientation, rhs.GetRotation().GetForwardVector());
|
||||
Set(lhs.rotation, rhs.Rotator());
|
||||
}
|
||||
|
||||
static void Set(carla_image &cImage, const FCapturedImage &uImage)
|
||||
{
|
||||
if (uImage.BitMap.Num() > 0) {
|
||||
cImage.width = uImage.SizeX;
|
||||
cImage.height = uImage.SizeY;
|
||||
cImage.type = PostProcessEffect::ToUInt(uImage.PostProcessEffect);
|
||||
cImage.data = &uImage.BitMap.GetData()->DWColor();
|
||||
|
||||
#ifdef CARLA_SERVER_EXTRA_LOG
|
||||
{
|
||||
const auto Size = uImage.BitMap.Num();
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Sending image %dx%d (%d) type %d"), cImage.width, cImage.height, Size, cImage.type);
|
||||
}
|
||||
} else {
|
||||
UE_LOG(LogCarlaServer, Warning, TEXT("Sending empty image"));
|
||||
#endif // CARLA_SERVER_EXTRA_LOG
|
||||
}
|
||||
}
|
||||
|
||||
static void SetBoxSpeedAndType(carla_agent &values, const ACharacter *Walker)
|
||||
{
|
||||
values.type = CARLA_SERVER_AGENT_PEDESTRIAN;
|
||||
values.forward_speed = FVector::DotProduct(Walker->GetVelocity(), Walker->GetActorRotation().Vector()) * 0.036f;
|
||||
/// @todo Perhaps the box it is not the same for every walker...
|
||||
values.box_extent = {45.0f, 35.0f, 100.0f};
|
||||
}
|
||||
|
||||
static void SetBoxSpeedAndType(carla_agent &values, const ACarlaWheeledVehicle *Vehicle)
|
||||
{
|
||||
values.type = CARLA_SERVER_AGENT_VEHICLE;
|
||||
values.forward_speed = Vehicle->GetVehicleForwardSpeed();
|
||||
Set(values.box_extent, Vehicle->GetVehicleBoundsExtent());
|
||||
}
|
||||
|
||||
static void SetBoxSpeedAndType(carla_agent &values, const ATrafficSignBase *TrafficSign)
|
||||
{
|
||||
switch (TrafficSign->GetTrafficSignState()) {
|
||||
case ETrafficSignState::TrafficLightRed:
|
||||
values.type = CARLA_SERVER_AGENT_TRAFFICLIGHT_RED;
|
||||
break;
|
||||
case ETrafficSignState::TrafficLightYellow:
|
||||
values.type = CARLA_SERVER_AGENT_TRAFFICLIGHT_YELLOW;
|
||||
break;
|
||||
case ETrafficSignState::TrafficLightGreen:
|
||||
values.type = CARLA_SERVER_AGENT_TRAFFICLIGHT_GREEN;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_30:
|
||||
values.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
values.forward_speed = 30.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_40:
|
||||
values.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
values.forward_speed = 40.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_50:
|
||||
values.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
values.forward_speed = 50.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_60:
|
||||
values.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
values.forward_speed = 60.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_90:
|
||||
values.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
values.forward_speed = 90.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_100:
|
||||
values.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
values.forward_speed = 100.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_120:
|
||||
values.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
values.forward_speed = 120.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_130:
|
||||
values.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
values.forward_speed = 130.0f;
|
||||
break;
|
||||
default:
|
||||
UE_LOG(LogCarla, Error, TEXT("Unknown traffic sign!"));
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// -- CarlaServer --------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
CarlaServer::CarlaServer(const uint32 InWorldPort, const uint32 InTimeOut) :
|
||||
WorldPort(InWorldPort),
|
||||
TimeOut(InTimeOut),
|
||||
Server(carla_make_server()) {
|
||||
check(Server != nullptr);
|
||||
}
|
||||
|
||||
CarlaServer::~CarlaServer()
|
||||
{
|
||||
#ifdef CARLA_SERVER_EXTRA_LOG
|
||||
UE_LOG(LogCarlaServer, Warning, TEXT("Destroying CarlaServer"));
|
||||
#endif // CARLA_SERVER_EXTRA_LOG
|
||||
carla_free_server(Server);
|
||||
}
|
||||
|
||||
CarlaServer::ErrorCode CarlaServer::Connect()
|
||||
{
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Waiting for the client to connect..."));
|
||||
return ParseErrorCode(carla_server_connect(Server, WorldPort, TimeOut));
|
||||
}
|
||||
|
||||
CarlaServer::ErrorCode CarlaServer::ReadNewEpisode(UCarlaSettings &Settings, const bool bBlocking)
|
||||
{
|
||||
carla_request_new_episode values;
|
||||
auto ec = ParseErrorCode(carla_read_request_new_episode(Server, values, GetTimeOut(TimeOut, bBlocking)));
|
||||
if (Success == ec) {
|
||||
auto IniFile = FString(values.ini_file_length, ANSI_TO_TCHAR(values.ini_file));
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Received new episode"));
|
||||
#ifdef CARLA_SERVER_EXTRA_LOG
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Received CarlaSettings.ini:\n%s"), *IniFile);
|
||||
#endif // CARLA_SERVER_EXTRA_LOG
|
||||
Settings.LoadSettingsFromString(IniFile);
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
|
||||
CarlaServer::ErrorCode CarlaServer::SendSceneDescription(
|
||||
const TArray<APlayerStart *> &AvailableStartSpots,
|
||||
const bool bBlocking)
|
||||
{
|
||||
const int32 NumberOfStartSpots = AvailableStartSpots.Num();
|
||||
auto StartSpots = MakeUnique<carla_transform[]>(NumberOfStartSpots);
|
||||
|
||||
for (auto i = 0; i < NumberOfStartSpots; ++i) {
|
||||
Set(StartSpots[i], AvailableStartSpots[i]->GetActorTransform());
|
||||
}
|
||||
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Sending %d available start positions"), NumberOfStartSpots);
|
||||
carla_scene_description scene;
|
||||
scene.player_start_spots = StartSpots.Get();
|
||||
scene.number_of_player_start_spots = NumberOfStartSpots;
|
||||
|
||||
return ParseErrorCode(carla_write_scene_description(Server, scene, GetTimeOut(TimeOut, bBlocking)));
|
||||
}
|
||||
|
||||
CarlaServer::ErrorCode CarlaServer::ReadEpisodeStart(uint32 &StartPositionIndex, const bool bBlocking)
|
||||
{
|
||||
carla_episode_start values;
|
||||
auto ec = ParseErrorCode(carla_read_episode_start(Server, values, GetTimeOut(TimeOut, bBlocking)));
|
||||
if (Success == ec) {
|
||||
StartPositionIndex = values.player_start_spot_index;
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Episode start received: { StartIndex = %d }"), StartPositionIndex);
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
|
||||
CarlaServer::ErrorCode CarlaServer::SendEpisodeReady(const bool bBlocking)
|
||||
{
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Ready to play, notifying client"));
|
||||
const carla_episode_ready values = {true};
|
||||
return ParseErrorCode(carla_write_episode_ready(Server, values, GetTimeOut(TimeOut, bBlocking)));
|
||||
}
|
||||
|
||||
CarlaServer::ErrorCode CarlaServer::ReadControl(ACarlaVehicleController &Player, const bool bBlocking)
|
||||
{
|
||||
carla_control values;
|
||||
auto ec = ParseErrorCode(carla_read_control(Server, values, GetTimeOut(TimeOut, bBlocking)));
|
||||
if (Success == ec) {
|
||||
check(Player.IsPossessingAVehicle());
|
||||
auto Vehicle = Player.GetPossessedVehicle();
|
||||
Vehicle->SetSteeringInput(values.steer);
|
||||
Vehicle->SetThrottleInput(values.throttle);
|
||||
Vehicle->SetBrakeInput(values.brake);
|
||||
Vehicle->SetHandbrakeInput(values.hand_brake);
|
||||
Vehicle->SetReverse(values.reverse);
|
||||
#ifdef CARLA_SERVER_EXTRA_LOG
|
||||
UE_LOG(
|
||||
LogCarlaServer,
|
||||
Log,
|
||||
TEXT("Read control (%s): { Steer = %f, Throttle = %f, Brake = %f, Handbrake = %s, Reverse = %s }"),
|
||||
(bBlocking ? TEXT("Sync") : TEXT("Async")),
|
||||
values.steer,
|
||||
values.throttle,
|
||||
values.brake,
|
||||
(values.hand_brake ? TEXT("True") : TEXT("False")),
|
||||
(values.reverse ? TEXT("True") : TEXT("False")));
|
||||
#endif // CARLA_SERVER_EXTRA_LOG
|
||||
} else if ((!bBlocking) && (TryAgain == ec)) {
|
||||
UE_LOG(LogCarlaServer, Warning, TEXT("No control received from the client this frame!"));
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void AddAgents(TArray<carla_agent> &Agents, const TArray<T> &Actors)
|
||||
{
|
||||
for (auto &&Actor : Actors) {
|
||||
if (Actor != nullptr) {
|
||||
Agents.Emplace();
|
||||
auto &values = Agents.Last();
|
||||
values.id = GetTypeHash(Actor);
|
||||
Set(values.transform, Actor->GetActorTransform());
|
||||
SetBoxSpeedAndType(values, Actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GetAgentInfo(
|
||||
const ACarlaGameState &GameState,
|
||||
TArray<carla_agent> &Agents)
|
||||
{
|
||||
const auto *WalkerSpawner = GameState.GetWalkerSpawner();
|
||||
const auto *VehicleSpawner = GameState.GetVehicleSpawner();
|
||||
const auto &TrafficSigns = GameState.GetTrafficSigns();
|
||||
|
||||
auto NumberOfAgents = TrafficSigns.Num();
|
||||
if (WalkerSpawner != nullptr) {
|
||||
NumberOfAgents += WalkerSpawner->GetCurrentNumberOfWalkers();
|
||||
}
|
||||
if (VehicleSpawner != nullptr) {
|
||||
NumberOfAgents += VehicleSpawner->GetNumberOfSpawnedVehicles();
|
||||
}
|
||||
Agents.Reserve(NumberOfAgents);
|
||||
|
||||
AddAgents(Agents, TrafficSigns);
|
||||
if (WalkerSpawner != nullptr) {
|
||||
AddAgents(Agents, WalkerSpawner->GetWalkersWhiteList());
|
||||
AddAgents(Agents, WalkerSpawner->GetWalkersBlackList());
|
||||
}
|
||||
if (VehicleSpawner != nullptr) {
|
||||
AddAgents(Agents, VehicleSpawner->GetVehicles());
|
||||
}
|
||||
}
|
||||
|
||||
CarlaServer::ErrorCode CarlaServer::SendMeasurements(
|
||||
const ACarlaGameState &GameState,
|
||||
const ACarlaPlayerState &PlayerState,
|
||||
const bool bSendNonPlayerAgentsInfo)
|
||||
{
|
||||
// Measurements.
|
||||
carla_measurements values;
|
||||
values.platform_timestamp = PlayerState.GetPlatformTimeStamp();
|
||||
values.game_timestamp = PlayerState.GetGameTimeStamp();
|
||||
auto &player = values.player_measurements;
|
||||
Set(player.transform, PlayerState.GetTransform());
|
||||
Set(player.acceleration, PlayerState.GetAcceleration());
|
||||
Set(player.forward_speed, PlayerState.GetForwardSpeed());
|
||||
Set(player.collision_vehicles, PlayerState.GetCollisionIntensityCars());
|
||||
Set(player.collision_pedestrians, PlayerState.GetCollisionIntensityPedestrians());
|
||||
Set(player.collision_other, PlayerState.GetCollisionIntensityOther());
|
||||
Set(player.intersection_otherlane, PlayerState.GetOtherLaneIntersectionFactor());
|
||||
Set(player.intersection_offroad, PlayerState.GetOffRoadIntersectionFactor());
|
||||
Set(player.autopilot_control.steer, PlayerState.GetSteer());
|
||||
Set(player.autopilot_control.throttle, PlayerState.GetThrottle());
|
||||
Set(player.autopilot_control.brake, PlayerState.GetBrake());
|
||||
Set(player.autopilot_control.hand_brake, PlayerState.GetHandBrake());
|
||||
Set(player.autopilot_control.reverse, PlayerState.GetCurrentGear() < 0);
|
||||
|
||||
TArray<carla_agent> Agents;
|
||||
if (bSendNonPlayerAgentsInfo) {
|
||||
GetAgentInfo(GameState, Agents);
|
||||
}
|
||||
values.non_player_agents = (Agents.Num() > 0 ? Agents.GetData() : nullptr);
|
||||
values.number_of_non_player_agents = Agents.Num();
|
||||
|
||||
#ifdef CARLA_SERVER_EXTRA_LOG
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Sending data of %d agents"), values.number_of_non_player_agents);
|
||||
#endif // CARLA_SERVER_EXTRA_LOG
|
||||
|
||||
// Images.
|
||||
const auto NumberOfImages = PlayerState.GetNumberOfImages();
|
||||
TUniquePtr<carla_image[]> images;
|
||||
if (NumberOfImages > 0) {
|
||||
images = MakeUnique<carla_image[]>(NumberOfImages);
|
||||
for (auto i = 0; i < NumberOfImages; ++i) {
|
||||
Set(images[i], PlayerState.GetImages()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return ParseErrorCode(carla_write_measurements(Server, values, images.Get(), NumberOfImages));
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "Carla.h"
|
||||
#include "DataRouter.h"
|
||||
|
||||
#include "Sensor/Sensor.h"
|
||||
|
||||
void FDataRouter::RegisterPlayer(ACarlaVehicleController &InPlayer)
|
||||
{
|
||||
if (Player == nullptr) {
|
||||
Player = &InPlayer;
|
||||
} else {
|
||||
UE_LOG(
|
||||
LogCarla,
|
||||
Error,
|
||||
TEXT("FDataRouter: Trying to register a second player but only one is supported"));
|
||||
}
|
||||
}
|
||||
|
||||
void FDataRouter::RegisterSensor(ASensor &InSensor)
|
||||
{
|
||||
if (SensorDataSink.IsValid()) {
|
||||
InSensor.SetSensorDataSink(SensorDataSink);
|
||||
} else {
|
||||
UE_LOG(
|
||||
LogCarla,
|
||||
Error,
|
||||
TEXT("FDataRouter: Trying to register a sensor but I don't have a SensorDataSink"));
|
||||
}
|
||||
}
|
||||
|
||||
void FDataRouter::RestartLevel()
|
||||
{
|
||||
if (Player != nullptr) {
|
||||
Player->RestartLevel();
|
||||
Player = nullptr;
|
||||
} else {
|
||||
UE_LOG(
|
||||
LogCarla,
|
||||
Error,
|
||||
TEXT("FDataRouter: Trying to restart level but I don't have any player registered"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Util/NonCopyable.h"
|
||||
|
||||
#include "Sensor/SensorDataSink.h"
|
||||
|
||||
#include "Vehicle/CarlaVehicleController.h"
|
||||
#include "Vehicle/CarlaWheeledVehicle.h"
|
||||
|
||||
class ACarlaPlayerState;
|
||||
class ASensor;
|
||||
class UAgentComponent;
|
||||
struct FVehicleControl;
|
||||
|
||||
class FDataRouter : private NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
void SetSensorDataSink(TSharedPtr<ISensorDataSink> InSensorDataSink)
|
||||
{
|
||||
check(!SensorDataSink.IsValid());
|
||||
SensorDataSink = InSensorDataSink;
|
||||
}
|
||||
|
||||
void RegisterPlayer(ACarlaVehicleController &InPlayer);
|
||||
|
||||
void RegisterSensor(ASensor &InSensor);
|
||||
|
||||
void RegisterAgent(const UAgentComponent *Agent)
|
||||
{
|
||||
check(Agent != nullptr);
|
||||
Agents.Emplace(Agent);
|
||||
}
|
||||
|
||||
void DeregisterAgent(const UAgentComponent *Agent)
|
||||
{
|
||||
check(Agent != nullptr);
|
||||
Agents.RemoveSwap(Agent);
|
||||
}
|
||||
|
||||
const ACarlaPlayerState &GetPlayerState() const
|
||||
{
|
||||
check(Player != nullptr);
|
||||
return Player->GetPlayerState();
|
||||
}
|
||||
|
||||
const TArray<const UAgentComponent *> &GetAgents() const
|
||||
{
|
||||
return Agents;
|
||||
}
|
||||
|
||||
void ApplyVehicleControl(const FVehicleControl &VehicleControl)
|
||||
{
|
||||
check((Player != nullptr) && (Player->IsPossessingAVehicle()));
|
||||
Player->GetPossessedVehicle()->ApplyVehicleControl(VehicleControl);
|
||||
}
|
||||
|
||||
void RestartLevel();
|
||||
|
||||
private:
|
||||
|
||||
TArray<const UAgentComponent *> Agents;
|
||||
|
||||
ACarlaVehicleController *Player = nullptr;
|
||||
|
||||
TSharedPtr<ISensorDataSink> SensorDataSink = nullptr;
|
||||
};
|
|
@ -7,8 +7,22 @@
|
|||
#include "Carla.h"
|
||||
#include "MockGameController.h"
|
||||
|
||||
MockGameController::MockGameController(const FMockGameControllerSettings &InSettings) :
|
||||
Settings(InSettings) {}
|
||||
#include "Game/DataRouter.h"
|
||||
#include "Sensor/SensorDataSink.h"
|
||||
|
||||
class FMockSensorDataSink : public ISensorDataSink {
|
||||
public:
|
||||
|
||||
virtual void Write(const FSensorDataView &) final {}
|
||||
};
|
||||
|
||||
MockGameController::MockGameController(
|
||||
FDataRouter &InDataRouter,
|
||||
const FMockGameControllerSettings &InSettings)
|
||||
: ICarlaGameControllerBase(InDataRouter),
|
||||
Settings(InSettings) {
|
||||
DataRouter.SetSensorDataSink(MakeShared<FMockSensorDataSink>());
|
||||
}
|
||||
|
||||
void MockGameController::Initialize(UCarlaSettings &CarlaSettings)
|
||||
{
|
||||
|
|
|
@ -6,25 +6,26 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "CarlaGameControllerBase.h"
|
||||
#include "MockGameControllerSettings.h"
|
||||
#include "Game/CarlaGameControllerBase.h"
|
||||
|
||||
#include "Game/MockGameControllerSettings.h"
|
||||
|
||||
/// Mocks the CARLA game controller class for testing purposes.
|
||||
class CARLA_API MockGameController : public CarlaGameControllerBase
|
||||
class MockGameController : public ICarlaGameControllerBase
|
||||
{
|
||||
public:
|
||||
|
||||
explicit MockGameController(const FMockGameControllerSettings &Settings);
|
||||
explicit MockGameController(FDataRouter &DataRouter, const FMockGameControllerSettings &Settings);
|
||||
|
||||
virtual void Initialize(UCarlaSettings &CarlaSettings) override;
|
||||
virtual void Initialize(UCarlaSettings &CarlaSettings) final;
|
||||
|
||||
virtual APlayerStart *ChoosePlayerStart(const TArray<APlayerStart *> &AvailableStartSpots) override;
|
||||
virtual APlayerStart *ChoosePlayerStart(const TArray<APlayerStart *> &AvailableStartSpots) final;
|
||||
|
||||
virtual void RegisterPlayer(AController &NewPlayer) override;
|
||||
virtual void RegisterPlayer(AController &NewPlayer) final;
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
virtual void BeginPlay() final;
|
||||
|
||||
virtual void Tick(float DeltaSeconds) override;
|
||||
virtual void Tick(float DeltaSeconds) final;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "MockGameControllerSettings.generated.h"
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FMockGameControllerSettings
|
||||
struct CARLA_API FMockGameControllerSettings
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
|
||||
#include "Carla.h"
|
||||
#include "Tagger.h"
|
||||
#include "EngineUtils.h"
|
||||
#include "Engine/StaticMesh.h"
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
#include "Components/StaticMeshComponent.h"
|
||||
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "Components/StaticMeshComponent.h"
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
#include "Engine/StaticMesh.h"
|
||||
#include "EngineUtils.h"
|
||||
#include "PhysicsEngine/PhysicsAsset.h"
|
||||
|
||||
#ifdef CARLA_TAGGER_EXTRA_LOG
|
|
@ -7,8 +7,9 @@
|
|||
#include "Carla.h"
|
||||
#include "TaggerDelegate.h"
|
||||
|
||||
#include "Game/Tagger.h"
|
||||
|
||||
#include "Engine/World.h"
|
||||
#include "Tagger.h"
|
||||
|
||||
UTaggerDelegate::UTaggerDelegate() :
|
||||
ActorSpawnedDelegate(FOnActorSpawned::FDelegate::CreateUObject(this, &UTaggerDelegate::OnActorSpawned)) {}
|
||||
|
|
|
@ -73,7 +73,7 @@ enum class ECityMapMeshTag : uint8
|
|||
};
|
||||
|
||||
/// Helper class for working with ECityMapMeshTag.
|
||||
class CARLA_API CityMapMeshTag
|
||||
class CityMapMeshTag
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
namespace MapGen {
|
||||
|
||||
/// Random DoublyConnectedEdgeList generator.
|
||||
class CARLA_API GraphGenerator : private NonCopyable
|
||||
class GraphGenerator : private NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace MapGen {
|
|||
|
||||
class DoublyConnectedEdgeList;
|
||||
|
||||
class CARLA_API GraphParser : private NonCopyable
|
||||
class GraphParser : private NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
namespace MapGen {
|
||||
|
||||
template<typename T>
|
||||
class CARLA_API Position {
|
||||
class Position {
|
||||
public:
|
||||
using number_type = T;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
/// Road map intersection result. See URoadMap.
|
||||
USTRUCT(BlueprintType)
|
||||
struct FRoadMapIntersectionResult
|
||||
struct CARLA_API FRoadMapIntersectionResult
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
namespace MapGen {
|
||||
|
||||
class CARLA_API RoadSegmentDescription : private NonCopyable
|
||||
class RoadSegmentDescription : private NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ enum class ELaneMarkingType : uint8
|
|||
|
||||
/// Description of a road segment piece.
|
||||
USTRUCT(BlueprintType)
|
||||
struct FRoadSegmentPiece
|
||||
struct CARLA_API FRoadSegmentPiece
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "Carla.h"
|
||||
#include "Lidar.h"
|
||||
|
||||
#include "DrawDebugHelpers.h"
|
||||
#include "Engine/CollisionProfile.h"
|
||||
#include "Runtime/Engine/Classes/Kismet/KismetMathLibrary.h"
|
||||
#include "StaticMeshResources.h"
|
||||
|
||||
ALidar::ALidar(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
|
||||
auto MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CamMesh0"));
|
||||
MeshComp->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
|
||||
MeshComp->bHiddenInGame = true;
|
||||
MeshComp->CastShadow = false;
|
||||
MeshComp->PostPhysicsComponentTick.bCanEverTick = false;
|
||||
RootComponent = MeshComp;
|
||||
}
|
||||
|
||||
void ALidar::Set(const ULidarDescription &LidarDescription)
|
||||
{
|
||||
Super::Set(LidarDescription);
|
||||
Description = &LidarDescription;
|
||||
LidarMeasurement = FLidarMeasurement(GetId(), Description->Channels);
|
||||
CreateLasers();
|
||||
}
|
||||
|
||||
void ALidar::CreateLasers()
|
||||
{
|
||||
check(Description != nullptr);
|
||||
const auto NumberOfLasers = Description->Channels;
|
||||
check(NumberOfLasers > 0u);
|
||||
const float DeltaAngle =
|
||||
(Description->UpperFovLimit - Description->LowerFovLimit) /
|
||||
static_cast<float>(NumberOfLasers - 1);
|
||||
LaserAngles.Empty(NumberOfLasers);
|
||||
for(auto i = 0u; i < NumberOfLasers; ++i)
|
||||
{
|
||||
const float VerticalAngle =
|
||||
Description->UpperFovLimit - static_cast<float>(i) * DeltaAngle;
|
||||
LaserAngles.Emplace(VerticalAngle);
|
||||
}
|
||||
}
|
||||
|
||||
void ALidar::Tick(const float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
|
||||
ReadPoints(DeltaTime);
|
||||
WriteSensorData(LidarMeasurement.GetView());
|
||||
}
|
||||
|
||||
void ALidar::ReadPoints(const float DeltaTime)
|
||||
{
|
||||
const uint32 ChannelCount = Description->Channels;
|
||||
const uint32 PointsToScanWithOneLaser =
|
||||
FMath::RoundHalfFromZero(
|
||||
Description->PointsPerSecond * DeltaTime / float(ChannelCount));
|
||||
check(PointsToScanWithOneLaser > 0);
|
||||
check(ChannelCount == LaserAngles.Num());
|
||||
check(Description != nullptr);
|
||||
|
||||
const float CurrentHorizontalAngle = LidarMeasurement.GetHorizontalAngle();
|
||||
const float AngleDistanceOfTick = Description->RotationFrequency * 360.0f * DeltaTime;
|
||||
const float AngleDistanceOfLaserMeasure = AngleDistanceOfTick / PointsToScanWithOneLaser;
|
||||
|
||||
LidarMeasurement.Reset(ChannelCount * PointsToScanWithOneLaser);
|
||||
|
||||
for (auto Channel = 0u; Channel < ChannelCount; ++Channel)
|
||||
{
|
||||
for (auto i = 0u; i < PointsToScanWithOneLaser; ++i)
|
||||
{
|
||||
FVector Point;
|
||||
const float Angle = CurrentHorizontalAngle + AngleDistanceOfLaserMeasure * i;
|
||||
if (ShootLaser(Channel, Angle, Point))
|
||||
{
|
||||
LidarMeasurement.WritePoint(Channel, Point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const float HorizontalAngle = std::fmod(CurrentHorizontalAngle + AngleDistanceOfTick, 360.0f);
|
||||
LidarMeasurement.SetHorizontalAngle(HorizontalAngle);
|
||||
}
|
||||
|
||||
bool ALidar::ShootLaser(const uint32 Channel, const float HorizontalAngle, FVector &XYZ) const
|
||||
{
|
||||
const float VerticalAngle = LaserAngles[Channel];
|
||||
|
||||
FCollisionQueryParams TraceParams = FCollisionQueryParams(FName(TEXT("Laser_Trace")), true, this);
|
||||
TraceParams.bTraceComplex = true;
|
||||
TraceParams.bReturnPhysicalMaterial = false;
|
||||
|
||||
FHitResult HitInfo(ForceInit);
|
||||
|
||||
FVector LidarBodyLoc = GetActorLocation();
|
||||
FRotator LidarBodyRot = GetActorRotation();
|
||||
FRotator LaserRot (VerticalAngle, HorizontalAngle, 0); // float InPitch, float InYaw, float InRoll
|
||||
FRotator ResultRot = UKismetMathLibrary::ComposeRotators(
|
||||
LaserRot,
|
||||
LidarBodyRot
|
||||
);
|
||||
const auto Range = Description->Range;
|
||||
FVector EndTrace = Range * UKismetMathLibrary::GetForwardVector(ResultRot) + LidarBodyLoc;
|
||||
|
||||
GetWorld()->LineTraceSingleByChannel(
|
||||
HitInfo,
|
||||
LidarBodyLoc,
|
||||
EndTrace,
|
||||
ECC_MAX,
|
||||
TraceParams,
|
||||
FCollisionResponseParams::DefaultResponseParam
|
||||
);
|
||||
|
||||
if (HitInfo.bBlockingHit)
|
||||
{
|
||||
if (Description->ShowDebugPoints)
|
||||
{
|
||||
DrawDebugPoint(
|
||||
GetWorld(),
|
||||
HitInfo.ImpactPoint,
|
||||
10, //size
|
||||
FColor(255,0,255),
|
||||
false, //persistent (never goes away)
|
||||
0.1 //point leaves a trail on moving object
|
||||
);
|
||||
}
|
||||
|
||||
XYZ = LidarBodyLoc - HitInfo.ImpactPoint;
|
||||
XYZ = UKismetMathLibrary::RotateAngleAxis(
|
||||
XYZ,
|
||||
- LidarBodyRot.Yaw + 90,
|
||||
FVector(0, 0, 1)
|
||||
);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Sensor/Sensor.h"
|
||||
|
||||
#include "Sensor/LidarMeasurement.h"
|
||||
#include "Settings/LidarDescription.h"
|
||||
|
||||
#include "Lidar.generated.h"
|
||||
|
||||
/// A ray-trace based Lidar sensor.
|
||||
UCLASS()
|
||||
class CARLA_API ALidar : public ASensor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
ALidar(const FObjectInitializer &ObjectInitializer);
|
||||
|
||||
void Set(const ULidarDescription &LidarDescription);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
||||
private:
|
||||
|
||||
/// Creates a Laser for each channel.
|
||||
void CreateLasers();
|
||||
|
||||
/// Updates LidarMeasurement with the points read in DeltaTime.
|
||||
void ReadPoints(float DeltaTime);
|
||||
|
||||
/// Shoot a laser ray-trace, return whether the laser hit something.
|
||||
bool ShootLaser(uint32 Channel, float HorizontalAngle, FVector &Point) const;
|
||||
|
||||
UPROPERTY(Category = "LiDAR", VisibleAnywhere)
|
||||
const ULidarDescription *Description;
|
||||
|
||||
TArray<float> LaserAngles;
|
||||
|
||||
FLidarMeasurement LidarMeasurement;
|
||||
};
|
|
@ -0,0 +1,95 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Sensor/SensorDataView.h"
|
||||
|
||||
#include "Containers/Array.h"
|
||||
|
||||
/// Stores the data generated by ALidar. To be used by ALidar solely.
|
||||
///
|
||||
/// The header consists of an array of uint32's in the following layout
|
||||
///
|
||||
/// {
|
||||
/// Horizontal angle (float),
|
||||
/// Channel count,
|
||||
/// Point count of channel 0,
|
||||
/// ...
|
||||
/// Point count of channel n,
|
||||
/// }
|
||||
///
|
||||
/// The points are stored in an array of floats
|
||||
///
|
||||
/// {
|
||||
/// X0, Y0, Z0,
|
||||
/// ...
|
||||
/// Xn, Yn, Zn,
|
||||
/// }
|
||||
///
|
||||
class FLidarMeasurement {
|
||||
static_assert(sizeof(float) == sizeof(uint32), "Invalid float size");
|
||||
public:
|
||||
|
||||
explicit FLidarMeasurement(uint32 SensorId = 0u, uint32 ChannelCount = 0u)
|
||||
: SensorId(SensorId)
|
||||
{
|
||||
Header.AddDefaulted(2u + ChannelCount);
|
||||
Header[1] = ChannelCount;
|
||||
}
|
||||
|
||||
FLidarMeasurement &operator=(FLidarMeasurement &&Other)
|
||||
{
|
||||
SensorId = Other.SensorId;
|
||||
Header = std::move(Other.Header);
|
||||
Points = std::move(Other.Points);
|
||||
Other.SensorId = 0u;
|
||||
return *this;
|
||||
}
|
||||
|
||||
float GetHorizontalAngle() const
|
||||
{
|
||||
return reinterpret_cast<const float &>(Header[0]);
|
||||
}
|
||||
|
||||
void SetHorizontalAngle(float HorizontalAngle)
|
||||
{
|
||||
Header[0] = reinterpret_cast<const uint32 &>(HorizontalAngle);
|
||||
}
|
||||
|
||||
uint32 GetChannelCount() const
|
||||
{
|
||||
return Header[1];
|
||||
}
|
||||
|
||||
void Reset(uint32 TotalPointCount)
|
||||
{
|
||||
std::memset(Header.GetData() + 2u, 0, sizeof(uint32) * GetChannelCount());
|
||||
Points.Reset(3u * TotalPointCount);
|
||||
}
|
||||
|
||||
void WritePoint(uint32 Channel, const FVector &Point)
|
||||
{
|
||||
check(Header[1] > Channel);
|
||||
Header[2u + Channel] += 1u;
|
||||
Points.Emplace(Point.X);
|
||||
Points.Emplace(Point.Y);
|
||||
Points.Emplace(Point.Z);
|
||||
}
|
||||
|
||||
FSensorDataView GetView() const
|
||||
{
|
||||
return FSensorDataView(SensorId, Header, Points);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32 SensorId;
|
||||
|
||||
TArray<uint32> Header;
|
||||
|
||||
TArray<float> Points;
|
||||
};
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Containers/Array.h"
|
||||
|
||||
/// A view over a read-only buffer. Does not own the data.
|
||||
class FReadOnlyBufferView {
|
||||
public:
|
||||
|
||||
FReadOnlyBufferView() = default;
|
||||
|
||||
explicit FReadOnlyBufferView(const void *InData, uint32 InSize)
|
||||
: Data(InData),
|
||||
Size(InSize) {}
|
||||
|
||||
template <typename T>
|
||||
FReadOnlyBufferView(const TArray<T> &Array)
|
||||
: FReadOnlyBufferView(Array.GetData(), sizeof(T) * Array.Num()) {}
|
||||
|
||||
bool HasData() const
|
||||
{
|
||||
return (Data != nullptr) && (Size > 0u);
|
||||
}
|
||||
|
||||
const void *GetData() const
|
||||
{
|
||||
return Data;
|
||||
}
|
||||
|
||||
uint32 GetSize() const
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const void *Data = nullptr;
|
||||
|
||||
uint32 Size = 0u;
|
||||
};
|
|
@ -7,6 +7,8 @@
|
|||
#include "Carla.h"
|
||||
#include "SceneCaptureCamera.h"
|
||||
|
||||
#include "Sensor/SensorDataView.h"
|
||||
|
||||
#include "Components/DrawFrustumComponent.h"
|
||||
#include "Components/SceneCaptureComponent2D.h"
|
||||
#include "Components/StaticMeshComponent.h"
|
||||
|
@ -38,7 +40,7 @@ ASceneCaptureCamera::ASceneCaptureCamera(const FObjectInitializer& ObjectInitial
|
|||
SizeY(512u),
|
||||
PostProcessEffect(EPostProcessEffect::SceneFinal)
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true; /// @todo Does it need to tick?
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
PrimaryActorTick.TickGroup = TG_PrePhysics;
|
||||
|
||||
MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CamMesh0"));
|
||||
|
@ -119,6 +121,43 @@ void ASceneCaptureCamera::BeginPlay()
|
|||
Super::BeginPlay();
|
||||
}
|
||||
|
||||
void ASceneCaptureCamera::Tick(const float DeltaSeconds)
|
||||
{
|
||||
Super::Tick(DeltaSeconds);
|
||||
|
||||
/// @todo This should be done on render thread.
|
||||
|
||||
struct {
|
||||
uint32 Width;
|
||||
uint32 Height;
|
||||
uint32 Type;
|
||||
float FOV;
|
||||
} ImageHeader = {
|
||||
SizeX,
|
||||
SizeY,
|
||||
PostProcessEffect::ToUInt(PostProcessEffect),
|
||||
CaptureComponent2D->FOVAngle
|
||||
};
|
||||
|
||||
static_assert(sizeof(ImageHeader) == 4u * sizeof(uint32), "Invalid header size");
|
||||
|
||||
TArray<FColor> BitMap;
|
||||
if (ReadPixels(BitMap)) {
|
||||
FSensorDataView DataView(
|
||||
GetId(),
|
||||
FReadOnlyBufferView{reinterpret_cast<const void *>(&ImageHeader), sizeof(ImageHeader)},
|
||||
FReadOnlyBufferView{BitMap});
|
||||
|
||||
WriteSensorData(DataView);
|
||||
}
|
||||
}
|
||||
|
||||
float ASceneCaptureCamera::GetFOVAngle() const
|
||||
{
|
||||
check(CaptureComponent2D != nullptr);
|
||||
return CaptureComponent2D->FOVAngle;
|
||||
}
|
||||
|
||||
void ASceneCaptureCamera::SetImageSize(uint32 otherSizeX, uint32 otherSizeY)
|
||||
{
|
||||
SizeX = otherSizeX;
|
||||
|
@ -149,29 +188,27 @@ void ASceneCaptureCamera::SetTargetGamma(const float TargetGamma)
|
|||
CaptureRenderTarget->TargetGamma = TargetGamma;
|
||||
}
|
||||
|
||||
void ASceneCaptureCamera::Set(const FCameraDescription &CameraDescription)
|
||||
void ASceneCaptureCamera::Set(const UCameraDescription &CameraDescription)
|
||||
{
|
||||
Super::Set(CameraDescription);
|
||||
|
||||
if (CameraDescription.bOverrideCameraPostProcessParameters) {
|
||||
auto &Override = CameraDescription.CameraPostProcessParameters;
|
||||
auto &PostProcessSettings = CaptureComponent2D->PostProcessSettings;
|
||||
PostProcessSettings.bOverride_AutoExposureMethod = true;
|
||||
PostProcessSettings.AutoExposureMethod = Override.AutoExposureMethod;
|
||||
PostProcessSettings.bOverride_AutoExposureMinBrightness = true;
|
||||
PostProcessSettings.AutoExposureMinBrightness = Override.AutoExposureMinBrightness;
|
||||
PostProcessSettings.bOverride_AutoExposureMaxBrightness = true;
|
||||
PostProcessSettings.AutoExposureMaxBrightness = Override.AutoExposureMaxBrightness;
|
||||
PostProcessSettings.bOverride_AutoExposureBias = true;
|
||||
PostProcessSettings.AutoExposureBias = Override.AutoExposureBias;
|
||||
}
|
||||
SetImageSize(CameraDescription.ImageSizeX, CameraDescription.ImageSizeY);
|
||||
SetPostProcessEffect(CameraDescription.PostProcessEffect);
|
||||
SetFOVAngle(CameraDescription.FOVAngle);
|
||||
}
|
||||
|
||||
void ASceneCaptureCamera::Set(
|
||||
const FCameraDescription &CameraDescription,
|
||||
const FCameraPostProcessParameters &OverridePostProcessParameters)
|
||||
{
|
||||
auto &PostProcessSettings = CaptureComponent2D->PostProcessSettings;
|
||||
PostProcessSettings.bOverride_AutoExposureMethod = true;
|
||||
PostProcessSettings.AutoExposureMethod = OverridePostProcessParameters.AutoExposureMethod;
|
||||
PostProcessSettings.bOverride_AutoExposureMinBrightness = true;
|
||||
PostProcessSettings.AutoExposureMinBrightness = OverridePostProcessParameters.AutoExposureMinBrightness;
|
||||
PostProcessSettings.bOverride_AutoExposureMaxBrightness = true;
|
||||
PostProcessSettings.AutoExposureMaxBrightness = OverridePostProcessParameters.AutoExposureMaxBrightness;
|
||||
PostProcessSettings.bOverride_AutoExposureBias = true;
|
||||
PostProcessSettings.AutoExposureBias = OverridePostProcessParameters.AutoExposureBias;
|
||||
Set(CameraDescription);
|
||||
}
|
||||
|
||||
bool ASceneCaptureCamera::ReadPixels(TArray<FColor> &BitMap) const
|
||||
{
|
||||
FTextureRenderTargetResource* RTResource = CaptureRenderTarget->GameThread_GetRenderTargetResource();
|
|
@ -6,9 +6,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "StaticMeshResources.h"
|
||||
#include "Sensor/Sensor.h"
|
||||
|
||||
#include "Settings/CameraDescription.h"
|
||||
|
||||
#include "StaticMeshResources.h"
|
||||
|
||||
#include "SceneCaptureCamera.generated.h"
|
||||
|
||||
class UDrawFrustumComponent;
|
||||
|
@ -19,7 +22,7 @@ class UTextureRenderTarget2D;
|
|||
/// Own SceneCapture, re-implementing some of the methods since ASceneCapture
|
||||
/// cannot be subclassed.
|
||||
UCLASS(hidecategories=(Collision, Attachment, Actor))
|
||||
class CARLA_API ASceneCaptureCamera : public AActor
|
||||
class CARLA_API ASceneCaptureCamera : public ASensor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
@ -35,6 +38,8 @@ public:
|
|||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void Tick(float DeltaSeconds) override;
|
||||
|
||||
uint32 GetImageSizeX() const
|
||||
{
|
||||
return SizeX;
|
||||
|
@ -50,6 +55,8 @@ public:
|
|||
return PostProcessEffect;
|
||||
}
|
||||
|
||||
float GetFOVAngle() const;
|
||||
|
||||
void SetImageSize(uint32 SizeX, uint32 SizeY);
|
||||
|
||||
void SetPostProcessEffect(EPostProcessEffect PostProcessEffect);
|
||||
|
@ -58,11 +65,7 @@ public:
|
|||
|
||||
void SetTargetGamma(float TargetGamma);
|
||||
|
||||
void Set(const FCameraDescription &CameraDescription);
|
||||
|
||||
void Set(
|
||||
const FCameraDescription &CameraDescription,
|
||||
const FCameraPostProcessParameters &OverridePostProcessParameters);
|
||||
void Set(const UCameraDescription &CameraDescription);
|
||||
|
||||
bool ReadPixels(TArray<FColor> &BitMap) const;
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
ASceneCaptureToDiskCamera::ASceneCaptureToDiskCamera(const FObjectInitializer& ObjectInitializer) :
|
||||
Super(ObjectInitializer),
|
||||
SaveToFolder(FPaths::Combine(FPaths::GameSavedDir(), "SceneCaptures")),
|
||||
SaveToFolder(FPaths::Combine(FPaths::ProjectSavedDir(), "SceneCaptures")),
|
||||
FileName("capture_%05d.png") {}
|
||||
|
||||
void ASceneCaptureToDiskCamera::BeginPlay()
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "SceneCaptureCamera.h"
|
||||
#include "Sensor/SceneCaptureCamera.h"
|
||||
|
||||
#include "SceneCaptureToDiskCamera.generated.h"
|
||||
|
||||
UCLASS(Blueprintable,BlueprintType)
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "Carla.h"
|
||||
#include "Sensor.h"
|
||||
|
||||
ASensor::ASensor(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer),
|
||||
Id(0u) {}
|
||||
|
||||
void ASensor::AttachToActor(AActor *Actor)
|
||||
{
|
||||
check(Actor != nullptr);
|
||||
Super::AttachToActor(Actor, FAttachmentTransformRules::KeepRelativeTransform);
|
||||
SetOwner(Actor);
|
||||
Actor->AddTickPrerequisiteActor(this);
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GameFramework/Actor.h"
|
||||
|
||||
#include "Sensor/SensorDataSink.h"
|
||||
#include "Settings/SensorDescription.h"
|
||||
|
||||
#include "Sensor.generated.h"
|
||||
|
||||
/// Base class for sensors.
|
||||
UCLASS(Abstract, hidecategories=(Collision, Attachment, Actor))
|
||||
class CARLA_API ASensor : public AActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
ASensor(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
uint32 GetId() const
|
||||
{
|
||||
return Id;
|
||||
}
|
||||
|
||||
void AttachToActor(AActor *Actor);
|
||||
|
||||
void SetSensorDataSink(TSharedPtr<ISensorDataSink> InSensorDataSink)
|
||||
{
|
||||
SensorDataSink = InSensorDataSink;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void Set(const USensorDescription &SensorDescription)
|
||||
{
|
||||
Id = SensorDescription.GetId();
|
||||
}
|
||||
|
||||
void WriteSensorData(const FSensorDataView &SensorData)
|
||||
{
|
||||
if (SensorDataSink.IsValid()) {
|
||||
SensorDataSink->Write(SensorData);
|
||||
} else {
|
||||
UE_LOG(LogCarla, Warning, TEXT("Sensor %d has no data sink."), Id);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
uint32 Id;
|
||||
|
||||
TSharedPtr<ISensorDataSink> SensorDataSink = nullptr;
|
||||
};
|
|
@ -4,9 +4,15 @@
|
|||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "Carla.h"
|
||||
#include "CarlaGameState.h"
|
||||
#pragma once
|
||||
|
||||
class FSensorDataView;
|
||||
|
||||
/// Interface for sensor data sinks.
|
||||
class ISensorDataSink {
|
||||
public:
|
||||
|
||||
virtual ~ISensorDataSink() {}
|
||||
|
||||
virtual void Write(const FSensorDataView &SensorData) = 0;
|
||||
};
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Sensor/ReadOnlyBufferView.h"
|
||||
|
||||
/// A view over a sensor's output data. Does not own the data.
|
||||
class FSensorDataView {
|
||||
public:
|
||||
|
||||
FSensorDataView(
|
||||
uint32 InSensorId,
|
||||
FReadOnlyBufferView InHeader,
|
||||
FReadOnlyBufferView InData)
|
||||
: SensorId(InSensorId),
|
||||
Header(InHeader),
|
||||
Data(InData) {}
|
||||
|
||||
uint32 GetSensorId() const
|
||||
{
|
||||
return SensorId;
|
||||
}
|
||||
|
||||
FReadOnlyBufferView GetHeader() const
|
||||
{
|
||||
return Header;
|
||||
}
|
||||
|
||||
FReadOnlyBufferView GetData() const
|
||||
{
|
||||
return Data;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32 SensorId;
|
||||
|
||||
FReadOnlyBufferView Header;
|
||||
|
||||
FReadOnlyBufferView Data;
|
||||
};
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Carla.h"
|
||||
#include "SensorFactory.h"
|
||||
|
||||
#include "Sensor/Lidar.h"
|
||||
#include "Sensor/SceneCaptureCamera.h"
|
||||
#include "Settings/CameraDescription.h"
|
||||
#include "Settings/LidarDescription.h"
|
||||
|
||||
template <typename T, typename D>
|
||||
static T *SpawnSensor(const D &Description, UWorld &World)
|
||||
{
|
||||
FActorSpawnParameters Params;
|
||||
Params.Name = FName(*Description.Name);
|
||||
return World.SpawnActor<T>(Description.Position, Description.Rotation, Params);
|
||||
}
|
||||
|
||||
ASensor *FSensorFactory::Make(
|
||||
const USensorDescription &Description,
|
||||
UWorld &World)
|
||||
{
|
||||
FSensorFactory Visitor(World);
|
||||
Description.AcceptVisitor(Visitor);
|
||||
check(Visitor.Sensor != nullptr);
|
||||
return Visitor.Sensor;
|
||||
}
|
||||
|
||||
FSensorFactory::FSensorFactory(UWorld &World) : World(World) {}
|
||||
|
||||
void FSensorFactory::Visit(const UCameraDescription &Description)
|
||||
{
|
||||
auto Camera = SpawnSensor<ASceneCaptureCamera>(Description, World);
|
||||
Camera->Set(Description);
|
||||
UE_LOG(
|
||||
LogCarla,
|
||||
Log,
|
||||
TEXT("Created Capture Camera %d with postprocess \"%s\""),
|
||||
Camera->GetId(),
|
||||
*PostProcessEffect::ToString(Camera->GetPostProcessEffect()));
|
||||
Sensor = Camera;
|
||||
}
|
||||
|
||||
void FSensorFactory::Visit(const ULidarDescription &Description)
|
||||
{
|
||||
auto Lidar = SpawnSensor<ALidar>(Description, World);
|
||||
Lidar->Set(Description);
|
||||
UE_LOG(
|
||||
LogCarla,
|
||||
Log,
|
||||
TEXT("Created LiDAR %d"),
|
||||
Lidar->GetId());
|
||||
Sensor = Lidar;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Settings/SensorDescriptionVisitor.h"
|
||||
|
||||
class ASensor;
|
||||
class UWorld;
|
||||
|
||||
class FSensorFactory : private ISensorDescriptionVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
static ASensor *Make(
|
||||
const USensorDescription &Description,
|
||||
UWorld &World);
|
||||
|
||||
private:
|
||||
|
||||
FSensorFactory(UWorld &World);
|
||||
|
||||
virtual void Visit(const UCameraDescription &) final;
|
||||
|
||||
virtual void Visit(const ULidarDescription &) final;
|
||||
|
||||
UWorld &World;
|
||||
|
||||
ASensor *Sensor = nullptr;
|
||||
};
|
|
@ -0,0 +1,209 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "Carla.h"
|
||||
#include "CarlaEncoder.h"
|
||||
|
||||
#include "Agent/TrafficSignAgentComponent.h"
|
||||
#include "Agent/VehicleAgentComponent.h"
|
||||
#include "Agent/WalkerAgentComponent.h"
|
||||
#include "Game/CarlaPlayerState.h"
|
||||
#include "Settings/SensorDescription.h"
|
||||
|
||||
#include "GameFramework/PlayerStart.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
// =============================================================================
|
||||
// -- Static local methods -----------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
static auto MakeCharBuffer(const FString &String)
|
||||
{
|
||||
const char *Ptr = TCHAR_TO_ANSI(*String);
|
||||
auto Buffer = MakeUnique<char[]>(std::strlen(Ptr) + 1u); // + null terminator.
|
||||
std::strcpy(Buffer.Get(), Ptr);
|
||||
return TUniquePtr<const char[]>(Buffer.Release());
|
||||
}
|
||||
|
||||
static void Encode(const FVector &Vector, carla_vector3d &Data)
|
||||
{
|
||||
Data = {Vector.X, Vector.Y, Vector.Z};
|
||||
}
|
||||
|
||||
static void Encode(const FRotator &Rotator, carla_rotation3d &Data)
|
||||
{
|
||||
Data.pitch = Rotator.Pitch;
|
||||
Data.roll = Rotator.Roll;
|
||||
Data.yaw = Rotator.Yaw;
|
||||
}
|
||||
|
||||
static void Encode(const FTransform &Transform, carla_transform &Data)
|
||||
{
|
||||
Encode(Transform.GetLocation(), Data.location);
|
||||
Encode(Transform.GetRotation().GetForwardVector(), Data.orientation);
|
||||
Encode(Transform.Rotator(), Data.rotation);
|
||||
}
|
||||
|
||||
static TUniquePtr<const char[]> Encode(
|
||||
const USensorDescription &SensorDescription,
|
||||
carla_sensor_definition &Data)
|
||||
{
|
||||
Data.id = SensorDescription.GetId();
|
||||
Data.type = [](const FString &Type) {
|
||||
#define CARLA_CHECK_TYPE(Str) if (Type == TEXT(#Str)) return CARLA_SERVER_ ## Str;
|
||||
CARLA_CHECK_TYPE(CAMERA)
|
||||
CARLA_CHECK_TYPE(LIDAR_RAY_TRACE)
|
||||
else return CARLA_SERVER_SENSOR_UNKNOWN;
|
||||
#undef CARLA_CHECK_TYPE
|
||||
}(SensorDescription.Type);
|
||||
auto Memory = MakeCharBuffer(SensorDescription.Name);
|
||||
Data.name = Memory.Get();
|
||||
return Memory;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// -- FCarlaEncoder static methods ---------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
void FCarlaEncoder::Encode(
|
||||
const TArray<APlayerStart *> &AvailableStartSpots,
|
||||
TArray<carla_transform> &Data)
|
||||
{
|
||||
const int32 NumberOfStartSpots = AvailableStartSpots.Num();
|
||||
Data.AddUninitialized(NumberOfStartSpots);
|
||||
for (auto i = 0; i < NumberOfStartSpots; ++i) {
|
||||
check(AvailableStartSpots[i] != nullptr);
|
||||
::Encode(AvailableStartSpots[i]->GetActorTransform(), Data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void FCarlaEncoder::Encode(
|
||||
const TArray<USensorDescription *> &SensorDescriptions,
|
||||
TArray<carla_sensor_definition> &Data,
|
||||
TArray<TUniquePtr<const char[]>> &SensorNames)
|
||||
{
|
||||
const int32 NumberOfSensors = SensorDescriptions.Num();
|
||||
Data.AddUninitialized(NumberOfSensors);
|
||||
SensorNames.Reserve(NumberOfSensors);
|
||||
for (auto i = 0; i < NumberOfSensors; ++i) {
|
||||
check(SensorDescriptions[i] != nullptr);
|
||||
SensorNames.Emplace(::Encode(*SensorDescriptions[i], Data[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void FCarlaEncoder::Encode(
|
||||
const ACarlaPlayerState &PlayerState,
|
||||
carla_measurements &Data)
|
||||
{
|
||||
Data.platform_timestamp = PlayerState.GetPlatformTimeStamp();
|
||||
Data.game_timestamp = PlayerState.GetGameTimeStamp();
|
||||
auto &Player = Data.player_measurements;
|
||||
::Encode(PlayerState.GetTransform(), Player.transform);
|
||||
::Encode(PlayerState.GetAcceleration(), Player.acceleration);
|
||||
Player.forward_speed = PlayerState.GetForwardSpeed();
|
||||
Player.collision_vehicles = PlayerState.GetCollisionIntensityCars();
|
||||
Player.collision_pedestrians = PlayerState.GetCollisionIntensityPedestrians();
|
||||
Player.collision_other = PlayerState.GetCollisionIntensityOther();
|
||||
Player.intersection_otherlane = PlayerState.GetOtherLaneIntersectionFactor();
|
||||
Player.intersection_offroad = PlayerState.GetOffRoadIntersectionFactor();
|
||||
Player.autopilot_control.steer = PlayerState.GetSteer();
|
||||
Player.autopilot_control.throttle = PlayerState.GetThrottle();
|
||||
Player.autopilot_control.brake = PlayerState.GetBrake();
|
||||
Player.autopilot_control.hand_brake = PlayerState.GetHandBrake();
|
||||
Player.autopilot_control.reverse = PlayerState.GetCurrentGear() < 0;
|
||||
}
|
||||
|
||||
void FCarlaEncoder::Encode(
|
||||
const TArray<const UAgentComponent *> &Agents,
|
||||
TArray<carla_agent> &Data)
|
||||
{
|
||||
const int32 NumberOfAgents = Agents.Num();
|
||||
Data.AddUninitialized(NumberOfAgents);
|
||||
for (auto i = 0; i < NumberOfAgents; ++i) {
|
||||
check(Agents[i] != nullptr);
|
||||
Encode(*Agents[i], Data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void FCarlaEncoder::Encode(const UAgentComponent &AgentComponent, carla_agent &AgentData)
|
||||
{
|
||||
AgentData.id = AgentComponent.GetId();
|
||||
::Encode(AgentComponent.GetComponentTransform(), AgentData.transform);
|
||||
FCarlaEncoder Encoder(AgentData);
|
||||
AgentComponent.AcceptVisitor(Encoder);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// -- FCarlaEncoder ------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
FCarlaEncoder::FCarlaEncoder(carla_agent &InData) : Data(InData) {}
|
||||
|
||||
void FCarlaEncoder::Visit(const UTrafficSignAgentComponent &Agent)
|
||||
{
|
||||
auto &TrafficSign = Agent.GetTrafficSign();
|
||||
switch (TrafficSign.GetTrafficSignState()) {
|
||||
case ETrafficSignState::TrafficLightRed:
|
||||
Data.type = CARLA_SERVER_AGENT_TRAFFICLIGHT_RED;
|
||||
break;
|
||||
case ETrafficSignState::TrafficLightYellow:
|
||||
Data.type = CARLA_SERVER_AGENT_TRAFFICLIGHT_YELLOW;
|
||||
break;
|
||||
case ETrafficSignState::TrafficLightGreen:
|
||||
Data.type = CARLA_SERVER_AGENT_TRAFFICLIGHT_GREEN;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_30:
|
||||
Data.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
Data.forward_speed = 30.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_40:
|
||||
Data.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
Data.forward_speed = 40.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_50:
|
||||
Data.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
Data.forward_speed = 50.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_60:
|
||||
Data.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
Data.forward_speed = 60.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_90:
|
||||
Data.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
Data.forward_speed = 90.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_100:
|
||||
Data.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
Data.forward_speed = 100.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_120:
|
||||
Data.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
Data.forward_speed = 120.0f;
|
||||
break;
|
||||
case ETrafficSignState::SpeedLimit_130:
|
||||
Data.type = CARLA_SERVER_AGENT_SPEEDLIMITSIGN;
|
||||
Data.forward_speed = 130.0f;
|
||||
break;
|
||||
default:
|
||||
UE_LOG(LogCarla, Error, TEXT("Unknown traffic sign!"));
|
||||
}
|
||||
}
|
||||
|
||||
void FCarlaEncoder::Visit(const UVehicleAgentComponent &Agent)
|
||||
{
|
||||
auto &Vehicle = Agent.GetVehicle();
|
||||
Data.type = CARLA_SERVER_AGENT_VEHICLE;
|
||||
Data.forward_speed = Vehicle.GetVehicleForwardSpeed();
|
||||
::Encode(Vehicle.GetVehicleBoundsExtent(), Data.box_extent);
|
||||
}
|
||||
|
||||
void FCarlaEncoder::Visit(const UWalkerAgentComponent &Agent)
|
||||
{
|
||||
Data.type = CARLA_SERVER_AGENT_PEDESTRIAN;
|
||||
Data.forward_speed = Agent.GetForwardSpeed();
|
||||
::Encode(Agent.GetBoundingBoxExtent(), Data.box_extent);
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Agent/AgentComponentVisitor.h"
|
||||
|
||||
#include "Sensor/SensorDataView.h"
|
||||
#include "Vehicle/VehicleControl.h"
|
||||
|
||||
#include <carla/carla_server.h>
|
||||
|
||||
/// Encodes Unreal classes to CarlaServer API. To be used by FCarlaServer only.
|
||||
class FCarlaEncoder : private IAgentComponentVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
static void Encode(
|
||||
const TArray<APlayerStart *> &AvailableStartSpots,
|
||||
TArray<carla_transform> &Data);
|
||||
|
||||
static void Encode(
|
||||
const TArray<USensorDescription *> &SensorDescriptions,
|
||||
TArray<carla_sensor_definition> &Data,
|
||||
TArray<TUniquePtr<const char[]>> &SensorNamesMemory);
|
||||
|
||||
static void Encode(
|
||||
const ACarlaPlayerState &PlayerState,
|
||||
carla_measurements &Data);
|
||||
|
||||
static void Encode(
|
||||
const TArray<const UAgentComponent *> &Agents,
|
||||
TArray<carla_agent> &Data);
|
||||
|
||||
static void Encode(const FSensorDataView &SensorData, carla_sensor_data &Data)
|
||||
{
|
||||
Data.id = SensorData.GetSensorId();
|
||||
Data.header = SensorData.GetHeader().GetData();
|
||||
Data.header_size = SensorData.GetHeader().GetSize();
|
||||
Data.data = SensorData.GetData().GetData();
|
||||
Data.data_size = SensorData.GetData().GetSize();
|
||||
}
|
||||
|
||||
static void Decode(const carla_request_new_episode &Data, FString &IniFile)
|
||||
{
|
||||
IniFile = FString(Data.ini_file_length, ANSI_TO_TCHAR(Data.ini_file));
|
||||
}
|
||||
|
||||
static void Decode(const carla_control &Data, FVehicleControl &Control)
|
||||
{
|
||||
Control.Steer = Data.steer;
|
||||
Control.Throttle = Data.throttle;
|
||||
Control.Brake = Data.brake;
|
||||
Control.bHandBrake = Data.hand_brake;
|
||||
Control.bReverse = Data.reverse;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void Encode(const UAgentComponent &AgentComponent, carla_agent &Data);
|
||||
|
||||
FCarlaEncoder(carla_agent &Data);
|
||||
|
||||
virtual void Visit(const UTrafficSignAgentComponent &) override;
|
||||
|
||||
virtual void Visit(const UVehicleAgentComponent &) override;
|
||||
|
||||
virtual void Visit(const UWalkerAgentComponent &) override;
|
||||
|
||||
carla_agent &Data;
|
||||
};
|
|
@ -0,0 +1,165 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "Carla.h"
|
||||
#include "CarlaServer.h"
|
||||
|
||||
#include "Server/CarlaEncoder.h"
|
||||
|
||||
#include <carla/carla_server.h>
|
||||
|
||||
// =============================================================================
|
||||
// -- Static local methods -----------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
static FCarlaServer::ErrorCode ParseErrorCode(const uint32 ErrorCode)
|
||||
{
|
||||
if (ErrorCode == CARLA_SERVER_SUCCESS) {
|
||||
return FCarlaServer::Success;
|
||||
} else if (ErrorCode == CARLA_SERVER_TRY_AGAIN) {
|
||||
return FCarlaServer::TryAgain;
|
||||
} else {
|
||||
return FCarlaServer::Error;
|
||||
}
|
||||
}
|
||||
|
||||
static int32 GetTimeOut(uint32 TimeOut, const bool bBlocking)
|
||||
{
|
||||
return (bBlocking ? TimeOut : 0u);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// -- CarlaServer --------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
FCarlaServer::FCarlaServer(const uint32 InWorldPort, const uint32 InTimeOut) :
|
||||
WorldPort(InWorldPort),
|
||||
TimeOut(InTimeOut),
|
||||
Server(carla_make_server()) {
|
||||
check(Server != nullptr);
|
||||
}
|
||||
|
||||
FCarlaServer::~FCarlaServer()
|
||||
{
|
||||
#ifdef CARLA_SERVER_EXTRA_LOG
|
||||
UE_LOG(LogCarlaServer, Warning, TEXT("Destroying CarlaServer"));
|
||||
#endif // CARLA_SERVER_EXTRA_LOG
|
||||
carla_free_server(Server);
|
||||
}
|
||||
|
||||
FCarlaServer::ErrorCode FCarlaServer::Connect()
|
||||
{
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Waiting for the client to connect..."));
|
||||
return ParseErrorCode(carla_server_connect(Server, WorldPort, TimeOut));
|
||||
}
|
||||
|
||||
FCarlaServer::ErrorCode FCarlaServer::ReadNewEpisode(FString &IniFile, const bool bBlocking)
|
||||
{
|
||||
carla_request_new_episode values;
|
||||
auto ec = ParseErrorCode(carla_read_request_new_episode(Server, values, GetTimeOut(TimeOut, bBlocking)));
|
||||
if (Success == ec) {
|
||||
FCarlaEncoder::Decode(values, IniFile);
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Received new episode"));
|
||||
#ifdef CARLA_SERVER_EXTRA_LOG
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Received CarlaSettings.ini:\n%s"), *IniFile);
|
||||
#endif // CARLA_SERVER_EXTRA_LOG
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
|
||||
FCarlaServer::ErrorCode FCarlaServer::SendSceneDescription(
|
||||
const TArray<APlayerStart *> &AvailableStartSpots,
|
||||
const TArray<USensorDescription *> &SensorDescriptions,
|
||||
const bool bBlocking)
|
||||
{
|
||||
carla_scene_description scene;
|
||||
// Encode start spots.
|
||||
TArray<carla_transform> Transforms;
|
||||
FCarlaEncoder::Encode(AvailableStartSpots, Transforms);
|
||||
scene.player_start_spots = (Transforms.Num() > 0 ? Transforms.GetData() : nullptr);;
|
||||
scene.number_of_player_start_spots = Transforms.Num();
|
||||
// Encode sensors.
|
||||
TArray<TUniquePtr<const char[]>> SensorNames; // This holds the memory while we send it.
|
||||
TArray<carla_sensor_definition> Sensors;
|
||||
FCarlaEncoder::Encode(SensorDescriptions, Sensors, SensorNames);
|
||||
scene.sensors = (Sensors.Num() > 0 ? Sensors.GetData() : nullptr);;
|
||||
scene.number_of_sensors = Sensors.Num();
|
||||
// Send scene description.
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Sending %d available start positions"), scene.number_of_player_start_spots);
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Sending %d sensor descriptions"), scene.number_of_sensors);
|
||||
return ParseErrorCode(carla_write_scene_description(Server, scene, GetTimeOut(TimeOut, bBlocking)));
|
||||
}
|
||||
|
||||
FCarlaServer::ErrorCode FCarlaServer::ReadEpisodeStart(uint32 &StartPositionIndex, const bool bBlocking)
|
||||
{
|
||||
carla_episode_start values;
|
||||
auto ec = ParseErrorCode(carla_read_episode_start(Server, values, GetTimeOut(TimeOut, bBlocking)));
|
||||
if (Success == ec) {
|
||||
StartPositionIndex = values.player_start_spot_index;
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Episode start received: { StartIndex = %d }"), StartPositionIndex);
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
|
||||
FCarlaServer::ErrorCode FCarlaServer::SendEpisodeReady(const bool bBlocking)
|
||||
{
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Ready to play, notifying client"));
|
||||
const carla_episode_ready values = {true};
|
||||
return ParseErrorCode(carla_write_episode_ready(Server, values, GetTimeOut(TimeOut, bBlocking)));
|
||||
}
|
||||
|
||||
FCarlaServer::ErrorCode FCarlaServer::ReadControl(FVehicleControl &Control, const bool bBlocking)
|
||||
{
|
||||
carla_control values;
|
||||
auto ec = ParseErrorCode(carla_read_control(Server, values, GetTimeOut(TimeOut, bBlocking)));
|
||||
if (Success == ec) {
|
||||
#ifdef CARLA_SERVER_EXTRA_LOG
|
||||
UE_LOG(
|
||||
LogCarlaServer,
|
||||
Log,
|
||||
TEXT("Read control (%s): { Steer = %f, Throttle = %f, Brake = %f, Handbrake = %s, Reverse = %s }"),
|
||||
(bBlocking ? TEXT("Sync") : TEXT("Async")),
|
||||
values.steer,
|
||||
values.throttle,
|
||||
values.brake,
|
||||
(values.hand_brake ? TEXT("True") : TEXT("False")),
|
||||
(values.reverse ? TEXT("True") : TEXT("False")));
|
||||
#endif // CARLA_SERVER_EXTRA_LOG
|
||||
FCarlaEncoder::Decode(values, Control);
|
||||
} else if ((!bBlocking) && (TryAgain == ec)) {
|
||||
UE_LOG(LogCarlaServer, Warning, TEXT("No control received from the client this frame!"));
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
|
||||
FCarlaServer::ErrorCode FCarlaServer::SendSensorData(const FSensorDataView &Data)
|
||||
{
|
||||
carla_sensor_data values;
|
||||
FCarlaEncoder::Encode(Data, values);
|
||||
return ParseErrorCode(carla_write_sensor_data(Server, values));
|
||||
}
|
||||
|
||||
FCarlaServer::ErrorCode FCarlaServer::SendMeasurements(
|
||||
const ACarlaPlayerState &PlayerState,
|
||||
const TArray<const UAgentComponent *> &Agents,
|
||||
const bool bSendNonPlayerAgentsInfo)
|
||||
{
|
||||
// Encode measurements.
|
||||
carla_measurements values;
|
||||
FCarlaEncoder::Encode(PlayerState, values);
|
||||
// Encode agents.
|
||||
TArray<carla_agent> AgentsData;
|
||||
if (bSendNonPlayerAgentsInfo) {
|
||||
FCarlaEncoder::Encode(Agents, AgentsData);
|
||||
}
|
||||
values.non_player_agents = (AgentsData.Num() > 0 ? AgentsData.GetData() : nullptr);;
|
||||
values.number_of_non_player_agents = AgentsData.Num();
|
||||
// Send measurements.
|
||||
#ifdef CARLA_SERVER_EXTRA_LOG
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Sending data of %d agents"), values.number_of_non_player_agents);
|
||||
#endif // CARLA_SERVER_EXTRA_LOG
|
||||
return ParseErrorCode(carla_write_measurements(Server, values));
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue