Skip to content

Commit

Permalink
Day-night cycle working
Browse files Browse the repository at this point in the history
  • Loading branch information
sytelus committed Feb 24, 2018
1 parent 70ff9bb commit fcb01f5
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 60 deletions.
27 changes: 27 additions & 0 deletions AirLib/include/common/AirSimSettings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ struct AirSimSettings {

struct TimeOfDaySettings {
bool enabled = false;
std::string start_datetime = ""; //format: %Y-%m-%d %H:%M:%S
bool is_start_datetime_dst = false;
float celestial_clock_speed = 1;
float update_interval_secs = 60;
};

private: //fields
Expand All @@ -147,6 +151,7 @@ struct AirSimSettings {

RecordingSettings recording_settings;
SegmentationSettings segmentation_settings;
TimeOfDaySettings tod_settings;

std::vector<std::string> warning_messages;

Expand Down Expand Up @@ -547,6 +552,28 @@ struct AirSimSettings {

enable_collision_passthrough = settings.getBool("EnableCollisionPassthrogh", false);
log_messages_visible = settings.getBool("LogMessagesVisible", true);

{ //load origin geopoint
Settings origin_geopoint_json;
if (settings.getChild("OriginGeopoint", origin_geopoint_json)) {
GeoPoint origin = origin_geopoint.home_point;
origin.latitude = origin_geopoint_json.getDouble("Latitude", origin.latitude);
origin.longitude = origin_geopoint_json.getDouble("Longitude", origin.longitude);
origin.altitude = origin_geopoint_json.getFloat("Latitude", origin.altitude);
origin_geopoint.initialize(origin);
}
}

{ //time of day settings
Settings tod_settings_json;
if (settings.getChild("TimeOfDay", tod_settings_json)) {
tod_settings.enabled = tod_settings_json.getBool("Enabled", tod_settings.enabled);
tod_settings.start_datetime = tod_settings_json.getString("StartDateTime", tod_settings.start_datetime);
tod_settings.celestial_clock_speed = tod_settings_json.getFloat("CelestialClockSpeed", tod_settings.celestial_clock_speed);
tod_settings.is_start_datetime_dst = tod_settings_json.getBool("StartDateTimeDst", tod_settings.is_start_datetime_dst);
tod_settings.update_interval_secs = tod_settings_json.getFloat("UpdateIntervalSecs", tod_settings.update_interval_secs);
}
}
}

void loadClockSettings(const Settings& settings)
Expand Down
21 changes: 12 additions & 9 deletions AirLib/include/common/common_utils/Utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,9 +470,13 @@ class Utils {
return system_clock::now();
}

static string to_string(time_point<system_clock> time)
static std::time_t to_time_t(const std::string& str, bool is_dst = false, const std::string& format = "%Y-%m-%d %H:%M:%S")
{
return to_string(time, "%Y-%m-%d-%H-%M-%S");
std::tm t = {0};
t.tm_isdst = is_dst ? 1 : 0;
std::istringstream ss(str);
ss >> std::get_time(&t, format.c_str());
return mktime(&t);

/* GCC doesn't implement put_time yet
stringstream ss;
Expand All @@ -481,16 +485,15 @@ class Utils {
*/
}

static std::time_t to_time_t(const std::string& str, bool is_dst = false, const std::string& format = "%Y-%b-%d %H:%M:%S")
static string to_string(time_t tt, const char* format = "%Y-%m-%d-%H-%M-%S")
{
std::tm t = {0};
t.tm_isdst = is_dst ? 1 : 0;
std::istringstream ss(str);
ss >> std::get_time(&t, format.c_str());
return mktime(&t);
char str[1024];
if (std::strftime(str, sizeof(str), format, std::localtime(&tt)))
return string(str);
else return string();
}

static string to_string(time_point<system_clock> time, const char* format)
static string to_string(time_point<system_clock> time, const char* format = "%Y-%m-%d-%H-%M-%S")
{
time_t tt = system_clock::to_time_t(time);
char str[1024];
Expand Down
Binary file not shown.
2 changes: 2 additions & 0 deletions Unreal/Plugins/AirSim/Source/Car/SimModeCar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ void ASimModeCar::reset()

void ASimModeCar::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);

report_wrapper_.update();
report_wrapper_.setEnable(EnableReport);

Expand Down
3 changes: 2 additions & 1 deletion Unreal/Plugins/AirSim/Source/PIPCamera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ void APIPCamera::BeginPlay()
{
Super::BeginPlay();

ned_transform_.initialize(this->GetOwner());
auto* p = this->GetAttachParentActor();
ned_transform_.initialize(p ? p : this);

noise_materials_.AddZeroed(imageTypeCount() + 1);

Expand Down
143 changes: 136 additions & 7 deletions Unreal/Plugins/AirSim/Source/SimMode/SimModeBase.cpp
Original file line number Diff line number Diff line change
@@ -1,33 +1,45 @@
#include "SimModeBase.h"
#include <memory>
#include "Misc/MessageDialog.h"
#include "Misc/EngineVersion.h"
#include "AirBlueprintLib.h"
#include "Runtime/Launch/Resources/Version.h"
#include "common/AirSimSettings.hpp"
#include "Recording/RecordingThread.h"
#include "common/ScalableClock.hpp"
#include "common/SteppableClock.hpp"
#include "ConstructorHelpers.h"
#include "Kismet/GameplayStatics.h"
#include "SimJoyStick/SimJoyStick.h"
#include "Misc/OutputDeviceNull.h"
#include "common/EarthCelestial.hpp"


const char ASimModeBase::kUsageScenarioComputerVision[] = "ComputerVision";


ASimModeBase::ASimModeBase()
{
PrimaryActorTick.bCanEverTick = true;

static ConstructorHelpers::FClassFinder<AActor> sky_sphere_class(TEXT("Blueprint'/Engine/EngineSky/BP_Sky_Sphere'"));
sky_sphere_class_ = sky_sphere_class.Succeeded() ? sky_sphere_class.Class : nullptr;

}

void ASimModeBase::BeginPlay()
{
Super::BeginPlay();

float clock_speed = getSettings().clock_speed;

if (clock_speed != 1.0f) {
this->GetWorldSettings()->SetTimeDilation(clock_speed);
UAirBlueprintLib::LogMessageString("Clock Speed: ", std::to_string(clock_speed), LogDebugLevel::Informational);
}
setupClock();

setStencilIDs();

record_tick_count = 0;
setupInputBindings();

setupTimeOfDay();

UAirBlueprintLib::LogMessage(TEXT("Press F1 to see help"), TEXT(""), LogDebugLevel::Informational);
}

Expand All @@ -49,13 +61,130 @@ void ASimModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason)
Super::EndPlay(EndPlayReason);
}

void ASimModeBase::setupTimeOfDay()
{
sky_sphere_ = nullptr;

const auto& tod_settings = getSettings().tod_settings;

if (tod_settings.enabled) {
TArray<AActor*> sky_spheres;
UGameplayStatics::GetAllActorsOfClass(this->GetWorld(), sky_sphere_class_, sky_spheres);
if (sky_spheres.Num() == 0)
UAirBlueprintLib::LogMessage(TEXT("BP_Sky_Sphere was not found. "),
TEXT("TimeOfDay settings would be ignored."), LogDebugLevel::Failure);
else if (sky_spheres.Num() > 1)
UAirBlueprintLib::LogMessage(TEXT("More than BP_Sky_Sphere were found. "),
TEXT("TimeOfDay settings would be applied to first one."), LogDebugLevel::Failure);

if (sky_spheres.Num() >= 1) {
sky_sphere_ = sky_spheres[0];
//for (TFieldIterator<UProperty> PropIt(sky_sphere_->GetClass()); PropIt; ++PropIt)
//{
// // We are iterating over all properties of Actor
// UProperty* Property{ *PropIt };
// FString PropertyName{ GetNameSafe(Property) };
// std::string MyStdString(TCHAR_TO_UTF8(*PropertyName));
// Utils::log(MyStdString);
//}
static const FName sun_prop_name(TEXT("Directional light actor"));
auto* p = sky_sphere_class_->FindPropertyByName(sun_prop_name);
UObjectProperty* sun_prop = Cast<UObjectProperty>( p);
UObject* sun_obj = sun_prop->GetObjectPropertyValue_InContainer(sky_sphere_);
sun_ = Cast<ADirectionalLight>(sun_obj);
//if (sun_) {
// sun_->GetRootComponent()->Mobility = EComponentMobility::Movable;
//}

tod_sim_clock_start_ = ClockFactory::get()->nowNanos();
tod_last_update_ = tod_sim_clock_start_;
if (tod_settings.start_datetime != "")
tod_start_time_ = Utils::to_time_t(tod_settings.start_datetime, tod_settings.is_start_datetime_dst);
else
tod_start_time_ = std::time(nullptr);
}
}
//else ignore
}


void ASimModeBase::setupClock()
{
float clock_speed = getSettings().clock_speed;

//setup clock in PhysX
if (clock_speed != 1.0f) {
this->GetWorldSettings()->SetTimeDilation(clock_speed);
UAirBlueprintLib::LogMessageString("Clock Speed: ", std::to_string(clock_speed), LogDebugLevel::Informational);
}

//setup clock in ClockFactory
std::string clock_type = getSettings().clock_type;

if (clock_type == "ScalableClock")
ClockFactory::get(std::make_shared<msr::airlib::ScalableClock>(clock_speed == 1 ? 1 : 1 / clock_speed));
else if (clock_type == "SteppableClock")
ClockFactory::get(std::make_shared<msr::airlib::SteppableClock>(
static_cast<msr::airlib::TTimeDelta>(getPhysicsLoopPeriod() * 1E-9 * clock_speed)));
else
throw std::invalid_argument(common_utils::Utils::stringf(
"clock_type %s is not recognized", clock_type.c_str()));
}

long long ASimModeBase::getPhysicsLoopPeriod() //nanoseconds
{
/*
300Hz seems to be minimum for non-aggresive flights
400Hz is needed for moderately aggressive flights (such as
high yaw rate with simultaneous back move)
500Hz is recommanded for more aggressive flights
Lenovo P50 high-end config laptop seems to be topping out at 400Hz.
HP Z840 desktop high-end config seems to be able to go up to 500Hz.
To increase freq with limited CPU power, switch Barometer to constant ref mode.
*/

if (getSettings().usage_scenario == kUsageScenarioComputerVision)
return 30000000LL; //30ms
else
return 3000000LL; //3ms
}

void ASimModeBase::Tick(float DeltaSeconds)
{
if (isRecording())
++record_tick_count;

advanceTimeOfDay();

Super::Tick(DeltaSeconds);
}

void ASimModeBase::advanceTimeOfDay()
{
if (sky_sphere_ && sun_) {
auto secs = ClockFactory::get()->elapsedSince(tod_last_update_);
const auto& settings = getSettings();
if (secs > settings.tod_settings.update_interval_secs) {
tod_last_update_ = ClockFactory::get()->nowNanos();

auto interval = ClockFactory::get()->elapsedSince(tod_sim_clock_start_) * settings.tod_settings.celestial_clock_speed;
uint64_t cur_time = ClockFactory::get()->addTo(tod_sim_clock_start_, interval) / 1E9;

UAirBlueprintLib::LogMessageString("DateTime: ", Utils::to_string(cur_time), LogDebugLevel::Informational);

auto coord = msr::airlib::EarthCelestial::getSunCoordinates(cur_time, settings.origin_geopoint.home_point.latitude,
settings.origin_geopoint.home_point.longitude);

auto rot = FRotator(-coord.altitude, coord.azimuth, 0);
sun_->SetActorRotation(rot);

FOutputDeviceNull ar;
sky_sphere_->CallFunctionByNameWithArguments(TEXT("UpdateSunDirection"), ar, NULL, true);
}

}
}

void ASimModeBase::reset()
{
//Should be overridden by derived classes
Expand Down
20 changes: 18 additions & 2 deletions Unreal/Plugins/AirSim/Source/SimMode/SimModeBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include "ManualPoseController.h"
#include "VehiclePawnWrapper.h"
#include "common/AirSimSettings.hpp"
#include "Components/SkyLightComponent.h"
#include "Engine/DirectionalLight.h"
#include "SimModeBase.generated.h"


Expand Down Expand Up @@ -50,15 +52,29 @@ class AIRSIM_API ASimModeBase : public AActor
typedef msr::airlib::AirSimSettings AirSimSettings;
virtual void setupInputBindings();
virtual const AirSimSettings& getSettings() const;
long long getPhysicsLoopPeriod();

protected: //settings
int record_tick_count;
static const char kUsageScenarioComputerVision[];


private:
typedef common_utils::Utils Utils;
typedef msr::airlib::ClockFactory ClockFactory;
typedef msr::airlib::TTimePoint TTimePoint;

private:
void readSettings();
void setStencilIDs();
UClass* sky_sphere_class_;
UPROPERTY() AActor* sky_sphere_;
UPROPERTY() ADirectionalLight* sun_;;
TTimePoint tod_sim_clock_start_;
TTimePoint tod_last_update_;
std::time_t tod_start_time_;

private:
void setStencilIDs();
void setupTimeOfDay();
void setupClock();
void advanceTimeOfDay();
};
38 changes: 0 additions & 38 deletions Unreal/Plugins/AirSim/Source/SimMode/SimModeWorldBase.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
#include "SimModeWorldBase.h"
#include "common/ScalableClock.hpp"
#include "common/SteppableClock.hpp"
#include <exception>

const char ASimModeWorldBase::kUsageScenarioComputerVision[] = "ComputerVision";

void ASimModeWorldBase::BeginPlay()
{
Super::BeginPlay();

setupClock();

manual_pose_controller = NewObject<UManualPoseController>();
setupInputBindings();

Expand All @@ -33,22 +28,6 @@ void ASimModeWorldBase::BeginPlay()
}
}

void ASimModeWorldBase::setupClock()
{
typedef msr::airlib::ClockFactory ClockFactory;

float clock_speed = getSettings().clock_speed;
std::string clock_type = getSettings().clock_type;

if (clock_type == "ScalableClock")
ClockFactory::get(std::make_shared<msr::airlib::ScalableClock>(clock_speed == 1 ? 1 : 1 / clock_speed));
else if (clock_type == "SteppableClock")
ClockFactory::get(std::make_shared<msr::airlib::SteppableClock>(
static_cast<msr::airlib::TTimeDelta>(getPhysicsLoopPeriod() * 1E-9 * clock_speed)));
else
throw std::invalid_argument(common_utils::Utils::stringf(
"clock_type %s is not recognized", clock_type.c_str()));
}

void ASimModeWorldBase::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Expand All @@ -70,23 +49,6 @@ void ASimModeWorldBase::stopAsyncUpdator()
physics_world_->stopAsyncUpdator();
}

long long ASimModeWorldBase::getPhysicsLoopPeriod() //nanoseconds
{
/*
300Hz seems to be minimum for non-aggresive flights
400Hz is needed for moderately aggressive flights (such as
high yaw rate with simultaneous back move)
500Hz is recommanded for more aggressive flights
Lenovo P50 high-end config laptop seems to be topping out at 400Hz.
HP Z840 desktop high-end config seems to be able to go up to 500Hz.
To increase freq with limited CPU power, switch Barometer to constant ref mode.
*/

if (getSettings().usage_scenario == kUsageScenarioComputerVision)
return 30000000LL; //30ms
else
return 3000000LL; //3ms
}

std::vector<ASimModeWorldBase::UpdatableObject*> ASimModeWorldBase::toUpdatableObjects(
const std::vector<ASimModeWorldBase::VehiclePtr>& vehicles)
Expand Down
Loading

0 comments on commit fcb01f5

Please sign in to comment.