Closed pyalot closed 7 years ago
You're right, it's computationally expensive. Not so much to calculate sun exposure, dot products are cheap, but to calculate occlusion from parts and nearby terrain is more expensive, particularly in a Unity-based game with very expensive raycasting. So the panels only use 3-6 points depending on radius size. It seems like a pretty good compromise, particularly given plot 2, which shows about a 10% deviation at most. I'm happy enough with this. With 4 raycast points, a full circle of panels is already 16 raycasts per tick (a tick is longer in this case), which is already at least 4x as expensive as a stock solar panel.
Yes, I could model it analytically using calc, but this is actually more versatile. Since the occlusion points are specified on the model, it's easy to use it for panels that are different in geometry to arcs. The module can theoretically do any shape of panel this way.
I see your point about casting and occlusion cost, still there's something odd going on. Even if you just use 6 points, the curve should still match more closely (after all the 4-facet model still resembles the ideal curve much more closely).
I also see the point about flexibility and an analytic solution. But it'd still be possible to plug an analytic approximation for panels segments and make up your panels of multiples of those (like say 18° segments).
Where are you placing the facet points in your plots? That could affect things, as I've placed the source transforms manually and probably aren't perfectly distributed.
The revised code places half a facet at the extremes and a full facet inbetween each evenly distributed, see the second code snippet.
Yeah that's different than my distribution, which places each facet so that each point represents a full face with no halves. That might be the reason there is a difference. (for 90 degrees of arc, one is at 15, 45 and 75)
Even so, there's still something odd. Revised the code a bit again and test both facet placement methods:
def roundPanelExposure(exposureAngle, arcCoverage, facetCount):
count = 0.0
amount = 0.0
for facetNum in range(0,facetCount):
if facetNum == 0 or facetNum == facetCount-1:
weight = 0.5
else:
weight = 1.0
facetNum = float(facetNum)
facetScalar = facetNum/(facetCount-1)
facetAngle = arcCoverage*facetScalar-arcCoverage*0.5
angle = exposureAngle + facetAngle
amount += flatPanelExposure(angle)*weight
count += weight
return amount/count
def roundPanelExposureAllFull(exposureAngle, arcCoverage, facetCount):
count = 0.0
amount = 0.0
endsOffset = (arcCoverage/facetCount)*0.5
arc = arcCoverage-endsOffset*2.0
for facetNum in range(0,facetCount):
facetNum = float(facetNum)
facetScalar = facetNum/(facetCount-1)
facetAngle = endsOffset + facetScalar*arc - arcCoverage*0.5
angle = exposureAngle + facetAngle
amount += flatPanelExposure(angle)
count += 1.0
return amount/count
Comparing 4-facets, it's not terribly good, but still much closer than the observed result.
6-facets is really close:
I'm pretty confident in saying this is just due to lazy "facet" transform placement by me. Regardless, it's nowhere near serious enough to invest the time to fix it now. I will leave the issue open though to remind me to take a look when I next open up those source files though.
Will be reviewing the positions of the transforms for 0.5.6
Be sure to use a test-rig as illustrated using Infernal Robotics to review your results. By setting appropriate pre-sets for the rotation and picking the time of day just right you can get quite good readings (fiddling by hand to move to the angles tends to be a lot less accurate).
Just so you know, I don't really intend to do a perfect analysis or simulation. I merely aim to look at the positions of the sun transforms and back-of-the-envelope determine if that's what is causing a discrepancy (it will be obvious) and adjust the positions a bit if it's egregiously bad.
Sure, but proper methodology for addressing an issue is to 1) measure 2) fix. You'll want to exclude as much uncertainty as reasonably possible from measuring so you can see if you've made progress in your fix. Otherwise fuzz/noise is going to overshadow your results and you wasted your time fixing something because you didn't have an appropriate means to measure if you've made progress.
Using Infernal Robotics, setting 10 presets for a rotatron, making a 4-part test rig, adjusting your time of day appropriately and noting down 10 data points in a spreadsheet is by my estimation quite a reasonable effort as it'll take you about 10 minutes to do, compared to many more minutes spent fiddling with the asset...
Also keep in mind that I've provided you with code/data to compare your fix against, so you don't need to invent the wheel in terms of reference data either.
I was testing the sun exposure/incident angle of round panels and came upon something strange (it's possible to following observation is limited by KSP and it's not your fault, nevertheless it's good to record).
The test setup I used to take these measurements:
The measurements for a round panel (NV-3) and a flat panel (PX-Stat 1x2), the other columns are estimates for flat panel (Cos(A)) and estimates for round panels. Here is the raw data:
The theoretical estimates for round panels where created using this python program that divides round panels up into 100 facets and computes their sum exposure:
Plotting for a flat panel we see that the flat panel matches estimated performance quite closely:
Judging the NV-3 panel from the looks/curvature it seems to be designed to cover a 90° arc. However I observed that visually (when rotated) it seems to be more like 80°, and from observation it already cuts out energy flow for a coverage that'd correspond to 40°.
Comparing the round panel to cos(a) and for the 90° estimate, we can see that it matches neither (it should really match the 90° estimate).
Comparing the round panel to 90°, 80° and 40° we can see that its actual performance is more closely aligned with the 40° estimate (maybe a bit above that, like 45°).
It might be a bit expensive to estimate a round panel using a hundred facets, so I tested which facet count still provides a fairly good estimate (the program is slightly modified for that to account correctly for the half facets at the start and end and have a parameter for facet count, here's the updated estimation function):
And here is the result:
Down to 8 facets things look fairly good, but at 4 facets it gets kinda bad.
It'd also be possible to approximate with a trigonometric function, use calculus (I'm very bad at calculus), or use curve fitting (cool online tool for that http://mycurvefit.com/) of a polynominal (quadric or quintic or some spline/smoothstep). Although it's doubtful the maths to evaluate those curve fits are any much cheaper than taking 8 facets for sampling.