Added replayer speed (time factor for slow/fast motion)

This commit is contained in:
bernatx 2019-03-05 18:01:17 +01:00
parent 4ec09d262e
commit be37d22335
16 changed files with 153 additions and 9 deletions

View File

@ -1,5 +1,7 @@
## CARLA 0.9.5
* Added playback speed (slow/fast motion) for the replayer
* We can use an absolute path for the recorded files (to choose where to 'write to' or 'read from')
* New Town07, rural environment with narrow roads
* Reworked OpenDRIVE parser and waypoints API
- Fixed several situations in which the XODR was incorrectly parsed

View File

@ -20,6 +20,7 @@
- `show_recorder_file_info(string filename)`
- `show_recorder_collisions(string filename, char category1, char category2)`
- `show_recorder_actors_blocked(string filename, float min_time, float min_distance)`
- `set_replayer_speed(float time_factor)`
- `apply_batch(commands, do_tick=False)`
- `apply_batch_sync(commands, do_tick=False) -> list(carla.command.Response)`

View File

@ -449,6 +449,16 @@ client.replay_file("recording01.log", start, duration, camera)
* **duration**: we can say how many seconds we want to play. If the simulation has not reached the end, then all actors will have autopilot enabled automatically. The intention here is to allow for replaying a piece of a simulation and then let all actors start driving in autopilot again.
* **camera**: we can specify the Id of an actor and then the camera will follow that actor while replaying. Continue reading to know which Id has an actor.
We can specify the speed for the replayer at any moment, using the next API:
```py
client.set_replayer_speed(2.0)
```
A value greater than 1.0 will play in fast motion, and a value below 1.0 will play in slow motion, being 1.0 the default value for normal playback.
As a performance trick, with values over 2.0 the interpolation of positions is disabled.
The call of this API will not stop the replayer in course, it will change just the speed, so you can change that several times while the replayer is running.
We can know details about a recorded simulation, using this API:
```py

View File

@ -84,6 +84,10 @@ namespace client {
return _simulator->ReplayFile(name, start, duration, follow_id);
}
void SetReplayerSpeed(double time_factor) {
_simulator->SetReplayerSpeed(time_factor);
}
void ApplyBatch(
std::vector<rpc::Command> commands,
bool do_tick_cue = false) const {

View File

@ -291,6 +291,10 @@ namespace detail {
return _pimpl->CallAndWait<std::string>("replay_file", name, start, duration, follow_id);
}
void Client::SetReplayerSpeed(double time_factor) {
_pimpl->AsyncCall("set_replayer_speed", time_factor);
}
void Client::SubscribeToStream(
const streaming::Token &token,
std::function<void(Buffer)> callback) {

View File

@ -182,6 +182,8 @@ namespace detail {
std::string ReplayFile(std::string name, double start, double duration, uint32_t follow_id);
void SetReplayerSpeed(double time_factor);
void SubscribeToStream(
const streaming::Token &token,
std::function<void(Buffer)> callback);

View File

@ -293,6 +293,10 @@ namespace detail {
return _client.ReplayFile(std::move(name), start, duration, follow_id);
}
void SetReplayerSpeed(double time_factor) {
_client.SetReplayerSpeed(time_factor);
}
/// @}
// =========================================================================
/// @name Operations with sensors

View File

@ -68,6 +68,7 @@ void export_client() {
.def("show_recorder_collisions", CALL_WITHOUT_GIL_3(cc::Client, ShowRecorderCollisions, std::string, char, char), (arg("name"), arg("type1"), arg("type2")))
.def("show_recorder_actors_blocked", CALL_WITHOUT_GIL_3(cc::Client, ShowRecorderActorsBlocked, std::string, float, float), (arg("name"), arg("min_time"), arg("min_distance")))
.def("replay_file", CALL_WITHOUT_GIL_4(cc::Client, ReplayFile, std::string, float, float, int), (arg("name"), arg("time_start"), arg("duration"), arg("follow_id")))
.def("set_replayer_speed", &cc::Client::SetReplayerSpeed, (arg("time_factor")))
.def("apply_batch", &ApplyBatchCommands, (arg("commands"), arg("do_tick")=false))
.def("apply_batch_sync", &ApplyBatchCommandsSync, (arg("commands"), arg("do_tick")=false))
;

View File

@ -61,6 +61,12 @@ def main():
default=0,
type=int,
help='camera follows an actor (ex: 82)')
argparser.add_argument(
'-x', '--speed',
metavar='X',
default=1.0,
type=float,
help='time factor(default 1.0)')
args = argparser.parse_args()
try:
@ -68,6 +74,7 @@ def main():
client = carla.Client(args.host, args.port)
client.set_timeout(60.0)
client.set_replayer_speed(args.speed)
print(client.replay_file(args.recorder_filename, args.start, args.duration, args.camera))
finally:

View File

@ -0,0 +1,70 @@
#!/usr/bin/env python
# Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma de
# Barcelona (UAB).
#
# This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>.
import glob
import os
import sys
try:
sys.path.append(glob.glob('**/*%d.%d-%s.egg' % (
sys.version_info.major,
sys.version_info.minor,
'win-amd64' if os.name == 'nt' else 'linux-x86_64'))[0])
except IndexError:
pass
import carla
import argparse
import random
import time
def main():
argparser = argparse.ArgumentParser(
description=__doc__)
argparser.add_argument(
'--host',
metavar='H',
default='127.0.0.1',
help='IP of the host server (default: 127.0.0.1)')
argparser.add_argument(
'-p', '--port',
metavar='P',
default=2000,
type=int,
help='TCP port to listen to (default: 2000)')
argparser.add_argument(
'-x', '--speed',
metavar='X',
default=1.0,
type=float,
help='time factor(default 1.0)')
args = argparser.parse_args()
try:
client = carla.Client(args.host, args.port)
client.set_timeout(2.0)
# client.load_world("Town03")
client.set_replayer_speed(args.speed)
finally:
pass
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass
finally:
print('\ndone.')

View File

@ -45,6 +45,11 @@ std::string ACarlaRecorder::ReplayFile(std::string Path, std::string Name, doubl
return Replayer.ReplayFile(Path + Name, TimeStart, Duration, FollowId);
}
inline void ACarlaRecorder::SetReplayerSpeed(double TimeFactor)
{
return Replayer.SetSpeed(TimeFactor);
}
void ACarlaRecorder::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);

View File

@ -103,6 +103,7 @@ public:
std::string ShowFileCollisions(std::string Path, std::string Name, char Type1, char Type2);
std::string ShowFileActorsBlocked(std::string Path, std::string Name, double MinTime = 30, double MinDistance = 10);
std::string ReplayFile(std::string Path, std::string Name, double TimeStart, double Duration, uint32_t FollowId);
void SetReplayerSpeed(double TimeFactor);
void Tick(float DeltaSeconds) final;

View File

@ -467,13 +467,18 @@ void CarlaReplayer::UpdatePositions(double Per)
auto Result = TempMap.find(CurrPos[i].DatabaseId);
if (Result != TempMap.end())
{
// interpolate
InterpolatePosition(PrevPos[Result->second], CurrPos[i], Per);
// check if time factor is high
if (TimeFactor >= 2.0)
// assign first position
InterpolatePosition(PrevPos[Result->second], CurrPos[i], 0.0);
else
// interpolate
InterpolatePosition(PrevPos[Result->second], CurrPos[i], Per);
}
else
{
// assign last position (we don't have previous one)
InterpolatePosition(CurrPos[i], CurrPos[i], 0);
InterpolatePosition(CurrPos[i], CurrPos[i], 0.0);
}
// move the camera to follow this actor if required
@ -502,8 +507,14 @@ void CarlaReplayer::Tick(float Delta)
// check if there are events to process
if (Enabled)
{
ProcessToTime(Delta);
ProcessToTime(Delta * TimeFactor);
}
// UE_LOG(LogCarla, Log, TEXT("Replayer tick"));
}
// speed (time factor)
inline void CarlaReplayer::SetSpeed(double NewTimeFactor)
{
TimeFactor = NewTimeFactor;
}

View File

@ -60,6 +60,9 @@ public:
Helper.SetEpisode(ThisEpisode);
}
// playback speed (time factor)
void SetSpeed(double NewTimeFactor);
// tick for the replayer
void Tick(float Time);
@ -85,6 +88,8 @@ private:
CarlaReplayerHelper Helper;
// follow camera
uint32_t FollowId;
// speed (time factor)
double TimeFactor { 1.0 };
// utils
bool ReadHeader();

View File

@ -228,11 +228,21 @@ bool CarlaReplayerHelper::ProcessReplayerPosition(CarlaRecorderPosition Pos1, Ca
AActor *Actor = Episode->GetActorRegistry().Find(Pos1.DatabaseId).GetActor();
if (Actor && !Actor->IsPendingKill())
{
// interpolate transform
FVector Location = FMath::Lerp(FVector(Pos1.Location), FVector(Pos2.Location), Per);
FRotator Rotation = FMath::Lerp(FRotator::MakeFromEuler(Pos1.Rotation), FRotator::MakeFromEuler(Pos2.Rotation), Per);
FTransform Trans(Rotation, Location, FVector(1, 1, 1));
Actor->SetActorTransform(Trans, false, nullptr, ETeleportType::TeleportPhysics);
// check to assign first position or interpolate between both
if (Per == 0.0)
{
// assign position 1
FTransform Trans(FRotator::MakeFromEuler(Pos1.Rotation), FVector(Pos1.Location), FVector(1, 1, 1));
Actor->SetActorTransform(Trans, false, nullptr, ETeleportType::TeleportPhysics);
}
else
{
// interpolate positions
FVector Location = FMath::Lerp(FVector(Pos1.Location), FVector(Pos2.Location), Per);
FRotator Rotation = FMath::Lerp(FRotator::MakeFromEuler(Pos1.Rotation), FRotator::MakeFromEuler(Pos2.Rotation), Per);
FTransform Trans(Rotation, Location, FVector(1, 1, 1));
Actor->SetActorTransform(Trans, false, nullptr, ETeleportType::TeleportPhysics);
}
// reset velocities
ResetVelocities(Actor);
return true;

View File

@ -761,6 +761,13 @@ void FTheNewCarlaServer::FPimpl::BindActions()
follow_id));
};
BIND_SYNC(set_replayer_speed) << [this](double time_factor) -> R<void>
{
REQUIRE_CARLA_EPISODE();
Episode->GetRecorder()->SetReplayerSpeed(time_factor);
return R<void>::Success();
};
// ~~ Draw debug shapes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BIND_SYNC(draw_debug_shape) << [this](const cr::DebugShape &shape) -> R<void>