function-style casts in UE4

150 views Asked by At

consider this code from a library file:

#pragma once

#include "carla/MsgPack.h"

#ifdef LIBCARLA_INCLUDED_FROM_UE4
#include "Carla/Vehicle/VehicleControl.h"
#endif // LIBCARLA_INCLUDED_FROM_UE4

namespace carla {
namespace rpc {

  class VehicleControl {
  public:

    VehicleControl() = default;

    VehicleControl(
        float in_throttle,
        float in_steer,
        float in_brake,
        bool in_hand_brake,
        bool in_reverse,
        bool in_manual_gear_shift,
        int32_t in_gear)
      : throttle(in_throttle),
        steer(in_steer),
        brake(in_brake),
        hand_brake(in_hand_brake),
        reverse(in_reverse),
        manual_gear_shift(in_manual_gear_shift),
        gear(in_gear) {}

    float throttle = 0.0f;
    float steer = 0.0f;
    float brake = 0.0f;
    bool hand_brake = false;
    bool reverse = false;
    bool manual_gear_shift = false;
    int32_t gear = 0;

#ifdef LIBCARLA_INCLUDED_FROM_UE4

    VehicleControl(const FVehicleControl &Control)
      : throttle(Control.Throttle),
        steer(Control.Steer),
        brake(Control.Brake),
        hand_brake(Control.bHandBrake),
        reverse(Control.bReverse),
        manual_gear_shift(Control.bManualGearShift),
        gear(Control.Gear) {}

    operator FVehicleControl() const {
      FVehicleControl Control;
      Control.Throttle = throttle;
      Control.Steer = steer;
      Control.Brake = brake;
      Control.bHandBrake = hand_brake;
      Control.bReverse = reverse;
      Control.bManualGearShift = manual_gear_shift;
      Control.Gear = gear;
      return Control;
    }

#endif // LIBCARLA_INCLUDED_FROM_UE4

    bool operator!=(const VehicleControl &rhs) const {
      return
          throttle != rhs.throttle ||
          steer != rhs.steer ||
          brake != rhs.brake ||
          hand_brake != rhs.hand_brake ||
          reverse != rhs.reverse ||
          manual_gear_shift != rhs.manual_gear_shift ||
          gear != rhs.gear;
    }

    bool operator==(const VehicleControl &rhs) const {
      return !(*this != rhs);
    }

    MSGPACK_DEFINE_ARRAY(
        throttle,
        steer,
        brake,
        hand_brake,
        reverse,
        manual_gear_shift,
        gear);
  };

} // namespace rpc
} // namespace carla

that is included in this cpp file:

#include "Carla.h"
#include "Carla/Sensor/WorldObserver.h"
#include "Carla/Actor/ActorData.h"
#include "Carla/Actor/ActorRegistry.h"
#include "Carla/Game/CarlaEpisode.h"

#include "Carla/Traffic/TrafficLightBase.h"
#include "Carla/Traffic/TrafficLightComponent.h"
#include "Carla/Traffic/TrafficLightController.h"
#include "Carla/Traffic/TrafficLightGroup.h"
#include "Carla/Traffic/TrafficSignBase.h"
#include "Carla/Traffic/SignComponent.h"
#include "Carla/Walker/WalkerController.h"

#include "CoreGlobals.h"

#include <compiler/disable-ue4-macros.h>
#include <carla/rpc/String.h>
#include <carla/sensor/SensorRegistry.h>
#include <carla/sensor/data/ActorDynamicState.h>
#include <carla/rpc/VehicleControl.h>
#include <carla/rpc/WalkerControl.h>
#include <compiler/enable-ue4-macros.h>

static auto FWorldObserver_GetActorState(const FCarlaActor &View, const FActorRegistry &Registry)
{
  using AType = FCarlaActor::ActorType;

  carla::sensor::data::ActorDynamicState::TypeDependentState state{};

  if (AType::Vehicle == View.GetActorType())
  {
    auto Vehicle = Cast<ACarlaWheeledVehicle>(View.GetActor());
    if (Vehicle != nullptr)
    {
      state.vehicle_data.control = carla::rpc::VehicleControl{Vehicle->GetVehicleControl()};
      auto Controller = Cast<AWheeledVehicleAIController>(Vehicle->GetController());
      if (Controller != nullptr)
      {
        using TLS = carla::rpc::TrafficLightState;
        state.vehicle_data.traffic_light_state = static_cast<TLS>(Controller->GetTrafficLightState());
        state.vehicle_data.speed_limit = Controller->GetSpeedLimit();
        auto TrafficLight = Controller->GetTrafficLight();
        if (TrafficLight != nullptr)
        {
          state.vehicle_data.has_traffic_light = true;
          auto* TrafficLightView = Registry.FindCarlaActor(TrafficLight);
          if(TrafficLightView)
          {
            state.vehicle_data.traffic_light_id = TrafficLightView->GetActorId();
          }
          else
          {
            state.vehicle_data.has_traffic_light = false;
          }
        }
        else
        {
          state.vehicle_data.has_traffic_light = false;
        }
      }
    }
  }

  else if (AType::Walker == View.GetActorType())
  {
    auto Walker = Cast<APawn>(View.GetActor());
    auto Controller = Walker != nullptr ? Cast<AWalkerController>(Walker->GetController()) : nullptr;
    if (Controller != nullptr)
    {
      state.walker_control = carla::rpc::WalkerControl{Controller->GetWalkerControl()};
    }
  }
  else if (AType::TrafficLight == View.GetActorType())
  {
    auto TrafficLight = Cast<ATrafficLightBase>(View.GetActor());
    if (TrafficLight != nullptr)
    {
      auto* TrafficLightComponent =
          TrafficLight->GetTrafficLightComponent();

      using TLS = carla::rpc::TrafficLightState;

      if(TrafficLightComponent == nullptr)
      {
        // Old way: traffic lights are actors
        state.traffic_light_data.sign_id[0] = '\0';
        state.traffic_light_data.state = static_cast<TLS>(TrafficLight->GetTrafficLightState());
        state.traffic_light_data.green_time = TrafficLight->GetGreenTime();
        state.traffic_light_data.yellow_time = TrafficLight->GetYellowTime();
        state.traffic_light_data.red_time = TrafficLight->GetRedTime();
        state.traffic_light_data.elapsed_time = TrafficLight->GetElapsedTime();
        state.traffic_light_data.time_is_frozen = TrafficLight->GetTimeIsFrozen();
        state.traffic_light_data.pole_index = TrafficLight->GetPoleIndex();
      }
      else
      {
        const UTrafficLightController* Controller =  TrafficLightComponent->GetController();
        const ATrafficLightGroup* Group = TrafficLightComponent->GetGroup();

        if (!Controller)
        {
          UE_LOG(LogCarla, Error, TEXT("TrafficLightComponent doesn't have any Controller assigned"));
        }
        else if (!Group)
        {
          UE_LOG(LogCarla, Error, TEXT("TrafficLightComponent doesn't have any Group assigned"));
        }
        else
        {
          const FString fstring_sign_id = TrafficLightComponent->GetSignId();
          const std::string sign_id = carla::rpc::FromFString(fstring_sign_id);
          constexpr size_t max_size = sizeof(state.traffic_light_data.sign_id);
          size_t sign_id_length = sign_id.length();
          if(max_size < sign_id_length)
          {
            UE_LOG(LogCarla, Warning, TEXT("The max size of a signal id is 32. %s (%d)"), *fstring_sign_id, sign_id.length());
            sign_id_length = max_size;
          }
          std::memset(state.traffic_light_data.sign_id, '\0', max_size);
          std::memcpy(state.traffic_light_data.sign_id, sign_id.c_str(), sign_id_length);
          state.traffic_light_data.state = static_cast<TLS>(TrafficLightComponent->GetLightState());
          state.traffic_light_data.green_time = Controller->GetGreenTime();
          state.traffic_light_data.yellow_time = Controller->GetYellowTime();
          state.traffic_light_data.red_time = Controller->GetRedTime();
          state.traffic_light_data.elapsed_time = Controller->GetElapsedTime();
          state.traffic_light_data.time_is_frozen = Group->IsFrozen();
          state.traffic_light_data.pole_index = TrafficLight->GetPoleIndex();
        }
      }
    }
  }
  else if (AType::TrafficSign == View.GetActorType())
  {
    auto TrafficSign = Cast<ATrafficSignBase>(View.GetActor());
    if (TrafficSign != nullptr)
    {
      USignComponent* TrafficSignComponent =
        Cast<USignComponent>(TrafficSign->FindComponentByClass<USignComponent>());

      if(TrafficSignComponent)
      {
        const FString fstring_sign_id = TrafficSignComponent->GetSignId();
        const std::string sign_id = carla::rpc::FromFString(fstring_sign_id);
        constexpr size_t max_size = sizeof(state.traffic_sign_data.sign_id);
        size_t sign_id_length = sign_id.length();
        if(max_size < sign_id_length)
        {
          UE_LOG(LogCarla, Warning, TEXT("The max size of a signal id is 32. %s (%d)"), *fstring_sign_id, sign_id.length());
          sign_id_length = max_size;
        }
        std::memset(state.traffic_light_data.sign_id, '\0', max_size);
        std::memcpy(state.traffic_sign_data.sign_id, sign_id.c_str(), sign_id_length);
      }
    }
  }
  return state;
}

Do you have any idea, how the code

state.vehicle_data.control = carla::rpc::VehicleControl{Vehicle->GetVehicleControl()};

would throw compiler error 2440?

D:/carla/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/WorldObserver.cpp(42): error C2440: "<function-style-cast>": "initializer list" kann nicht in "carla::rpc::VehicleControl" konvertiert werden

The respective constructor is defined and should be included, as LIBCARLA_INCLUDED_BY_UE4 is defined in <compiler/disable-ue4-macros.h>, before the library file is included.

Any suggestions? I can't see where the error would be.

1

There are 1 answers

1
roque2205 On

Turned out that I had to move my library includes to the top of the .cpp-File, or carla::rpc::VehicleControl and carla::rpc::WalkerControl wouldn't be known to the compiler early enough, which would lead to the error with the function-style cast.