Copyright (c) 2022 Mario Konrad (mario.konrad@gmx.net)
This is a C++ library for MARitime NAVigation purposes.
It supports (partially):
See chapter Features for a complete and detailed list.
There are already implementaions for reading and writing NMEA-0183 or AIS. The goal of this library is
Supported sentences for NMEA-0183 (read and write):
Obsolete (according to [NMEA Revealed]) but implemented:
Vendor Extensions:
Miscellaneous:
Supported messages for AIS (decode and encode):
Supported payload of binary message 08:
Suported messages for SeaTalk (decode and encode):
Basic geodesic functions, suitable for martime navigation.
More examples here.
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";
nmea::mtw mtw;
mtw.set_temperature(units::celsius{22.5});
std::string data = nmea::to_string(mtw);
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";
}
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";
}
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:
Tools needed to build the library:
Tools needed to develop the library:
Tools needed to build the documentation:
Optional used for development:
Optional (no core dependency):
Opeating system:
There are no other dependencies despite the standard library (C++17) to build this library.
The following build types -DCMAKE_BUILD_TYPE=x
are possible:
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 sanitizersComponents:
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
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make
mkdir build
cd build
cmake ..
make doc
make package
or individual package types:
cpack -G TGZ
cpack -G DEB
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Coverage ..
make -j 8
make coverage doc cppcheck
There is a script bin/static-analysis-clang
for doing this, there is not yet
an integration of clang-tidy in the cmake build.
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'
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.
Mario Konrad (mario.konrad@gmx.net) with help from others.
Search the repository for a complete list:
git log --format=%an | sort -u
A (non-complete) collection of resources from where information was gathered.
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.