rust-mavlink
rust-mavlink copied to clipboard
PARAM_VALUE_DATA
How are the different types in MavParamType encoded in PARAM_VALUE_DATA?
Especially, how is a UINT64 put to the PARAM_VALUE_DATA.param_value
field, which is only f32?
Hi @wucke13, PARAM_VALUE
does not support uint64, only float32, you can check it here:
https://mavlink.io/en/messages/common.html#PARAM_VALUE
@patrickelectric Thank you for the fast response, though that does not answer my question fully. E.g., if I want to write 13 aka 0xd to a variable which is uint, not float, what do I write to said f32
? 13.0
?
Can you explain which parameter are you talking about ? Take in mind that you are right now talking about the mavlink specification and not the mavlink rust library, since the specification says that the parameter is a float 32 value.
I don't really see the point in speaking about one parameter in particular, but here you go. ARMING_CHECK seems to be a bitmask. How is this represented in rust-mavlink?
The information is encoded as a bitmask, but the true value of ARMING_CHECK is an int that is casted to float. And this is not how rust-mavlink deals with the value, that's how the mavlink protocol is defined. E.g: Barometer + Compass will result in 0b0000'0000'0000'0110, that's equal to 6 (int), that is casted to float as 6.0; As a side note, all parameters are casted to float, as I said, this is how the mavlink protocol works, think that any value will be in the backend an int number if the information is a bitmask, hexadecimal and etc.
Ok, thank you for the detailed explanation! Then only one question is left on my side: what meaning does param_type
have in this setting? Can it be arbitrarily, because the FC know what type a parameter is anyways?
it's only important for the GCS, the flight controller will probably ignore this field. Please close the issue if that answers your question.
Yes it does! Thank you!
@patrickelectric After carefully reading the mavlink specs section about the parameter protocol, I'm inclined to believe that this statement is wrong:
The information is encoded as a bitmask, but the true value of ARMING_CHECK is an int that is casted to float. And this is not how rust-mavlink deals with the value, that's how the mavlink protocol is defined.
What I understand from reading it is, that the correct way per mavlink spec would be to cast (in the sense of CPP's static_cast
, so rather convert than) an int to a float (e.g 13i16
-> 13.0f32
).
Doing this is indeed incompatible with the mavlink spec (even though Ardupilot does it like that). The correct way would be similar of what in CPP is referred to as a reinterprete_cast
(and maybe some zero padding, if the encoded types size is smaller than the 4 bytes of an f32
). Despite the mavlink spec's claim that the param_value
is of type f32
, it actually is a 4 byte payload, which might contain the bytewise repesentation of an u16
, an i32
or whatever else is mentioned in the MAV_PARAM_TYPE enum.
The current mavlink-rs API does not reflect this. And AFAIK in safe Rust it is not even possible to directly store some arbitrary bytes in the memory region which makes up a f32
. I think this should be fixed in the API, possibly using the rust enum + union approach, e.g. making MavParamType
's variants take one value of the respective type plus some From
& Into
magic for it, while getting rid of the raw param_value
field. As an alternative, param_value
could be of type [u8; 4]
, and we leave it up to the user to populate it with something like 13f32.to_ne_bytes()
and so on.
What I do not understand so far is how values with more than 4 bytes are to be represented in MAVLink.