自动驾驶仿真工具之CARLA使用小结
大家好,我已经把CSDN上的博客迁移到了知乎上,欢迎大家在知乎关注我的专栏慢慢悠悠小马车(https://zhuanlan.zhihu.com/duangduangduang)。希望大家可以多多交流,互相学习。
接触CARLA有近一个月的时间了,主要实现了在其中控制车辆沿规划的轨迹行驶。我使用CARLA的目的在于验证自己的决策规划算法是否正确,此处暂时不提决策规划的内容,只说如何将轨迹输入到CARLA仿真环境中。
我采用的方式是决策规划模块输出的轨迹封装成ROS Message的形式发布出来,将CARLA/PythonAPI/examples/automatic_control.py改成一个订阅该topic的节点,然后周期性的将轨迹传送到CARLA server端。server端有AWheeledVehicleAIController 与自动驾驶模式对应,并且在这个类中有SetFixedRoute()函数可以设定自车的行驶轨迹。可惜的是,PythonAPI中并没有这个函数,那么,就需要自定义API啦。定义API、打通server和client端的联系,套路对于每个函数都是一样的,这里以SetAutopilot(bool Enable)函数为例,请自行补充默认参数设置和头文件的相关声明。
-
在AWheeledVehicleAIController(或其他位置)中定义好SetAutopilot(bool Enable)的具体行为;
-
在CarlaServer.cpp中
BIND_SYNC(set_actor_autopilot) << [this]( cr::ActorId ActorId, bool bEnabled) -> R<void> { REQUIRE_CARLA_EPISODE(); auto ActorView = Episode->FindActor(ActorId); if (!ActorView.IsValid()) { RESPOND_ERROR("unable to set autopilot: actor not found"); } auto Vehicle = Cast<ACarlaWheeledVehicle>(ActorView.GetActor()); if (Vehicle == nullptr) { RESPOND_ERROR("unable to set autopilot: actor does not support autopilot"); } auto Controller = Cast<AWheeledVehicleAIController>(Vehicle->GetController()); if (Controller == nullptr) { RESPOND_ERROR("unable to set autopilot: vehicle controller does not support autopilot"); } Controller->SetAutopilot(bEnabled); return R<void>::Success(); };
-
在Client.cpp中
void Client::SetActorAutopilot(rpc::ActorId vehicle, const bool enabled) { _pimpl->AsyncCall("set_actor_autopilot", vehicle, enabled); }
-
在 Simulator.h中
void SetVehicleAutopilot(Vehicle &vehicle, bool enabled = true) { _client.SetActorAutopilot(vehicle.GetId(), enabled); }
-
在Vehicle.cpp中
void Vehicle::SetAutopilot(bool enabled) { GetEpisode().Lock()->SetVehicleAutopilot(*this, enabled); }
-
在Actor.cpp中
.def("set_autopilot", &cc::Vehicle::SetAutopilot, (arg("enabled") = true))
-
在PythonAPI中就可以调用set_autopilot()函数了。
world.player.set_autopilot(True)
非容器(stl的vector、map,Python的list等)类参数按上述操作即可成功,但是对于vector、list参数的传递和解析,一直没有成功。希望有经验的同学可以教我。于是,我采用了逐点设置的方式设定轨迹,这里注意每点之间要加延时(>100us),否则client设定的顺序可能和server接收的顺序不一致,表现为车在行进过程中突然掉头。另外,AWheeledVehicleAIController中判断车是否到达某点的距离阈值也要小心设置,若过小,很可能车在上一帧还没有到达该点(大于阈值),下一帧已经超过该点了(大于阈值),就会表现为车在行进过程中突然掉头去往这个已经走过的点。当然,添加位置检测,当车已经超过某点时,即便大于阈值依然pop该轨迹点,我认为会更稳妥些,这样做需注意轨迹点间距和U形弯道的情况。
另外,零零碎碎的提一些小的trick。
-
Carla是左手坐标系。
-
Carla中Server端和Client端的速度单位不统一,km/h和m/s还有cm/s,要注意区分。如PythonAPI中 player.get_velocity()返回值是m/s,而Server中Vehicle.GetVehicleForwardSpeed()是cm/s,SpeedLimit又是km/h。
-
ImportError: No module named agents.navigation.roaming_agent,解决办法:在.bashrc文件中添加 export PYTHONPATH=$PYTHONPATH:CARLA_PATH/PythonAPI/carla
-
设置server启动时默认加载的地图,方法:在carla/Unreal/CarlaUE4/Config/DefaultEngine.ini中,把TownXX全部改成想要的地图。
[/Script/EngineSettings.GameMapsSettings]
EditorStartupMap=/Game/Carla/Maps/Town04.Town04
GameDefaultMap=/Game/Carla/Maps/Town04.Town04
ServerDefaultMap=/Game/Carla/Maps/Town04.Town04
GlobalDefaultGameMode=/Game/Carla/Blueprints/Game/CarlaGameMode.CarlaGameMode_C
GameInstanceClass=/Script/Carla.CarlaGameInstance
TransitionMap=/Game/Carla/Maps/Town04.Town04
GlobalDefaultServerGameMode=/Game/Carla/Blueprints/Game/CarlaGameMode.CarlaGameMode_C
-
设置automatic_control.py生成的自车的speed limit,方法:在carla/PythonAPI/carla/agents/navigation/basic_agent.py中,修改初始化函数__init__中的target_speed参数。
class BasicAgent(Agent):
"""
BasicAgent implements a basic agent that navigates scenes to reach a given
target destination. This agent respects traffic lights and other vehicles.
"""
def __init__(self, vehicle, target_speed=120):
"""
:param vehicle: actor to apply to local planner logic onto
"""
super(BasicAgent, self).__init__(vehicle)
self._proximity_threshold = 10.0 # meters
self._state = AgentState.NAVIGATING
args_lateral_dict = {
'K_P': 1,
'K_D': 0.02,
'K_I': 0,
'dt': 1.0/20.0}
self._local_planner = LocalPlanner(
self._vehicle, opt_dict={'target_speed' : target_speed,
'lateral_control_dict':args_lateral_dict})
self._hop_resolution = 2.0
self._path_seperation_hop = 2
self._path_seperation_threshold = 0.5
self._target_speed = target_speed
self._grp = None
- Client类的reload_world()可以destroy原来world中已经创建的所有actors。
client = carla.Client(args.host, args.port)
if client.get_world() is not None:
client.reload_world();
- 通过waypoint判断临近的lane是否drivable,可以将waypoint.lane_change与carla.LaneChange做位运算实现。如waypoint.lane_change & carla.LaneChange.Left != 0表示可以左转。参考资料
- world.get_map().get_spawn_points() 每次返回的都是同样的点集,即推荐的可以生成车辆的地点,这是预先设置好的,共250个点。
更多推荐
所有评论(0)