-
Notifications
You must be signed in to change notification settings - Fork 103
Expand file tree
/
Copy pathGaussianNoiseModel.cc
More file actions
182 lines (154 loc) · 5.66 KB
/
Copy pathGaussianNoiseModel.cc
File metadata and controls
182 lines (154 loc) · 5.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*
* Copyright (C) 2018 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifdef _WIN32
// Ensure that Winsock2.h is included before Windows.h, which can get
// pulled in by anybody (e.g., Boost).
#include <Winsock2.h>
#endif
#include "gz/sensors/GaussianNoiseModel.hh"
#include <gz/math/Helpers.hh>
#include <gz/math/Rand.hh>
#include "gz/common/Console.hh"
using namespace gz;
using namespace sensors;
class gz::sensors::GaussianNoiseModelPrivate
{
/// \brief If type starts with GAUSSIAN, the mean of the distribution
/// from which we sample when adding noise.
public: double mean = 0.0;
/// \brief If type starts with GAUSSIAN, the standard deviation of the
/// distribution from which we sample when adding noise.
public: double stdDev = 0.0;
/// \brief If type starts with GAUSSIAN, the bias we'll add.
public: double bias = 0.0;
/// \brief If type starts with GAUSSIAN, the standard deviation of the
/// distribution from which the dynamic bias will be driven.
public: double dynamicBiasStdDev = 0.0;
/// \brief If type starts with GAUSSIAN, the correlation time of the
/// process from which the dynamic bias will be driven.
public: double dynamicBiasCorrTime = 0.0;
/// \brief If type==GAUSSIAN_QUANTIZED, the precision to which
/// the output signal is rounded.
public: double precision = 0.0;
/// \brief True if the type is GAUSSIAN_QUANTIZED
public: bool quantized = false;
};
//////////////////////////////////////////////////
GaussianNoiseModel::GaussianNoiseModel()
: Noise(NoiseType::GAUSSIAN), dataPtr(new GaussianNoiseModelPrivate())
{
}
//////////////////////////////////////////////////
GaussianNoiseModel::~GaussianNoiseModel()
{
delete this->dataPtr;
this->dataPtr = nullptr;
}
//////////////////////////////////////////////////
void GaussianNoiseModel::Load(const sdf::Noise &_sdf)
{
Noise::Load(_sdf);
std::ostringstream out;
this->dataPtr->mean = _sdf.Mean();
this->dataPtr->stdDev = _sdf.StdDev();
this->dataPtr->dynamicBiasStdDev = _sdf.DynamicBiasStdDev();
this->dataPtr->dynamicBiasCorrTime = _sdf.DynamicBiasCorrelationTime();
// Sample the bias
double biasMean = 0;
double biasStdDev = 0;
biasMean = _sdf.BiasMean();
biasStdDev = _sdf.BiasStdDev();
if (biasStdDev > 0.0)
this->dataPtr->bias = math::Rand::DblNormal(biasMean, biasStdDev);
else
this->dataPtr->bias = biasMean;
// With equal probability, we pick a negative bias (by convention,
// rateBiasMean should be positive, though it would work fine if
// negative).
if (math::Rand::DblUniform() < 0.5)
this->dataPtr->bias = -this->dataPtr->bias;
this->Print(out);
this->dataPtr->precision = _sdf.Precision();
if (this->dataPtr->precision < 0)
gzerr << "Noise precision cannot be less than 0" << std::endl;
else if (!math::equal(this->dataPtr->precision, 0.0, 1e-6))
this->dataPtr->quantized = true;
}
//////////////////////////////////////////////////
double GaussianNoiseModel::ApplyImpl(double _in, double _dt)
{
// Generate independent (uncorrelated) Gaussian noise to each input value.
double whiteNoise = this->dataPtr->stdDev > 0.0 ?
math::Rand::DblNormal(this->dataPtr->mean, this->dataPtr->stdDev) :
this->dataPtr->mean;
// Generate varying (correlated) bias to each input value.
// This implementation is based on the one available in Rotors:
// https://github.com/ethz-asl/rotors_simulator/blob/master/rotors_gazebo_plugins/src/gazebo_imu_plugin.cpp
//
// More information about the parameters and their derivation:
//
// https://github.com/ethz-asl/kalibr/wiki/IMU-Noise-Model
//
// This can only be generated in the case that _dt > 0.0
if (this->dataPtr->dynamicBiasStdDev > 0 &&
this->dataPtr->dynamicBiasCorrTime > 0 &&
_dt > 0)
{
double sigma_b = this->dataPtr->dynamicBiasStdDev;
double tau = this->dataPtr->dynamicBiasCorrTime;
double sigma_b_d = sqrt(-sigma_b * sigma_b *
tau / 2 * expm1(-2 * _dt / tau));
double phi_d = exp(-_dt / tau);
this->dataPtr->bias = phi_d * this->dataPtr->bias +
math::Rand::DblNormal(0, sigma_b_d);
}
double output = _in + this->dataPtr->bias + whiteNoise;
if (this->dataPtr->quantized)
{
// Apply this->dataPtr->precision
if (!math::equal(this->dataPtr->precision, 0.0, 1e-6))
{
output = std::round(output / this->dataPtr->precision) *
this->dataPtr->precision;
}
}
return output;
}
//////////////////////////////////////////////////
double GaussianNoiseModel::Mean() const
{
return this->dataPtr->mean;
}
//////////////////////////////////////////////////
double GaussianNoiseModel::StdDev() const
{
return this->dataPtr->stdDev;
}
//////////////////////////////////////////////////
double GaussianNoiseModel::Bias() const
{
return this->dataPtr->bias;
}
//////////////////////////////////////////////////
void GaussianNoiseModel::Print(std::ostream &_out) const
{
_out << "Gaussian noise, mean[" << this->dataPtr->mean << "], "
<< "stdDev[" << this->dataPtr->stdDev << "] "
<< "bias[" << this->dataPtr->bias << "] "
<< "precision[" << this->dataPtr->precision << "] "
<< "quantized[" << this->dataPtr->quantized << "]";
}