Add acceleration and delta-time to world observer message to make data self contained

This commit is contained in:
nsubiron 2019-02-22 15:30:54 +01:00
parent bcc44c97fb
commit 3ec2483316
10 changed files with 68 additions and 52 deletions

View File

@ -43,15 +43,14 @@ namespace detail {
auto self = weak.lock(); auto self = weak.lock();
if (self != nullptr) { if (self != nullptr) {
auto data = sensor::Deserializer::Deserialize(std::move(buffer)); auto data = sensor::Deserializer::Deserialize(std::move(buffer));
const auto &raw_data = CastData(*data);
std::shared_ptr<const EpisodeState> next; auto next = std::make_shared<const EpisodeState>(CastData(*data));
std::shared_ptr<const EpisodeState> prev = self->GetState(); auto prev = self->GetState();
do { do {
if (prev->GetFrameCount() >= raw_data.GetFrameNumber()) { if (prev->GetFrameCount() >= next->GetFrameCount()) {
self->_on_tick_callbacks.Call(next->GetTimestamp());
return; return;
} }
next = prev->DeriveNextStep(raw_data);
} while (!self->_state.compare_exchange(&prev, next)); } while (!self->_state.compare_exchange(&prev, next));
if (next->GetEpisodeId() != prev->GetEpisodeId()) { if (next->GetEpisodeId() != prev->GetEpisodeId()) {

View File

@ -10,38 +10,26 @@ namespace carla {
namespace client { namespace client {
namespace detail { namespace detail {
static auto DeriveAcceleration( EpisodeState::EpisodeState(const sensor::data::RawEpisodeState &state)
double delta_seconds, : _episode_id(state.GetEpisodeId()),
const geom::Vector3D &v0, _timestamp(
const geom::Vector3D &v1) { state.GetFrameNumber(),
/// @todo add methods to Vector3D for scalar multiplication. state.GetGameTimeStamp(),
auto acc = v1 - v0; state.GetDeltaSeconds(),
acc.x /= delta_seconds; state.GetPlatformTimeStamp()) {
acc.y /= delta_seconds; _actors.reserve(state.size());
acc.z /= delta_seconds;
return acc;
}
std::shared_ptr<const EpisodeState> EpisodeState::DeriveNextStep(
const sensor::data::RawEpisodeState &state) const {
auto next = std::make_shared<EpisodeState>(state.GetEpisodeId());
next->_timestamp.frame_count = state.GetFrameNumber();
next->_timestamp.elapsed_seconds = state.GetGameTimeStamp();
next->_timestamp.platform_timestamp = state.GetPlatformTimeStamp();
next->_timestamp.delta_seconds = next->_timestamp.elapsed_seconds - _timestamp.elapsed_seconds;
next->_actors.reserve(state.size());
for (auto &&actor : state) { for (auto &&actor : state) {
auto acceleration = DeriveAcceleration(
next->_timestamp.delta_seconds,
GetActorState(actor.id).velocity,
actor.velocity);
DEBUG_ONLY(auto result = ) DEBUG_ONLY(auto result = )
next->_actors.emplace( _actors.emplace(
actor.id, actor.id,
ActorState{actor.transform, actor.velocity, actor.angular_velocity, acceleration, actor.state}); ActorState{
actor.transform,
actor.velocity,
actor.angular_velocity,
actor.acceleration,
actor.state});
DEBUG_ASSERT(result.second); DEBUG_ASSERT(result.second);
} }
return next;
} }
} // namespace detail } // namespace detail

View File

@ -36,6 +36,8 @@ namespace detail {
explicit EpisodeState(uint64_t episode_id) : _episode_id(episode_id) {} explicit EpisodeState(uint64_t episode_id) : _episode_id(episode_id) {}
explicit EpisodeState(const sensor::data::RawEpisodeState &state);
auto GetEpisodeId() const { auto GetEpisodeId() const {
return _episode_id; return _episode_id;
} }
@ -65,14 +67,11 @@ namespace detail {
iterator::make_map_keys_iterator(_actors.end())); iterator::make_map_keys_iterator(_actors.end()));
} }
std::shared_ptr<const EpisodeState> DeriveNextStep(
const sensor::data::RawEpisodeState &state) const;
private: private:
const uint64_t _episode_id; const uint64_t _episode_id;
Timestamp _timestamp; const Timestamp _timestamp;
std::unordered_map<actor_id_type, ActorState> _actors; std::unordered_map<actor_id_type, ActorState> _actors;
}; };

View File

@ -117,6 +117,8 @@ namespace detail {
geom::Vector3D angular_velocity; geom::Vector3D angular_velocity;
geom::Vector3D acceleration;
union TypeDependentState { union TypeDependentState {
detail::TrafficLightData traffic_light_data; detail::TrafficLightData traffic_light_data;
detail::VehicleData vehicle_data; detail::VehicleData vehicle_data;
@ -127,7 +129,7 @@ namespace detail {
#pragma pack(pop) #pragma pack(pop)
static_assert( static_assert(
sizeof(ActorDynamicState) == 13u * sizeof(uint32_t) + sizeof(detail::VehicleData), sizeof(ActorDynamicState) == 16u * sizeof(uint32_t) + sizeof(detail::VehicleData),
"Invalid ActorDynamicState size!"); "Invalid ActorDynamicState size!");
} // namespace data } // namespace data

View File

@ -53,6 +53,11 @@ namespace data {
double GetPlatformTimeStamp() const { double GetPlatformTimeStamp() const {
return GetHeader().platform_timestamp; return GetHeader().platform_timestamp;
} }
/// Simulated seconds elapsed since previous frame.
double GetDeltaSeconds() const {
return GetHeader().delta_seconds;
}
}; };
} // namespace data } // namespace data

View File

@ -32,6 +32,7 @@ namespace s11n {
uint64_t episode_id; uint64_t episode_id;
double game_timestamp; double game_timestamp;
double platform_timestamp; double platform_timestamp;
float delta_seconds;
}; };
#pragma pack(pop) #pragma pack(pop)

View File

@ -25,4 +25,7 @@ public:
FBoundingBox BoundingBox; FBoundingBox BoundingBox;
carla::rpc::Actor SerializedData; carla::rpc::Actor SerializedData;
/// @todo To be used solely by the FWorldObserver.
mutable FVector Velocity = {0.0f, 0.0f, 0.0f};
}; };

View File

@ -69,7 +69,7 @@ void FCarlaEngine::OnPreTick(ELevelTick TickType, float DeltaSeconds)
if ((TickType == ELevelTick::LEVELTICK_All) && (CurrentEpisode != nullptr)) if ((TickType == ELevelTick::LEVELTICK_All) && (CurrentEpisode != nullptr))
{ {
CurrentEpisode->TickTimers(DeltaSeconds); CurrentEpisode->TickTimers(DeltaSeconds);
WorldObserver.BroadcastTick(*CurrentEpisode); WorldObserver.BroadcastTick(*CurrentEpisode, DeltaSeconds);
} }
} }

View File

@ -78,9 +78,31 @@ static auto FWorldObserver_GetActorState(const FActorView &View, const FActorReg
return state; return state;
} }
static carla::geom::Vector3D FWorldObserver_GetAngularVelocity(const AActor &Actor)
{
const auto RootComponent = Cast<UPrimitiveComponent>(Actor.GetRootComponent());
const FVector AngularVelocity =
RootComponent != nullptr ?
RootComponent->GetPhysicsAngularVelocityInDegrees() :
FVector{0.0f, 0.0f, 0.0f};
return {AngularVelocity.X, AngularVelocity.Y, AngularVelocity.Z};
}
static carla::geom::Vector3D FWorldObserver_GetAcceleration(
const FActorView &View,
const FVector &Velocity,
const float DeltaSeconds)
{
FVector &PreviousVelocity = View.GetActorInfo()->Velocity;
const FVector Acceleration = (Velocity - PreviousVelocity) / DeltaSeconds;
PreviousVelocity = Velocity;
return {Acceleration.X, Acceleration.Y, Acceleration.Z};
}
static carla::Buffer FWorldObserver_Serialize( static carla::Buffer FWorldObserver_Serialize(
carla::Buffer buffer, carla::Buffer buffer,
const UCarlaEpisode &Episode) const UCarlaEpisode &Episode,
float DeltaSeconds)
{ {
using Serializer = carla::sensor::s11n::EpisodeStateSerializer; using Serializer = carla::sensor::s11n::EpisodeStateSerializer;
using ActorDynamicState = carla::sensor::data::ActorDynamicState; using ActorDynamicState = carla::sensor::data::ActorDynamicState;
@ -101,6 +123,7 @@ static carla::Buffer FWorldObserver_Serialize(
header.episode_id = Episode.GetId(); header.episode_id = Episode.GetId();
header.game_timestamp = Episode.GetElapsedGameTime(); header.game_timestamp = Episode.GetElapsedGameTime();
header.platform_timestamp = FPlatformTime::Seconds(); header.platform_timestamp = FPlatformTime::Seconds();
header.delta_seconds = DeltaSeconds;
write_data(header); write_data(header);
// Write every actor. // Write every actor.
@ -108,19 +131,14 @@ static carla::Buffer FWorldObserver_Serialize(
{ {
check(View.IsValid()); check(View.IsValid());
constexpr float TO_METERS = 1e-2; constexpr float TO_METERS = 1e-2;
const auto velocity = TO_METERS * View.GetActor()->GetVelocity(); const auto Velocity = TO_METERS * View.GetActor()->GetVelocity();
// get the angular velocity
const auto RootComponent = Cast<UPrimitiveComponent>(View.GetActor()->GetRootComponent());
FVector angularVelocity { 0.0f, 0.0f, 0.0f };
if (RootComponent != nullptr)
{
angularVelocity = RootComponent->GetPhysicsAngularVelocityInDegrees();
}
ActorDynamicState info = { ActorDynamicState info = {
View.GetActorId(), View.GetActorId(),
View.GetActor()->GetActorTransform(), View.GetActor()->GetActorTransform(),
carla::geom::Vector3D{velocity.X, velocity.Y, velocity.Z}, carla::geom::Vector3D{Velocity.X, Velocity.Y, Velocity.Z},
carla::geom::Vector3D{angularVelocity.X, angularVelocity.Y, angularVelocity.Z}, FWorldObserver_GetAngularVelocity(*View.GetActor()),
FWorldObserver_GetAcceleration(View, Velocity, DeltaSeconds),
FWorldObserver_GetActorState(View, Registry) FWorldObserver_GetActorState(View, Registry)
}; };
write_data(info); write_data(info);
@ -130,13 +148,14 @@ static carla::Buffer FWorldObserver_Serialize(
return buffer; return buffer;
} }
void FWorldObserver::BroadcastTick(const UCarlaEpisode &Episode) void FWorldObserver::BroadcastTick(const UCarlaEpisode &Episode, float DeltaSeconds)
{ {
auto AsyncStream = Stream.MakeAsyncDataStream(*this); auto AsyncStream = Stream.MakeAsyncDataStream(*this);
auto buffer = FWorldObserver_Serialize( auto buffer = FWorldObserver_Serialize(
AsyncStream.PopBufferFromPool(), AsyncStream.PopBufferFromPool(),
Episode); Episode,
DeltaSeconds);
AsyncStream.Send(*this, std::move(buffer)); AsyncStream.Send(*this, std::move(buffer));
} }

View File

@ -32,7 +32,7 @@ public:
/// Send a message to every connected client with the info about the given @a /// Send a message to every connected client with the info about the given @a
/// Episode. /// Episode.
void BroadcastTick(const UCarlaEpisode &Episode); void BroadcastTick(const UCarlaEpisode &Episode, float DeltaSeconds);
/// Dummy. Required for compatibility with other sensors only. /// Dummy. Required for compatibility with other sensors only.
FTransform GetActorTransform() const FTransform GetActorTransform() const