how to redefine atan2 function from -inf to inf in matlab?
Categories:
Extending atan2
in MATLAB for a Full -∞ to +∞ Phase Range

Explore methods to redefine MATLAB's atan2
function to provide a continuous phase output from negative infinity to positive infinity, crucial for applications requiring unwrapped phase.
MATLAB's atan2(y, x)
function is widely used to calculate the four-quadrant inverse tangent, returning an angle in the range of (-π, π]
radians. While this range is suitable for many applications, certain scenarios, particularly in signal processing, control systems, or physics simulations, require a phase that extends continuously from negative infinity to positive infinity. This is often referred to as 'unwrapped phase' and is essential when tracking cumulative angular displacement or integrating phase changes over time.
Understanding the Limitation of Standard atan2
The standard atan2
function inherently provides a principal value, meaning it always maps the input (y, x)
pair to an angle within a single 2π
interval. This behavior is mathematically sound for determining the angle of a vector in a Cartesian plane. However, when dealing with sequences of angles that might cross the ±π
boundary multiple times, this 'wrapping' can lead to discontinuities. For instance, if an angle smoothly increases from π/2
to 3π/2
, atan2
would report a jump from π/2
to -π/2
, rather than a continuous increase.
flowchart TD A[Input: (y, x) pair] --> B{Calculate atan2(y, x)} B --> C[Output: Angle in (-π, π]] C --> D{Is continuous phase needed?} D -- No --> E[Use standard atan2 result] D -- Yes --> F[Apply phase unwrapping algorithm] F --> G[Output: Angle in (-∞, ∞)]
Flowchart illustrating the decision process for using standard vs. unwrapped atan2
.
Implementing Phase Unwrapping for atan2
To extend the range of atan2
to (-∞, ∞)
, you need to implement a phase unwrapping algorithm. This typically involves tracking the phase changes between consecutive samples and adding or subtracting multiples of 2π
whenever a 2π
jump (or wrap) is detected. MATLAB provides the unwrap
function, which is specifically designed for this purpose. It operates on an array of phase values, correcting the discontinuities.
% Example: Generating a complex signal with increasing phase
t = 0:0.01:10;
frequency = 1;
phase_true = 2 * pi * frequency * t; % True continuous phase
% Create a complex signal
complex_signal = exp(1i * phase_true);
% Calculate phase using atan2 (wrapped phase)
wrapped_phase = atan2(imag(complex_signal), real(complex_signal));
% Unwrap the phase
unwrapped_phase = unwrap(wrapped_phase);
% Plotting to visualize
figure;
plot(t, phase_true, 'b', 'DisplayName', 'True Phase');
hold on;
plot(t, wrapped_phase, 'r--', 'DisplayName', 'Wrapped Phase (atan2)');
plot(t, unwrapped_phase, 'g:', 'DisplayName', 'Unwrapped Phase');
xlabel('Time (s)');
ylabel('Phase (radians)');
title('Phase Unwrapping with atan2');
legend('Location', 'best');
grid on;
MATLAB code demonstrating the use of unwrap
on atan2
output.
unwrap
function works best when the phase difference between consecutive samples is less than π
. If your phase changes too rapidly between samples, unwrap
might misinterpret the 2π
jumps, leading to incorrect unwrapping. Ensure your sampling rate is sufficient for the rate of phase change.Manual Unwrapping for Custom Scenarios
While MATLAB's unwrap
function is robust, there might be specific cases where you need more control or are working with non-sequential data. In such situations, you can implement a manual unwrapping logic. This typically involves iterating through the phase array and adjusting each point based on the previous point's value and the 2π
boundary.
function unwrapped_phase = manual_unwrap(wrapped_phase)
unwrapped_phase = zeros(size(wrapped_phase));
unwrapped_phase(1) = wrapped_phase(1);
for k = 2:length(wrapped_phase)
diff = wrapped_phase(k) - wrapped_phase(k-1);
if diff > pi
unwrapped_phase(k) = wrapped_phase(k) - 2*pi;
elseif diff < -pi
unwrapped_phase(k) = wrapped_phase(k) + 2*pi;
else
unwrapped_phase(k) = wrapped_phase(k);
end
% Add the accumulated 2*pi shifts from previous steps
unwrapped_phase(k) = unwrapped_phase(k) + (unwrapped_phase(k-1) - (wrapped_phase(k-1) - mod(wrapped_phase(k-1) + pi, 2*pi) + pi));
end
end
% Example usage with the previous wrapped_phase
% unwrapped_phase_manual = manual_unwrap(wrapped_phase);
% figure;
% plot(t, phase_true, 'b', 'DisplayName', 'True Phase');
% hold on;
% plot(t, wrapped_phase, 'r--', 'DisplayName', 'Wrapped Phase (atan2)');
% plot(t, unwrapped_phase_manual, 'm-.', 'DisplayName', 'Manual Unwrapped Phase');
% xlabel('Time (s)');
% ylabel('Phase (radians)');
% title('Manual Phase Unwrapping');
% legend('Location', 'best');
% grid on;
A basic manual phase unwrapping function. Note: MATLAB's unwrap
is generally more robust.
unwrap
function unless you have a very specific reason and thoroughly test your custom implementation.1. Generate Complex Data
Create a complex signal z = x + iy
where x
and y
are the real and imaginary components, respectively. This could be from an FFT, a filter output, or a simulated signal.
2. Calculate Wrapped Phase
Use atan2(imag(z), real(z))
to obtain the initial wrapped phase values. This will be in the (-π, π]
range.
3. Apply Unwrapping Function
Pass the wrapped_phase
array to MATLAB's unwrap
function: unwrapped_phase = unwrap(wrapped_phase)
. This will correct the 2π
discontinuities.
4. Verify Results
Plot both the original wrapped_phase
and the unwrapped_phase
to visually confirm that the discontinuities have been removed and the phase now extends continuously.