Skip to content

Commit

Permalink
Predictive PEC: use the monotonic clock rather than the system wall c…
Browse files Browse the repository at this point in the history
…lock

GP guider needs accurate time interval measurements, and is not interested
in the wall clock.  std::chrono::steady_clock is a better choice than system_clock.

Testing:
 - gp guider unit tests pass
  • Loading branch information
agalasso committed Dec 21, 2024
1 parent adda1b6 commit b6bb34f
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@
#define HYSTERESIS 0.1 // for the hybrid mode

GaussianProcessGuider::GaussianProcessGuider(guide_parameters parameters)
: start_time_(std::chrono::system_clock::now()), last_time_(std::chrono::system_clock::now()), control_signal_(0),
prediction_(0), last_prediction_end_(0), dither_steps_(0), dithering_active_(false), dither_offset_(0.0),
circular_buffer_data_(CIRCULAR_BUFFER_SIZE), covariance_function_(), output_covariance_function_(),
gp_(covariance_function_), learning_rate_(DEFAULT_LEARNING_RATE), parameters(parameters)
: start_time_(clock::now()), last_time_(clock::now()), control_signal_(0), prediction_(0), last_prediction_end_(0),
dither_steps_(0), dithering_active_(false), dither_offset_(0.0), circular_buffer_data_(CIRCULAR_BUFFER_SIZE),
covariance_function_(), output_covariance_function_(), gp_(covariance_function_), learning_rate_(DEFAULT_LEARNING_RATE),
parameters(parameters)
{
circular_buffer_data_.push_front(data_point()); // add first point
circular_buffer_data_[0].control = 0; // set first control to zero
Expand All @@ -86,7 +86,7 @@ GaussianProcessGuider::~GaussianProcessGuider() { }

void GaussianProcessGuider::SetTimestamp()
{
auto current_time = std::chrono::system_clock::now();
auto current_time = clock::now();
double delta_measurement_time = std::chrono::duration<double>(current_time - last_time_).count();
last_time_ = current_time;
get_last_point().timestamp = std::chrono::duration<double>(current_time - start_time_).count() -
Expand Down Expand Up @@ -238,7 +238,7 @@ double GaussianProcessGuider::PredictGearError(double prediction_location)
// in the first step of each sequence, use the current time stamp as last prediction end
if (last_prediction_end_ < 0.0)
{
last_prediction_end_ = std::chrono::duration<double>(std::chrono::system_clock::now() - start_time_).count();
last_prediction_end_ = std::chrono::duration<double>(clock::now() - start_time_).count();
}

// prediction from the last endpoint to the prediction point
Expand Down Expand Up @@ -296,7 +296,7 @@ double GaussianProcessGuider::result(double input, double SNR, double time_step,
// the starting time is set at the first call of result after startup or reset
if (get_number_of_measurements() == 1)
{
start_time_ = std::chrono::system_clock::now();
start_time_ = clock::now();
last_time_ = start_time_; // this is OK, since last_time_ only provides a minor correction
}

Expand Down Expand Up @@ -325,7 +325,7 @@ double GaussianProcessGuider::result(double input, double SNR, double time_step,
{
if (prediction_point < 0.0)
{
prediction_point = std::chrono::duration<double>(std::chrono::system_clock::now() - start_time_).count();
prediction_point = std::chrono::duration<double>(clock::now() - start_time_).count();
}
// the point of highest precision shoud be between now and the next step
UpdateGP(prediction_point + 0.5 * time_step);
Expand Down Expand Up @@ -380,7 +380,7 @@ double GaussianProcessGuider::deduceResult(double time_step, double prediction_p
{
if (prediction_point < 0.0)
{
prediction_point = std::chrono::duration<double>(std::chrono::system_clock::now() - start_time_).count();
prediction_point = std::chrono::duration<double>(clock::now() - start_time_).count();
}
// the point of highest precision should be between now and the next step
UpdateGP(prediction_point + 0.5 * time_step);
Expand Down Expand Up @@ -416,8 +416,8 @@ void GaussianProcessGuider::reset()
circular_buffer_data_[0].control = 0; // set first control to zero

last_prediction_end_ = -1.0; // the negative value signals we didn't predict yet
start_time_ = std::chrono::system_clock::now();
last_time_ = std::chrono::system_clock::now();
start_time_ = clock::now();
last_time_ = clock::now();

dither_offset_ = 0.0;
dither_steps_ = 0;
Expand Down Expand Up @@ -573,7 +573,7 @@ void GaussianProcessGuider::inject_data_point(double timestamp, double input, do
last_prediction_end_ = timestamp;
get_last_point().timestamp = timestamp; // overrides the usual HandleTimestamps();

start_time_ = std::chrono::system_clock::now() - std::chrono::seconds((int) timestamp);
start_time_ = clock::now() - std::chrono::seconds((int) timestamp);

add_one_point(); // add new point here, since the control is for the next point in time
HandleControls(control); // already store control signal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ enum Hyperparameters
class GaussianProcessGuider
{
public:
typedef std::chrono::steady_clock clock;

struct data_point
{
double timestamp;
Expand Down Expand Up @@ -113,8 +115,8 @@ class GaussianProcessGuider
};

private:
std::chrono::system_clock::time_point start_time_; // reference time
std::chrono::system_clock::time_point last_time_;
clock::time_point start_time_; // reference time
clock::time_point last_time_;

double control_signal_;
double prediction_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,11 +244,11 @@ TEST_F(GPGTest, timer_test)
GPG->result(1.0, 2.0, 3.0);
std::this_thread::sleep_for(std::chrono::milliseconds(wait));

auto time_start = std::chrono::system_clock::now();
auto time_start = GaussianProcessGuider::clock::now();
GPG->result(1.0, 2.0, 3.0);
double first_time = GPG->get_second_last_point().timestamp;
std::this_thread::sleep_for(std::chrono::milliseconds(wait));
auto time_end = std::chrono::system_clock::now();
auto time_end = GaussianProcessGuider::clock::now();
GPG->result(1.0, 2.0, 3.0);
double second_time = GPG->get_second_last_point().timestamp;

Expand Down
4 changes: 2 additions & 2 deletions src/guide_algorithm_gaussian_process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1019,7 +1019,7 @@ void GuideAlgorithmGaussianProcess::GuidingStarted()
bool need_reset = true;
double ra_offset; // RA delta in SI seconds

auto now = std::chrono::system_clock::now();
auto now = std::chrono::steady_clock::now();

double prev_ra = guiding_ra_;
guiding_ra_ = CurrentRA();
Expand Down Expand Up @@ -1092,7 +1092,7 @@ void GuideAlgorithmGaussianProcess::GuidingStopped()
double period_length = GPG->GetGPHyperparameters()[PKPeriodLength];
pConfig->Profile.SetDouble(GetConfigPath() + "/gp_period_per_kern", period_length);

guiding_stopped_time_ = std::chrono::system_clock::now();
guiding_stopped_time_ = std::chrono::steady_clock::now();
}

void GuideAlgorithmGaussianProcess::GuidingPaused() { }
Expand Down
2 changes: 1 addition & 1 deletion src/guide_algorithm_gaussian_process.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class GuideAlgorithmGaussianProcess : public GuideAlgorithm
bool block_updates_; // Don't update GP if guiding is disabled
double guiding_ra_; // allow resuming guiding after guiding stopped if there is no change in RA
PierSide guiding_pier_side_;
std::chrono::system_clock::time_point guiding_stopped_time_; // time guiding stopped
std::chrono::steady_clock::time_point guiding_stopped_time_; // time guiding stopped

protected:
double GetControlGain() const;
Expand Down

0 comments on commit b6bb34f

Please sign in to comment.