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:

committed by
WebRTC LUCI CQ

parent
ae4a832730
commit
949530e6aa
@ -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]) -
|
||||
kalmanGain[1] * frame_size_variation_bytes * t00;
|
||||
theta_cov_[1][1] = theta_cov_[1][1] * (1 - kalmanGain[1]) -
|
||||
kalmanGain[1] * frame_size_variation_bytes * t01;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user