Skip to content

Commit

Permalink
[NMEA2K]: Finished NMEA2000 message interface
Browse files Browse the repository at this point in the history
  • Loading branch information
ad3154 committed Jul 14, 2023
1 parent 8fd14ac commit 2b5e60c
Show file tree
Hide file tree
Showing 5 changed files with 668 additions and 61 deletions.
40 changes: 35 additions & 5 deletions isobus/include/isobus/isobus/nmea2000_message_definitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ namespace isobus

/// @brief This message is a way for a GNSS receiver to provide a current position without using fast packet based on
/// The content of the last position data combined from the GNSS Position Data message and any prior position delta messages.
/// This PGN provides latitude and longitude referenced to WGS84.
class PositionDeltaHighPrecisionRapidUpdate
{
public:
Expand Down Expand Up @@ -550,10 +551,15 @@ namespace isobus
/// @returns True if the value that was set differed from the stored value, otherwise false
bool set_longitude(std::int64_t longitudeToSet);

/// @brief Returns the geoidal separation @todo units?
/// @brief Returns the geoidal separation in units of 0.01 meters
/// @details This returns the difference between the earth ellipsoid and mean-sea-level (geoid) defined by the reference datum
/// @returns The geoidal separation
std::int32_t get_geoidal_separation() const;
/// @returns The geoidal separation in units of 0.01m
std::int32_t get_raw_geoidal_separation() const;

/// @brief Returns the geoidal separation in units of meters
/// @details This returns the difference between the earth ellipsoid and mean-sea-level (geoid) defined by the reference datum
/// @returns The geoidal separation in units of meters
float get_geoidal_separation() const;

/// @brief Sets the geoidal separation
/// @details This value is the difference between the earth ellipsoid and mean-sea-level (geoid) defined by the reference datum
Expand Down Expand Up @@ -643,6 +649,28 @@ namespace isobus
/// @returns True if the value that was set differed from the stored value, otherwise false
bool set_number_of_reference_stations(std::uint8_t stations);

/// @brief Returns the specified reference station's ID by index
/// @param[in] index The index of the reference station to get the ID of
/// @returns Reference station's ID by index
std::uint16_t get_reference_station_id(std::size_t index) const;

/// @brief Returns the specified reference station's DGNSS corrections age by index
/// @prarm[in] index The index of the reference station to get the DGNSS corrections age for
/// @returns Reference station's DGNSS corrections age by index
std::uint16_t get_reference_station_corrections_age(std::size_t index) const;

/// @brief Returns the specified reference station's system type by index
/// @param[in] index The index of the reference station to get the system type for
/// @returns The specified reference station's system type by index
TypeOfSystem get_reference_station_system_type(std::size_t index) const;

/// @brief Sets the data for the specified reference station by index
/// @param[in] index The index of the reference station to set
/// @param[in] ID The station ID to set
/// @param[in] type The type of reference station
/// @param[in] ageOfCorrections Age of the DGNSS corrections in units of 0.01 seconds
bool set_reference_station(std::size_t index, std::uint16_t ID, TypeOfSystem type, std::uint16_t ageOfCorrections);

/// @brief Returns the date associated with the current position.
/// @returns Number of days relative to UTC since Jan 1 1970 (0 is equal to Jan 1, 1970). Max value is 65532 days.
std::uint16_t get_position_date() const;
Expand All @@ -654,12 +682,12 @@ namespace isobus

/// @brief Returns the number of seconds since midnight
/// @returns Number of seconds since midnight (0 == midnight), range allows for up to two leap seconds per day
std::uint16_t get_position_time() const;
std::uint32_t get_position_time() const;

/// @brief Sets the number of seconds since midnight
/// @param[in] timeToSet Seconds since midnight (0 == midnight), range allows for up to two leap seconds per day
/// @returns True if the value that was set differed from the stored value, otherwise false
bool set_position_time(std::uint16_t timeToSet);
bool set_position_time(std::uint32_t timeToSet);

/// @brief Serializes the current state of this object into a buffer to be sent on the CAN bus
/// @param[in] buffer A buffer to serialize the message data into
Expand Down Expand Up @@ -715,6 +743,8 @@ namespace isobus

/// @brief A NMEA2000 message that describes datum (reference frame) information. PGN 129044 (0x1F814)
/// A common one might be the WGS84 datum or the NSRS, for example.
/// @details This provides local geodetic datum and datum offsets from a reference datum.
/// This PGN is used to define the datum to which a position location output by the same device in other PGNs is referenced.
class Datum
{
public:
Expand Down
8 changes: 4 additions & 4 deletions isobus/include/isobus/isobus/nmea2000_message_interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ namespace isobus
/// @brief Returns a GNSSPositionData object that you can use to
/// set the message's individual signal values, which will then be transmitted if the interface is configured to do so.
/// @returns GNSSPositionData used to set the individual signal values sent in the GNSS position data message
NMEA2000Messages::GNSSPositionData &gnss_position_data_transmit_message();
NMEA2000Messages::GNSSPositionData &get_gnss_position_data_transmit_message();

/// @brief Returns a PositionDeltaHighPrecisionRapidUpdate object that you can use to
/// set the message's individual signal values, which will then be transmitted if the interface is configured to do so.
/// @returns PositionDeltaHighPrecisionRapidUpdate used to set the individual signal values sent in the position delta message
NMEA2000Messages::PositionDeltaHighPrecisionRapidUpdate &position_delta_high_precision_rapid_update_transmit_message();
NMEA2000Messages::PositionDeltaHighPrecisionRapidUpdate &get_position_delta_high_precision_rapid_update_transmit_message();

/// @brief Returns a PositionRapidUpdate object that you can use to
/// set the message's individual signal values, which will then be transmitted if the interface is configured to do so.
Expand All @@ -78,12 +78,12 @@ namespace isobus
/// @brief Returns a RateOfTurn object that you can use to
/// set the message's individual signal values, which will then be transmitted if the interface is configured to do so.
/// @returns RateOfTurn used to set the individual signal values sent in the rate of turn message
NMEA2000Messages::RateOfTurn &rate_of_turn_transmit_message();
NMEA2000Messages::RateOfTurn &get_rate_of_turn_transmit_message();

/// @brief Returns a VesselHeading object that you can use to
/// set the message's individual signal values, which will then be transmitted if the interface is configured to do so.
/// @returns VesselHeading used to set the individual signal values sent in the vessel heading message
NMEA2000Messages::VesselHeading &vessel_heading_transmit_message();
NMEA2000Messages::VesselHeading &get_vessel_heading_transmit_message();

/// @brief Returns the number of unique senders of the COG & SOG message
/// @returns The number of unique COG & SOG message senders
Expand Down
110 changes: 91 additions & 19 deletions isobus/src/nmea2000_message_definitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ namespace isobus

float VesselHeading::get_heading() const
{
return (headingReading * 0.0001f);
return (headingReading * 10E-4f);
}

bool VesselHeading::set_heading(std::uint16_t heading)
Expand All @@ -67,7 +67,7 @@ namespace isobus

float VesselHeading::get_magnetic_deviation() const
{
return (magneticDeviation * 0.0001f);
return (magneticDeviation * 10E-4f);
}

bool VesselHeading::set_magnetic_deviation(std::uint16_t deviation)
Expand All @@ -84,7 +84,7 @@ namespace isobus

float VesselHeading::get_magnetic_variation() const
{
return (magneticVariation * 0.0001f);
return (magneticVariation * 10E-4f);
}

bool VesselHeading::set_magnetic_variation(std::int16_t variation)
Expand Down Expand Up @@ -377,7 +377,7 @@ namespace isobus

float CourseOverGroundSpeedOverGroundRapidUpdate::get_course_over_ground() const
{
return (0.0001f * courseOverGround);
return (10E-4f * courseOverGround);
}

bool CourseOverGroundSpeedOverGroundRapidUpdate::set_course_over_ground(std::uint16_t course)
Expand All @@ -394,7 +394,7 @@ namespace isobus

float CourseOverGroundSpeedOverGroundRapidUpdate::get_speed_over_ground() const
{
return (0.01f * speedOverGround);
return (10E-2f * speedOverGround);
}

bool CourseOverGroundSpeedOverGroundRapidUpdate::set_speed_over_ground(std::uint16_t speed)
Expand Down Expand Up @@ -495,7 +495,7 @@ namespace isobus

double PositionDeltaHighPrecisionRapidUpdate::get_latitude_delta() const
{
return (latitudeDelta * 10E-16);
return (latitudeDelta * 10E-7);
}

bool PositionDeltaHighPrecisionRapidUpdate::set_latitude_delta(std::int32_t delta)
Expand All @@ -512,7 +512,7 @@ namespace isobus

double PositionDeltaHighPrecisionRapidUpdate::get_longitude_delta() const
{
return (longitudeDelta * 10E-16);
return (longitudeDelta * 10E-7);
}

bool PositionDeltaHighPrecisionRapidUpdate::set_longitude_delta(std::int32_t delta)
Expand Down Expand Up @@ -541,7 +541,7 @@ namespace isobus

double PositionDeltaHighPrecisionRapidUpdate::get_time_delta() const
{
return (timeDelta * (5 * 10E-3));
return ((timeDelta * 5.0) / 1000.0);
}

bool PositionDeltaHighPrecisionRapidUpdate::set_time_delta(std::uint8_t delta)
Expand All @@ -556,13 +556,31 @@ namespace isobus
buffer.resize(CAN_DATA_LENGTH);

buffer.at(0) = sequenceID;
//! @todo Finish serializer
buffer.at(1) = timeDelta;
buffer.at(2) = static_cast<std::uint8_t>(latitudeDelta & 0xFF);
buffer.at(3) = static_cast<std::uint8_t>((latitudeDelta >> 8) & 0xFF);
buffer.at(4) = static_cast<std::uint8_t>((latitudeDelta >> 16) & 0xFF);
buffer.at(5) = static_cast<std::uint8_t>(longitudeDelta & 0xFF);
buffer.at(6) = static_cast<std::uint8_t>((longitudeDelta >> 8) & 0xFF);
buffer.at(7) = static_cast<std::uint8_t>((longitudeDelta >> 16) & 0xFF);
}

bool PositionDeltaHighPrecisionRapidUpdate::deserialize(const CANMessage &receivedMessage)
{
bool retVal = false;
//! @todo Finish deserializer

if (CAN_DATA_LENGTH == receivedMessage.get_data_length())
{
retVal = set_sequence_id(receivedMessage.get_uint8_at(0));
retVal |= set_time_delta(receivedMessage.get_uint8_at(1));
retVal |= set_latitude_delta(receivedMessage.get_uint24_at(2));
retVal |= set_longitude_delta(receivedMessage.get_uint24_at(5));
retVal |= set_timestamp(SystemTiming::get_timestamp_ms());
}
else
{
CANStackLogger::warn("[NMEA2K]: Cannot deserialize position delta high precision rapid update. DLC must be 8 bytes.");
}
return retVal;
}

Expand All @@ -588,7 +606,7 @@ namespace isobus

double GNSSPositionData::get_altitude() const
{
return (altitude * 10E-6);
return (altitude * 1E-6);
}

bool GNSSPositionData::set_altitude(std::int64_t altitudeToSet)
Expand All @@ -605,7 +623,7 @@ namespace isobus

double GNSSPositionData::get_latitude() const
{
return (latitude * 10E-16);
return (latitude * 1E-16);
}

bool GNSSPositionData::set_latitude(std::int64_t latitudeToSet)
Expand All @@ -622,7 +640,7 @@ namespace isobus

double GNSSPositionData::get_longitude() const
{
return (longitude * 10E-16);
return (longitude * 1E-16);
}

bool GNSSPositionData::set_longitude(std::int64_t longitudeToSet)
Expand All @@ -632,11 +650,16 @@ namespace isobus
return retVal;
}

std::int32_t GNSSPositionData::get_geoidal_separation() const
std::int32_t GNSSPositionData::get_raw_geoidal_separation() const
{
return geoidalSeparation;
}

float GNSSPositionData::get_geoidal_separation() const
{
return (geoidalSeparation * 0.01f);
}

bool GNSSPositionData::set_geoidal_separation(std::int32_t separation)
{
bool retVal = (geoidalSeparation != separation);
Expand Down Expand Up @@ -752,6 +775,53 @@ namespace isobus
return retVal;
}

std::uint16_t GNSSPositionData::get_reference_station_id(std::size_t index) const
{
std::uint16_t retVal = 0;

if (index < referenceStations.size())
{
retVal = referenceStations.at(index).stationID;
}
return retVal;
}

std::uint16_t GNSSPositionData::get_reference_station_corrections_age(std::size_t index) const
{
std::uint16_t retVal = 0;

if (index < referenceStations.size())
{
retVal = referenceStations.at(index).ageOfDGNSSCorrections;
}
return retVal;
}

GNSSPositionData::TypeOfSystem GNSSPositionData::get_reference_station_system_type(std::size_t index) const
{
TypeOfSystem retVal = TypeOfSystem::Null;

if (index < referenceStations.size())
{
retVal = referenceStations.at(index).stationType;
}
return retVal;
}

bool GNSSPositionData::set_reference_station(std::size_t index, std::uint16_t ID, TypeOfSystem type, std::uint16_t ageOfCorrections)
{
bool retVal = false;

if (index < referenceStations.size())
{
retVal |= referenceStations.at(index).ageOfDGNSSCorrections != ageOfCorrections;
retVal |= referenceStations.at(index).stationID != ID;
retVal |= referenceStations.at(index).stationType != type;
referenceStations.at(index) = ReferenceStationData(ID, type, ageOfCorrections);
}
return retVal;
}

std::uint16_t GNSSPositionData::get_position_date() const
{
return positionDate;
Expand All @@ -764,12 +834,12 @@ namespace isobus
return retVal;
}

std::uint16_t GNSSPositionData::get_position_time() const
std::uint32_t GNSSPositionData::get_position_time() const
{
return positionTime;
}

bool GNSSPositionData::set_position_time(std::uint16_t timeToSet)
bool GNSSPositionData::set_position_time(std::uint32_t timeToSet)
{
bool retVal = (positionTime != timeToSet);
positionTime = timeToSet;
Expand Down Expand Up @@ -860,9 +930,11 @@ namespace isobus

for (std::uint8_t i = 0; i < get_number_of_reference_stations(); i++)
{
if (receivedMessage.get_data_length() >= MINIMUM_LENGTH_BYTES + (i * 4))
if (receivedMessage.get_data_length() >= static_cast<std::uint32_t>(MINIMUM_LENGTH_BYTES + (i * 4)))
{
referenceStations.push_back(std::move(ReferenceStationData((receivedMessage.get_uint16_at(MINIMUM_LENGTH_BYTES + (i * 4)) >> 4), static_cast<TypeOfSystem>(receivedMessage.get_uint8_at(MINIMUM_LENGTH_BYTES + (i * 4)) & 0x0F), receivedMessage.get_uint16_at(2 + MINIMUM_LENGTH_BYTES + (i * 4)))));
referenceStations.at(i) = std::move(ReferenceStationData((receivedMessage.get_uint16_at(MINIMUM_LENGTH_BYTES + (i * 4)) >> 4),
static_cast<TypeOfSystem>(receivedMessage.get_uint8_at(MINIMUM_LENGTH_BYTES + (i * 4)) & 0x0F),
receivedMessage.get_uint16_at(2 + MINIMUM_LENGTH_BYTES + (i * 4))));
}
else
{
Expand Down Expand Up @@ -989,7 +1061,7 @@ namespace isobus

float Datum::get_delta_altitude() const
{
return (0.02f * deltaAltitude);
return (10E-2f * deltaAltitude);
}

bool Datum::set_delta_altitude(std::int32_t delta)
Expand Down
Loading

0 comments on commit 2b5e60c

Please sign in to comment.