快速入门

本教程引导你从安装到运行第一次链路仿真, 完成对 nearlink-sdr 的初步了解。

前置条件

  • Python 3.14 或更高版本

  • uv 包管理器

安装

克隆仓库并安装依赖:

git clone https://github.com/sanchuanhehe/nearlink_sdr_sim.git nearlink-sdr
cd nearlink-sdr
uv sync

运行测试

确认所有模块工作正常:

	uv run pytest tests/ -v --tb=short

第一次仿真: GFSK 链路

GFSK 是 SparkLink SLE 帧类型 1 使用的调制方式。下面的代码演示一次完整的 GFSK 调制-信道-解调流程:

from nearlink_sdr.phy.channel import ChannelModel
from nearlink_sdr.phy.gfsk import GFSKDemodulator, GFSKModulator

# 生成随机数据比特
rng = np.random.default_rng(42)
data_bits = rng.integers(0, 2, 200)

# 调制
mod = GFSKModulator(sps=8, mod_index=0.5)
tx_signal = mod.modulate(data_bits)

# 通过 AWGN 信道
ch = ChannelModel(snr_db=12.0)
rx_signal = ch.apply_awgn(tx_signal)

# 解调
demod = GFSKDemodulator(sps=8)
rx_bits = demod.demodulate(rx_signal)

# 计算误码率
ber = np.mean(data_bits != rx_bits[:len(data_bits)])
print(f"BER = {ber:.4f}")

完整代码见 examples/getting_started.py 中的 gfsk_link() 函数。

第一次仿真: PSK 编码链路

帧类型 2/3/4 使用 PSK 调制。结合 Polar 编码可以获得编码增益:

from nearlink_sdr.common.polar import PolarDecoder, PolarEncoder, get_info_bit_count

# Polar 编码参数: 码长 256, 码率 1/2
code_length = 256
K = get_info_bit_count("1/2", code_length)
enc = PolarEncoder(code_length, K)
dec = PolarDecoder(code_length, K)

# 信息比特
rng = np.random.default_rng(42)
info_bits = rng.integers(0, 2, K, dtype=np.int8)

# 编码
coded_bits = enc.encode(info_bits)

# BPSK 调制 (0 -> +1, 1 -> -1)
bpsk_signal = 1.0 - 2.0 * coded_bits.astype(np.float64)

# AWGN 信道
snr_db = 2.0
snr_lin = 10.0 ** (snr_db / 10.0)
R = K / code_length
noise_var = 1.0 / (2.0 * R * snr_lin)
noise = rng.normal(0, np.sqrt(noise_var), code_length)
received = bpsk_signal + noise

# SC 解码
llr = 2.0 * received / noise_var
decoded = dec.decode(llr)

errors = int(np.sum(info_bits != decoded))
print(f"比特错误数: {errors}/{K}")

BER 曲线仿真

项目内置了批量仿真函数, 可以直接绘制 BER 曲线:

make sim-phase1
# 输出 BER 数据并保存 ber_phase1.png

全链路 Pipeline 仿真

调用 sim_pipeline_link 进行端到端仿真, 覆盖 CRC、Polar 编码、加扰、调制、帧组装等全部物理层处理:

from nearlink_sdr.sim.link_sim import sim_pipeline_link

result = sim_pipeline_link(
    frame_type=2,
    mcs_index=7,
    n_data_bytes=10,
    snr_range_db=np.arange(0, 12, 2),
    n_frames=20,
)
for snr, ber in zip(result["snr_db"], result["ber"], strict=False):
    print(f"SNR={snr:2.0f} dB  BER={ber:.5f}")

SleNode 节点仿真

SleNode 是项目的顶层实体, 将物理层和 MAC 层全部组件整合为统一接口:

from nearlink_sdr.node import NodeConfig, NodeRole, SleNode

# 创建节点
config = NodeConfig(
    address=b"\x01\x02\x03\x04\x05\x06",
    role=NodeRole.G_NODE,
    frame_type=2,
    mcs_index=7,
    band="2400",
    hop_param2=0x1234,
)
node = SleNode(config=config)

# 推进时隙并获取当前跳频信道
node.advance_slot(1)
channel = node.current_channel
print(f"当前信道: {channel}")

# 功率调整
node.adjust_power(3.0)  # 增加 3 dB

# 查看节点状态
stats = node.stats
print(stats)

Phase 15 集成仿真

项目提供基于 SleNode 的完整集成仿真, 覆盖跳频、功率自适应、接入流程和信道扫频:

make sim-phase15
# 输出四面板可视化图: 跳频/接入/功率/信道

运行示例

所有入门示例已整合为独立脚本, 可直接运行:

make examples

下一步