Looks like projectgus's pull request on Github also solves the issue, just by calling on:
using std::abs;
...in the "Arduino.h" file and deleting the Arduino macro. This redefines abs() using the C++ standard library function.
MartinL:
Looks like projectgus's pull request on Github also solves the issue, just by calling on:
using std::abs;
...in the "Arduino.h" file and deleting the Arduino macro. This redefines abs() using the C++ standard library function.
yes, but my point was:
C++11 and C++14 also have std::abs just for ints and std::fabs and std::fabsf for floats !
Just C++17 has std::abs both for ints and fps...
but does Arduino actually use C++17 ...?
pert
May 5, 2019, 6:42pm
23
Arduino SAMD Boards is currently using C++11:
compiler.warning_flags.all=-Wall -Wextra
# EXPERIMENTAL feature: optimization flags
# - this is alpha and may be subject to change without notice
compiler.optimization_flags=-Os
compiler.optimization_flags.release=-Os
compiler.optimization_flags.debug=-Og -g3
compiler.path={runtime.tools.arm-none-eabi-gcc-7-2017q4.path}/bin/
compiler.c.cmd=arm-none-eabi-gcc
compiler.c.flags=-mcpu={build.mcu} -mthumb -c -g {compiler.optimization_flags} {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -MMD
compiler.c.elf.cmd=arm-none-eabi-g++
compiler.c.elf.flags={compiler.optimization_flags} -Wl,--gc-sections -save-temps
compiler.S.cmd=arm-none-eabi-gcc
compiler.S.flags=-mcpu={build.mcu} -mthumb -c -g -x assembler-with-cpp -MMD
compiler.cpp.cmd=arm-none-eabi-g++
compiler.cpp.flags=-mcpu={build.mcu} -mthumb -c -g {compiler.optimization_flags} {compiler.warning_flags} -std=gnu++11 -ffunction-sections -fdata-sections -fno-threadsafe-statics -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -MMD
compiler.ar.cmd=arm-none-eabi-ar
compiler.ar.flags=rcs
compiler.objcopy.cmd=arm-none-eabi-objcopy
compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0
The toolchain version currently in use doesn't even support C++17. However, there are plans to update the toolchain and use C++17 in the near future:
opened 11:05AM - 09 Mar 18 UTC
closed 09:31AM - 16 Jul 19 UTC
Component: Toolchain
The current toolchain (based on GCC 4.8) is significantly outdated, it lacks man… y C++14 features. C++14 is an important update to C++ because it expands on template metaprogramming, which is a very useful technique for embedded programming: it allows writing nicely looking, convenient code that does a lot of stuff at compile-time, with zero run-time overhead. Most notably, GCC 4.8 lacks extended `constexpr` and generic lambdas - the latter is exactly what I'm missing right now and can't compile my project without.
I tried [this release](https://launchpad.net/gcc-arm-embedded/4.9/4.9-2015-q3-update), just dropped it into the toolchain-gccarmnoneeabi folder, and it seems to work just fine!
There are much newer toolchain versions available, but that's not as important as getting full c++14 support. So I'm only asking for a minor upgrade from GCC 4.8 to 4.9, because 4.9 supports `-std=c++14`.
P. S. Even the AVR compiler is based on GCC 4.9.3 and supports c++14. Its standard library is lacking (nearly non-existent, even), but that's not such a big problem because there are c++11/14 stdlib implementations for Arduino AVR.
The ESP32 core for Arduino is also using C++11:
C++11 and C++14 also have std::abs just for ints and std::fabs and std::fabsf for floats !
Just C++17 has std::abs both for ints and fps...
but does Arduino actually use C++17 ...?
Yes, it's really confusing. I was also wondering why simply adding the "using std::abs;" line, allows the abs() function to work with floats, although the ESP32 is using C++11 (and not C++17).
After some investigation, I believe that the C++11's file which is included in "Arduino.h", undefines the "abs" macro and redefines it as an overloaded function "std::abs" for a number of data types including floats.
The "using std::abs;" line allows "abs" to be used in lieu of any predefined macros, so that it isn't necessary to call "std::abs" in your sketch, but simply use "abs" instead.
MartinL:
Yes, it's really confusing. I was also wondering why simply adding the "using std::abs;" line, allows the abs() function to work with floats, although the ESP32 is using C++11 (and not C++17).
After some investigation, I believe that the C++11's file which is included in "Arduino.h", undefines the "abs" macro and redefines it as an overloaded function "std::abs" for a number of data types including floats.
The "using std::abs;" line allows "abs" to be used in lieu of any predefined macros, so that it isn't necessary to call "std::abs" in your sketch, but simply use "abs" instead.
it appears as if gpp already features the std::abs() for fp since C14 or even 11, opposite to C++ standards only since 17
https://en.cppreference.com/w/cpp/numeric/math/fabs
opened 05:04PM - 01 May 19 UTC
closed 01:16PM - 16 May 19 UTC
Arduino IDE 1.8.8
different ESP32 MCUs (Adafruit Feather ESP32, ESP32 Dev Board… , WROOM32)
vs.
different ARM Cortex boards (Adafruit Feather M4, Arduino Zero (M0), Arduino Due (ATSAM3X8E)
Arduino AVR Mega2560
In the following code all ARM Cortex Boards and the Arduino Mega evalutate to 32.843750,
whilst all ESP32 evaluate to 54196.625
Ref.:
"HaWe" (ESP32, M3, M4, Mega2560): https://www.roboternetz.de/community/threads/73360-ESP32-berechnet-floats-falsch-im-Vergleich-zu-M4-und-Due-M3
"Ceos" (ESP32): https://www.roboternetz.de/community/threads/73360-ESP32-berechnet-floats-falsch-im-Vergleich-zu-M4-und-Due-M3?p=651789&viewfull=1#post651789
"BDL" (M4): https://forums.adafruit.com/viewtopic.php?f=57&t=151070&p=746220#p746147
"MartinL" (ESP32, M0): http://forum.arduino.cc/index.php?topic=613077.msg4157601#msg4157601
(to be continued...)
application source code (issue coincidentally detected):
the questionable value is the last one in either Serial output line (TBase.m)
changing float (fp32) to double (fp64) makes no difference basically.
```
// Lunar Lander
// preprocessor defaults for time sync:
//#define SYNC_REALTIME // real time sync; outcomment for time lapse
#if defined (SAM)
#include "avr/dtostrf.h" // sprintf() and dtostrf() for floats
#endif
//----------------------------------------------------
// flight control
//----------------------------------------------------
// public:
float mFuel=8200; // fuel mass in kg for landing
float hi=15300; // act height in m
float vHorz=1685; // Horizontal orbital speed m/s
float sTargm=470000; // horizontal way to target landing place
float burnPerc=0; // user input: burnrate %
float ftilt; // tilt horiz...vert -1...0...+1
float tiltDeg; // tilt degrees -90°...0...+90°
//----------------------------------------------------
// private:
float ti=0.0, dt=0.5; // act time, delta time in sec
const float g=1.62; // Moon gravity
const float MoonRad=3476000/2.0; // Moon radius
const float mLander=6500; // lander mass in kg with launch fuel
const float Isp=3050; // Rocket engine Specific Impulse
const float FBrake=45000; // Rocket engine max Propulsion Force
float burnMax=FBrake/Isp; // absolute max fuel burnrate
float mTotal=mLander+mFuel; // brutto weight with full tanks
float rBrake; // user Rocket brake force 100%, percentual
float dFuel=0; // delta fuel
float burnf=0; // burnrate factor 0.0 ... 1.0
float dh=0.0; // delta height in m
float scaleH=hi/100; // scaler for tft.hight=100%
float vVert=0.0; // Impact speed in m/s
float accVert=0; // vertical accel (sum)
float accBrake=0; // acc by break rockets
float fCentrifug=0; // centrifugal force by orbital speed
float accCentrif=0; // centrifugal accel by orbital speed
float sHorzm=0.0; // horizontal way flown in m
//----------------------------------------------------
// Serial LogBook
//----------------------------------------------------
void LogBook(){
char sbuf1[50], sbuf2[50] ;
char* headline1 = "t.sec hi.m vVert vHoriz ";
char* headline2 = "Burn tilt brake acc Fuel TBase.m";
Serial.print(headline1);
Serial.println(headline2);
sprintf(sbuf1, "%5.1f %5d %4d %4d ",
ti, (int)hi, (int)vVert, (int)vHorz);
sprintf(sbuf2, "%3d%% %4d %3.1f %4.1f %5d %f",
(int)burnPerc, (int)(ftilt*90), accBrake, accVert,
(int)mFuel, (float)(sTargm-sHorzm));
Serial.print(sbuf1); Serial.println(sbuf2);
Serial.println();
}
uint32_t dtime;
//----------------------------------------------------
// Lander Move
//----------------------------------------------------
void LanderMove() {
static float t0=ti;
dtime=millis();
if(hi>0) {
// Burn Ratio:
// 100 = 100% == full brake power
// 50 = 50% == half brake power
// 0 = 0% == zero brake power
// or anything in between
//
// 100% BURN RATIO (BRAKE POWER)
// => 45000kN propulsion force
// => 14,75 kg Fuel burn per second
// => brake accelation = 3m/s²
// XEROX Board Computer program, debug:
if( sHorzm<15600.0) burnPerc=0; // sHorzm<15600
else
if( vVert>60||vHorz>30 ) burnPerc=100; //
else
if(vVert>50) burnPerc=65;
else
if(vVert>40&&hi<3000) burnPerc=45;
else
if(vVert>35&&hi<1800) burnPerc=40;
else
if(vVert>10&&hi<1100) burnPerc=35;
else
if(vVert>=1&&hi<120) burnPerc=33;
else
burnPerc=0;
// calculate control
fCentrifug=vHorz*vHorz*mTotal/(MoonRad+hi);
accCentrif=fCentrifug/mTotal;
if(mFuel==0) burnPerc=0; // no fuel, no burn ;)
burnf = burnPerc/100.0; // factor 0...1
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
dFuel= burnMax*burnf*dt; // try burnrate: enough fuel?
dFuel = min(dFuel, mFuel); // calc available rest fuel
burnf = (dFuel/burnMax)/dt; // re-calc burnrate by rest fuel
burnPerc = burnf*100;
rBrake= FBrake*burnf; // rel brake force
accBrake= rBrake/mTotal; // rocket brake acceleration
mFuel = max(mFuel-dFuel, (float)0); // rest fuel >=0
mTotal= mLander+mFuel; // new total mass
if(vVert>=5 ) {
if(vVert>=40 && vHorz>2 ) ftilt=0.65; // 58.5°
else
if(vVert>=30 && vHorz>2 ) ftilt=0.75; // 67.5°
else
if(vVert>=20 && vHorz>2 ) ftilt=0.80; // 72.0°
else
if(vHorz<=2 && vHorz>=-2) ftilt=0.0;
else
if(vHorz<0) ftilt=0.0;
else ftilt=0.85; // 76.5°
}
else
if(vVert<5&&vHorz>20 ) ftilt=1;
else ftilt=0;
accVert = g - (1-abs(ftilt))*accBrake -accCentrif;
vVert = vVert + accVert*dt; // fractional vertical brake
if(vHorz>0)
vHorz = vHorz - (ftilt)*accBrake*dt; // fractional horizonal brake
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
sHorzm = sHorzm + vHorz*dt; // horizontal way flown
dh = 0.5*accVert*dt*dt + vVert*dt ; // delta height by res. grav+centrifug.+brake acc.
hi = hi-dh; // new resulting height
//-----------------------------------------------
// pause
#ifdef SYNC_REALTIME
while( millis()-dtime < dt*1000 );
#endif
//-----------------------------------------------
ti+=dt;
LogBook();
t0=ti;
//-----------------------------------------------
// Landing specs/ratings
if ( (( hi<=0 && vVert>=5 ) && vVert<8) ) // Damage
{
Serial.println();
Serial.println(" !! Damage !!");
}
else
if ( hi<=0 && vVert<5 && abs(sTargm-sHorzm)>100) { // very good Landing but way off
burnPerc=0;
Serial.println();
Serial.println("Very good but way off!");
}
else
if ( hi<=0 && vVert<5) { // Perfect Landing
burnPerc=0;
Serial.println();
Serial.println("Perfect Landing!");
}
else
if ( hi<=0 ) // B L A S T
{
Serial.println();
Serial.println(" !!! B L A S T !!!");
}
}
}
//----------------------------------------------------
// setup
//----------------------------------------------------
void setup() {
#if defined (SAM)
asm(".global _printf_float"); // sprintf() and dtostrf() for floats
#endif
Serial.begin(115200);
delay(2000);
Serial.println("Serial started!");
sHorzm=0; // way flown
Serial.println();
delay(dt*1000);
fCentrifug=vHorz*vHorz*mTotal/(MoonRad+hi);
accCentrif=fCentrifug/mTotal;
accVert=g-accBrake-accCentrif;
LogBook();
}
//----------------------------------------------------
// loop
//----------------------------------------------------
void loop(void) {
if (hi>0) {
LanderMove();
}
}
```
it appears as if gpp already features the std::abs() for fp since C14 or even 11, opposite to C++ standards only since 17
Compiler Explorer
std::abs(float), std::fabs, std::fabsf, std::fabsl - cppreference.com
float computations (fp32, fp64) evaluate differently vs. ARM Cortex M0+M3+M4 & Mega2560 (IDFGH-1084) · Issue #3405 · espressif/esp-idf · GitHub
Thanks for the links regarding the GCC and C++.
Yes, it appears to be a complex mix of Arduino, compiler and C/C++ standards. Thanks for flagging this up on Github. At least situation is now sorted, or a least will be once ESP32's "Arduino.h" is officially updated.