算法艺术创作
algorithmic-art
通过代码和可调参数创作生成艺术与交互式视觉效果。
matlab-design-radar-waveform【设计与创意】Design, select, and analyze waveforms for radar, sonar, and active sensing using the Phased Array System Toolbox. Covers LFM, NLFM, FMCW, phase-coded, CW, stepped FM, custom IQ, ambiguity functions, sidelobe reduction, and Doppler tolerance. Key objects: phased.LinearFMWaveform, phased.NonlinearFMWaveform, phased.CustomFMWaveform, phased.PhaseCodedWa…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
name: matlab-design-radar-waveform description: > Design, select, and analyze waveforms for radar, sonar, and active sensing using the Phased Array System Toolbox. Covers LFM, NLFM, FMCW, phase-coded, CW, stepped FM, custom IQ, ambiguity functions, sidelobe reduction, and Doppler tolerance. Key objects: phased.LinearFMWaveform, phased.NonlinearFMWaveform, phased.CustomFMWaveform, phased.PhaseCodedWaveform, phased.FMCWWaveform, phased.SteppedFMWaveform, phased.MFSKWaveform, phased.RectangularWaveform, nlfmspec2freq, shapespectrum, ambgfun, pambgfun, sidelobelevel, legendreseq, mlseq, radarWaveformGenerator. keywords:
Design and select radar waveforms using the Phased Array System Toolbox. Use the decision tree to select the correct waveform object based on requirements, follow correct function-to-object pairings, and avoid common mistakes.
Primary keywords (any of these alone can trigger the skill): waveform, signal, chirp, LFM, NLFM, FMCW, PMCW, pulse compression, transmit signal, M-sequence, MLS, PN code, spread spectrum, phase code, joint radar-communication, dual-function waveform
Sensing-context words (confirm sensing domain when paired with primary keywords): target, jammer, jamming, pulse, pulses, spectrum, sidelobe, Doppler, range resolution, detection, clutter, matched filter, ambiguity, sweep, PRF, PRI
Trigger logic:
After triggering, clarify purpose and scope:
Purpose — application-driven or exploration/learning?
radarWaveformGenerator. Do not push for application context.Application dimensions (ask what's unknown — applies to any sensing application): Range scale | Target motion and velocity | Resolution need | Environment (clutter, jamming, interference) | Hardware limits (ADC, duty cycle) | Primary metric (detection, resolution, accuracy, or ambiguity-free)
Requirements — Derive waveform parameters from the answers above (see table below)
Do not answer as if waveform choice alone solves:
Instead, explain that the issue is system-level and identify what waveform-related part can still be addressed.
radarWaveformGenerator appAlways generate signals using toolbox System objects and functions — never
manually construct exp(1j*...) or write custom LFSR/sequence generators.
If mlseq, legendreseq, phased.LinearFMWaveform, or another toolbox
function can produce what you need, use it. Manual construction is only
acceptable when no toolbox equivalent exists for the specific operation
(e.g., applying element-wise phase modulation to an existing waveform vector).
For hybrid waveforms (e.g., LFM + communication encoding), generate the base
with the appropriate object, apply the modification, then wrap the result with
PhaseCodedWaveform using Code='Custom'. If no built-in object fits (e.g.,
exact DFT-bin nulls, non-contiguous bands), escalate to custom IQ synthesis but
keep toolbox functions for parameter derivation, wrapping, and analysis. Always
state which parts are toolbox-based and which are custom.
Never use xcorr for radar waveform autocorrelation or matched filter
response visualization. Instead:
ambgfun with
'Cut','Doppler' (zero-Doppler cut = response vs delay).sidelobelevel on the dB-converted cut.ambgfun with 'Cut','Delay' (zero-delay
cut = response vs Doppler).phased.MatchedFilter when you
need the actual filtered signal (range processing, bit recovery, etc.).mlseq/legendreseq/apaseq for sequences, wrap custom results in PhaseCodedWaveform with Custom code. Do not write manual signal construction. Suggest radarWaveformGenerator for interactive exploration.radarWaveformGenerator requires R2026a.evaluate_matlab_code calls. Instead, design the full script, save it to a .m file, and run it once with run_matlab_file. To save the file: use the Write tool if available, otherwise use evaluate_matlab_code with MATLAB's writelines or fopen/fprintf/fclose. Never use Bash heredocs for MATLAB code — single quotes and format strings (%d, \n) break shell quoting. If you are uncertain about an API or parameter and find yourself wanting to "try things" in MATLAB, that is a signal to stop and ask the user for clarification rather than exploring interactively. Reserve evaluate_matlab_code for at most: (1) one setup/cleanup call, (2) saving and running the script, and (3) one retry if needed.Once the application dimensions are known, check for these specific gaps:
| If the user hasn't specified... | Ask about... | Impacts... |
|---|---|---|
| Modulation type | Pulsed vs CW; FM vs phase-coded | Object selection (decision tree) |
| Range resolution | Required resolution (m) | Bandwidth via rangeres2bw |
| Sidelobe requirement | Acceptable PSL (dB) | NLFM vs windowed matched filter vs phase code choice |
| Range and velocity together | Max unambiguous range AND velocity | PRF conflict check (see Parameter Derivation) |
| Doppler tolerance | Max target velocity during dwell | LFM (tolerant) vs phase-coded (sensitive) tradeoff |
| Hardware constraints | ADC bandwidth, instantaneous BW limit | Stretch processing or stepped FM instead of wideband LFM |
shapespectrum only for PRO-FM. See references/spectral-notching.mdnlfmspec2freq + CustomFMWaveformPhaseCodedWaveform with Code='Custom')pambgfun (not ambgfun)See references/waveform-objects.md for the family summary table (strengths/tradeoffs).
Is the waveform continuous (CW)?
├── Yes: Does the user need linear FM sweep?
│ ├── Yes: Multiple targets where ghost targets are a concern?
│ │ ├── Yes → phased.MFSKWaveform (resolves range+speed without ghosts)
│ │ └── No → phased.FMCWWaveform (triangle sweep for range+speed)
│ └── No: Does the user need multiple frequency steps?
│ ├── Yes → phased.MFSKWaveform
│ └── No: No dedicated CW object for desired modulation?
│ └── Use pulsed object with PRF = 1/PulseWidth (see CW Pattern below)
│ ├── Nonlinear FM → phased.NonlinearFMWaveform or phased.CustomFMWaveform
│ └── Phase-coded → phased.PhaseCodedWaveform
│
└── No (pulsed): What modulation?
├── None (simple pulse) → phased.RectangularWaveform
├── Linear FM → phased.LinearFMWaveform
├── Nonlinear FM (built-in type) → phased.NonlinearFMWaveform
│ (4 types: Polynomial, Hyperbolic, Hybrid Linear-Tangent, Stepped Price)
├── Nonlinear FM (custom shape) → phased.CustomFMWaveform
│ (use with nlfmspec2freq for stationary-phase design)
├── Phase-coded → phased.PhaseCodedWaveform
├── Stepped frequency → phased.SteppedFMWaveform
└── Hybrid (base waveform + additional modulation)
→ Generate base with appropriate FM/pulse object
→ Apply secondary modulation to the IQ vector
→ Wrap result with PhaseCodedWaveform (Code='Custom')
| Function | Purpose | Available From |
|---|---|---|
rangeres2bw | Convert range resolution (m) to bandwidth (Hz) | — |
speed2dop | Convert speed to Doppler shift (one-way only; multiply by 2 for radar) | — |
freq2wavelen | Convert carrier frequency to wavelength | — |
nlfmspec2freq | Compute instantaneous frequency from desired spectrum shape | R2023a |
shapespectrum | Generate waveform with desired spectrum shape (notching, masks) | R2024b |
sidelobelevel | Measure peak and integrated sidelobe levels (input must be in dB) | R2024b |
legendreseq | Generate Legendre sequences (perfect periodic autocorrelation) | R2024a |
mlseq | Generate maximum-length sequences | R2024a |
apaseq | Generate almost-perfect autocorrelation sequences; pass length N | R2024a |
pnkcode | Generate polyphase P(n,k) code of length N: pnkcode(N, n, k) — best for deep PSL | R2024a |
getMatchedFilter | Return matched filter coefficients; returns a matrix (one column per step) for SteppedFMWaveform — filter each pulse with its corresponding column | — |
bandwidth | Return waveform bandwidth (Hz); available on all pulsed objects except SteppedFMWaveform | — |
ambgfun | Compute ambiguity function (any waveform, including pulse trains) | — |
pambgfun | Compute periodic ambiguity function (CW/periodic waveforms) | — |
Derive all waveform parameters from system requirements — never hardcode.
fc = 10e9; % carrier frequency
rangeRes = 20; % required range resolution (m)
maxRange = 80e3; % max unambiguous range (m)
maxVel = 300; % max target velocity (m/s)
lambda = freq2wavelen(fc);
bw = rangeres2bw(rangeRes); % bandwidth from range resolution
c = physconst('LightSpeed');
prfMax = c / (2 * maxRange); % max PRF from range ambiguity
fdMax = 2 * speed2dop(maxVel, lambda); % TWO-WAY Doppler (speed2dop is one-way)
tbp = 50; % time-bandwidth product
pw = tbp / bw; % pulse width from TBP
PRF conflict: If fdMax > prfMax, the velocity requirement demands a higher
PRF than the range requirement allows — no single PRF satisfies both. Do NOT
proceed with a single-PRF design. Present the conflict, explain the trade-off
(range vs velocity), and recommend staggered PRF or medium-PRF with ambiguity
resolution. Ask which strategy the user prefers before generating any waveform code.
Waveform objects accept PRF as a vector for staggered operation, but the ambiguity
resolution strategy is a system-level concern — see Escalation / Boundary Conditions.
Before generating code, verify:
PulseWidth <= 1/PRF (pulse fits within PRI)SampleRate / PRF is integer (integer samples per PRI)SampleRate * ChipWidth is integerfs = ceil(8*bw / prf) * prf guarantees integer samples/PRI + oversamplingMainlobe broadening compensation: When using tapering (windowed MF or NLFM):
bwComp = rangeres2bw(rangeRes, 'RangeBroadening', broadeningFactor) (Taylor ~1.3×).
Use nlfmspec2freq to compute the frequency profile from a desired spectrum
shape, then feed it to phased.CustomFMWaveform. Do NOT use with
phased.NonlinearFMWaveform (which has fixed built-in types only).
% Design NLFM waveform with low sidelobes
bw = 5e6;
nSamples = 500;
desiredSpectrum = taylorwin(nSamples, 4, -40);
freq = nlfmspec2freq(bw, desiredSpectrum);
wav = phased.CustomFMWaveform( ...
'PulseWidth', 10e-6, ...
'SampleRate', 10e6, ...
'FrequencyModulation', freq);
TBP-PSL trade-off: The stationary-phase approximation introduces Fresnel ripples that limit achievable PSL. The design spectrum (e.g., Taylor window) sets an upper bound, but actual PSL is always worse than the design SLL — the gap narrows as TBP increases. At low TBP (< 100), expect PSL significantly above the design target; at high TBP (200+), PSL approaches the design SLL.
If the achieved PSL doesn't meet the target, do not iterate on window parameters or design tweaks — the gap is a fundamental limitation of the stationary-phase method at that TBP. Instead, present the trade-off options:
When no dedicated CW object exists for your modulation type, use a pulsed
waveform object with PRF = 1/PulseWidth so the pulse fills the entire PRI.
Do NOT use DutyCycle = 1 — this errors on all pulsed waveform objects.
Instead, set PRF equal to the reciprocal of the pulse width.
% Phase-coded CW using Legendre sequence
seq = legendreseq(127);
chipWidth = 1e-6;
prf = 1/(numel(seq) * chipWidth); % 100% duty cycle
wav = phased.PhaseCodedWaveform( ...
'Code', 'Custom', ...
'CustomCode', seq, ... % Do NOT set NumChips — inferred from vector length
'ChipWidth', chipWidth, ...
'PRF', prf, ...
'SampleRate', 10e6);
IMPORTANT: Never set NumChips when Code='Custom'. The chip count is
inferred from the CustomCode vector length. Setting NumChips explicitly
produces a warning and may cause unexpected behavior.
PMCW (Phase-Modulated Continuous Wave): PMCW = phase-coded CW with 100%
duty cycle. Configure as PRF = 1/(numel(code) * ChipWidth). If the user says
"PMCW", treat as CW — PRI in PMCW context means code repetition interval, not
pulsed transmission with dead time.
Use phased.PhaseCodedWaveform with Code='Custom' to wrap ANY complex IQ
vector into the toolbox ecosystem — whether captured from hardware, loaded from
a file, or constructed by combining/modifying other waveforms (e.g., LFM with
embedded communication phase modulation). Despite the name, CustomCode accepts
any complex-valued vector — not just phase values. Do not set NumChips when
using Custom code — it is inferred from the vector length.
% Example: LFM + communication phase encoding as a toolbox object
wfLFM = phased.LinearFMWaveform('SampleRate', fs, 'PulseWidth', pw, ...
'SweepBandwidth', bw, 'PRF', prf);
xLfm = wfLFM();
xHybrid = xLfm(1:nPulse) .* exp(1j * commPhaseVector);
wfHybrid = phased.PhaseCodedWaveform( ...
'Code', 'Custom', ...
'CustomCode', xHybrid, ...
'ChipWidth', 1/fs, ...
'SampleRate', fs, ...
'PRF', prf);
% Now usable with toolbox processing
mfCoeffs = getMatchedFilter(wfHybrid);
When NOT to wrap: If you only need ambiguity analysis on IQ, pass it
directly to ambgfun(iq, fs, prf) — no object needed. Use the wrapper only when
you need toolbox integration (matched filter, range processing, etc.).
Three approaches, depending on context:
1. Time-domain windowed matched filter (reliable, works with any waveform):
Apply a window directly to the matched filter coefficients. This reliably
achieves the target PSL at any TBP, at the cost of mismatch loss (~3 dB for
-35 dB target, ~4 dB for -40 dB). Use SampleRate >= 8 * bandwidth for
accurate PSL measurement.
wav = phased.LinearFMWaveform('PulseWidth', 10e-6, 'SweepBandwidth', 5e6, ...
'SampleRate', 40e6, 'PRF', 1e4);
mfCoeffs = getMatchedFilter(wav);
N = numel(mfCoeffs);
tWin = taylorwin(N, 4, -40); % target -40 dB PSL
mf = phased.MatchedFilter('Coefficients', mfCoeffs .* tWin);
Note on SpectrumWindow property: The SpectrumWindow property of
phased.MatchedFilter applies spectral weighting in the frequency domain.
Testing indicates it achieves only ~50% of the specified attenuation in dB
(e.g., Taylor-40 spec → ~-20 dB actual PSL). Use time-domain coefficient
windowing when precise PSL control is required.
2. NLFM (inherent low sidelobes, no SNR loss):
Use the NLFM Design pattern above with nlfmspec2freq + CustomFMWaveform.
No SNR loss unlike windowed matched filter. Mainlobe broadens (amount depends
on the spectral taper shape). Requires sufficient TBP to approach target PSL.
3. Phase codes with good autocorrelation:
Use pnkcode for deep PSL (< -30 dB) at moderate lengths. legendreseq only
achieves ~-17 dB PSL. See references/phase-code-reference.md for selection.
Ambiguity shape drives waveform choice:
| Shape | Character | When to use |
|---|---|---|
| Ridge (LFM) | Doppler tolerant — shift causes range offset, not SNR loss | Robustness to unknown Doppler; velocity resolved elsewhere |
| Thumbtack-like (some phase-coded, optimized codes) | Clean range–Doppler decoupling | Need unambiguous range AND Doppler from the same waveform |
Do not assume waveform class guarantees thumbtack — phase-coded can still be
Doppler sensitive; NLFM improves range sidelobes but may not decouple delay-Doppler.
Always validate with ambgfun 2D cut.
Choose the right function: ambgfun for single pulses and pulse trains;
pambgfun for CW/periodic waveforms (exploits periodicity for finer Doppler).
Critical: Pass the full PRI output to ambgfun (includes trailing zeros),
not just the pulse portion — pulse-only will error:
sig = wf(); % full PRI — pass this to ambgfun
Cut direction (counterintuitive naming): The 'Cut' parameter specifies
which variable is HELD CONSTANT, not which axis is returned:
| Cut parameter | Held constant | Returns | Use for |
|---|---|---|---|
'Cut','Doppler' | Doppler = CutValue (Hz) | [afmag, delay] | Range sidelobes (matched filter response) |
'Cut','Delay' | Delay = CutValue (s) | [afmag, doppler] | Doppler tolerance (velocity sensitivity) |
Cuts return 2 outputs only — do not request 3 outputs with cuts.
See references/analysis-functions.md for detailed usage examples and
plotting guidelines.
Processing stepped FM data requires coherent integration across frequency steps,
not a single matched filter. Apply matched filter per step, then combine returns
across steps (IFFT across the frequency dimension) to synthesize the full
bandwidth and achieve the fine range resolution. The effective bandwidth is
NumSteps × FrequencyStep. See references/waveform-objects.md for full code.
When approximate target range is known, use stretch processing instead of matched
filtering to avoid wideband ADC. Only available for LinearFMWaveform.
wav = phased.LinearFMWaveform('PulseWidth', 10e-6, 'SweepBandwidth', 100e6);
strproc = getStretchProcessor(wav, 5000, 200); % refRange, rngSpan
slope = bw / pw; % sweep slope for range conversion
rng = stretchfreq2rng(beatFreq, slope, refRange);
phased.NonlinearFMWaveform with Type='Polynomial': the polynomial defines
instantaneous frequency, not phase. LFM = linear frequency → coefficients
[0, 1, 0]. Do NOT use [1, 0, 0] — that gives quadratic frequency (not LFM).
See references/waveform-objects.md for coefficient examples.
Waveform-only PSL claims are incomplete — always state the receiver assumption:
| Receiver | PSL behavior | SNR cost |
|---|---|---|
| Pure matched filter | Waveform-determined PSL | 0 dB (optimal) |
| Time-domain windowed MF | Achieves target PSL reliably | ~3-4 dB mismatch loss |
| Full-band MF after Tx notch | Narrow notch: controlled by window; wide: floor from gap | Negligible for narrow notch |
| NLFM (self-matched) | TBP-limited PSL, no Rx loss | 0 dB |
Every waveform design script should report:
sidelobelevel) and whether it meets the requirementNumChips (inferred from vector)SampleRate >= 8*bandwidth and dB input to sidelobelevelSampleRate/PRF is integerambgfun size error → pass full PRI from wf(), not just pulse portion2*speed2dop for two-way radar DopplerSampleRate*ChipWidth is integerSee references/common-mistakes.md for the full catalog.
CustomFMWaveform + PRF=1/PulseWidth + nlfmspec2freq → pambgfunexp(1j*...) or custom sequence generators (see Construction Rule)radarWaveformGenerator for interactive waveform exploration (requires R2026a)references/phase-code-reference.md)yline(targetPSL, 'r--') on the zero-Doppler cut for visual pass/fail verificationreferences/waveform-objects.md — All 8 waveform objects with properties and constraintsreferences/phase-code-reference.md — Code types, binary vs polyphase, NumChips constraintsreferences/analysis-functions.md — ambgfun, pambgfun, sidelobelevel usage detailsreferences/common-mistakes.md — Full catalog of common mistakes with correctionsreferences/spectral-notching.md — Spectral notching for interference avoidance, shapespectrum API