carla源码学习(一)设置车辆控制参数apply_control()

参考资料:https://blog.csdn.net/zxh1592000/article/details/109095605?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-2-109095605-blog-125250141.pc_relevant_3mothn_strategy_and_data_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-2-109095605-blog-125250141.pc_relevant_3mothn_strategy_and_data_recovery&utm_relevant_index=2

一、整体架构

carla源码学习(一)设置车辆控制参数apply_control()_第1张图片
整体代码就分为客户端、通信接口、服务端三部分。
客户端代码在PythonApi文件夹,主要形式是由c++通过boost::python封装实现的的pythonapi。
通信代码在LibCarla文件夹,主要是通过c++的rpc库实现客户端和server的通信。carla的通信使用的是c++单独的rpc库,而不是使用的ue4的rpc通信机制。
服务端代码在unreal文件夹,这部分与其他由c++开发的ue4项目的代码类似。

二、客户端

这里的客户端代码特指实现基础功能(生成车辆、设置油门/方向),不包括carla在例程中给出的示例应用程序和算法。

carla是基于ue4的服务器-客户端架构实现的,所有计算都是在服务端实现的,客户端只负责发出请求、接收响应(这种说法并不严谨,有小部分简单功能的计算是在本地实现的)。所以客户端的程序要么是调用通信接口与服务器通信,要么是接收响应后在本地输出。

1、api封装

下面这个代码是D:\carla-master\LibCarla\source\carla\client\Actor.cpp的一部分,如果对carla的pythonapi熟悉的化就会对其中的这些名字比较熟悉。这里调用了boost::python库,将后面的c++函数封装成python函数,最后测成一个python类

  class_<cc::Vehicle, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::Vehicle>>("Vehicle",
      no_init)
      .def("apply_control", &cc::Vehicle::ApplyControl, (arg("control")))
      .def("get_control", &cc::Vehicle::GetControl)
      .def("set_light_state", &cc::Vehicle::SetLightState, (arg("light_state")))
      .def("open_door", &cc::Vehicle::OpenDoor, (arg("door_idx")))
      .def("close_door", &cc::Vehicle::CloseDoor, (arg("door_idx")))
      .def("set_wheel_steer_direction", &cc::Vehicle::SetWheelSteerDirection, (arg("wheel_location")), (arg("angle_in_deg")))
      .def("get_wheel_steer_angle", &cc::Vehicle::GetWheelSteerAngle, (arg("wheel_location")))
      .def("get_light_state", CONST_CALL_WITHOUT_GIL(cc::Vehicle, GetLightState))
      .def("apply_physics_control", &cc::Vehicle::ApplyPhysicsControl, (arg("physics_control")))
      .def("get_physics_control", CONST_CALL_WITHOUT_GIL(cc::Vehicle, GetPhysicsControl))
      .def("set_autopilot", CALL_WITHOUT_GIL_2(cc::Vehicle, SetAutopilot, bool, uint16_t), (arg("enabled") = true, arg("tm_port") = ctm::TM_DEFAULT_PORT))
      .def("show_debug_telemetry", &cc::Vehicle::ShowDebugTelemetry, (arg("enabled") = true))
      .def("get_speed_limit", &cc::Vehicle::GetSpeedLimit)
      .def("get_traffic_light_state", &cc::Vehicle::GetTrafficLightState)
      .def("is_at_traffic_light", &cc::Vehicle::IsAtTrafficLight)
      .def("get_traffic_light", &cc::Vehicle::GetTrafficLight)
      .def("enable_carsim", &cc::Vehicle::EnableCarSim, (arg("simfile_path") = ""))
      .def("use_carsim_road", &cc::Vehicle::UseCarSimRoad, (arg("enabled")))
      .def("enable_chrono_physics", &cc::Vehicle::EnableChronoPhysics, (arg("max_substeps")=30, arg("max_substep_delta_time")=0.002, arg("vehicle_json")="", arg("powetrain_json")="", arg("tire_json")="", arg("base_json_path")=""))
      .def(self_ns::str(self_ns::self))
  ;

2、api的c++函数实现

以apply_control为例,这个函数的功能是给出新油门和方向盘的数据。一路“转到定义”,最后发现这个函数在D:\carla-master\LibCarla\source\carla\client\detail\client.cpp文件中。
carla源码学习(一)设置车辆控制参数apply_control()_第2张图片

通信使用的是rpc,这里就是最后通信部分的代码

三、通信接口

未完待续。。。

四、服务端

如果之前有按照carla的官方文档实现过添加自定义传感器,那么对这里应该会熟悉一点。
这块的文件在D:\carla-master\Unreal\CarlaUE4\Plugins\Carla\Source\Carla\Server\CarlaServer.cpp,代码如下:

  // ~~ Apply control ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  BIND_SYNC(apply_control_to_vehicle) << [this](
      cr::ActorId ActorId,
      cr::VehicleControl Control) -> R<void>
  {
    REQUIRE_CARLA_EPISODE();
    FCarlaActor* CarlaActor = Episode->FindCarlaActor(ActorId);
    if (!CarlaActor)
    {
      return RespondError(
          "apply_control_to_vehicle",
          ECarlaServerResponse::ActorNotFound,
          " Actor Id: " + FString::FromInt(ActorId));
    }
    ECarlaServerResponse Response =
        CarlaActor->ApplyControlToVehicle(Control, EVehicleInputPriority::Client);
    if (Response != ECarlaServerResponse::Success)
    {
      return RespondError(
          "apply_control_to_vehicle",
          Response,
          " Actor Id: " + FString::FromInt(ActorId));
    }
    return R<void>::Success();
  };

这里的关键就是调用了ApplyControlToVehicle(),这个函数是虚函数,真正的实现在D:\carla-master\Unreal\CarlaUE4\Plugins\Carla\Source\Carla\Actor\CarlaActor.cpp,代码如下:

ECarlaServerResponse FVehicleActor::ApplyControlToVehicle(
      const FVehicleControl& Control, const EVehicleInputPriority& Priority)
{
  if (IsDormant())
  {
    FVehicleData* ActorData = GetActorData<FVehicleData>();
    ActorData->Control = Control;
  }
  else
  {
    auto Vehicle = Cast<ACarlaWheeledVehicle>(GetActor());
    if (Vehicle == nullptr)
    {
      return ECarlaServerResponse::NotAVehicle;
    }
    Vehicle->ApplyVehicleControl(Control, Priority);
  }
  return ECarlaServerResponse::Success;
}

再次跳转到ApplyVehicleControl()的定义,代码如下:

  UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
  void ApplyVehicleControl(const FVehicleControl &Control, EVehicleInputPriority Priority)
  {
    if (InputControl.Priority <= Priority)
    {
      InputControl.Control = Control;
      InputControl.Priority = Priority;
    }
  }

如果做过ue4开发对这里就很熟悉了,就是直接设置相关参数。

你可能感兴趣的:(学习,python,开发语言)