MATLAB: unwrap function
I'm in a discussion with someone from Mathworks re: the unwrap
function which has a "bug" in it for jump tolerances other than π, and would like to get some other perspectives:
开发者_Go百科Description
Q = unwrap(P)
corrects the radian phase angles in a vector P by adding multiples of ±2π when absolute jumps between consecutive elements of P are greater than or equal to the default jump tolerance of π radians. If P is a matrix, unwrap operates columnwise. If P is a multidimensional array, unwrap operates on the first nonsingleton dimension.
Q = unwrap(P,tol)
uses a jump tolerance tol instead of the default value, π.
There are two possible interpretations of the documentation:
Q = unwrap(P,tol)
corrects the radian phase angles in a vector P by adding multiples of ±2π when absolute jumps between consecutive elements of P are greater than or equal to tol radians. If P is a matrix, unwrap operates columnwise. If P is a multidimensional array, unwrap operates on the first nonsingleton dimension.Example:
>> x = mod(0:20:200,100); unwrap(x, 50) ans = 0 20.0000 40.0000 60.0000 80.0000 81.6814 101.6814 121.6814 141.6814 161.6814 163.3628
Q = unwrap(P,tol)
corrects the elements in a vector P by adding multiples of ±2*tol when absolute jumps between consecutive elements of P are greater than or equal to tol. If P is a matrix, unwrap operates columnwise. If P is a multidimensional array, unwrap operates on the first nonsingleton dimension.Example:
>> x = mod(0:20:200,100); unwrap(x, 50) ans = 0 20 40 60 80 100 120 140 160 180 200
The actual behavior of unwrap()
in MATLAB (at least up to R2010a) is #1. My interpretation of unwrap()
is that it's supposed to be #2, and therefore there is a bug in the behavior. If unwrap()
's behavior matched #2, then unwrap could be used as an inverse for mod for slowly-varying inputs, i.e. unwrap(mod(x,T),T/2) = x
for vectors x where successive elements vary by less than tol=T/2.
Note that this 2nd interpretation is more general than angles, and can unwrap anything with a wraparound period T. (whether a default of T=2π for radians, 360 for degrees, 256 for 8-bit numbers, 65536 for 16-bit numbers, etc.)
So my question is:
Are there possible uses for behavior #1? Which interpretation makes more sense?
Interpretation #1 is how I read the documentation and I think it makes sense. I could imagine to use it for reconstructing the driven distance from a wheel encoder. For slow speeds the tolerance doesn't matter, but for high speeds (high enough to violate the sampling theorem, i.e. you have less than two samples per wheel rotation), the tolerance helps you to get the right reconstruction if you know the direction.
Another reason why #1 makes more sense is probably that the ordinary unwrap can be extended easily to a generic one and therefore there's no direct need for the period to be a parameter.
% example for 16 bit integers
>> x1 = [10 5 0 65535 65525];
T = 65536;
x2 = T * unwrap(x1 * 2 * pi / T) / (2 * pi)
x2 =
10.0000 5.0000 0 -1.0000 -11.0000
Or just make your own function:
function ret = generic_unwrap(x, T)
ret = T * unwrap(x * 2 * pi / T) / (2 * pi);
end
Behavor #1 makes sense, since the input is assumed to be radians, not degrees. The adjustment adds pi/2 if you're above jump tolerance, so that's fine.
What would be nice was if unwrap had a feature that allowed it to work on any kind of series, not simply on radian angles.
The jump tolerance is not sufficient to tell whether you have a series in radian, or degree, or any other kind, so there would need to be an additional input.
I had always assumed that the second behavior was the actual one, but never tested it out. A literal reading of the help file does indicate behavior #1. But that's not what one would ever want to do. As a simple example, consider doing an unwrapping in degrees
x = mod(0:30:720, 360)
y = unwrap(x,180)
obviously you would want y = 0:30:720, but instead you get ...
y =
Columns 1 through 7
0 30.0000 60.0000 90.0000 120.0000 150.0000 180.0000
Columns 8 through 14
210.0000 240.0000 270.0000 300.0000 330.0000 333.0088 363.0088
Columns 15 through 21
393.0088 423.0088 453.0088 483.0088 513.0088 543.0088 573.0088
Columns 22 through 25
603.0088 633.0088 663.0088 666.0176
which is wrong (y no longer corresponds to the same angle as x, which is the point of unwrap)
Can anyone give an example of when you would want behavior #1 (the current behavior?)
x = mod(0:30*pi/180:4*pi, 2*pi);
y = unwrap(x)*180/pi;
It works in radians, but not in degrees.
精彩评论