4、太阳角度与时间模拟:掌握如何通过调整太阳方位角和天顶角来模拟一天中的不同时间
各位同学,咱们今天聊聊Carla里怎么模拟一天中的时间变化。说白了,就是通过控制太阳的位置,让场景从清晨到正午再到黄昏,甚至深夜。这个功能在自动驾驶仿真里特别重要——你想想看,如果算法只在中午12点测试过,那到了傍晚光线变暗的时候,它还能正常工作吗?
我个人习惯把太阳角度拆成两个关键参数:方位角和天顶角。这两个东西搞明白了,时间模拟就掌握了一半。
4.1 方位角与天顶角:太阳位置的两个核心参数
先说说这两个角到底是什么。
- 方位角(Azimuth):太阳在水平面上的方向。0度代表正北,顺时针旋转。90度是正东,180度是正南,270度是正西。
- 天顶角(Zenith):太阳与天顶方向的夹角。0度代表太阳在头顶正上方,90度代表太阳在地平线上。
嗯,这里要注意:Carla里用的天顶角其实是太阳高度角的补角。高度角是太阳与地平线的夹角,天顶角 = 90° - 高度角。所以天顶角越大,太阳越低。
核心公式:
太阳高度角 = 90° - 天顶角
天顶角 = 90° - 太阳高度角
我在项目中遇到过一个问题:有同事直接把真实世界的天顶角数据丢进Carla,结果发现太阳位置完全不对。后来查文档才发现,Carla的天顶角定义和某些气象数据源是反的。所以大家用之前,一定先确认一下数据格式。
4.2 一天中的时间与太阳角度的对应关系
咱们来做个简单的映射。假设一天从早上6点到晚上6点,太阳轨迹大致是这样的:
| 时间 | 方位角(度) | 天顶角(度) | 说明 |
|---|---|---|---|
| 6:00(日出) | 90(正东) | 90 | 太阳刚露出地平线 |
| 9:00 | 120 | 60 | 上午,光线斜射 |
| 12:00(正午) | 180(正南) | 10 | 太阳接近头顶 |
| 15:00 | 240 | 60 | 下午,光线开始变斜 |
| 18:00(日落) | 270(正西) | 90 | 太阳即将落下 |
你想想看,这个表格其实是个简化版。真实世界中,不同季节、不同纬度,太阳轨迹差别很大。但做仿真时,我们往往不需要那么精确,只要视觉上看起来合理就行。
4.3 在Carla中设置太阳角度
好了,理论讲完了,咱们直接上代码。Carla里控制太阳角度是通过WeatherParameters类来实现的。
import carla
# 连接到Carla服务器
client = carla.Client('localhost', 2000)
world = client.get_world()
# 获取当前天气参数
weather = world.get_weather()
# 设置太阳方位角和天顶角
# 模拟正午12点:太阳在正南,接近头顶
weather.sun_azimuth_angle = 180.0 # 正南
weather.sun_altitude_angle = 80.0 # 高度角80度,接近头顶
# 注意:Carla用的是高度角,不是天顶角!
# 如果你有天顶角数据,需要转换:高度角 = 90 - 天顶角
# 应用天气设置
world.set_weather(weather)
小技巧:我个人习惯把太阳高度角控制在-10度到90度之间。低于-10度,场景会变得非常暗,而且Carla的渲染可能会出现一些奇怪的噪点。高于90度?嗯,太阳不可能跑到地底下去,所以别设超过90。
4.4 动态模拟一天的时间变化
静态设置太阳角度很简单,但咱们做仿真往往需要动态变化。比如测试一个从早上8点到中午12点的场景。这时候就需要在游戏循环里不断更新太阳角度。
import carla
import time
client = carla.Client('localhost', 2000)
world = client.get_world()
weather = world.get_weather()
# 模拟从早上8点到中午12点
start_hour = 8
end_hour = 12
total_minutes = (end_hour - start_hour) * 60
# 每帧更新一次,持续模拟
for minute in range(total_minutes):
# 计算当前时间对应的小时和分钟
current_hour = start_hour + minute // 60
current_minute = minute % 60
# 根据时间计算太阳角度(简化模型)
# 方位角:从90度(正东)线性变化到180度(正南)
azimuth = 90.0 + (current_hour - 8) * 22.5 # 每小时变化22.5度
# 高度角:从30度线性变化到80度
altitude = 30.0 + (current_hour - 8) * 12.5 # 每小时变化12.5度
weather.sun_azimuth_angle = azimuth
weather.sun_altitude_angle = altitude
world.set_weather(weather)
print(f"当前时间: {current_hour:02d}:{current_minute:02d}, "
f"方位角: {azimuth:.1f}°, 高度角: {altitude:.1f}°")
# 每模拟一分钟,等待0.1秒(实际仿真中根据帧率调整)
time.sleep(0.1)
这段代码里我用了线性插值,说白了就是简单粗暴地让太阳匀速移动。但真实世界中,太阳角度变化不是线性的,尤其是日出日落前后变化更快。不过对于大多数仿真场景,线性模型已经够用了。
避坑指南:我曾经在做一个连续12小时的仿真时,直接用线性模型模拟太阳轨迹。结果到了下午,太阳位置明显偏离了真实情况。后来我改用正弦曲线来模拟高度角的变化,效果就好多了。如果你需要高精度模拟,建议用天文算法计算太阳位置,或者直接查表。
4.5 结合光照强度调整
光调太阳角度还不够。你想想看,正午和黄昏的光照强度能一样吗?所以咱们还得同步调整光照强度。
Carla里光照强度是通过sun_intensity参数控制的,范围是0到100。我一般这样设置:
| 时间 | 太阳高度角 | 光照强度 |
|---|---|---|
| 日出/日落 | 0° - 15° | 20 - 40 |
| 上午/下午 | 15° - 60° | 60 - 80 |
| 正午前后 | 60° - 90° | 90 - 100 |
# 根据高度角设置光照强度
if altitude < 15:
intensity = 20 + (altitude / 15) * 20 # 20到40
elif altitude < 60:
intensity = 40 + ((altitude - 15) / 45) * 40 # 40到80
else:
intensity = 80 + ((altitude - 60) / 30) * 20 # 80到100
weather.sun_intensity = intensity
嗯,这里要注意:光照强度不要设到100以上,否则场景会过曝,看起来很不自然。我试过设到120,结果路面白花花一片,啥也看不清。
4.6 实战建议:如何快速验证太阳角度设置
最后分享一个我常用的调试方法。每次调整完太阳角度,我都会在场景里放一个参考物体,比如一个白色的立方体或者一辆车。然后观察它的阴影:
- 正午时分,阴影应该很短,几乎在物体正下方
- 早晨和傍晚,阴影应该很长,且方向明确
- 如果阴影方向不对,说明方位角设置有问题
- 如果阴影长度不对,说明高度角设置有问题
这个方法虽然土,但特别管用。我当年刚接触Carla时,就是靠这个办法一点点调出了满意的光照效果。
总结一下:
- 太阳位置由方位角和高度角(或天顶角)控制
- Carla用的是高度角,不是天顶角,注意转换
- 动态模拟时,建议用非线性模型更真实
- 别忘了同步调整光照强度
- 用阴影验证你的设置是否正确
好了,这一章的内容就到这里。下一章咱们聊聊云层和雾气的模拟,那个也挺有意思的。有什么问题,咱们群里见。