Giter Site home page Giter Site logo

marnav's Introduction

marnav

Copyright (c) 2022 Mario Konrad ([email protected])


Abstract

This is a C++ library for MARitime NAVigation purposes.

It supports (partially):

  • NMEA-0183
  • AIS
  • SeaTalk (Raymarine device communication)
  • Basic geodesic functions, suitable for martime navigation.
  • Reading data from serial ports (NMEA, SeaTalk). This is a separate library, available only if required environment is present, typically a Linux system.

See chapter Features for a complete and detailed list.


Goals

There are already implementaions for reading and writing NMEA-0183 or AIS. The goal of this library is

  • to have an implementation in modern C++
  • easy to use API (std lib like, integrating well)
  • unit tested (high test coverage)
  • trivial integration into projects (liberal license, as few dependencies as possible)
  • (more or less) well documented
  • (more or less) complete, as far as information is freely available
  • having fun

Features

NMEA-0183

Supported sentences for NMEA-0183 (read and write):

  • AAM: Waypoint Arrival Alarm
  • ACK: Acknowledge Alarm
  • ALM: GPS Almanac Data
  • ALR: Set Alarm State
  • APB: Autopilot Sentence "B"
  • BEC: Bearing and Distance to Waypoint
  • BOD: Bearing - Waypoint to Waypoint
  • BWC: Bearing & Distance to Waypoint - Geat Circle
  • BWR: Bearing and Distance to Waypoint - Rhumb Line
  • BWW: Bearing - Waypoint to Waypoint
  • DBT: Depth Below Transducer
  • DPT: Depth of Water
  • DSC: Digital Selective Calling Information (experimental)
  • DSE: Extended DSC (experimental)
  • DTM: Datum Reference
  • FSI: Frequency Set Information
  • GBS: GPS Satellite Fault Detection
  • GGA: Global Positioning System Fix Data
  • GLC: Geographic Position, Loran-C
  • GLL: Geographic Position - Latitude/Longitude
  • GNS: Fix data
  • GRS: GPS Range Residuals
  • GSA: Geographic Position - Latitude/Longitude
  • GST: GPS Pseudorange Noise Statistics
  • GSV: Satellites in view
  • HDG: Heading - Deviation & Variation
  • HDT: Heading - True
  • HFB: Trawl Headrope to Footrope and Bottom
  • HSC: Heading Steering Command
  • ITS: Trawl Door Spread 2 Distance
  • LCD: Loran-C Signal Data
  • MOB: Man over Board
  • MSK: Control for a Beacon Receiver
  • MSS: Beacon Receiver Status
  • MTW: Mean Temperature of Water
  • MWD: Wind Direction and Speed
  • MWV: Wind Speed and Angle
  • OSD: Own Ship Data
  • RMA: Recommended Minimum Navigation Information
  • RMB: Recommended Minimum Navigation Information
  • RMC: Recommended Minimum Navigation Information
  • ROT: Rate Of Turn
  • RPM: Revolutions
  • RSA: Rudder Sensor Angle
  • RSD: RADAR System Data (experimental)
  • RTE: Routes
  • SFI: Scanning Frequency Information
  • STN: Multiple Data ID
  • TDS: Trawl Door Spread Distance
  • TEP: Transit Satellite Predicted Elevation
  • TFI: Trawl Filling Indicator
  • TLL: Target Latitude and Longitude
  • TPC: Trawl Position Cartesian Coordinates
  • TPR: Trawl Position Relative Vessel
  • TPT: Trawl Position True
  • TTM: Tracked Target Message
  • VBW: Dual Ground/Water Speed
  • VDM: AIS VHF Data-Link Message
  • VDO: AIS VHF Data-Link Own-Vessel Report
  • VDR: Set and Drift
  • VHW: Water speed and heading
  • VLW: Distance Traveled through Water
  • VPW: Speed - Measured Parallel to Wind
  • VTG: Track made good and Ground speed
  • WCV: Waypoint Closure Velocity
  • WNC: Distance - Waypoint to Waypoint
  • WPL: Waypoint Location
  • XDR: Transducer Measurement
  • XTE: Cross-Track Error, Measured
  • XTR: Cross Track Error - Dead Reckoning
  • ZDA: Time & Date - UTC, day, month, year and local time zone
  • ZDL: Time and Distance to Variable Point
  • ZFO: UTC & Time from origin Waypoint
  • ZPI - Arrival time at point of interest
  • ZTG: UTC & Time to Destination Waypoint

Obsolete (according to [NMEA Revealed]) but implemented:

  • APA: Autopilot Sentence "A"
  • DBK: Depth Below Keel
  • GTD: Geographic Location in Time Differences
  • HDM: Heading - Magnetic (obsolete as of 2009)
  • MTA: Air Temperature
  • R00: Waypoints in active route
  • VWE: Wind Track Efficiency
  • VWR: Relative Wind Speed and Angle.
  • WDC: Distance to Waypoint
  • WDR: Distance to Waypoint, Rumb line
  • ZFI: Elapsed time since point of interest
  • ZLZ: Time of Day
  • ZTA: UTC & Estimated arrival time at point of interest
  • ZTE: UTC & Estimated remaining time to event

Vendor Extensions:

  • PGRME: Garmin Estimated Error
  • PGRMM: Garmin Map Datum
  • PGRMZ: Garmin Altitude Information
  • STALK: SeaTalk Raw Format

Miscellaneous:

  • Tag Block Support (generic for all sentences)

AIS

Supported messages for AIS (decode and encode):

  • Type 01: Position Report Class A
  • Type 02: Position Report Class A (Assigned Schedule)
  • Type 03: Position Report Class A (Response to Interrogation)
  • Type 04: Base Station Report
  • Type 05: Static and Voyage Related Data
  • Type 06: Binary Addressed Message
  • Type 07: Binary Acknowledge
  • Type 08: Binary Broadcast Message
  • Type 09: Standard SAR Aircraft Position Report
  • Type 10: UTC/Date Inquiry
  • Type 11: UTC/Date Response
  • Type 12: Addressed Safety-Related Message
  • Type 13: Safety-Related Acknowledgement
  • Type 14: Safety-Related Broadcast Message
  • Type 17: DGNSS Broadcast Binary Message
  • Type 18: Standard Class B CS Position Report
  • Type 19: Extended Class B CS Position Report
  • Type 20: Data Link Management
  • Type 21: Aid-to-Navigation Report
  • Type 22: Channel Management
  • Type 23: Group Assignment Command
  • Type 24: Static Data Report (part A and B, norma and auxiliary vessel)

Supported payload of binary message 08:

  • 001/11: Meteorological and Hydrological Data (IMO236)
  • 200/10: Inland ship static and voyage related data (Inland AIS)

SeaTalk

Suported messages for SeaTalk (decode and encode):

  • Type 00: depth below transducer
  • Type 01: equipment id
  • Type 05: Engine RPM and PITCH
  • Type 10: apparent wind angle
  • Type 11: apparent wind speed
  • Type 20: speed through water
  • Type 21: trip mileage
  • Type 22: total mileage
  • Type 23: water temperature 1
  • Type 24: Display unit for Mileage and Speed
  • Type 25: total and trip log
  • Type 26: Speed through Water
  • Type 27: water temperature 2
  • Type 30: Set Lamp Intensity
  • Type 36: Cancel MOB condition
  • Type 38: Codelock data (experimental)
  • Type 50: LAT Postion
  • Type 51: LON Postion
  • Type 52: Speed over Ground
  • Type 53: Magnetic Course in Degrees
  • Type 54: GMT Time
  • Type 56: Date
  • Type 58: LAT/LON
  • Type 59: Set Count Down Timer (sent by ST60)
  • Type 65: Select Fathom display unit for depth display (see message 00)
  • Type 66: Wind Alarm
  • Type 6C: Second equipment-ID
  • Type 86: Keystroke
  • Type 87: Response Level
  • Type 89: Compass heading (sent by ST40 compass instrument)

IO

  • Reading data from serial ports (NMEA, SeaTalk). Available only if the environment supports the implementation, typically a Linux system.

Geodesic Functions

Basic geodesic functions, suitable for martime navigation.

  • Calculation of CPA (closest point of approach) and TCPA (time to closest point of approach)
  • Distance of two points on a sphere
  • Distance of two points on an ellipsoid using formula of Vincenty
  • Distance of two points on an ellipsoid using formula of Lambert

Examples

More examples here.

Parse NMEA Sentence

using namespace marnav;

auto sentence = nmea::make_sentence(
	"$GPRMC,201034,A,4702.4040,N,00818.3281,E,0.0,328.4,260807,0.6,E,A*17");
std::cout << sentence->tag() << "\n";
auto rmc = nmea::sentence_cast<nmea::rmc>(sentence);
std::cout << "latitude : " << nmea::to_string(rmc->get_latitude()) << "\n";
std::cout << "longitude: " << nmea::to_string(rmc->get_longitude()) << "\n";

Create a specific sentence directly:

using namespace marnav;

auto rmc = nmea::create_sentence<nmea::rmc>(
	"$GPRMC,201034,A,4702.4040,N,00818.3281,E,0.0,328.4,260807,0.6,E,A*17");
std::cout << "latitude : " << nmea::to_string(rmc.get_latitude()) << "\n";
std::cout << "longitude: " << nmea::to_string(rmc.get_longitude()) << "\n";

Write NMEA Sentence

nmea::mtw mtw;
mtw.set_temperature(units::celsius{22.5});
std::string data = nmea::to_string(mtw);

Parse AIS Message from NMEA data

using namespace marnav;

// received sentences
const std::vector<std::string> received_strings
	= {"!AIVDM,2,1,3,B,55P5TL01VIaAL@7WKO@mBplU@<PDhh000000001S;AJ::4A80?4i@E53,0*3E",
		"!AIVDM,2,2,3,B,1@0000000000000,2*55"};

// parse NMEA sentences
std::vector<std::unique_ptr<nmea::sentence>> sentences;
for (auto const & txt : received_strings) {
	auto sentence = nmea::make_sentence(txt);
	if (sentence->id() == nmea::sentence_id::VDM) {
		sentences.push_back(std::move(sentence));
	}
}

// parse and and process AIS messags
auto payload = nmea::collect_payload(sentences.begin(), sentences.end());
auto message = ais::make_message(payload);
if (message->type() == ais::message_id::static_and_voyage_related_data) {
	auto report = ais::message_cast<ais::message_05>(message);
	std::cout << "shipname: " << report->get_shipname() << "\n";
	std::cout << "callsign: " << report->get_callsign() << "\n";
}

Create NMEA sentences from AIS data

using namespace marnav;

// prepare AIS data
ais::message_01 pos_report;
pos_report.set_sog(units::knots{8.2});
// ... most data not shown here

// create payload
auto payload = ais::encode_message(pos_report);

// create NMEA sentences
for (uint32_t fragment = 0; fragment < payload.size(); ++fragment) {
	nmea::vdm vdm;
	vdm.set_n_fragments(payload.size());
	vdm.set_fragment(fragment + 1);
	vdm.set_radio_channel(nmea::ais_channel::B);
	vdm.set_payload(payload[fragment]);

	// collect, send or do something with the sentence...
	std::string s = nmea::to_string(vdm);
	std::cout << s << "\n";
}

or simply use nmea::make_vdms:

using namespace marnav;

// prepare AIS data
ais::message_01 pos_report;
pos_report.set_sog(units::knots{8.2});
// ... most data not shown here

// create payload
auto payload = ais::encode_message(pos_report);

// create NMEA sentences
auto sentences = nmea::make_vdms(payload);

// process sentences, somehow...
for (auto const & sentence : sentences) {
	std::cout << nmea::to_string(*sentence) << "\n";
}

Requirements

The primary target architecture is x86_64, Linux on ARM is supposed to work as well though. It is possible to run unit tests through qemu-arm or use binfmt_misc on Linux hosts.

This chapter describes the requirements in order to build the library. Tools and their versions are listed below, newer/older/other tools (i.e. compilers, etc.) may work, but not tested.

Compiler:

  • GCC 7
  • GCC 8
  • GCC 9
  • GCC 10
  • GCC 11
  • GCC 12
  • GCC 13
  • Clang 5
  • Clang 6
  • Clang 7
  • Clang 8
  • Clang 9
  • Clang 10
  • Clang 11
  • Clang 12
  • Clang 13
  • Clang 14
  • Clang 15
  • Clang 16
  • Clang 17
  • VC++ 14.34 (_MSC_VER=1934, Visual Studio 2022)

Tools needed to build the library:

  • cmake 3.19 or newer

Tools needed to develop the library:

  • git
  • clang-format 10

Tools needed to build the documentation:

  • doxygen
  • graphviz
  • LaTeX (there are formulas!)

Optional used for development:

  • lcov / genhtml, c++filt
  • cppcheck
  • clang-tools (analyzer)
  • perf

Optional (no core dependency):

  • Boost.ASIO (used only for some examples)
  • Qt 5 (used only for some examples)

Opeating system:

  • Linux
  • Windows 10

There are no other dependencies despite the standard library (C++17) to build this library.


Build

The following build types -DCMAKE_BUILD_TYPE=x are possible:

  • Debug
  • Release
  • Coverage

Build options:

  • ENABLE_STATIC : enables static build, if OFF, a shared library is being built. Default: ON
  • ENABLE_PROFILING : enables profiling for gprof
  • ENABLE_BENCHMARK : enables benchmarking (disables some optimization)
  • ENABLE_SANITIZER : enables address and undefined sanitizers

Components:

  • ENABLE_EXAMPLES: enables examples. Default: ON
  • ENABLE_TOOLS: enables tools. Default: ON
  • ENABLE_TESTS: enables unit tests, integration tests and benchmarks. Default: ON
  • ENABLE_TESTS_BENCHMARK: enables benchmark tests, enabled only if ENABLE_TESTS is also enabled. Default: ON

Library

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make

Documentation

mkdir build
cd build
cmake ..
make doc

Package

make package

or individual package types:

cpack -G TGZ
cpack -G DEB

Developpers Choice

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Coverage ..
make -j 8
make coverage doc cppcheck

Static Analysis with Clang

There is a script bin/static-analysis-clang for doing this, there is not yet an integration of clang-tidy in the cmake build.

Perform Benchmarks

Build in Release mode, perform individual benchmarks:

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j 8
test/benchmark_nmea_split

Using perf to do performance analysis:

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_BENCHMARK=ON ..
make -j 8
perf record -g test/benchmark_nmea_split
perf report -g 'graph,0.5,caller'

Formatting Test

There is a helper script bin/check-format which uses clang-format to check the formatting of all files in the directories containing code (src, test and examples). This script can be used manually:

bin/check-format

or used as git pre-commit hook:

cd .git/hooks
ln -s ../../bin/check-format pre-commit

which prevents a commit if there are files not complying with the formatting rules. Be aware of using the script as pre-commit hook, the checking can take several seconds.


Authors

Mario Konrad ([email protected]) with help from others.

Search the repository for a complete list:

git log --format=%an | sort -u

Links

A (non-complete) collection of resources from where information was gathered.


LICENSE

NOTE: The official NMEA 0183 Standard document is not available for free. It was not consulted at any point during the development of this library. All information was found from free sources on the internet. This library (especially the NMEA part) is not derivative work of this standard.

See also LICENSE

(BSD)

Copyright (c) 2022, Mario Konrad
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
   must display the following acknowledgement:
   This product includes software developed by Mario Konrad.
4. Neither the name of the software nor the names of its contributors
   may be used to endorse or promote products derived from this software
   without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

marnav's People

Contributors

cheungxiongwei avatar jesvinjoseph avatar mariokonrad avatar msis avatar nohal avatar snild avatar solosuper avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

marnav's Issues

return type of sog is utils::optional<units::velocity> not utils::optional<units::knots> in the rmc sentence

Hi,
First of all, Thank you for the good Library 👍

I have a small question.

The return type of sog in the rmc sentence is utils::optional<units::velocity>. I think this by default converts the data into meter per second because of the to_base convertion in the basic dimention. But the data type of the sog variable is utils::optional<units::knots>. How can I get the sog data in knots?

utils::optional<units::knots> sog_;

utils::optional<units::velocity> get_sog() const;

rte message formatting look wrong

void rte::append_data_to(std::string & s) const
{
append(s, to_string(n_messages_));
append(s, to_string(message_number_));
append(s, to_string(message_mode_));

if (n_messages_) {
	for (uint32_t i = 0; (i < n_messages_) && (i < max_waypoints); ++i) {
		append(s, waypoint_id_[i].value());
	}
}

}
look like n_messages_ may not affect on waypoint output cout, if i not miss something.
Also look like format has differences, look like field RouteId missing:
//route send from navico maris ecdis sensor monitor(NMEA mode)
"$IIRTE,1,1,c,2,001,002,003,004,005*0F" "$IIWPL,4102.038,N,02900.753,E,001*6B" "$IIWPL,4102.449,N,02901.939,E,002*69" "$IIWPL,4103.268,N,02902.623,E,003*6B" "$IIWPL,4103.268,N,02902.623,E,003*6B" "$IIWPL,4103.268,N,02902.619,E,004*65" "$IIWPL,4103.820,N,02902.875,E,005*66" "$IIWPL,4103.820,N,02902.875,E,005*66"

here after "C" exists additional filed for route id

Read AND write from Devices

I want to build up a multiplexing system, which writes AND receives messages from TCP (only write right now, but doesn't matter), NMEA-0183-Devices and one Seatalk-Bus.

I am able to receive seatalk messages (convert them to NMEA) and from NMEA-Devices.

The problem is, that i also want to WRITE to these buses. TCP is no problem.

But the examples (with default_nmea_reader or seatalk message_reader) only show message-receivers, but no writers. OR if there is a writer, it's is not a receiver.

Could you give an example how to do both?

a new tag (0.41.1 for instance) would be useful

Hi
I have got problem to compile marnav tag 0.14 with GCC14

And I have had to add a line
#include
inside some src files :

/include/marnav/ais/binary_data.hpp
/include/marnav/nmea/checksum.hpp
/include/marnav/nmea/date.hpp
/include/marnav/utils/mmsi_country.hpp

I was on the way to propose a patch for this but I have discovered that you already did this for them in your commit from 2023/05/04

Since lots of linux distribution are switching to GCC14 I think a new tag would be useful (simpler than having to clone the source from your last commit)

Hoping this will help
Thanks for your useful job

Philippe

bitset size is not extended properly

extend() method checks the capacity() of vector instead of size(). I have fixed this in my branch with commit 8115b4b but this branch also has Visual Studio 2017 changes so I can create clean pull request.

This issue is revealed by running the test-ais-sample which asserts on access beyond the size of the data vector in bitset from bitset(const_iterator first, const_iterator last) -> append() -> append_block() -> extend(). This bitset constructor already increases the capacity of the data vector and adds the data itself but for the remainder bits uses append() for some reason. Maybe this whole path should be refactored to just use the append()?

Invalid SNR GSV value.

Hi,

First of all thanks for providing nice library.

My GPS module feeds the lib with fallowing data:
"$GPGSV,3,1,09,09,74,265,,04,63,066,14,06,50,261,,03,32,123,31*7B"
As You can see SNR field is empty.

Because of uninitialized satellite_info (marnav/nmea/gsv.hpp) snr member has garbage value (252 in my case).

Please consider initialize satellite_info structure or change members type to optional.

Thanks.

Decimal conversion

Hi,

Thank you for this really good library. I am using it to cast NMEA frames in my developments.

But, I encountered some troubles when I used it with my locale french computer. During NMEA parsing (from string to numerical values), a call to the std::atod is made to convert string to double. But this function depends on current locale and causes troubles and throws exception :

terminate called after throwing an instance of 'std::runtime_error'
what(): invalid string to convert to double: [250.5]

I had to modify my current locale by "std::setlocale(LC_ALL, "C");" to avoid errors. Is it possible to integrate this modification in your code?

Thanks again for your work.

VRI

Safety Messages NMEA ammendement, MOB, SMV, SM1, SM2, SM3, SM4 NMEA Messages

Safety Messages NMEA ammendement

MOB, SMV, SM1, SM2, SM3, SM4

http://www.nmea.org/Assets/20130816%20nmea%200183%20safetynet%20amendment.pdf

Examples:



$CSSM3,123456,005213,798,0,3,14,00,2012,04,05,14,30,3400,N,076,W,300*hh
$CSSMB,008,001,0,123456,FROM:Maritime Rescue Coordination Centre xxx^0D^0ATO:*hh
$CSSMB,008,002,0,123456, ALL SHIPS IN xxxxxxx^0D^0ASAR SITREP NO: 02^0D^0AFIS*hh
$CSSMB,008,003,0,123456,HING BOAT 'xxx' WITH THREE PERSONS ON BOARD DEPARRTED*hh
$CSSMB,008,004,0,123456, FROM xxx ISLAND ON^0D^0Axxx AT NOONTIME AND SINCE TH*hh
$CSSMB,008,005,0,123456,EN NO INFORMATION ABOUT HER. PARTICULARS ...^0D^0ASHI*hh
$CSSMB,008,006,0,123456,PS SAILING IN VICINITY ARE KINDLY REQUESTED TO KEEP A*hh
$CSSMB,008,007,0,123456, SHARP LOOK OUT^0D^0AINFORMING MRCC^0D^0AREGARDS^0D*hh
$CSSMB,008,008,0,123456,^0A DUTY OFFICER*hh
/g:1-9-1234*hh/$CSSM3,123456,005213,798,0,3,14,00,2012,04,05,14,30,3400,N,076,W,300*hh
/g:2-9-1234*hh/$CSSMB,008,001,0,123456,FROM:Maritime Rescue Coordination Centre xxx^0D^0ATO:*hh
/g:3-9-1234*hh/$CSSMB,008,002,0,123456, ALL SHIPS IN xxxxxxx^0D^0ASAR SITREP NO: 02^0D^0AFIS*hh
/g:4-9-1234*hh/$CSSMB,008,003,0,123456,HING BOAT 'xxx' WITH THREE PERSONS ON BOARD DEPARRTED*hh
/g:5-9-1234*hh/$CSSMB,008,004,0,123456, FROM xxx ISLAND ON^0D^0Axxx AT NOONTIME AND SINCE TH*hh
/g:6-9-1234*hh/$CSSMB,008,005,0,123456,EN NO INFORMATION ABOUT HER. PARTICULARS ...^0D^0ASHI*hh
/g:7-9-1234*hh/$CSSMB,008,006,0,123456,PS SAILING IN VICINITY ARE KINDLY REQUESTED TO KEEP A*hh
/g:8-9-1234*hh/$CSSMB,008,007,0,123456, SHARP LOOK OUT^0D^0AINFORMING MRCC^0D^0AREGARDS^0D*hh
/g:9-9-1234*hh/$CSSMB,008,008,0,123456,^0A DUTY OFFICER*hh
/g:1-9-1234,c:1333636200*hh/$CSSM3,123456,005213,798,0,3,14,00,2012,04,05,14,30,3400,N,076,W,300*hh
/g:2-9-1234*hh/$CSSMB,008,001,0,123456,FROM:Maritime Rescue Coordination Centre xxx^0D^0ATO:*hh
/g:3-9-1234*hh/$CSSMB,008,002,0,123456, ALL SHIPS IN xxxxxxx^0D^0ASAR SITREP NO: 02^0D^0AFIS*hh
/g:4-9-1234*hh/$CSSMB,008,003,0,123456,HING BOAT 'xxx' WITH THREE PERSONS ON BOARD DEPARRTED*hh
/g:5-9-1234*hh/$CSSMB,008,004,0,123456, FROM xxx ISLAND ON^0D^0Axxx AT NOONTIME AND SINCE TH*hh
/g:6-9-1234*hh/$CSSMB,008,005,0,123456,EN NO INFORMATION ABOUT HER. PARTICULARS ...^0D^0ASHI*hh
/g:7-9-1234*hh/$CSSMB,008,006,0,123456,PS SAILING IN VICINITY ARE KINDLY REQUESTED TO KEEP A*hh
/g:8-9-1234*hh/$CSSMB,008,007,0,123456, SHARP LOOK OUT^0D^0AINFORMING MRCC^0D^0AREGARDS^0D*hh
/g:9-9-1234*hh/$CSSMB,008,008,0,123456,^0A DUTY OFFICER*hh 
/g:1-9-1234,s:egcterm1,n:213,c:1333636200*hh/$CSSM3,123456,005213,798,0,3,14,00,2012,04,05,14,30,3400,N,076,W,300*hh
/g:2-9-1234,n:214*hh/$CSSMB,008,001,0,123456,FROM:Maritime Rescue Coordination Centre xxx^0D^0ATO:*hh
/g:3-9-1234,n:215*hh/$CSSMB,008,002,0,123456, ALL SHIPS IN xxxxxxx^0D^0ASAR SITREP NO: 02^0D^0AFIS*hh
/g:4-9-1234,n:216*hh/$CSSMB,008,003,0,123456,HING BOAT 'xxx' WITH THREE PERSONS ON BOARD DEPARRTED*hh
/g:5-9-1234,n:217*hh/$CSSMB,008,004,0,123456, FROM xxx ISLAND ON^0D^0Axxx AT NOONTIME AND SINCE TH*hh
/g:6-9-1234,n:218*hh/$CSSMB,008,005,0,123456,EN NO INFORMATION ABOUT HER. PARTICULARS ...^0D^0ASHI*hh
/g:7-9-1234,n:219*hh/$CSSMB,008,006,0,123456,PS SAILING IN VICINITY ARE KINDLY REQUESTED TO KEEP A*hh
/g:8-9-1234,n:220*hh/$CSSMB,008,007,0,123456, SHARP LOOK OUT^0D^0AINFORMING MRCC^0D^0AREGARDS^0D*hh
/g:9-9-1234,n:221*hh/$CSSMB,008,008,0,123456,^0A DUTY OFFICER*hh


Missing support for NMEA NavTex messages (alerts)

Specs are here:

https://www.pentestpartners.com/security-blog/hacking-navtex-maritime-warning-messages/

Example:



Source messages look like this:

    $CRNRX,007,001,00,TD02,1,135600,27,06,2001,241,3,A,==========================*09
    $CRNRX,007,002,00,,,,,,,,,,========^0D^0AISSUED ON SATURDAY 06 JANUARY 2001.*29
    $CRNRX,007,003,00,,,,,,,,,,^0D^0AINSHORE WATERS FORECAST TO 12 MILES^0D^0AOFF*0D
    $CRNRX,007,004,00,,,,,,,,,,SHORE FROM 1700 UTC TO 0500 UTC.^0D^0A^0D^0ANORT*70
    $CRNRX,007,005,00,,,,,,,,,,H FORELAND TO SELSEY BILL.^0D^0A12 HOURS FOREC*16
    $CRNRX,007,006,00,,,,,,,,,,AST:^0D^0A^0ASHOWERY WINDS, STRONGEST IN NORTH.^0D*15
    $CRNRX,007,007,00,,,,,,,,,,^0A^0A*79

The syntax is as follows:

$CRNRX <number of lines in message>,<message identifier (B1B2B3B4)>,<line number>, <frequency>, <day of month>,<month>,<year>,<time in UTC>,<error rate> then a 2 byte XOR checksum

Preceded by ZCZC and terminated with NNNN

The Message Identifier is made up of

    B1: transmitter identity
    B2: subject indicator
    B3&B4: serial number of the subject indicator

Thanks

GSV: Invalid satellite status for empty fields

Hi,

Could You please check use case for from UT below. It is failing.
Probably because of falsely positive satellite_info structure.

TEST(MarnavNmeaTests, GsvGetSatEmptySats)
{
    auto sentence = marnav::nmea::make_sentence(
        "$GLGSV,3,3,10,83,11,003,,83,11,003,,,,,,,,,*64");
    auto gsvSentence = marnav::nmea::sentence_cast<marnav::nmea::gsv>(sentence);

    EXPECT_EQ(3u, gsvSentence->get_n_messages());
    EXPECT_EQ(3u, gsvSentence->get_message_number());
    EXPECT_EQ(10u, gsvSentence->get_n_satellites_in_view());

    {
        const auto sat = *gsvSentence->get_sat(0);
        EXPECT_EQ(83u, sat.prn);
        EXPECT_EQ(11u, sat.elevation);
        EXPECT_EQ(3u, sat.azimuth);
        EXPECT_FALSE(sat.snr);
    }
    {
        const auto sat = *gsvSentence->get_sat(1);
        EXPECT_EQ(83u, sat.prn);
        EXPECT_EQ(11u, sat.elevation);
        EXPECT_EQ(3u, sat.azimuth);
        EXPECT_FALSE(sat.snr);
    }
    {
        const auto sat = gsvSentence->get_sat(2);
        EXPECT_FALSE(sat.has_value());
    }
    {
        const auto sat = gsvSentence->get_sat(3);
        EXPECT_FALSE(sat.has_value());
    }
}

Checksum calculation without white space character

Hi,
I want to use the library with a standardized AIS equipment. When I use nmeatool to read data, checksum of some ALR packets is labeled with error as in the below
nmeaTool

However, when i checked the raw serial data , it comes with white spaces in the sentence after (AIS:).
CuteComAis

I figured out that the device calculates it with white spaces. What does the standard says about this character issue?

ignore_checksum does not work for all nmea sentences.

"$IIMWV,30,T,1.85,M,A"


std::unique_ptr<sentence> mwv::parse(
    const std::string & talker, const std::vector<std::string> & fields)
{
    if (fields.size() != 5) <== This will be 4 without checksum
        throw std::invalid_argument{"invalid number of fields in mwv::parse"};

AIS broadcast message text corruption

message text for this kind of message corrupting while encoding.
this code will result AIS SART ??????? string. decoding by over ais library do same result so reason in encoding part.
Compiler: Visual Studio 2015 x86

const char AisSartMessage[] = "AIS SART activated";
using namespace marnav;
ais::message_14 broadcast;
broadcast.set_mmsi(utils::mmsi(cs));
broadcast.set_repeat_indicator(IsRepeat);
broadcast.set_text(AisSartMessage);
auto payload = encode_message(broadcast);
{
auto message = ais::make_message(payload);
if (message->type() == ais::message_id::safety_related_broadcast_message) {
auto report = ais::message_castais::message_14(message);
auto messagetext = report->get_text();
assert(messagetext==AisSartMessage);
}
}

Errors during executable linking when using latest package

When building marnav from the latest released package (0.8.0), marnav will fail to link the various generated executables. I'm on Ubuntu 18.04, with GCC7.

The error received is:
c++: error: -E or -x required when input is from standard input

Having a poke through the CMakeLists file, I can easily spot the issue (at line 30 from the packaged version):

### version handling
if(NOT ("${CMAKE_BUILD_TYPE}" MATCHES "Release"))
	set(PROJECT_VERSION "${PROJECT_VERSION}-${GIT_COMMIT_HASH_SHORT}")
endif()
message(STATUS "Project Vesion: ${PROJECT_VERSION}")

The git commit hash is missing as I'm using the packaged sources. Without ${GIT_COMMIT_HASH_SHORT} being set, the version gets set to '0.8.0-' which leads GCC to incorrectly think that I'm going to provide additional input from the terminal due to the trailing dash.

I now realise that this will only be a problem when using a non-release build type but as CMake defaults to not filling in the build type, I'm sure that I'm not the only soul who would hit this rather minor issue.

Thanks for your time.

Install instructions for ctags

Hi,
Thanks for a great library.

What version of ctags are you using? Perhaps a comment about required version and a link to installation instructions could be provided?


Details

I'm trying to build the documentation using make doc on Ubuntu 18.04. The first error is

CMake Error at cmake/Documentation.cmake:20 (add_dependencies):
  The dependency target "tags" of target "doc" does not exist.

I find that the tags target is created by CTags.cmake, and the file indicates that i might be missing ctags and/or cscope

find_program(CTAGS_PATH ctags)
find_program(CSCOPE_PATH cscope)

if(CTAGS_PATH AND CSCOPE_PATH)
	message(STATUS "Found ctags: ${CTAGS_PATH}")
	message(STATUS "Found cscope: ${CSCOPE_PATH}")

, so I tried installing it.

sudo apt install ctags cscope

This gives me "Exuberant Ctags 5.9", but make tags (or make doc) outputs the error

ctags: Unknown option: --extras

Including doxygen and the proper ctags and cscope in your docker images could be a sufficient solution for me personally, as I'm only looking for a way to generate the documentation.

Missing `std::move` in `utils::optional`

Hi,
Fetching the value from a temporary utils::optional::value raises a compiler error:

// message is a const std::unique_ptr<marnav::ais::message_01>&
double rot = message->get_rot().value();
(...)/optional.hpp:106:27: error: cannot bind rvalue reference of type ‘double&&’ to lvalue of type ‘double’
  T && value() && { return data_; }

Inserting a std::move solves the problem:

T && value() && { return std::move(data_); }

SignalK and sensors support on raspberry Pi ideas

There are few other related C++ projects.

https://github.com/raffmont/signalk-server-cpp

https://github.com/epsilonrt/piduino

https://github.com/SignalK/SensESP

Just as an idea.
I think using those (at least first two) it would be possible to create marine multiplexer server for pi which would support many types of sensors (in similar fashion to SenseEsp)
but connected directly to Pi instead of ESP32.

Unfortunately https://github.com/raffmont/signalk-server-cpp
is not actively maintained but it could be a core of such server (it is based on marnav)

Thanks

NEW MOB Sentence..

You're probably aware but I just wanted to make sure, I didn't see it in the source code:
NMEA has added a new sentence to the 4.10 spec for Man overboard.
$--MOB, blah, blah,blah,,,,,,0*2F

I know the whole legality of 'Reverse Engineering' a proprietary spec is tight rope to walk, derivative work, , but the technical bulletin I found from NMEA on the Man overboard sentence specifically states it's a public document if you want to research it.
"I specifically did not put a link to the document here to maintain your legal cleanliness"
It's easy enough to find...

Hope this helps, I only bring it up for completeness...

Cheers,
TR. Martin

Problem with fmt version

Hello
I'm packaging some marine programs for a Linux distribution (OpenCPN and its plugins)
For this we use our system libraries
I intended to package opencpn-nsk-plugin which uses marnav... as a BuildRequire
So I need to build and package marnav
And then problems appear :

  • if I build and package marnav as it is in your source, I get conflict since our fmt version is different from yours
  • if I try to build marnav upon a more recent fmt version it's not possible since two required headers don't exist anymore in recent fmt version : no more posix.h nor locale.h in fmt include (they still exist in your extern/fmt/include/fmt folder) (version6)

Would it be not to much difficult for you to use a more recent version of fmt ? for compatibility with recent linux distributions

Thanks for this
Philippe (filochard)

Problem with negative latitude or longitude to generate AIS message 1

Hello,

I use this marnav library to parse and to create nmea sentence. on my project.

Today, I observed a problem to generate an AIS message 1 sentence.
I have no problem to generate AIS sentence if the latitude and longitude are positive (respectively North and East) but if I try to set a West longitude, the sentence are create without longitude value... It is similar to generate a South latitude.

I check different version to set negative value but none works :

ais::message_01 pos_report;

pos_report.set_lon(geo::longitude{3.3118});  // work correctly
pos_report.set_lon(geo::longitude{-3.3118}); // ko
pos_report.set_lon(geo::longitude{3.3118, geo::longitude::hemisphere::west});  // ko
pos_report.set_lon(geo::longitude{-3.3118, geo::longitude::hemisphere::west}); // ko
pos_report.set_lon(geo::longitude{3,31,18, geo::longitude::hemisphere::west});  // ko

If someone has a solution, I'm interested :)

Thanks,
Ronan.

Error linking Linking CXX executable read_nmea_boostasio

-- Build files have been written to: /home/user/signalk-server-cpp/build/marnav-prefix/src/marnav-build
[ 57%] Performing build step for 'marnav'
[  2%] Built target extern_benchmark
[  4%] Built target extern_gmock
[  4%] Built target nmeasum
[ 47%] Built target marnav
[ 48%] Built target nmeadump
[ 49%] Built target create_nmea_from_ais_2
[ 49%] Built target create_nmea_from_ais
[ 50%] Built target read_ais
[ 51%] Linking CXX executable read_nmea_boostasio
/usr/bin/ld: CMakeFiles/read_nmea_boostasio.dir/read_nmea_boostasio.cpp.o: undefined reference to symbol 'pthread_getspecific@@GLIBC_2.4'
/usr/bin/ld: //lib/arm-linux-gnueabihf/libpthread.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make[5]: *** [examples/CMakeFiles/read_nmea_boostasio.dir/build.make:86: examples/read_nmea_boostasio] Error 1
make[4]: *** [CMakeFiles/Makefile2:449: examples/CMakeFiles/read_nmea_boostasio.dir/all] Error 2
make[3]: *** [Makefile:163: all] Error 2
make[2]: *** [CMakeFiles/marnav.dir/build.make:112: marnav-prefix/src/marnav-stamp/marnav-build] Error 2
make[1]: *** [CMakeFiles/Makefile2:261: CMakeFiles/marnav.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

Early stage library call make wrong data for Visual Studio 2015

On early stage of application running global variables created and call this code, but static dictionary for 6-bit encoding still not ready, so code gives corrupted data without any error. This minor level bug, but can affect on some situations. Maybe exception on try to encode on not ready dictionary needed.
class test
{
public:
test(){
using namespace marnav;
ais::message_14 broadcast;
broadcast.set_mmsi(utils::mmsi(cs));
broadcast.set_repeat_indicator(IsRepeat);
broadcast.set_text(AisSartMessage);
auto payload = encode_message(broadcast); //this data broken
}
}
test globalvariable;

actual,expected checksum wrongly displaying

In ensure_checksum() of nmea.cpp we are calculating checksum and considering it as actual checksum. we are providing wrong information here, calculated checksum must be the expected checksum and actual checksum is the one we received from the message. in case if we pass a wrong checksum(34) and actual checksum is (44) we will be getting below message

checksum error: (actual:44, expected:34)

but it must be printed as

checksum error:(actual: 34, expected:44)

Compiling on OSX

I'm trying to compile marnav under macOS High Sierra 13.10.6 with AppleClang version 9.1:
Apple LLVM version 9.1.0 (clang-902.0.39.2)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
Just adding the following lines in CMakeLists.txt :
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
message(STATUS "Compiler: AppleClang")

In ### compiler check solves the issue.
Unfortunately I had the following compiler error:

mmbp:build raffaelemontella$ make
[ 2%] Built target extern_gmock
[ 4%] Built target extern_benchmark
[ 4%] Building CXX object src/CMakeFiles/marnav.dir/marnav/nmea/name.cpp.o
/Users/raffaelemontella/dev/marnav/src/marnav/nmea/name.cpp:265:67: error: constexpr variable 'talkers' must be initialized by a constant
expression

static constexpr const std::array<entry, talker_id::num_talkers> talkers = {{
^ ~~
/Users/raffaelemontella/dev/marnav/src/marnav/nmea/name.cpp:266:3: note: non-constexpr constructor 'pair<true, false>' cannot be used in a
constant expression

{talker_id::none, "used for vendor extensions"},
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/utility:422:5: note: declared here
pair(_T1 const& __t1, _T2 const& __t2)
^
1 error generated.
make[2]: *** [src/CMakeFiles/marnav.dir/marnav/nmea/name.cpp.o] Error 1
make[1]: *** [src/CMakeFiles/marnav.dir/all] Error 2
make: *** [all] Error 2

Any suggestion?

Missing support for DSC NMEA alerts and messages

64 bit mmsi

hello and thanks for your neat works.
you've supposed that mmsi is 32 bit but there are 64 bit mmsi also.
I've tried to correct it, in utils::mmsi you've declared a type with name value_type, I changed it to u_int64 but in ais message classes (message_1,2,...) you've defined bitset<..., u_int32> mmsi, so conversion is cumbersome.

distance_ellipsoid_vincenty limitations

This function (marnav/src/geo/geodesic line84) only returns azimuths from -pi/2 to pi/2 rad because of atan function used instead of atan2.
It also returns a 0 distance for points on the same longitude (angles 0 and pi).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.