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();
if (self != nullptr) {
auto data = sensor::Deserializer::Deserialize(std::move(buffer));
const auto &raw_data = CastData(*data);
std::shared_ptr<const EpisodeState> next;
std::shared_ptr<const EpisodeState> prev = self->GetState();
auto next = std::make_shared<const EpisodeState>(CastData(*data));
auto prev = self->GetState();
do {
if (prev->GetFrameCount() >= raw_data.GetFrameNumber()) {
if (prev->GetFrameCount() >= next->GetFrameCount()) {
self->_on_tick_callbacks.Call(next->GetTimestamp());
return;
}
next = prev->DeriveNextStep(raw_data);
} while (!self->_state.compare_exchange(&prev, next));
if (next->GetEpisodeId() != prev->GetEpisodeId()) {

View File

@ -10,38 +10,26 @@ namespace carla {
namespace client {
namespace detail {
static auto DeriveAcceleration(
double delta_seconds,
const geom::Vector3D &v0,
const geom::Vector3D &v1) {
/// @todo add methods to Vector3D for scalar multiplication.
auto acc = v1 - v0;
acc.x /= delta_seconds;
acc.y /= delta_seconds;
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());
EpisodeState::EpisodeState(const sensor::data::RawEpisodeState &state)
: _episode_id(state.GetEpisodeId()),
_timestamp(
state.GetFrameNumber(),
state.GetGameTimeStamp(),
state.GetDeltaSeconds(),
state.GetPlatformTimeStamp()) {
_actors.reserve(state.size());
for (auto &&actor : state) {
auto acceleration = DeriveAcceleration(
next->_timestamp.delta_seconds,
GetActorState(actor.id).velocity,
actor.velocity);
DEBUG_ONLY(auto result = )
next->_actors.emplace(
_actors.emplace(
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);
}
return next;
}
} // namespace detail

View File

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

View File

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

View File

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

View File

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

View File

@ -25,4 +25,7 @@ public:
FBoundingBox BoundingBox;
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))
{
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;
}
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(
carla::Buffer buffer,
const UCarlaEpisode &Episode)
const UCarlaEpisode &Episode,
float DeltaSeconds)
{
using Serializer = carla::sensor::s11n::EpisodeStateSerializer;
using ActorDynamicState = carla::sensor::data::ActorDynamicState;
@ -101,6 +123,7 @@ static carla::Buffer FWorldObserver_Serialize(
header.episode_id = Episode.GetId();
header.game_timestamp = Episode.GetElapsedGameTime();
header.platform_timestamp = FPlatformTime::Seconds();
header.delta_seconds = DeltaSeconds;
write_data(header);
// Write every actor.
@ -108,19 +131,14 @@ static carla::Buffer FWorldObserver_Serialize(
{
check(View.IsValid());
constexpr float TO_METERS = 1e-2;
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();
}
const auto Velocity = TO_METERS * View.GetActor()->GetVelocity();
ActorDynamicState info = {
View.GetActorId(),
View.GetActor()->GetActorTransform(),
carla::geom::Vector3D{velocity.X, velocity.Y, velocity.Z},
carla::geom::Vector3D{angularVelocity.X, angularVelocity.Y, angularVelocity.Z},
carla::geom::Vector3D{Velocity.X, Velocity.Y, Velocity.Z},
FWorldObserver_GetAngularVelocity(*View.GetActor()),
FWorldObserver_GetAcceleration(View, Velocity, DeltaSeconds),
FWorldObserver_GetActorState(View, Registry)
};
write_data(info);
@ -130,13 +148,14 @@ static carla::Buffer FWorldObserver_Serialize(
return buffer;
}
void FWorldObserver::BroadcastTick(const UCarlaEpisode &Episode)
void FWorldObserver::BroadcastTick(const UCarlaEpisode &Episode, float DeltaSeconds)
{
auto AsyncStream = Stream.MakeAsyncDataStream(*this);
auto buffer = FWorldObserver_Serialize(
AsyncStream.PopBufferFromPool(),
Episode);
Episode,
DeltaSeconds);
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
/// Episode.
void BroadcastTick(const UCarlaEpisode &Episode);
void BroadcastTick(const UCarlaEpisode &Episode, float DeltaSeconds);
/// Dummy. Required for compatibility with other sensors only.
FTransform GetActorTransform() const