LGSVL-python API使用方法

pythonAPI总述

LGSVL模拟器可以实时与PythonAPI进行功能通信,你可以用其来操控已加载场景中的物体的位置、车辆的运动、召回传感器配置和数据、控制天气、时间状态以及其它。
API调用的监听接口是在config.yml中定义的。可以在这里查找更多的关于配置文件和命令行参数的信息。

要求

PythonAPI需要在Python 3.5或者更新的版本中运行。

快速开始 quickstart

PythonAPI放在与模拟器不同的代码仓库:https://github.com/lgsvl/PythonAPI
从github仓库下载或者克隆后,按如下步骤运行:
1.运行如下命令来安装Python文件和必要的依赖;

 pip3 install --user -e .

2.运行模拟器(从binary.exe或者从Unity编辑器),模拟器默认从8181接口监听主机的连接。
3.点击Open Browser按钮启动模拟器的交互页面。
4.在默认地图和车辆下载完成后,找到Simulation页。
5.创建一个新的模拟,为其命名并确保打开API Only选项,点击Submit。
6.选择新创建的模拟,点击右下方的Play按钮。
7.运行一下案例来查看API的动作:

 ./quickstart/05-ego-drive-in-circle.py

这会加载BorregasAve.unity场景,实例化一个EGO车辆,然后要求你敲击Enter键来使车辆进行环形驾驶。
当脚本运行的时候,其会将油门和方向盘指令应用到车辆中,使其产生响应的运动。

核心概念

模拟器和API之间的通讯是靠运行在8181接口上的websocket服务器发送json来实现的。API客户端可以运行在同一机器或者处在同一局域网的其它机器。
API主要有以下几个类:

  • Simulator-连接至模拟器以及创建其它物体的主要对象
  • Agent-车辆和行人对象的父类
  • EgoVehicle-具有精确物理模拟以及传感器的EGO 车辆
  • NpcVehicle-具有简化的物理特性的NPC车辆,常用作创建许多背景车辆
  • Pedestrian-在人行道上行走的行人
    Vehicle和Pedestrian是Agent的子类,其都有像转换、位置、速度等共同的属性。
    API中的坐标返回的值是Unity坐标系中的值,其基本单位是米,且为左手坐标系,X向左,Z向前,Y向上。
    模拟器类提供转换坐标系为经纬度的方法,反之亦可。

Simulation

想要连接至模拟器,你就需要一个Simulator类的实例

import lgsvl
sim = lgsvl.Simulator(address = "localhost", port = 8181)

你可以制定不同的地址作为主机名或者IP地址,默认情况下,只有8181接口用作API连接,一次只能有一台客户端连接到模拟器。
然后,加载场景(“map”),这是通过load的方法实现的:

sim.load(scene = "BorregasAve", seed = 650387)

场景是Web UI中代表地图名的字符串,目前可用的场景为:

  • BorregasAVE-小的郊区地图
  • AutonomousStuff-小的办公公园
    Seed(可选)是一个整数(-2,147,483,648 - 2,147,483,647),它决定着NPC和雨滴效果的随机程度。

可以在Web UI Maps页面看到可用的场景列表。
一旦已经加载了场景,你可以将“行动者”实例化,并运行模拟。参照Agents部分来学习如何创建车辆和行人
加载场景需要一定的时间,可以通过reset方法重置场景来初始化状态,而不用重新加载:

sim.reset()

这会移除已经注册的任何车辆或回调函数。
在设置场景至目标状态后,你可以开始高级时间,当python代码在模拟器中的执行时间是停止的。想要模拟器在实际时间状态运行,调用run方法:

sim.run(time_limit = 5.0)

run有可选参数来制定模拟的运行时间,默认为0代表一直运行。

非实时模拟运行

模拟器可以根据计算机的性能来进行比真实时间更快的高速模拟,可以通过调用run方法的time_scalw参数:

sim.run(time_limit = 6, time_scale = 2)

run的第二个参数指定以多快的速度来运行模拟,如果计算机足够快的话,该模拟将会在3秒完成(6s/2),但是会产生6个虚拟秒时间的数据。如果只指定了time)_scale或者time_limit=0,模拟器会一直以非真实时间运行。
同理,time_scale也可以设置的比1小,这代表运行的速度比真实世界的时间慢。

Agents 行动者

你可以创建车辆和行人,通过使用add_agent方法,这是Simulator的对象。e.g.

ego = sim.add_agent(name = "Lincoln2017MKZ (Apollo 5.0)", \
agent_type = lgsvl.AgentType.EGO, state = None)

这会从Web UI Vehicle页面创建Lincoln2017MKZ (Apollo 5.0)这一车辆,其它可用的Agents类为:

  • AgentType.EGO - EGO vehicle
  • AgentType.NPC - NPC vehicle
  • AgentType.PEDESTRIAN - pedestrian
    每个agent类都预设了你可以使用的名字,目前可用的EGO车辆有:
  • Jaguar2015XE (Apollo 3.0) - Apollo 3.0 vehicle
  • Jaguar2015XE (Apollo 5.0) - Apollo 5.0 vehicle
  • Jaguar2015XE (Autoware) - Autoware vehicle
  • Lexus2016RXHybrid (Autoware) - Autoware vehicle
  • Lincoln2017MKZ (Apollo 5.0) - Apollo 5.0 vehicle
    可用的NPC车辆有:
  • Sedan
  • SUV
  • Jeep
  • Hatchback
  • SchoolBus
  • BoxTruck

可用的行人类有:

  • Bob
  • EntrepreneurFemale
  • Howard
  • Johny
  • Pamela
  • Presley
  • Red
  • Robin
  • Stephen
  • Zoe
    如果输入了不正确的名字,会提示Python异常。
    另外,你还可以在场景中创建处于特定位置和旋转角度的agents对象。你可以利用AgentState类,e.g.
state = lgsvl.AgentState()
state.transform.position = lgsvl.Vector(10, 0, 30)
state.transform.rotation.y = 90
ego = sim.add_agent("Lincoln2017MKZ (Apollo 5.0)", lgsvl.AgentType.EGO, state)

这会创建一个处于x=70,z=30,围绕垂直轴旋转90°的车辆,位置和旋转是处于世界坐标系中的。
当然你也可以随时调正位置、旋转、速度、角速度:

s = ego.state
s.velocity.x = -50
ego.state = s

这会使x方向每秒发生-50米的偏移,而y和z的速度则不变化。
所有的Agents都有以下共同的属性:

  • state - 设置行动者的状态属性
  • transform - property to get transform member of the state (shortcut for state.transform)
  • bounding_box - property to get bounding box in local coordinate space. Note that bounding box is not centered around (0,0,0) - it depends on the actual geometry of the agent.
  • on_collision - method to set a callback function to be called when the agent collides with something (other agent or static obstacle), see callbacks section for more information.

EGO vehicle

EGO 车辆有以下的额外属性:

  • apply_control - 指定车辆油门、刹车、转向或其它动作

sticky=True 应用这些值到所有模拟器的迭代中

  • get_sensors - 返回传感器列表 sensors
  • connect_bridge - 连接到ROS或Cyber RT的方法
  • bridge_connected - 布尔属性,如果连接则为True

你可以通过以下几种方式控制EGO车辆的运动:手动指定状态、应用手动控制、通过bridge连接。
控制油门为20%的示例:

ego = sim.add_agent("Lincoln2017MKZ (Apollo 5.0)", lgsvl.AgentType.EGO)
c = lgsvl.VehicleControl()
c.throttle = 0.2
ego.apply_control(c, True)

NPC 车辆

你可以创建多辆NPC车辆,它们可以沿着车道线或者指定的航点进行行驶。NPC 车辆有以下属性:
change_lane - 让车辆变道的方法
follow - 使车辆沿着航点的方法
follow_closest_lane - 使车辆沿着车道线行驶的方法
on_waypoint_reached - 回调车辆到达的航点位置的方法on_stop_line - 回调车辆到达停止位置的方法on_lane_change - 车辆变道时的回调函数
可以通过以下方式控制NPC车辆的运动:手动指定状态、指示其沿着车道线或者航点行驶。
使车辆沿着航点行驶需要准备DriveWaypoint对象列表,并调用folow方法:

npc = sim.add_agent("Sedan", lgsvl.AgentType.NPC)
waypoints = [
  lgsvl.DriveWaypoint(lgsvl.Vector(1,0,3), 5, lgsvl.Vector(0, 0, 0), 0, False, 0),
  lgsvl.DriveWaypoint(lgsvl.Vector(5,0,3), 10, lgsvl.Vector(0, 0, 0), 0, False, 0),
  lgsvl.DriveWaypoint(lgsvl.Vector(1,0,5), 5, lgsvl.Vector(0, 0, 0), 0, False, 0),
]
npc.follow(waypoints, loop=True)

每一个航点都在世界坐标系中有一个坐标信息,一个设定的速度m/s,一个设定的偏转角度,作为欧拉角的矢量,一个车辆保持空闲的设定的等待时间,以及NPC车辆在空闲状态下是否激活的布尔值,以及一个可选的激活距离。NPC车辆会无视交通规则,并且会无视碰撞驶向下一航点。NPC车辆会以在DriveWaypoint中设置的角度,以内插的方式穿过航点。激活距离,如果使用的话,提供了一种暂停NPC车辆的方式,如果ego车辆接近的话。当NPC车辆与EGO车辆的距离低于设定的激活距离的话,NPC车辆便会开始运动。
follow_closest_lane会使npc车辆沿着最近的线行驶,当到达十字路口时,会随机决定是直行还是转向。

Pedestrians 行人

你可以创建Pedestrian行动着,这可以在人行道上创建行人,并使他们行走。
Pedestrian有以下属性:
walk_randomly - 使行人在人行道随机行走方法
follow - 使行人沿着航点行走方法
on_waypoint_reached -
设置回调所抵达航点的回调函数方法
你可以通过以下方法控制行人的运动:手动指定状态、指示他们沿着航点行走或随机行走。
想要使行人沿着航点行走,你需要准备好一个WalkWaypoin对象列表,并调用follow方法:

npc = sim.add_agent("Bob", lgsvl.AgentType.PEDESTRIAN)
waypoints = [
  lgsvl.WalkWaypoint(lgsvl.Vector(1,0,3), 5, 0),
  lgsvl.WalkWaypoint(lgsvl.Vector(5,0,3), 10, 0),
  lgsvl.WalkWaypoint(lgsvl.Vector(1,0,5), 5, 0),
]
npc.follow(waypoints, loop=True)

与npc车辆类似,你也可以设置等待时间和激活距离,当车辆到达一定距离行人才开始出现并进行运动。

回调 Callbacks

PythonAPI可以激活回调函数来提醒你在模拟运行中的特定事件。回调函数在Simulator.run方法中激活,并且当回调函数运行时,仿真世界里的时间会暂停。一旦回调时间重新开始,仿真也开始重新执行。你可以调用Simulator.stop来结束进一步的执行并立刻跳出回调函数。

Agent Callbacks 行动者回调函数

collision-当行动者与其它东西发生碰撞时调用
用法示例:

def on_collision(agent1, agent2, contact):
  name1 = "STATIC OBSTACLE" if agent1 is None else agent1.name
  name2 = "STATIC OBSTACLE" if agent2 is None else agent2.name
  print("{} collided with {} at {}".format(name1, name2, contact))

ego.on_collision(on_collision)

回调函数接受三个参数:(agent1,agent2,contact)-前两个是发生碰撞的行动者,其中一个可以为空,例如与建筑物或交通灯杆发生碰撞时,第三个是碰撞点的世界坐标位置。

EgoVehicle Callbacks

除了Agent类的回调函数,EgoVehicle还有另一个回调函数。
on_custon-当传感器插件发送回调函数时调用;可以接收三个参数:(agent, kind, context)-行动者距离,传感器插件的类型(字符串),JSON文本。
参看Sensor Plugins.

NPC Vehicle Callbacks

除了Agent类的回调函数,NpcVehicle还有另三个回调函数。
waypoint_reached-当车辆到达一个航点时调用;接收两个参数:(agent, index)-行动者距离和航点索引(整数)
stop_line-当车辆在交通灯或者通知标志的停车线停下时调用;接收一个参数:(agent)-行动者距离
lane_change-当车辆开始变道时调用;接收一个参数:(agent)-行动者距离

Pesrstrian Callbacks

除了Agent类的回调函数,Pedestrian还有另一个回调函数。
waypoint_reached-当行人到达航点时调用;接收两个参数:(agent, index)-行动者距离和航点索引(整数)

Sensor 传感器

EGO vehicles有绑定的传感器。你可以通过调用EgoVehicle.get_Sensors()来获得它们的列表,它会返回一个如下类的列表:

  • CameraSensor-参考Camera传感器
  • LidarSensor-参考Lidar传感器
  • ImuSensor-参考IMU传感器
  • GpsSensor-参考GPS传感器
  • RadarSensor-参考Radar传感器
  • CanBusSensor-参考CAN bus传感器

每个传感器都有以下共同的属性:

  • name-传感器的名字,用以区分同一类传感器的不同个,例如选择连接到EGO车辆的多个摄像头中的一个。
  • transform-包含了与行动者变换相关的位置和角度信息属性
    +enable-布尔值,如果允许捕获和发送数据至ROS或Cyber,将其设为True

Camera Sensor摄像头传感器

摄像头传感器有以下只读属性:

  • frequency-捕获和发送至ROS或Cyber图像的频率
  • width-图像宽度
  • height-图像高度
  • fov-垂直视角
  • near_plane-近面距离
  • far_plane-远面距离
  • format-图像格式(“RGB”代表24位真彩图,“DEPTH”代表8位灰度深度图像,“SEMANTIC”代表24位真彩分割图像)
    摄像头的图像可以调用save来保存至硬盘:
ego = sim.add_agent("Lincoln2017MKZ (Apollo 5.0)", lgsvl.AgentType.EGO)

for sensor in ego.get_sensors():
  if sensor.name = "Main Camera":
    sensor.save("main-camera.png", compression=0)

save方法接收与运行中的模拟器相关的路径,可以选择compression(0...9)来选择保存png格式的品质,选择quality(0...100)选择jpeg格式的品质。

IMU Sensor

你可以使用IMU sensor来获得车辆的位置。所有的IMU可以提供的测量数据可以通过使用agent的transform属性来获得。

GPS Sensor

可以通过调用data来获得当前的gps位置信息:

data = gps_sensor.data()
print("Latitude:", data.latitude)

返回的数据会包括以下内容:

  • latitude

  • longitude

  • northin

  • easting

  • altitude

  • orientation- 沿向上的轴旋转的角度

Radar Sensor

目前雷达传感器只能用来获取车辆的位置和偏转角度,雷达测量数据可以通过设置传感器的enable属性来将其传递给ROS或Cyber。

CAN bus

目前CAN bus只能用来获得车辆的位置和偏转角度信息,测量数据可以通过设置传感器的enable属性来将其传递给ROS或Cyber。

天气、时间控制

你可以通过读或写weather属性来控制模拟器的天气属性,你可以设置rain,fog, witness(浮点0...1). e.g.

w = sim.weather
w.rain = 0.5     # set rain to 50%
sim.weather = w

改变一天中的时间可以控制场景是处于白天还是夜晚。通过读取time_of_day来获得当前时间:

print("Current time of day:", sim.time_of_day)

这会返回一个处于0-24的浮点值,可以通过调用set_time_of_day来设置一天中的时间:

sim.set_time_of_day(10, fixed=True)

这会将时间设定在10:00am,属性fixed的布尔值属性会调节模拟器是否自动进行时间流逝还是冻结时间(fixed=True).

可控制的对象

可控对象是指你可以通过Python API来控制其动作的对象。每一个可控对象有其自己的valid actions(例如绿色、红色、黄色、激发、等待、循环),可以通过control policy来进行控制,这为控制动作制定了规则。
例如,交通灯是一个可控对象,你可以通过升级控制策略来改变其行为:
"trigger=50;green=1;yellow=1.5;red=2;loop"

  • trigger=50-当ego车辆处于50米以内时激活
  • green=1-改变当前状态为green并等待1秒
  • yellow=1.5-改变当前状态为yellow,并等待1.5秒
  • red=2-改变当前状态为red并等待2秒
  • loop-从控制测策略的开始状态进行循环
    可控对象的类型:
  • signal
  • cone

所有的可控对象可以动态的添加或移除,当reset()被调用时,所有的可控对象被移除,新的可控对象被添加回来(如果地图中存在的话)。 可控对象可以作为插件在运行时载入。插件必须包含IControllable并且可以在Assets/Exteral/Controllables文件夹内被模拟器构建程序构建。
获得一个场景中的可控对象列表:

controllables = sim.get_controllables()

对于一个感兴趣的可控对象,你可以获得以下信息:

signal = controllables[0]
print("Type:", signal.type)
print("Transform:", signal.transform)
print("Current state:", signal.current_state)
print("Valid actions:", signal.valid_actions)

就控制策略而言,每个可控对象都有默认的控制策略(只读),当你第一次加载一个场景或重置场景为出示状态时,可控对象会将其控制策略变更为默认控制策略。
你可以通过以下方式获得默认控制策略和当前控制策略:

print("Default control policy:", signal.default_control_policy)
print("Current control policy:", signal.control_policy)

要改变当前的控制策略,你可以创建一个新的控制策略,并通过调用control函数来使用:

control_policy = "trigger=50;green=1;yellow=1.5;red=2;loop"
signal.control(control_policy)

要添加可控插件并设置对象状态,参考如下:

state = lgsvl.ObjectState()
state.transform.position = lgsvl.Vector(0,0,0)
state.transform.rotation = lgsvl.Vector(0,0,0)
state.velocity = lgsvl.Vector(0,10,0)
state.angular_velocity = lgsvl.Vector(6.5,0,0)

cone = sim.controllable_add("TrafficCone", state)

要获得可控对象插件状态:

cone.object_state

要设置可控对象插件状态:

state = lgsvl.ObjectState()
state.transform.position = lgsvl.Vector(0, 0, -10)
cone.object_state = state

Helper Functions 帮助函数

模拟器类提供如下帮助函数:

  • version-版本
  • current_scene-以字符串返回当前运行场景的名称,如果未载如为None
  • current_frame-返回当前模拟的帧数(整数)
  • current_time-返回当前仿真时间,单位秒(浮点数)
  • get_spawn-返回代表地图中放置车辆的较好位置列表,这些列表可能时空的,取决于unity中地图的情况。以整数形式返回position,rotation
  • get_agents-返回包含了可以通过add_agent添加的运动者的列表。
    模拟器提供以下两种函数来在GPS坐标系中模拟Unity坐标系:
  • map_to_gps-将地图变换为GPS位置,返回用GPS Sensordata方法一样的数据
  • map_from_gps-将GPS信息转换成坐标系
  • raycast-从指定位置射出一束光线,返回其接触最近的物体
    map_from_gps接受两种不同的输入- latitude/longitude 或 northing/easting
tr1 = sim.map_from_gps(latitude=10, longitude=-30)
tr2 = sim.map_from_gps(northing=123455, easting=552341)

raycast可以以如下方式使用:

direction = lgsvl.Vector(1, 0, 0)
hit = sim.raycast(origin, direction, layer_mask=1)
if hit:
  print("Distance right:", hit.distance)

这会从(10,0,20)在x轴正方向发生光束,如果接触到物体,会返回RaycastHit对象的distance,point,normal,否则会返回None.
当你使用raycast时候需要指定layer_mask,来指定检查“碰撞”的物体,这与unity中检测项目的实际值的层是相对应的。

Changelog

  • 2020-01-30 拓展可控对象以支持插件
  • 2019-09-05 拓展DriveWaypoint以支持角度、空闲时间和激活距离
    增加了可控对象,使用Simulatoe.get_controllables
  • 2019-08-12 增加time_scale参数来是模式器以非真实世界时间进行模拟
    添加Simulatoe.loadseed参数,来检测NPC
  • 2019-04-19 最初发布

https://github.com/lgsvl/simulator/blob/master/Docs/docs/python-api.md

你可能感兴趣的:(LGSVL-python API使用方法)