Question 1: Assuming that the oscillator (perhaps programmable) is
given, what kind of hardware would you suggest for (2) and (3) ?
For 2: All-pass (phase-shifting) filter, a.k.a. Hilbert transformer
For 3: Balanced modulator
Question 2: Does this setup have significant shortcomings (beside cost
of components?)
Yes. While direct conversion to complex baseband is regularly done in the digital domain, it can be quite finicky to get the same concept working well (and reliably) in the analog domain. It's nearly always easier to do the detection at an intermediate RF frequency.
Question 3: is this observation [about square-wave local oscillators] correct?
Yes, except that you want a bandbass filter that's centered on the carrier frequency, not a lowpass filter. Sometimes this filter has a bandwidth of approximately 2B, in which case it needs to be tuned along with the local oscillator. This sort of setup is called a preselector, and is commonly used in superheterodyne receivers, such as those used for the AM and FM broadcast bands.
But sometimes, a fixed bandpass filter that covers the entire band of interest is used instead. This works as long as none of the unwanted "image" bands ever falls into the band of interest. This is more common in 2-way VHF communications systems, such as those used for air traffic control and public service (police, fire).
I'm not sure what you're looking at, but you need to understand the exmples you link.
None of them use the truth-value within the actual filtering. It's there so you have something to compare to with regard to the filter output.
Here is the simple script:
import random
# intial parameters
iteration_count = 500
actual_values = [-0.37727 + j * j * 0.00001 for j in xrange(iteration_count)]
noisy_measurement = [random.random() * 0.6 - 0.3 + actual_val for actual_val in actual_values]
process_variance = 1e-5 # process variance
estimated_measurement_variance = 0.1 ** 2 # estimate of measurement variance, change to see effect
# allocate space for arrays
posteri_estimate_for_graphing = []
# intial guesses
posteri_estimate = 0.0
posteri_error_estimate = 1.0
for iteration in range(1, iteration_count):
# time update
priori_estimate = posteri_estimate
priori_error_estimate = posteri_error_estimate + process_variance
# measurement update
blending_factor = priori_error_estimate / (priori_error_estimate + estimated_measurement_variance)
posteri_estimate = priori_estimate + blending_factor * (noisy_measurement[iteration] - priori_estimate)
posteri_error_estimate = (1 - blending_factor) * priori_error_estimate
posteri_estimate_for_graphing.append(posteri_estimate)
import pylab
pylab.figure()
pylab.plot(noisy_measurement, color='r', label='noisy measurements')
pylab.plot(posteri_estimate_for_graphing, 'b-', label='a posteri estimate')
pylab.plot(actual_values, color='g', label='truth value')
pylab.legend()
pylab.xlabel('Iteration')
pylab.ylabel('Voltage')
pylab.show()
Lets break it down:
First, build the input array, and then create the simulated "noisy" input by adding random values to each item in the input array.
import random
# intial parameters
iteration_count = 500
actual_values = [-0.37727 + j * j * 0.00001 for j in xrange(iteration_count)]
noisy_measurement = [random.random() * 0.6 - 0.3 + actual_val for actual_val in actual_values]
Next, several parameters are defined that describe the characteristics of the system variance. These will have to be derived from your signal source.
process_variance = 1e-5 # process variance
estimated_measurement_variance = 0.1 ** 2 # estimate of measurement variance, change to see effect
# allocate space for arrays
posteri_estimate_for_graphing = []
# intial guesses
posteri_estimate = 0.0
posteri_error_estimate = 1.0
This is the actual filtering code:
for iteration in range(1, iteration_count):
# time update
priori_estimate = posteri_estimate
priori_error_estimate = posteri_error_estimate + process_variance
# measurement update
blending_factor = priori_error_estimate / (priori_error_estimate + estimated_measurement_variance)
posteri_estimate = priori_estimate + blending_factor * (noisy_measurement[iteration] - priori_estimate)
posteri_error_estimate = (1 - blending_factor) * priori_error_estimate
posteri_estimate_for_graphing.append(posteri_estimate)
Note: actual_values
is not referenced anywhere in the above code. The Kalman filter operates entirely on just the data within the noisy_measurement
array.
Finally, plot the various arrays.
import pylab
pylab.figure()
pylab.plot(noisy_measurement, color='r', label='noisy measurements')
pylab.plot(posteri_estimate_for_graphing, 'b-', label='a posteri estimate')
pylab.plot(actual_values, color='g', label='truth value')
pylab.legend()
pylab.xlabel('Iteration')
pylab.ylabel('Voltage')
pylab.show()
So basically, you don't need the truth value at all. You need to actually read your examples. It's graphed just so you can determine the efficacy of the Kalman filter.
Critically, particularly for testing purposes, you cannot characterize the error produced by a Kalman filter with contants of {n} without knowing the actual truth value. The filter will filter fine, but there is no way to determine if the output is accurate. Properly setting up the filter requires being able to measure just the noise within the system.
Best Answer
You can certainly use an adaptive Kalman Filter to identify or remove noise, and there are hundreds of articles on this in the signal processing literature. Whether you need to or not depends on the nature of your task and the noise -- whether the noise is in the frequency range of the signal, whether the noise is signal dependent, etc.
If it were me, unless there were reason to do otherwise, I'd try (in the following order)
1) make sure the signal is good -- i.e., make sure you're doing everything you can to quash the noise before its acquired, and make sure you're not doing something silly, like aliasing your noise into the signal by not acquiring fast enough or prefiltering (which will make your task very difficult
2) Try standard filtering techniques, like FIR and IIR filters to do what you need to do
3) Move on to non-linear, but easy, techniques, like median filtering, Sovitsky-Golay filtering, ..., which might be more tolerant to your noise.
4) Pull out the big guns-- the adaptive filters.
Finding the right filter in tough situations can be a matter of rolling up your sleeves and trying different things.