Estimate diffuse and direct component from global irradiance - pvlib

I am looking to separate the diffuse and direct component of global irradiance and found the Erbs model to do this in pvlib (see pvlib.irradiance.erbs) however, I am getting very strange results. I would expect the Direct Normal Irradiance (DNI) to be lower than the Global Horizontal Irradiance (GHI); or am I missing something? Values of GHI are not above 800 W m^2 for these days.
EDIT: As per Cliff H advice, I have limited the solar zenith to less than 85 arc degrees; the results have improved however, there are large spikes in DNI values that do not appear very reasonable, e.g. start of 07-16.

DNI > GHI is common at low solar elevation. GHI decreases much faster than DNI as solar elevation decreases. For example, think of a clear day with the sun right near the horizon. DNI will large because it's measured on a plane normal to the sun vector, but GHI will be near zero.
The values of DNI that are much greater than 1000 W/m2 are likely at very high zenith, since the Erbs model basically divides by cos(zenith). In practice, I limit using decomposition models like Erbs to zenith<85 degrees, to avoid the non-physical results.

Related

pvlib : time convention issue with cumulated GHI

I have a question regarding time conventions in pvlib.
As far as I understand, all the computations are made using instantaneous timestep convention. Instant weather will produce instant electric power.
However, in the weather models like GFS, GHI parameter is cumulated over the last hour. This makes inconsitant the solar radiation and astronomical parameters (zenith, azimuth...).
For example, if I take a look at the ERBS function, used to compute DHI and DHI from GHI :
df_dni_dhi_kt = pvlib.irradiance.erbs(ghi, zenith, ghi.index)
Here, all parameters are hourly timeseries, but the because of the convention, the output may be inaccurate.
ghi : cumulated radiation over last hour
zenith : zenith angle at exact hour (instantaneous)
ghi.index : hourly DateTimeIndex
At the end of the power conversion process, a shift is observed between observations and model (please don't care about the amplitude difference, only time shift matters).
Any idea about using cumulated GHI as input of the library ?
When using hourly data there definitely is a dilemma in how to calculate the solar position. The most common method is to calculate the solar position for the middle of the time step. This is definitely an improvement to using either the start or end of the hour (as shown in your example). However, around sunset and sunrise this poses an issue, as the sun may be below the horizon at the middle of the hour. Thus some calculate the sun position for the middle where the period is defined as the part of the hour where the sun is above the horizon - but that adds complexity.
There's a good discussion on the topic here: https://pvlib-python.readthedocs.io/en/stable/gallery/irradiance-transposition/plot_interval_transposition_error.html

AprilTag Localization Expected Acuracy

I am using the University of Michigan AprilTag library for localizing objects and am seeking advice for meeting my localization accuracy goals. I am using a 0.4 MegaPixel camera, on tags that are roughly 7.5 cm wide from distances of 0.1-1.5 meters away. I have used MatLab to calibrate my camera intrinsics and distortion coefficients.
Desired Outcome
I would like to be able to localize tags to within 5 mm accuracy.
Observed Outcome
As I move the camera relative to the tag, the localization results vary. For every 100 cm I move away from the tag, I find drift in the projected location of the tag in the world of about 10cm.
What is a reasonable expectation for the accuracy of the my localization? What actions can I take to reduce the drift I am observing?
If the drift mainly appears in the Z component of the TVEC and the error increases more or less linearly it is a sure sign that the focal length (fx & fy in the camera matrix) of your calibration is off.
Try the following:
check your calibration board: Is the size of the grid correct? Make sure that your printer does not scale the original file
make sure that the calibration board is fixed on a sturdy, flat surface
calibrate again and check if the values of fx and fy have changed (entries (0,0) and (1,1) in the camera matrix).
use at least 50 pictures, vary the board's angle and remove all pictures showing motion blur before calibrating
also check your detection parameters: You can try to activate para.cornerRefinementMethod = cv2.aruco.CORNER_REFINE_APRILTAG to improve corner accuracy (if you are using c++, adjust the command accordingly).
(too long for a comment, so I have to post it as another answer:) This will depend on the pixel size of your sensor and the focal length of your lens (which will "scale" your actual pixel size to a "projected" pixel size). As the effective resolution changes with the distance, a safe estimate would be to use the 1.5 m effective pixel value. In terms of pixels I would not trust marker corner accuracies below 0.3 px as there seems to be an issue with subpixeling accuracy, when rotating the marker (see my open question: Understanding openCV aruco marker detection/pose estimation in detail: subpixel accuracy). Tilting the marker will also degrade the accuracy as the precision of the determined rotation (rvec of the pose) is usually only within a few degrees. If small angles (say e. g. tilted only by 2°) occur, the pose might not reflect that and thus the marker will appear smaller and the distance will thus be over-estimated. In a flat setup (provided you are not using a wide angle lens) you might be able to get the 5 mm accuracy with a sensor > 5 MPx. But taking into account tilt & rotation of the marker, I am not sure if it will suffice...

Ray Tracing: Only use single ray instead of both reflection & refraction rays

I am currently trying to understand the ray tracer developed by Kevin Beason (smallpt: http://www.kevinbeason.com/smallpt/) and if I understand the code correctly he randomly chooses to either reflect or refract the ray (if the surface is both reflective and refractive).
Line 71-73:
return obj.e + f.mult(depth>2 ? (erand48(Xi)<P ? // Russian roulette
radiance(reflRay,depth,Xi)*RP:radiance(Ray(x,tdir),depth,Xi)*TP) :
radiance(reflRay,depth,Xi)*Re+radiance(Ray(x,tdir),depth,Xi)*Tr);
Can anybody please explain the disadvantages of only casting a single ray instead of both of them? I had never heard of this technique and I am curious what the trade-off is, given that it results in a huge complexity reduction.
This is a monte-carlo ray tracer. Its advantages are that you don't spawn an exponentially increasing number of rays - which can occur in some simple geometries.. The down side is that you need to average over a large number of samples. Typically you sample until the expected deviation from the true value is "low enough". Working out how many samples is required requires some stats - or you just take a lot of samples.
Presumably he's relying on super-sampling pixels and trusting that the average colour will work out roughly correct, although not as accurate.
i.e. fire 4 rays through one pixel and on average 2 are reflected, 2 are refracted.
Combine them to get an approximation of one ray reflected and refracted.

D3DXVec3Unproject is inaccurate in C++

I have a problem in my 3D Direct X Map Application (aka Google Earth)
All coordinates are geocentric (XYZ) in meters.
The maps are drawn above earth ellipsoid.
Everything works nice, except one issue.
When I go to very close zoom (about 1 meter per pixel), the D3DXVec3Unproject function returns inaccurate results. I have an error of 10-30 meters and cannot make map panning.
A lot of investigations isolate problem as follows:
D3DXVECTOR3 vScreen, vBack;
D3DXVec3Project( &vScreen, &m_vecAt, &m_viewPort, &m_matProj, &m_matView, &m_matWorld );
D3DXVec3Unproject( &vBack, &vScreen, &m_viewPort, &m_matProj, &m_matView, &m_matWorld );
m_vecAt is a looking point.
D3DXVec3Project returns correct vScreen - exactly center of window (+/- 0.5 pixel) with vScreen.z = 0.99, but vBack differs from m_vecAt by tens meters.
Sign again, that everything else works, so I assume, that all matrices and other data are calculated correctly.
The only one reason, that I can think about, is a not enough calculation precision of single float point arithmetic.
Please help.
Thank you guys.
I solved the problem. The near plane of projection matrix was too close to camera.
Precision of float might be one reason but another issue you should investigate is the accuracy of the ellipsoid or geoid model you are using. Errors at the range of 10~40 meters is expected in most usual models. More precise models are available but they are significantly more complex. Wikipedia article has some good links to follow.
It can't be the geoid given that the example code is generic 3D projection code which doesn't know anything about it. It must be floating point inaccuracy. Is it particularly bad for points towards the back of screen space (ie z ~ 1)? Since you're projecting a frustum to a cube, the back of the projected volume covers more world space, so any inaccuracy is more pronounced.

How to exploit periodicity to reduce noise of a signal?

100 periods have been collected from a 3 dimensional periodic signal. The wavelength slightly varies. The noise of the wavelength follows Gaussian distribution with zero mean. A good estimate of the wavelength is known, that is not an issue here. The noise of the amplitude may not be Gaussian and may be contaminated with outliers.
How can I compute a single period that approximates 'best' all of the collected 100 periods?
Time-series, ARMA, ARIMA, Kalman Filter, autoregression and autocorrelation seem to be keywords here.
UPDATE 1: I have no idea how time-series models work. Are they prepared for varying wavelengths? Can they handle non-smooth true signals? If a time-series model is fitted, can I compute a 'best estimate' for a single period? How?
UPDATE 2: A related question is this. Speed is not an issue in my case. Processing is done off-line, after all periods have been collected.
Origin of the problem: I am measuring acceleration during human steps at 200 Hz. After that I am trying to double integrate the data to get the vertical displacement of the center of gravity. Of course the noise introduces a HUGE error when you integrate twice. I would like to exploit periodicity to reduce this noise. Here is a crude graph of the actual data (y: acceleration in g, x: time in second) of 6 steps corresponding to 3 periods (1 left and 1 right step is a period):
My interest is now purely theoretical, as http://jap.physiology.org/content/39/1/174.abstract gives a pretty good recipe what to do.
We have used wavelets for noise suppression with similar signal measured from cows during walking.
I'm don't think the noise is so much of a problem here and the biggest peaks represent actual changes in the acceleration during walking.
I suppose that the angle of the leg and thus accelerometer changes during your experiment and you need to account for that in order to calculate the distance i.e you need to know what is the orientation of the accelerometer in each time step. See e.g this technical note for one to account for angle.
If you need get accurate measures of the position the best solution would be to get an accelerometer with a magnetometer, which also measures orientation. Something like this should work: http://www.sparkfun.com/products/10321.
EDIT: I have looked into this a bit more in the last few days because a similar project is in my to do list as well... We have not used gyros in the past, but we are doing so in the next project.
The inaccuracy in the positioning doesn't come from the white noise, but from the inaccuracy and drift of the gyro. And the error then accumulates very quickly due to the double integration. Intersense has a product called Navshoe, that addresses this problem by zeroing the error after each step (see this paper). And this is a good introduction to inertial navigation.
Periodic signal without noise has the following property:
f(a) = f(a+k), where k is the wavelength.
Next bit of information that is needed is that your signal is composed of separate samples. Every bit of information you've collected are based on samples, which are values of f() function. From 100 samples, you can get the mean value:
1/n * sum(s_i), where i is in range [0..n-1] and n = 100.
This needs to be done for every dimension of your data. If you use 3d data, it will be applied 3 times. Result would be (x,y,z) points. You can find value of s_i from the periodic signal equation simply by doing
s_i(a).x = f(a+k*i).x
s_i(a).y = f(a+k*i).y
s_i(a).z = f(a+k*i).z
If the wavelength is not accurate, this will give you additional source of error or you'll need to adjust it to match the real wavelength of each period. Since
k*i = k+k+...+k
if the wavelength varies, you'll need to use
k_1+k_2+k_3+...+k_i
instead of k*i.
Unfortunately with errors in wavelength, there will be big problems keeping this k_1..k_i chain in sync with the actual data. You'd actually need to know how to regognize the starting position of each period from your actual data. Possibly need to mark them by hand.
Now, all the mean values you calculated would be functions like this:
m(a) :: R->(x,y,z)
Now this is a curve in 3d space. More complex error models will be left as an excersize for the reader.
If you have a copy of Curve Fitting Toolbox, localized regression might be a good choice.
Curve Fitting Toolbox supports both lowess and loess localized regression models for curve and curve fitting.
There is an option for robust localized regression
The following blog post shows how to use cross validation to estimate an optimzal spaning parameter for a localized regression model, as well as techniques to estimate confidence intervals using a bootstrap.
http://blogs.mathworks.com/loren/2011/01/13/data-driven-fitting/