Reputation: 132
[Context]
I am currently working on a probe balloon. My communication is restricted to messages of the 12 bytes in which I have to transmit several pieces of information. (Altitude, max temperature, longitude, latitude, average acceleration).
The probe is based on a raspberry pi 2 b.
[Question]
I am currently building my datagram and want to store my latitude and longitude as a 32-bit double (lossy). Storage can be done with floating point or fixed point
Are there tools to do this kind of conversion? How else can I do that? (in particular on the rounded party)
I initially planned to work in Java but I can migrate to python.
Thank you in advance
Upvotes: 3
Views: 360
Reputation: 533530
Instead of using a float
which is not really designed for a lat/long I suggest using a fraction. If you multiply by Integer.MAX_VALUE/90
for latitude and Integer.MAX_VALUE/180.0
for longitude you will get a value which uses a 32-bit value more efficiently.
float lat = 90f;
System.out.println("precision using float: " + (lat - Math.nextDown(lat)) + " degrees");
double ratio = Integer.MAX_VALUE / 90.0;
int val2 = (int) Math.round(90 * ratio);
System.out.println("precision using int: " + 1 / ratio + " degrees");
prints
precision using float: 7.6293945E-6 degrees
precision using int: 4.190951587721217E-8 degrees
in short, an int
can have more than 100x the precision as it has 32-bits of precision whereas a float
has a 23-bit mantissa.
For longitude, this error represents 1.7m for float and 0.94 cm using an int
this way.
NOTE: If a 2m error is ok (more accurate than a mobile phone GPS) you might decide that float
is simpler to work with.
Upvotes: 2
Reputation: 8695
If you want to translate a double
to 64-bits, you can use long Double.doubleToLongBits(double value)
, and double Double.longBitsToDouble(long bits)
to convert it back.
If you want to convert 32-bit values to Float
values and back, the corresponding functions are floatToIntBits(...)
and intBitsToFloat(...)
.
For double
to 32 bits, I'd use a 2-step conversion, converting to float
first:
double val = ...;
int bits = Float.floatToIntBits( (float) val );
And back:
int bits = ...;
double val = (double) Float.intBitsToFloat(bits);
Packing and unpacking directly to a buffer:
ByteArrayOutputStream baos = new ByteArrayOutputStream(20);
DataOutputStream dos = new DataOutputStream( ... );
dos.writeFloat( altitude );
dos.writeFloat( max_temperature );
dos.writeFloat( longitude );
dos.writeFloat( latitude );
dos.writeFloat( average_acceleration);
byte[] data = baos.toByteArray();
Of course, this creates a 20 byte buffer (5 x 32 bit floats), not a 12 byte buffer, so you'll need to figure out which values you want as 32 bits, and which you can cram into smaller space.
Unpacking, use a DataInputStream
and readFloat()
.
ByteArrayInputStream bais = ...
DataInputStream dis = new DataInputStream(bais);
altitude = dis.readFloat();
max_temperature = dis.readFloat();
...etc...
Upvotes: 1