2. 光伏输出特性与浮标姿态耦合的日发电量估算
问题拆解:倾角时变如何进入发电量计算
浮标光伏板的输出功率由到达板面的辐照度决定,而板面辐照度又取决于太阳与板面法线之间的夹角。浮标随波浪摇摆时,板面倾角与方位角都在变化,因此不能用一个固定倾角代表全天。本例把这一耦合关系拆成三层:太阳位置几何、板面姿态序列、辐照度到功率的转换,再沿时间积分得到日发电量。
关键几何关系与计算约定
为避免方向混乱,本例统一采用东-北-天(ENU)右手坐标系:x 轴指向东,y 轴指向北,z 轴指向天顶。太阳方向单位向量由高度角 αs 与方位角 γs(从北顺时针)给出:
s = [cos(αs)·sin(γs), cos(αs)·cos(γs), sin(αs)]
板面法线由浮标姿态决定。设浮标静止时板面朝正南、倾角为 β0,横摇角 θr(绕 x 轴)与纵摇角 θp(绕 y 轴)随时间变化,则法线为:
n = R_x(θr) · R_y(θp) · n0
n0 = [0, −sin(β0), cos(β0)] // 朝南倾斜 β0
入射角余弦取 cosθ = max(0, n·s)。当 cosθ ≤ 0 时,直射分量记为零,仅保留散射分量。这一约定在正文、代码与上图中保持一致。
可运行的日发电量估算程序
下面给出一个不依赖第三方库的 Python 实现。它用正弦函数合成一条教学用的姿态序列(横摇 ±12°、纵摇 ±8°,周期分别为 6 s 与 9 s),并按 1 分钟步长积分。太阳位置采用简化的赤纬与时角公式,辐照度用晴空正弦包络加固定散射比例,所有数值均为教学示例假设,不代表实测。
import math
LAT = math.radians(26.0) # 浮标纬度(示例)
BETA0 = math.radians(30.0) # 静止时板面倾角
AREA = 0.6 # 组件面积 m^2
ETA = 0.18 # 组件效率
DNI_PEAK = 850.0 # 晴空直射峰值 W/m^2(示例)
DHI_RATIO = 0.18 # 散射占直射峰值比例(示例)
DT = 60.0 # 步长 s
def sun_vector(day_of_year, hour):
"""返回 ENU 坐标系下的太阳方向单位向量与高度角。"""
decl = math.radians(23.45) * math.sin(
math.radians(360.0 * (284 + day_of_year) / 365.0))
omega = math.radians(15.0 * (hour - 12.0))
sin_alt = (math.sin(LAT) * math.sin(decl)
+ math.cos(LAT) * math.cos(decl) * math.cos(omega))
alt = math.asin(max(-1.0, min(1.0, sin_alt)))
cos_alt = math.cos(alt)
if cos_alt < 1e-6:
return (0.0, 0.0, 0.0), alt
sin_az = -math.cos(decl) * math.sin(omega) / cos_alt
cos_az = ((math.sin(decl) - math.sin(alt) * math.sin(LAT))
/ (cos_alt * math.cos(LAT)))
az = math.atan2(sin_az, cos_az)
s = (cos_alt * math.sin(az), cos_alt * math.cos(az), math.sin(alt))
return s, alt
def normal_vector(roll, pitch):
"""由横摇、纵摇得到板面法线(ENU)。"""
n0 = (0.0, -math.sin(BETA0), math.cos(BETA0))
# R_y(pitch)
cy, sy = math.cos(pitch), math.sin(pitch)
x1 = cy * n0[0] + sy * n0[2]
y1 = n0[1]
z1 = -sy * n0[0] + cy * n0[2]
# R_x(roll)
cx, sx = math.cos(roll), math.sin(roll)
x2 = x1
y2 = cx * y1 - sx * z1
z2 = sx * y1 + cx * z1
return (x2, y2, z2)
def irradiance(s, n, alt):
"""板面辐照度 W/m^2。"""
if alt <= 0:
return 0.0
cos_theta = max(0.0, s[0]*n[0] + s[1]*n[1] + s[2]*n[2])
dni = DNI_PEAK * math.sin(alt)
dhi = DNI_PEAK * DHI_RATIO
beta = math.acos(max(-1.0, min(1.0, n[2])))
g = dni * cos_theta + dhi * (1.0 + math.cos(beta)) / 2.0
return g
def daily_energy(use_attitude):
total = 0.0
steps = int(24 * 3600 / DT)
for k in range(steps):
t = k * DT
hour = t / 3600.0
s, alt = sun_vector(172, hour) # 示例:夏至前后
if use_attitude:
roll = math.radians(12.0) * math.sin(2*math.pi*t/6.0)
pitch = math.radians(8.0) * math.sin(2*math.pi*t/9.0)
else:
roll = pitch = 0.0
n = normal_vector(roll, pitch)
g = irradiance(s, n, alt)
total += g * AREA * ETA * DT
return total / 3600.0 # Wh
e_fix = daily_energy(False)
e_att = daily_energy(True)
delta = (e_att - e_fix) / e_fix * 100.0
print(f"固定倾角日发电量: {e_fix:.1f} Wh")
print(f"实测姿态日发电量: {e_att:.1f} Wh")
print(f"姿态耦合偏差: {delta:+.2f}%")
结果判读与工程含义
运行上述程序会得到两个日发电量数值和一个百分比偏差。判读时注意三点:
- 偏差符号:若 E_att 低于 E_fix,说明摇摆使板面平均偏离最佳朝向,充电策略若按固定倾角估算会高估可用能量,需下调充电功率预期或延长充电窗口。
- 偏差量级:教学示例中横摇 ±12°、纵摇 ±8° 通常带来个位数到十几个百分点的差异,具体取决于纬度、季节与摇摆周期。偏差越大,固定倾角模型作为策略输入的误差越不可忽略。
- 时间分布:日总量相同不代表过程相同。正午前后太阳高度角大,倾角扰动对 cosθ 的影响更敏感;清晨傍晚则相反。策略若按小时调度,应关注逐时功率曲线而非仅看日总量。
把
use_attitude 换成从实际姿态日志读取的 (roll, pitch) 序列,即可将本程序直接用于真实浮标数据。姿态采样率高于 1 分钟时,建议先降采样或对功率做时间平均,避免高频摇摆被步长混叠。本例的辐照度模型是晴空正弦包络,未含云量、遮挡与组件温升。用于策略对比时结论方向可信,但绝对发电量不能当作实测值。若需更接近实际,应替换为历史气象辐照序列并加入温度修正项。
交付物:姿态耦合影响评估表
将程序输出整理成下表,可直接作为充电策略输入修正的依据。表中数值为上述教学示例在给定假设下的预期结果,实际运行会因参数不同而变化。
| 评估项 | 固定倾角基准 | 实测姿态序列 | 判读要点 |
|---|---|---|---|
| 板面倾角 β | 30° 恒定 | 随横摇/纵摇时变 | 姿态序列需与辐照序列时间对齐 |
| 日发电量 | E_fix | E_att | 两者用同一辐照与温度假设 |
| 相对偏差 Δ | 0(基准) | (E_att−E_fix)/E_fix | |Δ| 越大,固定倾角模型误差越大 |
| 对充电策略的影响 | 可能高估可用能量 | 更接近真实输入 | 偏差显著时改用姿态耦合估算 |
完成本例后,你应能说清一件事:浮标摇摆不是简单的“效率打折”,而是通过 cosθ 逐时改变板面接收的直射分量,最终在日积分上体现为可量化的偏差。这个偏差就是后续充电启停逻辑与策略回放需要使用的真实输入。