Fill Python API tutorial

This commit is contained in:
nsubiron 2018-12-16 00:02:22 +01:00
parent e464913014
commit 668c509484
3 changed files with 277 additions and 57 deletions

View File

@ -8,7 +8,7 @@
<h3>Quick start</h3>
* [Getting started](getting_started.md)
* [Python API overview](python_api_overview.md)
* [Python API tutorial](python_api_overview.md)
* [Configuring the simulation](configuring_the_simulation.md)
<!-- * [Measurements](measurements.md) -->
* [Cameras and sensors](cameras_and_sensors.md)

View File

@ -1,102 +1,186 @@
<h1>Python API overview</h1>
<h1>Python API tutorial</h1>
![Client window](img/client_window.png)
In this tutorial we introduce the basic concepts of the CARLA Python API, as
well as an overview of its most important functionalities. The reference of all
classes and methods available can be found at
[Python API reference](python_api.md).
First we need to introduce a few core concepts:
!!! note
**This document applies only to the latest development version**. <br>
The API has been significantly changed in the latest versions starting at
0.9.0. We commonly refer to the new API as **0.9.X API** as opposed to
the previous **0.8.X API**.
First of all, we need to introduce a few core concepts:
- **Actor:** Actor is anything that plays a role in the simulation and can be
moved around, examples of actors are vehicles, pedestrians, and sensors.
- **Blueprint:** Before spawning an actor you need to specify its attributes,
and that's what blueprints are for. We provide a blueprint library with
the definitions of all the actors available for you to choose.
the definitions of all the actors available.
- **World:** The world represents the currently loaded map and contains the
functions for converting a blueprint into a living actor.
functions for converting a blueprint into a living actor, among other. It
also provides access to the road map and functions to change the weather
conditions.
For the full list of methods available take a look at the
[Python API reference](python_api.md).
#### Connecting and retrieving the world
#### Connecting and retrieving the current world
To connect to a simulator we need to create a "Client" object providing IP
address and port of a running instance of the simulator.
To connect to a simulator we need to create a "Client" object, and to do so we
need to provide the IP address and port of a running instance of the simulator
```py
client = carla.Client('localhost', 2000)
```
It is very convenient to set the time-out, otherwise networking operations may
block forever.
First thing most scripts do is setting the client time-out. This time-out sets a
time limit to all networking operations, if the time-out is not set networking
operations may block forever.
```py
client.set_timeout(10.0) # seconds
```
Next step is retrieving the active world, we use this world for spawning actors,
changing weather, and getting road info.
Once we have the client configured we can directly retrieve the world
```py
world = client.get_world()
```
#### Blueprint library
Typically we won't need the client object anymore, all the objects created by
the world will connect to the IP and port provided if they need to. This
operations are usually done in the background and are transparent to the user.
Before we can create an actor, we need to take a look at the blueprint library.
#### Blueprints
A blueprint contains the information necessary to create a new actor. For
instance, if the blueprint defines a car, we can change its color here, if it
defines a lidar, we can decide here how many channels the lidar will have. A
blueprints also has an ID that uniquely identifies it and all the actor
instances created with it. Examples of IDs are "vehicle.nissan.patrol" or
"sensor.camera.depth".
The list of all available blueprints is kept in the **blueprint library**
```py
blueprint_library = world.get_blueprint_library()
```
You can filter with wildcards.
The library allows us to find specific blueprints by ID, filter them with
wildcards, or just choosing one at random
Some of the attributes of the blueprints can be modified.
```py
# Find specific blueprint.
collision_sensor_bp = blueprint_library.find('sensor.other.collision')
# Chose a vehicle blueprint at random.
vehicle_bp = random.choice(blueprint_library.filter('vehicle.bmw.*'))
```
Some of the attributes of the blueprints can be modified while some other are
just read-only. For instance, we cannot modify the number of wheels of a vehicle
but we can change its color
```py
vehicles = blueprint_library.filter('vehicle.*')
bikes = [x for x in vehicles if int(x.get_attribute('number_of_wheels')) == 2]
for bike in bikes:
bike.set_attribute('color', '255,0,0')
```
Modifiable attributes also come with a list of recommended values
```py
for attr in blueprint:
if attr.is_modifiable:
blueprint.set_attribute(attr.id, random.choice(attr.recommended_values))
```
The blueprint system has been designed to ease contributors adding their custom
actors directly in Unreal Editor, we'll add a tutorial on this soon, keep tuned!
#### Spawning actors
Let's just go for a practical example. The following code adds a red Mustang to
the simulation and enables its autopilot so the car can drive freely around the
city on its own
Once we have the blueprint set up, spawning an actor is pretty straightforward
```py
blueprint = blueprint_library.find('vehicle.ford.mustang')
blueprint.set_attribute('color', '255,0,0')
transform = carla.Transform(carla.Location(x=230, y=195, z=40), carla.Rotation(yaw=180))
vehicle = world.spawn_actor(blueprint, transform)
transform = Transform(Location(x=230, y=195, z=40), Rotation(yaw=180))
actor = world.spawn_actor(blueprint, transform)
```
Spawn actor function has two flavours, `spawn_actor` and `try_spawn_actor`.
The spawn actor function comes in two flavours, `spawn_actor` and
`try_spawn_actor`. The former will raise an exception if the actor could not be
spawned, the later will return `None` instead. The most typical cause of
failure is collision at spawn point, meaning the actor does not fit at the spot
we chose; probably another vehicle is in that spot or we tried to spawn into a
building.
To ease the task of finding a spawn location, each map provides a list of
recommended transforms
```py
spawn_points = world.get_map().get_spawn_points()
```
We add more on the map class later in this tutorial.
Finally, the spawn functions have an optional argument that controls whether the
actor is going to be attached to another actor. This is specially useful for
sensors. In the next example the camera remains rigidly attached to our vehicle
during the rest of the simulation
```py
camera = world.spawn_actor(camera_bp, relative_transform, attach_to=my_vehicle)
```
Note that in this case, the transform provided is treated relative to the parent
actor.
#### Handling actors
Actors can also be teleported and moved around the city, for that we have
exposed the `set_location` and `set_transform` methods
Once we have an actor alive in the world, we can move this actor around and
check its dynamic properties
```py
location = vehicle.get_location()
location.x += 10.0
vehicle.set_location(location)
location = actor.get_location()
location.z += 10.0
actor.set_location(location)
print(actor.get_acceleration())
print(actor.get_velocity())
```
`get_transform()`, `get_velocity()`, `get_acceleration()`.
`set_simulate_physics(False)`.
Once we are tired of an actor we can remove it from the simulation with
We can even freeze and actor by disabling its physics simulation
```py
vehicle.destroy()
actor.set_simulate_physics(False)
```
And once we are tired of an actor we can remove it from the simulation with
```py
actor.destroy()
```
Note that actors are not cleaned up automatically when we the Python script
finishes, if we want to get rid of them we need to explicitly destroy them.
!!! important
**Known issue:** To improve performance, most of the methods send requests
to the simulator asynchronously. The simulator queues each of these
requests, but only has a limited amount of time each update to parse them.
If we flood the simulator by calling "set" methods too often, e.g.
set_transform, the requests will accumulate a significant lag.
#### Vehicles
and in the special case of vehicles, they can be controlled too in the usual way
Vehicles are a special type of actors that provide a few methods specific for
wheeled vehicles. Apart from the handling methods common to all actors, vehicles
can also be controlled by providing throttle, break, and steer values
```py
vehicle.apply_control(carla.VehicleControl(throttle=1.0, steer=-1.0))
```
These are all the parameters of the VehicleControl
These are all the parameters of the VehicleControl object and their default
values
```py
carla.VehicleControl(
@ -109,28 +193,164 @@ carla.VehicleControl(
gear = 0)
```
`set_autopilot()`, `bounding_box`.
Our vehicles also come with a handy autopilot
```py
vehicle.set_autopilot(True)
```
As has been a common misconception, we need to clarify that this autopilot
control is purely hard-coded into the simulator and it's not based at all in
machine learning techniques.
Finally, vehicles also have a bounding box that encapsulates them
```py
box = vehicle.bounding_box
print(box.location) # Location relative to the vehicle.
print(box.extent) # XYZ half-box extents in meters.
```
#### Sensors
Now let's attach a camera to this vehicle so we can take a look at what's going
on, we are going to save this images to disk
Sensors are a special type of actor that produce a stream of data. Sensors are
such a key component of CARLA that they deserve their own documentation page, so
here we'll limit ourselves to show a small example of how sensors work
```py
blueprint = world.get_blueprint_library().find('sensor.camera.rgb')
transform = carla.Transform(carla.Location(x=0.5, z=1.8))
camera = world.spawn_actor(blueprint, transform, attach_to=vehicle)
camera.listen(lambda image: image.save_to_disk('%06d.png' % image.frame_number))
camera_bp = blueprint_library.find('sensor.camera.rgb')
camera = world.spawn_actor(camera_bp, relative_transform, attach_to=my_vehicle)
camera.listen(lambda image: image.save_to_disk('output/%06d.png' % image.frame_number))
```
the callback function passed to the `listen` method will be called every time a
new image is received. This callback is executed asynchronously, this
considerably speeds up the parsing of images. Now it is possible to do things
like saving images to disk keeping up with the speed of the simulator.
In this example we have attached a camera to a vehicle, and told the camera to
save to disk each of the images generated.
The full list of sensors and their measurement is explained in
[Cameras and sensors](cameras_and_sensors.md).
#### Other actors
Apart from vehicles and sensors, there are many other actors in the world. The
full list can be requested to the world
```py
actor_list = world.get_actors()
```
The actor list object returned has functions for finding, filtering, and
iterating actors
```py
# Find an actor by id.
actor = actor_list.find(id)
# Print the location of all the speed limit signs in the world.
for speed_sign in actor_list.filter('traffic.speed_limit.*'):
print(speed_sign.get_location())
```
Among the actors you can find in this list are
* **Traffic lights** with a `state` property to check the light's current state.
* **Speed limit signs** with the speed codified in their type_id.
* The **Spectator** actor that can be used to move the view of the simulator window.
#### Changing the weather
#### Map
The lighting and weather conditions can be requested and changed with the world
object
```py
weather = carla.WeatherParameters(
cloudyness=80.0,
precipitation=30.0,
sun_altitude_angle=70.0)
world.set_weather(weather)
print(world.get_weather())
```
For convenience, we also provided a list of predefined weather presets that can
be directly applied to the world
```py
world.set_weather(carla.WeatherParameters.WetCloudySunset)
```
The full list of presets can be found in the
[WeatherParameters reference](python_api.md#carlaweatherparameters).
#### Map and waypoints
One of the key features of CARLA is that our roads are fully annotated, all our
maps come accompanied by an OpenDrive file that defines the road layout.
Furthermore, we provide a higher level API for querying and navigating this
information.
These objects were a recent addition to our API and are still in heavy
development, we hope to make them soon much more powerful that are now.
Let's start by getting the map of the current world
```py
map = world.get_map()
```
For starters, the map has a `name` attribute that matches the name of the
currently loaded city, e.g. Town01. And, as we've seen before, we can also ask
the map to provide a list of recommended locations for spawning vehicles,
`map.get_spawn_points()`.
However, the real power of this map API comes apparent when we introduce
waypoints. We can tell the map to give us a waypoint on the road closest to our
vehicle
```py
waypoint = map.get_waypoint(vehicle.get_location())
```
This waypoint's `transform` is located on a drivable lane, and it's oriented
according to the road direction at that point.
Waypoints also have function to query the "next" waypoints, this method returns
a list of waypoints at a certain distance that can be accessed from this
waypoint following the traffic rules. In other words, if a vehicle is placed in
this waypoint, give me the list of posible locations that this vehicle can drive
to. Let's see a practical example
```py
# Retrieve the closest waypoint.
waypoint = map.get_waypoint(vehicle.get_location())
# Disable physics, in this example we're just teleporting the vehicle.
vehicle.set_simulate_physics(False)
while True:
# Find next waypoint 2 meters ahead.
waypoint = random.choice(waypoint.next(2.0))
# Teleport the vehicle.
vehicle.set_transform(waypoint.transform)
```
The map object also provides methods for generating in bulk waypoints all over
the map at an approximated distance between them
```py
map.generate_waypoints(2.0)
```
For routing purposes, it is also possible to retrieve a topology graph of the
roads
```py
waypoint_tuple_list = map.get_topology()
```
this method returns a list of pairs (tuples) of waypoints, for each pair, the
first element connects with the second one. Only the minimal set of waypoints to
define the topology are generated by this method, only a waypoint for each lane
for each road segment in the map.
Finally, to allow access to the whole road information, the map object can be
converted to OpenDrive format, and saved to disk as such.

View File

@ -7,7 +7,7 @@ pages:
- Home: 'index.md'
- Quick start:
- 'Getting started': 'getting_started.md'
- 'Python API overview': 'python_api_overview.md'
- 'Python API tutorial': 'python_api_overview.md'
- 'Configuring the simulation': 'configuring_the_simulation.md'
# - 'Measurements': 'measurements.md'
- 'Cameras and sensors': 'cameras_and_sensors.md'