merged with carla master after 0.7.0

This commit is contained in:
Anton Pechenko 2017-12-05 14:47:52 +03:00
commit 56c65871e5
64 changed files with 2874 additions and 1361 deletions

2
.gitignore vendored
View File

@ -18,9 +18,9 @@ Util/Build
*.workspace *.workspace
*CodeCompletionFolders.txt *CodeCompletionFolders.txt
*CodeLitePreProcessor.txt *CodeLitePreProcessor.txt
*_pb2.py
.codelite .codelite
.tags* .tags*
.vs .vs
__pycache__ __pycache__
_images
core core

View File

@ -42,7 +42,8 @@
"settings": "settings":
{ {
"tab_size": 2, "tab_size": 2,
"translate_tabs_to_spaces": true "translate_tabs_to_spaces": true,
"trim_trailing_white_space_on_save": true
}, },
"build_systems": "build_systems":
[ [

View File

@ -1,8 +1,25 @@
## CARLA 0.7.0
* New Python client API
- Cleaner and more robust
- Compatible with Python 2 and 3
- Improved exception handling
- Improved examples
- Included methods for parsing the images
- Better documentation
- Protocol: renamed "ai_control" to "autopilot_control"
- Merged testing client
- Added the maps for both cities, the client can now access the car position within the lane.
* Make CARLA start without client by default
* Added wind effect to some trees and plants
* Improvements to the existing weather presets
* Build script: skip content download if up-to-date
## CARLA 0.6.0 ## CARLA 0.6.0
* Included Unreal project and reorganised folders * Included Unreal project and reorganised folders
* Enabled semantic segmentation by default * Enabled semantic segmentation by default
* Added Felipe's Pyhton client * Added Felipe's Python client
* New build system (Linux only) * New build system (Linux only)
* Few fixes to city assets * Few fixes to city assets

View File

@ -8,16 +8,11 @@ started (every time the level is loaded).
Settings are loaded following the next hierarchy, with values later in the Settings are loaded following the next hierarchy, with values later in the
hierarchy overriding earlier values. hierarchy overriding earlier values.
1. `{ProjectFolder}/Config/CarlaSettings.ini` 1. `{CarlaFolder}/Unreal/CarlaUE4/Config/CarlaSettings.ini`.
2. File provided by command-line argument `-carla-settings=<path-to-ini-file>` 2. File provided by command-line argument `-carla-settings="Path/To/CarlaSettings.ini"`.
3. Other command-line arguments as `-world-port`, or `-carla-no-networking` 3. Other command-line arguments as `-carla-server` or `-world-port`.
4. Settings file sent by the client on every new episode. 4. Settings file sent by the client on every new episode.
Take a look at the [CARLA Settings example][settingslink]. Take a look at the [CARLA Settings example][settingslink].
[settingslink]: https://github.com/carla-simulator/carla/blob/master/Docs/Example.CarlaSettings.ini [settingslink]: https://github.com/carla-simulator/carla/blob/master/Docs/Example.CarlaSettings.ini
!!! tip
If you are in editor, you most probably want to disable networking.
Otherwise the game will hang until a client connects. Set
`UseNetworking=false` in "./Unreal/CarlaUE4/Config/CarlaSettings.ini".

35
Docs/faq.md Normal file
View File

@ -0,0 +1,35 @@
CARLA F.A.Q.
============
#### What is the expected disk space needed for building CARLA?
Building CARLA from source requires about 15GB of disk space, not counting
Unreal Engine installation.
However, you will also need to build and install Unreal Engine, which on Linux
requires much more disk space as it keeps all the intermediate files,
[see this thread](https://answers.unrealengine.com/questions/430541/linux-engine-size.html).
#### Is it possible to dump images from the CARLA server view?
Yes, this is an Unreal Engine feature. You can dump the images of the server
camera by running CARLA with
$ ./CarlaUE4.sh -benchmark -fps=30 -dumpmovie
Images are saved to "CarlaUE4/Saved/Screenshots/LinuxNoEditor".
#### I downloaded CARLA source from GitHub, where is the "CarlaUE4.sh" script?
There is no "CarlaUE4.sh" script in the source version of CARLA, you need to
follow the instructions in the [documentation](http://carla.readthedocs.io) on
building CARLA from source.
Once you open the project in the Unreal Editor, you can hit Play to test CARLA.
#### How can I create a binary version of CARLA?
To compile a binary (packaged) version of CARLA, open the CarlaUE4 project with
Unreal Editor, go to the menu “File -> Package Project”, and select your
platform. This takes a while, but in the end it should generate a packaged
version of CARLA to execute without Unreal Editor.

View File

@ -6,7 +6,7 @@ How to build CARLA on Linux
Install the build tools and dependencies Install the build tools and dependencies
$ sudo apt-get install build-essential clang-3.9 git cmake ninja-build python3-pip python3-requests python-dev tzdata curl wget unzip autoconf libtool $ sudo apt-get install build-essential clang-3.9 git cmake ninja-build python3-pip python3-requests python-dev tzdata sed curl wget unzip autoconf libtool
$ sudo pip3 install protobuf $ sudo pip3 install protobuf
To avoid compatibility issues between Unreal Engine and the CARLA dependencies, To avoid compatibility issues between Unreal Engine and the CARLA dependencies,
@ -74,6 +74,15 @@ use the Makefile generated in the Unreal project folder
$ cd Unreal/CarlaUE4 $ cd Unreal/CarlaUE4
$ make CarlaUE4Editor $ make CarlaUE4Editor
Updating CARLA
--------------
Every new release of CARLA we release a new package with the latest changes in
the CARLA assets. To download the latest version, run the "Update" script
$ git pull
$ ./Update.sh
Launching the editor Launching the editor
-------------------- --------------------

View File

@ -7,79 +7,88 @@ CARLA Simulator
Welcome to CARLA simulator. Welcome to CARLA simulator.
This file contains the instructions to run the CARLA simulator binaries on This file contains the instructions to run the CARLA simulator binaries on
Linux. [Get the latest release here.][releaselink] Linux.
[Get the latest release here.][releaselink]
For building CARLA from source, please check out the For building CARLA from source, please check out the
[CARLA Documentation][docslink]. [CARLA Documentation][docslink].
CARLA can be run directly by running the "CarlaUE4.sh" script provided in the
release package.
There are currently two scenarios available, the desired scenario can be chosen
from the command-line
$ ./CarlaUE4.sh /Game/Maps/Town01
or
$ ./CarlaUE4.sh /Game/Maps/Town02
To run CARLA as server, see ["Running the server"](#running-the-server) below.
[releaselink]: https://github.com/carla-simulator/carla/releases/latest [releaselink]: https://github.com/carla-simulator/carla/releases/latest
[docslink]: http://carla.readthedocs.io [docslink]: http://carla.readthedocs.io
Running the Python client Running the Python client
------------------------- -------------------------
Requires Python 3 with some extra modules installed The "carla" Python module provides a basic API for communicating with the CARLA
server. In the "PythonClient" folder we provide a couple of examples on how to
use this API. We recommend Python 3, but they are also compatible with Python 2.
The basic functionality requires only the protobuf module to be installed
$ sudo apt-get install python3 python3-pip $ sudo apt-get install python3 python3-pip
$ sudo pip3 install protobuf numpy Pillow $ sudo pip3 install protobuf
A sample Python script is provided at `PythonClient/client_example.py`. The However, other operations as handling images require some extra modules, and the
script is well commented explaining how to use the client API. "manual_control.py" example requires pygame
The script can be run and provides basic functionality for controlling the $ sudo pip3 install numpy Pillow pygame
vehicle and saving images to disk. Run the help command to see options available
$ ./carla_example.py --help The script "PythonClient/client_example.py" provides basic functionality for
controlling the vehicle and saving images to disk. Run the help command to see
options available
A second Python script is provided at `PythonClient/carla_manual_control.py`. $ ./client_example.py --help
The script is pygame dependent and serves as an interactive example where the
user controls the car with a keyboard.
$ sudo apt-get install python3-tk The script "PythonClient/manual_control.py" launches a PyGame window with
$ sudo pip3 install pygame matplolib several views and allows to control the vehicle using the WASD keys.
Run the help command to see options available $ ./manual_control.py --help
$ ./carla_manual_control.py --help
Running the server Running the server
------------------ ------------------
!!! note The server can be started by running the "CarlaUE4.sh" script with some extra
By default the game starts in networking mode. It will hang until a client arguments. When run in server mode (controlled by the CARLA client), it is
is connected. See below how to run it without client. highly recommended to run it at fixed time-step
The server can be started by running the `CarlaUE4.sh` script. When run in $ ./CarlaUE4.sh /Game/Maps/Town01 -carla-server -benchmark -fps=15
networking mode (controlled by the CARLA client), it is highly recommended to
run it at fixed time-step
$ ./CarlaUE4.sh /Game/Maps/Town01 -benchmark -fps=15
The arguments `-benchmark -fps=15` make the engine run at a fixed time-step of The arguments `-benchmark -fps=15` make the engine run at a fixed time-step of
1/15 seconds. In this mode, game-time decouples from real-time and the 1/15 seconds. In this mode, game-time decouples from real-time and the
simulation runs as fast as possible. simulation runs as fast as possible.
To run the game on the second city, just change the command to select the To run the game on the second town, just change the command to select the
"Town02" "Town02" map
$ ./CarlaUE4.sh /Game/Maps/Town02 -benchmark -fps=15 $ ./CarlaUE4.sh /Game/Maps/Town02 -carla-server -benchmark -fps=15
To run the game windowed at a given resolution When run as server, it is sometimes useful to run the game in a smaller window,
this can be chosen with
$ ./CarlaUE4.sh /Game/Maps/Town01 -benchmark -fps=15 -windowed -ResX=800 -ResY=600 $ ./CarlaUE4.sh /Game/Maps/Town01 -carla-server -benchmark -fps=15 -windowed -ResX=800 -ResY=600
The game can also be run without a client, this way you can drive around the #### CARLA specific command-line options
city just using the keyboard (in this mode is not recommended to use fixed
frame-rate to get a more realistic feeling)
$ ./CarlaUE4.sh /Game/Maps/Town02 -carla-no-networking * `-carla-server` Launches CARLA as server, the execution hangs until a client connects.
* `-carla-settings="Path/To/CarlaSettings.ini"` Load settings from the given INI file. See Example.CarlaSettings.ini.
#### CARLA command-line options * `-carla-world-port=N` Listen for client connections at port N, agent ports are set to N+1 and N+2 respectively. Activates server.
* `-carla-settings=<ini-file-path>` Load settings from the given INI file. See Example.CarlaSettings.ini.
* `-carla-world-port=<port-number>` Listen for client connections at <port-number>, agent ports are set to <port-number>+1 and <port-number>+2 respectively. Activates networking.
* `-carla-no-networking` Disable networking. Overrides other settings.
* `-carla-no-hud` Do not display the HUD by default. * `-carla-no-hud` Do not display the HUD by default.
* `-carla-no-networking` Disable networking. Overrides `-carla-server` if present.
#### Running CARLA off-screen #### Running CARLA off-screen
@ -134,9 +143,9 @@ started (every time the level is loaded).
Settings are loaded following the next hierarchy, with values later in the Settings are loaded following the next hierarchy, with values later in the
hierarchy overriding earlier values. hierarchy overriding earlier values.
1. `{ProjectFolder}/Config/CarlaSettings.ini` 1. `{ProjectFolder}/Config/CarlaSettings.ini`.
2. File provided by command-line argument `-carla-settings=<path-to-ini-file>` 2. File provided by command-line argument `-carla-settings="Path/To/CarlaSettings.ini"`.
3. Other command-line arguments as `-world-port`, or `-carla-no-networking` 3. Other command-line arguments as `-carla-server` or `-world-port`.
4. Settings file sent by the client on every new episode. 4. Settings file sent by the client on every new episode.
Take a look at the Example.CarlaSettings.ini file for further details. Take a look at the Example.CarlaSettings.ini file for further details.

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

View File

@ -7,6 +7,8 @@ CARLA Documentation
* [CARLA settings](carla_settings.md) * [CARLA settings](carla_settings.md)
* [Measurements](measurements.md) * [Measurements](measurements.md)
* [Cameras and sensors](cameras_and_sensors.md) * [Cameras and sensors](cameras_and_sensors.md)
* [F.A.Q.](faq.md)
* [Troubleshooting](troubleshooting.md) * [Troubleshooting](troubleshooting.md)
#### Building from source #### Building from source
@ -17,5 +19,6 @@ CARLA Documentation
#### Development #### Development
* [Map customization](map_customization.md)
* [How to add assets](how_to_add_assets.md) * [How to add assets](how_to_add_assets.md)
* [CarlaServer documentation](carla_server.md) * [CarlaServer documentation](carla_server.md)

93
Docs/map_customization.md Normal file
View File

@ -0,0 +1,93 @@
# Map customization
This are the specific blueprint assets created to help building the environment.
## MultipleFloorBuilding:
The purpose of this blueprint is to make repeating and varying tall buildings a bit easier. Provided a Base, a MiddleFloor and a roof; this blueprint repeats the middle floor to the desired number of stores and tops it whith the last floor given some conditions:
- All model pivots should be in the bottom center of the Specific mesh.
- Al models must start and end exactly where the repetition happen.
This blueprint is controlled by this 6 specific Parameters:
- GroundFloor: The mesh to be placed in the base of the building.
- Floor: The mesh to be repeated along the building.
- Roof: Final mesh to top the building.
- FloorNumber: Number of stores of the building.
- FloorHeightOffset: Adjust The placement of every floor verticaly.
- RoofOffset: Adjust the placement of the roof verticaly.
All of This parameters can be modified once this blueprint is placed in the world.
## SplinemeshRepeater:
!!! Bug
See [#35 SplineMeshRepeater loses its collider mesh](https://github.com/carla-simulator/carla/issues/35)
### Standard use:
SplineMeshRepeater "Content/Blueprints/SplineMeshRepeater" is a tool included in the Carla Project to help building urban environments; It repeats and aligns a specific choosen mesh along a [Spline](https://docs.unrealengine.com/latest/INT/Engine/BlueprintSplines/Reference/SplineEditorTool/index.html) (Unreal Component). Its principal function is to build Tipicaly tiled and repetitive structures as Walls, Roads, Bridges, Fences... Once the actor is placed into the world the spline can be modified so the object gets the desired form. Each Point Defining the spline Generates a new tile so that as more points the Spline has, the more defined it will be, but also heavyer on the world. This actor is defined by the following parameters:
- StaticMesh: The mesh to be repeated along the spline.
- ForWardAxis: Changes the mesh axis to be alingned with the spline.
- Material: Overrides the mesh' default material.
- Colission Enabled: Chooses the tipe of colission to use.
- Gap distance: Places a Gap between each repeated mesh, for repetitive non continuous walls: bush chains, bollards...
(Last three variables are specific for some particular assets to be defined in the next point) A requisite to create assets compatibles with this componenis is that all the meshes have their pivot placed wherever the repetition starts in the lower point possible with the rest of the mesh pointing positive (Preferably by the X axis)
### Specific Walls (Dynamic material)
In the project folder "Content/Static/Walls" are included some specific assets to be used with this SplineMeshRepeater with a series of special caracteristics. The uv space of this meshes and their materials are the same for all of them, making them excangeable. each material is composed of three different surfaces the last three parameters slightly modify the color of this surfaces:
- MainMaterialColor: Change the main material of the Wall
- DetailsColor: Change the color of the details (if any)
- TopWallColor: Cambia el color de la cubierta del muro (if any)
To add elements that profit from this functions exist in the (Carpeta) folder the GardenWallMask File that defines the uv space to place the materials: (Blue space: MainMaterial; green space: Details; red space TopWall).
Between the material masters is WallMaster which is going to be the master of the materials using this function. An instance of this material will be created and the correspondent textures will be added. This material includes the following parameters to be modified by the material to use:
- Normal Flattener: Slightly modifies the normal map values to exagerate it or flatten it.
- RoughnessCorrection: Para corregir El valor de rugosidad dado por la textura.
The rest of the parameters are the mask the textures and the color corrections that won't be modified in this instance but in the blueprint that will be launched into the world.
## Weather
This is the actor in charge of modifying all the lighting, environmental actors an anything that affects the impression of the climate. It runs automaticaly with the game when is not specified otherwise In the Config.Ini but has Its own actor to launch in editor mode to configure the climatic conditions. To fuly work It will need One of each of the folowing actors: SkySphere, Skylight, Postprocess Volume (Boundless) And Light Source to exist in the world.
- SunPolarAngle: polar angle of the sun, determines time of the day
- SunAzimuthAngle: adds to the location of the sun in the current level
- SunBrightness: Brightness of the rendering of the sun in the skybox
- SunDirectionalLightIntensity: Intensity of the sunlight
- SunDirectionalLightColor: Color of the sunlight
- SunIndirectLightIntensity: intensity of the bounces of the main light
- CloudOpacity: visivility of the cloud rendering on the skybox
- HorizontFalloff: determines the height of the gradient between the zenith and horizon color
- ZenithColor: Defines the color of the zenith.
- HorizonColor: Defines the color of the horizon.
- CloudColor: Defines the color of the Clouds, if any.
- OverallSkyColor: multiplies every colored element in the sky by a single color.
- SkyLightIntensity: Intensity of the light bounced from the sky.
- SkyLightColor: Color of the light bounced from the sky.
- Precipitation: Defines if any precipitation is active.
- PrecipitationType: the type of precipitation to active.
- PrecipitationAmount: the quantity of the chosen precipitation.
- PrecipitationAccumulation: the acumulation of the chosen precipitation.
- bWind: defines if there is any wind.
- WindIntensity: defines the wind intensity.
- WindAngle: defines the wind direction.
- bOverrideCameraPostProcessParameters: Defines if the default camera postprocess is overwritten.
- CameraPostProcessParameters.AutoExposureMethod: Defines the method of autoexposure.
- CameraPostProcessParameters.AutoExposureMinBrightness: defines the minimum brightness the autoexposure will count as right in the final image.
- CameraPostProcessParameters.AutoExposureMaxBrightness: defines the maximum brightness the autoexposure will count as right in the final image.
- CameraPostProcessParameters.AutoExposureBias: Darkens or brightens the final image towards a defined bias.
You can have as many different configurations saved in the proyect as you want and choose the configuration to aply while on the build, through the [settings file](carla_settings.md); or in the editor while building the level or testing.

View File

@ -33,7 +33,7 @@ collision_pedestrians | float | Collision intensity with pedestrians.
collision_other | float | General collision intensity (everything else but pedestrians and vehicles). collision_other | float | General collision intensity (everything else but pedestrians and vehicles).
intersection_otherlane | float | Percentage of the car invading other lanes. intersection_otherlane | float | Percentage of the car invading other lanes.
intersection_offroad | float | Percentage of the car off-road. intersection_offroad | float | Percentage of the car off-road.
ai_control | Control | Vehicle's AI control that would apply this frame. autopilot_control | Control | Vehicle's autopilot control that would apply this frame.
###### Transform ###### Transform
@ -67,10 +67,10 @@ rectangle) against the map image of the city. These images are generated in the
editor and serialized for runtime use. You can find them too in the release editor and serialized for runtime use. You can find them too in the release
package under the folder "RoadMaps". package under the folder "RoadMaps".
###### AI control ###### Autopilot control
The `ai_control` measurement contains the control values that the in-game AI The `autopilot_control` measurement contains the control values that the in-game
would apply if it were controlling the vehicle. autopilot system would apply as if it were controlling the vehicle.
This is the same structure used to send the vehicle control to the server. This is the same structure used to send the vehicle control to the server.
@ -82,6 +82,16 @@ brake | float | Brake input between [ 0.0, 1.0]
hand_brake | bool | Whether the hand-brake is engaged hand_brake | bool | Whether the hand-brake is engaged
reverse | bool | Whether the vehicle is in reverse gear reverse | bool | Whether the vehicle is in reverse gear
To activate the autopilot from the client, send this `autopilot_control` back
to the server. Note that you can modify it before sending it back.
```py
measurements, sensor_data = carla_client.read_data()
control = measurements.player_measurements.autopilot_control
# modify here control if wanted.
carla_client.send_control(control)
```
(*) The actual steering angle depends on the vehicle used. The default Mustang (*) The actual steering angle depends on the vehicle used. The default Mustang
has a maximum steering angle of 70 degrees (this can be checked in the vehicle's has a maximum steering angle of 70 degrees (this can be checked in the vehicle's
front wheel blueprint). front wheel blueprint).
@ -102,10 +112,22 @@ If enabled, the server attaches a list of agents to the measurements package
every frame. Each of these agents has an unique id that identifies it, and every frame. Each of these agents has an unique id that identifies it, and
belongs to one of the following classes belongs to one of the following classes
* **Vehicle** Contains its transform, bounding-box, and forward speed. * **Vehicle** Contains its transform, box-extent, and forward speed.
* **Pedestrian** Contains its transform, bounding-box, and forward speed. (*) * **Pedestrian** Contains its transform, box-extent, and forward speed. (*)
* **Traffic light** Contains its transform and state (green, yellow, red). * **Traffic light** Contains its transform and state (green, yellow, red).
* **Speed-limit sign** Contains its transform and speed-limit. * **Speed-limit sign** Contains its transform and speed-limit.
(*) At this point every pedestrian is assumed to have the same bounding-box (*) At this point every pedestrian is assumed to have the same bounding-box
size. size.
###### Transform and bounding box
The transform defines the location and orientation of the agent. The bounding
box is assumed to be centered at the agent's location. The box extent gives the
radii dimensions of the bounding box of the agent.
![Vehicle Bounding Box](img/vehicle_bounding_box.png)
!!! important
As seen in the picture, the Z coordinate of the box is not fitted to
vehicle's height.

10
Docs/release_readme.md Normal file
View File

@ -0,0 +1,10 @@
CARLA Simulator
===============
Thanks for downloading CARLA!
Execute "CarlaUE4.sh" to launch CARLA.
For more details and running options please refer to our online documentation
http://carla.readthedocs.io

View File

@ -3,12 +3,26 @@ Troubleshooting
#### Editor hangs after hitting Play #### Editor hangs after hitting Play
By default, when CARLA is started it waits for a client to be connected and This is most probably happening because CARLA is started in server mode. Check
control the vehicle. This is the intended behavior. This can be changed in in your CarlaSettings.ini file ("./Unreal/CarlaUE4/Config/CarlaSettings.ini")
"./Unreal/CarlaUE4/Config/CarlaSettings.ini" changing `UseNetworking=false`. and set
```ini
[CARLA/Server]
UseNetworking=false
```
#### Very low FPS in editor when not in focus #### Very low FPS in editor when not in focus
UE4 Editor goes to a low performance mode when out of focus. It can be disabled UE4 Editor goes to a low performance mode when out of focus. It can be disabled
in the editor preferences. Go to "Edit->Editor Preferences->Performance" and in the editor preferences. Go to "Edit->Editor Preferences->Performance" and
disable the "Use Less CPU When in Background" option. disable the "Use Less CPU When in Background" option.
#### Fatal error: file '/usr/include/linux/version.h' has been modified since the precompiled header
This happens from time to time due to Linux updates. It is possible to force a
rebuild of all the project files with
$ cd Unreal/CarlaUE4/
$ make CarlaUE4Editor ARGS=-clean
$ make CarlaUE4Editor

View File

@ -1,5 +1,5 @@
INSTALL_FOLDER=$(CURDIR)/Unreal/CarlaUE4/Plugins/Carla/CarlaServer INSTALL_FOLDER=$(CURDIR)/Unreal/CarlaUE4/Plugins/Carla/CarlaServer
PYTHON_CLIENT_FOLDER=$(CURDIR)/Util/TestingClient/test PYTHON_CLIENT_FOLDER=$(CURDIR)/PythonClient/test
BASE_BUILD_FOLDER=$(CURDIR)/Util/Build/carlaserver-build BASE_BUILD_FOLDER=$(CURDIR)/Util/Build/carlaserver-build
MY_CMAKE_FOLDER=$(CURDIR)/Util/cmake MY_CMAKE_FOLDER=$(CURDIR)/Util/cmake
MY_CMAKE_FLAGS=-B"$(BUILD_FOLDER)" -DCMAKE_INSTALL_PREFIX="$(INSTALL_FOLDER)" MY_CMAKE_FLAGS=-B"$(BUILD_FOLDER)" -DCMAKE_INSTALL_PREFIX="$(INSTALL_FOLDER)"

View File

@ -1,3 +0,0 @@
from .carla import CARLA
from .protoc import SceneDescription,EpisodeStart,EpisodeReady,Control,Measurements,RequestNewEpisode

View File

@ -1,323 +0,0 @@
#!/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>.
from __future__ import print_function
from .datastream import DataStream
import socket
import time
import os, signal
import sys
import logging
import struct
import re
from .protoc import *
from . import socket_util
def get_image_resolution(data):
return int(re.search('[\n\r].*ImageSizeX\s*=([^\n\r]*)', data).group(1)),int(re.search('[\n\r].*ImageSizeY\s*=([^\n\r]*)', data).group(1))
class CARLA(object):
"""
Normal instanciation of the class, creating also the thread class responsible for receiving data
"""
def __init__(self,host,port):
self._host = host
self._port = port
logging.debug('selected host %s' % host)
logging.debug('selected port %s' % port)
self._port_control = self._port +2
self._port_stream = self._port +1
# Default start. Keep it as class param for eventual restart
self._image_x =0
self._image_y = 0
self._socket_world = socket_util.pers_connect(self._host ,self._port)
print ('Successfully Connected to Carla Server')
logging.debug("Connected to Unreal Server World Socket")
self._socket_stream = 0
self._socket_control = 0
self._latest_start = 0
self._agent_is_running = False
self._episode_requested = False
self._data_stream = None
logging.debug("Started Unreal Client")
"""
Starting the Player Agent. The image stream port
and the control port
Args:
None
Returns:
None
"""
def startAgent(self):
self._data_stream = DataStream(self._image_x,self._image_y)
logging.debug("Going to Connect Stream and start thread")
# Perform persistent connections, try up to 10 times
try:
self._socket_stream = socket_util.pers_connect(self._host ,self._port_stream)
except Exception:
logging.exception("Attempts to connect Stream all failed, restart...")
self.restart()
self._data_stream.start(self._socket_stream)
logging.debug("Streaming Thread Started")
try:
self._socket_control = socket_util.pers_connect(self._host ,self._port_control)
except Exception:
logging.exception("Attempts to connect Agent all failed, restart ...")
self.restart()
logging.debug("Control Socket Connected")
self._agent_is_running = True
def stopAgent(self):
logging.debug("Going to Stop thread and Disconect Stream")
self._data_stream.stop()
logging.debug("Streaming Thread Stoped")
socket_util.disconnect(self._socket_control)
logging.debug("Control Socket DisConnected")
self._agent_is_running = False
# This function requests a new episode and send the string containing this episode configuration file
def receiveSceneConfiguration(self):
try:
logging.debug("Reading for the scene configuration")
data = socket_util.get_message(self._socket_world)
scene = SceneDescription()
scene.ParseFromString(data)
logging.debug("Received Scene Configuration")
return scene.player_start_spots
except Exception as e:
logging.exception("Server not responing when receiving configuration")
return self.restart()
def requestNewEpisode(self,ini_path=None):
if ini_path == None:
ini_file = self._config_path
else:
ini_file = ini_path
self._config_path = ini_path # We just save the last config file in case the client dies
requestEpisode = RequestNewEpisode()
with open (ini_file, "r") as myfile:
data=myfile.read()
try:
self._image_x,self._image_y = get_image_resolution(data)
except Exception as e:
logging.exception("No image resolution found on config file")
logging.debug("Resolution %d , %d",self._image_x,self._image_y)
logging.debug("Set the Init File")
logging.debug("sent %s" % (data))
requestEpisode.ini_file = data.encode('utf-8')
try:
socket_util.send_message(self._socket_world,requestEpisode)
except Exception as e:
logging.exception("Server not responding when requesting new episode")
self.restart()
else:
logging.debug("Successfully sent the new episode Request")
if self._agent_is_running:
self.stopAgent()
self._episode_requested = True
return self.receiveSceneConfiguration()
def loadConfigurationFile(self,ini_path):
return self.requestNewEpisode(ini_path)
def newEpisode(self,start_index):
# Save the latest new episode positon, just in case of crashes
self._latest_start = start_index
if not self._episode_requested:
positions = self.requestNewEpisode(self._config_path)
scene_init = EpisodeStart()
scene_init.player_start_spot_index = start_index
try:
socket_util.send_message(self._socket_world,scene_init)
except Exception:
logging.exception("Server not responding when trying to send episode start confirmation")
self.restart()
else:
logging.debug("Successfully sent the new episode Message")
episode_ready = EpisodeReady()
episode_ready.ready = False
try:
data = socket_util.get_message(self._socket_world)
logging.debug("Got the episode ready message")
episode_ready.ParseFromString(data)
except Exception:
logging.exception("Server not responding when trying to receive episode reading")
self.restart()
else:
logging.debug("Episode is Ready")
self.startAgent()
self._episode_requested = False
""" Measurements
returns
@game time
@wall time
@player measurements
@non_player_agents : vector with all agents present on the game
@image_data
"""
def getMeasurements(self):
while True:
try:
meas_dict = self._data_stream.get_the_latest_data()
logging.debug("Got A new Measurement")
return meas_dict
except AttributeError:
logging.exception("Unitialized DataStream. Tip: Connect and start an episode before requesting measurements")
return None
except Exception:
logging.exception("Got an empty Measurement")
self.restart()
""" Command contains:
Steering: -1 to 1
Acc : -1 to 1
"""
def sendCommand(self,control):
logging.debug("Send Control Comand : throttle -> %f , steer %f, brake %f, hand_brake %d, gear %d" % (control.throttle,control.steer,control.brake,control.hand_brake,control.reverse))
try:
socket_util.send_message(self._socket_control,control)
except Exception:
logging.exception("Problems on sending the commands... restarting")
self.restart() # the mensage is not resend because it likely lost its relevance.
def restart(self):
logging.debug("Trying to close clients")
self.closeConections()
connected = False
if self._data_stream != None:
self._data_stream._running = False
self._agent_is_running = False
while not connected:
try:
logging.debug("Trying to connect to the world thread")
self._socket_world = socket_util.connect(self._host ,self._port)
connected = True
except Exception:
logging.exception("Couldn't connected ... retry in 10 seconds...")
time.sleep(10)
self._data_stream = DataStream(self._image_x,self._image_y)
positions = self.requestNewEpisode()
self.newEpisode(self._latest_start)
logging.debug("restarted the world connection")
return positions
def stop(self):
self.closeConections()
connected = False
self._data_stream._running = False
self._data_stream = DataStream(self._image_x,self._image_y)
def closeConections(self):
try:
self._socket_world.shutdown(socket.SHUT_RDWR)
self._socket_world.close()
logging.debug("Close world")
except Exception as ex:
logging.exception("Exception on closing Connections")
try:
self._socket_stream.shutdown(socket.SHUT_RDWR)
self._socket_stream.close()
logging.debug("Close Stream")
except Exception as ex:
logging.exception("Exception on closing Connections")
try:
self._socket_control.shutdown(socket.SHUT_RDWR)
self._socket_control.close()
logging.debug("Close Control")
except Exception as ex:
logging.exception("Exception on closing Connections")

View File

@ -0,0 +1,836 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: carla_server.proto
import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
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\"b\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.Vector3D\"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')
)
_TRAFFICLIGHT_STATE = _descriptor.EnumDescriptor(
name='State',
full_name='carla_server.TrafficLight.State',
filename=None,
file=DESCRIPTOR,
values=[
_descriptor.EnumValueDescriptor(
name='GREEN', index=0, number=0,
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='YELLOW', index=1, number=1,
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='RED', index=2, number=2,
options=None,
type=None),
],
containing_type=None,
options=None,
serialized_start=538,
serialized_end=577,
)
_sym_db.RegisterEnumDescriptor(_TRAFFICLIGHT_STATE)
_VECTOR3D = _descriptor.Descriptor(
name='Vector3D',
full_name='carla_server.Vector3D',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='x', full_name='carla_server.Vector3D.x', index=0,
number=1, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='y', full_name='carla_server.Vector3D.y', index=1,
number=2, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='z', full_name='carla_server.Vector3D.z', index=2,
number=3, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=36,
serialized_end=79,
)
_TRANSFORM = _descriptor.Descriptor(
name='Transform',
full_name='carla_server.Transform',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='location', full_name='carla_server.Transform.location', index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='orientation', full_name='carla_server.Transform.orientation', index=1,
number=2, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=81,
serialized_end=179,
)
_VEHICLE = _descriptor.Descriptor(
name='Vehicle',
full_name='carla_server.Vehicle',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='transform', full_name='carla_server.Vehicle.transform', index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='box_extent', full_name='carla_server.Vehicle.box_extent', index=1,
number=2, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='forward_speed', full_name='carla_server.Vehicle.forward_speed', index=2,
number=3, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=181,
serialized_end=301,
)
_PEDESTRIAN = _descriptor.Descriptor(
name='Pedestrian',
full_name='carla_server.Pedestrian',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='transform', full_name='carla_server.Pedestrian.transform', index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='box_extent', full_name='carla_server.Pedestrian.box_extent', index=1,
number=2, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='forward_speed', full_name='carla_server.Pedestrian.forward_speed', index=2,
number=3, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=303,
serialized_end=426,
)
_TRAFFICLIGHT = _descriptor.Descriptor(
name='TrafficLight',
full_name='carla_server.TrafficLight',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='transform', full_name='carla_server.TrafficLight.transform', index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='state', full_name='carla_server.TrafficLight.state', 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),
],
extensions=[
],
nested_types=[],
enum_types=[
_TRAFFICLIGHT_STATE,
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=429,
serialized_end=577,
)
_SPEEDLIMITSIGN = _descriptor.Descriptor(
name='SpeedLimitSign',
full_name='carla_server.SpeedLimitSign',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='transform', full_name='carla_server.SpeedLimitSign.transform', index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='speed_limit', full_name='carla_server.SpeedLimitSign.speed_limit', index=1,
number=2, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=579,
serialized_end=660,
)
_AGENT = _descriptor.Descriptor(
name='Agent',
full_name='carla_server.Agent',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='id', full_name='carla_server.Agent.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='vehicle', full_name='carla_server.Agent.vehicle', index=1,
number=2, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='pedestrian', full_name='carla_server.Agent.pedestrian', index=2,
number=3, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='traffic_light', full_name='carla_server.Agent.traffic_light', index=3,
number=4, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='speed_limit_sign', full_name='carla_server.Agent.speed_limit_sign', index=4,
number=5, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
_descriptor.OneofDescriptor(
name='agent', full_name='carla_server.Agent.agent',
index=0, containing_type=None, fields=[]),
],
serialized_start=663,
serialized_end=892,
)
_REQUESTNEWEPISODE = _descriptor.Descriptor(
name='RequestNewEpisode',
full_name='carla_server.RequestNewEpisode',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='ini_file', full_name='carla_server.RequestNewEpisode.ini_file', index=0,
number=1, 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=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=894,
serialized_end=931,
)
_SCENEDESCRIPTION = _descriptor.Descriptor(
name='SceneDescription',
full_name='carla_server.SceneDescription',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='player_start_spots', full_name='carla_server.SceneDescription.player_start_spots', index=0,
number=1, 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=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=933,
serialized_end=1004,
)
_EPISODESTART = _descriptor.Descriptor(
name='EpisodeStart',
full_name='carla_server.EpisodeStart',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='player_start_spot_index', full_name='carla_server.EpisodeStart.player_start_spot_index', index=0,
number=1, type=13, 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),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=1006,
serialized_end=1053,
)
_EPISODEREADY = _descriptor.Descriptor(
name='EpisodeReady',
full_name='carla_server.EpisodeReady',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='ready', full_name='carla_server.EpisodeReady.ready', index=0,
number=1, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=1055,
serialized_end=1084,
)
_CONTROL = _descriptor.Descriptor(
name='Control',
full_name='carla_server.Control',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='steer', full_name='carla_server.Control.steer', index=0,
number=1, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='throttle', full_name='carla_server.Control.throttle', index=1,
number=2, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='brake', full_name='carla_server.Control.brake', index=2,
number=3, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='hand_brake', full_name='carla_server.Control.hand_brake', index=3,
number=4, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='reverse', full_name='carla_server.Control.reverse', index=4,
number=5, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=1086,
serialized_end=1180,
)
_MEASUREMENTS_PLAYERMEASUREMENTS = _descriptor.Descriptor(
name='PlayerMeasurements',
full_name='carla_server.Measurements.PlayerMeasurements',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='transform', full_name='carla_server.Measurements.PlayerMeasurements.transform', index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='acceleration', full_name='carla_server.Measurements.PlayerMeasurements.acceleration', index=1,
number=3, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='forward_speed', full_name='carla_server.Measurements.PlayerMeasurements.forward_speed', index=2,
number=4, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='collision_vehicles', full_name='carla_server.Measurements.PlayerMeasurements.collision_vehicles', index=3,
number=5, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='collision_pedestrians', full_name='carla_server.Measurements.PlayerMeasurements.collision_pedestrians', index=4,
number=6, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='collision_other', full_name='carla_server.Measurements.PlayerMeasurements.collision_other', index=5,
number=7, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='intersection_otherlane', full_name='carla_server.Measurements.PlayerMeasurements.intersection_otherlane', index=6,
number=8, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='intersection_offroad', full_name='carla_server.Measurements.PlayerMeasurements.intersection_offroad', index=7,
number=9, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='autopilot_control', full_name='carla_server.Measurements.PlayerMeasurements.autopilot_control', index=8,
number=10, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=1376,
serialized_end=1705,
)
_MEASUREMENTS = _descriptor.Descriptor(
name='Measurements',
full_name='carla_server.Measurements',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='platform_timestamp', full_name='carla_server.Measurements.platform_timestamp', index=0,
number=1, type=13, 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='game_timestamp', full_name='carla_server.Measurements.game_timestamp', index=1,
number=2, type=13, 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='player_measurements', full_name='carla_server.Measurements.player_measurements', index=2,
number=3, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='non_player_agents', full_name='carla_server.Measurements.non_player_agents', index=3,
number=4, 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=[
],
nested_types=[_MEASUREMENTS_PLAYERMEASUREMENTS, ],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=1183,
serialized_end=1705,
)
_TRANSFORM.fields_by_name['location'].message_type = _VECTOR3D
_TRANSFORM.fields_by_name['orientation'].message_type = _VECTOR3D
_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
_PEDESTRIAN.fields_by_name['box_extent'].message_type = _VECTOR3D
_TRAFFICLIGHT.fields_by_name['transform'].message_type = _TRANSFORM
_TRAFFICLIGHT.fields_by_name['state'].enum_type = _TRAFFICLIGHT_STATE
_TRAFFICLIGHT_STATE.containing_type = _TRAFFICLIGHT
_SPEEDLIMITSIGN.fields_by_name['transform'].message_type = _TRANSFORM
_AGENT.fields_by_name['vehicle'].message_type = _VEHICLE
_AGENT.fields_by_name['pedestrian'].message_type = _PEDESTRIAN
_AGENT.fields_by_name['traffic_light'].message_type = _TRAFFICLIGHT
_AGENT.fields_by_name['speed_limit_sign'].message_type = _SPEEDLIMITSIGN
_AGENT.oneofs_by_name['agent'].fields.append(
_AGENT.fields_by_name['vehicle'])
_AGENT.fields_by_name['vehicle'].containing_oneof = _AGENT.oneofs_by_name['agent']
_AGENT.oneofs_by_name['agent'].fields.append(
_AGENT.fields_by_name['pedestrian'])
_AGENT.fields_by_name['pedestrian'].containing_oneof = _AGENT.oneofs_by_name['agent']
_AGENT.oneofs_by_name['agent'].fields.append(
_AGENT.fields_by_name['traffic_light'])
_AGENT.fields_by_name['traffic_light'].containing_oneof = _AGENT.oneofs_by_name['agent']
_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
_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
_MEASUREMENTS_PLAYERMEASUREMENTS.containing_type = _MEASUREMENTS
_MEASUREMENTS.fields_by_name['player_measurements'].message_type = _MEASUREMENTS_PLAYERMEASUREMENTS
_MEASUREMENTS.fields_by_name['non_player_agents'].message_type = _AGENT
DESCRIPTOR.message_types_by_name['Vector3D'] = _VECTOR3D
DESCRIPTOR.message_types_by_name['Transform'] = _TRANSFORM
DESCRIPTOR.message_types_by_name['Vehicle'] = _VEHICLE
DESCRIPTOR.message_types_by_name['Pedestrian'] = _PEDESTRIAN
DESCRIPTOR.message_types_by_name['TrafficLight'] = _TRAFFICLIGHT
DESCRIPTOR.message_types_by_name['SpeedLimitSign'] = _SPEEDLIMITSIGN
DESCRIPTOR.message_types_by_name['Agent'] = _AGENT
DESCRIPTOR.message_types_by_name['RequestNewEpisode'] = _REQUESTNEWEPISODE
DESCRIPTOR.message_types_by_name['SceneDescription'] = _SCENEDESCRIPTION
DESCRIPTOR.message_types_by_name['EpisodeStart'] = _EPISODESTART
DESCRIPTOR.message_types_by_name['EpisodeReady'] = _EPISODEREADY
DESCRIPTOR.message_types_by_name['Control'] = _CONTROL
DESCRIPTOR.message_types_by_name['Measurements'] = _MEASUREMENTS
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
Vector3D = _reflection.GeneratedProtocolMessageType('Vector3D', (_message.Message,), dict(
DESCRIPTOR = _VECTOR3D,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.Vector3D)
))
_sym_db.RegisterMessage(Vector3D)
Transform = _reflection.GeneratedProtocolMessageType('Transform', (_message.Message,), dict(
DESCRIPTOR = _TRANSFORM,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.Transform)
))
_sym_db.RegisterMessage(Transform)
Vehicle = _reflection.GeneratedProtocolMessageType('Vehicle', (_message.Message,), dict(
DESCRIPTOR = _VEHICLE,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.Vehicle)
))
_sym_db.RegisterMessage(Vehicle)
Pedestrian = _reflection.GeneratedProtocolMessageType('Pedestrian', (_message.Message,), dict(
DESCRIPTOR = _PEDESTRIAN,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.Pedestrian)
))
_sym_db.RegisterMessage(Pedestrian)
TrafficLight = _reflection.GeneratedProtocolMessageType('TrafficLight', (_message.Message,), dict(
DESCRIPTOR = _TRAFFICLIGHT,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.TrafficLight)
))
_sym_db.RegisterMessage(TrafficLight)
SpeedLimitSign = _reflection.GeneratedProtocolMessageType('SpeedLimitSign', (_message.Message,), dict(
DESCRIPTOR = _SPEEDLIMITSIGN,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.SpeedLimitSign)
))
_sym_db.RegisterMessage(SpeedLimitSign)
Agent = _reflection.GeneratedProtocolMessageType('Agent', (_message.Message,), dict(
DESCRIPTOR = _AGENT,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.Agent)
))
_sym_db.RegisterMessage(Agent)
RequestNewEpisode = _reflection.GeneratedProtocolMessageType('RequestNewEpisode', (_message.Message,), dict(
DESCRIPTOR = _REQUESTNEWEPISODE,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.RequestNewEpisode)
))
_sym_db.RegisterMessage(RequestNewEpisode)
SceneDescription = _reflection.GeneratedProtocolMessageType('SceneDescription', (_message.Message,), dict(
DESCRIPTOR = _SCENEDESCRIPTION,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.SceneDescription)
))
_sym_db.RegisterMessage(SceneDescription)
EpisodeStart = _reflection.GeneratedProtocolMessageType('EpisodeStart', (_message.Message,), dict(
DESCRIPTOR = _EPISODESTART,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.EpisodeStart)
))
_sym_db.RegisterMessage(EpisodeStart)
EpisodeReady = _reflection.GeneratedProtocolMessageType('EpisodeReady', (_message.Message,), dict(
DESCRIPTOR = _EPISODEREADY,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.EpisodeReady)
))
_sym_db.RegisterMessage(EpisodeReady)
Control = _reflection.GeneratedProtocolMessageType('Control', (_message.Message,), dict(
DESCRIPTOR = _CONTROL,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.Control)
))
_sym_db.RegisterMessage(Control)
Measurements = _reflection.GeneratedProtocolMessageType('Measurements', (_message.Message,), dict(
PlayerMeasurements = _reflection.GeneratedProtocolMessageType('PlayerMeasurements', (_message.Message,), dict(
DESCRIPTOR = _MEASUREMENTS_PLAYERMEASUREMENTS,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.Measurements.PlayerMeasurements)
))
,
DESCRIPTOR = _MEASUREMENTS,
__module__ = 'carla_server_pb2'
# @@protoc_insertion_point(class_scope:carla_server.Measurements)
))
_sym_db.RegisterMessage(Measurements)
_sym_db.RegisterMessage(Measurements.PlayerMeasurements)
DESCRIPTOR.has_options = True
DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\370\001\001'))
# @@protoc_insertion_point(module_scope)

View File

@ -0,0 +1,202 @@
# 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>.
"""CARLA Client."""
import struct
from contextlib import contextmanager
from . import sensor
from . import settings
from . import tcp
from . import util
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')
VehicleControl = carla_protocol.Control
@contextmanager
def make_carla_client(host, world_port, timeout=15):
"""Context manager for creating and connecting a CarlaClient."""
with util.make_connection(CarlaClient, host, world_port, timeout) as client:
yield client
class CarlaClient(object):
"""The CARLA client. Manages communications with the CARLA server."""
def __init__(self, host, world_port, timeout=15):
self._world_client = tcp.TCPClient(host, world_port, timeout)
self._stream_client = tcp.TCPClient(host, world_port + 1, timeout)
self._control_client = tcp.TCPClient(host, world_port + 2, timeout)
self._current_settings = None
self._is_episode_requested = False
self._sensor_names = []
def connect(self, connection_attempts=10):
"""
Try to establish a connection to a CARLA server at the given host:port.
"""
self._world_client.connect(connection_attempts)
def disconnect(self):
"""Disconnect from server."""
self._control_client.disconnect()
self._stream_client.disconnect()
self._world_client.disconnect()
def connected(self):
"""Return whether there is an active connection."""
return self._world_client.connected()
def load_settings(self, carla_settings):
"""
Load new settings and request a new episode based on these settings.
carla_settings object must be convertible to a str holding the contents
of a CarlaSettings.ini file.
Return a protobuf object holding the scene description.
"""
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
player_start_index. The list of player starts is retrieved by
"load_settings".
The new episode is started based on the last settings loaded by
"load_settings".
This function waits until the server answers with an EpisodeReady.
"""
if self._current_settings is None:
raise RuntimeError('no settings loaded, cannot start episode')
# if no new settings are loaded, request new episode with previous
if not self._is_episode_requested:
self._request_new_episode(self._current_settings)
try:
pb_message = carla_protocol.EpisodeStart()
pb_message.player_start_spot_index = player_start_index
self._world_client.write(pb_message.SerializeToString())
# Wait for EpisodeReady.
data = self._world_client.read()
if not data:
raise RuntimeError('failed to read data from server')
pb_message = carla_protocol.EpisodeReady()
pb_message.ParseFromString(data)
if not pb_message.ready:
raise RuntimeError('cannot start episode: server failed to start episode')
# We can start the agent clients now.
self._stream_client.connect()
self._control_client.connect()
# Set again the status for no episode requested
finally:
self._is_episode_requested = False
def read_data(self):
"""
Read the data sent from the server this frame. The episode must be
started. Return a pair containing the protobuf object containing the
measurements followed by the raw data of the sensors.
"""
# Read measurements.
data = self._stream_client.read()
if not data:
raise RuntimeError('failed to read data from server')
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)
def send_control(self, *args, **kwargs):
"""
Send the VehicleControl to be applied this frame.
If synchronous mode was requested, the server will pause the simulation
until this message is received.
"""
if isinstance(args[0] if args else None, carla_protocol.Control):
pb_message = args[0]
else:
pb_message = carla_protocol.Control()
pb_message.steer = kwargs.get('steer', 0.0)
pb_message.throttle = kwargs.get('throttle', 0.0)
pb_message.brake = kwargs.get('brake', 0.0)
pb_message.hand_brake = kwargs.get('hand_brake', False)
pb_message.reverse = kwargs.get('reverse', False)
self._control_client.write(pb_message.SerializeToString())
def _request_new_episode(self, carla_settings):
"""
Internal function to request a new episode. Prepare the client for a new
episode by disconnecting agent clients.
"""
# Disconnect agent clients.
self._stream_client.disconnect()
self._control_client.disconnect()
# Send new episode request.
pb_message = carla_protocol.RequestNewEpisode()
pb_message.ini_file = str(carla_settings)
self._world_client.write(pb_message.SerializeToString())
# Read scene description.
data = self._world_client.read()
if not data:
raise RuntimeError('failed to read data from server')
pb_message = carla_protocol.SceneDescription()
pb_message.ParseFromString(data)
if len(pb_message.player_start_spots) < 1:
raise RuntimeError("received 0 player start spots")
self._sensor_names = settings._get_sensor_names(carla_settings)
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)))
@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', 'Lidar']
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]
getfloatval = lambda index: struct.unpack('<d', raw_data[index*4:index*4+8])[0]
total_size = len(raw_data) / 4
index = 0
while index < total_size:
sensor_type = gettype(getval(index + 2))
if sensor_type == 'Lidar':
horizontal_angle = getfloatval(index)
channels_count = getval(index + 3)
lm = sensor.LidarMeasurement(
horizontal_angle, channels_count,
sensor_type, raw_data[index*4:])
index += lm.size_in_bytes
yield lm
else:
width = getval(index)
height = getval(index + 1)
begin = index + 3
end = begin + width * height
index = end
yield sensor.Image(width, height, sensor_type, raw_data[begin*4:end*4])

View File

@ -0,0 +1,103 @@
# 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>.
"""
Handy conversions for CARLA images.
The functions here are provided for real-time display, if you want to save the
converted images, save the images from Python without conversion and convert
them afterwards with the C++ implementation at "Util/ImageConverter" as it
provides considerably better performance.
"""
try:
import numpy
except ImportError:
raise RuntimeError('cannot import numpy, make sure numpy package is installed')
from . import sensor
def to_bgra_array(image):
"""Convert a CARLA raw image to a BGRA numpy array."""
if not isinstance(image, sensor.Image):
raise ValueError("Argument must be a carla.sensor.Image")
array = numpy.frombuffer(image.raw_data, dtype=numpy.dtype("uint8"))
array = numpy.reshape(array, (image.height, image.width, 4))
return array
def to_rgb_array(image):
"""Convert a CARLA raw image to a RGB numpy array."""
array = to_bgra_array(image)
# Convert BGRA to RGB.
array = array[:, :, :3]
array = array[:, :, ::-1]
return array
def labels_to_array(image):
"""
Convert an image containing CARLA semantic segmentation labels to a 2D array
containing the label of each pixel.
"""
return to_bgra_array(image)[:, :, 2]
def labels_to_cityscapes_palette(image):
"""
Convert an image containing CARLA semantic segmentation labels to
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
}
array = labels_to_array(image)
result = numpy.zeros((array.shape[0], array.shape[1], 3))
for key, value in classes.items():
result[numpy.where(array == key)] = value
return result
def depth_to_array(image):
"""
Convert an image containing CARLA encoded depth-map to a 2D array containing
the depth value of each pixel normalized between [0.0, 1.0].
"""
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
def depth_to_logarithmic_grayscale(image):
"""
Convert an image containing CARLA encoded depth-map to a logarithmic
grayscale image array.
"""
grayscale = depth_to_array(image)
# Convert to logarithmic depth.
logdepth = numpy.ones(grayscale.shape) + (numpy.log(grayscale) / 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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 KiB

View File

@ -0,0 +1,49 @@
0.0,0.0,-3811.000000
0.000000,0.000000,0.0
1.000000,1.000000,1.000000
-1643.022,-1643.022,0.000
49, 41
0,0 0,40 40
0,40 0,0 40
48,40 41,40 7
41,40 48,40 7
48,0 48,40 40
48,40 48,0 40
0,0 11,0 11
11,0 0,0 11
41,0 48,0 7
48,0 41,0 7
41,40 11,40 30
11,40 41,40 30
41,0 41,7 7
41,7 41,0 7
11,40 0,40 11
0,40 11,40 11
11,0 19,0 8
19,0 11,0 8
11,40 11,24 16
11,24 11,40 16
41,24 41,40 16
41,40 41,24 16
11,24 11,16 8
11,16 11,24 8
41,24 11,24 30
11,24 41,24 30
41,16 41,24 8
41,24 41,16 8
11,16 11,7 9
11,7 11,16 9
41,16 11,16 30
11,16 41,16 30
41,7 41,16 9
41,16 41,7 9
11,7 11,0 7
11,0 11,7 7
41,7 19,7 22
19,7 41,7 22
19,0 41,0 22
41,0 19,0 22
19,7 11,7 8
11,7 19,7 8
19,0 19,7 7
19,7 19,0 7

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

View File

@ -0,0 +1,37 @@
544.000000,-10748.000000,-22.000000
0.000000,0.000000,0.000000
1.000000,1.000000,1.000000
-1643.022,-1643.022,0.000
25, 25
0,10 0,24 14
0,24 0,10 14
24,24 6,24 18
6,24 24,24 18
24,0 24,10 10
24,10 24,0 10
0,0 24,0 24
24,0 0,0 24
0,10 0,0 10
0,0 0,10 10
24,10 24,16 6
24,16 24,10 6
0,10 6,10 6
6,10 0,10 6
6,24 0,24 6
0,24 6,24 6
6,10 17,10 11
17,10 6,10 11
6,24 6,16 8
6,16 6,24 8
24,16 24,24 8
24,24 24,16 8
6,16 6,10 6
6,10 6,16 6
24,16 17,16 7
17,16 24,16 7
17,16 6,16 11
6,16 17,16 11
17,10 24,10 7
24,10 17,10 7
17,16 17,10 6
17,10 17,16 6

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,146 @@
# 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>.
"""Class used for operating the city map."""
import math
import os
try:
import numpy as np
except ImportError:
raise RuntimeError('cannot import numpy, make sure numpy package is installed')
try:
from PIL import Image
except ImportError:
raise RuntimeError('cannot import PIL, make sure pillow package is installed')
def string_to_node(string):
vec = string.split(',')
return (int(vec[0]), int(vec[1]))
def string_to_floats(string):
vec = string.split(',')
return (float(vec[0]), float(vec[1]), float(vec[2]))
class CarlaMap(object):
def __init__(self, city):
dir_path = os.path.dirname(__file__)
city_file = os.path.join(dir_path, city + '.txt')
city_map_file = os.path.join(dir_path, city + '.png')
city_map_file_lanes = os.path.join(dir_path, city + 'Lanes.png')
with open(city_file, 'r') as file:
linewordloffset = file.readline()
# The offset of the world from the zero coordinates ( The
# coordinate we consider zero)
self.worldoffset = string_to_floats(linewordloffset)
lineworldangles = file.readline()
self.angles = string_to_floats(lineworldangles)
self.worldrotation = np.array([
[math.cos(math.radians(self.angles[2])), -math.sin(math.radians(self.angles[2])), 0.0],
[math.sin(math.radians(self.angles[2])), math.cos(math.radians(self.angles[2])), 0.0],
[0.0, 0.0, 1.0]])
# Ignore for now, these are offsets for map coordinates and scale
# (not used).
_ = file.readline()
linemapoffset = file.readline()
# The offset of the map zero coordinate.
self.mapoffset = string_to_floats(linemapoffset)
# the graph resolution.
linegraphres = file.readline()
self.resolution = string_to_node(linegraphres)
# The number of game units per pixel.
self.pixel_density = 16.43
# Load the lanes image
self.map_image_lanes = Image.open(city_map_file_lanes)
self.map_image_lanes.load()
self.map_image_lanes = np.asarray(self.map_image_lanes, dtype="int32")
# Load the image
self.map_image = Image.open(city_map_file)
self.map_image.load()
self.map_image = np.asarray(self.map_image, dtype="int32")
def get_map(self, height=None):
if height is not None:
img = Image.fromarray(self.map_image.astype(np.uint8))
aspect_ratio = height/float(self.map_image.shape[0])
img = img.resize((int(aspect_ratio*self.map_image.shape[1]),height), Image.ANTIALIAS)
img.load()
return np.asarray(img, dtype="int32")
return np.fliplr(self.map_image)
def get_map_lanes(self, height=None):
if size is not None:
img = Image.fromarray(self.map_image_lanes.astype(np.uint8))
img = img.resize((size[1], size[0]), Image.ANTIALIAS)
img.load()
return np.fliplr(np.asarray(img, dtype="int32"))
return np.fliplr(self.map_image_lanes)
def get_position_on_map(self, world):
"""Get the position on the map for a certain world position."""
relative_location = []
pixel = []
rotation = np.array([world[0], world[1], world[2]])
rotation = rotation.dot(self.worldrotation)
relative_location.append(rotation[0] + self.worldoffset[0] - self.mapoffset[0])
relative_location.append(rotation[1] + self.worldoffset[1] - self.mapoffset[1])
relative_location.append(rotation[2] + self.worldoffset[2] - self.mapoffset[2])
pixel.append(math.floor(relative_location[0] / float(self.pixel_density)))
pixel.append(math.floor(relative_location[1] / float(self.pixel_density)))
return pixel
def get_position_on_world(self, pixel):
"""Get world position of a certain map position."""
relative_location = []
world_vertex = []
relative_location.append(pixel[0] * self.pixel_density)
relative_location.append(pixel[1] * self.pixel_density)
world_vertex.append(relative_location[0] + self.mapoffset[0] - self.worldoffset[0])
world_vertex.append(relative_location[1] + self.mapoffset[1] - self.worldoffset[1])
world_vertex.append(22) # Z does not matter for now.
return world_vertex
def get_lane_orientation(self, world):
"""Get the lane orientation of a certain world position."""
relative_location = []
pixel = []
rotation = np.array([world[0], world[1], world[2]])
rotation = rotation.dot(self.worldrotation)
relative_location.append(rotation[0] + self.worldoffset[0] - self.mapoffset[0])
relative_location.append(rotation[1] + self.worldoffset[1] - self.mapoffset[1])
relative_location.append(rotation[2] + self.worldoffset[2] - self.mapoffset[2])
pixel.append(math.floor(relative_location[0] / float(self.pixel_density)))
pixel.append(math.floor(relative_location[1] / float(self.pixel_density)))
ori = self.map_image_lanes[int(pixel[1]), int(pixel[0]), 2]
ori = ((float(ori) / 255.0)) * 2 * math.pi
return (-math.cos(ori), -math.sin(ori))

View File

@ -1,2 +0,0 @@
from .carla_server_pb2 import SceneDescription,EpisodeStart,EpisodeReady,Control,Measurements,RequestNewEpisode

View File

@ -0,0 +1,231 @@
# 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>.
"""CARLA sensors."""
import os
import numpy as np
# ==============================================================================
# -- Sensor --------------------------------------------------------------------
# ==============================================================================
class Sensor(object):
"""
Base class for sensor descriptions. Used to add sensors to CarlaSettings.
"""
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)
class Camera(Sensor):
"""
Camera description. This class can be added to a CarlaSettings object to add
a camera to the player vehicle.
"""
def __init__(self, name, **kwargs):
self.CameraName = name
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.set(**kwargs)
def set_image_size(self, pixels_x, pixels_y):
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):
self.LidarName = name
# Number of lasers
self.Channels = 32
# Measure distance
self.Range = 5000
# Points generated by all lasers per second
self.PointsPerSecond = 100000
# Lidar rotation frequency
self.RotationFrequency = 10
# Upper laser angle, counts from horizontal,
# positive values means above horizontal line
self.UpperFovLimit = 10
# Lower laser angle, counts from horizontal,
# negative values means under horizontal line
self.LowerFovLimit = -30
# wether to show debug points of laser hits in simulator
self.ShowDebugPoints = False
# Position relative to the player.
self.LidarPositionX = 0
self.LidarPositionY = 0
self.LidarPositionZ = 250
# Rotation relative to the player.
self.LidarRotationPitch = 0
self.LidarRotationRoll = 0
self.LidarRotationYaw = 0
self.set(**kwargs)
def set_position(self, x, y, z):
self.LidarPositionX = x
self.LidarPositionY = y
self.LidarPositionZ = z
def set_rotation(self, pitch, roll, yaw):
self.LidarRotationPitch = pitch
self.LidarRotationRoll = roll
self.LidarRotationYaw = yaw
# ==============================================================================
# -- SensorData ----------------------------------------------------------------
# ==============================================================================
class SensorData(object):
"""Base class for sensor data returned from the server."""
pass
class Image(SensorData):
"""Data generated by a Camera."""
def __init__(self, width, height, image_type, raw_data):
assert len(raw_data) == 4 * width * height
self.width = width
self.height = height
self.type = image_type
self.raw_data = raw_data
self._converted_data = None
@property
def data(self):
"""
Lazy initialization for data property, stores converted data in its
default format.
"""
if self._converted_data is None:
from . import image_converter
if self.type == 'Depth':
self._converted_data = image_converter.depth_to_array(self)
elif self.type == 'SemanticSegmentation':
self._converted_data = image_converter.labels_to_array(self)
else:
self._converted_data = image_converter.to_rgb_array(self)
return self._converted_data
def save_to_disk(self, filename):
"""Save this image to disk (requires PIL installed)."""
try:
from PIL import Image as PImage
except ImportError:
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, a = image.split()
image = PImage.merge("RGB", (r, g, b))
folder = os.path.dirname(filename)
if not os.path.isdir(folder):
os.makedirs(folder)
image.save(filename)
class LidarMeasurement(SensorData):
"""Data generated by a Lidar."""
def __init__(self, horizontal_angle, channels_count, lidar_type, raw_data):
self.horizontal_angle = horizontal_angle
self.channels_count = channels_count
self.type = lidar_type
self._converted_data = None
points_count_by_channel_size = channels_count * 4
points_count_by_channel_bytes = raw_data[4*4:4*4 + points_count_by_channel_size]
self.points_count_by_channel = np.frombuffer(points_count_by_channel_bytes, dtype=np.dtype('uint32'))
self.points_size = int(np.sum(self.points_count_by_channel) * 3 * 8) # three floats X, Y, Z
begin = 4*4 + points_count_by_channel_size # 4*4 is horizontal_angle, type, channels_count
end = begin + self.points_size
self.points_data = raw_data[begin:end]
self._data_size = 4*4 + points_count_by_channel_size + self.points_size
@property
def size_in_bytes(self):
return self._data_size
@property
def data(self):
"""
Lazy initialization for data property, stores converted data in its
default format.
"""
if self._converted_data is None:
points_in_one_channel = self.points_count_by_channel[0]
points = np.frombuffer(self.points_data[:self.points_size], dtype='float')
points = np.reshape(points, (self.channels_count, points_in_one_channel, 3))
self._converted_data = {
'horizontal_angle' : self.horizontal_angle,
'channels_count' : self.channels_count,
'points_count_by_channel' : self.points_count_by_channel,
'points' : points
}
return self._converted_data
def save_to_disk(self, filename):
"""Save lidar measurements to disk"""
pass
# image = PImage.frombytes(
# mode='RGBA',
# size=(self.width, self.height),
# data=self.raw_data,
# decoder_name='raw')
# b, g, r, a = image.split()
# image = PImage.merge("RGB", (r, g, b))
#
# folder = os.path.dirname(filename)
# if not os.path.isdir(folder):
# os.makedirs(folder)
# image.save(filename)

View File

@ -6,53 +6,32 @@
"""CARLA Settings""" """CARLA Settings"""
import configparser
import io import io
import random import random
import sys
if sys.version_info >= (3, 0):
from configparser import ConfigParser
else:
from ConfigParser import RawConfigParser as ConfigParser
from . import sensor as carla_sensor
MAX_NUMBER_OF_WEATHER_IDS = 14 MAX_NUMBER_OF_WEATHER_IDS = 14
class Camera(object):
"""Camera description. To be added to CarlaSettings."""
def __init__(self, name, **kwargs):
self.CameraName = name
self.PostProcessing = 'SceneFinal'
self.ImageSizeX = 800
self.ImageSizeY = 600
self.CameraFOV = 90
self.CameraPositionX = 15
self.CameraPositionY = 0
self.CameraPositionZ = 123
self.CameraRotationPitch = 8
self.CameraRotationRoll = 0
self.CameraRotationYaw = 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):
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 CarlaSettings(object): class CarlaSettings(object):
"""CARLA settings object. Convertible to str as CarlaSettings.ini.""" """
The CarlaSettings object controls the settings of an episode. The __str__
method retrieves an str with a CarlaSettings.ini file contents.
"""
def __init__(self, **kwargs): def __init__(self, **kwargs):
# [CARLA/Server] # [CARLA/Server]
self.SynchronousMode = True self.SynchronousMode = True
@ -67,6 +46,7 @@ class CarlaSettings(object):
self.randomize_weather() self.randomize_weather()
self.set(**kwargs) self.set(**kwargs)
self._cameras = [] self._cameras = []
self._lidars = []
def set(self, **kwargs): def set(self, **kwargs):
for key, value in kwargs.items(): for key, value in kwargs.items():
@ -74,25 +54,30 @@ class CarlaSettings(object):
raise ValueError('CarlaSettings: no key named %r' % key) raise ValueError('CarlaSettings: no key named %r' % key)
setattr(self, key, value) setattr(self, key, value)
def get_number_of_agents(self):
if not self.SendNonPlayerAgentsInfo:
return 0
return self.NumberOfVehicles + self.NumberOfPedestrians
def randomize_seeds(self): def randomize_seeds(self):
"""
Randomize the seeds of the new episode's pseudo-random number
generators.
"""
self.SeedVehicles = random.getrandbits(16) self.SeedVehicles = random.getrandbits(16)
self.SeedPedestrians = random.getrandbits(16) self.SeedPedestrians = random.getrandbits(16)
def randomize_weather(self): def randomize_weather(self):
"""Randomized the WeatherId."""
self.WeatherId = random.randint(0, MAX_NUMBER_OF_WEATHER_IDS) self.WeatherId = random.randint(0, MAX_NUMBER_OF_WEATHER_IDS)
def add_camera(self, camera): def add_sensor(self, sensor):
if not isinstance(camera, Camera): """Add a sensor to the player vehicle (see sensor.py)."""
raise ValueError('Can only add instances of carla_settings.Camera') if isinstance(sensor, carla_sensor.Camera):
self._cameras.append(camera) self._cameras.append(sensor)
elif isinstance(sensor, carla_sensor.Lidar):
self._lidars.append(sensor)
else:
raise ValueError('Sensor not supported')
def __str__(self): def __str__(self):
ini = configparser.ConfigParser() """Converts this object to an INI formatted string."""
ini = ConfigParser()
ini.optionxform=str ini.optionxform=str
S_SERVER = 'CARLA/Server' S_SERVER = 'CARLA/Server'
S_LEVEL = 'CARLA/LevelSettings' S_LEVEL = 'CARLA/LevelSettings'
@ -117,6 +102,7 @@ class CarlaSettings(object):
ini.add_section(S_CAPTURE) ini.add_section(S_CAPTURE)
ini.set(S_CAPTURE, 'Cameras', ','.join(c.CameraName for c in self._cameras)) ini.set(S_CAPTURE, 'Cameras', ','.join(c.CameraName for c in self._cameras))
ini.set(S_CAPTURE, 'Lidars', ','.join(l.LidarName for l in self._lidars))
for camera in self._cameras: for camera in self._cameras:
add_section(S_CAPTURE + '/' + camera.CameraName, camera, [ add_section(S_CAPTURE + '/' + camera.CameraName, camera, [
@ -131,6 +117,49 @@ class CarlaSettings(object):
'CameraRotationRoll', 'CameraRotationRoll',
'CameraRotationYaw']) 'CameraRotationYaw'])
text = io.StringIO() for lidar in self._lidars:
add_section(S_CAPTURE + '/' + lidar.LidarName, lidar, [
'Channels',
'Range',
'PointsPerSecond',
'RotationFrequency',
'UpperFovLimit',
'LowerFovLimit',
'ShowDebugPoints',
'LidarPositionX',
'LidarPositionY',
'LidarPositionZ',
'LidarRotationPitch',
'LidarRotationRoll',
'LidarRotationYaw'])
if sys.version_info >= (3, 0):
text = io.StringIO()
else:
text = io.BytesIO()
ini.write(text) ini.write(text)
return text.getvalue().replace(' = ', '=') 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):
return [camera.CameraName for camera in settings._cameras] + \
[lidar.LidarName for lidar in settings._lidars]
ini = ConfigParser()
if sys.version_info >= (3, 0):
ini.readfp(io.StringIO(settings))
else:
ini.readfp(io.BytesIO(settings))
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 []

View File

@ -1,114 +0,0 @@
#!/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>.
import binascii
import socket
import struct
import logging
import time
import select
def int2bytes(i):
hex_string = '%x' % i
n = len(hex_string)
return binascii.unhexlify(hex_string.zfill(n + (n & 1)))
def bytes2int(str):
return int(str.encode('hex'), 16)
def connect(host,port):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(100)
except socket.error:
logginge.exception("Error Creating Socket World")
sock.connect((host,port))
logging.debug("connected to %s port %d" %(host,port))
return sock
def pers_connect(host,port):
for attempt in range(10):
try:
sock = connect(host,port)
return sock
except Exception as e:
logging.exception("Failure on connection")
time.sleep(1)
continue
else:
break
raise socket.error
def disconnect(sock):
sock.shutdown(socket.SHUT_RDWR)
sock.close()
def send_message(sock, message):
""" Send a serialized message (protobuf Message interface)
to a socket, prepended by its length packed in 4
bytes (big endian).
"""
s = message.SerializeToString()
packed_len =struct.pack('<L', len(s)) #int2bytes(len(s))
logging.debug( "SOCKET Send: %d bytes" % int(len(s)))
sock.sendall(packed_len + s)
def get_message(sock):
""" Read a message from a socket.
"""
len_buf = socket_read_n(sock, 4)
msg_len = struct.unpack('<L', len_buf)[0]
logging.debug( "SOCKET RECEIVED: %d bytes" % msg_len)
msg_buf = socket_read_n(sock, msg_len)
return msg_buf
def socket_read_n(sock,n):
""" Read exactly n bytes from the socket.
Raise RuntimeError if the connection closed before
n bytes were read.
"""
buf = b''
while n > 0:
sock.setblocking(0)
ready = select.select([sock], [], [], 3)
if ready[0]:
try:
data = sock.recv(n)
if data == b'':
raise RuntimeError('unexpected connection close')
buf += data
n -= len(data)
except socket.error:
raise socket.error
sock.setblocking(1)
return buf

98
PythonClient/carla/tcp.py Normal file
View File

@ -0,0 +1,98 @@
# 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 TCP client."""
import logging
import socket
import struct
import time
class TCPConnectionError(Exception):
pass
class TCPClient(object):
"""
Basic networking client for TCP connections. Errors occurred during
networking operations are raised as TCPConnectionError.
Received messages are expected to be prepended by a int32 defining the
message size. Messages are sent following this convention.
"""
def __init__(self, host, port, timeout):
self._host = host
self._port = port
self._timeout = timeout
self._socket = None
self._logprefix = '(%s:%s) ' % (self._host, self._port)
def connect(self, connection_attempts=10):
"""Try to establish a connection to the given host:port."""
connection_attempts = max(1, connection_attempts)
error = None
for attempt in range(1, connection_attempts + 1):
try:
self._socket = socket.create_connection(address=(self._host, self._port), timeout=self._timeout)
self._socket.settimeout(self._timeout)
logging.debug(self._logprefix + 'connected')
return
except Exception as exception:
error = exception
logging.debug(self._logprefix + 'connection attempt %d: %s', attempt, error)
time.sleep(1)
continue
self._reraise_exception_as_tcp_error('failed to connect', error)
def disconnect(self):
"""Disconnect any active connection."""
if self._socket is not None:
logging.debug(self._logprefix + 'disconnecting')
self._socket.close()
self._socket = None
def connected(self):
"""Return whether there is an active connection."""
return self._socket is not None
def write(self, message):
"""Send message to the server."""
if self._socket is None:
raise TCPConnectionError(self._logprefix + 'not connected')
header = struct.pack('<L', len(message))
try:
self._socket.sendall(header + message)
except Exception as exception:
self._reraise_exception_as_tcp_error('failed to write data', exception)
def read(self):
"""Read a message from the server."""
header = self._read_n(4)
if not header:
raise TCPConnectionError(self._logprefix + 'connection closed')
length = struct.unpack('<L', header)[0]
data = self._read_n(length)
return data
def _read_n(self, length):
"""Read n bytes from the socket."""
if self._socket is None:
raise TCPConnectionError(self._logprefix + 'not connected')
buf = bytes()
while length > 0:
try:
data = self._socket.recv(length)
except Exception as exception:
self._reraise_exception_as_tcp_error('failed to read data', exception)
if not data:
raise TCPConnectionError(self._logprefix + 'connection closed')
buf += data
length -= len(data)
return buf
def _reraise_exception_as_tcp_error(self, message, exception):
raise TCPConnectionError('%s%s: %s' % (self._logprefix, message, exception))

View File

@ -5,17 +5,14 @@
# For a copy, see <https://opensource.org/licenses/MIT>. # For a copy, see <https://opensource.org/licenses/MIT>.
import datetime import datetime
import sys
from contextlib import contextmanager from contextlib import contextmanager
def to_hex_str(header):
return ':'.join('{:02x}'.format(ord(c)) for c in header)
@contextmanager @contextmanager
def make_connection(client_type, *args, **kwargs): def make_connection(client_type, *args, **kwargs):
"""Context manager to create and connect a networking object.""" """Context manager to create and connect a networking client object."""
client = None client = None
try: try:
client = client_type(*args, **kwargs) client = client_type(*args, **kwargs)
@ -36,3 +33,29 @@ class StopWatch(object):
def milliseconds(self): def milliseconds(self):
return 1000.0 * (self.end - self.start).total_seconds() return 1000.0 * (self.end - self.start).total_seconds()
def to_hex_str(header):
return ':'.join('{:02x}'.format(ord(c)) for c in header)
if sys.version_info >= (3, 3):
import shutil
def print_over_same_line(text):
terminal_width = shutil.get_terminal_size((80, 20)).columns
empty_space = max(0, terminal_width - len(text))
sys.stdout.write('\r' + text + empty_space * ' ')
sys.stdout.flush()
else:
# Workaround for older Python versions.
def print_over_same_line(text):
line_length = max(print_over_same_line._last_line_length, len(text))
empty_space = max(0, line_length - len(text))
sys.stdout.write('\r' + text + empty_space * ' ')
sys.stdout.flush()
print_over_same_line._last_line_length = line_length
print_over_same_line._last_line_length = 0

View File

@ -1,241 +0,0 @@
#!/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 example."""
from __future__ import print_function
# General Imports
import numpy as np
from PIL import Image
import random
import time
import sys
import argparse
import logging
import os
# Carla imports, Everything can be imported directly from "carla" package
from carla import CARLA
from carla import Control
from carla import Measurements
# Constant that set how offten the episodes are reseted
RESET_FREQUENCY = 100
"""
Print function, prints all the measurements saving
the images into a folder. WARNING just prints the first BGRA image
Args:
param1: The measurements dictionary to be printed
param2: The iterations
Returns:
None
Raises:
None
"""
def print_pack(measurements,i,write_images):
if write_images:
image_result = Image.fromarray( measurements['BGRA'][0])
b, g, r,a = image_result.split()
image_result = Image.merge("RGBA", (r, g, b,a))
if not os.path.exists('images'):
os.mkdir('images')
image_result.save('images/image' + str(i) + '.png')
print ('Pack ',i)
print (' Wall Time: ',measurements['WallTime'])
print (' Game Time: ',measurements['GameTime'])
print (' Player Measurements ')
print (' Position: (%f,%f,%f)' % (measurements['PlayerMeasurements'].\
transform.location.x,measurements['PlayerMeasurements'].transform.location.y,\
measurements['PlayerMeasurements'].transform.location.z ))
print (' Orientation: (%f,%f,%f)' % (measurements['PlayerMeasurements'].\
transform.orientation.x,measurements['PlayerMeasurements'].transform.orientation.y,\
measurements['PlayerMeasurements'].transform.orientation.z ))
print (' Acceleration: (%f,%f,%f)' % (measurements['PlayerMeasurements'].\
acceleration.x,measurements['PlayerMeasurements'].acceleration.y,measurements['PlayerMeasurements'].acceleration.z ))
print (' Speed: ',measurements['PlayerMeasurements'].forward_speed)
print (' Collision Vehicles (Acum. Impact): ',measurements['PlayerMeasurements'].collision_vehicles)
print (' Collision Pedestrians (Acum. Impact): ',measurements['PlayerMeasurements'].collision_pedestrians)
print (' Collision Other (Acum. Impact): ',measurements['PlayerMeasurements'].collision_other)
print (' Intersection Opposite Lane (% Volume): ',measurements['PlayerMeasurements'].intersection_otherlane)
print (' Intersection Opposite Sidewalk (% Volume): ',measurements['PlayerMeasurements'].intersection_offroad)
print (' ',len(measurements['Agents']),' Agents (Positions not printed)')
print (' ',end='')
for agent in measurements['Agents']:
if agent.HasField('vehicle'):
print ('Car',end='')
elif agent.HasField('pedestrian'):
print ('Pedestrian',end='')
elif agent.HasField('traffic_light'):
print ('Traffic Light',end='')
elif agent.HasField('speed_limit_sign'):
print ('Speed Limit Sign',end='')
print(',',end='')
print('')
def use_example(ini_file,port = 2000, host ='127.0.0.1',print_measurements =False,images_to_disk=False):
# We assume the CARLA server is already waiting for a client to connect at
# host:port. To create a connection we can use the CARLA
# constructor, it creates a CARLA client object and starts the
# connection. It will throw an exception if something goes wrong.
carla =CARLA(host,port)
""" As a first step, Carla must have a configuration file loaded. This will load a map in the server
with the properties specified by the ini file. It returns all the posible starting positions on the map
in a vector.
"""
positions = carla.loadConfigurationFile(ini_file)
"""
Ask Server for a new episode starting on position of index zero in the positions vector
"""
carla.newEpisode(0)
capture = time.time()
# General iteratior
i = 1
# Iterator that will go over the positions on the map after each episode
iterator_start_positions = 1
while True:
try:
"""
User get the measurements dictionary from the server.
Measurements contains:
* WallTime: Current time on Wall from server machine.
* GameTime: Current time on Game. Restarts at every episode
* PlayerMeasurements : All information and events that happens to player
* Agents : All non-player agents present on the map information such as cars positions, traffic light states
* BRGA : BGRA optical images
* Depth : Depth Images
* Labels : Images containing the semantic segmentation. NOTE: the semantic segmentation must be
previously activated on the server. See documentation for that.
"""
measurements = carla.getMeasurements()
# Print all the measurements... Will write images to disk
if print_measurements:
print_pack(measurements,i,images_to_disk)
"""
Sends a control command to the server
This control structue contains the following fields:
* throttle : goes from 0 to -1
* steer : goes from -1 to 1
* brake : goes from 0 to 1
* hand_brake : Activate or desactivate the Hand Brake.
* reverse: Activate or desactive the reverse gear.
"""
control = Control()
control.throttle = 0.9
control.steer = (random.random() * 2) - 1
carla.sendCommand(control)
i+=1
if i % RESET_FREQUENCY ==0:
print ('Fps for this episode : ',(1.0/((time.time() -capture)/100.0)))
"""
Starts another new episode, the episode will have the same configuration as the previous
one. In order to change configuration, the loadConfigurationFile could be called at any
time.
"""
if iterator_start_positions < len(positions):
carla.newEpisode(iterator_start_positions)
iterator_start_positions+=1
else :
carla.newEpisode(0)
iterator_start_positions = 1
print("Now Starting on Position: ",iterator_start_positions-1)
capture = time.time()
except Exception as e:
logging.exception('Exception raised to the top')
time.sleep(1)
if __name__ == "__main__" :
parser = argparse.ArgumentParser(description='Run the carla client example that connects to a server')
parser.add_argument('host', metavar='HOST', type=str, help='host to connect to')
parser.add_argument('port', metavar='PORT', type=int, help='port to connect to')
parser.add_argument("-c", "--config", help="the path for the server ini file that the client sends",type=str,default="CarlaSettings.ini")
parser.add_argument("-l", "--log", help="activate the log file",action="store_true")
parser.add_argument("-lv", "--log_verbose", help="activate log and put the log file to screen",action="store_true")
parser.add_argument("-pm", "--print", help=" prints the game measurements",action="store_true")
parser.add_argument(
'-i', '--images-to-disk',
action='store_true',
help='save images to disk')
args = parser.parse_args()
if args.log or args.log_verbose:
LOG_FILENAME = 'log_manual_control.log'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG)
if args.log_verbose: # set of functions to put the logging to screen
root = logging.getLogger()
root.setLevel(logging.DEBUG)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
root.addHandler(ch)
else:
sys.tracebacklimit=0 # Avoid huge exception messages out of debug mode
use_example(args.config,port=args.port, host=args.host,print_measurements=args.print,images_to_disk= args.images_to_disk)

231
PythonClient/client_example.py Executable file
View File

@ -0,0 +1,231 @@
#!/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 example."""
from __future__ import print_function
import argparse
import logging
import random
import sys
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
def run_carla_client(host, port, autopilot_on, save_images_to_disk, image_filename_format, settings_filepath):
# Here we will run 3 episodes with 300 frames each.
number_of_episodes = 3
frames_per_episode = 300
# We assume the CARLA server is already waiting for a client to connect at
# host:port. To create a connection we can use the `make_carla_client`
# 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:
print('CarlaClient connected')
for episode in range(0, number_of_episodes):
# Start a new episode.
if settings_filepath is None:
# Create a CarlaSettings object. This object is a wrapper around
# the CarlaSettings.ini file. Here we set the configuration we
# want for the new episode.
settings = CarlaSettings()
settings.set(
SynchronousMode=True,
SendNonPlayerAgentsInfo=True,
NumberOfVehicles=20,
NumberOfPedestrians=40,
WeatherId=random.choice([1, 3, 7, 8, 14]))
settings.randomize_seeds()
# Now we want to add a couple of cameras to the player vehicle.
# We will collect the images produced by these cameras every
# frame.
# The default camera captures RGB images of the scene.
camera0 = Camera('CameraRGB')
# Set image resolution in pixels.
camera0.set_image_size(800, 600)
# Set its position relative to the car in centimeters.
camera0.set_position(30, 0, 130)
settings.add_sensor(camera0)
# Let's add another camera producing ground-truth depth.
camera1 = Camera('CameraDepth', PostProcessing='Depth')
camera1.set_image_size(800, 600)
camera1.set_position(30, 0, 130)
settings.add_sensor(camera1)
else:
# Alternatively, we can load these settings from a file.
with open(settings_filepath, 'r') as fp:
settings = fp.read()
# Now we load these settings into the server. The server replies
# with a scene description containing the available start spots for
# the player. Here we can provide a CarlaSettings object or a
# CarlaSettings.ini file as string.
scene = client.load_settings(settings)
# Choose one player start at random.
number_of_player_starts = len(scene.player_start_spots)
player_start = random.randint(0, max(0, number_of_player_starts - 1))
# Notify the server that we want to start the episode at the
# player_start index. This function blocks until the server is ready
# to start the episode.
print('Starting new episode...')
client.start_episode(player_start)
# Iterate every frame in the episode.
for frame in range(0, frames_per_episode):
# Read the data produced by the server this frame.
measurements, sensor_data = client.read_data()
# Print some of the measurements.
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))
# We can access the encoded data of a given image as numpy
# array using its "data" property. For instance, to get the
# depth value (normalized) at pixel X, Y
#
# depth_array = sensor_data['CameraDepth'].data
# value_at_pixel = depth_array[Y, X]
#
# Now we have to send the instructions to control the vehicle.
# If we are in synchronous mode the server will pause the
# simulation until we send this control.
if not autopilot_on:
client.send_control(
steer=random.uniform(-1.0, 1.0),
throttle=0.5,
brake=0.0,
hand_brake=False,
reverse=False)
else:
# Together with the measurements, the server has sent the
# control that the in-game autopilot would do this frame. We
# can enable autopilot by sending back this control to the
# server. We can modify it if wanted, here for instance we
# will add some noise to the steer.
control = measurements.player_measurements.autopilot_control
control.steer += random.uniform(-0.1, 0.1)
client.send_control(control)
def print_measurements(measurements):
number_of_agents = len(measurements.non_player_agents)
player_measurements = measurements.player_measurements
message = 'Vehicle at ({pos_x:.1f}, {pos_y:.1f}), '
message += '{speed:.2f} km/h, '
message += 'Collision: {{vehicles={col_cars:.0f}, pedestrians={col_ped:.0f}, other={col_other:.0f}}}, '
message += '{other_lane:.0f}% other lane, {offroad:.0f}% off-road, '
message += '({agents_num:d} non-player agents in the scene)'
message = message.format(
pos_x=player_measurements.transform.location.x / 100, # cm -> m
pos_y=player_measurements.transform.location.y / 100,
speed=player_measurements.forward_speed,
col_cars=player_measurements.collision_vehicles,
col_ped=player_measurements.collision_pedestrians,
col_other=player_measurements.collision_other,
other_lane=100 * player_measurements.intersection_otherlane,
offroad=100 * player_measurements.intersection_offroad,
agents_num=number_of_agents)
print_over_same_line(message)
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(
'-a', '--autopilot',
action='store_true',
help='enable autopilot')
argparser.add_argument(
'-i', '--images-to-disk',
action='store_true',
help='save images to disk')
argparser.add_argument(
'-c', '--carla-settings',
metavar='PATH',
default=None,
help='Path to a "CarlaSettings.ini" file')
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,
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)
print('Done.')
return
except TCPConnectionError as error:
logging.error(error)
time.sleep(1)
except Exception as exception:
logging.exception(exception)
sys.exit(1)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('\nCancelled by user. Bye!')

398
PythonClient/manual_control.py Executable file
View File

@ -0,0 +1,398 @@
#!/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>.
# Keyboard controlling for carla. Please refer to client_example for a simpler
# and more documented example.
"""
Welcome to CARLA manual control.
Use ARROWS or WASD keys for control.
W : throttle
S : brake
AD : steer
Q : toggle reverse
Space : hand-brake
R : restart level
STARTING in a moment...
"""
from __future__ import print_function
import argparse
import logging
import random
import sys
import time
try:
import pygame
from pygame.locals import *
except ImportError:
raise RuntimeError('cannot import pygame, make sure pygame package is installed')
try:
import numpy as np
except ImportError:
raise RuntimeError('cannot import numpy, make sure numpy package is installed')
from carla import image_converter
from carla import sensor
from carla.client import make_carla_client, VehicleControl
from carla.planner.map import CarlaMap
from carla.settings import CarlaSettings
from carla.tcp import TCPConnectionError
from carla.util import print_over_same_line
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
MINI_WINDOW_WIDTH = 320
MINI_WINDOW_HEIGHT = 180
def make_carla_settings():
"""Make a CarlaSettings object with the settings we need."""
settings = CarlaSettings()
settings.set(
SynchronousMode=False,
SendNonPlayerAgentsInfo=True,
NumberOfVehicles=15,
NumberOfPedestrians=30,
WeatherId=random.choice([1, 3, 7, 8, 14]))
settings.randomize_seeds()
camera0 = sensor.Camera('CameraRGB')
camera0.set_image_size(WINDOW_WIDTH, WINDOW_HEIGHT)
camera0.set_position(200, 0, 140)
camera0.set_rotation(0.0, 0.0, 0.0)
settings.add_sensor(camera0)
camera1 = sensor.Camera('CameraDepth', PostProcessing='Depth')
camera1.set_image_size(MINI_WINDOW_WIDTH, MINI_WINDOW_HEIGHT)
camera1.set_position(200, 0, 140)
camera1.set_rotation(0.0, 0.0, 0.0)
settings.add_sensor(camera1)
camera2 = sensor.Camera('CameraSemSeg', PostProcessing='SemanticSegmentation')
camera2.set_image_size(MINI_WINDOW_WIDTH, MINI_WINDOW_HEIGHT)
camera2.set_position(200, 0, 140)
camera2.set_rotation(0.0, 0.0, 0.0)
settings.add_sensor(camera2)
lidar0 = sensor.Lidar('Lidar32')
lidar0.set_position(0, 0, 250)
lidar0.set_rotation(0, 0, 0)
lidar0.set(
Channels = 32,
Range = 5000,
PointsPerSecond = 100000,
RotationFrequency = 10,
UpperFovLimit = 10,
LowerFovLimit = -30,
ShowDebugPoints = False)
settings.add_sensor(lidar0)
return settings
class Timer(object):
def __init__(self):
self.step = 0
self._lap_step = 0
self._lap_time = time.time()
def tick(self):
self.step += 1
def lap(self):
self._lap_step = self.step
self._lap_time = time.time()
def ticks_per_second(self):
return float(self.step - self._lap_step) / self.elapsed_seconds_since_lap()
def elapsed_seconds_since_lap(self):
return time.time() - self._lap_time
class CarlaGame(object):
def __init__(self, carla_client, 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._map_view = None
self._is_on_reverse = False
self._city_name = city_name
self._map = CarlaMap(city_name) if city_name is not None else None
self._map_shape = self._map.map_image.shape if city_name is not None else None
self._map_view = self._map.get_map(WINDOW_HEIGHT) if city_name is not None else None
def execute(self):
"""Launch the PyGame."""
pygame.init()
self._initialize_game()
try:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
self._on_loop()
self._on_render()
finally:
pygame.quit()
def _initialize_game(self):
if self._city_name is not None:
self._display = pygame.display.set_mode(
(WINDOW_WIDTH + int((WINDOW_HEIGHT/float(self._map.map_image.shape[0]))*self._map.map_image.shape[1]), WINDOW_HEIGHT),
pygame.HWSURFACE | pygame.DOUBLEBUF)
else:
self._display = pygame.display.set_mode(
(WINDOW_WIDTH, WINDOW_HEIGHT),
pygame.HWSURFACE | pygame.DOUBLEBUF)
logging.debug('pygame started')
self._on_new_episode()
def _on_new_episode(self):
scene = self.client.load_settings(make_carla_settings())
number_of_player_starts = len(scene.player_start_spots)
player_start = np.random.randint(number_of_player_starts)
print('Starting new episode...')
self.client.start_episode(player_start)
self._timer = Timer()
self._is_on_reverse = False
def _on_loop(self):
self._timer.tick()
measurements, sensor_data = self.client.read_data()
self._main_image = sensor_data['CameraRGB']
self._mini_view_image1 = sensor_data['CameraDepth']
self._mini_view_image2 = sensor_data['CameraSemSeg']
self._lidar_measurement = sensor_data['Lidar32']
# Print measurements every second.
if self._timer.elapsed_seconds_since_lap() > 1.0:
if self._city_name is not None:
# Function to get car position on map.
map_position = self._map.get_position_on_map([
measurements.player_measurements.transform.location.x,
measurements.player_measurements.transform.location.y,
measurements.player_measurements.transform.location.z])
# Function to get orientation of the road car is in.
lane_orientation = self._map.get_lane_orientation([
measurements.player_measurements.transform.location.x,
measurements.player_measurements.transform.location.y,
measurements.player_measurements.transform.location.z])
self._print_player_measurements_map(
measurements.player_measurements,
map_position,
lane_orientation)
else:
self._print_player_measurements(measurements.player_measurements)
# Plot position on the map as well.
self._timer.lap()
control = self._get_keyboard_control(pygame.key.get_pressed())
# Set the player position
if self._city_name is not None:
self._position = self._map.get_position_on_map([
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:
self._on_new_episode()
else:
self.client.send_control(control)
def _get_keyboard_control(self, keys):
"""
Return a VehicleControl message based on the pressed keys. Return None
if a new episode was requested.
"""
if keys[K_r]:
return None
control = VehicleControl()
if keys[K_LEFT] or keys[K_a]:
control.steer = -1.0
if keys[K_RIGHT] or keys[K_d]:
control.steer = 1.0
if keys[K_UP] or keys[K_w]:
control.throttle = 1.0
if keys[K_DOWN] or keys[K_s]:
control.brake = 1.0
if keys[K_SPACE]:
control.hand_brake = True
if keys[K_q]:
self._is_on_reverse = not self._is_on_reverse
control.reverse = self._is_on_reverse
return control
def _print_player_measurements_map(
self,
player_measurements,
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 += '{speed:.2f} km/h, '
message += '{other_lane:.0f}% other lane, {offroad:.0f}% off-road'
message = message.format(
map_x=map_position[0],
map_y=map_position[1],
ori_x=lane_orientation[0],
ori_y=lane_orientation[1],
step=self._timer.step,
fps=self._timer.ticks_per_second(),
speed=player_measurements.forward_speed,
other_lane=100 * player_measurements.intersection_otherlane,
offroad=100 * player_measurements.intersection_offroad)
print_over_same_line(message)
def _print_player_measurements(self, player_measurements):
message = 'Step {step} ({fps:.1f} FPS): '
message += '{speed:.2f} km/h, '
message += '{other_lane:.0f}% other lane, {offroad:.0f}% off-road'
message = message.format(
step=self._timer.step,
fps=self._timer.ticks_per_second(),
speed=player_measurements.forward_speed,
other_lane=100 * player_measurements.intersection_otherlane,
offroad=100 * player_measurements.intersection_offroad)
print_over_same_line(message)
def _on_render(self):
gap_x = (WINDOW_WIDTH - 2 * MINI_WINDOW_WIDTH) / 3
mini_image_y = WINDOW_HEIGHT - MINI_WINDOW_HEIGHT - gap_x
if self._main_image is not None:
array = image_converter.to_rgb_array(self._main_image)
surface = pygame.surfarray.make_surface(array.swapaxes(0, 1))
self._display.blit(surface, (0, 0))
if self._mini_view_image1 is not None:
array = image_converter.depth_to_logarithmic_grayscale(self._mini_view_image1)
surface = pygame.surfarray.make_surface(array.swapaxes(0, 1))
self._display.blit(surface, (gap_x, mini_image_y))
if self._mini_view_image2 is not None:
array = image_converter.labels_to_cityscapes_palette(
self._mini_view_image2)
surface = pygame.surfarray.make_surface(array.swapaxes(0, 1))
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['points'][:, :, :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])
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)
for agent in self._agent_positions:
if agent.HasField('vehicle'):
agent_position = self._map.get_position_on_map([
agent.vehicle.transform.location.x,
agent.vehicle.transform.location.y,
agent.vehicle.transform.location.z])
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)
self._display.blit(surface, (WINDOW_WIDTH, 0))
pygame.display.flip()
def main():
argparser = argparse.ArgumentParser(
description='CARLA Manual Control Client')
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(
'-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)')
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)
print(__doc__)
while True:
try:
with make_carla_client(args.host, args.port) as client:
game = CarlaGame(client, args.map_name)
game.execute()
break
except TCPConnectionError as error:
logging.error(error)
time.sleep(1)
except Exception as exception:
logging.exception(exception)
sys.exit(1)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('\nCancelled by user. Bye!')

View File

@ -15,8 +15,9 @@ import threading
import time import time
from .client import CarlaClient from carla.client import CarlaClient
from .settings import CarlaSettings, Camera from carla.sensor import Camera, Image
from carla.settings import CarlaSettings
class _Control(object): class _Control(object):
@ -55,7 +56,7 @@ def get_default_carla_settings(args):
NumberOfVehicles=20, NumberOfVehicles=20,
NumberOfPedestrians=40, NumberOfPedestrians=40,
WeatherId=1) WeatherId=1)
settings.add_camera(Camera('Camera1')) settings.add_sensor(Camera('Camera1'))
return str(settings) return str(settings)
@ -88,7 +89,6 @@ class CarlaClientConsole(cmd.Cmd):
self.done = False self.done = False
self.thread.start() self.thread.start()
def cleanup(self): def cleanup(self):
self.do_disconnect() self.do_disconnect()
self.done = True self.done = True
@ -129,7 +129,7 @@ class CarlaClientConsole(cmd.Cmd):
self.control = _Control() self.control = _Control()
if not self.client.connected(): if not self.client.connected():
self.client.connect() self.client.connect()
self.client.request_new_episode(self.settings) self.client.load_settings(self.settings)
self.client.start_episode(0) self.client.start_episode(0)
logging.info('new episode started') logging.info('new episode started')
except Exception as exception: except Exception as exception:
@ -165,11 +165,12 @@ class CarlaClientConsole(cmd.Cmd):
filename = '_images/console/camera_{:0>3d}/image_{:0>8d}.png' filename = '_images/console/camera_{:0>3d}/image_{:0>8d}.png'
while not self.done: while not self.done:
try: try:
measurements, images = self.client.read_measurements() measurements, sensor_data = self.client.read_data()
if self.print_measurements: if self.print_measurements:
print(measurements) print(measurements)
if self.args.images_to_disk: if self.args.images_to_disk:
images = [x for x in sensor_data.values() if isinstance(x, Image)]
for n, image in enumerate(images): for n, image in enumerate(images):
path = filename.format(n, measurements.game_timestamp) path = filename.format(n, measurements.game_timestamp)
image.save_to_disk(path) image.save_to_disk(path)

View File

@ -20,11 +20,13 @@ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import carla import carla
from carla.client import CarlaClient from carla.client import CarlaClient
from carla.console import CarlaClientConsole from carla.sensor import Camera, Image
from carla.settings import CarlaSettings, Camera from carla.settings import CarlaSettings
from carla.tcp import TCPClient from carla.tcp import TCPClient
from carla.util import make_connection from carla.util import make_connection
import console
def run_carla_client(args): def run_carla_client(args):
with make_connection(CarlaClient, args.host, args.port, timeout=15) as client: with make_connection(CarlaClient, args.host, args.port, timeout=15) as client:
@ -39,12 +41,12 @@ def run_carla_client(args):
settings.randomize_seeds() settings.randomize_seeds()
camera = Camera('DefaultCamera') camera = Camera('DefaultCamera')
camera.set_image_size(300, 200) # Do not change this, hard-coded in test. camera.set_image_size(300, 200) # Do not change this, hard-coded in test.
settings.add_camera(camera) settings.add_sensor(camera)
logging.debug('sending CarlaSettings:\n%s', settings) logging.debug('sending CarlaSettings:\n%s', settings)
logging.info('new episode requested') logging.info('new episode requested')
scene = client.request_new_episode(settings) scene = client.load_settings(settings)
number_of_player_starts = len(scene.player_start_spots) number_of_player_starts = len(scene.player_start_spots)
player_start = random.randint(0, max(0, number_of_player_starts - 1)) player_start = random.randint(0, max(0, number_of_player_starts - 1))
@ -56,12 +58,13 @@ def run_carla_client(args):
client.start_episode(player_start) client.start_episode(player_start)
use_ai_control = (random.random() < 0.5) use_autopilot_control = (random.random() < 0.5)
reverse = (random.random() < 0.2) reverse = (random.random() < 0.2)
for frame in range(0, frames_per_episode): for frame in range(0, frames_per_episode):
logging.debug('reading measurements...') logging.debug('reading measurements...')
measurements, images = client.read_measurements() measurements, sensor_data = client.read_data()
images = [x for x in sensor_data.values() if isinstance(x, Image)]
logging.debug('received data of %d agents', len(measurements.non_player_agents)) logging.debug('received data of %d agents', len(measurements.non_player_agents))
assert len(images) == 1 assert len(images) == 1
@ -71,8 +74,8 @@ def run_carla_client(args):
images[0].save_to_disk(filename.format(episode, frame)) images[0].save_to_disk(filename.format(episode, frame))
logging.debug('sending control...') logging.debug('sending control...')
control = measurements.player_measurements.ai_control control = measurements.player_measurements.autopilot_control
if not use_ai_control: if not use_autopilot_control:
control.steer = random.uniform(-1.0, 1.0) control.steer = random.uniform(-1.0, 1.0)
control.throttle = 0.3 control.throttle = 0.3
control.hand_brake = False control.hand_brake = False
@ -140,7 +143,7 @@ def main():
logging.info('listening to server %s:%s', args.host, args.port) logging.info('listening to server %s:%s', args.host, args.port)
if args.console: if args.console:
cmd = CarlaClientConsole(args) cmd = console.CarlaClientConsole(args)
try: try:
cmd.cmdloop() cmd.cmdloop()
finally: finally:

View File

@ -23,6 +23,7 @@ sys.path.append(os.path.join(os.path.dirname(__file__), '.'))
import carla import carla
from carla.tcp import TCPConnectionError
from carla.util import StopWatch from carla.util import StopWatch
from unit_tests import CarlaServerTest from unit_tests import CarlaServerTest
@ -99,14 +100,20 @@ def run_test(test, args):
logging.error('exception instantiating %r: %s', test.name, exception) logging.error('exception instantiating %r: %s', test.name, exception)
return False return False
log_test(RUN, test.name) log_test(RUN, test.name)
try: while True:
timer = StopWatch() try:
result = test.run() timer = StopWatch()
timer.stop() result = test.run()
except Exception as exception: timer.stop()
timer.stop() break
logging.error('exception: %s', exception) except TCPConnectionError as error:
result = False logging.error(error)
time.sleep(1)
except Exception as exception:
timer.stop()
logging.exception('exception: %s', exception)
result = False
break
log_test(OK if result else FAILED, '%s (%d ms)', test.name, timer.milliseconds()) log_test(OK if result else FAILED, '%s (%d ms)', test.name, timer.milliseconds())
return result return result
@ -118,9 +125,6 @@ def do_the_tests(args):
failed = [] failed = []
log_test(SEP0, 'Running %d tests.', len(tests)) log_test(SEP0, 'Running %d tests.', len(tests))
for test in tests: for test in tests:
if succeeded or failed:
logging.info('waiting for the server to be ready again')
time.sleep(7)
if run_test(test, args): if run_test(test, args):
succeeded.append(test) succeeded.append(test)
else: else:

View File

@ -4,20 +4,21 @@
# This work is licensed under the terms of the MIT license. # This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>. # For a copy, see <https://opensource.org/licenses/MIT>.
import unit_tests
import logging import logging
import random import random
import unit_tests
import carla import carla
from carla.client import CarlaClient from carla.client import CarlaClient
from carla.settings import CarlaSettings, Camera from carla.sensor import Camera, Image
from carla.settings import CarlaSettings
from carla.util import make_connection from carla.util import make_connection
class _BasicTestBase(unit_tests.CarlaServerTest): class _BasicTestBase(unit_tests.CarlaServerTest):
def run_carla_client(self, carla_settings, number_of_episodes, number_of_frames, use_ai_control=None): def run_carla_client(self, carla_settings, number_of_episodes, number_of_frames, use_autopilot_control=None):
with make_connection(CarlaClient, self.args.host, self.args.port, timeout=15) as client: with make_connection(CarlaClient, self.args.host, self.args.port, timeout=15) as client:
logging.info('CarlaClient connected, running %d episodes', number_of_episodes) logging.info('CarlaClient connected, running %d episodes', number_of_episodes)
for _ in range(0, number_of_episodes): for _ in range(0, number_of_episodes):
@ -25,7 +26,7 @@ class _BasicTestBase(unit_tests.CarlaServerTest):
carla_settings.randomize_weather() carla_settings.randomize_weather()
logging.debug('sending CarlaSettings:\n%s', carla_settings) logging.debug('sending CarlaSettings:\n%s', carla_settings)
logging.info('new episode requested') logging.info('new episode requested')
scene = client.request_new_episode(carla_settings) scene = client.load_settings(carla_settings)
number_of_player_starts = len(scene.player_start_spots) number_of_player_starts = len(scene.player_start_spots)
player_start = random.randint(0, max(0, number_of_player_starts - 1)) player_start = random.randint(0, max(0, number_of_player_starts - 1))
logging.info( logging.info(
@ -34,20 +35,21 @@ class _BasicTestBase(unit_tests.CarlaServerTest):
number_of_player_starts, number_of_player_starts,
number_of_frames) number_of_frames)
client.start_episode(player_start) client.start_episode(player_start)
if use_ai_control is None: if use_autopilot_control is None:
use_ai_control = (random.random() < 0.5) use_autopilot_control = (random.random() < 0.5)
reverse = (random.random() < 0.2) reverse = (random.random() < 0.2)
for _ in range(0, number_of_frames): for _ in range(0, number_of_frames):
logging.debug('reading measurements...') logging.debug('reading measurements...')
measurements, images = client.read_measurements() measurements, sensor_data = client.read_data()
images = [x for x in sensor_data.values() if isinstance(x, Image)]
number_of_agents = len(measurements.non_player_agents) number_of_agents = len(measurements.non_player_agents)
logging.debug('received data of %d agents', number_of_agents) logging.debug('received data of %d agents', number_of_agents)
logging.debug('received %d images', len(images)) logging.debug('received %d images', len(images))
if len(images) != len(carla_settings._cameras): if len(images) != len(carla_settings._cameras):
raise RuntimeError('received %d images, expected %d' % (len(images), len(carla_settings._cameras))) raise RuntimeError('received %d images, expected %d' % (len(images), len(carla_settings._cameras)))
logging.debug('sending control...') logging.debug('sending control...')
control = measurements.player_measurements.ai_control control = measurements.player_measurements.autopilot_control
if not use_ai_control: if not use_autopilot_control:
control.steer = random.uniform(-1.0, 1.0) control.steer = random.uniform(-1.0, 1.0)
control.throttle = 0.3 control.throttle = 0.3
control.hand_brake = False control.hand_brake = False
@ -63,7 +65,7 @@ class _BasicTestBase(unit_tests.CarlaServerTest):
class UseCase(_BasicTestBase): class UseCase(_BasicTestBase):
def run(self): def run(self):
settings = CarlaSettings() settings = CarlaSettings()
settings.add_camera(Camera('DefaultCamera')) settings.add_sensor(Camera('DefaultCamera'))
self.run_carla_client(settings, 5, 200) self.run_carla_client(settings, 5, 200)
@ -76,18 +78,18 @@ class NoCamera(_BasicTestBase):
class TwoCameras(_BasicTestBase): class TwoCameras(_BasicTestBase):
def run(self): def run(self):
settings = CarlaSettings() settings = CarlaSettings()
settings.add_camera(Camera('DefaultCamera')) settings.add_sensor(Camera('DefaultCamera'))
camera2 = Camera('Camera2') camera2 = Camera('Camera2')
camera2.set(PostProcessing='Depth', CameraFOV=120) camera2.set(PostProcessing='Depth', CameraFOV=120)
camera2.set_image_size(1924, 1028) camera2.set_image_size(1924, 1028)
settings.add_camera(camera2) settings.add_sensor(camera2)
self.run_carla_client(settings, 3, 100) self.run_carla_client(settings, 3, 100)
class SynchronousMode(_BasicTestBase): class SynchronousMode(_BasicTestBase):
def run(self): def run(self):
settings = CarlaSettings(SynchronousMode=True) settings = CarlaSettings(SynchronousMode=True)
settings.add_camera(Camera('DefaultCamera')) settings.add_sensor(Camera('DefaultCamera'))
self.run_carla_client(settings, 3, 200) self.run_carla_client(settings, 3, 200)
@ -99,12 +101,12 @@ class GetAgentsInfo(_BasicTestBase):
SendNonPlayerAgentsInfo=True, SendNonPlayerAgentsInfo=True,
NumberOfVehicles=60, NumberOfVehicles=60,
NumberOfPedestrians=90) NumberOfPedestrians=90)
settings.add_camera(Camera('DefaultCamera')) settings.add_sensor(Camera('DefaultCamera'))
self.run_carla_client(settings, 3, 100) self.run_carla_client(settings, 3, 100)
class LongEpisode(_BasicTestBase): class LongEpisode(_BasicTestBase):
def run(self): def run(self):
settings = CarlaSettings() settings = CarlaSettings()
settings.add_camera(Camera('DefaultCamera')) settings.add_sensor(Camera('DefaultCamera'))
self.run_carla_client(settings, 1, 2000, use_ai_control=True) self.run_carla_client(settings, 1, 2000, use_autopilot_control=True)

View File

@ -16,6 +16,25 @@ environmental conditions.
For instructions on how to use and compile CARLA, check out For instructions on how to use and compile CARLA, check out
[CARLA Documentation](http://carla.readthedocs.io). [CARLA Documentation](http://carla.readthedocs.io).
News
----
- 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).
Roadmap
-------
We are continuously working on improving CARLA, and we appreciate contributions
from the community. Our most immediate goals are:
- Releasing the methods evaluated in the CARLA paper
- Adding a LiDAR sensor
- Allowing for flexible and user-friendly import and editing of maps
- Allowing the users to control non-player characters (and therefore set up user-specified scenarios)
We will post a detailed roadmap and contribution guidelines soon - stay tuned!
Paper Paper
----- -----

View File

@ -22,32 +22,12 @@ command -v clang++-3.9 >/dev/null 2>&1 || {
exit 1; exit 1;
} }
# Update content.
./Update.sh
mkdir -p Util/Build mkdir -p Util/Build
pushd Util/Build >/dev/null pushd Util/Build >/dev/null
# ==============================================================================
# -- Download the content ------------------------------------------------------
# ==============================================================================
CONTENT_FOLDER=$SCRIPT_DIR/Unreal/CarlaUE4/Content
CONTENT_GDRIVE_ID=$(tac $SCRIPT_DIR/Util/ContentVersions.txt | egrep -m 1 . | rev | cut -d' ' -f1 | rev)
if [[ ! -d "$CONTENT_FOLDER/.git" ]]; then
if [[ -d "$CONTENT_FOLDER" ]]; then
echo "Backing up existing Content..."
mv -v "$CONTENT_FOLDER" "${CONTENT_FOLDER}_$(date +%Y%m%d%H%M%S)"
fi
mkdir -p $CONTENT_FOLDER
mkdir -p Content
../download_from_gdrive.py $CONTENT_GDRIVE_ID Content.tar.gz
tar -xvzf Content.tar.gz -C Content
rm Content.tar.gz
mv Content/* $CONTENT_FOLDER
else
echo "Using git version of 'Content', skipping download..."
fi
# ============================================================================== # ==============================================================================
# -- Get and compile libc++ ---------------------------------------------------- # -- Get and compile libc++ ----------------------------------------------------
# ============================================================================== # ==============================================================================
@ -175,7 +155,8 @@ popd >/dev/null
CARLA_SETTINGS_FILE="./Unreal/CarlaUE4/Config/CarlaSettings.ini" CARLA_SETTINGS_FILE="./Unreal/CarlaUE4/Config/CarlaSettings.ini"
if [[ ! -f $CARLA_SETTINGS_FILE ]]; then if [[ ! -f $CARLA_SETTINGS_FILE ]]; then
cp -v ./Docs/Example.CarlaSettings.ini $CARLA_SETTINGS_FILE echo "Copying CarlaSettings.ini..."
sed -e 's/UseNetworking=true/UseNetworking=false/' ./Docs/Example.CarlaSettings.ini > $CARLA_SETTINGS_FILE
fi fi
./Util/Protoc.sh ./Util/Protoc.sh

View File

@ -18,7 +18,7 @@ PrecipitationType=Rain
PrecipitationAmount=0 PrecipitationAmount=0
PrecipitationAccumulation=0 PrecipitationAccumulation=0
bWind=False bWind=False
WindIntensity=20 WindIntensity=40
WindAngle=0 WindAngle=0
bOverrideCameraPostProcessParameters=True bOverrideCameraPostProcessParameters=True
CameraPostProcessParameters.AutoExposureMethod=Histogram CameraPostProcessParameters.AutoExposureMethod=Histogram
@ -46,7 +46,7 @@ PrecipitationType=Rain
PrecipitationAmount=0 PrecipitationAmount=0
PrecipitationAccumulation=0 PrecipitationAccumulation=0
bWind=False bWind=False
WindIntensity=20 WindIntensity=40
WindAngle=0 WindAngle=0
bOverrideCameraPostProcessParameters=True bOverrideCameraPostProcessParameters=True
CameraPostProcessParameters.AutoExposureMethod=Histogram CameraPostProcessParameters.AutoExposureMethod=Histogram

View File

@ -158,7 +158,7 @@ PrecipitationType=Rain
PrecipitationAmount=40 PrecipitationAmount=40
PrecipitationAccumulation=50 PrecipitationAccumulation=50
bWind=False bWind=False
WindIntensity=20 WindIntensity=40
WindAngle=0 WindAngle=0
bOverrideCameraPostProcessParameters=True bOverrideCameraPostProcessParameters=True
CameraPostProcessParameters.AutoExposureMethod=Histogram CameraPostProcessParameters.AutoExposureMethod=Histogram
@ -186,7 +186,7 @@ PrecipitationType=Rain
PrecipitationAmount=80 PrecipitationAmount=80
PrecipitationAccumulation=87.248 PrecipitationAccumulation=87.248
bWind=False bWind=False
WindIntensity=20 WindIntensity=40
WindAngle=0 WindAngle=0
bOverrideCameraPostProcessParameters=True bOverrideCameraPostProcessParameters=True
CameraPostProcessParameters.AutoExposureMethod=Histogram CameraPostProcessParameters.AutoExposureMethod=Histogram
@ -333,19 +333,19 @@ CameraPostProcessParameters.AutoExposureBias=-3.5
[MidRainSunset] [MidRainSunset]
SunPolarAngle=86 SunPolarAngle=86
SunAzimuthAngle=0.0 SunAzimuthAngle=0
SunBrightness=13.761 SunBrightness=12.381
SunDirectionalLightIntensity=12.587 SunDirectionalLightIntensity=5.714
SunDirectionalLightColor=(R=0.810000,G=0.347162,B=0.083003,A=1.000000) SunDirectionalLightColor=(R=0.810000,G=0.347162,B=0.083003,A=1.000000)
SunIndirectLightIntensity=6 SunIndirectLightIntensity=6
CloudOpacity=44.037 CloudOpacity=17.143
HorizontFalloff=1.835 HorizontFalloff=1.835
ZenithColor=(R=0.360000,G=0.000000,B=0.025421,A=1.000000) ZenithColor=(R=0.317708,G=0.208096,B=0.260868,A=1.000000)
HorizonColor=(R=1.000000,G=0.590000,B=0.000000,A=1.000000) HorizonColor=(R=1.000000,G=0.590000,B=0.000000,A=1.000000)
CloudColor=(R=0.555000,G=0.290880,B=0.066600,A=1.000000) CloudColor=(R=0.555000,G=0.290880,B=0.066600,A=1.000000)
OverallSkyColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000) OverallSkyColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000)
SkyLightIntensity=7.339 SkyLightIntensity=6.667
SkyLightColor=(R=0.086250,G=0.159340,B=0.750000,A=0.000000) SkyLightColor=(R=0.214844,G=0.273773,B=0.750000,A=0.000000)
bPrecipitation=True bPrecipitation=True
PrecipitationType=Rain PrecipitationType=Rain
PrecipitationAmount=37.156 PrecipitationAmount=37.156
@ -361,19 +361,19 @@ CameraPostProcessParameters.AutoExposureBias=-3.5
[HardRainSunset] [HardRainSunset]
SunPolarAngle=86 SunPolarAngle=86
SunAzimuthAngle=0.0 SunAzimuthAngle=0
SunBrightness=13.761 SunBrightness=0.952
SunDirectionalLightIntensity=12.587 SunDirectionalLightIntensity=3.063
SunDirectionalLightColor=(R=0.810000,G=0.347162,B=0.083003,A=1.000000) SunDirectionalLightColor=(R=0.810000,G=0.347162,B=0.083003,A=1.000000)
SunIndirectLightIntensity=6 SunIndirectLightIntensity=6
CloudOpacity=44.037 CloudOpacity=17.37
HorizontFalloff=1.835 HorizontFalloff=1.835
ZenithColor=(R=0.360000,G=0.000000,B=0.025421,A=1.000000) ZenithColor=(R=0.307292,G=0.161669,B=0.123237,A=1.000000)
HorizonColor=(R=1.000000,G=0.590000,B=0.000000,A=1.000000) HorizonColor=(R=0.453125,G=0.297809,B=0.228923,A=1.000000)
CloudColor=(R=0.555000,G=0.290880,B=0.066600,A=1.000000) CloudColor=(R=0.416667,G=0.288257,B=0.189558,A=1.000000)
OverallSkyColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000) OverallSkyColor=(R=1.000000,G=0.736403,B=0.487039,A=1.000000)
SkyLightIntensity=7.339 SkyLightIntensity=5.81
SkyLightColor=(R=0.086250,G=0.159340,B=0.750000,A=0.000000) SkyLightColor=(R=0.500000,G=0.383356,B=0.250000,A=0.000000)
bPrecipitation=True bPrecipitation=True
PrecipitationType=Rain PrecipitationType=Rain
PrecipitationAmount=84.862 PrecipitationAmount=84.862

View File

@ -3,7 +3,7 @@ ProjectID=675BF8694238308FA9368292CC440350
ProjectName=CARLA UE4 ProjectName=CARLA UE4
CompanyName=CVC CompanyName=CVC
CopyrightNotice="Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonomade 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>." CopyrightNotice="Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonomade 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>."
ProjectVersion=0.6.0 ProjectVersion=0.7.0
[/Script/UnrealEd.ProjectPackagingSettings] [/Script/UnrealEd.ProjectPackagingSettings]
BuildConfiguration=PPBC_Development BuildConfiguration=PPBC_Development

View File

@ -1,7 +1,7 @@
{ {
"FileVersion": 3, "FileVersion": 3,
"Version": 1, "Version": 1,
"VersionName": "0.6.0", "VersionName": "0.7.0",
"FriendlyName": "CARLA", "FriendlyName": "CARLA",
"Description": "", "Description": "",
"Category": "Science", "Category": "Science",

View File

@ -195,6 +195,9 @@ void UCarlaSettings::LoadSettings()
} }
// Override settings from command-line. // Override settings from command-line.
{ {
if (FParse::Param(FCommandLine::Get(), TEXT("carla-server"))) {
bUseNetworking = true;
}
uint32 Value; uint32 Value;
if (FParse::Value(FCommandLine::Get(), TEXT("-world-port="), Value) || if (FParse::Value(FCommandLine::Get(), TEXT("-world-port="), Value) ||
FParse::Value(FCommandLine::Get(), TEXT("-carla-world-port="), Value)) { FParse::Value(FCommandLine::Get(), TEXT("-carla-world-port="), Value)) {

View File

@ -73,7 +73,7 @@ public:
/** If active, wait for the client to connect and control the pawn. */ /** If active, wait for the client to connect and control the pawn. */
UPROPERTY(Category = "CARLA Server", VisibleAnywhere) UPROPERTY(Category = "CARLA Server", VisibleAnywhere)
bool bUseNetworking = true; bool bUseNetworking = false;
/** World port to listen for client connections. */ /** World port to listen for client connections. */
UPROPERTY(Category = "CARLA Server", VisibleAnywhere, meta = (EditCondition = bUseNetworking)) UPROPERTY(Category = "CARLA Server", VisibleAnywhere, meta = (EditCondition = bUseNetworking))

45
Update.sh Executable file
View File

@ -0,0 +1,45 @@
#! /bin/bash
################################################################################
# Updates CARLA contents.
################################################################################
set -e
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
pushd "$SCRIPT_DIR" >/dev/null
CONTENT_FOLDER=$SCRIPT_DIR/Unreal/CarlaUE4/Content
CONTENT_GDRIVE_ID=$(tac $SCRIPT_DIR/Util/ContentVersions.txt | egrep -m 1 . | rev | cut -d' ' -f1 | rev)
VERSION_FILE=${CONTENT_FOLDER}/.version
function download_content {
if [[ -d "$CONTENT_FOLDER" ]]; then
echo "Backing up existing Content..."
mv -v "$CONTENT_FOLDER" "${CONTENT_FOLDER}_$(date +%Y%m%d%H%M%S)"
fi
mkdir -p $CONTENT_FOLDER
mkdir -p Content
./Util/download_from_gdrive.py $CONTENT_GDRIVE_ID Content.tar.gz
tar -xvzf Content.tar.gz -C Content
rm Content.tar.gz
mv Content/* $CONTENT_FOLDER
echo "$CONTENT_GDRIVE_ID" > "$VERSION_FILE"
echo "Content updated successfully."
}
if [[ -d "$CONTENT_FOLDER/.git" ]]; then
echo "Using git version of 'Content', skipping update."
elif [[ -f "$CONTENT_FOLDER/.version" ]]; then
if [ "$CONTENT_GDRIVE_ID" == `cat $VERSION_FILE` ]; then
echo "Content is up-to-date."
else
download_content
fi
else
download_content
fi
popd >/dev/null

View File

@ -126,7 +126,7 @@ namespace server {
player->set_collision_other(values.player_measurements.collision_other); player->set_collision_other(values.player_measurements.collision_other);
player->set_intersection_otherlane(values.player_measurements.intersection_otherlane); player->set_intersection_otherlane(values.player_measurements.intersection_otherlane);
player->set_intersection_offroad(values.player_measurements.intersection_offroad); player->set_intersection_offroad(values.player_measurements.intersection_offroad);
Set(player->mutable_ai_control(), values.player_measurements.ai_control); Set(player->mutable_autopilot_control(), values.player_measurements.ai_control);
// Non-player agents. // Non-player agents.
message->clear_non_player_agents(); // we need to clear as we cache the message. message->clear_non_player_agents(); // we need to clear as we cache the message.
for (auto &agent : agents(values)) { for (auto &agent : agents(values)) {

View File

@ -66,7 +66,7 @@ namespace server {
auto begin = buffer; auto begin = buffer;
for (const auto &lidar_measurement : lidar_measurements) { for (const auto &lidar_measurement : lidar_measurements) {
begin += WriteDoubleToBuffer(begin, lidar_measurement.horizontal_angle); begin += WriteDoubleToBuffer(begin, lidar_measurement.horizontal_angle);
begin += WriteIntToBuffer(begin, 10); // type of lidar message begin += WriteIntToBuffer(begin, 4); // type of lidar message
begin += WriteIntToBuffer(begin, lidar_measurement.channels_count); begin += WriteIntToBuffer(begin, lidar_measurement.channels_count);
begin += WriteLidarMeasurementToBuffer(begin, lidar_measurement); begin += WriteLidarMeasurementToBuffer(begin, lidar_measurement);
} }

View File

@ -6,3 +6,4 @@
0.5.4: 0B2HFV-VuKn3PYUFFanlmZ2VMTW8 0.5.4: 0B2HFV-VuKn3PYUFFanlmZ2VMTW8
0.6.0: 1Gw8sw01hDEV4FtpHEZZwvS-6XN0jmaLT 0.6.0: 1Gw8sw01hDEV4FtpHEZZwvS-6XN0jmaLT
0.7.0: 11PKC_lG7L80L1ZxiMlzV17utU45UcRnT

View File

@ -1,3 +1,3 @@
./bin bin
./images images
./converted_images converted_images

View File

@ -111,7 +111,7 @@ message Measurements {
float intersection_otherlane = 8; float intersection_otherlane = 8;
float intersection_offroad = 9; float intersection_offroad = 9;
Control ai_control = 10; Control autopilot_control = 10;
} }
uint32 platform_timestamp = 1; uint32 platform_timestamp = 1;

View File

@ -2,16 +2,14 @@
set PROTOBUF_SRC_DIR=Proto set PROTOBUF_SRC_DIR=Proto
set PROTOBUF_CPP_OUT_DIR=CarlaServer/source/carla/server set PROTOBUF_CPP_OUT_DIR=CarlaServer/source/carla/server
set PROTOBUF_PY_OUT_DIR0=../PythonClient/carla/protoc set PROTOBUF_PY_OUT_DIR=../PythonClient/carla
set PROTOBUF_PY_OUT_DIR1=TestingClient/carla
set PROTO_BASENAME=carla_server set PROTO_BASENAME=carla_server
if "%1" == "--clean" ( if "%1" == "--clean" (
rem Delete existing ones. rem Delete existing ones.
rm -f %PROTOBUF_CPP_OUT_DIR%/carla_server.pb.h rm -f %PROTOBUF_CPP_OUT_DIR%/carla_server.pb.h
rm -f %PROTOBUF_CPP_OUT_DIR%/carla_server.pb.cc rm -f %PROTOBUF_CPP_OUT_DIR%/carla_server.pb.cc
rm -f %PROTOBUF_PY_OUT_DIR0%/carla_server_pb2.py rm -f %PROTOBUF_PY_OUT_DIR%/carla_server_pb2.py
rm -f %PROTOBUF_PY_OUT_DIR1%/carla_server_pb2.py
goto end goto end
) )
@ -24,8 +22,7 @@ if exist %PROTOC% (
%PROTOC% ^ %PROTOC% ^
-I=%PROTOBUF_SRC_DIR% ^ -I=%PROTOBUF_SRC_DIR% ^
--cpp_out=%PROTOBUF_CPP_OUT_DIR% ^ --cpp_out=%PROTOBUF_CPP_OUT_DIR% ^
--python_out=%PROTOBUF_PY_OUT_DIR0% ^ --python_out=%PROTOBUF_PY_OUT_DIR% ^
--python_out=%PROTOBUF_PY_OUT_DIR1% ^
%PROTOBUF_SRC_DIR%/%PROTO_BASENAME%.proto %PROTOBUF_SRC_DIR%/%PROTO_BASENAME%.proto
echo done. echo done.

View File

@ -7,15 +7,13 @@ pushd "$SCRIPT_DIR" >/dev/null
PROTOBUF_SRC_DIR=Proto PROTOBUF_SRC_DIR=Proto
PROTOBUF_CPP_OUT_DIR=CarlaServer/source/carla/server PROTOBUF_CPP_OUT_DIR=CarlaServer/source/carla/server
PROTOBUF_PY_OUT_DIR0=../PythonClient/carla/protoc PROTOBUF_PY_OUT_DIR=../PythonClient/carla
PROTOBUF_PY_OUT_DIR1=TestingClient/carla
PROTO_BASENAME=carla_server PROTO_BASENAME=carla_server
if [ "$1" == "--clean" ]; then if [ "$1" == "--clean" ]; then
# Delete existing ones. # Delete existing ones.
rm -f ${PROTOBUF_CPP_OUT_DIR}/*.pb.h ${PROTOBUF_CPP_OUT_DIR}/*.pb.cc rm -f ${PROTOBUF_CPP_OUT_DIR}/*.pb.h ${PROTOBUF_CPP_OUT_DIR}/*.pb.cc
rm -f ${PROTOBUF_PY_OUT_DIR0}/*_pb2.py rm -f ${PROTOBUF_PY_OUT_DIR}/*_pb2.py
rm -f ${PROTOBUF_PY_OUT_DIR1}/*_pb2.py
exit 0 exit 0
fi fi
@ -33,8 +31,7 @@ echo "Compiling ${PROTO_BASENAME}.proto..."
${PROTOC} \ ${PROTOC} \
-I=${PROTOBUF_SRC_DIR} \ -I=${PROTOBUF_SRC_DIR} \
--cpp_out=${PROTOBUF_CPP_OUT_DIR} \ --cpp_out=${PROTOBUF_CPP_OUT_DIR} \
--python_out=${PROTOBUF_PY_OUT_DIR0} \ --python_out=${PROTOBUF_PY_OUT_DIR} \
--python_out=${PROTOBUF_PY_OUT_DIR1} \
${PROTOBUF_SRC_DIR}/${PROTO_BASENAME}.proto ${PROTOBUF_SRC_DIR}/${PROTO_BASENAME}.proto
popd >/dev/null popd >/dev/null

View File

@ -1,12 +0,0 @@
CARLA Client for Testing
========================
Requires Python 3 and the protobuf module installed, saving images to disk
requires the PIL module too.
$ sudo apt-get install python3 python3-pip
$ sudo pip3 install protobuf
A sample Python script explaining how to use the client API is provided
$ ./client_example.py --help

View File

@ -1,161 +0,0 @@
# 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>.
"""CARLA Client."""
import os
import struct
from contextlib import contextmanager
from . import tcp
from . import util
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')
@contextmanager
def make_carla_client(host, world_port, timeout=15):
with util.make_connection(CarlaClient, host, world_port, timeout) as client:
yield client
class CarlaClient(object):
def __init__(self, host, world_port, timeout=15):
self._world_client = tcp.TCPClient(host, world_port, timeout)
self._stream_client = tcp.TCPClient(host, world_port + 1, timeout)
self._control_client = tcp.TCPClient(host, world_port + 2, timeout)
def connect(self):
self._world_client.connect()
def disconnect(self):
self._control_client.disconnect()
self._stream_client.disconnect()
self._world_client.disconnect()
def connected(self):
return self._world_client.connected()
def request_new_episode(self, carla_settings):
"""Request a new episode. carla_settings object must be convertible to
a str holding a CarlaSettings.ini.
Returns a protobuf object holding the scene description.
"""
# Disconnect agent clients.
self._stream_client.disconnect()
self._control_client.disconnect()
# Send new episode request.
pb_message = carla_protocol.RequestNewEpisode()
pb_message.ini_file = str(carla_settings)
self._world_client.write(pb_message.SerializeToString())
# Read scene description.
data = self._world_client.read()
if not data:
raise RuntimeError('failed to read data from server')
pb_message = carla_protocol.SceneDescription()
pb_message.ParseFromString(data)
if len(pb_message.player_start_spots) < 1:
raise RuntimeError("received 0 player start spots")
return pb_message
def start_episode(self, player_start_index):
"""Start the new episode at the player start given by the
player_start_index. The list of player starts is retrieved by
request_new_episode().
This function waits until the server answers with an EpisodeReady.
"""
pb_message = carla_protocol.EpisodeStart()
pb_message.player_start_spot_index = player_start_index
self._world_client.write(pb_message.SerializeToString())
# Wait for EpisodeReady.
data = self._world_client.read()
if not data:
raise RuntimeError('failed to read data from server')
pb_message = carla_protocol.EpisodeReady()
pb_message.ParseFromString(data)
if not pb_message.ready:
raise RuntimeError('cannot start episode: server failed to start episode')
# We can start the agent clients now.
self._stream_client.connect()
self._control_client.connect()
def read_measurements(self):
"""Read measuremnts of current frame. The episode must be started.
Return the protobuf object with the measurements followed by the raw
data with the images.
"""
# Read measurements.
data = self._stream_client.read()
if not data:
raise RuntimeError('failed to read data from server')
pb_message = carla_protocol.Measurements()
pb_message.ParseFromString(data)
# Read images.
images_raw_data = self._stream_client.read()
return pb_message, CarlaImage.parse_raw_data(images_raw_data)
def send_control(self, *args, **kwargs):
"""Send vehicle control for the current frame."""
if isinstance(args[0] if args else None, carla_protocol.Control):
pb_message = args[0]
else:
pb_message = carla_protocol.Control()
pb_message.steer = kwargs.get('steer', 0.0)
pb_message.throttle = kwargs.get('throttle', 0.0)
pb_message.brake = kwargs.get('brake', 0.0)
pb_message.hand_brake = kwargs.get('hand_brake', False)
pb_message.reverse = kwargs.get('reverse', False)
self._control_client.write(pb_message.SerializeToString())
class CarlaImage(object):
@staticmethod
def parse_raw_data(raw_data):
getval = lambda index: struct.unpack('<L', raw_data[index*4:index*4+4])[0]
images = []
total_size = len(raw_data) / 4
index = 0
while index < total_size:
width = getval(index)
height = getval(index + 1)
image_type = getval(index + 2)
begin = index + 3
end = begin + width * height
images.append(CarlaImage(width, height, image_type, raw_data[begin*4:end*4]))
index = end
return images
def __init__(self, width, height, image_type, raw_data):
assert len(raw_data) == 4 * width * height
self.width = width
self.height = height
self.image_type = image_type
self.raw = raw_data
def save_to_disk(self, filename):
try:
from PIL import Image
except ImportError:
raise RuntimeError('cannot import PIL, make sure pillow package is installed')
image = Image.frombytes(
mode='RGBA',
size=(self.width, self.height),
data=self.raw,
decoder_name='raw')
b, g, r, a = image.split()
image = Image.merge("RGB", (r, g, b))
folder = os.path.dirname(filename)
if not os.path.isdir(folder):
os.makedirs(folder)
image.save(filename)

View File

@ -1,62 +0,0 @@
# 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 TCP client."""
import logging
import socket
import struct
class TCPClient(object):
def __init__(self, host, port, timeout):
self._host = host
self._port = port
self._timeout = timeout
self._socket = None
def connect(self):
self._socket = socket.create_connection(address=(self._host, self._port), timeout=self._timeout)
self._socket.settimeout(self._timeout)
self._log('connected')
def disconnect(self):
if self._socket is not None:
self._log('disconnecting...')
self._socket.close()
self._socket = None
def connected(self):
return self._socket is not None
def write(self, message):
if self._socket is None:
raise RuntimeError('%s:%s not connected' % (self._host, self._port))
header = struct.pack('<L', len(message))
self._socket.sendall(header + message)
def read(self):
header = self._read_n(4)
if not header:
raise RuntimeError('%s:%s connection closed' % (self._host, self._port))
length = struct.unpack('<L', header)[0]
data = self._read_n(length)
return data
def _read_n(self, length):
if self._socket is None:
raise RuntimeError('%s:%s not connected' % (self._host, self._port))
buf = bytes()
while length > 0:
data = self._socket.recv(length)
if not data:
raise RuntimeError('%s:%s connection closed' % (self._host, self._port))
buf += data
length -= len(data)
return buf
def _log(self, message, *args):
logging.debug('tcpclient %s:%d - ' + message, self._host, self._port, *args)

View File

@ -1,215 +0,0 @@
#!/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 example."""
import argparse
import logging
import random
import shutil
import sys
import time
from carla.client import make_carla_client
from carla.console import CarlaClientConsole
from carla.settings import CarlaSettings, Camera
def run_carla_client(host, port, autopilot_on, save_images_to_disk, image_filename_format):
# Here we will run 3 episodes with 300 frames each.
number_of_episodes = 3
frames_per_episode = 300
# We assume the CARLA server is already waiting for a client to connect at
# host:port. To create a connection we can use the `make_carla_client`
# 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:
print('CarlaClient connected')
for episode in range(0, number_of_episodes):
# Start a new episode.
# Create a CarlaSettings object. This object is a handy wrapper
# around the CarlaSettings.ini file. Here we set the configuration
# we want for the new episode.
settings = CarlaSettings()
settings.set(
SynchronousMode=True,
NumberOfVehicles=30,
NumberOfPedestrians=50,
WeatherId=random.choice([1, 3, 7, 8, 14]))
settings.randomize_seeds()
# Now we want to add a couple of cameras to the player vehicle. We
# will collect the images produced by these cameras every frame.
# The default camera captures RGB images of the scene.
camera0 = Camera('CameraRGB')
# Set image resolution in pixels.
camera0.set_image_size(800, 600)
# Set its position relative to the car in centimeters.
camera0.set_position(30, 0, 130)
settings.add_camera(camera0)
# Let's add another camera producing ground-truth depth.
camera1 = Camera('CameraDepth', PostProcessing='Depth')
camera1.set_image_size(800, 600)
camera1.set_position(30, 0, 130)
settings.add_camera(camera1)
print('Requesting new episode...')
# Now we request a new episode with these settings. The server
# replies with a scene description containing the available start
# spots for the player. Here instead of a CarlaSettings object we
# could also provide a CarlaSettings.ini file as string.
scene = client.request_new_episode(settings)
# Choose one player start at random.
number_of_player_starts = len(scene.player_start_spots)
player_start = random.randint(0, max(0, number_of_player_starts - 1))
# Notify the server that we want to start the episode at
# `player_start`. This function blocks until the server is ready to
# start the episode.
client.start_episode(player_start)
# Iterate every frame in the episode.
for frame in range(0, frames_per_episode):
# Read the measurements and images produced by the server this
# frame.
measurements, images = client.read_measurements()
# Print some of the measurements we received.
print_player_measurements(measurements.player_measurements)
# Save the images to disk if requested.
if save_images_to_disk:
for n, image in enumerate(images):
image.save_to_disk(image_filename_format.format(episode, n, frame))
# Now we have to send the instructions to control the vehicle.
# If we are in synchronous mode the server will pause the
# simulation until we send this control.
if not autopilot_on:
client.send_control(
steer=random.uniform(-1.0, 1.0),
throttle=0.3,
brake=False,
hand_brake=False,
reverse=False)
else:
# Together with the measurements, the server has sent the
# control that the in-game AI would do this frame. We can
# enable autopilot by sending back this control to the
# server. Here we will also add some noise to the steer.
control = measurements.player_measurements.ai_control
control.steer += random.uniform(-0.1, 0.1)
client.send_control(control)
print('Done.')
return True
def print_player_measurements(player_measurements):
message = 'Vehicle at ({pos_x:.1f}, {pos_y:.1f}, {pos_z:.1f}) '
message += '{speed:.2f} km/h, '
message += '{other_lane:.0f}% other lane, {offroad:.0f}% off-road'
message = message.format(
pos_x=player_measurements.transform.location.x / 100, # cm -> m
pos_y=player_measurements.transform.location.y / 100,
pos_z=player_measurements.transform.location.z / 100,
speed=player_measurements.forward_speed,
other_lane=100 * player_measurements.intersection_otherlane,
offroad=100 * player_measurements.intersection_offroad)
empty_space = shutil.get_terminal_size((80, 20)).columns - len(message)
sys.stdout.write('\r' + message + empty_space * ' ')
sys.stdout.flush()
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='127.0.0.1',
help='IP of the host server (default: 127.0.0.1)')
argparser.add_argument(
'-p', '--port',
metavar='P',
default=2000,
type=int,
help='TCP port to listen to (default: 2000)')
argparser.add_argument(
'-a', '--autopilot',
action='store_true',
help='enable autopilot')
argparser.add_argument(
'-i', '--images-to-disk',
action='store_true',
help='save images to disk')
argparser.add_argument(
'-c', '--console',
action='store_true',
help='start the client console')
args = argparser.parse_args()
log_level = logging.DEBUG if args.debug else logging.INFO
logging.basicConfig(format='carla_client: %(levelname)s: %(message)s', level=log_level)
logging.info('listening to server %s:%s', args.host, args.port)
if args.console:
args.synchronous = True
cmd = CarlaClientConsole(args)
try:
cmd.cmdloop()
finally:
cmd.cleanup()
return
while True:
try:
end = 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}/camera_{:0>3d}/image_{:0>5d}.png')
if end:
return
except Exception as exception:
logging.error('exception: %s', exception)
time.sleep(1)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('\nCancelled by user. Bye!')

View File

@ -9,12 +9,14 @@ pages:
- 'CARLA Settings': 'carla_settings.md' - 'CARLA Settings': 'carla_settings.md'
- 'Measurements': 'measurements.md' - 'Measurements': 'measurements.md'
- 'Cameras and sensors': 'cameras_and_sensors.md' - 'Cameras and sensors': 'cameras_and_sensors.md'
- 'F.A.Q.': 'faq.md'
- 'Troubleshooting': 'troubleshooting.md' - 'Troubleshooting': 'troubleshooting.md'
- Building from source: - Building from source:
- 'How to build on Linux': 'how_to_build_on_linux.md' - 'How to build on Linux': 'how_to_build_on_linux.md'
- 'How to build on Windows': 'how_to_build_on_windows.md' - 'How to build on Windows': 'how_to_build_on_windows.md'
- 'How to add Automotive Materials': 'how_to_add_automotive_materials.md' - 'How to add Automotive Materials': 'how_to_add_automotive_materials.md'
- Development: - Development:
- 'Map customization': 'map_customization.md'
- 'How to add assets': 'how_to_add_assets.md' - 'How to add assets': 'how_to_add_assets.md'
- 'CarlaServer documentation': 'carla_server.md' - 'CarlaServer documentation': 'carla_server.md'