Newbie C++ Syntax Question
Prophead100
Posts: 192
OK... ...I was porting over some c++ code and ran into a problem. Perhaps, I don't understand the syntax because this creates an error code --> "double u = atan(0.99664719 * tan(lat_rad));" and this does not --> "double u = atan(0.99664719 );" What am I missing? The complete method is below:
void sun_right_ascension_parallax_and_topocentric_dec(double latitude, double elevation,
double xi, double h, double delta, double *delta_alpha, double *delta_prime)
{
double delta_alpha_rad;
double lat_rad = deg2rad(latitude);
double xi_rad = deg2rad(xi);
double h_rad = deg2rad(h);
double delta_rad = deg2rad(delta);
double u = atan(0.99664719 * tan(lat_rad));
double y = 0.99664719 * sin(u) + elevation*sin(lat_rad)/6378140.0;
double x = cos(u) + elevation*cos(lat_rad)/6378140.0;
delta_alpha_rad = atan2( - x*sin(xi_rad) *sin(h_rad),
cos(delta_rad) - x*sin(xi_rad) *cos(h_rad));
*delta_prime = rad2deg(atan2((sin(delta_rad) - y*sin(xi_rad))*cos(delta_alpha_rad),
cos(delta_rad) - x*sin(xi_rad) *cos(h_rad)));
*delta_alpha = rad2deg(delta_alpha_rad);
void sun_right_ascension_parallax_and_topocentric_dec(double latitude, double elevation,
double xi, double h, double delta, double *delta_alpha, double *delta_prime)
{
double delta_alpha_rad;
double lat_rad = deg2rad(latitude);
double xi_rad = deg2rad(xi);
double h_rad = deg2rad(h);
double delta_rad = deg2rad(delta);
double u = atan(0.99664719 * tan(lat_rad));
double y = 0.99664719 * sin(u) + elevation*sin(lat_rad)/6378140.0;
double x = cos(u) + elevation*cos(lat_rad)/6378140.0;
delta_alpha_rad = atan2( - x*sin(xi_rad) *sin(h_rad),
cos(delta_rad) - x*sin(xi_rad) *cos(h_rad));
*delta_prime = rad2deg(atan2((sin(delta_rad) - y*sin(xi_rad))*cos(delta_alpha_rad),
cos(delta_rad) - x*sin(xi_rad) *cos(h_rad)));
*delta_alpha = rad2deg(delta_alpha_rad);
Comments
propeller-elf-c++ -o a.out -Os -mxmmc -I . -m32bit-doubles -fno-exceptions -fno-rtti spa_tester.c -lm
/tmp/cc3LdvPB.o: In function `
sun_right_ascension_parallax_and_topocentric_dec(double, double, double, double, double, double*, double*)':
(.text+0x190c): undefined reference to `_atan'
collect2: ld returned 1 exit status
Done. Build Failed!
Check source for bad function call or global variable name `_atan'
Do you have #include <math.h> at the top of that file.
Looks like the is no atan function in the maths library which I find a bit odd.
Your example of taking atan of a constant works because the compiler can calculate it at compile time and optimize away the function call.
The program has three files. Spa_test (topfile) includes the other two (Spa.c & Spa.h).
Spa_test has #include <stdio.h>
#include "spa.h" //include the SPA header file
#include "spa.c" //include the SPA header file
Spa.c has: #include <math.h>
Thinking big picture, the superb effort here getting C++ working on the prop (and I say C++ specifically and with all credit to C89 using Catalina which has been around for some time) is that this opens a vast library of code. Much of that code may have been written for PCs where memory is not such an issue, so we may have to be selective finding the *best* library, ie the one that does what you want, and doesn't have megabytes of unused code either. Not that megabytes are a big problem any more, but programs do take a long time to download.
For trig functions, float would probably be better than double. On the other hand... recently I have been using some Spin code that I think falls somewhere between float and double with a fixed decimal point at 4 decimal points, and numbers packed into 32 bits. Such a compromise fits well with the propeller as the prop is natively 32 bits. I don't know if such a library exists in C++?
The might be some interesting libraries in the Arduino world which is C++ based. I have never taken a serious look.
Have a google for "c++ fixed point class" or such.
Seems there are many.
If there is one that is smaller/faster than float that might be very usefull.
The nice thing about C++ here is that you can overload the operators to make use of your new type. So none of that writing function calls in your source to multiply etc.
Yes I'm on the steep part of the learning curve too.
Ok, google search finds this http://www.codeproject.com/Articles/37636/Fixed-Point-Class
Sign up, email confirm, download to a directory, search in the /include directory, grab the file fixed_point.h and copy it.
Where to put it?
Try C:\propgcc\lib\gcc\propeller-elf\4.6.1\include
Add this line to a hello world program
and try compiling
error message
try changing the filename "fixed_point.h" to something different eg "afixed_point.h" . Now a different error
so I think it is finding the file, but is not including it somehow.
In general terms, it would be useful to brainstorm how to include external libraries. Is this the correct directory to put #include files?
I'd try another.
I found another one, and that one said it had all the code, but it still had an include that wasn't in the package.
So maybe try a third?
Hmm - that is one really nice thing about spin, the way the spin tool creates "readme.txt" which has a treeview of every include, and every include in those includes. I'm still finding my way around .h libraries.
Perhaps that fixed point thing only uses assert.h.
If you were lucky there maybe a #define that disables the use of assertion checking.
Thanks,
--Steve
Its a high accuracy (+/- 0.0003 degree) solar tracking algorithm with recent formula reviews and C code from NREL (see attached). I did a similar lower accuracy (+/- 1 degree) Solar Object (on the OBEX) which was compact and plenty accurate for basic solar panels (+/- <1 degree) and heliostats but fit nicely within the SPIN memory model. This code used with the larger GCC memory model would allow the propeller to step up to controlling high ratio solar concentrators such as parabolic mirrors and Fresnel lenses where accuracy needs to be +/- 0.06 degrees.
This appears to be a library issue, but looking at the build I can't see how.
One consideration beyond the 32-bit double build error:
The constants are suggesting a precision that needs 64-bit double math.
Here's the contents of my .side file:
spa_tester.c
>compiler=C++
>memtype=xmmc
>optimize=-Os
>-fno-exceptions
>-fno-rtti
>-lm
>BOARD::C3F
Build Status:
Project Directory: C:/gccdev/propside/MyProjects/solar_spa/
propeller-elf-c++ -o a.out -Os -mxmmc -I . -fno-exceptions -fno-rtti spa_tester.c -lm
propeller-elf-objdump -h a.out
Done. Build Succeeded!
Until new binaries are available, you can use atanf directly in 32 bit builds. Or if you want the same code to be able to build in 32bit and 64 bit, add a define to the start of your files, like:
#include <stdio.h>
#include <propeller.h>
#include "spa.h" //include the SPA header file
#include "spa.c" //include the SPA header file
#include <math.h>
int main (int argc, char *argv[])
{
spa_data spa; //declare the SPA structure
int result;
float min, sec;
//enter required input values into SPA structure
spa.year = 2003;
spa.month = 10;
spa.day = 17;
spa.hour = 12;
spa.minute = 30;
spa.second = 30;
spa.timezone = -7.0;
spa.delta_t = 67;
spa.longitude = -105.1786;
spa.latitude = 39.742476;
spa.elevation = 1830.14;
spa.pressure = 820;
spa.temperature = 11;
spa.slope = 30;
spa.azm_rotation = -10;
spa.atmos_refract = 0.5667;
spa.function = SPA_ALL;
//call the SPA calculate function and pass the SPA structure
result = spa_calculate(&spa);
if (result == 0) //check for SPA errors
{
//display the results inside the SPA structure
printf("Julian Day: %.6f\n",spa.jd);
printf("L: %.6e degrees\n",spa.l);
printf("B: %.6e degrees\n",spa.b);
printf("R: %.6f AU\n",spa.r);
printf("H: %.6f degrees\n",spa.h);
printf("Delta Psi: %.6e degrees\n",spa.del_psi);
printf("Delta Epsilon: %.6e degrees\n",spa.del_epsilon);
printf("Epsilon: %.6f degrees\n",spa.epsilon);
printf("Zenith: %.6f degrees\n",spa.zenith);
printf("Azimuth: %.6f degrees\n",spa.azimuth);
printf("Incidence: %.6f degrees\n",spa.incidence);
min = 60.0*(spa.sunrise - (int)(spa.sunrise));
sec = 60.0*(min - (int)min);
printf("Sunrise: %02d:%02d:%02d Local Time\n", (int)(spa.sunrise), (int)min, (int)sec);
min = 60.0*(spa.sunset - (int)(spa.sunset));
sec = 60.0*(min - (int)min);
printf("Sunset: %02d:%02d:%02d Local Time\n", (int)(spa.sunset), (int)min, (int)sec);
} else printf("SPA Error Code: %d\n", result);
return 0;
}
/////////////////////////////////////////////
// The output of this program should be:
//
//Julian Day: 2452930.312847
//L: 2.401826e+01 degrees
//B: -1.011219e-04 degrees
//R: 0.996542 AU
//H: 11.105902 degrees
//Delta Psi: -3.998404e-03 degrees
//Delta Epsilon: 1.666568e-03 degrees
//Epsilon: 23.440465 degrees
//Zenith: 50.111622 degrees
//Azimuth: 194.340241 degrees
//Incidence: 25.187000 degrees
//Sunrise: 06:12:43 Local Time
//Sunset: 17:20:19 Local Time
//
/////////////////////////////////////////////
(1) A board configuration issue -- can you run a simple "hello, world" program and see the output?
(2) Stack and/or memory overflow -- are you compiling in XMM or XMMC mode? If not, try one of those.
The program prints nothing. I tried printf before spa_calculate and still no output. The "Hello World" program worked fine though so maybe I'm having the stack and/or memory overflow. I was using XMMC on my PBOE (no memory card) so perhaps I can try the XMM or add a card for more memory.. Is there a print buffer I need to flush?
If you're using XMMC mode, and if the data section is getting close to 32K, then it's possible that the stack is overflowing and corrupting some library data. You can get a picture of where everything is in memory with the objdump utility (propeller-elf-objdump -h file.elf); I think SIDE has an option to get a memory map as well.
Can you post the map file here? On the project manager main C file right-click and choose Show Map File.
Thanks,
--Steve
SPAMap.doc
here behind the else
} else printf("SPA Error Code: %d\n", result);
return 0;
}
should look like
} else {
printf("SPA Error Code: %d\n", result);
return 0;
}
Enjoy!
Mike
I compiled the code under Cygwin, and it ran fine. I wonder if the problem under PropGCC has to do with how 64-bit values are handled. I recall there was a compiler bug when passing long long variables to printf. Maybe there's a similar issue with floating point. I realize that we're trying to use 32-bit double variables, but maybe there some part of the code that thinks it's 64 bits instead.
Dave
It did not compile under Debian on my PC:
Looks like the includes are messed up. Firstly I put #include "spa.h" at the top of spa.c where it should be.
Then I remove #include "spa.c" //include the SPA header from spa_tester.c where it should not be.
Now it compiles and runs fine:
Edit: Results look correct.