计算太阳的路径

我正在编写几种必要的方法来计算特定点的太阳路径。 我已经使用两个不同的来源编写代码用于计算,并且都没有产生所需的结果。 来源是: http : //www.pveducation.org/pvcdrom/properties-of-sunlight/suns-position和http://www.esrl.noaa.gov/gmd/grad/solcalc/solareqns.PDF

注意:弧度为Deg * 60分钟。

  1. localSolartime:我已经将经度转换为’分钟’,从localStandardTimeMeridian方法派生的本地标准时间子午线(lstm)返回’分钟’中的值,以及也以’分钟’返回的equationOfTime。 使用pveducation中的等式,我计算了时间校正,它解释了给定时区内的小时间变化。 当我将这个结果和localTime(每分钟几分钟)应用到当地的太阳时(lst)方程时,结果是676.515(此刻),这对我没有任何意义。 据我所知,当地的太阳时代表示相对于太阳的时间,当它处于天空的最高点时,在当地,被认为是太阳正午。 676.515没有意义。 有没有人理解可能导致这种情况的原因。

  2. HourAngle:我希望一旦我修复了localSolarTime方法,就不需要纠正了。

我选择了华盛顿特区的纬度和经度。 Zenith和Azimuth读数都应该是正值,而对于我这个时刻,它们分别是66和201。

public class PathOfSun { static LocalTime localTime = LocalTime.now(); static double dcLat = 38.83; static double dcLong = -77.02; static DecimalFormat df = new DecimalFormat("#.0"); public static void main(String [] args) { int day = dayOfYear(); double equationOfTime = equationOfTime(day); double lstm = localTimeMeridian(); double lst = localSolarTime(equationOfTime, dcLong, lstm); double declination = declination(day); double hourAngle = hourAngle(lst); double zenith = zenith(dcLat, declination, hourAngle); double azimuth = azimuth(dcLong, declination, zenith, hourAngle); } //Longitude of timezone meridian public static double localTimeMeridian() { TimeZone gmt = TimeZone.getTimeZone("GMT"); TimeZone est = TimeZone.getTimeZone("EST"); int td = gmt.getRawOffset() - est.getRawOffset(); double localStandardTimeMeridian = 15 * (td/(1000*60*60)); //convert td to hours //System.out.println("Local Time Meridian: " + localStandardTimeMeridian); return localStandardTimeMeridian; } //Get the number of days since Jan. 1 public static int dayOfYear() { Calendar localCalendar = Calendar.getInstance(TimeZone.getDefault()); int dayOfYear = localCalendar.get(Calendar.DAY_OF_YEAR); //System.out.println("Day: " + dayOfYear); return dayOfYear; } //Emperical equation to correct the eccentricity of Earth's orbit and axial tilt public static double equationOfTime (double day) { double d =(360.0/365.0)*(day - 81); d = Math.toRadians(d); double equationTime = 9.87*sin(2*d)-7.53*cos(d)-1.54*sin(d); //System.out.println("Equation Of Time: " + equationTime); return equationTime; } //The angle between the equator and a line drawn from the center of the Sun(degrees) public static double declination(int dayOfYear) { double declination = 23.5*sin((Math.toRadians(360.0/365.0))*(dayOfYear - 81)); //System.out.println("Declination: " + df.format(declination)); return declination; } //Add the number of minutes past midnight localtime// public static double hourAngle(double localSolarTime) { double hourAngle = 15 * (localSolarTime - 13); System.out.println("Hour Angle: " + df.format(hourAngle)); //(degrees) return hourAngle; } //Account for the variation within timezone - increases accuracy public static double localSolarTime(double equationOfTime, double longitude, double lstm) { //LocalSolarTime = 4min * (longitude + localStandardTimeMeridian) + equationOfTime //Time Correction is time variation within given time zone (minutes) //longitude = longitude/60; //convert degrees to arcminutes double localStandardTimeMeridian = lstm; double timeCorrection = (4 * (longitude + localStandardTimeMeridian) + equationOfTime); System.out.println("Time Correction: " + timeCorrection); //(in minutes) //localSolarTime represents solar time where noon represents sun's is highest position // in sky and the hour angle is 0 -- hour angle is negative in morning, and positive after solar noon. double localSolarTime = (localTime.toSecondOfDay() + (timeCorrection*60)); //(seconds) localSolarTime = localSolarTime/(60*60); //convert from seconds to hours //Convert double to Time (HH:mm:ss) for console output int hours = (int) Math.floor(localSolarTime); int minutes = (int) ((localSolarTime - hours) * 60); //-1 for the daylight savings Time solarTime = new Time((hours-1), minutes, 0); System.out.println("Local Solar Time: " + solarTime); //hours return localSolarTime; } public static double azimuth(double lat, double declination, double zenith, double hourAngle) { double azimuthDegree = 0; double elevation = 90 - zenith; elevation = Math.toRadians(elevation); zenith = Math.toRadians(zenith); lat = Math.toRadians(lat); declination = Math.toRadians(declination); hourAngle = Math.round(hourAngle); hourAngle = Math.toRadians(hourAngle); //double azimuthRadian = -sin(hourAngle)*cos(declination) / cos(elevation); double azimuthRadian = ((sin(declination)*cos(lat)) - (cos(hourAngle)*cos(declination)* sin(lat)))/cos(elevation); //Account for time quadrants Calendar cal = Calendar.getInstance(); int hour = cal.get(Calendar.HOUR_OF_DAY); if(hour > 0 && hour = 6 && hour = 12 && hour = 18 && hour < 24) { azimuthDegree = Math.toDegrees(acos(azimuthRadian)); azimuthDegree = 360 - azimuthDegree; } System.out.println("Azimuth: " + df.format(azimuthDegree)); return azimuthDegree; } public static double zenith(double lat, double declination, double hourAngle) { lat = Math.toRadians(lat); declination = Math.toRadians(declination); hourAngle = Math.round(hourAngle); hourAngle = Math.toRadians(hourAngle); //Solar Zenith Angle double zenith = Math.toDegrees(acos(sin(lat)*sin(declination) + (cos(lat)*cos(declination)*cos(hourAngle)))); //Solar Elevation Angle double elevation = Math.toDegrees(asin(sin(lat)*sin(declination) + (cos(lat)*cos(declination)*cos(hourAngle)))); System.out.println("Elevation: " + df.format(elevation)); System.out.println("Zenith: " + df.format(zenith)); return zenith; } } 

重申一下,当天,当地时间子午线是完全正确的,时间和赤纬方程是准确的但不准确。 —-更新输出—- 新产出

传感器程序

—–更新—–使用散点图全天显示太阳的仰角/方位角。 我仍然无法确定方位角输出。 这是正确的很长一段时间,但它会从增加和开始变为减少(~270 – > 0)。 一旦我最终得到正确的输出,我一定会更新代码。

您将经度传递给localSolarTime()作为度数,然后将其除以60,并注释声称这是为了转换为弧分。 这是错的; 你以后的计算需要度数,即使你需要几分钟的弧度,你也要乘以60而不是除数。

这种误差导致经度为-1.3°,当您找到当地时间子午线与您的位置之间的角度时,您会得到一个大角度(约75°)。 它应该是一个小角度,通常为±7.5°。 大角度导致大的时间校正,并抛弃一切。


更新:azimuth()方法的更新版本中,象限选择应基于太阳的小时角,或等效地,基于当地太阳时,而不是标准挂钟时间。 并且,所有计算中使用的小时角度不应四舍五入。 该方法可能如下所示,而不是测试四个不同的象限:

 public static double azimuth(double lat, double declination, double zenith, double hourAngle) { double elevation = Math.toRadians(90 - zenith); lat = Math.toRadians(lat); declination = Math.toRadians(declination); hourAngle = Math.toRadians(hourAngle); double azimuthRadian = acos(((sin(declination) * cos(lat)) - (cos(hourAngle) * cos(declination) * sin(lat))) / cos(elevation)); double azimuthDegree = Math.toDegrees(azimuthRadian); if (hourAngle > 0) azimuthDegree = 360 - azimuthDegree; System.out.println("Azimuth: " + df.format(azimuthDegree)); return azimuthDegree; } 

最后,您将dcLong作为azimuth()方法的lat参数传递; 这应该是dcLat

我建议在内部使用弧度,并且只在输入和输出上转换和转换。 这有助于防止错误,并减少舍入错误和不必要的混乱。