Merge branch 'master' into fix-map-convertions
This commit is contained in:
commit
3e36f99da4
|
@ -0,0 +1,16 @@
|
|||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 60
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- backlog
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
|
@ -1,31 +1,38 @@
|
|||
Build
|
||||
Dist
|
||||
Doxygen
|
||||
PythonClient/dist
|
||||
Util/Build
|
||||
Install
|
||||
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
*.a
|
||||
*.egg-info
|
||||
*.kdev4
|
||||
*.log
|
||||
*.pb.cc
|
||||
*.pb.h
|
||||
*.o
|
||||
*.pid
|
||||
*.pri
|
||||
*.pro
|
||||
*.py[cod]
|
||||
*.sln
|
||||
*.so
|
||||
*.stackdump
|
||||
*.sublime-workspace
|
||||
*.workspace
|
||||
*CodeCompletionFolders.txt
|
||||
*CodeLitePreProcessor.txt
|
||||
.codelite
|
||||
.gdb_history
|
||||
.tags*
|
||||
.vs
|
||||
__pycache__
|
||||
_benchmarks_results
|
||||
_images*
|
||||
_out
|
||||
_out*
|
||||
_site
|
||||
core
|
||||
profiler.csv
|
||||
|
|
52
.travis.yml
52
.travis.yml
|
@ -1,34 +1,50 @@
|
|||
language: python
|
||||
language: cpp
|
||||
compiler: clang
|
||||
|
||||
os: linux
|
||||
dist: trusty # xenial is not yet supported.
|
||||
|
||||
env: TEST="Pylint"
|
||||
python:
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
- "2.7"
|
||||
install:
|
||||
- pip install -r PythonClient/requirements.txt
|
||||
- pip install pylint
|
||||
script:
|
||||
- pylint --disable=R,C --rcfile=PythonClient/.pylintrc PythonClient/carla PythonClient/*.py
|
||||
dist: trusty
|
||||
sudo: false
|
||||
|
||||
matrix:
|
||||
include:
|
||||
|
||||
- env: TEST="CppCheck"
|
||||
install: true
|
||||
- env: TEST="Unit Tests"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-5.0
|
||||
packages:
|
||||
- g++-7 # we need this one for the libstdc++.
|
||||
- clang-5.0
|
||||
- ninja-build
|
||||
- python
|
||||
- python-pip
|
||||
- python3
|
||||
- python3-pip
|
||||
- libboost-python-dev
|
||||
install:
|
||||
- pip2 install --user setuptools nose2
|
||||
- pip3 install --user setuptools nose2
|
||||
- make setup
|
||||
script:
|
||||
- make check ARGS="--all --gtest_args=--gtest_filter=-*_mt"
|
||||
|
||||
- env: TEST="Pylint 2"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- cppcheck
|
||||
- python
|
||||
- python-pip
|
||||
install:
|
||||
- pip2 install --user -r PythonClient/requirements.txt
|
||||
- pip2 install --user pylint
|
||||
script:
|
||||
- cppcheck . -iBuild -i.pb.cc --error-exitcode=1 --enable=warning --inline-suppr --quiet
|
||||
- pylint --disable=R,C --rcfile=PythonClient/.pylintrc PythonClient/carla PythonClient/*.py
|
||||
|
||||
- env: TEST="MkDocs"
|
||||
install:
|
||||
- pip install mkdocs
|
||||
- pip install --user mkdocs
|
||||
script:
|
||||
- mkdocs build --verbose --clean --strict --site-dir _site
|
||||
|
||||
|
|
|
@ -1,149 +0,0 @@
|
|||
{
|
||||
"folders":
|
||||
[
|
||||
{
|
||||
"path": ".",
|
||||
"folder_exclude_patterns":
|
||||
[
|
||||
".clang",
|
||||
".codelite",
|
||||
".kdev4",
|
||||
".vs",
|
||||
".vscode",
|
||||
"Binaries",
|
||||
"Build",
|
||||
"DerivedDataCache",
|
||||
"Dist",
|
||||
"Doxygen",
|
||||
"Intermediate",
|
||||
"Saved",
|
||||
"Unreal/CarlaUE4/Content*",
|
||||
"__pycache__",
|
||||
"_site"
|
||||
],
|
||||
"file_exclude_patterns":
|
||||
[
|
||||
"*.VC.db",
|
||||
"*.VC.opendb",
|
||||
"*.kdev4",
|
||||
"*.pri",
|
||||
"*.pro",
|
||||
"*.py[cod]",
|
||||
"*.sln",
|
||||
"*.stackdump",
|
||||
"*.sublime-workspace",
|
||||
"*.uasset",
|
||||
"*.umap",
|
||||
"*.workspace",
|
||||
"*CodeCompletionFolders.txt",
|
||||
"*CodeLitePreProcessor.txt",
|
||||
".tags*",
|
||||
"core"
|
||||
]
|
||||
}
|
||||
],
|
||||
"settings":
|
||||
{
|
||||
"ensure_newline_at_eof_on_save": true,
|
||||
"tab_size": 2,
|
||||
"translate_tabs_to_spaces": true,
|
||||
"trim_trailing_white_space_on_save": true
|
||||
},
|
||||
"build_systems":
|
||||
[
|
||||
{
|
||||
"name": "CARLA - Pylint",
|
||||
"working_dir": "${project_path}",
|
||||
"file_regex": "^\\[([^:]*):([0-9]+):?([0-9]+)?\\]:? (.*)$",
|
||||
"shell_cmd": "pylint --disable=R,C --rcfile=PythonClient/.pylintrc PythonClient/carla PythonClient/*.py --msg-template='[{path}:{line:3d}:{column}]: {msg_id} {msg}'"
|
||||
},
|
||||
{
|
||||
"name": "CARLA - CppCheck",
|
||||
"working_dir": "${project_path}",
|
||||
"file_regex": "^\\[([^:]*):([0-9]+):?([0-9]+)?\\]:? (.*)$",
|
||||
"shell_cmd": "cppcheck . -iBuild -i.pb.cc --error-exitcode=0 --enable=warning --quiet"
|
||||
},
|
||||
{
|
||||
"name": "CARLA - Rebuild script",
|
||||
"working_dir": "${project_path}",
|
||||
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"linux":
|
||||
{
|
||||
"shell_cmd": "./Rebuild.sh"
|
||||
},
|
||||
"windows":
|
||||
{
|
||||
"shell_cmd": "start Rebuild.bat"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "CARLA - make CarlaUE4",
|
||||
"working_dir": "${project_path}/Unreal/CarlaUE4",
|
||||
"file_regex": "Unreal\\/CarlaUE4\\/([^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"syntax": "Packages/Makefile/Make Output.sublime-syntax",
|
||||
"linux":
|
||||
{
|
||||
"shell_cmd": "make CarlaUE4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "CARLA - make CarlaUE4 ARGS=-clean",
|
||||
"working_dir": "${project_path}/Unreal/CarlaUE4",
|
||||
"file_regex": "Unreal\\/CarlaUE4\\/([^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"syntax": "Packages/Makefile/Make Output.sublime-syntax",
|
||||
"linux":
|
||||
{
|
||||
"shell_cmd": "make CarlaUE4 ARGS=-clean"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "CARLA - make CarlaUE4Editor",
|
||||
"working_dir": "${project_path}/Unreal/CarlaUE4",
|
||||
"file_regex": "Unreal\\/CarlaUE4\\/([^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"syntax": "Packages/Makefile/Make Output.sublime-syntax",
|
||||
"linux":
|
||||
{
|
||||
"shell_cmd": "make CarlaUE4Editor"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "CARLA - make CarlaUE4Editor ARGS=-clean",
|
||||
"working_dir": "${project_path}/Unreal/CarlaUE4",
|
||||
"file_regex": "Unreal\\/CarlaUE4\\/([^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"syntax": "Packages/Makefile/Make Output.sublime-syntax",
|
||||
"linux":
|
||||
{
|
||||
"shell_cmd": "make CarlaUE4Editor ARGS=-clean"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "CARLA - make CarlaServer",
|
||||
"working_dir": "${project_path}",
|
||||
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"syntax": "Packages/Makefile/Make Output.sublime-syntax",
|
||||
"linux":
|
||||
{
|
||||
"shell_cmd": "make"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "CARLA - check CarlaServer",
|
||||
"working_dir": "${project_path}",
|
||||
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"syntax": "Packages/Makefile/Make Output.sublime-syntax",
|
||||
"linux":
|
||||
{
|
||||
"shell_cmd": "make check"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "CARLA - clean CarlaServer",
|
||||
"working_dir": "${project_path}",
|
||||
"syntax": "Packages/Makefile/Make Output.sublime-syntax",
|
||||
"linux":
|
||||
{
|
||||
"shell_cmd": "make clean"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
21
CHANGELOG.md
21
CHANGELOG.md
|
@ -1,3 +1,24 @@
|
|||
## CARLA 0.9.0
|
||||
|
||||
* Upgraded to Unreal Engine 4.19
|
||||
* Redesign of the networking architecture
|
||||
- Allows any number of clients to connect simultaneously
|
||||
- Now is possible to add and remove at any time any vehicle or camera
|
||||
- Now is possible to control any vehicle or camera
|
||||
- Now is possible to place cameras anywhere
|
||||
- Reduced to two ports instead of three
|
||||
- First port uses an RPC protocol based on [rpclib](http://rpclib.net/)
|
||||
- Second port is for the streaming of the sensor data
|
||||
* Redesign of the Python API
|
||||
- Actors and sensors are now exposed in the API and can be independently controlled
|
||||
- The Python module is built in C++, with significant performance gain in some operations
|
||||
- Many functionality haven't been ported yet, so expect a lot of things missing
|
||||
* Redesign of the build system to accommodate the changes in dependencies
|
||||
- Everything can be done now with the Makefile
|
||||
- For the moment only Linux is supported, sorry
|
||||
* Massive clean up of all unused assets
|
||||
* Some aesthetic fixes to the vehicles
|
||||
|
||||
## CARLA 0.8.4
|
||||
|
||||
* Community contribution: ROS bridge by @laurent-george
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.9.0)
|
||||
project(CARLA)
|
||||
|
||||
include("Build/CMakeLists.txt.in")
|
||||
|
||||
add_subdirectory("LibCarla/cmake")
|
|
@ -76,11 +76,11 @@ usually offers that make it very affordable.
|
|||
|
||||
#### What should I know before I get started?
|
||||
|
||||
Check out the ["CARLA Design"](carla_design.md) document to get an idea on the
|
||||
different modules that compose CARLA, and chose the most appropriate one to hold
|
||||
the new feature. We are aware the developers documentation is still scarce,
|
||||
please ask us in case of doubt, and of course don't hesitate to improve the
|
||||
current documentation if you feel confident enough.
|
||||
Check out the ["CARLA Design"](index.md)<!-- @todo --> document to get an idea
|
||||
on the different modules that compose CARLA, and chose the most appropriate one
|
||||
to hold the new feature. We are aware the developers documentation is still
|
||||
scarce, please ask us in case of doubt, and of course don't hesitate to improve
|
||||
the current documentation if you feel confident enough.
|
||||
|
||||
#### Are there any examples in CARLA to see how Unreal programming works?
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ In this tutorial we show:
|
|||
![Benchmark_structure](img/benchmark_diagram_small.png)
|
||||
|
||||
The driving benchmark is associated with other two modules.
|
||||
The *agent* module, that is a controller which performs in
|
||||
The *agent* module, that is a controller which performs in
|
||||
another module: the *experiment suite*.
|
||||
Both modules are abstract classes that must be redefined by
|
||||
the user.
|
||||
|
@ -54,11 +54,11 @@ Let's start by deriving a simple forward agent:
|
|||
|
||||
from carla.agent.agent import Agent
|
||||
from carla.client import VehicleControl
|
||||
|
||||
|
||||
class ForwardAgent(Agent):
|
||||
|
||||
|
||||
To have its performance evaluated, the ForwardAgent derived class _must_
|
||||
To have its performance evaluated, the ForwardAgent derived class _must_
|
||||
redefine the *run_step* function as it is done in the following excerpt:
|
||||
|
||||
def run_step(self, measurements, sensor_data, directions, target):
|
||||
|
@ -71,18 +71,18 @@ redefine the *run_step* function as it is done in the following excerpt:
|
|||
|
||||
|
||||
This function receives the following parameters:
|
||||
|
||||
* [Measurements](measurements.md): the entire state of the world received
|
||||
|
||||
* [Measurements](index.md)<!-- @todo -->: the entire state of the world received
|
||||
by the client from the CARLA Simulator. These measurements contains agent position, orientation,
|
||||
dynamic objects information, etc.
|
||||
* [Sensor Data](cameras_and_sensors.md): The measured data from defined sensors,
|
||||
* [Sensor Data](cameras_and_sensors.md): The measured data from defined sensors,
|
||||
such as Lidars or RGB cameras.
|
||||
* Directions: Information from the high level planner. Currently the planner sends
|
||||
a high level command from the follwoing set: STRAIGHT, RIGHT, LEFT, NOTHING.
|
||||
* Target Position: The position and orientation of the target.
|
||||
|
||||
With all this information, the *run_step* function is expected
|
||||
to return a [vehicle control message](measurements.md), containing:
|
||||
|
||||
With all this information, the *run_step* function is expected
|
||||
to return a [vehicle control message](index.md)<!-- @todo -->, containing:
|
||||
steering value, throttle value, brake value, etc.
|
||||
|
||||
|
||||
|
@ -108,12 +108,12 @@ as in the following code excerpt:
|
|||
from carla.agent_benchmark.experiment import Experiment
|
||||
from carla.sensor import Camera
|
||||
from carla.settings import CarlaSettings
|
||||
|
||||
|
||||
from .experiment_suite import ExperimentSuite
|
||||
|
||||
|
||||
|
||||
|
||||
class BasicExperimentSuite(ExperimentSuite):
|
||||
|
||||
|
||||
##### Define test and train weather conditions
|
||||
|
||||
The user must select the weathers to be used. One should select the set
|
||||
|
@ -126,7 +126,7 @@ class property as in the following example:
|
|||
@property
|
||||
def test_weathers(self):
|
||||
return [1]
|
||||
|
||||
|
||||
|
||||
##### Building Experiments
|
||||
|
||||
|
@ -134,15 +134,15 @@ The [experiments are composed by a *task* that is defined by a set of *poses*](b
|
|||
Let's start by selecting poses for one of the cities, let's take Town01, for instance.
|
||||
First of all, we need to see all the possible positions, for that, with
|
||||
a CARLA simulator running in a terminal, run:
|
||||
|
||||
|
||||
python view_start_positions.py
|
||||
|
||||
|
||||
![town01_positions](img/town01_positions.png)
|
||||
|
||||
|
||||
|
||||
|
||||
Now let's choose, for instance, 140 as start position and 134
|
||||
as the end position. This two positions can be visualized by running:
|
||||
|
||||
|
||||
python view_start_positions.py --pos 140,134 --no-labels
|
||||
|
||||
![town01_positions](img/town01_140_134.png)
|
||||
|
@ -165,7 +165,7 @@ the number of dynamic objects for each of these tasks and repeat
|
|||
the arbitrary position task to have it also defined with dynamic
|
||||
objects. In the following code excerpt we show the final
|
||||
defined positions and the number of dynamic objects for each task:
|
||||
|
||||
|
||||
# Define the start/end position below as tasks
|
||||
poses_task0 = [[7, 3]]
|
||||
poses_task1 = [[138, 17]]
|
||||
|
@ -212,7 +212,7 @@ vector as we show in the following code excerpt:
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
The full code could be found at [basic_experiment_suite.py](https://github.com/carla-simulator/carla/blob/master/PythonClient/carla/driving_benchmark/experiment_suites/basic_experiment_suite.py)
|
||||
|
||||
|
||||
|
@ -228,7 +228,7 @@ For that you should run the CARLA simulator as:
|
|||
The example presented in this tutorial can be executed for Town01 as:
|
||||
|
||||
./driving_benchmark_example.py -c Town01
|
||||
|
||||
|
||||
You should expect these results: [town01_basic_forward_results](benchmark_basic_results_town01)
|
||||
|
||||
For Town02:
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
<h1>Build system</h1>
|
||||
|
||||
> _This document is a work in progress, only the Linux build system is taken into account here._
|
||||
|
||||
The most challenging part of the setup is to compile all the dependencies and
|
||||
modules to be compatible with a) Unreal Engine in the server-side, and b) Python
|
||||
in the client-side.
|
||||
|
||||
The goal is to be able to call Unreal Engine's functions from a separate Python
|
||||
process.
|
||||
|
||||
![modules](img/modules.png)
|
||||
|
||||
In Linux, we compile CARLA and all the dependencies with clang-5.0 and C++14
|
||||
standard. We however link against different runtime C++ libraries depending on
|
||||
where the code going to be used, since all the code that is going to be linked
|
||||
with Unreal Engine needs to be compiled using `libc++`.
|
||||
|
||||
#### Setup
|
||||
|
||||
Command
|
||||
|
||||
```sh
|
||||
make setup
|
||||
```
|
||||
|
||||
Get and compile dependencies
|
||||
|
||||
* llvm-5.0 (libc++ and libc++abi)
|
||||
* rpclib-2.2.1 (twice, with libstdc++ and libc++)
|
||||
* boost-1.67 (headers only)
|
||||
* googletest-1.8.0 (with libc++)
|
||||
|
||||
#### LibCarla
|
||||
|
||||
Compiled with CMake (minimum version required CMake 3.9).
|
||||
|
||||
Command
|
||||
|
||||
```sh
|
||||
make LibCarla
|
||||
```
|
||||
|
||||
Two configurations:
|
||||
|
||||
| | Server | Client |
|
||||
|-----------------|--------------|-----------|
|
||||
| **Unit tests** | yes | no |
|
||||
| **Requires** | rpclib, gtest, boost | rpclib, boost
|
||||
| **std runtime** | LLVM's `libc++` | Default `libstdc++` |
|
||||
| **Output** | headers and test exes | `libcarla_client.a` |
|
||||
| **Required by** | Carla plugin | PythonAPI |
|
||||
|
||||
#### CarlaUE4 and Carla plugin
|
||||
|
||||
Both compiled at the same step with Unreal Engine 4.19 build tool. They require
|
||||
the `UE4_ROOT` environment variable set.
|
||||
|
||||
Command
|
||||
|
||||
```sh
|
||||
make CarlaUE4Editor
|
||||
```
|
||||
|
||||
To launch Unreal Engine's Editor run
|
||||
|
||||
```sh
|
||||
make launch
|
||||
```
|
||||
|
||||
#### PythonAPI
|
||||
|
||||
Compiled using Python's `setuptools` ("setup.py"). Currently requires the
|
||||
following to be installed in the machine: Python, libpython-dev, and
|
||||
libboost-python-dev; both for Python 2.7 and 3.5.
|
||||
|
||||
Command
|
||||
|
||||
```sh
|
||||
make PythonAPI
|
||||
```
|
||||
|
||||
It creates two "egg" packages
|
||||
|
||||
* `PythonAPI/dist/carla-0.9.0-py2.7-linux-x86_64.egg`
|
||||
* `PythonAPI/dist/carla-0.9.0-py3.5-linux-x86_64.egg`
|
||||
|
||||
This package can be directly imported into a Python script by adding it to the
|
||||
system path
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
sys.path.append(
|
||||
'PythonAPI/dist/carla-0.9.0-py%d.%d-linux-x86_64.egg' % (sys.version_info.major,
|
||||
sys.version_info.minor))
|
||||
|
||||
import carla
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
or installed with `easy_install`
|
||||
|
||||
```sh
|
||||
easy_install2 --user --no-deps PythonAPI/dist/carla-0.9.0-py2.7-linux-x86_64.egg
|
||||
easy_install3 --user --no-deps PythonAPI/dist/carla-0.9.0-py3.5-linux-x86_64.egg
|
||||
```
|
|
@ -1,5 +1,11 @@
|
|||
<h1>Cameras and sensors</h1>
|
||||
|
||||
!!! important
|
||||
This document still refers to the 0.8.X API (stable version). The
|
||||
proceedings stated here may not apply to latest versions, 0.9.0 or later.
|
||||
Latest versions introduced significant changes in the API, we are still
|
||||
working on documenting everything, sorry for the inconvenience.
|
||||
|
||||
!!! important
|
||||
Since version 0.8.0 the positions of the sensors are specified in meters
|
||||
instead of centimeters. Always relative to the vehicle.
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
> _This document is a work in progress and might be incomplete._
|
||||
|
||||
!!! important
|
||||
This document still refers to the 0.8.X API (stable version). The
|
||||
proceedings stated here may not apply to latest versions, 0.9.0 or later.
|
||||
Latest versions introduced significant changes in the API, we are still
|
||||
working on documenting everything, sorry for the inconvenience.
|
||||
|
||||
CarlaSettings.ini
|
||||
-----------------
|
||||
|
||||
|
@ -14,7 +20,7 @@ hierarchy overriding earlier values.
|
|||
|
||||
1. `{CarlaFolder}/Unreal/CarlaUE4/Config/CarlaSettings.ini`.
|
||||
2. File provided by command-line argument `-carla-settings="Path/To/CarlaSettings.ini"`.
|
||||
3. Other command-line arguments as `-carla-server` or `-world-port`.
|
||||
3. Other command-line arguments like `-carla-port`.
|
||||
4. Settings file sent by the client on every new episode.
|
||||
|
||||
Take a look at the [CARLA Settings example][settingslink].
|
||||
|
@ -54,8 +60,6 @@ WeatherId=6
|
|||
Simulator command-line options
|
||||
------------------------------
|
||||
|
||||
* `-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-world-port=N` Listen for client connections at port N, agent ports are set to N+1 and N+2 respectively. Activates server.
|
||||
* `-carla-port=N` Listen for client connections at port N, streaming port is set to N+1.
|
||||
* `-carla-no-hud` Do not display the HUD by default.
|
||||
* `-carla-no-networking` Disable networking. Overrides `-carla-server` if present.
|
||||
|
|
|
@ -26,11 +26,11 @@ C++
|
|||
---
|
||||
|
||||
* Compilation should not give any error or warning
|
||||
(`clang++ -Wall -Wextra -std=C++14`).
|
||||
(`clang++ -Wall -Wextra -std=C++14 -Wno-missing-braces`).
|
||||
* Unreal C++ code (CarlaUE4 and Carla plugin) follow the
|
||||
[Unreal Engine's Coding Standard][ue4link] with the exception of using
|
||||
spaces instead of tabs.
|
||||
* CarlaServer uses [Google's style guide][googlelink].
|
||||
* LibCarla uses a variation of [Google's style guide][googlelink].
|
||||
|
||||
[ue4link]: https://docs.unrealengine.com/latest/INT/Programming/Development/CodingStandard/
|
||||
[googlelink]: https://google.github.io/styleguide/cppguide.html
|
||||
|
|
|
@ -40,6 +40,8 @@ run the simulation at a fixed time-step of 0.2 seconds we execute
|
|||
It is important to note that this mode can only be enabled when launching the
|
||||
simulator since this is actually a feature of Unreal Engine.
|
||||
|
||||
<!-- Disabled for now...
|
||||
|
||||
Synchronous vs Asynchronous mode
|
||||
--------------------------------
|
||||
|
||||
|
@ -83,3 +85,4 @@ settings.set(SynchronousMode=True)
|
|||
[CARLA/Server]
|
||||
SynchronousMode=true
|
||||
```
|
||||
-->
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Download
|
||||
|
||||
### Stable
|
||||
|
||||
> The most tested and robust release out there!
|
||||
|
||||
- [CARLA 0.8.2](https://github.com/carla-simulator/carla/releases/tag/0.8.2) -
|
||||
[[Blog post](http://carla.org/2018/04/23/release-0.8.2/)] - _Driving Benchmark_
|
||||
|
||||
### Development
|
||||
|
||||
> These are the version of CARLA, more frequently updated and with the latest features.
|
||||
Keep in mind that everything in this channel can (and probably will) change.
|
||||
|
||||
- [CARLA 0.9.0](https://github.com/carla-simulator/carla/releases/tag/0.9.0) -
|
||||
[[Blog post](http://carla.org/2018/07/30/release-0.9.0/)] - _New API, multi-client multi-agent support_
|
||||
- [CARLA 0.8.4](https://github.com/carla-simulator/carla/releases/tag/0.8.4) -
|
||||
[[Blog post](http://carla.org/2018/06/18/release-0.8.4/)] - _Fixes And More!_
|
||||
- [CARLA 0.8.3](https://github.com/carla-simulator/carla/releases/tag/0.8.3) -
|
||||
[[Blog post](http://carla.org/2018/06/08/release-0.8.3/)] - _Now with bikes!_
|
|
@ -2,11 +2,16 @@
|
|||
|
||||
![Welcome to CARLA](img/welcome.png)
|
||||
|
||||
!!! important
|
||||
This tutorial refers to the latest development versions of CARLA, 0.9.0 or
|
||||
later. For the documentation of the stable version please switch to the
|
||||
[stable branch](https://carla.readthedocs.io/en/stable/getting_started/).
|
||||
|
||||
Welcome to CARLA! This tutorial provides the basic steps for getting started
|
||||
using CARLA.
|
||||
|
||||
<!-- Latest release button -->
|
||||
<p align="middle"><a href="https://github.com/carla-simulator/carla/releases/latest" target="_blank" class="btn btn-neutral" title="Go to the latest CARLA release"><span class="icon icon-github"></span> Get the latest release</a></p>
|
||||
<p align="middle"><a href="https://github.com/carla-simulator/carla/blob/master/Docs/download.md" target="_blank" class="btn btn-neutral" title="Go to the latest CARLA release"><span class="icon icon-github"></span> Get the latest release</a></p>
|
||||
|
||||
Download the latest release from our GitHub page and extract all the contents of
|
||||
the package in a folder of your choice.
|
||||
|
@ -14,17 +19,50 @@ the package in a folder of your choice.
|
|||
The release package contains the following
|
||||
|
||||
* The CARLA simulator.
|
||||
* The "carla" Python module.
|
||||
* Some Python client examples.
|
||||
* The "carla" Python API module.
|
||||
* A few Python scripts with usage examples.
|
||||
|
||||
For now we will focus on the simulator only. The simulator can be run in two
|
||||
different modes
|
||||
The simulator can be started by running `CarlaUE4.sh` on Linux, or
|
||||
`CarlaUE4.exe` on Windows. Unlike previous versions, now the simulator
|
||||
automatically starts in "server mode". That is, you can already start connecting
|
||||
your Python scripts to control the actors in the simulation.
|
||||
|
||||
* **Server mode:** The simulator is controlled by a client application that
|
||||
collects data and sends driving instructions. In this mode the simulator
|
||||
hangs until a client starts a connection.
|
||||
* **Standalone mode:** The simulator starts in sort of _video-game mode_ in
|
||||
which you can control the vehicle with the keyboard.
|
||||
CARLA requires two available TCP ports on your computer, by default 2000 and
|
||||
2001. Make sure you don't have a firewall or another application blocking those
|
||||
ports. Alternatively, you can manually change the port CARLA uses by launching
|
||||
the simulator with the command-line argument `-carla-port=N`, the second port
|
||||
will be automatically set to `N+1`.
|
||||
|
||||
In the next item in this tutorial we will run the **standalone mode** to take a
|
||||
first look into CARLA.
|
||||
!!! tip
|
||||
You can launch the simulator in windowed mode by using the argument
|
||||
`-windowed`, and control the window size with `-ResX=N` and `-ResY=N`.
|
||||
|
||||
#### Running the example script
|
||||
|
||||
Run the example script with
|
||||
|
||||
```sh
|
||||
python example.py
|
||||
```
|
||||
|
||||
If everything went well you should start seeing cars appearing in the scene.
|
||||
|
||||
_We strongly recommend taking a look at the example code to understand how it
|
||||
works, and modify it at will. We'll have soon tutorials for writing your own
|
||||
scripts, but for now the examples is all we have._
|
||||
|
||||
#### Changing the map
|
||||
|
||||
By default, the simulator starts up in our _"Town01"_ map. The second map can be
|
||||
started by passing the path to the map as first argument when launching the
|
||||
simulator
|
||||
|
||||
```sh
|
||||
# On Linux
|
||||
$ ./CarlaUE4.sh /Game/Carla/Maps/Town02
|
||||
```
|
||||
|
||||
```cmd
|
||||
rem On Windows
|
||||
> CarlaUE4.exe /Game/Carla/Maps/Town02
|
||||
```
|
||||
|
|
|
@ -11,23 +11,69 @@ for creating the Skeletal Mesh and Physics Asset. And
|
|||
[Vehicles User Guide](https://docs.unrealengine.com/latest/INT/Engine/Physics/Vehicles/VehicleUserGuide/)
|
||||
for the rest.
|
||||
|
||||
* Import fbx as Skelletal Mesh to its own folder inside `Content/Static/Vehicles`. A Physics asset and a Skeleton should be automatically created and linked the three together.
|
||||
!!! important
|
||||
If you want a simpler way you might copy our "General4wheeledSkeleton" from our project, either by
|
||||
exporting it and copying it into your model or by creating your skelleton using the same bone names and orientation.
|
||||
Bind it to your vehicle model and choose it when importing your vehicle into the editor.
|
||||
This way you won't need to configure the animation, you might just use "General4wheeledAnimation" (step 3)
|
||||
You also won't need to configure the bone names for your wheels (Step 7. Be carefull, you'll still need to asign the wheel blueprints).
|
||||
|
||||
|
||||
* Import fbx as Skelletal Mesh to its own folder inside `Content/Carla/Static/Vehicles`. A Physics asset and a Skeleton should be automatically created and linked the three together.
|
||||
* Tune the Physics asset. Delete the automatically created ones and add boxes to the `Vehicle_Base` bone matching the shape, make sure generate hit events is enabled. Add a sphere for each wheel and set their "Physics Type" to "Kinematic".
|
||||
* Inside that folder create an "Animation Blueprint", while creating select "VehicleAnimInstance" as parent class and the skeleton of this car model as the target skeleton. Add the animation graph as shown in the links given above (or look for it in other cars' animation, like Mustang).
|
||||
* Create folder `Content/Blueprints/Vehicles/<vehicle-model>`
|
||||
* Inside that folder create two blueprint classes derived from "VehicleWheel" class. Call them `<vehicle-model>_FrontWheel` and `<vehicle-model>_RearWheel`. Set their "Shape Radius" to exactly match the mesh wheel radius (careful, radius not diameter). Set their "Tire Config" to "CommonTireConfig". On the front wheel uncheck "Affected by Handbrake" and on the rear wheel set "Steer Angle" to zero.
|
||||
* Inside the same folder create a blueprint class derived from `BaseVehiclePawn` call it `<vehicle-model>`. Open it for edit and select component "Mesh", setup the "Skeletal Mesh" and the "Anim Class" to the corresponding ones. Then select component "VehicleMovement", under "Vehicle Setup" expand "Wheel Setups", setup each wheel
|
||||
* Inside the same folder create a blueprint class derived from `BaseVehiclePawn` call it `<vehicle-model>`. Open it for edit and select component "Mesh", setup the "Skeletal Mesh" and the "Anim Class" to the corresponding ones. Then select the VehicleBounds component and set the size to cover vehicle's volume as close as possible.
|
||||
* Select component "VehicleMovement", under "Vehicle Setup" expand "Wheel Setups", setup each wheel
|
||||
- 0 : Wheel Class=`<vehicle-model>_FrontWheel`, Bone Name=`Wheel_Front_Left`
|
||||
- 1 : Wheel Class=`<vehicle-model>_FrontWheel`, Bone Name=`Wheel_Front_Right`
|
||||
- 2 : Wheel Class=`<vehicle-model>_RearWheel`, Bone Name=`Wheel_Rear_Left`
|
||||
- 3 : Wheel Class=`<vehicle-model>_RearWheel`, Bone Name=`Wheel_Rear_Right`
|
||||
* Add a box component to it called "Box" (see Mustang blueprint) and set the size to cover vehicle's area as seen from above. Make sure the following is set
|
||||
- Hidden in game
|
||||
- Simulate physics is disable
|
||||
- Generate overlap events is disable
|
||||
- Collision presets is set to "NoCollision"
|
||||
* Test it, go to CarlaGameMode blueprint and change "Default Pawn Class" to the newly created car blueprint
|
||||
|
||||
Adding a 2 wheeled vehicle
|
||||
--------------------------
|
||||
|
||||
Adding 2 wheeled vehicles is similar to adding a 4 wheeled one but due to the complexity of the animation you'll need to set up aditional bones to guide the driver's animation:
|
||||
|
||||
As with the 4 wheeled vehicles, orient the model towards positive "x" and every bone axis towards positive x and with the z axis facing upwards.
|
||||
|
||||
```yaml
|
||||
Bone Setup:
|
||||
- Bike_Rig: # The origin point of the mesh. Place it in the point 0 of the scenecomment
|
||||
- BikeBody: # The model's body centre.
|
||||
- Pedals: # If the vehicle is a bike bind the pedalier to this bone, will rotate with the bike acceleration.
|
||||
- RightPedal: # Sets the driver's feet position and rotates with the pedalier if the vehicle is a bike.
|
||||
- LeftPedal: # ^
|
||||
- RearWheel: # Rear Wheel of the vehicle
|
||||
- Handler: # Rotates with the frontal wheel of the vehicle bind the vehicle handler to it.
|
||||
- HandlerMidBone: # Positioned over the front wheel bone to orient the handler with the wheel
|
||||
- HandlerRight: # Sets the position of the driver's hand, no need to bind it to anything.
|
||||
- HandlerLeft: # ^
|
||||
- Frontwheel: # Frontal wheel of the vehicle.
|
||||
- RightHelperRotator: # This four additional bones are here for an obsolete system of making the bike stable by using aditional invisible wheels
|
||||
- RightHelprWheel: # ^
|
||||
- LeftHelperRotator: # ^
|
||||
- LeftHelperWheel: # ^
|
||||
- Seat: # Sets the position of the drivers hip bone. No need to bind it to anything but place it carefully.
|
||||
```
|
||||
|
||||
* Import fbx as Skelletal Mesh to its own folder inside `Content/Carla/Static/Vehicles/2Wheeled`. When importing select "General2WheeledVehicleSkeleton" as skelleton A Physics asset should be automatically created and linked.
|
||||
* Tune the Physics asset. Delete the automatically created ones and add boxes to the `BikeBody` bone trying to match the shape as possible, make sure generate hit events is enabled. Add a sphere for each wheel and set their "Physics Type" to "Kinematic".
|
||||
* Create folder `Content/Blueprints/Vehicles/<vehicle-model>`
|
||||
* Inside that folder create two blueprint classes derived from "VehicleWheel" class. Call them `<vehicle-model>_FrontWheel` and `<vehicle-model>_RearWheel`. Set their "Shape Radius" to exactly match the mesh wheel radius (careful, radius not diameter). Set their "Tire Config" to "CommonTireConfig". On the front wheel uncheck "Affected by Handbrake" and on the rear wheel set "Steer Angle" to zero.
|
||||
* Inside the same folder create a blueprint class derived from `Base2WheeledVehicle` call it `<vehicle-model>`. Open it for edit and select component "Mesh", setup the "Skeletal Mesh" and the "Anim Class" to the corresponding ones. Then select the VehicleBounds component and set the size to cover vehicle's area as seen from above.
|
||||
* Select component "VehicleMovement", under "Vehicle Setup" expand "Wheel Setups", setup each wheel
|
||||
- 0 : Wheel Class=`<vehicle-model>_FrontWheel`, Bone Name=`FrontWheel`
|
||||
- 1 : Wheel Class=`<vehicle-model>_FrontWheel`, Bone Name=`FrontWheel`
|
||||
- 2 : Wheel Class=`<vehicle-model>_RearWheel`, Bone Name=`RearWheel`
|
||||
- 3 : Wheel Class=`<vehicle-model>_RearWheel`, Bone Name=`RearWheel`
|
||||
(You'll notice that we are basically placing two wheels in each bone. The vehicle class unreal provides does not support vehicles with wheel numbers different from 4 so we had to make it believe the vehicle has 4 wheels)
|
||||
* Select the variable "is bike" and tick it if your model is a bike. This will activate the pedalier rotation. Leave unmarked if you are setting up a motorbike.
|
||||
* Find the variable back Rotation and set it as it fit better select the component SkeletalMesh (The driver) and move it along x axis until its in the seat position.
|
||||
* Test it, go to CarlaGameMode blueprint and change "Default Pawn Class" to the newly created bike blueprint.
|
||||
|
||||
Map generation
|
||||
--------------
|
||||
|
||||
|
@ -35,55 +81,55 @@ For the road generation, the following meshes are expected to be found
|
|||
|
||||
```
|
||||
# Enum Filepath
|
||||
RoadTwoLanes_LaneLeft at "Content/Static/Road/St_Road_TileRoad_RoadL.uasset"
|
||||
RoadTwoLanes_LaneRight at "Content/Static/Road/St_Road_TileRoad_RoadR.uasset"
|
||||
RoadTwoLanes_SidewalkLeft at "Content/Static/SideWalk/St_Road_TileRoad_SidewalkL.uasset"
|
||||
RoadTwoLanes_SidewalkRight at "Content/Static/SideWalk/St_Road_TileRoad_SidewalkR.uasset"
|
||||
RoadTwoLanes_LaneMarkingSolid at "Content/Static/RoadLines/St_Road_TileRoad_LaneMarkingSolid.uasset"
|
||||
RoadTwoLanes_LaneMarkingBroken at "Content/Static/RoadLines/St_Road_TileRoad_LaneMarkingBroken.uasset"
|
||||
RoadTwoLanes_LaneLeft at "Content/Carla/Static/Road/St_Road_TileRoad_RoadL.uasset"
|
||||
RoadTwoLanes_LaneRight at "Content/Carla/Static/Road/St_Road_TileRoad_RoadR.uasset"
|
||||
RoadTwoLanes_SidewalkLeft at "Content/Carla/Static/SideWalk/St_Road_TileRoad_SidewalkL.uasset"
|
||||
RoadTwoLanes_SidewalkRight at "Content/Carla/Static/SideWalk/St_Road_TileRoad_SidewalkR.uasset"
|
||||
RoadTwoLanes_LaneMarkingSolid at "Content/Carla/Static/RoadLines/St_Road_TileRoad_LaneMarkingSolid.uasset"
|
||||
RoadTwoLanes_LaneMarkingBroken at "Content/Carla/Static/RoadLines/St_Road_TileRoad_LaneMarkingBroken.uasset"
|
||||
|
||||
Road90DegTurn_Lane0 at "Content/Static/Road/St_Road_Curve_Road1.uasset"
|
||||
Road90DegTurn_Lane1 at "Content/Static/Road/St_Road_Curve_Road2.uasset"
|
||||
Road90DegTurn_Lane2 at "Content/Static/Road/St_Road_Curve_Road3.uasset"
|
||||
Road90DegTurn_Lane3 at "Content/Static/Road/St_Road_Curve_Road4.uasset"
|
||||
Road90DegTurn_Lane3 at "Content/Static/Road/St_Road_Curve_Road5.uasset"
|
||||
Road90DegTurn_Lane3 at "Content/Static/Road/St_Road_Curve_Road6.uasset"
|
||||
Road90DegTurn_Lane3 at "Content/Static/Road/St_Road_Curve_Road7.uasset"
|
||||
Road90DegTurn_Lane3 at "Content/Static/Road/St_Road_Curve_Road8.uasset"
|
||||
Road90DegTurn_Lane3 at "Content/Static/Road/St_Road_Curve_Road9.uasset"
|
||||
Road90DegTurn_Sidewalk0 at "Content/Static/SideWalk/St_Road_Curve_Sidewalk1.uasset"
|
||||
Road90DegTurn_Sidewalk1 at "Content/Static/SideWalk/St_Road_Curve_Sidewalk2.uasset"
|
||||
Road90DegTurn_Sidewalk2 at "Content/Static/SideWalk/St_Road_Curve_Sidewalk3.uasset"
|
||||
Road90DegTurn_Sidewalk3 at "Content/Static/SideWalk/St_Road_Curve_Sidewalk4.uasset"
|
||||
Road90DegTurn_LaneMarking at "Content/Static/Road/St_Road_Curve_LaneMarking.uasset"
|
||||
Road90DegTurn_Lane0 at "Content/Carla/Static/Road/St_Road_Curve_Road1.uasset"
|
||||
Road90DegTurn_Lane1 at "Content/Carla/Static/Road/St_Road_Curve_Road2.uasset"
|
||||
Road90DegTurn_Lane2 at "Content/Carla/Static/Road/St_Road_Curve_Road3.uasset"
|
||||
Road90DegTurn_Lane3 at "Content/Carla/Static/Road/St_Road_Curve_Road4.uasset"
|
||||
Road90DegTurn_Lane3 at "Content/Carla/Static/Road/St_Road_Curve_Road5.uasset"
|
||||
Road90DegTurn_Lane3 at "Content/Carla/Static/Road/St_Road_Curve_Road6.uasset"
|
||||
Road90DegTurn_Lane3 at "Content/Carla/Static/Road/St_Road_Curve_Road7.uasset"
|
||||
Road90DegTurn_Lane3 at "Content/Carla/Static/Road/St_Road_Curve_Road8.uasset"
|
||||
Road90DegTurn_Lane3 at "Content/Carla/Static/Road/St_Road_Curve_Road9.uasset"
|
||||
Road90DegTurn_Sidewalk0 at "Content/Carla/Static/SideWalk/St_Road_Curve_Sidewalk1.uasset"
|
||||
Road90DegTurn_Sidewalk1 at "Content/Carla/Static/SideWalk/St_Road_Curve_Sidewalk2.uasset"
|
||||
Road90DegTurn_Sidewalk2 at "Content/Carla/Static/SideWalk/St_Road_Curve_Sidewalk3.uasset"
|
||||
Road90DegTurn_Sidewalk3 at "Content/Carla/Static/SideWalk/St_Road_Curve_Sidewalk4.uasset"
|
||||
Road90DegTurn_LaneMarking at "Content/Carla/Static/Road/St_Road_Curve_LaneMarking.uasset"
|
||||
|
||||
RoadTIntersection_Lane0 at "Content/Static/Road/St_Road_TCross_Road1.uasset"
|
||||
RoadTIntersection_Lane1 at "Content/Static/Road/St_Road_TCross_Road2.uasset"
|
||||
RoadTIntersection_Lane2 at "Content/Static/Road/St_Road_TCross_Road3.uasset"
|
||||
RoadTIntersection_Lane3 at "Content/Static/Road/St_Road_TCross_Road4.uasset"
|
||||
RoadTIntersection_Lane3 at "Content/Static/Road/St_Road_TCross_Road5.uasset"
|
||||
RoadTIntersection_Lane3 at "Content/Static/Road/St_Road_TCross_Road6.uasset"
|
||||
RoadTIntersection_Lane3 at "Content/Static/Road/St_Road_TCross_Road7.uasset"
|
||||
RoadTIntersection_Lane3 at "Content/Static/Road/St_Road_TCross_Road8.uasset"
|
||||
RoadTIntersection_Lane3 at "Content/Static/Road/St_Road_TCross_Road9.uasset"
|
||||
RoadTIntersection_Sidewalk0 at "Content/Static/SideWalk/St_Road_TCross_Sidewalk1.uasset"
|
||||
RoadTIntersection_Sidewalk1 at "Content/Static/SideWalk/St_Road_TCross_Sidewalk2.uasset"
|
||||
RoadTIntersection_Sidewalk2 at "Content/Static/SideWalk/St_Road_TCross_Sidewalk3.uasset"
|
||||
RoadTIntersection_Sidewalk3 at "Content/Static/SideWalk/St_Road_TCross_Sidewalk4.uasset"
|
||||
RoadTIntersection_LaneMarking at "Content/Static/RoadLines/St_Road_TCross_LaneMarking.uasset"
|
||||
RoadTIntersection_Lane0 at "Content/Carla/Static/Road/St_Road_TCross_Road1.uasset"
|
||||
RoadTIntersection_Lane1 at "Content/Carla/Static/Road/St_Road_TCross_Road2.uasset"
|
||||
RoadTIntersection_Lane2 at "Content/Carla/Static/Road/St_Road_TCross_Road3.uasset"
|
||||
RoadTIntersection_Lane3 at "Content/Carla/Static/Road/St_Road_TCross_Road4.uasset"
|
||||
RoadTIntersection_Lane3 at "Content/Carla/Static/Road/St_Road_TCross_Road5.uasset"
|
||||
RoadTIntersection_Lane3 at "Content/Carla/Static/Road/St_Road_TCross_Road6.uasset"
|
||||
RoadTIntersection_Lane3 at "Content/Carla/Static/Road/St_Road_TCross_Road7.uasset"
|
||||
RoadTIntersection_Lane3 at "Content/Carla/Static/Road/St_Road_TCross_Road8.uasset"
|
||||
RoadTIntersection_Lane3 at "Content/Carla/Static/Road/St_Road_TCross_Road9.uasset"
|
||||
RoadTIntersection_Sidewalk0 at "Content/Carla/Static/SideWalk/St_Road_TCross_Sidewalk1.uasset"
|
||||
RoadTIntersection_Sidewalk1 at "Content/Carla/Static/SideWalk/St_Road_TCross_Sidewalk2.uasset"
|
||||
RoadTIntersection_Sidewalk2 at "Content/Carla/Static/SideWalk/St_Road_TCross_Sidewalk3.uasset"
|
||||
RoadTIntersection_Sidewalk3 at "Content/Carla/Static/SideWalk/St_Road_TCross_Sidewalk4.uasset"
|
||||
RoadTIntersection_LaneMarking at "Content/Carla/Static/RoadLines/St_Road_TCross_LaneMarking.uasset"
|
||||
|
||||
RoadXIntersection_Lane0 at "Content/Static/Road/St_Road_XCross_Road1.uasset"
|
||||
RoadXIntersection_Lane1 at "Content/Static/Road/St_Road_XCross_Road2.uasset"
|
||||
RoadXIntersection_Lane2 at "Content/Static/Road/St_Road_XCross_Road3.uasset"
|
||||
RoadXIntersection_Lane3 at "Content/Static/Road/St_Road_XCross_Road4.uasset"
|
||||
RoadXIntersection_Lane3 at "Content/Static/Road/St_Road_XCross_Road5.uasset"
|
||||
RoadXIntersection_Lane3 at "Content/Static/Road/St_Road_XCross_Road6.uasset"
|
||||
RoadXIntersection_Lane3 at "Content/Static/Road/St_Road_XCross_Road7.uasset"
|
||||
RoadXIntersection_Lane3 at "Content/Static/Road/St_Road_XCross_Road8.uasset"
|
||||
RoadXIntersection_Lane3 at "Content/Static/Road/St_Road_XCross_Road9.uasset"
|
||||
RoadXIntersection_Sidewalk0 at "Content/Static/SideWalk/St_Road_XCross_Sidewalk1.uasset"
|
||||
RoadXIntersection_Sidewalk1 at "Content/Static/SideWalk/St_Road_XCross_Sidewalk2.uasset"
|
||||
RoadXIntersection_Sidewalk2 at "Content/Static/SideWalk/St_Road_XCross_Sidewalk3.uasset"
|
||||
RoadXIntersection_Sidewalk3 at "Content/Static/SideWalk/St_Road_XCross_Sidewalk4.uasset"
|
||||
RoadXIntersection_LaneMarking at "Content/Static/RoadLines/St_Road_XCross_LaneMarking.uasset"
|
||||
RoadXIntersection_Lane0 at "Content/Carla/Static/Road/St_Road_XCross_Road1.uasset"
|
||||
RoadXIntersection_Lane1 at "Content/Carla/Static/Road/St_Road_XCross_Road2.uasset"
|
||||
RoadXIntersection_Lane2 at "Content/Carla/Static/Road/St_Road_XCross_Road3.uasset"
|
||||
RoadXIntersection_Lane3 at "Content/Carla/Static/Road/St_Road_XCross_Road4.uasset"
|
||||
RoadXIntersection_Lane3 at "Content/Carla/Static/Road/St_Road_XCross_Road5.uasset"
|
||||
RoadXIntersection_Lane3 at "Content/Carla/Static/Road/St_Road_XCross_Road6.uasset"
|
||||
RoadXIntersection_Lane3 at "Content/Carla/Static/Road/St_Road_XCross_Road7.uasset"
|
||||
RoadXIntersection_Lane3 at "Content/Carla/Static/Road/St_Road_XCross_Road8.uasset"
|
||||
RoadXIntersection_Lane3 at "Content/Carla/Static/Road/St_Road_XCross_Road9.uasset"
|
||||
RoadXIntersection_Sidewalk0 at "Content/Carla/Static/SideWalk/St_Road_XCross_Sidewalk1.uasset"
|
||||
RoadXIntersection_Sidewalk1 at "Content/Carla/Static/SideWalk/St_Road_XCross_Sidewalk2.uasset"
|
||||
RoadXIntersection_Sidewalk2 at "Content/Carla/Static/SideWalk/St_Road_XCross_Sidewalk3.uasset"
|
||||
RoadXIntersection_Sidewalk3 at "Content/Carla/Static/SideWalk/St_Road_XCross_Sidewalk4.uasset"
|
||||
RoadXIntersection_LaneMarking at "Content/Carla/Static/RoadLines/St_Road_XCross_LaneMarking.uasset"
|
||||
```
|
||||
|
|
|
@ -5,15 +5,23 @@
|
|||
|
||||
Install the build tools and dependencies
|
||||
|
||||
$ sudo apt-get install build-essential clang-3.9 git cmake ninja-build python3-requests python-dev tzdata sed curl wget unzip autoconf libtool
|
||||
```
|
||||
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential clang-5.0 lld-5.0 g++-7 ninja-build python python-pip python-dev tzdata sed curl wget unzip autoconf libtool
|
||||
pip install --user setuptools nose2
|
||||
```
|
||||
|
||||
To avoid compatibility issues between Unreal Engine and the CARLA dependencies,
|
||||
the best configuration is to compile everything with the same compiler version
|
||||
and C++ runtime library. We use clang 3.9 and LLVM's libc++. You may need to
|
||||
change your default clang version to compile Unreal
|
||||
and C++ runtime library. We use clang 5.0 and LLVM's libc++. We recommend to
|
||||
change your default clang version to compile Unreal Engine and the CARLA
|
||||
dependencies
|
||||
|
||||
$ sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/lib/llvm-3.9/bin/clang++ 100
|
||||
$ sudo update-alternatives --install /usr/bin/clang clang /usr/lib/llvm-3.9/bin/clang 100
|
||||
```sh
|
||||
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/lib/llvm-5.0/bin/clang++ 101
|
||||
sudo update-alternatives --install /usr/bin/clang clang /usr/lib/llvm-5.0/bin/clang 101
|
||||
```
|
||||
|
||||
Build Unreal Engine
|
||||
-------------------
|
||||
|
@ -23,13 +31,15 @@ Build Unreal Engine
|
|||
need to add your GitHub username when you sign up at
|
||||
[www.unrealengine.com](https://www.unrealengine.com).
|
||||
|
||||
Download and compile Unreal Engine 4.18. Here we will assume you install it at
|
||||
"~/UnrealEngine_4.18", but you can install it anywhere, just replace the path
|
||||
Download and compile Unreal Engine 4.19. Here we will assume you install it at
|
||||
`~/UnrealEngine_4.19", but you can install it anywhere, just replace the path
|
||||
where necessary.
|
||||
|
||||
$ git clone --depth=1 -b 4.18 https://github.com/EpicGames/UnrealEngine.git ~/UnrealEngine_4.18
|
||||
$ cd ~/UnrealEngine_4.18
|
||||
$ ./Setup.sh && ./GenerateProjectFiles.sh && make
|
||||
```sh
|
||||
git clone --depth=1 -b 4.19 https://github.com/EpicGames/UnrealEngine.git ~/UnrealEngine_4.19
|
||||
cd ~/UnrealEngine_4.19
|
||||
./Setup.sh && ./GenerateProjectFiles.sh && make
|
||||
```
|
||||
|
||||
Check Unreal's documentation
|
||||
["Building On Linux"](https://wiki.unrealengine.com/Building_On_Linux) if any of
|
||||
|
@ -41,56 +51,47 @@ Build CARLA
|
|||
Clone or download the project from our
|
||||
[GitHub repository](https://github.com/carla-simulator/carla)
|
||||
|
||||
$ git clone https://github.com/carla-simulator/carla
|
||||
```sh
|
||||
git clone https://github.com/carla-simulator/carla
|
||||
```
|
||||
|
||||
Note that the `master` branch contains the latest fixes and features, for the
|
||||
latest stable code may be best to switch to the latest release tag.
|
||||
|
||||
Run the setup script to download the content and build all dependencies. It
|
||||
takes a while (you can speed up the process by parallelizing the script with the
|
||||
`--jobs=8` flag)
|
||||
Now you need to download the assets package, to do so we provide a handy script
|
||||
that downloads and extracts the latest version (note that the package is >10GB,
|
||||
this step might take some time depending on your connection)
|
||||
|
||||
$ ./Setup.sh
|
||||
```sh
|
||||
./Update.sh
|
||||
```
|
||||
|
||||
Once it's done it should print "Success" if everything went well.
|
||||
For CARLA to find your Unreal Engine's installation folder you need to set the
|
||||
following environment variable
|
||||
|
||||
To build CARLA, use the rebuild script. This script deletes all intermediate
|
||||
files, rebuilds whole CARLA, and launches the editor. Use it too for making a
|
||||
clean rebuild of CARLA
|
||||
```sh
|
||||
export UE4_ROOT=~/UnrealEngine_4.19
|
||||
```
|
||||
|
||||
$ UE4_ROOT=~/UnrealEngine_4.18 ./Rebuild.sh
|
||||
You can also add this variable to your `~/.bashrc` or `~/.profile`.
|
||||
|
||||
It looks at the environment variable `UE4_ROOT` to find the right version of
|
||||
Unreal Engine. You can also add this variable to your "~/.bashrc" or similar.
|
||||
Now that the environment is set up, you can run make to run different commands
|
||||
|
||||
Later, if you need to compile some changes without doing a full rebuild, you can
|
||||
use the Makefile generated in the Unreal project folder
|
||||
|
||||
$ cd Unreal/CarlaUE4
|
||||
$ make CarlaUE4Editor
|
||||
```sh
|
||||
make launch # Compiles CARLA and launches Unreal Engine's Editor.
|
||||
make package # Compiles CARLA and creates a packaged version for distribution.
|
||||
make help # Print all available commands.
|
||||
```
|
||||
|
||||
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
|
||||
the CARLA assets. To download the latest version and recompile CARLA, run
|
||||
|
||||
$ git pull
|
||||
$ ./Update.sh
|
||||
|
||||
Launching the editor
|
||||
--------------------
|
||||
|
||||
To open the editor once the project is already built
|
||||
|
||||
$ cd Unreal/CarlaUE4
|
||||
$ ~/UnrealEngine_4.18/Engine/Binaries/Linux/UE4Editor "$PWD/CarlaUE4.uproject"
|
||||
|
||||
Test (Optional)
|
||||
---------------
|
||||
|
||||
A set of unit tests is available for testing the CarlaServer library (note that
|
||||
these tests launch the python client, they require python3 and protobuf for
|
||||
python3 installed, as well as ports 2000 and 4000 available)
|
||||
|
||||
$ make check
|
||||
```sh
|
||||
make clean
|
||||
git pull
|
||||
./Update.sh
|
||||
make launch
|
||||
```
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
<h1>How to build CARLA on Windows</h1>
|
||||
|
||||
!!! important
|
||||
Since version 0.9.0 the build system changed, the instructions in this
|
||||
document are no longer valid. While we work on fixing this, we recommend
|
||||
either compile Carla on Linux or switch to the `stable` branch. Sorry for
|
||||
the inconvenience.
|
||||
|
||||
<h3>Necessary software</h3>
|
||||
- [Git](https://git-scm.com/downloads)
|
||||
- [Make](http://gnuwin32.sourceforge.net/downlinks/make-bin-zip.php)
|
||||
|
@ -22,7 +28,7 @@ You have different options:
|
|||
- [Enable a 64-Bit Visual C++ Toolset on the Command Line](https://msdn.microsoft.com/en-us/library/x4d2c09s.aspx) (the instructions will depend on the version of VS that you have).
|
||||
|
||||
!!! note
|
||||
Take care if you have **Cygwin** installed. This could cause the errors like
|
||||
Take care if you have **Cygwin** installed. This could cause the errors like
|
||||
`/usr/bin/sh: rd: command not found` While executing `Reuild.bat`.
|
||||
|
||||
<h3>Clone the repository</h3>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
|
@ -1,12 +1,17 @@
|
|||
<h1>CARLA Documentation</h1>
|
||||
|
||||
!!! important
|
||||
This documentation refers to the latest development versions of CARLA, 0.9.0
|
||||
or later. For the documentation of the stable version please switch to the
|
||||
[stable branch](https://carla.readthedocs.io/en/stable/).
|
||||
|
||||
<h3>Quick start</h3>
|
||||
|
||||
* [Getting started](getting_started.md)
|
||||
* [Running the simulator](running_simulator_standalone.md)
|
||||
* [Connecting a Python client](connecting_the_client.md)
|
||||
<!-- * [Running the simulator](running_simulator_standalone.md) -->
|
||||
<!-- * [Connecting a Python client](connecting_the_client.md) -->
|
||||
* [Configuring the simulation](configuring_the_simulation.md)
|
||||
* [Measurements](measurements.md)
|
||||
<!-- * [Measurements](measurements.md) -->
|
||||
* [Cameras and sensors](cameras_and_sensors.md)
|
||||
* [F.A.Q.](faq.md)
|
||||
|
||||
|
@ -21,11 +26,12 @@
|
|||
* [General Structure](benchmark_structure.md)
|
||||
* [Creating Your Benchmark](benchmark_creating.md)
|
||||
* [Computed Performance Metrics](benchmark_metrics.md)
|
||||
|
||||
|
||||
<h3>Advanced topics</h3>
|
||||
|
||||
* [CARLA settings](carla_settings.md)
|
||||
* [Simulator keyboard input](simulator_keyboard_input.md)
|
||||
* [Python API](python_api.md)
|
||||
<!-- * [Simulator keyboard input](simulator_keyboard_input.md) -->
|
||||
* [Running without display and selecting GPUs](carla_headless.md)
|
||||
* [How to link Epic's Automotive Materials](epic_automotive_materials.md)
|
||||
|
||||
|
@ -39,5 +45,6 @@
|
|||
|
||||
* [Map customization](map_customization.md)
|
||||
* [How to add assets](how_to_add_assets.md)
|
||||
* [CARLA design](carla_design.md)
|
||||
* [CarlaServer documentation](carla_server.md)
|
||||
<!-- * [CARLA design](carla_design.md) -->
|
||||
<!-- * [CarlaServer documentation](carla_server.md) -->
|
||||
* [Build system](build_system.md)
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
<h1>Python API Reference</h1>
|
||||
|
||||
!!! important
|
||||
Versions prior to 0.9.0 have a very different API. For the documentation of
|
||||
the stable version please switch to the
|
||||
[stable branch](https://carla.readthedocs.io/en/stable/).
|
||||
|
||||
## `carla.Client`
|
||||
|
||||
- `Client(host, port, worker_threads=0)`
|
||||
- `set_timeout(milliseconds)`
|
||||
- `get_client_version()`
|
||||
- `get_server_version()`
|
||||
- `ping()`
|
||||
- `get_world()`
|
||||
|
||||
## `carla.World`
|
||||
|
||||
- `get_blueprint_library()`
|
||||
- `get_spectator()`
|
||||
- `spawn_actor(blueprint, transform, attach_to=None)`
|
||||
- `try_spawn_actor(blueprint, transform, attach_to=None)`
|
||||
|
||||
## `carla.BlueprintLibrary`
|
||||
|
||||
- `find(id)`
|
||||
- `filter(wildcard_pattern)`
|
||||
- `__getitem__(pos)`
|
||||
- `__len__()`
|
||||
- `__iter__()`
|
||||
|
||||
## `carla.ActorBlueprint`
|
||||
|
||||
- `id`
|
||||
- `tags`
|
||||
- `contains_tag(tag)`
|
||||
- `match_tags(wildcard_pattern)`
|
||||
- `contains_attribute(key)`
|
||||
- `get_attribute(key)`
|
||||
- `set_attribute(key, value)`
|
||||
|
||||
## `carla.ActorAttribute`
|
||||
|
||||
- `is_modifiable`
|
||||
- `type`
|
||||
- `recommended_values`
|
||||
- `as_bool()`
|
||||
- `as_int()`
|
||||
- `as_float()`
|
||||
- `as_str()`
|
||||
- `as_color()`
|
||||
- `__eq__()`
|
||||
- `__ne__()`
|
||||
- `__nonzero__()`
|
||||
- `__bool__()`
|
||||
- `__int__()`
|
||||
- `__float__()`
|
||||
- `__str__()`
|
||||
|
||||
## `carla.Actor`
|
||||
|
||||
- `id`
|
||||
- `type_id`
|
||||
- `get_world()`
|
||||
- `get_location()`
|
||||
- `get_transform()`
|
||||
- `set_location(location)`
|
||||
- `set_transform(transform)`
|
||||
- `destroy()`
|
||||
|
||||
## `carla.Vehicle(carla.Actor)`
|
||||
|
||||
- `apply_control(vehicle_control)`
|
||||
- `set_autopilot(enabled=True)`
|
||||
|
||||
## `carla.Sensor(carla.Actor)`
|
||||
|
||||
- `listen(callback_function)`
|
||||
|
||||
## `carla.Image`
|
||||
|
||||
- `frame_number`
|
||||
- `width`
|
||||
- `height`
|
||||
- `type`
|
||||
- `fov`
|
||||
- `raw_data`
|
||||
|
||||
## `carla.VehicleControl`
|
||||
|
||||
- `throttle`
|
||||
- `steer`
|
||||
- `brake`
|
||||
- `hand_brake`
|
||||
- `reverse`
|
||||
|
||||
## `carla.Location`
|
||||
|
||||
- `x`
|
||||
- `y`
|
||||
- `z`
|
||||
|
||||
## `carla.Rotation`
|
||||
|
||||
- `pitch`
|
||||
- `yaw`
|
||||
- `roll`
|
||||
|
||||
## `carla.Transform`
|
||||
|
||||
- `location`
|
||||
- `rotation`
|
||||
|
||||
## `carla.Color`
|
||||
|
||||
- `r`
|
||||
- `g`
|
||||
- `b`
|
4
Doxyfile
4
Doxyfile
|
@ -11,7 +11,7 @@ CASE_SENSE_NAMES = YES
|
|||
SORT_BRIEF_DOCS = YES
|
||||
WARN_IF_UNDOCUMENTED = NO
|
||||
WARN_LOGFILE = Doxygen/warnings.log
|
||||
INPUT = Unreal/CarlaUE4/Source Unreal/CarlaUE4/Plugins/Carla/Source Util/CarlaServer/source
|
||||
INPUT = Unreal/CarlaUE4/Source Unreal/CarlaUE4/Plugins/Carla/Source LibCarla/source
|
||||
FILE_PATTERNS = *.cpp *.h *.hpp *.cc
|
||||
RECURSIVE = YES
|
||||
SOURCE_BROWSER = YES
|
||||
|
@ -26,7 +26,7 @@ FORMULA_FONTSIZE = 12
|
|||
GENERATE_LATEX = NO
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
INCLUDE_PATH = Unreal/CarlaUE4/Source Unreal/CarlaUE4/Plugins/Carla/Source Util/CarlaServer/source Util/CarlaServer/include
|
||||
INCLUDE_PATH = Unreal/CarlaUE4/Source Unreal/CarlaUE4/Plugins/Carla/Source LibCarla/source
|
||||
INCLUDE_FILE_PATTERNS = *.h *.hpp
|
||||
HIDE_UNDOC_RELATIONS = NO
|
||||
HAVE_DOT = YES
|
||||
|
|
|
@ -2,41 +2,58 @@ pipeline {
|
|||
agent any
|
||||
|
||||
environment {
|
||||
UE4_ROOT = '/var/lib/jenkins/UnrealEngine_4.18'
|
||||
UE4_ROOT = '/var/lib/jenkins/UnrealEngine_4.19'
|
||||
}
|
||||
|
||||
options {
|
||||
buildDiscarder(logRotator(numToKeepStr: '6', artifactNumToKeepStr: '6'))
|
||||
buildDiscarder(logRotator(numToKeepStr: '3', artifactNumToKeepStr: '3'))
|
||||
}
|
||||
|
||||
stages {
|
||||
|
||||
stage('Setup') {
|
||||
steps {
|
||||
sh './Setup.sh --jobs=12'
|
||||
sh 'make setup'
|
||||
sh './Update.sh'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh './Rebuild.sh --no-editor'
|
||||
sh 'make LibCarla'
|
||||
sh 'make PythonAPI'
|
||||
sh 'make CarlaUE4Editor'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Unit Tests') {
|
||||
steps {
|
||||
sh 'make check ARGS="--all --xml"'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
junit 'Build/test-results/*.xml'
|
||||
archiveArtifacts 'profiler.csv'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Package') {
|
||||
steps {
|
||||
sh './Package.sh --clean-intermediate'
|
||||
sh 'make package'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
archiveArtifacts 'Dist/*.tar.gz'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
post {
|
||||
|
||||
always {
|
||||
archiveArtifacts 'Dist/*.tar.gz'
|
||||
deleteDir()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
cmake_minimum_required(VERSION 3.9.0)
|
||||
project(libcarla)
|
||||
|
||||
message(STATUS "Building ${PROJECT_NAME} version ${CARLA_VERSION}")
|
||||
|
||||
set(libcarla_source_path "${PROJECT_SOURCE_DIR}/../source")
|
||||
|
||||
include_directories(${libcarla_source_path})
|
||||
|
||||
configure_file(${libcarla_source_path}/carla/Version.h.in ${libcarla_source_path}/carla/Version.h)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Client")
|
||||
add_subdirectory("client")
|
||||
elseif (CMAKE_BUILD_TYPE STREQUAL "Server")
|
||||
add_subdirectory("server")
|
||||
add_subdirectory("test")
|
||||
else ()
|
||||
message(FATAL_ERROR "Unknown build type '${CMAKE_BUILD_TYPE}'")
|
||||
endif ()
|
|
@ -0,0 +1,79 @@
|
|||
cmake_minimum_required(VERSION 3.9.0)
|
||||
project(libcarla-client)
|
||||
|
||||
# Install rpclib.
|
||||
install(DIRECTORY "${RPCLIB_INCLUDE_PATH}/rpc" DESTINATION include)
|
||||
install(FILES "${RPCLIB_LIB_PATH}/librpc.a" DESTINATION lib)
|
||||
|
||||
file(GLOB libcarla_sources
|
||||
"${libcarla_source_path}/carla/*.h"
|
||||
"${libcarla_source_path}/carla/*.cpp")
|
||||
|
||||
file(GLOB_RECURSE libcarla_client_sources
|
||||
"${libcarla_source_path}/carla/client/*.h"
|
||||
"${libcarla_source_path}/carla/client/*.cpp"
|
||||
"${libcarla_source_path}/carla/rpc/*.h"
|
||||
"${libcarla_source_path}/carla/rpc/*.cpp"
|
||||
"${libcarla_source_path}/carla/streaming/*.h"
|
||||
"${libcarla_source_path}/carla/streaming/*.cpp")
|
||||
|
||||
# Create targets for debug and release in the same build type.
|
||||
foreach(target carla_client_debug carla_client)
|
||||
add_library(${target} STATIC ${libcarla_client_sources} ${libcarla_sources})
|
||||
|
||||
target_include_directories(${target} PRIVATE
|
||||
"${BOOST_INCLUDE_PATH}"
|
||||
"${RPCLIB_INCLUDE_PATH}")
|
||||
|
||||
# @todo This was disabled because now everything is built in the setup.py.
|
||||
# install(TARGETS ${target} DESTINATION lib)
|
||||
endforeach(target)
|
||||
|
||||
# Specific options for debug.
|
||||
set_target_properties(carla_client_debug PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
target_compile_definitions(carla_client_debug PUBLIC -DBOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
|
||||
|
||||
# Specific options for release.
|
||||
set_target_properties(carla_client PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_RELEASE})
|
||||
|
||||
# Install headers.
|
||||
|
||||
install(DIRECTORY "${BOOST_INCLUDE_PATH}/boost" DESTINATION include)
|
||||
|
||||
file(GLOB boost_libraries "${BOOST_LIB_PATH}/*")
|
||||
install(FILES ${boost_libraries} DESTINATION lib)
|
||||
|
||||
file(GLOB libcarla_carla_headers
|
||||
"${libcarla_source_path}/carla/*.cpp"
|
||||
"${libcarla_source_path}/carla/*.h")
|
||||
install(FILES ${libcarla_carla_headers} DESTINATION include/carla)
|
||||
|
||||
file(GLOB libcarla_carla_client_headers
|
||||
"${libcarla_source_path}/carla/client/*.cpp"
|
||||
"${libcarla_source_path}/carla/client/*.h")
|
||||
install(FILES ${libcarla_carla_client_headers} DESTINATION include/carla/client)
|
||||
|
||||
file(GLOB libcarla_carla_rpc_headers
|
||||
"${libcarla_source_path}/carla/rpc/*.cpp"
|
||||
"${libcarla_source_path}/carla/rpc/*.h")
|
||||
install(FILES ${libcarla_carla_rpc_headers} DESTINATION include/carla/rpc)
|
||||
|
||||
file(GLOB libcarla_carla_streaming_headers
|
||||
"${libcarla_source_path}/carla/streaming/*.cpp"
|
||||
"${libcarla_source_path}/carla/streaming/*.h")
|
||||
install(FILES ${libcarla_carla_streaming_headers} DESTINATION include/carla/streaming)
|
||||
|
||||
file(GLOB libcarla_carla_streaming_detail_headers
|
||||
"${libcarla_source_path}/carla/streaming/detail/*.cpp"
|
||||
"${libcarla_source_path}/carla/streaming/detail/*.h")
|
||||
install(FILES ${libcarla_carla_streaming_detail_headers} DESTINATION include/carla/streaming/detail)
|
||||
|
||||
file(GLOB libcarla_carla_streaming_detail_tcp_headers
|
||||
"${libcarla_source_path}/carla/streaming/detail/tcp/*.cpp"
|
||||
"${libcarla_source_path}/carla/streaming/detail/tcp/*.h")
|
||||
install(FILES ${libcarla_carla_streaming_detail_tcp_headers} DESTINATION include/carla/streaming/detail/tcp)
|
||||
|
||||
file(GLOB libcarla_carla_streaming_low_level_headers
|
||||
"${libcarla_source_path}/carla/streaming/low_level/*.cpp"
|
||||
"${libcarla_source_path}/carla/streaming/low_level/*.h")
|
||||
install(FILES ${libcarla_carla_streaming_low_level_headers} DESTINATION include/carla/streaming/low_level)
|
|
@ -0,0 +1,60 @@
|
|||
cmake_minimum_required(VERSION 3.9.0)
|
||||
project(libcarla-server)
|
||||
|
||||
# Install libc++ shared libraries.
|
||||
file(GLOB LibCXX_Libraries "${LLVM_LIB_PATH}/libc++*")
|
||||
install(FILES ${LibCXX_Libraries} DESTINATION lib)
|
||||
|
||||
# Install rpclib.
|
||||
install(DIRECTORY "${RPCLIB_INCLUDE_PATH}/rpc" DESTINATION include)
|
||||
install(FILES "${RPCLIB_LIB_PATH}/librpc.a" DESTINATION lib)
|
||||
|
||||
# Install headers.
|
||||
|
||||
install(DIRECTORY "${libcarla_source_path}/compiler" DESTINATION include)
|
||||
|
||||
file(GLOB libcarla_carla_headers "${libcarla_source_path}/carla/*.h")
|
||||
install(FILES ${libcarla_carla_headers} DESTINATION include/carla)
|
||||
|
||||
file(GLOB libcarla_carla_rpc_headers "${libcarla_source_path}/carla/rpc/*.h")
|
||||
install(FILES ${libcarla_carla_rpc_headers} DESTINATION include/carla/rpc)
|
||||
|
||||
file(GLOB libcarla_carla_streaming_headers "${libcarla_source_path}/carla/streaming/*.h")
|
||||
install(FILES ${libcarla_carla_streaming_headers} DESTINATION include/carla/streaming)
|
||||
|
||||
file(GLOB libcarla_carla_streaming_detail_headers "${libcarla_source_path}/carla/streaming/detail/*.h")
|
||||
install(FILES ${libcarla_carla_streaming_detail_headers} DESTINATION include/carla/streaming/detail)
|
||||
|
||||
file(GLOB libcarla_carla_streaming_detail_tcp_headers "${libcarla_source_path}/carla/streaming/detail/tcp/*.h")
|
||||
install(FILES ${libcarla_carla_streaming_detail_tcp_headers} DESTINATION include/carla/streaming/detail/tcp)
|
||||
|
||||
file(GLOB libcarla_carla_streaming_low_level_headers "${libcarla_source_path}/carla/streaming/low_level/*.h")
|
||||
install(FILES ${libcarla_carla_streaming_low_level_headers} DESTINATION include/carla/streaming/low_level)
|
||||
|
||||
install(DIRECTORY "${BOOST_INCLUDE_PATH}/boost" DESTINATION include)
|
||||
|
||||
# carla_server library.
|
||||
|
||||
file(GLOB_RECURSE libcarla_server_sources
|
||||
"${libcarla_source_path}/carla/rpc/*.h"
|
||||
"${libcarla_source_path}/carla/rpc/*.cpp"
|
||||
"${libcarla_source_path}/carla/streaming/*.h"
|
||||
"${libcarla_source_path}/carla/streaming/*.cpp")
|
||||
|
||||
# Create targets for debug and release in the same build type.
|
||||
foreach(target carla_server_debug carla_server)
|
||||
add_library(${target} STATIC ${libcarla_server_sources})
|
||||
|
||||
target_include_directories(${target} PRIVATE
|
||||
"${BOOST_INCLUDE_PATH}"
|
||||
"${RPCLIB_INCLUDE_PATH}")
|
||||
|
||||
install(TARGETS ${target} DESTINATION lib)
|
||||
endforeach(target)
|
||||
|
||||
# Specific options for debug.
|
||||
set_target_properties(carla_server_debug PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
target_compile_definitions(carla_server_debug PUBLIC -DBOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
|
||||
|
||||
# Specific options for release.
|
||||
set_target_properties(carla_server PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_RELEASE})
|
|
@ -0,0 +1,38 @@
|
|||
cmake_minimum_required(VERSION 3.9.0)
|
||||
project(libcarla-unit-tests)
|
||||
|
||||
file(GLOB_RECURSE libcarla_test_sources
|
||||
"${libcarla_source_path}/carla/profiler/*.h"
|
||||
"${libcarla_source_path}/carla/profiler/*.cpp"
|
||||
"${libcarla_source_path}/test/*.h"
|
||||
"${libcarla_source_path}/test/*.cpp")
|
||||
|
||||
link_directories(
|
||||
${RPCLIB_LIB_PATH}
|
||||
${GTEST_LIB_PATH})
|
||||
|
||||
# Create targets for debug and release in the same build type.
|
||||
foreach(target libcarla_test_debug libcarla_test_release)
|
||||
add_executable(${target} ${libcarla_test_sources})
|
||||
|
||||
target_compile_definitions(${target} PUBLIC
|
||||
-DLIBCARLA_ENABLE_PROFILER
|
||||
-DLIBCARLA_WITH_GTEST)
|
||||
|
||||
target_include_directories(${target} PRIVATE
|
||||
"${BOOST_INCLUDE_PATH}"
|
||||
"${RPCLIB_INCLUDE_PATH}"
|
||||
"${GTEST_INCLUDE_PATH}")
|
||||
target_link_libraries(${target} "-lrpc -lgtest_main -lgtest")
|
||||
|
||||
install(TARGETS ${target} DESTINATION test)
|
||||
endforeach(target)
|
||||
|
||||
# Specific options for debug.
|
||||
set_target_properties(libcarla_test_debug PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
target_link_libraries(libcarla_test_debug "carla_server_debug")
|
||||
target_compile_definitions(libcarla_test_debug PUBLIC -DBOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
|
||||
|
||||
# Specific options for release.
|
||||
set_target_properties(libcarla_test_release PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_RELEASE})
|
||||
target_link_libraries(libcarla_test_release "carla_server")
|
|
@ -0,0 +1 @@
|
|||
Version.h
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NDEBUG
|
||||
# include <cassert>
|
||||
#endif // NDEBUG
|
||||
|
||||
#ifdef NDEBUG
|
||||
# define DEBUG_ONLY(code)
|
||||
#else
|
||||
# define DEBUG_ONLY(code) code
|
||||
#endif // NDEBUG
|
||||
|
||||
#define DEBUG_ASSERT(predicate) DEBUG_ONLY(assert(predicate));
|
||||
|
||||
#ifdef LIBCARLA_WITH_GTEST
|
||||
# include <gtest/gtest.h>
|
||||
|
||||
# define DEBUG_ASSERT_EQ(lhs, rhs) DEBUG_ONLY(EXPECT_EQ(lhs, rhs));DEBUG_ASSERT(lhs == rhs);
|
||||
# define DEBUG_ASSERT_NE(lhs, rhs) DEBUG_ONLY(EXPECT_NE(lhs, rhs));DEBUG_ASSERT(lhs != rhs);
|
||||
#else
|
||||
# define DEBUG_ASSERT_EQ(lhs, rhs) DEBUG_ASSERT((lhs) == (rhs))
|
||||
# define DEBUG_ASSERT_NE(lhs, rhs) DEBUG_ASSERT((lhs) != (rhs))
|
||||
#endif // LIBCARLA_WITH_GTEST
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
|
||||
namespace carla {
|
||||
namespace iterator {
|
||||
|
||||
/// Creates an iterator over the keys of a map.
|
||||
template <typename It>
|
||||
static auto make_map_keys_iterator(It it) {
|
||||
return boost::make_transform_iterator(it, [](auto &pair){ return pair.first; });
|
||||
}
|
||||
|
||||
/// Creates an iterator over the values of a map.
|
||||
template <typename It>
|
||||
static auto make_map_values_iterator(It it) {
|
||||
return boost::make_transform_iterator(it, [](auto &pair){ return pair.second; });
|
||||
}
|
||||
|
||||
} // namespace iterator
|
||||
} // namespace carla
|
|
@ -0,0 +1,148 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define LIBCARLA_LOG_LEVEL_DEBUG 10
|
||||
#define LIBCARLA_LOG_LEVEL_INFO 20
|
||||
#define LIBCARLA_LOG_LEVEL_WARNING 30
|
||||
#define LIBCARLA_LOG_LEVEL_ERROR 40
|
||||
#define LIBCARLA_LOG_LEVEL_CRITICAL 50
|
||||
#define LIBCARLA_LOG_LEVEL_NONE 100
|
||||
|
||||
#ifndef LIBCARLA_LOG_LEVEL
|
||||
# ifdef NDEBUG
|
||||
# define LIBCARLA_LOG_LEVEL LIBCARLA_LOG_LEVEL_WARNING
|
||||
# else
|
||||
# define LIBCARLA_LOG_LEVEL LIBCARLA_LOG_LEVEL_INFO
|
||||
# endif // NDEBUG
|
||||
#endif // LIBCARLA_LOG_LEVEL
|
||||
|
||||
// The following log functions are available, they are only active if
|
||||
// LIBCARLA_LOG_LEVEL is greater equal the function's log level.
|
||||
//
|
||||
// * log_debug
|
||||
// * log_info
|
||||
// * log_error
|
||||
// * log_critical
|
||||
//
|
||||
// And macros
|
||||
//
|
||||
// * LOG_DEBUG_ONLY(/* code here */)
|
||||
// * LOG_INFO_ONLY(/* code here */)
|
||||
|
||||
// =============================================================================
|
||||
// -- Implementation of log functions ------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace carla {
|
||||
|
||||
namespace logging {
|
||||
|
||||
// https://stackoverflow.com/a/27375675
|
||||
template <typename Arg, typename ... Args>
|
||||
static void write_to_stream(std::ostream &out, Arg &&arg, Args && ... args) {
|
||||
out << std::boolalpha << std::forward<Arg>(arg);
|
||||
using expander = int[];
|
||||
(void) expander{0, (void(out << ' ' << std::forward<Args>(args)), 0) ...};
|
||||
}
|
||||
|
||||
template <typename ... Args>
|
||||
static inline void log(Args && ... args) {
|
||||
logging::write_to_stream(std::cout, std::forward<Args>(args) ..., '\n');
|
||||
}
|
||||
|
||||
} // namespace logging
|
||||
|
||||
#if LIBCARLA_LOG_LEVEL <= LIBCARLA_LOG_LEVEL_DEBUG
|
||||
|
||||
template <typename ... Args>
|
||||
static inline void log_debug(Args && ... args) {
|
||||
logging::write_to_stream(std::cout, "DEBUG:", std::forward<Args>(args) ..., '\n');
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename ... Args>
|
||||
static inline void log_debug(Args && ...) {}
|
||||
|
||||
#endif
|
||||
|
||||
#if LIBCARLA_LOG_LEVEL <= LIBCARLA_LOG_LEVEL_INFO
|
||||
|
||||
template <typename ... Args>
|
||||
static inline void log_info(Args && ... args) {
|
||||
logging::write_to_stream(std::cout, "INFO: ", std::forward<Args>(args) ..., '\n');
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename ... Args>
|
||||
static inline void log_info(Args && ...) {}
|
||||
|
||||
#endif
|
||||
|
||||
#if LIBCARLA_LOG_LEVEL <= LIBCARLA_LOG_LEVEL_WARNING
|
||||
|
||||
template <typename ... Args>
|
||||
static inline void log_warning(Args && ... args) {
|
||||
logging::write_to_stream(std::cerr, "WARNING:", std::forward<Args>(args) ..., '\n');
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename ... Args>
|
||||
static inline void log_warning(Args && ...) {}
|
||||
|
||||
#endif
|
||||
|
||||
#if LIBCARLA_LOG_LEVEL <= LIBCARLA_LOG_LEVEL_ERROR
|
||||
|
||||
template <typename ... Args>
|
||||
static inline void log_error(Args && ... args) {
|
||||
logging::write_to_stream(std::cerr, "ERROR:", std::forward<Args>(args) ..., '\n');
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename ... Args>
|
||||
static inline void log_error(Args && ...) {}
|
||||
|
||||
#endif
|
||||
|
||||
#if LIBCARLA_LOG_LEVEL <= LIBCARLA_LOG_LEVEL_CRITICAL
|
||||
|
||||
template <typename ... Args>
|
||||
static inline void log_critical(Args && ... args) {
|
||||
logging::write_to_stream(std::cerr, "CRITICAL:", std::forward<Args>(args) ..., '\n');
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename ... Args>
|
||||
static inline void log_critical(Args && ...) {}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace carla
|
||||
|
||||
// =============================================================================
|
||||
// -- Implementation of macros -------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
#if LIBCARLA_LOG_LEVEL <= LIBCARLA_LOG_LEVEL_DEBUG
|
||||
# define LOG_DEBUG_ONLY(code) code
|
||||
#else
|
||||
# define LOG_DEBUG_ONLY(code)
|
||||
#endif
|
||||
|
||||
#if LIBCARLA_LOG_LEVEL <= LIBCARLA_LOG_LEVEL_INFO
|
||||
# define LOG_INFO_ONLY(code) code
|
||||
#else
|
||||
# define LOG_INFO_ONLY(code)
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace carla {
|
||||
|
||||
/// Inherit (privately) to suppress copy-construction and copy-assignment.
|
||||
class NonCopyable {
|
||||
public:
|
||||
|
||||
NonCopyable() = default;
|
||||
|
||||
NonCopyable(const NonCopyable &) = delete;
|
||||
|
||||
void operator=(const NonCopyable &) = delete;
|
||||
};
|
||||
|
||||
} // namespace carla
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace carla {
|
||||
namespace detail {
|
||||
|
||||
template <typename CLOCK>
|
||||
class StopWatchTmpl {
|
||||
static_assert(CLOCK::is_steady, "The StopWatch's clock must be steady");
|
||||
public:
|
||||
|
||||
using clock = CLOCK;
|
||||
|
||||
StopWatchTmpl() : _start(clock::now()), _end(), _is_running(true) {}
|
||||
|
||||
void Restart() {
|
||||
_is_running = true;
|
||||
_start = clock::now();
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
_end = clock::now();
|
||||
_is_running = false;
|
||||
}
|
||||
|
||||
typename clock::duration GetDuration() const {
|
||||
return _is_running ? clock::now() - _start : _end - _start;
|
||||
}
|
||||
|
||||
template <class RESOLUTION=std::chrono::milliseconds>
|
||||
typename RESOLUTION::rep GetElapsedTime() const {
|
||||
return std::chrono::duration_cast<RESOLUTION>(GetDuration()).count();
|
||||
}
|
||||
|
||||
bool IsRunning() const {
|
||||
return _is_running;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
typename clock::time_point _start;
|
||||
|
||||
typename clock::time_point _end;
|
||||
|
||||
bool _is_running;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
using StopWatch = detail::StopWatchTmpl<std::chrono::steady_clock>;
|
||||
|
||||
} // namespace carla
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/StringUtil.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <shlwapi.h>
|
||||
#else
|
||||
# include <fnmatch.h>
|
||||
#endif // _WIN32
|
||||
|
||||
namespace carla {
|
||||
|
||||
bool StringUtil::Match(const std::string &str, const std::string &test) {
|
||||
#ifdef _WIN32
|
||||
return PathMatchSpecA(str.c_str(), test.c_str());
|
||||
#else
|
||||
return 0 == fnmatch(test.c_str(), str.c_str(), 0);
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
} // namespace carla
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
namespace carla {
|
||||
|
||||
class StringUtil {
|
||||
public:
|
||||
|
||||
static void ToLower(std::string &str) {
|
||||
boost::algorithm::to_lower(str);
|
||||
}
|
||||
|
||||
static std::string ToLowerCopy(const std::string &str) {
|
||||
return boost::algorithm::to_lower_copy(str);
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
static void Split(Container &destination, const std::string &str, const std::string &separators) {
|
||||
boost::split(destination, str, boost::is_any_of(separators));
|
||||
}
|
||||
|
||||
/// Match @a str with the Unix shell-style @a wildcard_pattern.
|
||||
static bool Match(const std::string &str, const std::string &wildcard_pattern);
|
||||
};
|
||||
|
||||
} // namespace carla
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace carla {
|
||||
|
||||
class ThreadGroup {
|
||||
public:
|
||||
|
||||
ThreadGroup() {}
|
||||
|
||||
ThreadGroup(const ThreadGroup &) = delete;
|
||||
ThreadGroup &operator=(const ThreadGroup &) = delete;
|
||||
|
||||
~ThreadGroup() {
|
||||
JoinAll();
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void CreateThread(F &&functor) {
|
||||
_threads.emplace_back(std::forward<F>(functor));
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void CreateThreads(size_t count, F functor) {
|
||||
_threads.reserve(_threads.size() + count);
|
||||
for (size_t i = 0u; i < count; ++i) {
|
||||
CreateThread(functor);
|
||||
}
|
||||
}
|
||||
|
||||
void JoinAll() {
|
||||
for (auto &thread : _threads) {
|
||||
if (thread.joinable()) {
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::vector<std::thread> _threads;
|
||||
};
|
||||
|
||||
} // namespace carla
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace carla {
|
||||
|
||||
/// Positive time duration up to milliseconds resolution. Automatically casts
|
||||
/// between std::chrono::duration and boost::posix_time::time_duration.
|
||||
class time_duration {
|
||||
public:
|
||||
|
||||
static inline time_duration seconds(size_t timeout) {
|
||||
return std::chrono::seconds(timeout);
|
||||
}
|
||||
|
||||
static inline time_duration milliseconds(size_t timeout) {
|
||||
return std::chrono::milliseconds(timeout);
|
||||
}
|
||||
|
||||
constexpr time_duration() noexcept : _milliseconds(0u) {}
|
||||
|
||||
template <typename Rep, typename Period>
|
||||
time_duration(std::chrono::duration<Rep, Period> duration)
|
||||
: _milliseconds(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count()) {}
|
||||
|
||||
time_duration(boost::posix_time::time_duration timeout)
|
||||
: time_duration(std::chrono::milliseconds(timeout.total_milliseconds())) {}
|
||||
|
||||
time_duration(const time_duration &) = default;
|
||||
time_duration &operator=(const time_duration &) = default;
|
||||
|
||||
boost::posix_time::time_duration to_posix_time() const {
|
||||
return boost::posix_time::milliseconds(_milliseconds);
|
||||
}
|
||||
|
||||
constexpr auto to_chrono() const {
|
||||
return std::chrono::milliseconds(_milliseconds);
|
||||
}
|
||||
|
||||
operator boost::posix_time::time_duration() const {
|
||||
return to_posix_time();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
size_t _milliseconds;
|
||||
};
|
||||
|
||||
} // namespace carla
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace carla {
|
||||
|
||||
constexpr const char *version() {
|
||||
return "${CARLA_VERSION}";
|
||||
}
|
||||
|
||||
} // namespace carla
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/client/Actor.h"
|
||||
#include "carla/client/Client.h"
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
Location Actor::GetLocation() {
|
||||
return GetWorld()->GetClient().GetActorLocation(*this);
|
||||
}
|
||||
|
||||
Transform Actor::GetTransform() {
|
||||
return GetWorld()->GetClient().GetActorTransform(*this);
|
||||
}
|
||||
|
||||
bool Actor::SetLocation(const Location &location) {
|
||||
return GetWorld()->GetClient().SetActorLocation(*this, location);
|
||||
}
|
||||
|
||||
bool Actor::SetTransform(const Transform &transform) {
|
||||
return GetWorld()->GetClient().SetActorTransform(*this, transform);
|
||||
}
|
||||
|
||||
void Actor::Destroy() {
|
||||
GetWorld()->GetClient().DestroyActor(*this);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/Debug.h"
|
||||
#include "carla/NonCopyable.h"
|
||||
#include "carla/client/Memory.h"
|
||||
#include "carla/client/World.h"
|
||||
#include "carla/rpc/Actor.h"
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
class Client;
|
||||
|
||||
class Actor
|
||||
: public EnableSharedFromThis<Actor>,
|
||||
private NonCopyable {
|
||||
public:
|
||||
|
||||
virtual ~Actor() = default;
|
||||
|
||||
Actor(Actor &&) = default;
|
||||
Actor &operator=(Actor &&) = default;
|
||||
|
||||
auto GetId() const {
|
||||
return _actor.id;
|
||||
}
|
||||
|
||||
const std::string &GetTypeId() const {
|
||||
return _actor.description.id;
|
||||
}
|
||||
|
||||
SharedPtr<World> GetWorld() const {
|
||||
return _world;
|
||||
}
|
||||
|
||||
Location GetLocation();
|
||||
|
||||
Transform GetTransform();
|
||||
|
||||
bool SetLocation(const Location &location);
|
||||
|
||||
bool SetTransform(const Transform &transform);
|
||||
|
||||
const auto &Serialize() const {
|
||||
return _actor;
|
||||
}
|
||||
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
|
||||
Actor(carla::rpc::Actor actor, SharedPtr<World> world)
|
||||
: _actor(actor),
|
||||
_world(std::move(world)) {
|
||||
DEBUG_ASSERT(_world != nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class Client;
|
||||
|
||||
carla::rpc::Actor _actor;
|
||||
|
||||
SharedPtr<World> _world;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,105 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/client/ActorAttribute.h"
|
||||
|
||||
#include "carla/Logging.h"
|
||||
#include "carla/StringUtil.h"
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
#define LIBCARLA_THROW_INVALID_VALUE(message) throw InvalidAttributeValue(_attribute.id + ": " + message);
|
||||
#define LIBCARLA_THROW_BAD_VALUE_CAST(type) \
|
||||
if (GetType() != rpc::ActorAttributeType:: type) { \
|
||||
throw BadAttributeCast(_attribute.id + ": bad attribute cast: cannot convert to " #type); \
|
||||
}
|
||||
|
||||
void ActorAttribute::Set(std::string value) {
|
||||
if (!_attribute.is_modifiable) {
|
||||
LIBCARLA_THROW_INVALID_VALUE("read-only attribute");
|
||||
}
|
||||
if (GetType() == rpc::ActorAttributeType::Bool) {
|
||||
StringUtil::ToLower(value);
|
||||
}
|
||||
_attribute.value = std::move(value);
|
||||
Validate();
|
||||
}
|
||||
|
||||
template <>
|
||||
bool ActorAttribute::As<bool>() const {
|
||||
LIBCARLA_THROW_BAD_VALUE_CAST(Bool);
|
||||
auto value = StringUtil::ToLowerCopy(_attribute.value);
|
||||
if (value == "true") {
|
||||
return true;
|
||||
} else if (value == "false") {
|
||||
return false;
|
||||
}
|
||||
LIBCARLA_THROW_INVALID_VALUE("invalid bool: " + _attribute.value);
|
||||
}
|
||||
|
||||
template<>
|
||||
int ActorAttribute::As<int>() const {
|
||||
LIBCARLA_THROW_BAD_VALUE_CAST(Int);
|
||||
return std::atoi(_attribute.value.c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
float ActorAttribute::As<float>() const {
|
||||
LIBCARLA_THROW_BAD_VALUE_CAST(Float);
|
||||
double x = std::atof(_attribute.value.c_str());
|
||||
if ((x > std::numeric_limits<float>::max()) ||
|
||||
(x < std::numeric_limits<float>::lowest())) {
|
||||
LIBCARLA_THROW_INVALID_VALUE("float overflow");
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string ActorAttribute::As<std::string>() const {
|
||||
LIBCARLA_THROW_BAD_VALUE_CAST(String);
|
||||
return _attribute.value;
|
||||
}
|
||||
|
||||
template <>
|
||||
Color ActorAttribute::As<Color>() const {
|
||||
LIBCARLA_THROW_BAD_VALUE_CAST(RGBColor);
|
||||
|
||||
std::vector<std::string> channels;
|
||||
StringUtil::Split(channels, _attribute.value, ",");
|
||||
if (channels.size() != 3u) {
|
||||
log_error("invalid color", _attribute.value);
|
||||
LIBCARLA_THROW_INVALID_VALUE("colors must have 3 channels (R,G,B)");
|
||||
}
|
||||
|
||||
auto to_int = [this](const std::string &str) {
|
||||
int i = std::atoi(str.c_str());
|
||||
if (i > std::numeric_limits<uint8_t>::max()) {
|
||||
LIBCARLA_THROW_INVALID_VALUE("integer overflow in color channel");
|
||||
}
|
||||
return static_cast<uint8_t>(i);
|
||||
};
|
||||
|
||||
return {to_int(channels[0u]), to_int(channels[1u]), to_int(channels[2u])};
|
||||
}
|
||||
|
||||
void ActorAttribute::Validate() const {
|
||||
switch (_attribute.type) {
|
||||
case rpc::ActorAttributeType::Bool: As<rpc::ActorAttributeType::Bool>(); break;
|
||||
case rpc::ActorAttributeType::Int: As<rpc::ActorAttributeType::Int>(); break;
|
||||
case rpc::ActorAttributeType::Float: As<rpc::ActorAttributeType::Float>(); break;
|
||||
case rpc::ActorAttributeType::String: As<rpc::ActorAttributeType::String>(); break;
|
||||
case rpc::ActorAttributeType::RGBColor: As<rpc::ActorAttributeType::RGBColor>(); break;
|
||||
default:
|
||||
LIBCARLA_THROW_INVALID_VALUE("invalid value type");
|
||||
}
|
||||
}
|
||||
|
||||
#undef LIBCARLA_THROW_BAD_VALUE_CAST
|
||||
#undef LIBCARLA_THROW_INVALID_VALUE
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,160 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/client/Color.h"
|
||||
#include "carla/rpc/ActorAttribute.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <type_traits>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
// ===========================================================================
|
||||
// -- InvalidAttributeValue --------------------------------------------------
|
||||
// ===========================================================================
|
||||
|
||||
/// Exception thrown when the value given to an ActorAttribute cannot be
|
||||
/// converted to its type.
|
||||
class InvalidAttributeValue : public std::invalid_argument {
|
||||
public:
|
||||
|
||||
InvalidAttributeValue(const std::string &what) : std::invalid_argument(what) {}
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
// -- BadAttributeCast -------------------------------------------------------
|
||||
// ===========================================================================
|
||||
|
||||
/// Exception thrown when the value of an ActorAttribute cannot be cast to the
|
||||
/// requested type.
|
||||
class BadAttributeCast : public std::logic_error {
|
||||
public:
|
||||
|
||||
BadAttributeCast(const std::string &what) : std::logic_error(what) {}
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
// -- ActorAttribute ---------------------------------------------------------
|
||||
// ===========================================================================
|
||||
|
||||
/// An attribute of an ActorBlueprint.
|
||||
class ActorAttribute {
|
||||
public:
|
||||
|
||||
ActorAttribute(rpc::ActorAttribute attribute)
|
||||
: _attribute(std::move(attribute)) {
|
||||
Validate();
|
||||
}
|
||||
|
||||
/// Set the value of this attribute.
|
||||
///
|
||||
/// @throw InvalidAttributeValue if attribute is not modifiable.
|
||||
/// @throw InvalidAttributeValue if format does not match this type.
|
||||
void Set(std::string value);
|
||||
|
||||
bool IsModifiable() const {
|
||||
return _attribute.is_modifiable;
|
||||
}
|
||||
|
||||
rpc::ActorAttributeType GetType() const {
|
||||
return _attribute.type;
|
||||
}
|
||||
|
||||
const std::vector<std::string> &GetRecommendedValues() const {
|
||||
return _attribute.recommended_values;
|
||||
}
|
||||
|
||||
/// Cast the value to the given type.
|
||||
///
|
||||
/// @throw BadAttributeCast if the cast fails.
|
||||
template <typename T>
|
||||
T As() const;
|
||||
|
||||
/// Cast the value to the type specified by the enum
|
||||
/// carla::rpc::ActorAttributeType.
|
||||
///
|
||||
/// @throw BadAttributeCast if the cast fails.
|
||||
template <rpc::ActorAttributeType Type>
|
||||
auto As() const;
|
||||
|
||||
template <typename T>
|
||||
bool operator==(const T &rhs) const;
|
||||
|
||||
template <typename T>
|
||||
bool operator!=(const T &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
/// Serialize this object as a carla::rpc::ActorAttributeValue.
|
||||
operator rpc::ActorAttributeValue() const {
|
||||
return _attribute;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void Validate() const;
|
||||
|
||||
rpc::ActorAttribute _attribute;
|
||||
};
|
||||
|
||||
template <>
|
||||
bool ActorAttribute::As<bool>() const;
|
||||
|
||||
template <>
|
||||
int ActorAttribute::As<int>() const;
|
||||
|
||||
template <>
|
||||
float ActorAttribute::As<float>() const;
|
||||
|
||||
template <>
|
||||
std::string ActorAttribute::As<std::string>() const;
|
||||
|
||||
template <>
|
||||
Color ActorAttribute::As<Color>() const;
|
||||
|
||||
template <>
|
||||
inline auto ActorAttribute::As<rpc::ActorAttributeType::Bool>() const {
|
||||
return As<bool>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline auto ActorAttribute::As<rpc::ActorAttributeType::Int>() const {
|
||||
return As<int>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline auto ActorAttribute::As<rpc::ActorAttributeType::Float>() const {
|
||||
return As<float>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline auto ActorAttribute::As<rpc::ActorAttributeType::String>() const {
|
||||
return As<std::string>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline auto ActorAttribute::As<rpc::ActorAttributeType::RGBColor>() const {
|
||||
return As<Color>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool ActorAttribute::operator==(const T &rhs) const {
|
||||
return As<T>() == rhs;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool ActorAttribute::operator==(const ActorAttribute &rhs) const {
|
||||
return
|
||||
(_attribute.type == rhs._attribute.type) &&
|
||||
(_attribute.value == rhs._attribute.value);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/client/ActorBlueprint.h"
|
||||
|
||||
#include "carla/StringUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
template <typename Map, typename Container>
|
||||
static void FillMap(Map &destination, Container &source) {
|
||||
destination.reserve(source.size());
|
||||
for (auto &item : source) {
|
||||
auto id = item.id;
|
||||
destination.emplace(id, std::move(item));
|
||||
}
|
||||
}
|
||||
|
||||
ActorBlueprint::ActorBlueprint(rpc::ActorDefinition definition)
|
||||
: _uid(definition.uid),
|
||||
_id(std::move(definition.id)) {
|
||||
StringUtil::Split(_tags, definition.tags, ",");
|
||||
FillMap(_attributes, definition.attributes);
|
||||
}
|
||||
|
||||
bool ActorBlueprint::MatchTags(const std::string &wildcard_pattern) const {
|
||||
return std::any_of(_tags.begin(), _tags.end(), [&](const auto &tag) {
|
||||
return StringUtil::Match(tag, wildcard_pattern);
|
||||
});
|
||||
}
|
||||
|
||||
rpc::ActorDescription ActorBlueprint::MakeActorDescription() const {
|
||||
rpc::ActorDescription description;
|
||||
description.uid = _uid;
|
||||
description.id = _id;
|
||||
description.attributes.reserve(_attributes.size());
|
||||
for (const auto &attribute : *this) {
|
||||
if (attribute.IsModifiable()) {
|
||||
description.attributes.push_back(attribute);
|
||||
}
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,124 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/Debug.h"
|
||||
#include "carla/Iterator.h"
|
||||
#include "carla/client/ActorAttribute.h"
|
||||
#include "carla/rpc/ActorDefinition.h"
|
||||
#include "carla/rpc/ActorDescription.h"
|
||||
|
||||
#include <exception>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
/// Contains all the necessary information for spawning an Actor.
|
||||
class ActorBlueprint {
|
||||
public:
|
||||
|
||||
// =========================================================================
|
||||
/// @name Constructor
|
||||
// =========================================================================
|
||||
/// @{
|
||||
|
||||
explicit ActorBlueprint(rpc::ActorDefinition actor_definition);
|
||||
|
||||
/// @}
|
||||
// =========================================================================
|
||||
/// @name Id
|
||||
// =========================================================================
|
||||
/// @{
|
||||
|
||||
public:
|
||||
|
||||
const std::string &GetId() const {
|
||||
return _id;
|
||||
}
|
||||
|
||||
/// @}
|
||||
// =========================================================================
|
||||
/// @name Tags
|
||||
// =========================================================================
|
||||
/// @{
|
||||
|
||||
public:
|
||||
|
||||
bool ContainsTag(const std::string &tag) const {
|
||||
return _tags.find(tag) != _tags.end();
|
||||
}
|
||||
|
||||
/// Test if any of the flags matches @a wildcard_pattern.
|
||||
///
|
||||
/// @a wildcard_pattern follows Unix shell-style wildcards.
|
||||
bool MatchTags(const std::string &wildcard_pattern) const;
|
||||
|
||||
std::vector<std::string> GetTags() const {
|
||||
return {_tags.begin(), _tags.end()};
|
||||
}
|
||||
|
||||
/// @}
|
||||
// =========================================================================
|
||||
/// @name Attributes
|
||||
// =========================================================================
|
||||
/// @{
|
||||
|
||||
public:
|
||||
|
||||
bool ContainsAttribute(const std::string &id) const {
|
||||
return _attributes.find(id) != _attributes.end();
|
||||
}
|
||||
|
||||
/// @throw std::out_of_range if no such element exists.
|
||||
const ActorAttribute &GetAttribute(const std::string &id) const {
|
||||
return _attributes.at(id);
|
||||
}
|
||||
|
||||
/// Set the value of the attribute given by @a id.
|
||||
///
|
||||
/// @throw std::out_of_range if no such element exists.
|
||||
/// @throw InvalidAttributeValue if attribute is not modifiable.
|
||||
/// @throw InvalidAttributeValue if format does not match the attribute type.
|
||||
void SetAttribute(const std::string &id, std::string value) {
|
||||
_attributes.at(id).Set(std::move(value));
|
||||
}
|
||||
|
||||
auto begin() const {
|
||||
return iterator::make_map_values_iterator(_attributes.begin());
|
||||
}
|
||||
|
||||
auto end() const {
|
||||
return iterator::make_map_values_iterator(_attributes.end());
|
||||
}
|
||||
|
||||
/// @}
|
||||
// =========================================================================
|
||||
/// @name ActorDescription
|
||||
// =========================================================================
|
||||
/// @{
|
||||
|
||||
public:
|
||||
|
||||
rpc::ActorDescription MakeActorDescription() const;
|
||||
|
||||
/// @}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t _uid = 0u;
|
||||
|
||||
std::string _id;
|
||||
|
||||
std::unordered_set<std::string> _tags;
|
||||
|
||||
std::unordered_map<std::string, ActorAttribute> _attributes;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/client/BlueprintLibrary.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
BlueprintLibrary::BlueprintLibrary(
|
||||
const std::vector<rpc::ActorDefinition> &blueprints) {
|
||||
_blueprints.reserve(blueprints.size());
|
||||
for (auto &definition : blueprints) {
|
||||
_blueprints.emplace(definition.id, definition);
|
||||
}
|
||||
}
|
||||
|
||||
SharedPtr<BlueprintLibrary> BlueprintLibrary::Filter(
|
||||
const std::string &wildcard_pattern) const {
|
||||
map_type result;
|
||||
for (auto &pair : _blueprints) {
|
||||
if (pair.second.MatchTags(wildcard_pattern)) {
|
||||
result.emplace(pair);
|
||||
}
|
||||
}
|
||||
return SharedPtr<BlueprintLibrary>{new BlueprintLibrary(result)};
|
||||
}
|
||||
|
||||
BlueprintLibrary::const_reference BlueprintLibrary::at(size_type pos) const {
|
||||
if (pos >= size())
|
||||
throw std::out_of_range("index out of range");
|
||||
return operator[](pos);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/Debug.h"
|
||||
#include "carla/Iterator.h"
|
||||
#include "carla/NonCopyable.h"
|
||||
#include "carla/client/ActorBlueprint.h"
|
||||
#include "carla/client/Memory.h"
|
||||
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
/// @todo Works as a list but its actually a map. We should assess the use
|
||||
/// cases and reconsider this implementation.
|
||||
class BlueprintLibrary
|
||||
: public EnableSharedFromThis<BlueprintLibrary>,
|
||||
private NonCopyable {
|
||||
using map_type = std::unordered_map<std::string, ActorBlueprint>;
|
||||
public:
|
||||
|
||||
// Here we force a bit the typedefs to make this class look like a list.
|
||||
using key_type = map_type::key_type;
|
||||
using value_type = map_type::mapped_type;
|
||||
using size_type = map_type::size_type;
|
||||
using const_iterator = decltype(carla::iterator::make_map_values_iterator<map_type::const_iterator>(map_type::const_iterator{}));
|
||||
using const_reference = const value_type &;
|
||||
using const_pointer = const value_type *;
|
||||
|
||||
explicit BlueprintLibrary(const std::vector<rpc::ActorDefinition> &blueprints);
|
||||
|
||||
BlueprintLibrary(BlueprintLibrary &&) = default;
|
||||
BlueprintLibrary &operator=(BlueprintLibrary &&) = default;
|
||||
|
||||
/// Filters a list of ActorBlueprint with tags matching @a wildcard_pattern.
|
||||
SharedPtr<BlueprintLibrary> Filter(const std::string &wildcard_pattern) const;
|
||||
|
||||
const_pointer Find(const std::string &key) const {
|
||||
auto it = _blueprints.find(key);
|
||||
return it != _blueprints.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
const_reference at(const std::string &key) const {
|
||||
return _blueprints.at(key);
|
||||
}
|
||||
|
||||
/// @warning Linear complexity.
|
||||
const_reference operator[](size_type pos) const {
|
||||
return std::next(_blueprints.begin(), pos)->second;
|
||||
}
|
||||
|
||||
/// @warning Linear complexity.
|
||||
const_reference at(size_type pos) const;
|
||||
|
||||
const_iterator begin() const /*noexcept*/ {
|
||||
return iterator::make_map_values_iterator(_blueprints.begin());
|
||||
}
|
||||
|
||||
const_iterator end() const /*noexcept*/ {
|
||||
return iterator::make_map_values_iterator(_blueprints.end());
|
||||
}
|
||||
|
||||
bool empty() const /*noexcept*/ {
|
||||
return _blueprints.empty();
|
||||
}
|
||||
|
||||
size_type size() const /*noexcept*/ {
|
||||
return _blueprints.size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
BlueprintLibrary(map_type blueprints)
|
||||
: _blueprints(std::move(blueprints)) {}
|
||||
|
||||
map_type _blueprints;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,90 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/client/Client.h"
|
||||
|
||||
#include "carla/client/Actor.h"
|
||||
#include "carla/client/BlueprintLibrary.h"
|
||||
#include "carla/client/Control.h"
|
||||
#include "carla/client/Sensor.h"
|
||||
#include "carla/client/Vehicle.h"
|
||||
#include "carla/client/World.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
Client::Client(const std::string &host, uint16_t port, size_t worker_threads)
|
||||
: _client(host, port) {
|
||||
_streaming_client.AsyncRun(
|
||||
worker_threads > 0u ? worker_threads : std::thread::hardware_concurrency());
|
||||
}
|
||||
|
||||
SharedPtr<World> Client::GetWorld() {
|
||||
if (_active_world == nullptr) {
|
||||
_active_world.reset(new World(shared_from_this()));
|
||||
}
|
||||
return _active_world;
|
||||
}
|
||||
|
||||
SharedPtr<BlueprintLibrary> Client::GetBlueprintLibrary() {
|
||||
return MakeShared<BlueprintLibrary>(
|
||||
Call<std::vector<carla::rpc::ActorDefinition>>("get_actor_definitions"));
|
||||
}
|
||||
|
||||
SharedPtr<Actor> Client::GetSpectator() {
|
||||
auto spectator = Call<carla::rpc::Actor>("get_spectator");
|
||||
return SharedPtr<Actor>(new Actor{spectator, GetWorld()});
|
||||
}
|
||||
|
||||
SharedPtr<Actor> Client::SpawnActor(
|
||||
const ActorBlueprint &blueprint,
|
||||
const Transform &transform,
|
||||
Actor *parent) {
|
||||
auto actor = parent != nullptr ?
|
||||
Call<carla::rpc::Actor>("spawn_actor_with_parent", transform, blueprint.MakeActorDescription(), parent->Serialize()) :
|
||||
Call<carla::rpc::Actor>("spawn_actor", transform, blueprint.MakeActorDescription());
|
||||
if (actor.IsASensor()) {
|
||||
return SharedPtr<Actor>(new Sensor{actor, GetWorld()});
|
||||
}
|
||||
return SharedPtr<Actor>(new Vehicle{actor, GetWorld()});
|
||||
}
|
||||
|
||||
void Client::DestroyActor(Actor &actor) {
|
||||
_client.call("destroy_actor", actor.Serialize());
|
||||
}
|
||||
|
||||
Location Client::GetActorLocation(Actor &actor) {
|
||||
return Call<Location>("get_actor_location", actor.Serialize());
|
||||
}
|
||||
|
||||
Transform Client::GetActorTransform(Actor &actor) {
|
||||
return Call<Transform>("get_actor_transform", actor.Serialize());
|
||||
}
|
||||
|
||||
bool Client::SetActorLocation(Actor &actor, const Location &location) {
|
||||
return Call<bool>("set_actor_location", actor.Serialize(), location);
|
||||
}
|
||||
|
||||
bool Client::SetActorTransform(Actor &actor, const Transform &transform) {
|
||||
return Call<bool>("set_actor_transform", actor.Serialize(), transform);
|
||||
}
|
||||
|
||||
void Client::ApplyControlToActor(
|
||||
Actor &actor,
|
||||
const VehicleControl &control) {
|
||||
_client.call("apply_control_to_actor", actor.Serialize(), control);
|
||||
}
|
||||
|
||||
void Client::SetActorAutopilot(
|
||||
Actor &actor,
|
||||
const bool enabled) {
|
||||
_client.call("set_actor_autopilot", actor.Serialize(), enabled);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,108 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/NonCopyable.h"
|
||||
#include "carla/Version.h"
|
||||
#include "carla/client/Control.h"
|
||||
#include "carla/client/Memory.h"
|
||||
#include "carla/client/Transform.h"
|
||||
#include "carla/rpc/Client.h"
|
||||
#include "carla/streaming/Client.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
class Actor;
|
||||
class ActorBlueprint;
|
||||
class BlueprintLibrary;
|
||||
class World;
|
||||
|
||||
class Client
|
||||
: public EnableSharedFromThis<Client>,
|
||||
private NonCopyable {
|
||||
public:
|
||||
|
||||
/// Construct a carla client.
|
||||
///
|
||||
/// @param host IP address of the host machine running the simulator.
|
||||
/// @param port TCP port to connect with the simulator.
|
||||
/// @param worker_threads number of asynchronous threads to use, or 0 to use
|
||||
/// all available hardware concurrency.
|
||||
explicit Client(
|
||||
const std::string &host,
|
||||
uint16_t port,
|
||||
size_t worker_threads = 0u);
|
||||
|
||||
void SetTimeout(int64_t milliseconds) {
|
||||
_client.set_timeout(milliseconds);
|
||||
}
|
||||
|
||||
template <typename T, typename ... Args>
|
||||
T Call(const std::string &function, Args && ... args) {
|
||||
return _client.call(function, std::forward<Args>(args) ...).template as<T>();
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
void SubscribeToStream(const streaming::Token &token, Functor &&callback) {
|
||||
_streaming_client.Subscribe(token, std::forward<Functor>(callback));
|
||||
}
|
||||
|
||||
std::string GetClientVersion() const {
|
||||
return ::carla::version();
|
||||
}
|
||||
|
||||
std::string GetServerVersion() {
|
||||
return Call<std::string>("version");
|
||||
}
|
||||
|
||||
bool Ping() {
|
||||
return Call<bool>("ping");
|
||||
}
|
||||
|
||||
SharedPtr<World> GetWorld();
|
||||
|
||||
SharedPtr<BlueprintLibrary> GetBlueprintLibrary();
|
||||
|
||||
SharedPtr<Actor> GetSpectator();
|
||||
|
||||
SharedPtr<Actor> SpawnActor(
|
||||
const ActorBlueprint &blueprint,
|
||||
const Transform &transform,
|
||||
Actor *parent = nullptr);
|
||||
|
||||
void DestroyActor(Actor &actor);
|
||||
|
||||
Location GetActorLocation(Actor &actor);
|
||||
|
||||
Transform GetActorTransform(Actor &actor);
|
||||
|
||||
bool SetActorLocation(Actor &actor, const Location &location);
|
||||
|
||||
bool SetActorTransform(Actor &actor, const Transform &transform);
|
||||
|
||||
void ApplyControlToActor(
|
||||
Actor &actor,
|
||||
const VehicleControl &control);
|
||||
|
||||
void SetActorAutopilot(
|
||||
Actor &actor,
|
||||
bool enabled = true);
|
||||
|
||||
private:
|
||||
|
||||
carla::rpc::Client _client;
|
||||
|
||||
carla::streaming::Client _streaming_client;
|
||||
|
||||
SharedPtr<World> _active_world;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
struct Color {
|
||||
Color() = default;
|
||||
Color(uint8_t r, uint8_t g, uint8_t b) : r(r), g(g), b(b) {}
|
||||
|
||||
bool operator==(const Color &rhs) const {
|
||||
return (r == rhs.r) && (g == rhs.g) && (b == rhs.b);
|
||||
}
|
||||
|
||||
bool operator!=(const Color &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
uint8_t r = 0u;
|
||||
uint8_t g = 0u;
|
||||
uint8_t b = 0u;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/rpc/VehicleControl.h"
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
using VehicleControl = carla::rpc::VehicleControl;
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/Debug.h"
|
||||
#include "carla/client/Image.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
/// @todo This object should be shared and packed.
|
||||
struct FImageHeaderData
|
||||
{
|
||||
uint64_t FrameNumber;
|
||||
uint32_t Width;
|
||||
uint32_t Height;
|
||||
uint32_t Type;
|
||||
float FOV;
|
||||
};
|
||||
|
||||
static std::string GetTypeString(uint32_t type) {
|
||||
switch (type) {
|
||||
case 0u: return "None";
|
||||
case 1u: return "SceneFinal";
|
||||
case 2u: return "Depth";
|
||||
case 3u: return "SemanticSegmentation";
|
||||
default: return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
SharedPtr<Image> Image::FromBuffer(boost::asio::const_buffer buffer) {
|
||||
if (buffer.size() < sizeof(FImageHeaderData)) {
|
||||
throw std::invalid_argument("buffer too small to be an image");
|
||||
}
|
||||
auto begin = reinterpret_cast<const byte_type *>(buffer.data());
|
||||
auto image = MakeShared<Image>();
|
||||
FImageHeaderData data;
|
||||
std::memcpy(&data, begin, sizeof(data));
|
||||
image->_frame_number = data.FrameNumber;
|
||||
image->_width = data.Width;
|
||||
image->_height = data.Height;
|
||||
image->_type = GetTypeString(data.Type);
|
||||
image->_fov = data.FOV;
|
||||
const auto size = image->GetSize();
|
||||
DEBUG_ASSERT((size + sizeof(FImageHeaderData)) == buffer.size());
|
||||
auto raw_data = std::make_unique<byte_type[]>(size);
|
||||
std::memcpy(raw_data.get(), begin + sizeof(FImageHeaderData), size);
|
||||
image->_raw_data = std::move(raw_data);
|
||||
return image;
|
||||
}
|
||||
|
||||
Image::Image() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
Image::Image(Image &&rhs) {
|
||||
(*this) = std::move(rhs);
|
||||
}
|
||||
|
||||
Image &Image::operator=(Image &&rhs) {
|
||||
_width = rhs._width;
|
||||
_height = rhs._height;
|
||||
_type = rhs._type;
|
||||
_fov = rhs._fov;
|
||||
_raw_data = std::move(rhs._raw_data);
|
||||
rhs.Clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Image::Clear() {
|
||||
_frame_number = 0u;
|
||||
_width = 0u;
|
||||
_height = 0u;
|
||||
_type = "Invalid";
|
||||
_fov = 0.0f;
|
||||
_raw_data = nullptr;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,83 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/NonCopyable.h"
|
||||
#include "carla/client/Memory.h"
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
class Image
|
||||
: public EnableSharedFromThis<Image>,
|
||||
private NonCopyable {
|
||||
public:
|
||||
|
||||
using byte_type = unsigned char;
|
||||
|
||||
static SharedPtr<Image> FromBuffer(boost::asio::const_buffer buffer);
|
||||
|
||||
Image();
|
||||
|
||||
Image(Image &&rhs);
|
||||
Image &operator=(Image &&rhs);
|
||||
|
||||
void Clear();
|
||||
|
||||
size_t GetFrameNumber() const {
|
||||
return _frame_number;
|
||||
}
|
||||
|
||||
size_t GetWidth() const {
|
||||
return _width;
|
||||
}
|
||||
|
||||
size_t GetHeight() const {
|
||||
return _height;
|
||||
}
|
||||
|
||||
const std::string &GetType() const {
|
||||
return _type;
|
||||
}
|
||||
|
||||
float GetFOV() const {
|
||||
return _fov;
|
||||
}
|
||||
|
||||
byte_type *GetData() {
|
||||
return _raw_data.get();
|
||||
}
|
||||
|
||||
const byte_type *GetData() const {
|
||||
return _raw_data.get();
|
||||
}
|
||||
|
||||
size_t GetSize() const {
|
||||
return 4u * _width * _height;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
size_t _frame_number;
|
||||
|
||||
size_t _width;
|
||||
|
||||
size_t _height;
|
||||
|
||||
std::string _type;
|
||||
|
||||
float _fov;
|
||||
|
||||
std::unique_ptr<byte_type[]> _raw_data;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
// In this namespace, we use boost::shared_ptr for now to make it compatible
|
||||
// with boost::python, but it would be nice to make an adaptor for
|
||||
// std::shared_ptr.
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
template <typename T>
|
||||
using EnableSharedFromThis = boost::enable_shared_from_this<T>;
|
||||
|
||||
template <typename T>
|
||||
using SharedPtr = boost::shared_ptr<T>;
|
||||
|
||||
template <typename T, typename ... Args>
|
||||
static inline auto MakeShared(Args && ... args) {
|
||||
return boost::make_shared<T>(std::forward<Args>(args) ...);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/Logging.h"
|
||||
#include "carla/client/Actor.h"
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
class Sensor : public Actor {
|
||||
public:
|
||||
|
||||
template <typename Functor>
|
||||
void Listen(Functor callback) {
|
||||
/// @todo should we check if we are already listening?
|
||||
log_debug("sensor", GetId(), "type", GetTypeId(), ": subscribing to stream");
|
||||
GetWorld()->GetClient().SubscribeToStream(_stream_token, std::forward<Functor>(callback));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class Client;
|
||||
|
||||
Sensor(carla::rpc::Actor actor, SharedPtr<World> world)
|
||||
: Actor(actor, std::move(world)),
|
||||
_stream_token(actor.GetStreamToken()) {}
|
||||
|
||||
streaming::Token _stream_token;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/rpc/Transform.h"
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
using Location = carla::rpc::Location;
|
||||
using Rotation = carla::rpc::Rotation;
|
||||
using Transform = carla::rpc::Transform;
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/client/Actor.h"
|
||||
#include "carla/client/Control.h"
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
class Vehicle : public Actor {
|
||||
public:
|
||||
|
||||
void ApplyControl(const VehicleControl &control) {
|
||||
GetWorld()->GetClient().ApplyControlToActor(*this, control);
|
||||
}
|
||||
|
||||
void SetAutopilot(bool enabled = true) {
|
||||
GetWorld()->GetClient().SetActorAutopilot(*this, enabled);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class Client;
|
||||
|
||||
template <typename ... Args>
|
||||
Vehicle(Args && ... args) : Actor(std::forward<Args>(args)...) {}
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/client/World.h"
|
||||
|
||||
#include "carla/Logging.h"
|
||||
|
||||
#include <rpc/rpc_error.h>
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
SharedPtr<Actor> World::TrySpawnActor(
|
||||
const ActorBlueprint &blueprint,
|
||||
const Transform &transform,
|
||||
Actor *parent) {
|
||||
try {
|
||||
return SpawnActor(blueprint, transform, parent);
|
||||
} catch (const ::rpc::rpc_error &e) {
|
||||
log_warning("TrySpawnActor: failed with:", e.what());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/Debug.h"
|
||||
#include "carla/NonCopyable.h"
|
||||
#include "carla/client/Client.h"
|
||||
#include "carla/client/Memory.h"
|
||||
|
||||
namespace carla {
|
||||
namespace client {
|
||||
|
||||
class Actor;
|
||||
|
||||
class World
|
||||
: public EnableSharedFromThis<World>,
|
||||
private NonCopyable {
|
||||
public:
|
||||
|
||||
SharedPtr<BlueprintLibrary> GetBlueprintLibrary() const {
|
||||
return _parent->GetBlueprintLibrary();
|
||||
}
|
||||
|
||||
SharedPtr<Actor> GetSpectator() const {
|
||||
return _parent->GetSpectator();
|
||||
}
|
||||
|
||||
SharedPtr<Actor> TrySpawnActor(
|
||||
const ActorBlueprint &blueprint,
|
||||
const Transform &transform,
|
||||
Actor *parent = nullptr);
|
||||
|
||||
SharedPtr<Actor> SpawnActor(
|
||||
const ActorBlueprint &blueprint,
|
||||
const Transform &transform,
|
||||
Actor *parent = nullptr) {
|
||||
return _parent->SpawnActor(blueprint, transform, parent);
|
||||
}
|
||||
|
||||
Client &GetClient() const {
|
||||
DEBUG_ASSERT(_parent != nullptr);
|
||||
return *_parent;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class Client;
|
||||
|
||||
explicit World(SharedPtr<Client> parent)
|
||||
: _parent(std::move(parent)) {
|
||||
DEBUG_ASSERT(_parent != nullptr);
|
||||
}
|
||||
|
||||
SharedPtr<Client> _parent;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace carla
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#ifndef LIBCARLA_ENABLE_PROFILER
|
||||
# define LIBCARLA_ENABLE_PROFILER
|
||||
#endif // LIBCARLA_ENABLE_PROFILER
|
||||
|
||||
#include "carla/Logging.h"
|
||||
#include "carla/Version.h"
|
||||
#include "carla/profiler/Profiler.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
|
||||
namespace carla {
|
||||
namespace profiler {
|
||||
namespace detail {
|
||||
|
||||
template <typename Arg, typename ... Args>
|
||||
static void write_csv_to_stream(std::ostream &out, Arg &&arg, Args &&... args) {
|
||||
out << std::boolalpha
|
||||
<< std::left << std::setw(44)
|
||||
<< std::forward<Arg>(arg)
|
||||
<< std::right
|
||||
<< std::fixed << std::setprecision(2);
|
||||
using expander = int[];
|
||||
(void)expander{0, (void(out << ", " << std::setw(10) << std::forward<Args>(args)),0)...};
|
||||
}
|
||||
|
||||
class StaticProfiler {
|
||||
public:
|
||||
|
||||
StaticProfiler(std::string filename)
|
||||
: _filename(std::move(filename)) {
|
||||
logging::log("PROFILER: writing profiling data to", _filename);
|
||||
std::string header = "# LibCarla Profiler ";
|
||||
header += carla::version();
|
||||
#ifdef NDEBUG
|
||||
header += " (release)";
|
||||
#else
|
||||
header += " (debug)";
|
||||
#endif // NDEBUG
|
||||
write_to_file(std::ios_base::out, header);
|
||||
write_line("# context", "average", "maximum", "minimum", "units", "times");
|
||||
}
|
||||
|
||||
template <typename ... Args>
|
||||
void write_line(Args &&... args) {
|
||||
write_to_file(std::ios_base::app|std::ios_base::out, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <typename ... Args>
|
||||
void write_to_file(std::ios_base::openmode mode, Args &&... args) {
|
||||
if (!_filename.empty()) {
|
||||
static std::mutex MUTEX;
|
||||
std::lock_guard<std::mutex> guard(MUTEX);
|
||||
std::ofstream file(_filename, mode);
|
||||
write_csv_to_stream(file, std::forward<Args>(args)...);
|
||||
file << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string _filename;
|
||||
};
|
||||
|
||||
ProfilerData::~ProfilerData() {
|
||||
static StaticProfiler PROFILER{"profiler.csv"};
|
||||
if (_count > 0u) {
|
||||
if (_print_fps) {
|
||||
PROFILER.write_line(_name, fps(average()), fps(minimum()), fps(maximum()), "FPS", _count);
|
||||
} else {
|
||||
PROFILER.write_line(_name, average(), maximum(), minimum(), "ms", _count);
|
||||
}
|
||||
} else {
|
||||
log_error("profiler", _name, " was never run!");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace profiler
|
||||
} // namespace carla
|
|
@ -0,0 +1,124 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef LIBCARLA_ENABLE_PROFILER
|
||||
# define CARLA_PROFILE_SCOPE(context, profiler_name)
|
||||
# define CARLA_PROFILE_FPS(context, profiler_name)
|
||||
#else
|
||||
|
||||
#include "carla/StopWatch.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
namespace carla {
|
||||
namespace profiler {
|
||||
namespace detail {
|
||||
|
||||
class ProfilerData {
|
||||
public:
|
||||
|
||||
explicit ProfilerData(std::string name, bool print_fps = false)
|
||||
: _name(std::move(name)),
|
||||
_print_fps(print_fps) {}
|
||||
|
||||
~ProfilerData();
|
||||
|
||||
void Annotate(const StopWatch &stop_watch) {
|
||||
const size_t elapsed_microseconds =
|
||||
stop_watch.GetElapsedTime<std::chrono::microseconds>();
|
||||
++_count;
|
||||
_total_microseconds += elapsed_microseconds;
|
||||
_max_elapsed = std::max(elapsed_microseconds, _max_elapsed);
|
||||
_min_elapsed = std::min(elapsed_microseconds, _min_elapsed);
|
||||
}
|
||||
|
||||
float average() const {
|
||||
return ms(_total_microseconds) / static_cast<float>(_count);
|
||||
}
|
||||
|
||||
float maximum() const {
|
||||
return ms(_max_elapsed);
|
||||
}
|
||||
|
||||
float minimum() const {
|
||||
return ms(_min_elapsed);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static inline float ms(size_t microseconds) {
|
||||
return 1e-3f * static_cast<float>(microseconds);
|
||||
}
|
||||
|
||||
static inline float fps(float milliseconds) {
|
||||
return 1e3f / milliseconds;
|
||||
}
|
||||
|
||||
const std::string _name;
|
||||
|
||||
const bool _print_fps;
|
||||
|
||||
size_t _count = 0u;
|
||||
|
||||
size_t _total_microseconds = 0u;
|
||||
|
||||
size_t _max_elapsed = 0u;
|
||||
|
||||
size_t _min_elapsed = -1;
|
||||
};
|
||||
|
||||
class ScopedProfiler {
|
||||
public:
|
||||
|
||||
explicit ScopedProfiler(ProfilerData &parent) : _profiler(parent) {}
|
||||
|
||||
~ScopedProfiler() {
|
||||
_stop_watch.Stop();
|
||||
_profiler.Annotate(_stop_watch);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
ProfilerData &_profiler;
|
||||
|
||||
StopWatch _stop_watch;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace profiler
|
||||
} // namespace carla
|
||||
|
||||
#ifdef LIBCARLA_WITH_GTEST
|
||||
# define LIBCARLA_GTEST_GET_TEST_NAME() std::string(::testing::UnitTest::GetInstance()->current_test_info()->name())
|
||||
#else
|
||||
# define LIBCARLA_GTEST_GET_TEST_NAME() std::string("")
|
||||
#endif // LIBCARLA_WITH_GTEST
|
||||
|
||||
#define CARLA_PROFILE_SCOPE(context, profiler_name) \
|
||||
static thread_local ::carla::profiler::detail::ProfilerData carla_profiler_ ## context ## _ ## profiler_name ## _data( \
|
||||
LIBCARLA_GTEST_GET_TEST_NAME() + "." #context "." #profiler_name); \
|
||||
::carla::profiler::detail::ScopedProfiler carla_profiler_ ## context ## _ ## profiler_name ## _scoped_profiler( \
|
||||
carla_profiler_ ## context ## _ ## profiler_name ## _data);
|
||||
|
||||
#define CARLA_PROFILE_FPS(context, profiler_name) \
|
||||
{ \
|
||||
static thread_local ::carla::StopWatch stop_watch; \
|
||||
stop_watch.Stop(); \
|
||||
static thread_local bool first_time = true; \
|
||||
if (!first_time) { \
|
||||
static thread_local ::carla::profiler::detail::ProfilerData profiler_data( \
|
||||
LIBCARLA_GTEST_GET_TEST_NAME() + "." #context "." #profiler_name, true); \
|
||||
profiler_data.Annotate(stop_watch); \
|
||||
} else { \
|
||||
first_time = false; \
|
||||
} \
|
||||
stop_watch.Restart(); \
|
||||
}
|
||||
|
||||
#endif // LIBCARLA_ENABLE_PROFILER
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/Debug.h"
|
||||
#include "carla/rpc/ActorDescription.h"
|
||||
#include "carla/streaming/Token.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
class Actor {
|
||||
public:
|
||||
|
||||
using id_type = uint32_t;
|
||||
|
||||
Actor() = default;
|
||||
|
||||
id_type id;
|
||||
|
||||
ActorDescription description;
|
||||
|
||||
/// @todo This is only used by sensors actually.
|
||||
/// @name Sensor functionality
|
||||
/// @{
|
||||
|
||||
std::vector<unsigned char> stream_token;
|
||||
|
||||
bool IsASensor() const {
|
||||
return stream_token.size() == sizeof(streaming::Token::data);
|
||||
}
|
||||
|
||||
streaming::Token GetStreamToken() const {
|
||||
DEBUG_ASSERT(IsASensor());
|
||||
streaming::Token token;
|
||||
std::memcpy(&token.data[0u], stream_token.data(), stream_token.size());
|
||||
return token;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
Actor(FActorView View)
|
||||
: id(View.GetActorId()),
|
||||
description(*View.GetActorDescription()) {
|
||||
DEBUG_ASSERT(View.IsValid());
|
||||
}
|
||||
|
||||
Actor(FActorView View, const streaming::Token &StreamToken)
|
||||
: id(View.GetActorId()),
|
||||
description(*View.GetActorDescription()),
|
||||
stream_token(StreamToken.data.begin(), StreamToken.data.end()) {
|
||||
DEBUG_ASSERT(View.IsValid());
|
||||
}
|
||||
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(id, description, stream_token);
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -0,0 +1,99 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/rpc/ActorAttributeType.h"
|
||||
#include "carla/rpc/MsgPack.h"
|
||||
#include "carla/rpc/String.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
MSGPACK_ADD_ENUM(carla::rpc::ActorAttributeType);
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
class ActorAttribute {
|
||||
public:
|
||||
|
||||
ActorAttribute() = default;
|
||||
|
||||
std::string id;
|
||||
|
||||
ActorAttributeType type = ActorAttributeType::Int;
|
||||
|
||||
std::string value;
|
||||
|
||||
std::vector<std::string> recommended_values;
|
||||
|
||||
bool is_modifiable = true;
|
||||
|
||||
bool restrict_to_recommended = false;
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
ActorAttribute(const FActorAttribute &Attribute)
|
||||
: id(FromFString(Attribute.Id)),
|
||||
type(static_cast<ActorAttributeType>(Attribute.Type)),
|
||||
value(FromFString(Attribute.Value)),
|
||||
is_modifiable(false) {}
|
||||
|
||||
ActorAttribute(const FActorVariation &Variation)
|
||||
: id(FromFString(Variation.Id)),
|
||||
type(static_cast<ActorAttributeType>(Variation.Type)),
|
||||
is_modifiable(true),
|
||||
restrict_to_recommended(Variation.bRestrictToRecommended) {
|
||||
recommended_values.reserve(Variation.RecommendedValues.Num());
|
||||
for (const auto &Item : Variation.RecommendedValues) {
|
||||
recommended_values.push_back(FromFString(Item));
|
||||
}
|
||||
if (!recommended_values.empty()) {
|
||||
value = recommended_values[0u];
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(id, type, value, recommended_values, is_modifiable, restrict_to_recommended);
|
||||
};
|
||||
|
||||
class ActorAttributeValue {
|
||||
public:
|
||||
|
||||
ActorAttributeValue() = default;
|
||||
|
||||
ActorAttributeValue(const ActorAttribute &attribute)
|
||||
: id(attribute.id),
|
||||
type(attribute.type),
|
||||
value(attribute.value) {}
|
||||
|
||||
std::string id;
|
||||
|
||||
ActorAttributeType type = ActorAttributeType::Int;
|
||||
|
||||
std::string value;
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
ActorAttributeValue(const FActorAttribute &Attribute)
|
||||
: ActorAttributeValue(ActorAttribute(Attribute)) {}
|
||||
|
||||
operator FActorAttribute() const {
|
||||
FActorAttribute Attribute;
|
||||
Attribute.Id = ToFString(id);
|
||||
Attribute.Type = static_cast<EActorAttributeType>(type);
|
||||
Attribute.Value = ToFString(value);
|
||||
return Attribute;
|
||||
}
|
||||
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(id, type, value);
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
enum class ActorAttributeType : uint8_t {
|
||||
Bool,
|
||||
Int,
|
||||
Float,
|
||||
String,
|
||||
RGBColor,
|
||||
|
||||
SIZE,
|
||||
INVALID
|
||||
};
|
||||
|
||||
// Serialization of this class is in ActorAttribute.h, to reduce dependencies
|
||||
// since this file is directly included in UE4 code.
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/rpc/ActorAttribute.h"
|
||||
#include "carla/rpc/MsgPack.h"
|
||||
#include "carla/rpc/String.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
class ActorDefinition {
|
||||
public:
|
||||
|
||||
ActorDefinition() = default;
|
||||
|
||||
uint32_t uid = 0u;
|
||||
|
||||
std::string id;
|
||||
|
||||
std::string tags;
|
||||
|
||||
std::vector<ActorAttribute> attributes;
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
ActorDefinition(const FActorDefinition &Definition)
|
||||
: uid(Definition.UId),
|
||||
id(FromFString(Definition.Id)),
|
||||
tags(FromFString(Definition.Tags)) {
|
||||
attributes.reserve(Definition.Variations.Num() + Definition.Attributes.Num());
|
||||
for (const auto &Item : Definition.Variations) {
|
||||
attributes.push_back(Item);
|
||||
}
|
||||
for (const auto &Item : Definition.Attributes) {
|
||||
attributes.push_back(Item);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(uid, id, tags, attributes);
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/rpc/ActorAttribute.h"
|
||||
#include "carla/rpc/MsgPack.h"
|
||||
#include "carla/rpc/String.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
class ActorDescription {
|
||||
public:
|
||||
|
||||
ActorDescription() = default;
|
||||
|
||||
uint32_t uid = 0u;
|
||||
|
||||
std::string id;
|
||||
|
||||
std::vector<ActorAttributeValue> attributes;
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
ActorDescription(const FActorDescription &Description)
|
||||
: uid(Description.UId),
|
||||
id(FromFString(Description.Id)) {
|
||||
attributes.reserve(Description.Variations.Num());
|
||||
for (const auto &Item : Description.Variations) {
|
||||
attributes.emplace_back(Item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
operator FActorDescription() const {
|
||||
FActorDescription Description;
|
||||
Description.UId = uid;
|
||||
Description.Id = ToFString(id);
|
||||
Description.Variations.Reserve(attributes.size());
|
||||
for (const auto &item : attributes) {
|
||||
Description.Variations.Emplace(ToFString(item.id), item);
|
||||
}
|
||||
return Description;
|
||||
}
|
||||
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(uid, id, attributes);
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rpc/client.h>
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
using Client = ::rpc::client;
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/rpc/MsgPack.h"
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
# include "Math/Vector.h"
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
class Location {
|
||||
public:
|
||||
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
float z = 0.0f;
|
||||
|
||||
Location() = default;
|
||||
|
||||
Location(float ix, float iy, float iz)
|
||||
: x(ix),
|
||||
y(iy),
|
||||
z(iz) {}
|
||||
|
||||
Location &operator+=(const Location &rhs) {
|
||||
x += rhs.x;
|
||||
y += rhs.y;
|
||||
z += rhs.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend Location operator+(Location lhs, const Location &rhs) {
|
||||
lhs += rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
Location &operator-=(const Location &rhs) {
|
||||
x -= rhs.x;
|
||||
y -= rhs.y;
|
||||
z -= rhs.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend Location operator-(Location lhs, const Location &rhs) {
|
||||
lhs -= rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
Location(const FVector &vector) // from centimeters to meters.
|
||||
: Location(1e-2f * vector.X, 1e-2f * vector.Y, 1e-2f * vector.Z) {}
|
||||
|
||||
operator FVector() const {
|
||||
return FVector{1e2f * x, 1e2f * y, 1e2f * z}; // from meters to centimeters.
|
||||
}
|
||||
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
// =========================================================================
|
||||
/// @todo The following is copy-pasted from MSGPACK_DEFINE_ARRAY.
|
||||
/// This is a workaround for an issue in msgpack library. The
|
||||
/// MSGPACK_DEFINE_ARRAY macro is shadowing our `z` variable.
|
||||
/// https://github.com/msgpack/msgpack-c/issues/709
|
||||
// =========================================================================
|
||||
template <typename Packer>
|
||||
void msgpack_pack(Packer& pk) const
|
||||
{
|
||||
clmdep_msgpack::type::make_define_array(x, y, z).msgpack_pack(pk);
|
||||
}
|
||||
void msgpack_unpack(clmdep_msgpack::object const& o)
|
||||
{
|
||||
clmdep_msgpack::type::make_define_array(x, y, z).msgpack_unpack(o);
|
||||
}
|
||||
template <typename MSGPACK_OBJECT>
|
||||
void msgpack_object(MSGPACK_OBJECT* o, clmdep_msgpack::zone& sneaky_variable_that_shadows_z) const
|
||||
{
|
||||
clmdep_msgpack::type::make_define_array(x, y, z).msgpack_object(o, sneaky_variable_that_shadows_z);
|
||||
}
|
||||
// =========================================================================
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rpc/msgpack.hpp>
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/rpc/Server.h"
|
||||
|
||||
#include <rpc/this_handler.h>
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
void Server::RespondError(std::string error_message) {
|
||||
::rpc::this_handler().respond_error(std::move(error_message));
|
||||
}
|
||||
|
||||
} // namespace carla
|
||||
} // namespace rpc
|
|
@ -0,0 +1,121 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/Time.h"
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
#include <rpc/server.h>
|
||||
|
||||
#include <future>
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/// Function traits based on http://rpclib.net implementation.
|
||||
/// MIT Licensed, Copyright (c) 2015-2017, Tamás Szelei
|
||||
template <typename T>
|
||||
struct wrapper_function_traits : wrapper_function_traits<decltype(&T::operator())> {};
|
||||
|
||||
template <typename C, typename R, typename... Args>
|
||||
struct wrapper_function_traits<R (C::*)(Args...)> : wrapper_function_traits<R (*)(Args...)> {};
|
||||
|
||||
template <typename C, typename R, typename... Args>
|
||||
struct wrapper_function_traits<R (C::*)(Args...) const> : wrapper_function_traits<R (*)(Args...)> {};
|
||||
|
||||
template <typename R, typename... Args> struct wrapper_function_traits<R (*)(Args...)> {
|
||||
using result_type = R;
|
||||
using function_type = std::function<R(Args...)>;
|
||||
using packaged_task_type = std::packaged_task<R()>;
|
||||
};
|
||||
|
||||
/// Wraps @a functor into a function type with equivalent signature. The wrap
|
||||
/// function returned, when called, posts @a functor into the io_service and
|
||||
/// waits for it to finish.
|
||||
///
|
||||
/// This way, no matter from which thread the wrap function is called, the
|
||||
/// @a functor provided is always called from the context of the io_service.
|
||||
///
|
||||
/// @warning The wrap function blocks until @a functor is executed by the
|
||||
/// io_service.
|
||||
template <typename F>
|
||||
inline auto WrapSyncCall(boost::asio::io_service &io, F functor) {
|
||||
using func_t = typename wrapper_function_traits<F>::function_type;
|
||||
using task_t = typename wrapper_function_traits<F>::packaged_task_type;
|
||||
|
||||
return func_t([&io, functor=std::move(functor)](auto && ... args) {
|
||||
// We can pass arguments by ref to the lambda because the task will be
|
||||
// executed before this function exits.
|
||||
task_t task([functor=std::move(functor), &args...]() {
|
||||
return functor(std::forward<decltype(args)>(args)...);
|
||||
});
|
||||
auto result = task.get_future();
|
||||
io.post([&]() mutable { task(); });
|
||||
return result.get();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// An RPC server in which functions can be bind to run synchronously or
|
||||
/// asynchronously.
|
||||
///
|
||||
/// Use `AsyncRun` to start the worker threads, and use `SyncRunFor` to
|
||||
/// run a slice of work in the caller's thread.
|
||||
///
|
||||
/// Functions that are bind using `BindAsync` will run asynchronously in the
|
||||
/// worker threads. Functions that are bind using `BindSync` will run within
|
||||
/// `SyncRunFor` function.
|
||||
class Server {
|
||||
public:
|
||||
|
||||
template <typename ... Args>
|
||||
explicit Server(Args && ... args)
|
||||
: _server(std::forward<Args>(args) ...) {
|
||||
_server.suppress_exceptions(true);
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
void BindAsync(const std::string &name, Functor &&functor) {
|
||||
_server.bind(name, std::forward<Functor>(functor));
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
void BindSync(const std::string &name, Functor functor) {
|
||||
_server.bind(
|
||||
name,
|
||||
detail::WrapSyncCall(_sync_io_service, std::move(functor)));
|
||||
}
|
||||
|
||||
void AsyncRun(size_t worker_threads) {
|
||||
_server.async_run(worker_threads);
|
||||
}
|
||||
|
||||
void SyncRunFor(time_duration duration) {
|
||||
_sync_io_service.reset();
|
||||
_sync_io_service.run_for(duration.to_chrono());
|
||||
}
|
||||
|
||||
/// @warning does not stop the game thread.
|
||||
void Stop() {
|
||||
_server.stop();
|
||||
}
|
||||
|
||||
static void RespondError(std::string error_message);
|
||||
|
||||
private:
|
||||
|
||||
boost::asio::io_service _sync_io_service;
|
||||
|
||||
::rpc::server _server;
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
# include "UnrealString.h"
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
static inline std::string FromFString(const FString &Str) {
|
||||
return TCHAR_TO_UTF8(*Str);
|
||||
}
|
||||
|
||||
static inline FString ToFString(const std::string &str) {
|
||||
return FString(str.size(), UTF8_TO_TCHAR(str.c_str()));
|
||||
}
|
||||
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/rpc/Location.h"
|
||||
#include "carla/rpc/MsgPack.h"
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
# include "Transform.h"
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
class Rotation {
|
||||
public:
|
||||
|
||||
Rotation() = default;
|
||||
|
||||
Rotation(float p, float y, float r)
|
||||
: pitch(p),
|
||||
yaw(y),
|
||||
roll(r) {}
|
||||
|
||||
float pitch = 0.0f;
|
||||
float yaw = 0.0f;
|
||||
float roll = 0.0f;
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
Rotation(const FRotator &rotator)
|
||||
: Rotation(rotator.Pitch, rotator.Yaw, rotator.Roll) {}
|
||||
|
||||
operator FRotator() const {
|
||||
return FRotator{pitch, yaw, roll};
|
||||
}
|
||||
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(pitch, yaw, roll);
|
||||
};
|
||||
|
||||
class Transform {
|
||||
public:
|
||||
|
||||
Transform() = default;
|
||||
|
||||
Transform(const Location &in_location, const Rotation &in_rotation)
|
||||
: location(in_location),
|
||||
rotation(in_rotation) {}
|
||||
|
||||
Location location;
|
||||
Rotation rotation;
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
Transform(const FTransform &transform)
|
||||
: Transform(Location(transform.GetLocation()), Rotation(transform.Rotator())) {}
|
||||
|
||||
operator FTransform() const {
|
||||
const FVector scale{1.0f, 1.0f, 1.0f};
|
||||
return FTransform{FRotator(rotation), FVector(location), scale};
|
||||
}
|
||||
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(location, rotation);
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/rpc/MsgPack.h"
|
||||
|
||||
namespace carla {
|
||||
namespace rpc {
|
||||
|
||||
class VehicleControl {
|
||||
public:
|
||||
|
||||
VehicleControl() = default;
|
||||
|
||||
VehicleControl(
|
||||
float in_throttle,
|
||||
float in_steer,
|
||||
float in_brake,
|
||||
bool in_hand_brake,
|
||||
bool in_reverse)
|
||||
: throttle(in_throttle),
|
||||
steer(in_steer),
|
||||
brake(in_brake),
|
||||
hand_brake(in_hand_brake),
|
||||
reverse(in_reverse) {}
|
||||
|
||||
float throttle = 0.0f;
|
||||
float steer = 0.0f;
|
||||
float brake = 0.0f;
|
||||
bool hand_brake = false;
|
||||
bool reverse = false;
|
||||
|
||||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
VehicleControl(const FVehicleControl &Control)
|
||||
: throttle(Control.Throttle),
|
||||
steer(Control.Steer),
|
||||
brake(Control.Brake),
|
||||
hand_brake(Control.bHandBrake),
|
||||
reverse(Control.bReverse) {}
|
||||
|
||||
operator FVehicleControl() const {
|
||||
FVehicleControl Control;
|
||||
Control.Throttle = throttle;
|
||||
Control.Steer = steer;
|
||||
Control.Brake = brake;
|
||||
Control.bHandBrake = hand_brake;
|
||||
Control.bReverse = reverse;
|
||||
return Control;
|
||||
}
|
||||
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(
|
||||
throttle,
|
||||
steer,
|
||||
brake,
|
||||
hand_brake,
|
||||
reverse);
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
} // namespace carla
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/Logging.h"
|
||||
#include "carla/ThreadGroup.h"
|
||||
#include "carla/streaming/Token.h"
|
||||
#include "carla/streaming/detail/tcp/Client.h"
|
||||
#include "carla/streaming/low_level/Client.h"
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
|
||||
using stream_token = detail::token_type;
|
||||
|
||||
/// A client able to subscribe to multiple streams.
|
||||
class Client {
|
||||
public:
|
||||
|
||||
Client() : _io_service(), _work_to_do(_io_service) {}
|
||||
|
||||
~Client() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
void Subscribe(const Token &token, Functor &&callback) {
|
||||
_client.Subscribe(_io_service, token, std::forward<Functor>(callback));
|
||||
}
|
||||
|
||||
void Run() {
|
||||
_io_service.run();
|
||||
}
|
||||
|
||||
void AsyncRun(size_t worker_threads) {
|
||||
_workers.CreateThreads(worker_threads, [this]() { Run(); });
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
_io_service.stop();
|
||||
_workers.JoinAll();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
using underlying_client = low_level::Client<detail::tcp::Client>;
|
||||
|
||||
boost::asio::io_service _io_service;
|
||||
|
||||
boost::asio::io_service::work _work_to_do;
|
||||
|
||||
ThreadGroup _workers;
|
||||
|
||||
underlying_client _client;
|
||||
};
|
||||
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,136 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/Debug.h"
|
||||
#include "carla/streaming/detail/Types.h"
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <exception>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
|
||||
/// A message owns a buffer with raw data.
|
||||
class Message {
|
||||
|
||||
// =========================================================================
|
||||
// -- Typedefs -------------------------------------------------------------
|
||||
// =========================================================================
|
||||
|
||||
public:
|
||||
|
||||
using value_type = unsigned char;
|
||||
|
||||
using size_type = detail::message_size_type;
|
||||
|
||||
// =========================================================================
|
||||
// -- Construction and assignment ------------------------------------------
|
||||
// =========================================================================
|
||||
|
||||
public:
|
||||
|
||||
Message() = default;
|
||||
|
||||
explicit Message(size_type size)
|
||||
: _size(size),
|
||||
_data(std::make_unique<value_type[]>(_size)) {}
|
||||
|
||||
explicit Message(uint64_t size)
|
||||
: Message([size]() {
|
||||
#ifndef LIBCARLA_INCLUDED_FROM_UE4
|
||||
/// @todo What to do with exceptions?
|
||||
if (size > std::numeric_limits<size_type>::max()) {
|
||||
throw std::invalid_argument("message size too big");
|
||||
}
|
||||
#endif // LIBCARLA_INCLUDED_FROM_UE4
|
||||
return static_cast<size_type>(size);
|
||||
} ()) {}
|
||||
|
||||
template <typename ConstBufferSequence>
|
||||
explicit Message(ConstBufferSequence source)
|
||||
: Message(boost::asio::buffer_size(source)) {
|
||||
DEBUG_ONLY(auto bytes_copied = )
|
||||
boost::asio::buffer_copy(buffer(), source);
|
||||
DEBUG_ASSERT(bytes_copied == size());
|
||||
}
|
||||
|
||||
Message(const Message &) = delete;
|
||||
Message &operator=(const Message &) = delete;
|
||||
|
||||
Message(Message &&rhs) noexcept
|
||||
: _size(rhs._size),
|
||||
_data(std::move(rhs._data)) {
|
||||
rhs._size = 0u;
|
||||
}
|
||||
|
||||
Message &operator=(Message &&rhs) noexcept {
|
||||
_size = rhs._size;
|
||||
_data = std::move(rhs._data);
|
||||
rhs._size = 0u;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// -- Data access ----------------------------------------------------------
|
||||
// =========================================================================
|
||||
|
||||
public:
|
||||
|
||||
bool empty() const {
|
||||
return _size == 0u;
|
||||
}
|
||||
|
||||
size_type size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
const value_type *data() const {
|
||||
return _data.get();
|
||||
}
|
||||
|
||||
value_type *data() {
|
||||
return _data.get();
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// -- Conversions ----------------------------------------------------------
|
||||
// =========================================================================
|
||||
|
||||
public:
|
||||
|
||||
boost::asio::const_buffer buffer() const {
|
||||
return {data(), size()};
|
||||
}
|
||||
|
||||
boost::asio::mutable_buffer buffer() {
|
||||
return {data(), size()};
|
||||
}
|
||||
|
||||
std::array<boost::asio::const_buffer, 2u> encode() const {
|
||||
DEBUG_ASSERT(!empty());
|
||||
return {boost::asio::buffer(&_size, sizeof(_size)), buffer()};
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// -- Private members ------------------------------------------------------
|
||||
// =========================================================================
|
||||
|
||||
private:
|
||||
|
||||
size_type _size = 0u;
|
||||
|
||||
std::unique_ptr<value_type[]> _data = nullptr;
|
||||
};
|
||||
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,65 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/ThreadGroup.h"
|
||||
#include "carla/streaming/low_level/Server.h"
|
||||
#include "carla/streaming/detail/tcp/Server.h"
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
|
||||
/// A streaming server. Each new stream has a token associated, this token can
|
||||
/// be used by a client to subscribe to the stream.
|
||||
class Server {
|
||||
using underlying_server = low_level::Server<detail::tcp::Server>;
|
||||
public:
|
||||
|
||||
explicit Server(uint16_t port)
|
||||
: _server(_io_service, port) {}
|
||||
|
||||
explicit Server(const std::string &address, uint16_t port)
|
||||
: _server(_io_service, address, port) {}
|
||||
|
||||
~Server() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
void set_timeout(time_duration timeout) {
|
||||
_server.set_timeout(timeout);
|
||||
}
|
||||
|
||||
Stream MakeStream() {
|
||||
return _server.MakeStream();
|
||||
}
|
||||
|
||||
void Run() {
|
||||
_io_service.run();
|
||||
}
|
||||
|
||||
void AsyncRun(size_t worker_threads) {
|
||||
_workers.CreateThreads(worker_threads, [this](){ Run(); });
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
_io_service.stop();
|
||||
_workers.JoinAll();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
boost::asio::io_service _io_service;
|
||||
|
||||
underlying_server _server;
|
||||
|
||||
ThreadGroup _workers;
|
||||
};
|
||||
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,66 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/Debug.h"
|
||||
#include "carla/streaming/Message.h"
|
||||
#include "carla/streaming/Token.h"
|
||||
#include "carla/streaming/detail/StreamState.h"
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class Dispatcher;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class Stream {
|
||||
public:
|
||||
|
||||
Stream() = delete;
|
||||
|
||||
Stream(const Stream &) = default;
|
||||
Stream(Stream &&) = default;
|
||||
|
||||
Stream &operator=(const Stream &) = default;
|
||||
Stream &operator=(Stream &&) = default;
|
||||
|
||||
Token token() const {
|
||||
return _shared_state->token();
|
||||
}
|
||||
|
||||
template <typename ConstBufferSequence>
|
||||
void Write(ConstBufferSequence buffer) {
|
||||
_shared_state->Write(std::make_shared<Message>(buffer));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Stream &operator<<(const T &rhs) {
|
||||
Write(boost::asio::buffer(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class detail::Dispatcher;
|
||||
|
||||
Stream(std::shared_ptr<detail::StreamState> state)
|
||||
: _shared_state(std::move(state)) {
|
||||
DEBUG_ASSERT(_shared_state != nullptr);
|
||||
}
|
||||
|
||||
std::shared_ptr<detail::StreamState> _shared_state;
|
||||
};
|
||||
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/rpc/MsgPack.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
|
||||
class Token {
|
||||
public:
|
||||
|
||||
std::array<unsigned char, 24u> data;
|
||||
|
||||
MSGPACK_DEFINE_ARRAY(data);
|
||||
};
|
||||
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/streaming/detail/Dispatcher.h"
|
||||
|
||||
#include "carla/Logging.h"
|
||||
|
||||
#include <exception>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
|
||||
Stream Dispatcher::MakeStream() {
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
++_cached_token._token.stream_id; // id zero only happens in overflow.
|
||||
auto ptr = std::make_shared<StreamState>(_cached_token);
|
||||
auto result = _stream_map.emplace(std::make_pair(_cached_token.get_stream_id(), ptr));
|
||||
if (!result.second) {
|
||||
throw std::runtime_error("failed to create stream!");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void Dispatcher::RegisterSession(std::shared_ptr<Session> session) {
|
||||
DEBUG_ASSERT(session != nullptr);
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
auto search = _stream_map.find(session->get_stream_id());
|
||||
if (search != _stream_map.end()) {
|
||||
DEBUG_ASSERT(search->second != nullptr);
|
||||
search->second->set_session(std::move(session));
|
||||
} else {
|
||||
log_error("Invalid session: no stream available with id", session->get_stream_id());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/streaming/Stream.h"
|
||||
#include "carla/streaming/detail/Session.h"
|
||||
#include "carla/streaming/detail/StreamState.h"
|
||||
#include "carla/streaming/detail/Token.h"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
|
||||
/// Keeps the mapping between streams and sessions.
|
||||
class Dispatcher {
|
||||
public:
|
||||
|
||||
template <typename P>
|
||||
explicit Dispatcher(const boost::asio::ip::basic_endpoint<P> &ep)
|
||||
: _cached_token(0u, ep) {}
|
||||
|
||||
Stream MakeStream();
|
||||
|
||||
void RegisterSession(std::shared_ptr<Session> session);
|
||||
|
||||
private:
|
||||
|
||||
// We use a mutex here, but we assume that sessions and streams won't be
|
||||
// created too often.
|
||||
std::mutex _mutex;
|
||||
|
||||
token_type _cached_token;
|
||||
|
||||
std::unordered_map<
|
||||
stream_id_type,
|
||||
std::shared_ptr<StreamState>> _stream_map;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/streaming/detail/Types.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
|
||||
/// A wrapper to put clients into std::unordered_set.
|
||||
template <typename T>
|
||||
class HashableClient : public T {
|
||||
public:
|
||||
|
||||
template <typename ... Args>
|
||||
HashableClient(Args && ... args)
|
||||
: T(std::forward<Args>(args) ...) {}
|
||||
|
||||
bool operator==(const HashableClient &rhs) const {
|
||||
return T::GetStreamId() == rhs.GetStreamId();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
||||
|
||||
namespace std {
|
||||
|
||||
// Injecting a hash function for our clients into std namespace so we can
|
||||
// directly insert them into std::unordered_set.
|
||||
template <typename T>
|
||||
struct hash<carla::streaming::detail::HashableClient<T>> {
|
||||
using argument_type = carla::streaming::detail::HashableClient<T>;
|
||||
using result_type = std::size_t;
|
||||
result_type operator()(const argument_type &client) const noexcept {
|
||||
return std::hash<carla::streaming::detail::stream_id_type>()(client.GetStreamId());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/streaming/detail/tcp/ServerSession.h"
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
|
||||
using Session = tcp::ServerSession;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/NonCopyable.h"
|
||||
#include "carla/streaming/Message.h"
|
||||
#include "carla/streaming/detail/Session.h"
|
||||
#include "carla/streaming/detail/Token.h"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
|
||||
/// Handles the synchronization of the shared session.
|
||||
class SessionHolder {
|
||||
public:
|
||||
|
||||
void set_session(std::shared_ptr<Session> session) {
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
_session = std::move(session);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::shared_ptr<Session> get_session() const {
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
return _session;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
mutable std::mutex _mutex; /// @todo it can be atomic.
|
||||
|
||||
std::shared_ptr<Session> _session;
|
||||
};
|
||||
|
||||
/// Shared state among all the copies of a stream. Provides access to the
|
||||
/// underlying server session if active.
|
||||
class StreamState
|
||||
: public SessionHolder,
|
||||
private NonCopyable {
|
||||
public:
|
||||
|
||||
explicit StreamState(const token_type &token) : _token(token) {}
|
||||
|
||||
const token_type &token() const {
|
||||
return _token;
|
||||
}
|
||||
|
||||
void Write(std::shared_ptr<const Message> message) {
|
||||
auto session = get_session();
|
||||
if (session != nullptr) {
|
||||
session->Write(message);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const token_type _token;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/streaming/detail/Token.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
|
||||
void token_type::set_address(const boost::asio::ip::address &addr) {
|
||||
if (addr.is_v4()) {
|
||||
_token.address_type = token_data::address::ip_v4;
|
||||
_token.address.v4 = addr.to_v4().to_bytes();
|
||||
} else if (addr.is_v6()) {
|
||||
_token.address_type = token_data::address::ip_v6;
|
||||
_token.address.v6 = addr.to_v6().to_bytes();
|
||||
} else {
|
||||
throw std::invalid_argument("invalid ip address!");
|
||||
}
|
||||
}
|
||||
|
||||
boost::asio::ip::address token_type::get_address() const {
|
||||
if (_token.address_type == token_data::address::ip_v4) {
|
||||
return boost::asio::ip::address_v4(_token.address.v4);
|
||||
}
|
||||
return boost::asio::ip::address_v6(_token.address.v6);
|
||||
}
|
||||
|
||||
token_type::token_type(const Token &rhs) {
|
||||
std::memcpy(&_token, &rhs.data[0u], sizeof(_token));
|
||||
}
|
||||
|
||||
token_type::operator Token() const {
|
||||
Token token;
|
||||
std::memcpy(&token.data[0u], &_token, token.data.size());
|
||||
return token;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,146 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/Debug.h"
|
||||
#include "carla/streaming/Token.h"
|
||||
#include "carla/streaming/detail/Types.h"
|
||||
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ip/udp.hpp>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct token_data {
|
||||
stream_id_type stream_id;
|
||||
|
||||
uint16_t port;
|
||||
|
||||
enum class protocol : uint8_t {
|
||||
not_set,
|
||||
tcp,
|
||||
udp
|
||||
} protocol = protocol::not_set;
|
||||
|
||||
enum class address : uint8_t {
|
||||
not_set,
|
||||
ip_v4,
|
||||
ip_v6
|
||||
} address_type = address::not_set;
|
||||
|
||||
union {
|
||||
boost::asio::ip::address_v4::bytes_type v4;
|
||||
boost::asio::ip::address_v6::bytes_type v6;
|
||||
} address;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
static_assert(
|
||||
sizeof(token_data) == sizeof(Token::data),
|
||||
"Size shouldn't be more than"
|
||||
" v6 address : 128"
|
||||
" + state : 16"
|
||||
" + port : 16"
|
||||
" + stream id : 32"
|
||||
" -----------------"
|
||||
" 192");
|
||||
|
||||
/// Serializes a stream endpoint. Contains all the necessary information for a
|
||||
/// client to subscribe to a stream.
|
||||
class token_type {
|
||||
private:
|
||||
|
||||
template <typename P>
|
||||
static constexpr auto get_protocol() {
|
||||
return std::is_same<P, boost::asio::ip::tcp>::value ?
|
||||
token_data::protocol::tcp :
|
||||
token_data::protocol::udp;
|
||||
}
|
||||
|
||||
void set_address(const boost::asio::ip::address &addr);
|
||||
|
||||
boost::asio::ip::address get_address() const;
|
||||
|
||||
template <typename P>
|
||||
boost::asio::ip::basic_endpoint<P> get_endpoint() const {
|
||||
DEBUG_ASSERT(is_valid());
|
||||
DEBUG_ASSERT(get_protocol<P>() == _token.protocol);
|
||||
return {get_address(), _token.port};
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
explicit token_type(
|
||||
stream_id_type stream_id,
|
||||
const boost::asio::ip::basic_endpoint<P> &ep) {
|
||||
_token.stream_id = stream_id;
|
||||
_token.port = ep.port();
|
||||
_token.protocol = get_protocol<P>();
|
||||
set_address(ep.address());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
token_type() = default;
|
||||
token_type(const token_type &) = default;
|
||||
|
||||
token_type(const Token &rhs);
|
||||
|
||||
operator Token() const;
|
||||
|
||||
auto get_stream_id() const {
|
||||
return _token.stream_id;
|
||||
}
|
||||
|
||||
auto get_port() const {
|
||||
return _token.port;
|
||||
}
|
||||
|
||||
bool is_valid() const {
|
||||
return ((_token.protocol != token_data::protocol::not_set) &&
|
||||
(_token.address_type != token_data::address::not_set));
|
||||
}
|
||||
|
||||
bool address_is_v4() const {
|
||||
return _token.address_type == token_data::address::ip_v4;
|
||||
}
|
||||
|
||||
bool address_is_v6() const {
|
||||
return _token.address_type == token_data::address::ip_v6;
|
||||
}
|
||||
|
||||
bool protocol_is_udp() const {
|
||||
return _token.protocol == token_data::protocol::udp;
|
||||
}
|
||||
|
||||
bool protocol_is_tcp() const {
|
||||
return _token.protocol == token_data::protocol::tcp;
|
||||
}
|
||||
|
||||
boost::asio::ip::udp::endpoint to_udp_endpoint() const {
|
||||
return get_endpoint<boost::asio::ip::udp>();
|
||||
}
|
||||
|
||||
boost::asio::ip::tcp::endpoint to_tcp_endpoint() const {
|
||||
return get_endpoint<boost::asio::ip::tcp>();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class Dispatcher;
|
||||
|
||||
token_data _token;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
|
||||
using stream_id_type = uint32_t;
|
||||
|
||||
using message_size_type = uint32_t;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,195 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/streaming/detail/tcp/Client.h"
|
||||
|
||||
#include "carla/Debug.h"
|
||||
#include "carla/Logging.h"
|
||||
#include "carla/Time.h"
|
||||
|
||||
#include <boost/asio/connect.hpp>
|
||||
#include <boost/asio/read.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
namespace tcp {
|
||||
|
||||
// ===========================================================================
|
||||
// -- Decoder ----------------------------------------------------------------
|
||||
// ===========================================================================
|
||||
|
||||
class Decoder {
|
||||
public:
|
||||
|
||||
boost::asio::mutable_buffer header() {
|
||||
return boost::asio::buffer(&_size, sizeof(_size));
|
||||
}
|
||||
|
||||
boost::asio::mutable_buffer body() {
|
||||
DEBUG_ASSERT(_size > 0u);
|
||||
DEBUG_ASSERT(_message == nullptr);
|
||||
_message = std::make_shared<Message>(_size);
|
||||
return _message->buffer();
|
||||
}
|
||||
|
||||
auto size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
auto pop() {
|
||||
return std::move(_message);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
message_size_type _size = 0u;
|
||||
|
||||
std::shared_ptr<Message> _message;
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
// -- Client -----------------------------------------------------------------
|
||||
// ===========================================================================
|
||||
|
||||
Client::Client(
|
||||
boost::asio::io_service &io_service,
|
||||
endpoint ep,
|
||||
stream_id_type stream_id,
|
||||
callback_function_type callback)
|
||||
: _endpoint(std::move(ep)),
|
||||
_stream_id(stream_id),
|
||||
_callback(std::move(callback)),
|
||||
_socket(io_service),
|
||||
_strand(io_service),
|
||||
_connection_timer(io_service) {
|
||||
Connect();
|
||||
}
|
||||
|
||||
Client::~Client() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
void Client::Stop() {
|
||||
_connection_timer.cancel();
|
||||
_strand.post([this]() {
|
||||
_done = true;
|
||||
if (_socket.is_open()) {
|
||||
_socket.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Client::Connect() {
|
||||
_strand.post([this]() {
|
||||
if (_done) {
|
||||
return;
|
||||
}
|
||||
|
||||
using boost::system::error_code;
|
||||
|
||||
if (_socket.is_open()) {
|
||||
_socket.close();
|
||||
}
|
||||
|
||||
auto handle_connect = [=](error_code ec) {
|
||||
if (!ec) {
|
||||
// Send the stream id to subscribe to the stream.
|
||||
log_debug("streaming client: sending stream id", _stream_id);
|
||||
boost::asio::async_write(
|
||||
_socket,
|
||||
boost::asio::buffer(&_stream_id, sizeof(_stream_id)),
|
||||
_strand.wrap([=](error_code ec, size_t DEBUG_ONLY(bytes)) {
|
||||
if (!ec) {
|
||||
DEBUG_ASSERT_EQ(bytes, sizeof(_stream_id));
|
||||
// If succeeded start reading data.
|
||||
ReadData();
|
||||
} else {
|
||||
// Else try again.
|
||||
log_debug("streaming client: failed to send stream id:", ec.message());
|
||||
Connect();
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
log_debug("streaming client: connection failed:", ec.message());
|
||||
Reconnect();
|
||||
}
|
||||
};
|
||||
|
||||
log_debug("streaming client: connecting to", _endpoint);
|
||||
_socket.async_connect(_endpoint, _strand.wrap(handle_connect));
|
||||
});
|
||||
}
|
||||
|
||||
void Client::Reconnect() {
|
||||
_connection_timer.expires_from_now(time_duration::seconds(1u));
|
||||
_connection_timer.async_wait([this](boost::system::error_code ec) {
|
||||
if (!ec) {
|
||||
Connect();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Client::ReadData() {
|
||||
_strand.post([this]() {
|
||||
if (_done) {
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug("streaming client: Client::ReadData");
|
||||
|
||||
auto encoder = std::make_shared<Decoder>();
|
||||
|
||||
auto handle_read_data = [=](boost::system::error_code ec, size_t DEBUG_ONLY(bytes)) {
|
||||
DEBUG_ONLY(log_debug("streaming client: Client::ReadData.handle_read_data", bytes, "bytes"));
|
||||
if (!ec) {
|
||||
DEBUG_ASSERT_EQ(bytes, encoder->size());
|
||||
DEBUG_ASSERT_NE(bytes, 0u);
|
||||
// Move the buffer to the callback function and start reading
|
||||
// the next
|
||||
// piece of data.
|
||||
log_debug("streaming client: success reading data, calling the callback");
|
||||
_socket.get_io_service().post([this, encoder]() { _callback(encoder->pop()); });
|
||||
ReadData();
|
||||
} else {
|
||||
// As usual, if anything fails start over from the very top.
|
||||
log_debug("streaming client: failed to read data:", ec.message());
|
||||
Connect();
|
||||
}
|
||||
};
|
||||
|
||||
auto handle_read_header = [=](boost::system::error_code ec, size_t DEBUG_ONLY(bytes)) {
|
||||
DEBUG_ONLY(log_debug("streaming client: Client::ReadData.handle_read_header", bytes, "bytes"));
|
||||
if (!ec && (encoder->size() > 0u)) {
|
||||
DEBUG_ASSERT_EQ(bytes, sizeof(message_size_type));
|
||||
// Now that we know the size of the coming buffer, we can
|
||||
// allocate
|
||||
// our buffer and start putting data into it.
|
||||
boost::asio::async_read(
|
||||
_socket,
|
||||
encoder->body(),
|
||||
_strand.wrap(handle_read_data));
|
||||
} else {
|
||||
log_debug("streaming client: failed to read header:", ec.message());
|
||||
DEBUG_ONLY(log_debug("size = ", encoder->size()));
|
||||
DEBUG_ONLY(log_debug("bytes = ", bytes));
|
||||
Connect();
|
||||
}
|
||||
};
|
||||
|
||||
// Read the size of the buffer that is coming.
|
||||
boost::asio::async_read(
|
||||
_socket,
|
||||
encoder->header(),
|
||||
_strand.wrap(handle_read_header));
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace tcp
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/NonCopyable.h"
|
||||
#include "carla/streaming/Message.h"
|
||||
#include "carla/streaming/detail/Types.h"
|
||||
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
namespace tcp {
|
||||
|
||||
/// A client that connects to a single stream.
|
||||
///
|
||||
/// @warning The client should not be destroyed before the @a io_service is
|
||||
/// stopped.
|
||||
class Client : private NonCopyable {
|
||||
public:
|
||||
|
||||
using endpoint = boost::asio::ip::tcp::endpoint;
|
||||
using callback_function_type = std::function<void (std::shared_ptr<Message>)>;
|
||||
|
||||
Client(
|
||||
boost::asio::io_service &io_service,
|
||||
endpoint ep,
|
||||
stream_id_type stream_id,
|
||||
callback_function_type callback);
|
||||
|
||||
~Client();
|
||||
|
||||
stream_id_type GetStreamId() const {
|
||||
return _stream_id;
|
||||
}
|
||||
|
||||
void Stop();
|
||||
|
||||
private:
|
||||
|
||||
void Connect();
|
||||
|
||||
void Reconnect();
|
||||
|
||||
void ReadData();
|
||||
|
||||
const endpoint _endpoint;
|
||||
|
||||
const stream_id_type _stream_id;
|
||||
|
||||
callback_function_type _callback;
|
||||
|
||||
boost::asio::ip::tcp::socket _socket;
|
||||
|
||||
boost::asio::io_service::strand _strand;
|
||||
|
||||
boost::asio::deadline_timer _connection_timer;
|
||||
|
||||
bool _done = false;
|
||||
};
|
||||
|
||||
} // namespace tcp
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/streaming/detail/tcp/Server.h"
|
||||
|
||||
#include "carla/Logging.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
namespace tcp {
|
||||
|
||||
Server::Server(boost::asio::io_service &io_service, endpoint ep)
|
||||
: _acceptor(io_service, std::move(ep)),
|
||||
_timeout(time_duration::seconds(10u)) {}
|
||||
|
||||
void Server::OpenSession(
|
||||
const time_duration timeout,
|
||||
ServerSession::callback_function_type callback) {
|
||||
using boost::system::error_code;
|
||||
|
||||
auto session = std::make_shared<ServerSession>(_acceptor.get_io_service(), timeout);
|
||||
|
||||
auto handle_query = [=](const error_code &ec) {
|
||||
if (!ec) {
|
||||
session->Open(callback);
|
||||
} else {
|
||||
log_error("tcp accept error:", ec.message());
|
||||
}
|
||||
};
|
||||
|
||||
_acceptor.async_accept(session->_socket, [=](error_code ec) {
|
||||
// Handle query and open a new session immediately.
|
||||
_acceptor.get_io_service().post([=]() { handle_query(ec); });
|
||||
OpenSession(timeout, callback);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace tcp
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/NonCopyable.h"
|
||||
#include "carla/Time.h"
|
||||
#include "carla/streaming/detail/tcp/ServerSession.h"
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
namespace tcp {
|
||||
|
||||
class Server : private NonCopyable {
|
||||
public:
|
||||
|
||||
using endpoint = boost::asio::ip::tcp::endpoint;
|
||||
using protocol_type = endpoint::protocol_type;
|
||||
|
||||
explicit Server(boost::asio::io_service &io_service, endpoint ep);
|
||||
|
||||
/// Set session time-out. Applies only to newly created sessions. By default
|
||||
/// the time-out is set to 10 seconds.
|
||||
void set_timeout(time_duration timeout) {
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
/// Start listening for connections, on each new connection @a callback is
|
||||
/// called.
|
||||
template <typename Functor>
|
||||
void Listen(Functor callback) {
|
||||
_acceptor.get_io_service().post([=]() { OpenSession(_timeout, callback); });
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void OpenSession(time_duration timeout, ServerSession::callback_function_type callback);
|
||||
|
||||
boost::asio::ip::tcp::acceptor _acceptor;
|
||||
|
||||
std::atomic<time_duration> _timeout;
|
||||
};
|
||||
|
||||
} // namespace tcp
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,119 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "carla/streaming/detail/tcp/ServerSession.h"
|
||||
|
||||
#include "carla/Debug.h"
|
||||
#include "carla/Logging.h"
|
||||
|
||||
#include <boost/asio/read.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
namespace tcp {
|
||||
|
||||
static std::atomic_size_t SESSION_COUNTER{0u};
|
||||
|
||||
ServerSession::ServerSession(
|
||||
boost::asio::io_service &io_service,
|
||||
const time_duration timeout)
|
||||
: _session_id(SESSION_COUNTER++),
|
||||
_socket(io_service),
|
||||
_timeout(timeout),
|
||||
_deadline(io_service),
|
||||
_strand(io_service) {}
|
||||
|
||||
ServerSession::~ServerSession() {
|
||||
_deadline.cancel();
|
||||
}
|
||||
|
||||
void ServerSession::Open(callback_function_type callback) {
|
||||
StartTimer();
|
||||
auto self = shared_from_this(); // To keep myself alive.
|
||||
_strand.post([=]() {
|
||||
|
||||
auto handle_query = [this, self, cb=std::move(callback)](
|
||||
const boost::system::error_code &ec,
|
||||
size_t DEBUG_ONLY(bytes_received)) {
|
||||
DEBUG_ASSERT_EQ(bytes_received, sizeof(_stream_id));
|
||||
if (!ec) {
|
||||
log_debug("session", _session_id, "for stream", _stream_id, " started");
|
||||
_socket.get_io_service().post([=]() { cb(self); });
|
||||
} else {
|
||||
log_error("session", _session_id, ": error retrieving stream id :", ec.message());
|
||||
Close();
|
||||
}
|
||||
};
|
||||
|
||||
// Read the stream id.
|
||||
_deadline.expires_from_now(_timeout);
|
||||
boost::asio::async_read(
|
||||
_socket,
|
||||
boost::asio::buffer(&_stream_id, sizeof(_stream_id)),
|
||||
_strand.wrap(handle_query));
|
||||
});
|
||||
}
|
||||
|
||||
void ServerSession::Write(std::shared_ptr<const Message> message) {
|
||||
auto self = shared_from_this();
|
||||
_strand.post([=]() {
|
||||
|
||||
/// @todo has to be a better way of doing this...
|
||||
if (_is_writing) {
|
||||
// Repost and return;
|
||||
Write(std::move(message));
|
||||
return;
|
||||
}
|
||||
_is_writing = true;
|
||||
|
||||
auto handle_sent = [this, self, message](const boost::system::error_code &ec, size_t DEBUG_ONLY(bytes)) {
|
||||
_is_writing = false;
|
||||
if (ec) {
|
||||
log_error("session", _session_id, ": error sending data :", ec.message());
|
||||
} else {
|
||||
DEBUG_ONLY(log_debug("session", _session_id, ": successfully sent", bytes, "bytes"));
|
||||
DEBUG_ASSERT_EQ(bytes, sizeof(message_size_type) + message->size());
|
||||
}
|
||||
};
|
||||
|
||||
log_debug("session", _session_id, ": sending message of", message->size(), "bytes");
|
||||
|
||||
_deadline.expires_from_now(_timeout);
|
||||
boost::asio::async_write(
|
||||
_socket,
|
||||
message->encode(),
|
||||
_strand.wrap(handle_sent));
|
||||
});
|
||||
}
|
||||
|
||||
void ServerSession::Close() {
|
||||
_strand.post([this, self = shared_from_this()]() {
|
||||
if (_socket.is_open()) {
|
||||
_socket.close();
|
||||
}
|
||||
log_debug("session", _session_id, "closed");
|
||||
});
|
||||
}
|
||||
|
||||
void ServerSession::StartTimer() {
|
||||
if (_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now()) {
|
||||
log_debug("session", _session_id, "timed out");
|
||||
Close();
|
||||
} else {
|
||||
_deadline.async_wait([self = shared_from_this()](boost::system::error_code) {
|
||||
self->StartTimer();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tcp
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,82 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/NonCopyable.h"
|
||||
#include "carla/Time.h"
|
||||
#include "carla/streaming/Message.h"
|
||||
#include "carla/streaming/detail/Types.h"
|
||||
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace detail {
|
||||
namespace tcp {
|
||||
|
||||
/// A TCP server session. When a session opens, it reads from the socket a
|
||||
/// stream id object and passes itself to the callback functor. The session
|
||||
/// closes itself after @a timeout of inactivity is met.
|
||||
class ServerSession
|
||||
: public std::enable_shared_from_this<ServerSession>,
|
||||
private NonCopyable {
|
||||
public:
|
||||
|
||||
using socket_type = boost::asio::ip::tcp::socket;
|
||||
using callback_function_type = std::function<void(std::shared_ptr<ServerSession>)>;
|
||||
|
||||
explicit ServerSession(boost::asio::io_service &io_service, time_duration timeout);
|
||||
|
||||
~ServerSession();
|
||||
|
||||
/// Starts the session and calls @a callback after successfully reading the
|
||||
/// stream id.
|
||||
void Open(callback_function_type callback);
|
||||
|
||||
/// @warning This function should only be called after the session is
|
||||
/// opened. It is safe to call this function from within the @a callback.
|
||||
stream_id_type get_stream_id() const {
|
||||
return _stream_id;
|
||||
}
|
||||
|
||||
/// Writes some data to the socket.
|
||||
void Write(std::shared_ptr<const Message> message);
|
||||
|
||||
/// Posts a job to close this session.
|
||||
void Close();
|
||||
|
||||
private:
|
||||
|
||||
void StartTimer();
|
||||
|
||||
friend class Server;
|
||||
|
||||
const size_t _session_id;
|
||||
|
||||
stream_id_type _stream_id = 0u;
|
||||
|
||||
socket_type _socket;
|
||||
|
||||
time_duration _timeout;
|
||||
|
||||
boost::asio::deadline_timer _deadline;
|
||||
|
||||
boost::asio::io_service::strand _strand;
|
||||
|
||||
bool _is_writing = false;
|
||||
};
|
||||
|
||||
} // namespace tcp
|
||||
} // namespace detail
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/streaming/detail/HashableClient.h"
|
||||
#include "carla/streaming/detail/Token.h"
|
||||
#include "carla/streaming/detail/tcp/Client.h"
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace low_level {
|
||||
|
||||
/// A client able to subscribe to multiple streams. Accepts an external
|
||||
/// io_service.
|
||||
///
|
||||
/// @warning The client should not be destroyed before the @a io_service is
|
||||
/// stopped.
|
||||
template <typename T>
|
||||
class Client {
|
||||
public:
|
||||
|
||||
using underlying_client = detail::HashableClient<T>;
|
||||
|
||||
using token_type = carla::streaming::detail::token_type;
|
||||
|
||||
template <typename Functor>
|
||||
void Subscribe(
|
||||
boost::asio::io_service &io_service,
|
||||
const token_type &token,
|
||||
Functor &&callback) {
|
||||
if (!token.protocol_is_tcp()) { /// @todo
|
||||
throw std::invalid_argument("invalid token, only TCP tokens supported");
|
||||
}
|
||||
_clients.emplace(
|
||||
io_service,
|
||||
token.to_tcp_endpoint(),
|
||||
token.get_stream_id(),
|
||||
std::forward<Functor>(callback));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::unordered_set<underlying_client> _clients;
|
||||
};
|
||||
|
||||
} // namespace low_level
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "carla/streaming/detail/Dispatcher.h"
|
||||
#include "carla/streaming/Stream.h"
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
namespace carla {
|
||||
namespace streaming {
|
||||
namespace low_level {
|
||||
|
||||
/// A low-level streaming server. Each new stream has a token associated, this
|
||||
/// token can be used by a client to subscribe to the stream. This server
|
||||
/// requires an external io_service running.
|
||||
template <typename T>
|
||||
class Server {
|
||||
public:
|
||||
|
||||
using underlying_server = T;
|
||||
|
||||
using endpoint = typename underlying_server::endpoint;
|
||||
using protocol_type = typename underlying_server::protocol_type;
|
||||
|
||||
explicit Server(boost::asio::io_service &io_service, const endpoint &ep)
|
||||
: _server(io_service, ep),
|
||||
_dispatcher(ep) {
|
||||
_server.Listen([this](auto session){
|
||||
_dispatcher.RegisterSession(session);
|
||||
});
|
||||
}
|
||||
|
||||
explicit Server(boost::asio::io_service &io_service, uint16_t port)
|
||||
: Server(io_service, endpoint(protocol_type::v4(), port)) {}
|
||||
|
||||
explicit Server(boost::asio::io_service &io_service, const std::string &address, uint16_t port)
|
||||
: Server(io_service, endpoint(boost::asio::ip::address::from_string(address), port)) {}
|
||||
|
||||
void set_timeout(time_duration timeout) {
|
||||
_server.set_timeout(timeout);
|
||||
}
|
||||
|
||||
Stream MakeStream() {
|
||||
return _dispatcher.MakeStream();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
underlying_server _server;
|
||||
|
||||
detail::Dispatcher _dispatcher;
|
||||
};
|
||||
|
||||
} // namespace low_level
|
||||
} // namespace streaming
|
||||
} // namespace carla
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#ifndef LIBCARLA_INCLUDED_DISABLE_UE4_MACROS_HEADER
|
||||
# define LIBCARLA_INCLUDED_DISABLE_UE4_MACROS_HEADER
|
||||
#else
|
||||
# error disable-ue4-macros.h should only be included once!
|
||||
#endif // LIBCARLA_INCLUDED_DISABLE_UE4_MACROS_HEADER
|
||||
|
||||
#pragma push_macro("check")
|
||||
#undef check
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wmissing-braces"
|
||||
|
||||
#define LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
#ifndef BOOST_ERROR_CODE_HEADER_ONLY
|
||||
# define BOOST_ERROR_CODE_HEADER_ONLY
|
||||
#endif // BOOST_ERROR_CODE_HEADER_ONLY
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
# define BOOST_NO_EXCEPTIONS
|
||||
#endif // BOOST_NO_EXCEPTIONS
|
||||
|
||||
// Suppress clang warning.
|
||||
#if defined(__clang__)
|
||||
# ifndef __cpp_coroutines
|
||||
# define __cpp_coroutines 0
|
||||
# endif // __cpp_coroutines
|
||||
#endif // defined(__clang__)
|
||||
|
||||
namespace boost {
|
||||
|
||||
static inline void throw_exception(const std::exception &e) {
|
||||
UE_LOG(LogCarla, Fatal, TEXT("Exception thronw on Boost libraries: %s"), UTF8_TO_TCHAR(e.what()));
|
||||
}
|
||||
|
||||
} // namespace boost
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma pop_macro("check")
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#undef LIBCARLA_INCLUDED_FROM_UE4
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NDEBUG
|
||||
# define LIBCARLA_LOG_LEVEL LIBCARLA_LOG_LEVEL_INFO
|
||||
#endif // NDEBUG
|
||||
|
||||
#include "test/util/Message.h"
|
||||
|
||||
#include <carla/Logging.h>
|
||||
#include <carla/profiler/Profiler.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
constexpr uint16_t TESTING_PORT = 2000u;
|
||||
|
||||
using namespace std::chrono_literals;
|
|
@ -0,0 +1,137 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include <carla/streaming/Client.h>
|
||||
#include <carla/streaming/Server.h>
|
||||
|
||||
using namespace carla::streaming;
|
||||
|
||||
static auto make_special_message(size_t size) {
|
||||
std::vector<uint32_t> v(size/sizeof(uint32_t), 42u);
|
||||
Message msg(boost::asio::buffer(v));
|
||||
EXPECT_EQ(msg.size(), size);
|
||||
return msg;
|
||||
}
|
||||
|
||||
class Benchmark {
|
||||
public:
|
||||
|
||||
Benchmark(uint16_t port, size_t message_size)
|
||||
: _server(port),
|
||||
_client(),
|
||||
_message(make_special_message(message_size)),
|
||||
_client_callback(),
|
||||
_work_to_do(_client_callback) {}
|
||||
|
||||
void AddStream() {
|
||||
Stream stream = _server.MakeStream();
|
||||
|
||||
_client.Subscribe(stream.token(), [this](std::shared_ptr<Message> DEBUG_ONLY(msg)) {
|
||||
DEBUG_ASSERT_EQ(msg->size(), _message.size());
|
||||
DEBUG_ASSERT(*msg == _message);
|
||||
_client_callback.post([this]() {
|
||||
CARLA_PROFILE_FPS(client, listen_callback);
|
||||
++_number_of_messages_received;
|
||||
});
|
||||
});
|
||||
|
||||
_streams.push_back(stream);
|
||||
}
|
||||
|
||||
void AddStreams(size_t count) {
|
||||
for (auto i = 0u; i < count; ++i) {
|
||||
AddStream();
|
||||
}
|
||||
}
|
||||
|
||||
void Run(size_t number_of_messages) {
|
||||
_threads.CreateThread([this]() { _client_callback.run(); });
|
||||
_server.AsyncRun(_streams.size());
|
||||
_client.AsyncRun(_streams.size());
|
||||
|
||||
std::this_thread::sleep_for(1s); // the client needs to be ready so we make
|
||||
// sure we get all the messages.
|
||||
|
||||
for (auto &&stream : _streams) {
|
||||
_threads.CreateThread([=]() mutable {
|
||||
for (auto i = 0u; i < number_of_messages; ++i) {
|
||||
CARLA_PROFILE_SCOPE(game, write_to_stream);
|
||||
stream << _message.buffer();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (auto i = 0u; i < 30; ++i) {
|
||||
if (_number_of_messages_received >= (_streams.size() * number_of_messages)) {
|
||||
break;
|
||||
}
|
||||
std::cout << "received only " << _number_of_messages_received
|
||||
<< " messages, waiting..." << std::endl;
|
||||
std::this_thread::sleep_for(1s);
|
||||
}
|
||||
|
||||
_client_callback.stop();
|
||||
_threads.JoinAll();
|
||||
|
||||
std::cout << _number_of_messages_received << " messages received; done.\n";
|
||||
|
||||
_client.Stop();
|
||||
_server.Stop();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
carla::ThreadGroup _threads;
|
||||
|
||||
Server _server;
|
||||
|
||||
Client _client;
|
||||
|
||||
const Message _message;
|
||||
|
||||
boost::asio::io_service _client_callback;
|
||||
|
||||
boost::asio::io_service::work _work_to_do;
|
||||
|
||||
std::vector<Stream> _streams;
|
||||
|
||||
std::atomic_size_t _number_of_messages_received{0u};
|
||||
};
|
||||
|
||||
static void benchmark_image(
|
||||
const size_t dimensions,
|
||||
const size_t number_of_streams = 1u) {
|
||||
constexpr auto number_of_messages = 100u;
|
||||
Benchmark benchmark(TESTING_PORT, 4u * dimensions);
|
||||
benchmark.AddStreams(number_of_streams);
|
||||
benchmark.Run(number_of_messages);
|
||||
}
|
||||
|
||||
TEST(benchmark_streaming, image_200x200) {
|
||||
benchmark_image(200u * 200u);
|
||||
}
|
||||
|
||||
TEST(benchmark_streaming, image_800x600) {
|
||||
benchmark_image(800u * 600u);
|
||||
}
|
||||
|
||||
TEST(benchmark_streaming, image_1920x1080) {
|
||||
benchmark_image(1920u * 1080u);
|
||||
}
|
||||
|
||||
TEST(benchmark_streaming, image_200x200_mt) {
|
||||
benchmark_image(200u * 200u, 9u);
|
||||
}
|
||||
|
||||
TEST(benchmark_streaming, image_800x600_mt) {
|
||||
benchmark_image(800u * 600u, 9u);
|
||||
}
|
||||
|
||||
TEST(benchmark_streaming, image_1920x1080_mt) {
|
||||
benchmark_image(1920u * 1080u, 9u);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include <carla/Version.h>
|
||||
|
||||
TEST(miscellaneous, version) {
|
||||
std::cout << "LibCarla " << carla::version() << std::endl;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue