Merge branch 'master' into build-sytem
This commit is contained in:
commit
fcb32a96b2
|
@ -1,9 +1,11 @@
|
|||
Dist
|
||||
Doxygen
|
||||
PythonClient/dist
|
||||
Util/Build
|
||||
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
*.egg-info
|
||||
*.kdev4
|
||||
*.log
|
||||
*.pb.cc
|
||||
|
@ -22,5 +24,6 @@ Util/Build
|
|||
.tags*
|
||||
.vs
|
||||
__pycache__
|
||||
_images
|
||||
_benchmarks_results
|
||||
_images*
|
||||
core
|
||||
|
|
|
@ -24,4 +24,4 @@ matrix:
|
|||
packages:
|
||||
- cppcheck
|
||||
script:
|
||||
- cppcheck Unreal/CarlaUE4/Source Unreal/CarlaUE4/Plugins/Carla/Source Util/ -iUtil/Build -iUtil/CarlaServer/source/carla/server/carla_server.pb.cc --quiet --error-exitcode=1 --enable=warning
|
||||
- cppcheck . -iBuild -i.pb.cc --error-exitcode=1 --enable=warning --quiet
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
education, socio-economic status, nationality, personal appearance, race,
|
||||
religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at [INSERT EMAIL ADDRESS]. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
|
@ -1,23 +1,25 @@
|
|||
Contributing to CARLA
|
||||
=====================
|
||||
|
||||
> _This document is a work in progress and might be incomplete._
|
||||
|
||||
We are more than happy to accept contributions!
|
||||
|
||||
How can I contribute?
|
||||
|
||||
* Reporting bugs
|
||||
* Feature requests
|
||||
* Improving documentation
|
||||
* Code contributions
|
||||
|
||||
Reporting bugs
|
||||
--------------
|
||||
|
||||
Use our [issue section](issueslink) on GitHub. Please check before that the
|
||||
issue is not already reported.
|
||||
Use our [issue section][issueslink] on GitHub. Please check before that the
|
||||
issue is not already reported, and make sure you have read our
|
||||
[Documentation][docslink] and [FAQ][faqlink].
|
||||
|
||||
[issueslink]: https://github.com/carla-simulator/carla/issues
|
||||
[docslink]: http://carla.readthedocs.io
|
||||
[faqlink]: http://carla.readthedocs.io/en/latest/faq/
|
||||
|
||||
Feature requests
|
||||
----------------
|
||||
|
@ -28,6 +30,25 @@ your request as a new issue.
|
|||
|
||||
[frlink]: https://github.com/carla-simulator/carla/issues?q=is%3Aissue+is%3Aopen+label%3A%22feature+request%22
|
||||
|
||||
Improving documentation
|
||||
-----------------------
|
||||
|
||||
If you feel something is missing in the documentation, please don't hesitate to
|
||||
open an issue to let us know. Even better, if you think you can improve it
|
||||
yourself, it would be a great contribution to the community!
|
||||
|
||||
We build our documentation with [MkDocs](http://www.mkdocs.org/) based on the
|
||||
Markdown files inside the "Docs" folder. You can either directly modify them on
|
||||
GitHub or locally in your machine.
|
||||
|
||||
Once you are done with your changes, please submit a pull-request.
|
||||
|
||||
**TIP:** You can build and serve it locally by running `mkdocs` in the project's
|
||||
main folder
|
||||
|
||||
$ sudo pip install mkdocs
|
||||
$ mkdocs serve
|
||||
|
||||
Code contributions
|
||||
------------------
|
||||
|
||||
|
@ -52,34 +73,33 @@ current documentation if you feel confident enough.
|
|||
|
||||
#### Coding standard
|
||||
|
||||
Please follow the current coding style when submitting new code.
|
||||
|
||||
###### General
|
||||
|
||||
* Use spaces, not tabs.
|
||||
* Avoid adding trailing whitespace as it creates noise in the diffs.
|
||||
* Comments should not exceed 80 columns, code may exceed this limit a bit in rare occasions if it results in clearer code.
|
||||
|
||||
###### Python
|
||||
|
||||
* All code must be compatible with Python 2.7, 3.5, and 3.6.
|
||||
* [Pylint](https://www.pylint.org/) should not give any error or warning (few exceptions apply with external classes like `numpy`, see our `.pylintrc`).
|
||||
* Python code follows [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/) (use `autopep8` whenever possible).
|
||||
|
||||
###### C++
|
||||
|
||||
* Compilation should not give any error or warning (`clang++ -Wall -Wextra -std=C++14`).
|
||||
* Unreal C++ code (CarlaUE4 and Carla plugin) follow the [Unreal Engine's Coding Standard](https://docs.unrealengine.com/latest/INT/Programming/Development/CodingStandard/) with the exception of using spaces instead of tabs.
|
||||
* CarlaServer uses [Google's style guide](https://google.github.io/styleguide/cppguide.html).
|
||||
Please follow the current [coding standard](coding_standard.md) when submitting
|
||||
new code.
|
||||
|
||||
#### Pull-requests
|
||||
|
||||
Once you think your contribution is ready to be added to CARLA, please submit a
|
||||
pull-request to the `dev` branch.
|
||||
pull-request.
|
||||
|
||||
Try to be as descriptive as possible when filling the pull-request description.
|
||||
Adding images and gifs may help people to understand your changes or new
|
||||
features.
|
||||
|
||||
Please note that there are some checks that the new code is required to pass
|
||||
before we can do the merge. The checks are automatically run by the continuous
|
||||
integration system, you will see a green tick mark if all the checks succeeded.
|
||||
If you see a red mark, please correct your code accordingly.
|
||||
|
||||
###### Checklist
|
||||
|
||||
<!--
|
||||
If you modify this list please keep it up-to-date with pull_request_template.md
|
||||
-->
|
||||
|
||||
- [ ] Your branch is up-to-date with the `master` branch and tested with latest changes
|
||||
- [ ] Extended the README / documentation, if necessary
|
||||
- [ ] Code compiles correctly
|
||||
- [ ] All tests passing
|
||||
- [ ] `make check`
|
||||
- [ ] `pylint --disable=R,C --rcfile=PythonClient/.pylintrc PythonClient/carla PythonClient/*.py`
|
||||
- [ ] `cppcheck . -iBuild -i.pb.cc --enable=warning`
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
CARLA Benchmark
|
||||
===============
|
||||
|
||||
Running the Benchmark
|
||||
---------------------
|
||||
|
||||
The "carla" api provides a basic benchmarking system, that allows making several
|
||||
tests on a certain agent. We already provide the same benchmark used in the CoRL
|
||||
2017 paper. By running this benchmark you can compare the results of your agent
|
||||
to the results obtained by the agents show in the paper.
|
||||
|
||||
|
||||
Besides the requirements of the CARLA client, the benchmark package also needs
|
||||
the future package
|
||||
|
||||
$ sudo pip install future
|
||||
|
||||
By running the benchmark a default agent that just go straight will be tested.
|
||||
To run the benchmark you need a server running. For a default localhost server
|
||||
on port 2000, to run the benchmark you just need to run
|
||||
|
||||
$ ./run_benchmark.py
|
||||
|
||||
or
|
||||
|
||||
$ python run_benchmark.py
|
||||
|
||||
Run the help command to see options available
|
||||
|
||||
$ ./run_benchmark.py --help
|
||||
|
||||
Benchmarking your Agent
|
||||
---------------------
|
||||
The benchmark works by calling three lines of code
|
||||
|
||||
corl = CoRL2017(city_name=args.city_name, name_to_save=args.log_name)
|
||||
agent = Manual(args.city_name)
|
||||
results = corl.benchmark_agent(agent, client)
|
||||
|
||||
This is excerpt is executed in the [run_benchmark.py](https://github.com/carla-simulator/carla/blob/master/PythonClient/run_benchmark.py) example.
|
||||
|
||||
First a *benchmark* object is defined, for this case, a CoRL2017 benchmark. This is object is used to benchmark a certain Agent. <br>
|
||||
On the second line of our sample code, there is an object of a Manual class instanced. This class inherited an Agent base class
|
||||
that is used by the *benchmark* object.
|
||||
To be benchmarked, an Agent subclass must redefine the *run_step* function as it is done in the following excerpt:
|
||||
|
||||
def run_step(self, measurements, sensor_data, target):
|
||||
"""
|
||||
Function to run a control step in the CARLA vehicle.
|
||||
:param measurements: object of the Measurements type
|
||||
:param sensor_data: images list object
|
||||
:param target: target position of Transform type
|
||||
:return: an object of the control type.
|
||||
"""
|
||||
control = VehicleControl()
|
||||
control.throttle = 0.9
|
||||
return control
|
||||
The function receives measurements from the world, sensor data and a target position. With this, the function must return a control to the car, *i.e.* steering value, throttle value, brake value, etc.
|
||||
|
||||
The [measurements](measurements.md), [target](measurements.md), [sensor_data](cameras_and_sensors.md) and [control](measurements.md) types are described on the documentation.
|
||||
|
||||
|
||||
|
||||
Creating your Benchmark
|
||||
---------------------
|
||||
Tutorial to be added
|
|
@ -0,0 +1,25 @@
|
|||
Coding standard
|
||||
===============
|
||||
|
||||
> _This document is a work in progress and might be incomplete._
|
||||
|
||||
General
|
||||
-------
|
||||
|
||||
* Use spaces, not tabs.
|
||||
* Avoid adding trailing whitespace as it creates noise in the diffs.
|
||||
* Comments should not exceed 80 columns, code may exceed this limit a bit in rare occasions if it results in clearer code.
|
||||
|
||||
Python
|
||||
------
|
||||
|
||||
* All code must be compatible with Python 2.7, 3.5, and 3.6.
|
||||
* [Pylint](https://www.pylint.org/) should not give any error or warning (few exceptions apply with external classes like `numpy`, see our `.pylintrc`).
|
||||
* Python code follows [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/) (use `autopep8` whenever possible).
|
||||
|
||||
C++
|
||||
---
|
||||
|
||||
* Compilation should not give any error or warning (`clang++ -Wall -Wextra -std=C++14`).
|
||||
* Unreal C++ code (CarlaUE4 and Carla plugin) follow the [Unreal Engine's Coding Standard](https://docs.unrealengine.com/latest/INT/Programming/Development/CodingStandard/) with the exception of using spaces instead of tabs.
|
||||
* CarlaServer uses [Google's style guide](https://google.github.io/styleguide/cppguide.html).
|
138
Docs/faq.md
138
Docs/faq.md
|
@ -1,7 +1,20 @@
|
|||
CARLA F.A.Q.
|
||||
============
|
||||
<!-- ======================================================================= -->
|
||||
<details>
|
||||
<summary><h5 style="display:inline">
|
||||
What is the recommended hardware to run CARLA?
|
||||
</h4></summary>
|
||||
|
||||
#### What is the expected disk space needed for building CARLA?
|
||||
CARLA is a very performance demanding software, at the very minimum you would
|
||||
need a computer with a dedicated GPU capable of running Unreal Engine. See
|
||||
[Unreal Engine's recommended hardware](https://wiki.unrealengine.com/Recommended_Hardware).
|
||||
|
||||
</details>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<details>
|
||||
<summary><h5 style="display:inline">
|
||||
What is the expected disk space needed for building CARLA?
|
||||
</h4></summary>
|
||||
|
||||
Building CARLA from source requires about 15GB of disk space, not counting
|
||||
Unreal Engine installation.
|
||||
|
@ -10,24 +23,27 @@ However, you will also need to build and install Unreal Engine, which on Linux
|
|||
requires much more disk space as it keeps all the intermediate files,
|
||||
[see this thread](https://answers.unrealengine.com/questions/430541/linux-engine-size.html).
|
||||
|
||||
#### Is it possible to dump images from the CARLA server view?
|
||||
</details>
|
||||
|
||||
Yes, this is an Unreal Engine feature. You can dump the images of the server
|
||||
camera by running CARLA with
|
||||
|
||||
$ ./CarlaUE4.sh -benchmark -fps=30 -dumpmovie
|
||||
|
||||
Images are saved to "CarlaUE4/Saved/Screenshots/LinuxNoEditor".
|
||||
|
||||
#### I downloaded CARLA source from GitHub, where is the "CarlaUE4.sh" script?
|
||||
<!-- ======================================================================= -->
|
||||
<details>
|
||||
<summary><h5 style="display:inline">
|
||||
I downloaded CARLA source from GitHub, where is the "CarlaUE4.sh" script?
|
||||
</h4></summary>
|
||||
|
||||
There is no "CarlaUE4.sh" script in the source version of CARLA, you need to
|
||||
follow the instructions in the [documentation](http://carla.readthedocs.io) on
|
||||
follow the instructions in the [documentation](http://carla.readthedocs.io) for
|
||||
building CARLA from source.
|
||||
|
||||
Once you open the project in the Unreal Editor, you can hit Play to test CARLA.
|
||||
|
||||
#### Can I skip the download step in Setup.sh?
|
||||
</details>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<details>
|
||||
<summary><h5 style="display:inline">
|
||||
Setup.sh fails to download content, can I skip this step?
|
||||
</h4></summary>
|
||||
|
||||
It is possible to skip the download step by passing the `-s` argument to the
|
||||
setup script
|
||||
|
@ -40,9 +56,99 @@ for instructions or run
|
|||
|
||||
$ ./Update.sh -s
|
||||
|
||||
#### How can I create a binary version of CARLA?
|
||||
</details>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<details>
|
||||
<summary><h5 style="display:inline">
|
||||
Can I run the server from within Unreal Editor?
|
||||
</h4></summary>
|
||||
|
||||
Yes, you can connect the Python client to a server running within Unreal Editor
|
||||
as if it was the standalone server.
|
||||
|
||||
Go to **"Unreal/CarlaUE4/Config/CarlaSettings.ini"** (this file should have been
|
||||
created by the Setup.sh) and enable networking. If for whatever reason you don't
|
||||
have this file, just create it and add the following
|
||||
|
||||
```ini
|
||||
[CARLA/Server]
|
||||
UseNetworking=true
|
||||
```
|
||||
|
||||
Now when you hit Play the editor will hang until a client connects.
|
||||
|
||||
</details>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<details>
|
||||
<summary><h5 style="display:inline">
|
||||
Why Unreal Editor hangs after hitting Play?
|
||||
</h4></summary>
|
||||
|
||||
This is most probably happening because CARLA is starting in server mode. Check
|
||||
your **"Unreal/CarlaUE4/Config/CarlaSettings.ini"** and set
|
||||
|
||||
```ini
|
||||
[CARLA/Server]
|
||||
UseNetworking=false
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<details>
|
||||
<summary><h5 style="display:inline">
|
||||
How can I create a binary version of CARLA?
|
||||
</h4></summary>
|
||||
|
||||
To compile a binary (packaged) version of CARLA, open the CarlaUE4 project with
|
||||
Unreal Editor, go to the menu “File -> Package Project”, and select your
|
||||
Unreal Editor, go to the menu "File -> Package Project", and select your
|
||||
platform. This takes a while, but in the end it should generate a packaged
|
||||
version of CARLA to execute without Unreal Editor.
|
||||
|
||||
</details>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<details>
|
||||
<summary><h5 style="display:inline">
|
||||
Why do I have very low FPS when running the server in Unreal Editor?
|
||||
</h4></summary>
|
||||
|
||||
UE4 Editor goes to a low performance mode when out of focus. It can be disabled
|
||||
in the editor preferences. Go to "Edit->Editor Preferences->Performance" and
|
||||
disable the "Use Less CPU When in Background" option.
|
||||
|
||||
</details>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<details>
|
||||
<summary><h5 style="display:inline">
|
||||
Is it possible to dump images from the CARLA server view?
|
||||
</h4></summary>
|
||||
|
||||
Yes, this is an Unreal Engine feature. You can dump the images of the server
|
||||
camera by running CARLA with
|
||||
|
||||
$ ./CarlaUE4.sh -benchmark -fps=30 -dumpmovie
|
||||
|
||||
Images are saved to "CarlaUE4/Saved/Screenshots/LinuxNoEditor".
|
||||
|
||||
</details>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<details>
|
||||
<summary><h5 style="display:inline">
|
||||
Fatal error: 'version.h' has been modified since the precompiled header.
|
||||
</h4></summary>
|
||||
|
||||
This happens from time to time due to Linux updates. It is possible to force a
|
||||
rebuild of all the project files with
|
||||
|
||||
$ cd Unreal/CarlaUE4/
|
||||
$ make CarlaUE4Editor ARGS=-clean
|
||||
$ make CarlaUE4Editor
|
||||
|
||||
It takes a long time but fixes the issue. Sometimes a reboot is also needed.
|
||||
|
||||
</details>
|
||||
|
|
|
@ -38,15 +38,9 @@ The "carla" Python module provides a basic API for communicating with the CARLA
|
|||
server. In the "PythonClient" folder we provide a couple of examples on how to
|
||||
use this API. We recommend Python 3, but they are also compatible with Python 2.
|
||||
|
||||
The basic functionality requires only the protobuf module to be installed
|
||||
Install the dependencies with
|
||||
|
||||
$ sudo apt-get install python3 python3-pip
|
||||
$ sudo pip3 install protobuf
|
||||
|
||||
However, other operations as handling images require some extra modules, and the
|
||||
"manual_control.py" example requires pygame
|
||||
|
||||
$ sudo pip3 install numpy Pillow pygame
|
||||
$ pip install -r PythonClient/requirements.txt
|
||||
|
||||
The script "PythonClient/client_example.py" provides basic functionality for
|
||||
controlling the vehicle and saving images to disk. Run the help command to see
|
||||
|
|
|
@ -7,8 +7,8 @@ CARLA Documentation
|
|||
* [CARLA settings](carla_settings.md)
|
||||
* [Measurements](measurements.md)
|
||||
* [Cameras and sensors](cameras_and_sensors.md)
|
||||
* [Benchmark](benchmark.md)
|
||||
* [F.A.Q.](faq.md)
|
||||
* [Troubleshooting](troubleshooting.md)
|
||||
|
||||
#### Building from source
|
||||
|
||||
|
@ -19,6 +19,8 @@ CARLA Documentation
|
|||
#### Contributing
|
||||
|
||||
* [Contribution guidelines](CONTRIBUTING.md)
|
||||
* [Coding standard](coding_standard.md)
|
||||
* [Code of conduct](CODE_OF_CONDUCT.md)
|
||||
|
||||
#### Development
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<!--
|
||||
|
||||
Thanks for contributing to CARLA!
|
||||
|
||||
If you are asking a question please make sure your question was not asked before
|
||||
by searching among the existing issues. Also make sure you have read our
|
||||
documentation and FAQ at carla.readthedocs.io.
|
||||
|
||||
-->
|
|
@ -0,0 +1,32 @@
|
|||
<!--
|
||||
|
||||
Thanks for sending a pull request! Please make sure you click the link above to
|
||||
view the contribution guidelines, then fill out the blanks below.
|
||||
|
||||
Checklist:
|
||||
|
||||
- [ ] Your branch is up-to-date with the `master` branch and tested with latest changes
|
||||
- [ ] Extended the README / documentation, if necessary
|
||||
- [ ] Code compiles correctly
|
||||
- [ ] All tests passing
|
||||
- [ ] `make check`
|
||||
- [ ] `pylint --disable=R,C --rcfile=PythonClient/.pylintrc PythonClient/carla PythonClient/*.py`
|
||||
- [ ] `cppcheck . -iBuild -i.pb.cc --enable=warning`
|
||||
|
||||
-->
|
||||
|
||||
#### Description
|
||||
|
||||
<!-- Please explain the changes you made here as detailed as possible. -->
|
||||
|
||||
Fixes # <!-- If fixes an issue, please add here the issue number. -->
|
||||
|
||||
#### Where has this been tested?
|
||||
|
||||
* **Platform(s):** ...
|
||||
* **Python version(s):** ...
|
||||
* **Unreal Engine version(s):** ...
|
||||
|
||||
#### Possible Drawbacks
|
||||
|
||||
<!-- What are the possible side-effects or negative impacts of the code change? -->
|
|
@ -1,41 +0,0 @@
|
|||
Troubleshooting
|
||||
===============
|
||||
|
||||
#### Editor hangs after hitting Play
|
||||
|
||||
This is most probably happening because CARLA is started in server mode. Check
|
||||
in your CarlaSettings.ini file ("./Unreal/CarlaUE4/Config/CarlaSettings.ini")
|
||||
and set
|
||||
|
||||
```ini
|
||||
[CARLA/Server]
|
||||
UseNetworking=false
|
||||
```
|
||||
|
||||
#### Very low FPS in editor when not in focus
|
||||
|
||||
UE4 Editor goes to a low performance mode when out of focus. It can be disabled
|
||||
in the editor preferences. Go to "Edit->Editor Preferences->Performance" and
|
||||
disable the "Use Less CPU When in Background" option.
|
||||
|
||||
#### Fatal error: file '/usr/include/linux/version.h' has been modified since the precompiled header
|
||||
|
||||
This happens from time to time due to Linux updates. It is possible to force a
|
||||
rebuild of all the project files with
|
||||
|
||||
$ cd Unreal/CarlaUE4/
|
||||
$ make CarlaUE4Editor ARGS=-clean
|
||||
$ make CarlaUE4Editor
|
||||
|
||||
#### Setup.sh fails to download content
|
||||
|
||||
It is possible to skip the download step by passing the `-s` argument to the
|
||||
setup script
|
||||
|
||||
$ ./Setup.sh -s
|
||||
|
||||
Bear in mind that if you do so, you are supposed to manually download and
|
||||
extract the content package yourself, check out the last output of the Setup.sh
|
||||
for instructions or run
|
||||
|
||||
$ ./Update.sh -s
|
2
LICENSE
2
LICENSE
|
@ -1,7 +1,7 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
Barcelona (UAB).
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[pep8]
|
||||
max-line-length = 120
|
|
@ -0,0 +1,2 @@
|
|||
include carla/planner/*.txt
|
||||
include carla/planner/*.png
|
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env python2
|
||||
# -*- coding: utf-8 -*-
|
||||
# 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>.
|
||||
# @author: german,felipecode
|
||||
|
||||
|
||||
from __future__ import print_function
|
||||
import abc
|
||||
|
||||
from carla.planner.planner import Planner
|
||||
|
||||
|
||||
class Agent(object):
|
||||
def __init__(self, city_name):
|
||||
self.__metaclass__ = abc.ABCMeta
|
||||
self._planner = Planner(city_name)
|
||||
|
||||
def get_distance(self, start_point, end_point):
|
||||
path_distance = self._planner.get_shortest_path_distance(
|
||||
[start_point.location.x, start_point.location.y, 22]
|
||||
, [start_point.orientation.x, start_point.orientation.y, 22]
|
||||
, [end_point.location.x, end_point.location.y, 22]
|
||||
, [end_point.orientation.x, end_point.orientation.y, 22])
|
||||
# We calculate the timout based on the distance
|
||||
|
||||
return path_distance
|
||||
|
||||
@abc.abstractmethod
|
||||
def run_step(self, measurements, sensor_data, target):
|
||||
"""
|
||||
Function to be redefined by an agent.
|
||||
:param The measurements like speed, the image data and a target
|
||||
:returns A carla Control object, with the steering/gas/brake for the agent
|
||||
"""
|
|
@ -0,0 +1,377 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# 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>.
|
||||
|
||||
|
||||
import csv
|
||||
import datetime
|
||||
import math
|
||||
import os
|
||||
import abc
|
||||
import logging
|
||||
|
||||
|
||||
from builtins import input as input_data
|
||||
|
||||
|
||||
from carla.client import VehicleControl
|
||||
|
||||
def sldist(c1, c2):
|
||||
return math.sqrt((c2[0] - c1[0])**2 + (c2[1] - c1[1])**2)
|
||||
|
||||
|
||||
class Benchmark(object):
|
||||
|
||||
"""
|
||||
The Benchmark class, controls the execution of the benchmark by an
|
||||
Agent class.
|
||||
The benchmark class must be inherited
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
city_name,
|
||||
name_to_save,
|
||||
continue_experiment=False,
|
||||
save_images=False
|
||||
):
|
||||
|
||||
|
||||
self.__metaclass__ = abc.ABCMeta
|
||||
|
||||
self._city_name = city_name
|
||||
|
||||
|
||||
|
||||
self._base_name = name_to_save
|
||||
self._dict_stats = {'exp_id': -1,
|
||||
'rep': -1,
|
||||
'weather': -1,
|
||||
'start_point': -1,
|
||||
'end_point': -1,
|
||||
'result': -1,
|
||||
'initial_distance': -1,
|
||||
'final_distance': -1,
|
||||
'final_time': -1,
|
||||
'time_out': -1
|
||||
}
|
||||
|
||||
self._dict_rewards = {'exp_id': -1,
|
||||
'rep': -1,
|
||||
'weather': -1,
|
||||
'collision_gen': -1,
|
||||
'collision_ped': -1,
|
||||
'collision_car': -1,
|
||||
'lane_intersect': -1,
|
||||
'sidewalk_intersect': -1,
|
||||
'pos_x': -1,
|
||||
'pos_y': -1
|
||||
}
|
||||
|
||||
|
||||
self._experiments = self._build_experiments()
|
||||
# Create the log files and get the names
|
||||
self._suffix_name, self._full_name = self._create_log_record(name_to_save, self._experiments)
|
||||
# Get the line for the experiment to be continued
|
||||
self._line_on_file = self._continue_experiment(continue_experiment)
|
||||
|
||||
|
||||
|
||||
self._save_images = save_images
|
||||
self._image_filename_format = os.path.join(
|
||||
self._full_name, '_images/episode_{:s}/{:s}/image_{:0>5d}.jpg')
|
||||
|
||||
def run_navigation_episode(
|
||||
self,
|
||||
agent,
|
||||
carla,
|
||||
time_out,
|
||||
target,
|
||||
episode_name):
|
||||
|
||||
measurements, sensor_data = carla.read_data()
|
||||
carla.send_control(VehicleControl())
|
||||
|
||||
t0 = measurements.game_timestamp
|
||||
t1 = t0
|
||||
success = False
|
||||
measurement_vec = []
|
||||
frame = 0
|
||||
distance = 10000
|
||||
|
||||
while(t1 - t0) < (time_out * 1000) and not success:
|
||||
measurements, sensor_data = carla.read_data()
|
||||
|
||||
control = agent.run_step(measurements, sensor_data, target)
|
||||
|
||||
logging.info("Controller is Inputting:")
|
||||
logging.info('Steer = %f Throttle = %f Brake = %f ',
|
||||
control.steer, control.throttle, control.brake)
|
||||
|
||||
carla.send_control(control)
|
||||
|
||||
# measure distance to target
|
||||
if self._save_images:
|
||||
for name, image in sensor_data.items():
|
||||
image.save_to_disk(self._image_filename_format.format(
|
||||
episode_name, name, frame))
|
||||
|
||||
curr_x = measurements.player_measurements.transform.location.x
|
||||
curr_y = measurements.player_measurements.transform.location.y
|
||||
|
||||
measurement_vec.append(measurements.player_measurements)
|
||||
|
||||
t1 = measurements.game_timestamp
|
||||
|
||||
distance = sldist([curr_x, curr_y],
|
||||
[target.location.x, target.location.y])
|
||||
|
||||
logging.info('Status:')
|
||||
logging.info(
|
||||
'[d=%f] c_x = %f, c_y = %f ---> t_x = %f, t_y = %f',
|
||||
float(distance), curr_x, curr_y, target.location.x,
|
||||
target.location.y)
|
||||
|
||||
if distance < 200.0:
|
||||
success = True
|
||||
|
||||
frame += 1
|
||||
|
||||
if success:
|
||||
return 1, measurement_vec, float(t1 - t0) / 1000.0, distance
|
||||
return 0, measurement_vec, time_out, distance
|
||||
|
||||
def benchmark_agent(self, agent, carla):
|
||||
|
||||
if self._line_on_file == 0:
|
||||
# The fixed name considering all the experiments being run
|
||||
with open(os.path.join(self._full_name,
|
||||
self._suffix_name), 'w') as ofd:
|
||||
|
||||
w = csv.DictWriter(ofd, self._dict_stats.keys())
|
||||
w.writeheader()
|
||||
|
||||
with open(os.path.join(self._full_name,
|
||||
'details_' + self._suffix_name), 'w') as rfd:
|
||||
|
||||
rw = csv.DictWriter(rfd, self._dict_rewards.keys())
|
||||
rw.writeheader()
|
||||
start_task = 0
|
||||
start_pose = 0
|
||||
else:
|
||||
(start_task, start_pose) = self._get_pose_and_task(self._line_on_file)
|
||||
|
||||
logging.info(' START ')
|
||||
|
||||
for experiment in self._experiments[start_task:]:
|
||||
|
||||
positions = carla.load_settings(
|
||||
experiment.conditions).player_start_spots
|
||||
|
||||
for pose in experiment.poses[start_pose:]:
|
||||
for rep in range(experiment.repetitions):
|
||||
|
||||
start_point = pose[0]
|
||||
end_point = pose[1]
|
||||
|
||||
carla.start_episode(start_point)
|
||||
|
||||
logging.info('======== !!!! ==========')
|
||||
logging.info(' Start Position %d End Position %d ',
|
||||
start_point, end_point)
|
||||
|
||||
path_distance = agent.get_distance(
|
||||
positions[start_point], positions[end_point])
|
||||
euclidean_distance = \
|
||||
sldist([positions[start_point].location.x, positions[start_point].location.y],
|
||||
[positions[end_point].location.x, positions[end_point].location.y])
|
||||
|
||||
time_out = self._calculate_time_out(path_distance)
|
||||
# running the agent
|
||||
(result, reward_vec, final_time, remaining_distance) = \
|
||||
self.run_navigation_episode(
|
||||
agent, carla, time_out, positions[end_point],
|
||||
str(experiment.Conditions.WeatherId) + '_'
|
||||
+ str(experiment.id) + '_' + str(start_point)
|
||||
+ '.' + str(end_point))
|
||||
|
||||
# compute stats for the experiment
|
||||
|
||||
self._write_summary_results(
|
||||
experiment, pose, rep, euclidean_distance,
|
||||
remaining_distance, final_time, time_out, result)
|
||||
|
||||
self._write_details_results(experiment, rep, reward_vec)
|
||||
|
||||
if(result > 0):
|
||||
logging.info('+++++ Target achieved in %f seconds! +++++',
|
||||
final_time)
|
||||
else:
|
||||
logging.info('----- Timeout! -----')
|
||||
return self.get_all_statistics()
|
||||
|
||||
def _write_summary_results(self, experiment, pose, rep,
|
||||
path_distance, remaining_distance,
|
||||
final_time, time_out, result):
|
||||
|
||||
self._dict_stats['exp_id'] = experiment.id
|
||||
self._dict_stats['rep'] = rep
|
||||
self._dict_stats['weather'] = experiment.Conditions.WeatherId
|
||||
self._dict_stats['start_point'] = pose[0]
|
||||
self._dict_stats['end_point'] = pose[1]
|
||||
self._dict_stats['result'] = result
|
||||
self._dict_stats['initial_distance'] = path_distance
|
||||
self._dict_stats['final_distance'] = remaining_distance
|
||||
self._dict_stats['final_time'] = final_time
|
||||
self._dict_stats['time_out'] = time_out
|
||||
|
||||
with open(os.path.join(self._full_name, self._suffix_name), 'a+') as ofd:
|
||||
|
||||
w = csv.DictWriter(ofd, self._dict_stats.keys())
|
||||
|
||||
w.writerow(self._dict_stats)
|
||||
|
||||
def _write_details_results(self, experiment, rep, reward_vec):
|
||||
|
||||
with open(os.path.join(self._full_name,
|
||||
'details_' + self._suffix_name), 'a+') as rfd:
|
||||
|
||||
rw = csv.DictWriter(rfd, self._dict_rewards.keys())
|
||||
|
||||
for i in range(len(reward_vec)):
|
||||
self._dict_rewards['exp_id'] = experiment.id
|
||||
self._dict_rewards['rep'] = rep
|
||||
self._dict_rewards['weather'] = experiment.Conditions.WeatherId
|
||||
self._dict_rewards['collision_gen'] = reward_vec[
|
||||
i].collision_other
|
||||
self._dict_rewards['collision_ped'] = reward_vec[
|
||||
i].collision_pedestrians
|
||||
self._dict_rewards['collision_car'] = reward_vec[
|
||||
i].collision_vehicles
|
||||
self._dict_rewards['lane_intersect'] = reward_vec[
|
||||
i].intersection_otherlane
|
||||
self._dict_rewards['sidewalk_intersect'] = reward_vec[
|
||||
i].intersection_offroad
|
||||
self._dict_rewards['pos_x'] = reward_vec[
|
||||
i].transform.location.x
|
||||
self._dict_rewards['pos_y'] = reward_vec[
|
||||
i].transform.location.y
|
||||
|
||||
rw.writerow(self._dict_rewards)
|
||||
|
||||
def _create_log_record(self, base_name, experiments):
|
||||
"""
|
||||
This function creates the log files for the benchmark.
|
||||
|
||||
"""
|
||||
suffix_name = self._get_experiments_names(experiments)
|
||||
full_name = os.path.join('_benchmarks_results',
|
||||
base_name + '_'
|
||||
+ self._get_details() + '/')
|
||||
|
||||
folder = os.path.dirname(full_name)
|
||||
if not os.path.isdir(folder):
|
||||
os.makedirs(folder)
|
||||
|
||||
# Make a date file: to show when this was modified,
|
||||
# the number of times the experiments were run
|
||||
now = datetime.datetime.now()
|
||||
open(os.path.join(full_name, now.strftime("%Y%m%d%H%M")),'w').close()
|
||||
|
||||
return suffix_name, full_name
|
||||
|
||||
|
||||
def _continue_experiment(self, continue_experiment):
|
||||
|
||||
if self._experiment_exist():
|
||||
|
||||
if continue_experiment:
|
||||
line_on_file = self._get_last_position()
|
||||
|
||||
else:
|
||||
# Ask question, to avoid mistaken override situations
|
||||
answer = input_data("The experiment was already found in the files"
|
||||
+ ", Do you want to continue (y/n)? \n"
|
||||
)
|
||||
if answer == 'Yes' or answer == 'y':
|
||||
line_on_file = self._get_last_position()
|
||||
else:
|
||||
line_on_file = 0
|
||||
|
||||
else:
|
||||
line_on_file = 0
|
||||
|
||||
return line_on_file
|
||||
|
||||
|
||||
|
||||
def _experiment_exist(self):
|
||||
return os.path.isfile(self._full_name)
|
||||
|
||||
def _get_last_position(self):
|
||||
|
||||
with open(os.path.join(self._full_name, self._suffix_name)) as f:
|
||||
return sum(1 for _ in f)
|
||||
|
||||
|
||||
# To be redefined on subclasses on how to calculate timeout for an episode
|
||||
@abc.abstractmethod
|
||||
def _calculate_time_out(self, distance):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_details(self):
|
||||
"""
|
||||
Get details
|
||||
:return: a string with name and town of the subclass
|
||||
"""
|
||||
@abc.abstractmethod
|
||||
def _build_experiments(self):
|
||||
"""
|
||||
Returns a set of experiments to be evaluated
|
||||
Must be redefined in an inherited class.
|
||||
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_all_statistics(self):
|
||||
"""
|
||||
Get the statistics of the evaluated experiments
|
||||
:return:
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_pose_and_task(self, line_on_file):
|
||||
"""
|
||||
Parse the experiment depending on number of poses and tasks
|
||||
"""
|
||||
|
||||
|
||||
@abc.abstractmethod
|
||||
def plot_summary_train(self):
|
||||
"""
|
||||
returns the summary for the train weather/task episodes
|
||||
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def plot_summary_test(self):
|
||||
"""
|
||||
returns the summary for the test weather/task episodes
|
||||
|
||||
"""
|
||||
@staticmethod
|
||||
def _get_experiments_names(experiments):
|
||||
|
||||
name_cat = 'w'
|
||||
|
||||
for experiment in experiments:
|
||||
|
||||
name_cat += str(experiment.Conditions.WeatherId) + '.'
|
||||
|
||||
return name_cat
|
||||
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
# 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>.
|
||||
|
||||
# CORL experiment set.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
|
||||
from .benchmark import Benchmark
|
||||
from .experiment import Experiment
|
||||
from carla.sensor import Camera
|
||||
from carla.settings import CarlaSettings
|
||||
|
||||
from .metrics import compute_summary
|
||||
|
||||
|
||||
class CoRL2017(Benchmark):
|
||||
|
||||
def get_all_statistics(self):
|
||||
|
||||
summary = compute_summary(os.path.join(
|
||||
self._full_name, self._suffix_name), [3])
|
||||
|
||||
return summary
|
||||
|
||||
def plot_summary_train(self):
|
||||
|
||||
self._plot_summary([1.0, 3.0, 6.0, 8.0])
|
||||
|
||||
def plot_summary_test(self):
|
||||
|
||||
self._plot_summary([4.0, 14.0])
|
||||
|
||||
def _plot_summary(self, weathers):
|
||||
"""
|
||||
We plot the summary of the testing for the set selected weathers.
|
||||
The test weathers are [4,14]
|
||||
|
||||
"""
|
||||
|
||||
metrics_summary = compute_summary(os.path.join(
|
||||
self._full_name, self._suffix_name), [3])
|
||||
|
||||
for metric, values in metrics_summary.items():
|
||||
|
||||
print('Metric : ', metric)
|
||||
for weather, tasks in values.items():
|
||||
if weather in set(weathers):
|
||||
print(' Weather: ', weather)
|
||||
count = 0
|
||||
for t in tasks:
|
||||
print(' Task ', count, ' -> ', t)
|
||||
count += 1
|
||||
|
||||
print(' AvG -> ', float(sum(tasks)) / float(len(tasks)))
|
||||
|
||||
def _calculate_time_out(self, distance):
|
||||
"""
|
||||
Function to return the timeout ( in miliseconds) that is calculated based on distance to goal.
|
||||
This is the same timeout as used on the CoRL paper.
|
||||
"""
|
||||
|
||||
return ((distance / 100000.0) / 10.0) * 3600.0 + 10.0
|
||||
|
||||
def _poses_town01(self):
|
||||
"""
|
||||
Each matrix is a new task. We have all the four tasks
|
||||
|
||||
"""
|
||||
|
||||
def _poses_straight():
|
||||
return [[36, 40], [39, 35], [110, 114], [7, 3], [0, 4],
|
||||
[68, 50], [61, 59], [47, 64], [147, 90], [33, 87],
|
||||
[26, 19], [80, 76], [45, 49], [55, 44], [29, 107],
|
||||
[95, 104], [84, 34], [53, 67], [22, 17], [91, 148],
|
||||
[20, 107], [78, 70], [95, 102], [68, 44], [45, 69]]
|
||||
|
||||
def _poses_one_curve():
|
||||
return [[138, 17], [47, 16], [26, 9], [42, 49], [140, 124],
|
||||
[85, 98], [65, 133], [137, 51], [76, 66], [46, 39],
|
||||
[40, 60], [0, 29], [4, 129], [121, 140], [2, 129],
|
||||
[78, 44], [68, 85], [41, 102], [95, 70], [68, 129],
|
||||
[84, 69], [47, 79], [110, 15], [130, 17], [0, 17]]
|
||||
|
||||
def _poses_navigation():
|
||||
return [[105, 29], [27, 130], [102, 87], [132, 27], [24, 44],
|
||||
[96, 26], [34, 67], [28, 1], [140, 134], [105, 9],
|
||||
[148, 129], [65, 18], [21, 16], [147, 97], [42, 51],
|
||||
[30, 41], [18, 107], [69, 45], [102, 95], [18, 145],
|
||||
[111, 64], [79, 45], [84, 69], [73, 31], [37, 81]]
|
||||
|
||||
return [_poses_straight(),
|
||||
_poses_one_curve(),
|
||||
_poses_navigation(),
|
||||
_poses_navigation()]
|
||||
|
||||
def _poses_town02(self):
|
||||
|
||||
def _poses_straight():
|
||||
return [[38, 34], [4, 2], [12, 10], [62, 55], [43, 47],
|
||||
[64, 66], [78, 76], [59, 57], [61, 18], [35, 39],
|
||||
[12, 8], [0, 18], [75, 68], [54, 60], [45, 49],
|
||||
[46, 42], [53, 46], [80, 29], [65, 63], [0, 81],
|
||||
[54, 63], [51, 42], [16, 19], [17, 26], [77, 68]]
|
||||
|
||||
def _poses_one_curve():
|
||||
return [[37, 76], [8, 24], [60, 69], [38, 10], [21, 1],
|
||||
[58, 71], [74, 32], [44, 0], [71, 16], [14, 24],
|
||||
[34, 11], [43, 14], [75, 16], [80, 21], [3, 23],
|
||||
[75, 59], [50, 47], [11, 19], [77, 34], [79, 25],
|
||||
[40, 63], [58, 76], [79, 55], [16, 61], [27, 11]]
|
||||
|
||||
def _poses_navigation():
|
||||
return [[19, 66], [79, 14], [19, 57], [23, 1],
|
||||
[53, 76], [42, 13], [31, 71], [33, 5],
|
||||
[54, 30], [10, 61], [66, 3], [27, 12],
|
||||
[79, 19], [2, 29], [16, 14], [5, 57],
|
||||
[70, 73], [46, 67], [57, 50], [61, 49], [21, 12],
|
||||
[51, 81], [77, 68], [56, 65], [43, 54]]
|
||||
|
||||
return [_poses_straight(),
|
||||
_poses_one_curve(),
|
||||
_poses_navigation(),
|
||||
_poses_navigation()
|
||||
]
|
||||
|
||||
def _build_experiments(self):
|
||||
"""
|
||||
Creates the whole set of experiment objects,
|
||||
The experiments created depend on the selected Town.
|
||||
"""
|
||||
|
||||
# We set the camera
|
||||
# This single RGB camera is used on every experiment
|
||||
|
||||
camera = Camera('CameraRGB')
|
||||
camera.set(CameraFOV=100)
|
||||
|
||||
camera.set_image_size(800, 600)
|
||||
|
||||
camera.set_position(200, 0, 140)
|
||||
camera.set_rotation(-15.0, 0, 0)
|
||||
|
||||
weathers = [1, 3, 6, 8, 4, 14]
|
||||
if self._city_name == 'Town01':
|
||||
poses_tasks = self._poses_town01()
|
||||
vehicles_tasks = [0, 0, 0, 20]
|
||||
pedestrians_tasks = [0, 0, 0, 50]
|
||||
else:
|
||||
poses_tasks = self._poses_town02()
|
||||
vehicles_tasks = [0, 0, 0, 15]
|
||||
pedestrians_tasks = [0, 0, 0, 50]
|
||||
|
||||
experiments_vector = []
|
||||
|
||||
for weather in weathers:
|
||||
|
||||
for iteration in range(len(poses_tasks)):
|
||||
poses = poses_tasks[iteration]
|
||||
vehicles = vehicles_tasks[iteration]
|
||||
pedestrians = pedestrians_tasks[iteration]
|
||||
|
||||
conditions = CarlaSettings()
|
||||
conditions.set(
|
||||
SynchronousMode=True,
|
||||
SendNonPlayerAgentsInfo=True,
|
||||
NumberOfVehicles=vehicles,
|
||||
NumberOfPedestrians=pedestrians,
|
||||
WeatherId=weather,
|
||||
SeedVehicles=123456789,
|
||||
SeedPedestrians=123456789
|
||||
)
|
||||
# Add all the cameras that were set for this experiments
|
||||
|
||||
conditions.add_sensor(camera)
|
||||
|
||||
experiment = Experiment()
|
||||
experiment.set(
|
||||
Conditions=conditions,
|
||||
Poses=poses,
|
||||
Id=iteration,
|
||||
Repetitions=1
|
||||
)
|
||||
experiments_vector.append(experiment)
|
||||
|
||||
return experiments_vector
|
||||
|
||||
def _get_details(self):
|
||||
|
||||
# Function to get automatic information from the experiment for writing purposes
|
||||
return 'corl2017_' + self._city_name
|
||||
|
||||
def _get_pose_and_task(self, line_on_file):
|
||||
"""
|
||||
Returns the pose and task this experiment is, based on the line it was
|
||||
on the log file.
|
||||
"""
|
||||
# We assume that the number of poses is constant
|
||||
return int(line_on_file / len(self._experiments)), line_on_file % 25
|
|
@ -0,0 +1,38 @@
|
|||
# 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>.
|
||||
|
||||
from carla.settings import CarlaSettings
|
||||
|
||||
|
||||
class Experiment(object):
|
||||
|
||||
def __init__(self):
|
||||
self.Id = ''
|
||||
self.Conditions = CarlaSettings()
|
||||
self.Poses = [[]]
|
||||
self.Repetitions = 1
|
||||
|
||||
def set(self, **kwargs):
|
||||
for key, value in kwargs.items():
|
||||
if not hasattr(self, key):
|
||||
raise ValueError('Experiment: no key named %r' % key)
|
||||
setattr(self, key, value)
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self.Id
|
||||
|
||||
@property
|
||||
def conditions(self):
|
||||
return self.Conditions
|
||||
|
||||
@property
|
||||
def poses(self):
|
||||
return self.Poses
|
||||
|
||||
@property
|
||||
def repetitions(self):
|
||||
return self.Repetitions
|
|
@ -0,0 +1,205 @@
|
|||
# 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>.
|
||||
|
||||
|
||||
import numpy as np
|
||||
import math
|
||||
import os
|
||||
|
||||
|
||||
sldist = lambda c1, c2: math.sqrt((c2[0] - c1[0])**2 + (c2[1] - c1[1])**2)
|
||||
flatten = lambda l: [item for sublist in l for item in sublist]
|
||||
|
||||
|
||||
def get_colisions(selected_matrix, header):
|
||||
|
||||
count_gen = 0
|
||||
count_ped = 0
|
||||
count_car = 0
|
||||
i = 1
|
||||
|
||||
while i < selected_matrix.shape[0]:
|
||||
if (selected_matrix[i, header.index('collision_gen')]
|
||||
- selected_matrix[(i-10), header.index('collision_gen')]) > 40000:
|
||||
count_gen += 1
|
||||
i += 20
|
||||
i += 1
|
||||
|
||||
i = 1
|
||||
while i < selected_matrix.shape[0]:
|
||||
if (selected_matrix[i, header.index('collision_car')]
|
||||
- selected_matrix[(i-10), header.index('collision_car')]) > 40000:
|
||||
count_car += 1
|
||||
i += 30
|
||||
i += 1
|
||||
|
||||
i = 1
|
||||
while i < selected_matrix.shape[0]:
|
||||
if (selected_matrix[i, header.index('collision_ped')]
|
||||
- selected_matrix[i-5, header.index('collision_ped')]) > 30000:
|
||||
count_ped += 1
|
||||
i += 100
|
||||
i += 1
|
||||
|
||||
return count_gen, count_car, count_ped
|
||||
|
||||
|
||||
def get_distance_traveled(selected_matrix, header):
|
||||
|
||||
prev_x = selected_matrix[0, header.index('pos_x')]
|
||||
prev_y = selected_matrix[0, header.index('pos_y')]
|
||||
|
||||
i = 1
|
||||
acummulated_distance = 0
|
||||
while i < selected_matrix.shape[0]:
|
||||
|
||||
x = selected_matrix[i, header.index('pos_x')]
|
||||
y = selected_matrix[i, header.index('pos_y')]
|
||||
# Here we defined a maximun distance in a tick, this case 8 meters or 288km/h
|
||||
if sldist((x, y), (prev_x, prev_y)) < 800:
|
||||
acummulated_distance += sldist((x, y), (prev_x, prev_y))
|
||||
|
||||
|
||||
prev_x = x
|
||||
prev_y = y
|
||||
|
||||
i += 1
|
||||
|
||||
return float(acummulated_distance)/float(100*1000)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def get_out_of_road_lane(selected_matrix, header):
|
||||
|
||||
count_road = 0
|
||||
count_lane = 0
|
||||
|
||||
i = 0
|
||||
|
||||
while i < selected_matrix.shape[0]:
|
||||
# print selected_matrix[i,6]
|
||||
if (selected_matrix[i, header.index('sidewalk_intersect')]
|
||||
- selected_matrix[(i-10), header.index('sidewalk_intersect')]) > 0.3:
|
||||
count_road += 1
|
||||
i += 20
|
||||
if i >= selected_matrix.shape[0]:
|
||||
break
|
||||
|
||||
if (selected_matrix[i, header.index('lane_intersect')]
|
||||
- selected_matrix[(i-10), header.index('lane_intersect')]) > 0.4:
|
||||
count_lane += 1
|
||||
i += 20
|
||||
|
||||
i += 1
|
||||
|
||||
return count_lane, count_road
|
||||
|
||||
|
||||
|
||||
def compute_summary(filename, dynamic_episodes):
|
||||
|
||||
# Separate the PATH and the basename
|
||||
path = os.path.dirname(filename)
|
||||
base_name = os.path.basename(filename)
|
||||
|
||||
|
||||
|
||||
f = open(filename, "rb")
|
||||
header = f.readline()
|
||||
header = header.split(',')
|
||||
header[-1] = header[-1][:-2]
|
||||
f.close()
|
||||
|
||||
f = open(os.path.join(path, 'details_' + base_name), "rb")
|
||||
header_details = f.readline()
|
||||
header_details = header_details.split(',')
|
||||
header_details[-1] = header_details[-1][:-2]
|
||||
f.close()
|
||||
|
||||
data_matrix = np.loadtxt(open(filename, "rb"), delimiter=",", skiprows=1)
|
||||
|
||||
# Corner Case: The presented test just had one episode
|
||||
if data_matrix.ndim == 1:
|
||||
data_matrix = np.expand_dims(data_matrix, axis=0)
|
||||
|
||||
|
||||
tasks = np.unique(data_matrix[:, header.index('exp_id')])
|
||||
|
||||
all_weathers = np.unique(data_matrix[:, header.index('weather')])
|
||||
|
||||
reward_matrix = np.loadtxt(open(os.path.join(
|
||||
path, 'details_' + base_name), "rb"), delimiter=",", skiprows=1)
|
||||
|
||||
metrics_dictionary = {'average_completion': {w: [0.0]*len(tasks) for w in all_weathers},
|
||||
'intersection_offroad': {w: [0.0]*len(tasks) for w in all_weathers},
|
||||
'intersection_otherlane': {w: [0.0]*len(tasks) for w in all_weathers},
|
||||
'collision_pedestrians': {w: [0.0]*len(tasks) for w in all_weathers},
|
||||
'collision_vehicles': {w: [0.0]*len(tasks) for w in all_weathers},
|
||||
'collision_other': {w: [0.0]*len(tasks) for w in all_weathers},
|
||||
'average_fully_completed': {w: [0.0]*len(tasks) for w in all_weathers},
|
||||
'average_speed': {w: [0.0]*len(tasks) for w in all_weathers},
|
||||
'driven_kilometers': {w: [0.0]*len(tasks) for w in all_weathers}
|
||||
}
|
||||
|
||||
for t in tasks:
|
||||
task_data_matrix = data_matrix[
|
||||
data_matrix[:, header.index('exp_id')] == t]
|
||||
weathers = np.unique(task_data_matrix[:, header.index('weather')])
|
||||
|
||||
|
||||
|
||||
for w in weathers:
|
||||
t = int(t)
|
||||
|
||||
task_data_matrix = data_matrix[np.logical_and(data_matrix[:, header.index(
|
||||
'exp_id')] == t, data_matrix[:, header.index('weather')] == w)]
|
||||
|
||||
|
||||
task_reward_matrix = reward_matrix[np.logical_and(reward_matrix[:, header_details.index(
|
||||
'exp_id')] == float(t), reward_matrix[:, header_details.index('weather')] == float(w))]
|
||||
|
||||
km_run = get_distance_traveled(
|
||||
task_reward_matrix, header_details)
|
||||
|
||||
metrics_dictionary['average_fully_completed'][w][t] = sum(
|
||||
task_data_matrix[:, header.index('result')])/task_data_matrix.shape[0]
|
||||
|
||||
metrics_dictionary['average_completion'][w][t] = sum(
|
||||
(task_data_matrix[:, header.index('initial_distance')]
|
||||
- task_data_matrix[:, header.index('final_distance')])
|
||||
/ task_data_matrix[:, header.index('initial_distance')]) \
|
||||
/ len(task_data_matrix[:, header.index('final_distance')])
|
||||
|
||||
|
||||
metrics_dictionary['driven_kilometers'][w][t]= km_run
|
||||
metrics_dictionary['average_speed'][w][t]= km_run/ \
|
||||
((sum(task_data_matrix[:, header.index('final_time')]))/3600.0)
|
||||
|
||||
|
||||
|
||||
if list(tasks).index(t) in set(dynamic_episodes):
|
||||
|
||||
lane_road = get_out_of_road_lane(
|
||||
task_reward_matrix, header_details)
|
||||
colisions = get_colisions(task_reward_matrix, header_details)
|
||||
|
||||
|
||||
|
||||
metrics_dictionary['intersection_offroad'][
|
||||
w][t] = lane_road[0]/km_run
|
||||
metrics_dictionary['intersection_otherlane'][
|
||||
w][t] = lane_road[1]/km_run
|
||||
metrics_dictionary['collision_pedestrians'][
|
||||
w][t] = colisions[2]/km_run
|
||||
metrics_dictionary['collision_vehicles'][
|
||||
w][t] = colisions[1]/km_run
|
||||
metrics_dictionary['collision_other'][
|
||||
w][t] = colisions[0]/km_run
|
||||
|
||||
|
||||
return metrics_dictionary
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
|
@ -0,0 +1,156 @@
|
|||
# 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>.
|
||||
|
||||
import heapq
|
||||
|
||||
|
||||
class Cell(object):
|
||||
def __init__(self, x, y, reachable):
|
||||
"""Initialize new cell.
|
||||
|
||||
@param reachable is cell reachable? not a wall?
|
||||
@param x cell x coordinate
|
||||
@param y cell y coordinate
|
||||
@param g cost to move from the starting cell to this cell.
|
||||
@param h estimation of the cost to move from this cell
|
||||
to the ending cell.
|
||||
@param f f = g + h
|
||||
"""
|
||||
self.reachable = reachable
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.parent = None
|
||||
self.g = 0
|
||||
self.h = 0
|
||||
self.f = 0
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.g < other.g
|
||||
|
||||
|
||||
class AStar(object):
|
||||
def __init__(self):
|
||||
# open list
|
||||
self.opened = []
|
||||
heapq.heapify(self.opened)
|
||||
# visited cells list
|
||||
self.closed = set()
|
||||
# grid cells
|
||||
self.cells = []
|
||||
self.grid_height = None
|
||||
self.grid_width = None
|
||||
self.start = None
|
||||
self.end = None
|
||||
|
||||
def init_grid(self, width, height, walls, start, end):
|
||||
"""Prepare grid cells, walls.
|
||||
|
||||
@param width grid's width.
|
||||
@param height grid's height.
|
||||
@param walls list of wall x,y tuples.
|
||||
@param start grid starting point x,y tuple.
|
||||
@param end grid ending point x,y tuple.
|
||||
"""
|
||||
self.grid_height = height
|
||||
self.grid_width = width
|
||||
for x in range(self.grid_width):
|
||||
for y in range(self.grid_height):
|
||||
if (x, y) in walls:
|
||||
reachable = False
|
||||
else:
|
||||
reachable = True
|
||||
self.cells.append(Cell(x, y, reachable))
|
||||
self.start = self.get_cell(*start)
|
||||
self.end = self.get_cell(*end)
|
||||
|
||||
def get_heuristic(self, cell):
|
||||
"""Compute the heuristic value H for a cell.
|
||||
|
||||
Distance between this cell and the ending cell multiply by 10.
|
||||
|
||||
@returns heuristic value H
|
||||
"""
|
||||
return 10 * (abs(cell.x - self.end.x) + abs(cell.y - self.end.y))
|
||||
|
||||
def get_cell(self, x, y):
|
||||
"""Returns a cell from the cells list.
|
||||
|
||||
@param x cell x coordinate
|
||||
@param y cell y coordinate
|
||||
@returns cell
|
||||
"""
|
||||
return self.cells[x * self.grid_height + y]
|
||||
|
||||
def get_adjacent_cells(self, cell):
|
||||
"""Returns adjacent cells to a cell.
|
||||
|
||||
Clockwise starting from the one on the right.
|
||||
|
||||
@param cell get adjacent cells for this cell
|
||||
@returns adjacent cells list.
|
||||
"""
|
||||
cells = []
|
||||
if cell.x < self.grid_width - 1:
|
||||
cells.append(self.get_cell(cell.x + 1, cell.y))
|
||||
if cell.y > 0:
|
||||
cells.append(self.get_cell(cell.x, cell.y - 1))
|
||||
if cell.x > 0:
|
||||
cells.append(self.get_cell(cell.x - 1, cell.y))
|
||||
if cell.y < self.grid_height - 1:
|
||||
cells.append(self.get_cell(cell.x, cell.y + 1))
|
||||
return cells
|
||||
|
||||
def get_path(self):
|
||||
cell = self.end
|
||||
path = [(cell.x, cell.y)]
|
||||
while cell.parent is not self.start:
|
||||
cell = cell.parent
|
||||
path.append((cell.x, cell.y))
|
||||
|
||||
path.append((self.start.x, self.start.y))
|
||||
path.reverse()
|
||||
return path
|
||||
|
||||
def update_cell(self, adj, cell):
|
||||
"""Update adjacent cell.
|
||||
|
||||
@param adj adjacent cell to current cell
|
||||
@param cell current cell being processed
|
||||
"""
|
||||
adj.g = cell.g + 10
|
||||
adj.h = self.get_heuristic(adj)
|
||||
adj.parent = cell
|
||||
adj.f = adj.h + adj.g
|
||||
|
||||
def solve(self):
|
||||
"""Solve maze, find path to ending cell.
|
||||
|
||||
@returns path or None if not found.
|
||||
"""
|
||||
# add starting cell to open heap queue
|
||||
heapq.heappush(self.opened, (self.start.f, self.start))
|
||||
while len(self.opened):
|
||||
# pop cell from heap queue
|
||||
_, cell = heapq.heappop(self.opened)
|
||||
# add cell to closed list so we don't process it twice
|
||||
self.closed.add(cell)
|
||||
# if ending cell, return found path
|
||||
if cell is self.end:
|
||||
return self.get_path()
|
||||
# get adjacent cells for cell
|
||||
adj_cells = self.get_adjacent_cells(cell)
|
||||
for adj_cell in adj_cells:
|
||||
if adj_cell.reachable and adj_cell not in self.closed:
|
||||
if (adj_cell.f, adj_cell) in self.opened:
|
||||
# if adj cell in open list, check if current path is
|
||||
# better than the one previously found
|
||||
# for this adj cell.
|
||||
if adj_cell.g > cell.g + 10:
|
||||
self.update_cell(adj_cell, cell)
|
||||
else:
|
||||
self.update_cell(adj_cell, cell)
|
||||
# add adj cell to open list
|
||||
heapq.heappush(self.opened, (adj_cell.f, adj_cell))
|
|
@ -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>.
|
||||
|
||||
from carla.planner.graph import sldist
|
||||
|
||||
from carla.planner.astar import AStar
|
||||
from carla.planner.map import CarlaMap
|
||||
|
||||
|
||||
class CityTrack(object):
|
||||
|
||||
def __init__(self, city_name):
|
||||
|
||||
self._node_density = 50.0
|
||||
self._pixel_density = 16.43
|
||||
|
||||
self._map = CarlaMap(city_name, self._pixel_density, self._node_density)
|
||||
|
||||
self._astar = AStar()
|
||||
|
||||
# Refers to the start position of the previous route computation
|
||||
self._previous_node = []
|
||||
|
||||
# The current computed route
|
||||
self._route = None
|
||||
|
||||
def project_node(self, position):
|
||||
"""
|
||||
Projecting the graph node into the city road
|
||||
"""
|
||||
|
||||
node = self._map.convert_to_node(position)
|
||||
|
||||
# To change the orientation with respect to the map standards
|
||||
|
||||
node = tuple([int(x) for x in node])
|
||||
|
||||
# Set to zero if it is less than zero.
|
||||
|
||||
node = (max(0, node[0]), max(0, node[1]))
|
||||
node = (min(self._map.get_graph_resolution()[0] - 1, node[0]),
|
||||
min(self._map.get_graph_resolution()[1] - 1, node[1]))
|
||||
|
||||
node = self._map.search_on_grid(node)
|
||||
|
||||
return node
|
||||
|
||||
def get_intersection_nodes(self):
|
||||
return self._map.get_intersection_nodes()
|
||||
|
||||
def get_pixel_density(self):
|
||||
return self._pixel_density
|
||||
|
||||
def get_node_density(self):
|
||||
return self._node_density
|
||||
|
||||
def is_at_goal(self, source, target):
|
||||
return source == target
|
||||
|
||||
def is_at_new_node(self, current_node):
|
||||
return current_node != self._previous_node
|
||||
|
||||
def is_away_from_intersection(self, current_node):
|
||||
return self._closest_intersection_position(current_node) > 1
|
||||
|
||||
def is_far_away_from_route_intersection(self, current_node):
|
||||
# CHECK FOR THE EMPTY CASE
|
||||
if self._route is None:
|
||||
raise RuntimeError('Impossible to find route'
|
||||
+ ' Current planner is limited'
|
||||
+ ' Try to select start points away from intersections')
|
||||
|
||||
return self._closest_intersection_route_position(current_node,
|
||||
self._route) > 4
|
||||
|
||||
def compute_route(self, node_source, source_ori, node_target, target_ori):
|
||||
|
||||
self._previous_node = node_source
|
||||
|
||||
a_star = AStar()
|
||||
a_star.init_grid(self._map.get_graph_resolution()[0],
|
||||
self._map.get_graph_resolution()[1],
|
||||
self._map.get_walls_directed(node_source, source_ori,
|
||||
node_target, target_ori), node_source,
|
||||
node_target)
|
||||
|
||||
route = a_star.solve()
|
||||
|
||||
# JuSt a Corner Case
|
||||
# Clean this to avoid having to use this function
|
||||
if route is None:
|
||||
a_star = AStar()
|
||||
a_star.init_grid(self._map.get_graph_resolution()[0],
|
||||
self._map.get_graph_resolution()[1], self._map.get_walls(),
|
||||
node_source, node_target)
|
||||
|
||||
route = a_star.solve()
|
||||
|
||||
self._route = route
|
||||
|
||||
return route
|
||||
|
||||
def get_distance_closest_node_route(self, pos, route):
|
||||
distance = []
|
||||
|
||||
for node_iter in route:
|
||||
|
||||
if node_iter in self._map.get_intersection_nodes():
|
||||
distance.append(sldist(node_iter, pos))
|
||||
|
||||
if not distance:
|
||||
return sldist(route[-1], pos)
|
||||
return sorted(distance)[0]
|
||||
|
||||
|
||||
def _closest_intersection_position(self, current_node):
|
||||
|
||||
distance_vector = []
|
||||
for node_iterator in self._map.get_intersection_nodes():
|
||||
distance_vector.append(sldist(node_iterator, current_node))
|
||||
|
||||
return sorted(distance_vector)[0]
|
||||
|
||||
|
||||
def _closest_intersection_route_position(self, current_node, route):
|
||||
|
||||
distance_vector = []
|
||||
for _ in route:
|
||||
for node_iterator in self._map.get_intersection_nodes():
|
||||
distance_vector.append(sldist(node_iterator, current_node))
|
||||
|
||||
return sorted(distance_vector)[0]
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
# 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>.
|
||||
|
||||
import math
|
||||
import numpy as np
|
||||
|
||||
from carla.planner.graph import string_to_floats
|
||||
|
||||
# Constant definition enumeration
|
||||
|
||||
PIXEL = 0
|
||||
WORLD = 1
|
||||
NODE = 2
|
||||
|
||||
|
||||
class Converter(object):
|
||||
|
||||
def __init__(self, city_file, node_density, pixel_density):
|
||||
|
||||
self._node_density = node_density
|
||||
self._pixel_density = pixel_density
|
||||
with open(city_file, 'r') as f:
|
||||
# The offset of the world from the zero coordinates ( The
|
||||
# coordinate we consider zero)
|
||||
self._worldoffset = string_to_floats(f.readline())
|
||||
|
||||
angles = string_to_floats(f.readline())
|
||||
|
||||
# If there is an rotation between the world and map coordinates.
|
||||
self._worldrotation = np.array([
|
||||
[math.cos(math.radians(angles[2])), -math.sin(math.radians(angles[2])), 0.0],
|
||||
[math.sin(math.radians(angles[2])), math.cos(math.radians(angles[2])), 0.0],
|
||||
[0.0, 0.0, 1.0]])
|
||||
|
||||
# Ignore for now, these are offsets for map coordinates and scale
|
||||
# (not used).
|
||||
_ = f.readline()
|
||||
|
||||
# The offset of the map zero coordinate.
|
||||
self._mapoffset = string_to_floats(f.readline())
|
||||
|
||||
def convert_to_node(self, input_data):
|
||||
"""
|
||||
Receives a data type (Can Be Pixel or World )
|
||||
:param input_data: position in some coordinate
|
||||
:return: A vector representing a node
|
||||
"""
|
||||
|
||||
input_type = self._check_input_type(input_data)
|
||||
if input_type == PIXEL:
|
||||
return self._pixel_to_node(input_data)
|
||||
elif input_type == WORLD:
|
||||
return self._world_to_node(input_data)
|
||||
else:
|
||||
raise ValueError('Invalid node to be converted')
|
||||
|
||||
def convert_to_pixel(self, input_data):
|
||||
|
||||
"""
|
||||
Receives a data type (Can Be Node or World )
|
||||
:param input_data: position in some coordinate
|
||||
:return: A vector with pixel coordinates
|
||||
"""
|
||||
|
||||
input_type = self._check_input_type(input_data)
|
||||
if input_type == NODE:
|
||||
return self._node_to_pixel(input_data)
|
||||
elif input_type == WORLD:
|
||||
return self._world_to_pixel(input_data)
|
||||
else:
|
||||
raise ValueError('Invalid node to be converted')
|
||||
|
||||
def convert_to_world(self, input_data):
|
||||
|
||||
"""
|
||||
Receives a data type (Can Be Pixel or Node )
|
||||
:param input_data: position in some coordinate
|
||||
:return: vector with world coordinates
|
||||
"""
|
||||
|
||||
input_type = self._check_input_type(input_data)
|
||||
if input_type == NODE:
|
||||
return self._node_to_world(input_data)
|
||||
elif input_type == PIXEL:
|
||||
return self._pixel_to_world(input_data)
|
||||
else:
|
||||
raise ValueError('Invalid node to be converted')
|
||||
|
||||
def _node_to_pixel(self, node):
|
||||
"""
|
||||
Conversion from node format (graph) to pixel (image)
|
||||
:param node:
|
||||
:return: pixel
|
||||
"""
|
||||
pixel = [((node[0] + 2) * self._node_density)
|
||||
, ((node[1] + 2) * self._node_density)]
|
||||
return pixel
|
||||
|
||||
def _pixel_to_node(self, pixel):
|
||||
"""
|
||||
Conversion from pixel format (image) to node (graph)
|
||||
:param node:
|
||||
:return: pixel
|
||||
"""
|
||||
node = [int(((pixel[0]) / self._node_density) - 2)
|
||||
, int(((pixel[1]) / self._node_density) - 2)]
|
||||
|
||||
return tuple(node)
|
||||
|
||||
def _pixel_to_world(self, pixel):
|
||||
"""
|
||||
Conversion from pixel format (image) to world (3D)
|
||||
:param pixel:
|
||||
:return: world
|
||||
"""
|
||||
|
||||
relative_location = [pixel[0] * self._pixel_density,
|
||||
pixel[1] * self._pixel_density]
|
||||
|
||||
world = [
|
||||
relative_location[0] + self._mapoffset[0] - self._worldoffset[0],
|
||||
relative_location[1] + self._mapoffset[1] - self._worldoffset[1],
|
||||
22
|
||||
]
|
||||
|
||||
return world
|
||||
|
||||
def _world_to_pixel(self, world):
|
||||
"""
|
||||
Conversion from world format (3D) to pixel
|
||||
:param world:
|
||||
:return: pixel
|
||||
"""
|
||||
|
||||
rotation = np.array([world[0], world[1], world[2]])
|
||||
rotation = rotation.dot(self._worldrotation)
|
||||
|
||||
relative_location = [rotation[0] + self._worldoffset[0] - self._mapoffset[0],
|
||||
rotation[1] + self._worldoffset[1] - self._mapoffset[1],
|
||||
rotation[2] + self._worldoffset[2] - self._mapoffset[2]]
|
||||
|
||||
pixel = [math.floor(relative_location[0] / float(self._pixel_density)),
|
||||
math.floor(relative_location[1] / float(self._pixel_density))]
|
||||
|
||||
return pixel
|
||||
|
||||
def _world_to_node(self, world):
|
||||
return self._pixel_to_node(self._world_to_pixel(world))
|
||||
|
||||
def _node_to_world(self, node):
|
||||
|
||||
return self._pixel_to_world(self._node_to_pixel(node))
|
||||
|
||||
def _check_input_type(self, input_data):
|
||||
if len(input_data) > 2:
|
||||
return WORLD
|
||||
elif type(input_data[0]) is int:
|
||||
return NODE
|
||||
else:
|
||||
return PIXEL
|
|
@ -0,0 +1,141 @@
|
|||
# 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>.
|
||||
|
||||
import math
|
||||
import numpy as np
|
||||
|
||||
|
||||
def string_to_node(string):
|
||||
vec = string.split(',')
|
||||
return (int(vec[0]), int(vec[1]))
|
||||
|
||||
|
||||
def string_to_floats(string):
|
||||
vec = string.split(',')
|
||||
return (float(vec[0]), float(vec[1]), float(vec[2]))
|
||||
|
||||
|
||||
def sldist(c1, c2):
|
||||
return math.sqrt((c2[0] - c1[0]) ** 2 + (c2[1] - c1[1]) ** 2)
|
||||
|
||||
|
||||
def sldist3(c1, c2):
|
||||
return math.sqrt((c2[0] - c1[0]) ** 2 + (c2[1] - c1[1])
|
||||
** 2 + (c2[2] - c1[2]) ** 2)
|
||||
|
||||
|
||||
class Graph(object):
|
||||
"""
|
||||
A simple directed, weighted graph
|
||||
"""
|
||||
|
||||
def __init__(self, graph_file=None, node_density=50):
|
||||
|
||||
self._nodes = set()
|
||||
self._angles = {}
|
||||
self._edges = {}
|
||||
self._distances = {}
|
||||
self._node_density = node_density
|
||||
|
||||
if graph_file is not None:
|
||||
with open(graph_file, 'r') as f:
|
||||
# Skipe the first four lines that
|
||||
lines_after_4 = f.readlines()[4:]
|
||||
|
||||
# the graph resolution.
|
||||
linegraphres = lines_after_4[0]
|
||||
self._resolution = string_to_node(linegraphres)
|
||||
for line in lines_after_4[1:]:
|
||||
|
||||
from_node, to_node, d = line.split()
|
||||
from_node = string_to_node(from_node)
|
||||
to_node = string_to_node(to_node)
|
||||
|
||||
if from_node not in self._nodes:
|
||||
self.add_node(from_node)
|
||||
if to_node not in self._nodes:
|
||||
self.add_node(to_node)
|
||||
|
||||
self._edges.setdefault(from_node, [])
|
||||
self._edges[from_node].append(to_node)
|
||||
self._distances[(from_node, to_node)] = float(d)
|
||||
|
||||
def add_node(self, value):
|
||||
self._nodes.add(value)
|
||||
|
||||
def make_orientations(self, node, heading):
|
||||
|
||||
import collections
|
||||
distance_dic = {}
|
||||
for node_iter in self._nodes:
|
||||
if node_iter != node:
|
||||
distance_dic[sldist(node, node_iter)] = node_iter
|
||||
|
||||
distance_dic = collections.OrderedDict(
|
||||
sorted(distance_dic.items()))
|
||||
|
||||
self._angles[node] = heading
|
||||
for _, v in distance_dic.items():
|
||||
start_to_goal = np.array([node[0] - v[0], node[1] - v[1]])
|
||||
|
||||
print(start_to_goal)
|
||||
|
||||
self._angles[v] = start_to_goal / np.linalg.norm(start_to_goal)
|
||||
|
||||
def add_edge(self, from_node, to_node, distance):
|
||||
self._add_edge(from_node, to_node, distance)
|
||||
|
||||
def _add_edge(self, from_node, to_node, distance):
|
||||
self._edges.setdefault(from_node, [])
|
||||
self._edges[from_node].append(to_node)
|
||||
self._distances[(from_node, to_node)] = distance
|
||||
|
||||
def get_resolution(self):
|
||||
return self._resolution
|
||||
def get_edges(self):
|
||||
return self._edges
|
||||
|
||||
def intersection_nodes(self):
|
||||
|
||||
intersect_nodes = []
|
||||
for node in self._nodes:
|
||||
if len(self._edges[node]) > 2:
|
||||
intersect_nodes.append(node)
|
||||
|
||||
return intersect_nodes
|
||||
|
||||
# This contains also the non-intersection turns...
|
||||
|
||||
def turn_nodes(self):
|
||||
|
||||
return self._nodes
|
||||
|
||||
def plot_ori(self, c):
|
||||
from matplotlib import collections as mc
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
line_len = 1
|
||||
|
||||
lines = [[(p[0], p[1]), (p[0] + line_len * self._angles[p][0],
|
||||
p[1] + line_len * self._angles[p][1])] for p in self._nodes]
|
||||
lc = mc.LineCollection(lines, linewidth=2, color='green')
|
||||
_, ax = plt.subplots()
|
||||
ax.add_collection(lc)
|
||||
|
||||
ax.autoscale()
|
||||
ax.margins(0.1)
|
||||
|
||||
xs = [p[0] for p in self._nodes]
|
||||
ys = [p[1] for p in self._nodes]
|
||||
|
||||
plt.scatter(xs, ys, color=c)
|
||||
|
||||
def plot(self, c):
|
||||
import matplotlib.pyplot as plt
|
||||
xs = [p[0] for p in self._nodes]
|
||||
ys = [p[1] for p in self._nodes]
|
||||
|
||||
plt.scatter(xs, ys, color=c)
|
|
@ -0,0 +1,135 @@
|
|||
# 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>.
|
||||
|
||||
import copy
|
||||
import numpy as np
|
||||
|
||||
|
||||
def angle_between(v1, v2):
|
||||
return np.arccos(np.dot(v1, v2) / np.linalg.norm(v1) / np.linalg.norm(v2))
|
||||
|
||||
|
||||
class Grid(object):
|
||||
|
||||
def __init__(self, graph):
|
||||
|
||||
self._graph = graph
|
||||
self._structure = self._make_structure()
|
||||
self._walls = self._make_walls()
|
||||
|
||||
def search_on_grid(self, x, y):
|
||||
visit = [[0, 1], [0, -1], [1, 0], [1, 1],
|
||||
[1, -1], [-1, 0], [-1, 1], [-1, -1]]
|
||||
c_x, c_y = x, y
|
||||
scale = 1
|
||||
while self._structure[c_x, c_y] != 0:
|
||||
for offset in visit:
|
||||
c_x, c_y = x + offset[0] * scale, y + offset[1] * scale
|
||||
|
||||
if c_x >= 0 and c_x < self._graph.get_resolution()[
|
||||
0] and c_y >= 0 and c_y < self._graph.get_resolution()[1]:
|
||||
if self._structure[c_x, c_y] == 0:
|
||||
break
|
||||
else:
|
||||
c_x, c_y = x, y
|
||||
scale += 1
|
||||
|
||||
return c_x, c_y
|
||||
def get_walls(self):
|
||||
return self._walls
|
||||
|
||||
def get_wall_source(self, pos, pos_ori, target):
|
||||
|
||||
free_nodes = self._get_adjacent_free_nodes(pos)
|
||||
# print self._walls
|
||||
final_walls = copy.copy(self._walls)
|
||||
# print final_walls
|
||||
heading_start = np.array([pos_ori[0], pos_ori[1]])
|
||||
for adj in free_nodes:
|
||||
|
||||
start_to_goal = np.array([adj[0] - pos[0], adj[1] - pos[1]])
|
||||
angle = angle_between(heading_start, start_to_goal)
|
||||
if (angle > 1.6 and adj != target):
|
||||
final_walls.add((adj[0], adj[1]))
|
||||
|
||||
return final_walls
|
||||
|
||||
def get_wall_target(self, pos, pos_ori, source):
|
||||
|
||||
free_nodes = self._get_adjacent_free_nodes(pos)
|
||||
final_walls = copy.copy(self._walls)
|
||||
heading_start = np.array([pos_ori[0], pos_ori[1]])
|
||||
for adj in free_nodes:
|
||||
|
||||
start_to_goal = np.array([adj[0] - pos[0], adj[1] - pos[1]])
|
||||
angle = angle_between(heading_start, start_to_goal)
|
||||
|
||||
if (angle < 1.0 and adj != source):
|
||||
final_walls.add((adj[0], adj[1]))
|
||||
|
||||
return final_walls
|
||||
|
||||
def _draw_line(self, grid, xi, yi, xf, yf):
|
||||
|
||||
if xf < xi:
|
||||
aux = xi
|
||||
xi = xf
|
||||
xf = aux
|
||||
|
||||
if yf < yi:
|
||||
aux = yi
|
||||
yi = yf
|
||||
yf = aux
|
||||
|
||||
for i in range(xi, xf + 1):
|
||||
|
||||
for j in range(yi, yf + 1):
|
||||
grid[i, j] = 0.0
|
||||
|
||||
return grid
|
||||
|
||||
def _make_structure(self):
|
||||
structure = np.ones(
|
||||
(self._graph.get_resolution()[0],
|
||||
self._graph.get_resolution()[1]))
|
||||
|
||||
for key, connections in self._graph.get_edges().items():
|
||||
|
||||
# draw a line
|
||||
for con in connections:
|
||||
# print key[0],key[1],con[0],con[1]
|
||||
structure = self._draw_line(
|
||||
structure, key[0], key[1], con[0], con[1])
|
||||
# print grid
|
||||
return structure
|
||||
|
||||
def _make_walls(self):
|
||||
walls = set()
|
||||
|
||||
for i in range(self._structure.shape[0]):
|
||||
|
||||
for j in range(self._structure.shape[1]):
|
||||
if self._structure[i, j] == 1.0:
|
||||
walls.add((i, j))
|
||||
|
||||
return walls
|
||||
|
||||
def _get_adjacent_free_nodes(self, pos):
|
||||
""" Eight nodes in total """
|
||||
visit = [[0, 1], [0, -1], [1, 0], [1, 1],
|
||||
[1, -1], [-1, 0], [-1, 1], [-1, -1]]
|
||||
|
||||
adjacent = set()
|
||||
for offset in visit:
|
||||
node = (pos[0] + offset[0], pos[1] + offset[1])
|
||||
|
||||
if (node[0] >= 0 and node[0] < self._graph.get_resolution()[0]
|
||||
and node[1] >= 0 and node[1] < self._graph.get_resolution()[1]):
|
||||
|
||||
if self._structure[node[0], node[1]] == 0.0:
|
||||
adjacent.add(node)
|
||||
|
||||
return adjacent
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
@ -19,54 +19,36 @@ try:
|
|||
except ImportError:
|
||||
raise RuntimeError('cannot import PIL, make sure pillow package is installed')
|
||||
|
||||
|
||||
def string_to_node(string):
|
||||
vec = string.split(',')
|
||||
return (int(vec[0]), int(vec[1]))
|
||||
from carla.planner.graph import Graph
|
||||
from carla.planner.graph import sldist
|
||||
from carla.planner.grid import Grid
|
||||
from carla.planner.converter import Converter
|
||||
|
||||
|
||||
def string_to_floats(string):
|
||||
vec = string.split(',')
|
||||
return (float(vec[0]), float(vec[1]), float(vec[2]))
|
||||
def color_to_angle(color):
|
||||
return ((float(color) / 255.0)) * 2 * math.pi
|
||||
|
||||
|
||||
class CarlaMap(object):
|
||||
def __init__(self, city):
|
||||
|
||||
def __init__(self, city, pixel_density, node_density):
|
||||
dir_path = os.path.dirname(__file__)
|
||||
city_file = os.path.join(dir_path, city + '.txt')
|
||||
|
||||
city_map_file = os.path.join(dir_path, city + '.png')
|
||||
city_map_file_lanes = os.path.join(dir_path, city + 'Lanes.png')
|
||||
city_map_file_center = os.path.join(dir_path, city + 'Central.png')
|
||||
|
||||
with open(city_file, 'r') as file_object:
|
||||
# The built graph. This is the exact same graph that unreal builds. This
|
||||
# is a generic structure used for many cases
|
||||
self._graph = Graph(city_file, node_density)
|
||||
|
||||
linewordloffset = file_object.readline()
|
||||
# The offset of the world from the zero coordinates ( The
|
||||
# coordinate we consider zero)
|
||||
self.worldoffset = string_to_floats(linewordloffset)
|
||||
self._pixel_density = pixel_density
|
||||
self._grid = Grid(self._graph)
|
||||
# The number of game units per pixel. For now this is fixed.
|
||||
|
||||
lineworldangles = file_object.readline()
|
||||
self.angles = string_to_floats(lineworldangles)
|
||||
self._converter = Converter(city_file, pixel_density, node_density)
|
||||
|
||||
self.worldrotation = np.array([
|
||||
[math.cos(math.radians(self.angles[2])), -math.sin(math.radians(self.angles[2])), 0.0],
|
||||
[math.sin(math.radians(self.angles[2])), math.cos(math.radians(self.angles[2])), 0.0],
|
||||
[0.0, 0.0, 1.0]])
|
||||
|
||||
# Ignore for now, these are offsets for map coordinates and scale
|
||||
# (not used).
|
||||
_ = file_object.readline()
|
||||
linemapoffset = file_object.readline()
|
||||
|
||||
# The offset of the map zero coordinate.
|
||||
self.mapoffset = string_to_floats(linemapoffset)
|
||||
|
||||
# the graph resolution.
|
||||
linegraphres = file_object.readline()
|
||||
self.resolution = string_to_node(linegraphres)
|
||||
|
||||
# The number of game units per pixel.
|
||||
self.pixel_density = 16.43
|
||||
# Load the lanes image
|
||||
self.map_image_lanes = Image.open(city_map_file_lanes)
|
||||
self.map_image_lanes.load()
|
||||
|
@ -76,72 +58,95 @@ class CarlaMap(object):
|
|||
self.map_image.load()
|
||||
self.map_image = np.asarray(self.map_image, dtype="int32")
|
||||
|
||||
# Load the lanes image
|
||||
self.map_image_center = Image.open(city_map_file_center)
|
||||
self.map_image_center.load()
|
||||
self.map_image_center = np.asarray(self.map_image_center, dtype="int32")
|
||||
|
||||
def get_graph_resolution(self):
|
||||
|
||||
return self._graph.get_resolution()
|
||||
|
||||
def get_map(self, height=None):
|
||||
if height is not None:
|
||||
img = Image.fromarray(self.map_image.astype(np.uint8))
|
||||
|
||||
aspect_ratio = height/float(self.map_image.shape[0])
|
||||
aspect_ratio = height / float(self.map_image.shape[0])
|
||||
|
||||
img = img.resize((int(aspect_ratio*self.map_image.shape[1]),height), Image.ANTIALIAS)
|
||||
img = img.resize((int(aspect_ratio * self.map_image.shape[1]), height), Image.ANTIALIAS)
|
||||
img.load()
|
||||
return np.asarray(img, dtype="int32")
|
||||
return np.fliplr(self.map_image)
|
||||
|
||||
def get_map_lanes(self, height=None):
|
||||
# if size is not None:
|
||||
# img = Image.fromarray(self.map_image_lanes.astype(np.uint8))
|
||||
# img = img.resize((size[1], size[0]), Image.ANTIALIAS)
|
||||
# img.load()
|
||||
# return np.fliplr(np.asarray(img, dtype="int32"))
|
||||
# return np.fliplr(self.map_image_lanes)
|
||||
raise NotImplementedError
|
||||
|
||||
def get_position_on_map(self, world):
|
||||
"""Get the position on the map for a certain world position."""
|
||||
relative_location = []
|
||||
pixel = []
|
||||
|
||||
rotation = np.array([world[0], world[1], world[2]])
|
||||
rotation = rotation.dot(self.worldrotation)
|
||||
|
||||
relative_location.append(rotation[0] + self.worldoffset[0] - self.mapoffset[0])
|
||||
relative_location.append(rotation[1] + self.worldoffset[1] - self.mapoffset[1])
|
||||
relative_location.append(rotation[2] + self.worldoffset[2] - self.mapoffset[2])
|
||||
|
||||
pixel.append(math.floor(relative_location[0] / float(self.pixel_density)))
|
||||
pixel.append(math.floor(relative_location[1] / float(self.pixel_density)))
|
||||
|
||||
return pixel
|
||||
|
||||
def get_position_on_world(self, pixel):
|
||||
"""Get world position of a certain map position."""
|
||||
relative_location = []
|
||||
world_vertex = []
|
||||
relative_location.append(pixel[0] * self.pixel_density)
|
||||
relative_location.append(pixel[1] * self.pixel_density)
|
||||
|
||||
world_vertex.append(relative_location[0] + self.mapoffset[0] - self.worldoffset[0])
|
||||
world_vertex.append(relative_location[1] + self.mapoffset[1] - self.worldoffset[1])
|
||||
world_vertex.append(22) # Z does not matter for now.
|
||||
|
||||
return world_vertex
|
||||
def get_map_lanes(self, size=None):
|
||||
if size is not None:
|
||||
img = Image.fromarray(self.map_image_lanes.astype(np.uint8))
|
||||
img = img.resize((size[1], size[0]), Image.ANTIALIAS)
|
||||
img.load()
|
||||
return np.fliplr(np.asarray(img, dtype="int32"))
|
||||
return np.fliplr(self.map_image_lanes)
|
||||
|
||||
def get_lane_orientation(self, world):
|
||||
"""Get the lane orientation of a certain world position."""
|
||||
relative_location = []
|
||||
pixel = []
|
||||
rotation = np.array([world[0], world[1], world[2]])
|
||||
rotation = rotation.dot(self.worldrotation)
|
||||
|
||||
relative_location.append(rotation[0] + self.worldoffset[0] - self.mapoffset[0])
|
||||
relative_location.append(rotation[1] + self.worldoffset[1] - self.mapoffset[1])
|
||||
relative_location.append(rotation[2] + self.worldoffset[2] - self.mapoffset[2])
|
||||
|
||||
pixel.append(math.floor(relative_location[0] / float(self.pixel_density)))
|
||||
pixel.append(math.floor(relative_location[1] / float(self.pixel_density)))
|
||||
pixel = self.convert_to_pixel(world)
|
||||
|
||||
ori = self.map_image_lanes[int(pixel[1]), int(pixel[0]), 2]
|
||||
ori = ((float(ori) / 255.0)) * 2 * math.pi
|
||||
ori = color_to_angle(ori)
|
||||
|
||||
return (-math.cos(ori), -math.sin(ori))
|
||||
|
||||
def convert_to_node(self, input_data):
|
||||
"""
|
||||
Receives a data type (Can Be Pixel or World )
|
||||
:param input_data: position in some coordinate
|
||||
:return: A node object
|
||||
"""
|
||||
return self._converter.convert_to_node(input_data)
|
||||
|
||||
def convert_to_pixel(self, input_data):
|
||||
"""
|
||||
Receives a data type (Can Be Pixel or World )
|
||||
:param input_data: position in some coordinate
|
||||
:return: A node object
|
||||
"""
|
||||
return self._converter.convert_to_pixel(input_data)
|
||||
|
||||
def convert_to_world(self, input_data):
|
||||
"""
|
||||
Receives a data type (Can Be Pixel or World )
|
||||
:param input_data: position in some coordinate
|
||||
:return: A node object
|
||||
"""
|
||||
return self._converter.convert_to_world(input_data)
|
||||
|
||||
def get_walls_directed(self, node_source, source_ori, node_target, target_ori):
|
||||
"""
|
||||
This is the most hacky function. Instead of planning on two ways,
|
||||
we basically use a one way road and interrupt the other road by adding
|
||||
an artificial wall.
|
||||
|
||||
"""
|
||||
|
||||
final_walls = self._grid.get_wall_source(node_source, source_ori, node_target)
|
||||
|
||||
final_walls = final_walls.union(self._grid.get_wall_target(
|
||||
node_target, target_ori, node_source))
|
||||
return final_walls
|
||||
|
||||
def get_walls(self):
|
||||
|
||||
return self._grid.get_walls()
|
||||
|
||||
def get_distance_closest_node(self, pos):
|
||||
|
||||
distance = []
|
||||
for node_iter in self._graph.intersection_nodes():
|
||||
distance.append(sldist(node_iter, pos))
|
||||
|
||||
return sorted(distance)[0]
|
||||
|
||||
def get_intersection_nodes(self):
|
||||
return self._graph.intersection_nodes()
|
||||
|
||||
def search_on_grid(self,node):
|
||||
return self._grid.search_on_grid(node[0], node[1])
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
# 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>.
|
||||
|
||||
import collections
|
||||
import math
|
||||
|
||||
import numpy as np
|
||||
|
||||
from . import city_track
|
||||
|
||||
|
||||
def compare(x, y):
|
||||
return collections.Counter(x) == collections.Counter(y)
|
||||
|
||||
|
||||
|
||||
# Constants Used for the high level commands
|
||||
|
||||
|
||||
REACH_GOAL = 0.0
|
||||
GO_STRAIGHT = 5.0
|
||||
TURN_RIGHT = 4.0
|
||||
TURN_LEFT = 3.0
|
||||
LANE_FOLLOW = 2.0
|
||||
|
||||
|
||||
# Auxiliary algebra function
|
||||
def angle_between(v1, v2):
|
||||
return np.arccos(np.dot(v1, v2) / np.linalg.norm(v1) / np.linalg.norm(v2))
|
||||
|
||||
|
||||
def sldist(c1, c2): return math.sqrt((c2[0] - c1[0]) ** 2 + (c2[1] - c1[1]) ** 2)
|
||||
|
||||
|
||||
def signal(v1, v2):
|
||||
return np.cross(v1, v2) / np.linalg.norm(v1) / np.linalg.norm(v2)
|
||||
|
||||
|
||||
class Planner(object):
|
||||
|
||||
def __init__(self, city_name):
|
||||
|
||||
self._city_track = city_track.CityTrack(city_name)
|
||||
|
||||
self._commands = []
|
||||
|
||||
def get_next_command(self, source, source_ori, target, target_ori):
|
||||
"""
|
||||
Computes the full plan and returns the next command,
|
||||
:param source: source position
|
||||
:param source_ori: source orientation
|
||||
:param target: target position
|
||||
:param target_ori: target orientation
|
||||
:return: a command ( Straight,Lane Follow, Left or Right)
|
||||
"""
|
||||
|
||||
track_source = self._city_track.project_node(source)
|
||||
track_target = self._city_track.project_node(target)
|
||||
|
||||
# reach the goal
|
||||
|
||||
if self._city_track.is_at_goal(track_source, track_target):
|
||||
return REACH_GOAL
|
||||
|
||||
if (self._city_track.is_at_new_node(track_source)
|
||||
and self._city_track.is_away_from_intersection(track_source)):
|
||||
|
||||
route = self._city_track.compute_route(track_source, source_ori,
|
||||
track_target, target_ori)
|
||||
if route is None:
|
||||
raise RuntimeError('Impossible to find route')
|
||||
|
||||
self._commands = self._route_to_commands(route)
|
||||
|
||||
if self._city_track.is_far_away_from_route_intersection(
|
||||
track_source):
|
||||
return LANE_FOLLOW
|
||||
else:
|
||||
if self._commands:
|
||||
return self._commands[0]
|
||||
else:
|
||||
return LANE_FOLLOW
|
||||
else:
|
||||
|
||||
if self._city_track.is_far_away_from_route_intersection(
|
||||
track_source):
|
||||
return LANE_FOLLOW
|
||||
|
||||
# If there is computed commands
|
||||
if self._commands:
|
||||
return self._commands[0]
|
||||
else:
|
||||
return LANE_FOLLOW
|
||||
|
||||
def get_shortest_path_distance(
|
||||
self,
|
||||
source,
|
||||
source_ori,
|
||||
target,
|
||||
target_ori):
|
||||
|
||||
distance = 0
|
||||
track_source = self._city_track.project_node(source)
|
||||
track_target = self._city_track.project_node(target)
|
||||
|
||||
current_pos = track_source
|
||||
|
||||
route = self._city_track.compute_route(track_source, source_ori,
|
||||
track_target, target_ori)
|
||||
# No Route, distance is zero
|
||||
if route is None:
|
||||
return 0.0
|
||||
|
||||
for node_iter in route:
|
||||
distance += sldist(node_iter, current_pos)
|
||||
current_pos = node_iter
|
||||
|
||||
# We multiply by these values to convert distance to world coordinates
|
||||
return distance * self._city_track.get_pixel_density() \
|
||||
* self._city_track.get_node_density()
|
||||
|
||||
def is_there_posible_route(self, source, source_ori, target, target_ori):
|
||||
|
||||
track_source = self._city_track.project_node(source)
|
||||
track_target = self._city_track.project_node(target)
|
||||
|
||||
return not self._city_track.compute_route(
|
||||
track_source, source_ori, track_target, target_ori) is None
|
||||
|
||||
def test_position(self, source):
|
||||
|
||||
node_source = self._city_track.project_node(source)
|
||||
|
||||
return self._city_track.is_away_from_intersection(node_source)
|
||||
|
||||
def _route_to_commands(self, route):
|
||||
|
||||
"""
|
||||
from the shortest path graph, transform it into a list of commands
|
||||
|
||||
:param route: the sub graph containing the shortest path
|
||||
:return: list of commands encoded from 0-5
|
||||
"""
|
||||
|
||||
commands_list = []
|
||||
|
||||
for i in range(0, len(route)):
|
||||
if route[i] not in self._city_track.get_intersection_nodes():
|
||||
continue
|
||||
|
||||
current = route[i]
|
||||
past = route[i - 1]
|
||||
future = route[i + 1]
|
||||
|
||||
past_to_current = np.array(
|
||||
[current[0] - past[0], current[1] - past[1]])
|
||||
current_to_future = np.array(
|
||||
[future[0] - current[0], future[1] - current[1]])
|
||||
angle = signal(current_to_future, past_to_current)
|
||||
|
||||
if angle < -0.1:
|
||||
command = TURN_RIGHT
|
||||
elif angle > 0.1:
|
||||
command = TURN_LEFT
|
||||
else:
|
||||
command = GO_STRAIGHT
|
||||
|
||||
commands_list.append(command)
|
||||
|
||||
return commands_list
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
@ -41,7 +41,7 @@ class TCPClient(object):
|
|||
self._socket.settimeout(self._timeout)
|
||||
logging.debug('%sconnected', self._logprefix)
|
||||
return
|
||||
except OSError as exception:
|
||||
except socket.error as exception:
|
||||
error = exception
|
||||
logging.debug('%sconnection attempt %d: %s', self._logprefix, attempt, error)
|
||||
time.sleep(1)
|
||||
|
@ -65,7 +65,7 @@ class TCPClient(object):
|
|||
header = struct.pack('<L', len(message))
|
||||
try:
|
||||
self._socket.sendall(header + message)
|
||||
except OSError as exception:
|
||||
except socket.error as exception:
|
||||
self._reraise_exception_as_tcp_error('failed to write data', exception)
|
||||
|
||||
def read(self):
|
||||
|
@ -85,7 +85,7 @@ class TCPClient(object):
|
|||
while length > 0:
|
||||
try:
|
||||
data = self._socket.recv(length)
|
||||
except OSError as exception:
|
||||
except socket.error as exception:
|
||||
self._reraise_exception_as_tcp_error('failed to read data', exception)
|
||||
if not data:
|
||||
raise TCPConnectionError(self._logprefix + 'connection closed')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
@ -127,7 +127,7 @@ class CarlaGame(object):
|
|||
self._map_view = None
|
||||
self._is_on_reverse = False
|
||||
self._city_name = city_name
|
||||
self._map = CarlaMap(city_name) if city_name is not None else None
|
||||
self._map = CarlaMap(city_name, 16.43, 50.0) if city_name is not None else None
|
||||
self._map_shape = self._map.map_image.shape if city_name is not None else None
|
||||
self._map_view = self._map.get_map(WINDOW_HEIGHT) if city_name is not None else None
|
||||
self._position = None
|
||||
|
|
|
@ -2,3 +2,5 @@ Pillow
|
|||
numpy
|
||||
protobuf
|
||||
pygame
|
||||
matplotlib
|
||||
future
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# 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>.
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import time
|
||||
|
||||
from carla.benchmarks.agent import Agent
|
||||
from carla.benchmarks.corl_2017 import CoRL2017
|
||||
|
||||
from carla.client import make_carla_client, VehicleControl
|
||||
from carla.tcp import TCPConnectionError
|
||||
|
||||
|
||||
class Manual(Agent):
|
||||
"""
|
||||
Sample redefinition of the Agent,
|
||||
An agent that goes straight
|
||||
"""
|
||||
def run_step(self, measurements, sensor_data, target):
|
||||
control = VehicleControl()
|
||||
control.throttle = 0.9
|
||||
|
||||
return control
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
argparser = argparse.ArgumentParser(description=__doc__)
|
||||
argparser.add_argument(
|
||||
'-v', '--verbose',
|
||||
action='store_true',
|
||||
dest='verbose',
|
||||
help='print some extra status information')
|
||||
argparser.add_argument(
|
||||
'-db', '--debug',
|
||||
action='store_true',
|
||||
dest='debug',
|
||||
help='print debug information')
|
||||
argparser.add_argument(
|
||||
'--host',
|
||||
metavar='H',
|
||||
default='localhost',
|
||||
help='IP of the host server (default: localhost)')
|
||||
argparser.add_argument(
|
||||
'-p', '--port',
|
||||
metavar='P',
|
||||
default=2000,
|
||||
type=int,
|
||||
help='TCP port to listen to (default: 2000)')
|
||||
argparser.add_argument(
|
||||
'-c', '--city-name',
|
||||
metavar='C',
|
||||
default='Town01',
|
||||
help='The town that is going to be used on benchmark'
|
||||
+ '(needs to match active town in server, options: Town01 or Town02)')
|
||||
argparser.add_argument(
|
||||
'-n', '--log_name',
|
||||
metavar='T',
|
||||
default='test',
|
||||
help='The name of the log file to be created by the benchmark'
|
||||
)
|
||||
|
||||
args = argparser.parse_args()
|
||||
if args.debug:
|
||||
log_level = logging.DEBUG
|
||||
elif args.verbose:
|
||||
log_level = logging.INFO
|
||||
else:
|
||||
log_level = logging.WARNING
|
||||
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s', level=log_level)
|
||||
|
||||
logging.info('listening to server %s:%s', args.host, args.port)
|
||||
|
||||
while True:
|
||||
try:
|
||||
with make_carla_client(args.host, args.port) as client:
|
||||
corl = CoRL2017(city_name=args.city_name, name_to_save=args.log_name)
|
||||
agent = Manual(args.city_name)
|
||||
results = corl.benchmark_agent(agent, client)
|
||||
corl.plot_summary_test()
|
||||
corl.plot_summary_train()
|
||||
|
||||
break
|
||||
|
||||
except TCPConnectionError as error:
|
||||
logging.error(error)
|
||||
time.sleep(1)
|
|
@ -0,0 +1,15 @@
|
|||
from setuptools import setup
|
||||
|
||||
# @todo Dependencies are missing.
|
||||
|
||||
setup(
|
||||
name='carla_client',
|
||||
version='0.7.1',
|
||||
packages=['carla', 'carla.benchmarks', 'carla.planner'],
|
||||
license='MIT License',
|
||||
description='Python API for communicating with the CARLA server.',
|
||||
url='https://github.com/carla-simulator/carla',
|
||||
author='The CARLA team',
|
||||
author_email='carla.simulator@gmail.com',
|
||||
include_package_data=True
|
||||
)
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
"""Client that runs two servers simultaneously to test repeatability."""
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
|
||||
from carla.client import make_carla_client
|
||||
from carla.sensor import Camera, Image
|
||||
from carla.settings import CarlaSettings
|
||||
from carla.tcp import TCPConnectionError
|
||||
|
||||
|
||||
def run_carla_clients(args):
|
||||
filename = '_images_repeatability/server{:d}/{:0>6d}.png'
|
||||
with make_carla_client(args.host1, args.port1) as client1:
|
||||
logging.info('1st client connected')
|
||||
with make_carla_client(args.host2, args.port2) as client2:
|
||||
logging.info('2nd client connected')
|
||||
|
||||
settings = CarlaSettings()
|
||||
settings.set(
|
||||
SynchronousMode=True,
|
||||
SendNonPlayerAgentsInfo=True,
|
||||
NumberOfVehicles=50,
|
||||
NumberOfPedestrians=50,
|
||||
WeatherId=random.choice([1, 3, 7, 8, 14]))
|
||||
settings.randomize_seeds()
|
||||
|
||||
if args.images_to_disk:
|
||||
camera = Camera('DefaultCamera')
|
||||
camera.set_image_size(800, 600)
|
||||
settings.add_sensor(camera)
|
||||
|
||||
scene1 = client1.load_settings(settings)
|
||||
scene2 = client2.load_settings(settings)
|
||||
|
||||
number_of_player_starts = len(scene1.player_start_spots)
|
||||
assert number_of_player_starts == len(scene2.player_start_spots)
|
||||
player_start = random.randint(0, max(0, number_of_player_starts - 1))
|
||||
logging.info(
|
||||
'start episode at %d/%d player start (run forever, press ctrl+c to cancel)',
|
||||
player_start,
|
||||
number_of_player_starts)
|
||||
|
||||
client1.start_episode(player_start)
|
||||
client2.start_episode(player_start)
|
||||
|
||||
frame = 0
|
||||
while True:
|
||||
frame += 1
|
||||
|
||||
meas1, sensor_data1 = client1.read_data()
|
||||
meas2, sensor_data2 = client2.read_data()
|
||||
|
||||
player1 = meas1.player_measurements
|
||||
player2 = meas2.player_measurements
|
||||
|
||||
images1 = [x for x in sensor_data1.values() if isinstance(x, Image)]
|
||||
images2 = [x for x in sensor_data2.values() if isinstance(x, Image)]
|
||||
|
||||
control1 = player1.autopilot_control
|
||||
control2 = player2.autopilot_control
|
||||
|
||||
try:
|
||||
assert len(images1) == len(images2)
|
||||
assert len(meas1.non_player_agents) == len(meas2.non_player_agents)
|
||||
assert player1.transform.location.x == player2.transform.location.x
|
||||
assert player1.transform.location.y == player2.transform.location.y
|
||||
assert player1.transform.location.z == player2.transform.location.z
|
||||
assert control1.steer == control2.steer
|
||||
assert control1.throttle == control2.throttle
|
||||
assert control1.brake == control2.brake
|
||||
assert control1.hand_brake == control2.hand_brake
|
||||
assert control1.reverse == control2.reverse
|
||||
except AssertionError:
|
||||
logging.exception('assertion failed')
|
||||
|
||||
if args.images_to_disk:
|
||||
assert len(images1) == 1
|
||||
images1[0].save_to_disk(filename.format(1, frame))
|
||||
images2[0].save_to_disk(filename.format(2, frame))
|
||||
|
||||
client1.send_control(control1)
|
||||
client2.send_control(control2)
|
||||
|
||||
|
||||
def main():
|
||||
argparser = argparse.ArgumentParser(description=__doc__)
|
||||
argparser.add_argument(
|
||||
'-v', '--verbose',
|
||||
action='store_true',
|
||||
dest='debug',
|
||||
help='print debug information')
|
||||
argparser.add_argument(
|
||||
'--log',
|
||||
metavar='LOG_FILE',
|
||||
default=None,
|
||||
help='print output to file')
|
||||
argparser.add_argument(
|
||||
'--host1',
|
||||
metavar='H',
|
||||
default='127.0.0.1',
|
||||
help='IP of the first host server (default: 127.0.0.1)')
|
||||
argparser.add_argument(
|
||||
'-p1', '--port1',
|
||||
metavar='P',
|
||||
default=2000,
|
||||
type=int,
|
||||
help='TCP port to listen to the first server (default: 2000)')
|
||||
argparser.add_argument(
|
||||
'--host2',
|
||||
metavar='H',
|
||||
default='127.0.0.1',
|
||||
help='IP of the second host server (default: 127.0.0.1)')
|
||||
argparser.add_argument(
|
||||
'-p2', '--port2',
|
||||
metavar='P',
|
||||
default=3000,
|
||||
type=int,
|
||||
help='TCP port to listen to the second server (default: 3000)')
|
||||
argparser.add_argument(
|
||||
'-i', '--images-to-disk',
|
||||
action='store_true',
|
||||
help='save images to disk')
|
||||
|
||||
args = argparser.parse_args()
|
||||
|
||||
logging_config = {
|
||||
'format': '%(levelname)s: %(message)s',
|
||||
'level': logging.DEBUG if args.debug else logging.INFO
|
||||
}
|
||||
if args.log:
|
||||
logging_config['filename'] = args.log
|
||||
logging_config['filemode'] = 'w+'
|
||||
logging.basicConfig(**logging_config)
|
||||
|
||||
logging.info('listening to 1st server at %s:%s', args.host1, args.port1)
|
||||
logging.info('listening to 2nd server at %s:%s', args.host2, args.port2)
|
||||
|
||||
while True:
|
||||
try:
|
||||
|
||||
run_carla_clients(args)
|
||||
|
||||
except TCPConnectionError as error:
|
||||
logging.error(error)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print('\nCancelled by user. Bye!')
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
|
||||
# Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
# Barcelona (UAB).
|
||||
#
|
||||
# This work is licensed under the terms of the MIT license.
|
||||
# For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
41
README.md
41
README.md
|
@ -16,9 +16,14 @@ environmental conditions.
|
|||
For instructions on how to use and compile CARLA, check out
|
||||
[CARLA Documentation](http://carla.readthedocs.io).
|
||||
|
||||
If you want to benchmark your model in the same conditions as in our CoRL’17
|
||||
paper, check out
|
||||
[Benchmarking](http://carla.readthedocs.io/en/latest/benchmark/).
|
||||
|
||||
News
|
||||
----
|
||||
|
||||
- 22.01.2018 Job opening: [C++ (UE4) Programmer](https://drive.google.com/open?id=1Hx0eUgpXl95d4IL9meEGhJECgSRos1T1).
|
||||
- 28.11.2017 CARLA 0.7.0 released: [change log](https://github.com/carla-simulator/carla/blob/master/CHANGELOG.md#carla-070), [release](https://github.com/carla-simulator/carla/releases/tag/0.7.0).
|
||||
- 15.11.2017 CARLA 0.6.0 released: [change log](https://github.com/carla-simulator/carla/blob/master/CHANGELOG.md#carla-060), [release](https://github.com/carla-simulator/carla/releases/tag/0.6.0).
|
||||
|
||||
|
@ -55,6 +60,42 @@ Felipe Codevilla, Antonio Lopez, Vladlen Koltun; PMLR 78:1-16
|
|||
}
|
||||
```
|
||||
|
||||
Building CARLA
|
||||
--------------
|
||||
|
||||
Use `git clone` or download the project from this page. Note that the master
|
||||
branch contains the latest fixes and features, for the latest stable code may be
|
||||
best to switch to the `stable` branch.
|
||||
|
||||
Then follow the instruction at [How to build on Linux][buildlink].
|
||||
|
||||
Unfortunately we don't have yet official instructions to build on other
|
||||
platforms, please check the progress for [Windows][issue21] and [Mac][issue150].
|
||||
|
||||
[buildlink]: http://carla.readthedocs.io/en/latest/how_to_build_on_linux
|
||||
[issue21]: https://github.com/carla-simulator/carla/issues/21
|
||||
[issue150]: https://github.com/carla-simulator/carla/issues/150
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Please take a look at our [Contribution guidelines][contriblink].
|
||||
|
||||
[contriblink]: http://carla.readthedocs.io/en/latest/CONTRIBUTING
|
||||
|
||||
F.A.Q.
|
||||
------
|
||||
|
||||
If you run into problems, check our
|
||||
[FAQ](http://carla.readthedocs.io/en/latest/faq/).
|
||||
|
||||
Jobs
|
||||
----
|
||||
|
||||
We are currently looking for a new programmer to join our team
|
||||
|
||||
* [C++ (UE4) Programmer](https://drive.google.com/open?id=1Hx0eUgpXl95d4IL9meEGhJECgSRos1T1)
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
ProjectID=675BF8694238308FA9368292CC440350
|
||||
ProjectName=CARLA UE4
|
||||
CompanyName=CVC
|
||||
CopyrightNotice="Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonomade Barcelona (UAB), and the INTEL Visual Computing Lab.This work is licensed under the terms of the MIT license.For a copy, see <https://opensource.org/licenses/MIT>."
|
||||
CopyrightNotice="Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de Barcelona (UAB). This work is licensed under the terms of the MIT license. For a copy, see <https://opensource.org/licenses/MIT>."
|
||||
ProjectVersion=0.7.0
|
||||
|
||||
[/Script/UnrealEd.ProjectPackagingSettings]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
@ -104,7 +104,7 @@ void AVehicleSpawnerBase::SpawnVehicleAtSpawnPoint(
|
|||
Vehicle->SpawnDefaultController();
|
||||
auto Controller = GetController(Vehicle);
|
||||
if (Controller != nullptr) { // Sometimes fails...
|
||||
Controller->SetRandomEngine(GetRandomEngine());
|
||||
Controller->GetRandomEngine()->Seed(GetRandomEngine()->GenerateSeed());
|
||||
Controller->SetRoadMap(GetRoadMap());
|
||||
Controller->SetAutopilot(true);
|
||||
Vehicles.Add(Vehicle);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
@ -73,6 +73,8 @@ static void ClearQueue(std::queue<T> &Queue)
|
|||
AWheeledVehicleAIController::AWheeledVehicleAIController(const FObjectInitializer& ObjectInitializer) :
|
||||
Super(ObjectInitializer)
|
||||
{
|
||||
RandomEngine = CreateDefaultSubobject<URandomEngine>(TEXT("RandomEngine"));
|
||||
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
PrimaryActorTick.TickGroup = TG_PrePhysics;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
@ -98,14 +98,10 @@ public:
|
|||
/// @{
|
||||
public:
|
||||
|
||||
void SetRandomEngine(URandomEngine *InRandomEngine)
|
||||
{
|
||||
RandomEngine = InRandomEngine;
|
||||
}
|
||||
|
||||
UFUNCTION(Category = "Random Engine", BlueprintCallable)
|
||||
URandomEngine *GetRandomEngine()
|
||||
{
|
||||
check(RandomEngine != nullptr);
|
||||
return RandomEngine;
|
||||
}
|
||||
|
||||
|
@ -221,13 +217,13 @@ private:
|
|||
private:
|
||||
|
||||
UPROPERTY()
|
||||
ACarlaWheeledVehicle *Vehicle;
|
||||
ACarlaWheeledVehicle *Vehicle = nullptr;
|
||||
|
||||
UPROPERTY()
|
||||
URoadMap *RoadMap;
|
||||
URoadMap *RoadMap = nullptr;
|
||||
|
||||
UPROPERTY()
|
||||
URandomEngine *RandomEngine;
|
||||
URandomEngine *RandomEngine = nullptr;
|
||||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
bool bAutopilotEnabled = false;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
@ -176,7 +176,8 @@ void ACarlaGameModeBase::BeginPlay()
|
|||
VehicleSpawner->SetSeed(CarlaSettings.SeedVehicles);
|
||||
VehicleSpawner->SetRoadMap(RoadMap);
|
||||
if (PlayerController != nullptr) {
|
||||
PlayerController->SetRandomEngine(VehicleSpawner->GetRandomEngine());
|
||||
PlayerController->GetRandomEngine()->Seed(
|
||||
VehicleSpawner->GetRandomEngine()->GenerateSeed());
|
||||
}
|
||||
} else {
|
||||
UE_LOG(LogCarla, Error, TEXT("Missing vehicle spawner actor!"));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB), and the INTEL Visual Computing Lab.
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue