Improve FrameDelayDeltaKalmanFilter members naming.

* Update naming of data members.
* Start reordering code blocks in `PredictAndUpdate`.
  (The "predict" step is done in this C:. The "update"
   step will be improved in another cl.)

Bug: webrtc:14151
Change-Id: Idea1e8e786bd672dadedbcb3cd5598f4a033e81e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/271023
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Rasmus Brandt <brandtr@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37767}
This commit is contained in:
Rasmus Brandt
2022-08-12 13:53:21 +02:00
committed by WebRTC LUCI CQ
parent ae4a832730
commit 949530e6aa
2 changed files with 56 additions and 45 deletions

View File

@ -21,16 +21,20 @@ constexpr double kThetaLow = 0.000001;
FrameDelayDeltaKalmanFilter::FrameDelayDeltaKalmanFilter() {
// TODO(brandtr): Is there a factor 1000 missing here?
theta_[0] = 1 / (512e3 / 8); // Unit: [1 / bytes per ms]
theta_[1] = 0; // Unit: [ms]
estimate_[0] = 1 / (512e3 / 8); // Unit: [1 / bytes per ms]
estimate_[1] = 0; // Unit: [ms]
theta_cov_[0][0] = 1e-4; // Unit: [(1 / bytes per ms)^2]
theta_cov_[1][1] = 1e2; // Unit: [ms^2]
theta_cov_[0][1] = theta_cov_[1][0] = 0;
// Initial estimate covariance.
estimate_cov_[0][0] = 1e-4; // Unit: [(1 / bytes per ms)^2]
estimate_cov_[1][1] = 1e2; // Unit: [ms^2]
estimate_cov_[0][1] = estimate_cov_[1][0] = 0;
q_cov_[0][0] = 2.5e-10; // Unit: [(1 / bytes per ms)^2]
q_cov_[1][1] = 1e-10; // Unit: [ms^2]
q_cov_[0][1] = q_cov_[1][0] = 0;
// Process noise covariance.
process_noise_cov_[0][0] = 2.5e-10; // Unit: [(1 / bytes per ms)^2]
process_noise_cov_[1][1] = 1e-10; // Unit: [ms^2]
// TODO(brandtr): Remove, since matrix is always diagonal. No need to multiply
// by zero, below.
process_noise_cov_[0][1] = process_noise_cov_[1][0] = 0;
}
void FrameDelayDeltaKalmanFilter::PredictAndUpdate(
@ -38,28 +42,35 @@ void FrameDelayDeltaKalmanFilter::PredictAndUpdate(
double frame_size_variation_bytes,
DataSize max_frame_size,
double var_noise) {
// 1) Estimate prediction: There is no need to explicitly predict the
// estimate, since the state transition matrix is the identity.
// 2) Estimate covariance prediction: This is done by simply adding the
// process noise covariance, again since the state transition matrix is the
// identity.
estimate_cov_[0][0] += process_noise_cov_[0][0];
estimate_cov_[0][1] += process_noise_cov_[0][1]; // TODO(brandtr): Remove.
estimate_cov_[1][0] += process_noise_cov_[1][0];
estimate_cov_[1][1] += process_noise_cov_[1][1]; // TODO(brandtr): Remove.
// Measurement update.
// TODO(brandtr): Reorganize the code below to follow the standard update
// order as given by, e.g., Wikipedia.
double Mh[2];
double hMh_sigma;
double kalmanGain[2];
double measureRes;
double t00, t01;
// Kalman filtering
// Prediction
// M = M + Q
theta_cov_[0][0] += q_cov_[0][0];
theta_cov_[0][1] += q_cov_[0][1];
theta_cov_[1][0] += q_cov_[1][0];
theta_cov_[1][1] += q_cov_[1][1];
// Kalman gain
// K = M*h'/(sigma2n + h*M*h') = M*h'/(1 + h*M*h')
// h = [dFS 1]
// Mh = M*h'
// hMh_sigma = h*M*h' + R
Mh[0] = theta_cov_[0][0] * frame_size_variation_bytes + theta_cov_[0][1];
Mh[1] = theta_cov_[1][0] * frame_size_variation_bytes + theta_cov_[1][1];
Mh[0] =
estimate_cov_[0][0] * frame_size_variation_bytes + estimate_cov_[0][1];
Mh[1] =
estimate_cov_[1][0] * frame_size_variation_bytes + estimate_cov_[1][1];
// sigma weights measurements with a small deltaFS as noisy and
// measurements with large deltaFS as good
if (max_frame_size < DataSize::Bytes(1)) {
@ -86,45 +97,45 @@ void FrameDelayDeltaKalmanFilter::PredictAndUpdate(
// Correction
// theta = theta + K*(dT - h*theta)
measureRes = frame_delay_variation.ms() -
(frame_size_variation_bytes * theta_[0] + theta_[1]);
theta_[0] += kalmanGain[0] * measureRes;
theta_[1] += kalmanGain[1] * measureRes;
(frame_size_variation_bytes * estimate_[0] + estimate_[1]);
estimate_[0] += kalmanGain[0] * measureRes;
estimate_[1] += kalmanGain[1] * measureRes;
if (theta_[0] < kThetaLow) {
theta_[0] = kThetaLow;
if (estimate_[0] < kThetaLow) {
estimate_[0] = kThetaLow;
}
// M = (I - K*h)*M
t00 = theta_cov_[0][0];
t01 = theta_cov_[0][1];
theta_cov_[0][0] = (1 - kalmanGain[0] * frame_size_variation_bytes) * t00 -
kalmanGain[0] * theta_cov_[1][0];
theta_cov_[0][1] = (1 - kalmanGain[0] * frame_size_variation_bytes) * t01 -
kalmanGain[0] * theta_cov_[1][1];
theta_cov_[1][0] = theta_cov_[1][0] * (1 - kalmanGain[1]) -
t00 = estimate_cov_[0][0];
t01 = estimate_cov_[0][1];
estimate_cov_[0][0] = (1 - kalmanGain[0] * frame_size_variation_bytes) * t00 -
kalmanGain[0] * estimate_cov_[1][0];
estimate_cov_[0][1] = (1 - kalmanGain[0] * frame_size_variation_bytes) * t01 -
kalmanGain[0] * estimate_cov_[1][1];
estimate_cov_[1][0] = estimate_cov_[1][0] * (1 - kalmanGain[1]) -
kalmanGain[1] * frame_size_variation_bytes * t00;
theta_cov_[1][1] = theta_cov_[1][1] * (1 - kalmanGain[1]) -
estimate_cov_[1][1] = estimate_cov_[1][1] * (1 - kalmanGain[1]) -
kalmanGain[1] * frame_size_variation_bytes * t01;
// Covariance matrix, must be positive semi-definite.
RTC_DCHECK(theta_cov_[0][0] + theta_cov_[1][1] >= 0 &&
theta_cov_[0][0] * theta_cov_[1][1] -
theta_cov_[0][1] * theta_cov_[1][0] >=
RTC_DCHECK(estimate_cov_[0][0] + estimate_cov_[1][1] >= 0 &&
estimate_cov_[0][0] * estimate_cov_[1][1] -
estimate_cov_[0][1] * estimate_cov_[1][0] >=
0 &&
theta_cov_[0][0] >= 0);
estimate_cov_[0][0] >= 0);
}
double FrameDelayDeltaKalmanFilter::GetFrameDelayVariationEstimateSizeBased(
double frame_size_variation_bytes) const {
// Unit: [1 / bytes per millisecond] * [bytes] = [milliseconds].
return theta_[0] * frame_size_variation_bytes;
return estimate_[0] * frame_size_variation_bytes;
}
double FrameDelayDeltaKalmanFilter::GetFrameDelayVariationEstimateTotal(
double frame_size_variation_bytes) const {
double frame_transmission_delay_ms =
GetFrameDelayVariationEstimateSizeBased(frame_size_variation_bytes);
double link_queuing_delay_ms = theta_[1];
double link_queuing_delay_ms = estimate_[1];
return frame_transmission_delay_ms + link_queuing_delay_ms;
}

View File

@ -87,11 +87,11 @@ class FrameDelayDeltaKalmanFilter {
double frame_size_variation_bytes) const;
private:
double theta_[2]; // Estimated line parameters:
// (bandwidth [1 / bytes per ms],
// queue buildup [ms])
double theta_cov_[2][2]; // Estimate covariance.
double q_cov_[2][2]; // Process noise covariance.
// State estimate (bandwidth [1 / bytes per ms], queue buildup [ms]).
double estimate_[2];
double estimate_cov_[2][2]; // Estimate covariance.
double process_noise_cov_[2][2]; // Process noise covariance.
};
} // namespace webrtc