sdformat icon indicating copy to clipboard operation
sdformat copied to clipboard

Floats using D parse without warning but are broken

Open EmmanuelMess opened this issue 5 months ago • 8 comments

FORTRAN allows use of the character "D"/"d" instead of "E"/"e" in floats, it looks like the parser doesn't warn the user when this is done in sdf, but it doesn't seem to parse it correctly. This notation is used extensively in GPS files, and the incorrect input should be warned or should fail to parse.

EmmanuelMess avatar Jul 24 '25 01:07 EmmanuelMess

we are using std::stod and std::stof to parse floating point strings (see ValueFromStringImpl in Param.cc), and in my local testing, stod("1234.56d7") is parsed as 1234.56. It appears to just stop parsing when it hits the d character without throwing an exception

do you know any other libraries that support parsing Fortran floating point values? we are open to suggestions, but this is a bit tricky

scpeters avatar Sep 08 '25 22:09 scpeters

do you know any other libraries that support parsing Fortran floating point values?

No.

we are open to suggestions, but this is a bit tricky

My suggestion is that you outright fail for badly formatted input, and inform the library user. This might require a more strict version of std::stod / std::stof though.

EmmanuelMess avatar Sep 08 '25 23:09 EmmanuelMess

I think we can pass a std::size_t* pointer as the second argument of std::stod to determine how many characters were used as part of the conversion and report a warning / error if some characters were not included

can you share which datatypes are most susceptible to this issue, such as Scalars / Vector3 / Pose3?

scpeters avatar Sep 09 '25 00:09 scpeters

can you share which datatypes are most susceptible to this issue, such as Scalars / Vector3 / Pose3?

Ideally floats should all be handled the same. But I would say scalars and Vector3.

EmmanuelMess avatar Sep 09 '25 00:09 EmmanuelMess

can you share which datatypes are most susceptible to this issue, such as Scalars / Vector3 / Pose3?

Ideally floats should all be handled the same. But I would say scalars and Vector3.

👍

If you are able to attach an example file that exhibits this issue, we can use that in a test

scpeters avatar Sep 09 '25 00:09 scpeters

I am using a custom parsing routine in my plugin,that parses a custom tag:

            <gz:klobuchar>
              <gz:alphas>
                <gz:coeff0>0.6519e-8</gz:coeff0>
                <gz:coeff1>0.1490e-7</gz:coeff1>
                <gz:coeff2>-0.5960e-7</gz:coeff2>
                <gz:coeff3>-0.1192e-6</gz:coeff3>
              </gz:alphas>
              <gz:betas>
                <gz:coeff0>0.7782e5</gz:coeff0>
                <gz:coeff1>0.3277e5</gz:coeff1>
                <gz:coeff2>-0.6554e5</gz:coeff2>
                <gz:coeff3>-0.1966e6</gz:coeff3>
              </gz:betas>
            </gz:klobuchar>

Read like this:

  const auto alpha0 = alphasElement->FindElement(SDF_COEFF_0);
  const auto alpha1 = alphasElement->FindElement(SDF_COEFF_1);
  const auto alpha2 = alphasElement->FindElement(SDF_COEFF_2);
  const auto alpha3 = alphasElement->FindElement(SDF_COEFF_3);
  const auto beta0 = betasElement->FindElement(SDF_COEFF_0);
  const auto beta1 = betasElement->FindElement(SDF_COEFF_1);
  const auto beta2 = betasElement->FindElement(SDF_COEFF_2);
  const auto beta3 = betasElement->FindElement(SDF_COEFF_3);

  this->klobucharAlphas  = { alpha0->Get<double>(), alpha1->Get<double>(), alpha2->Get<double>(), alpha3->Get<double>()};
  this->klobucharBetas = { beta0->Get<double>(), beta1->Get<double>(), beta2->Get<double>(), beta3->Get<double>()};

I don't this file will be useful to you, because of the read code needed.

EmmanuelMess avatar Sep 09 '25 13:09 EmmanuelMess

so I assume some of the gz:coeff* elements are the ones where the d syntax may be used? We will be sure to add tests to cover this case

scpeters avatar Sep 09 '25 17:09 scpeters

so I assume some of the gz:coeff* elements are the ones where the d syntax may be used? We will be sure to add tests to cover this case

I would recommend you simply show/throw an error for the double parsing when it has "d", and not try to parse "d", as it might be more confusing to have only part of the FORTRAN parsing of floating point formats.

EmmanuelMess avatar Sep 09 '25 18:09 EmmanuelMess