Goby3  3.1.5a
2024.05.23
decode.h
Go to the documentation of this file.
1 // Copyright 2019-2021:
2 // GobySoft, LLC (2013-)
3 // Community contributors (see AUTHORS file)
4 // File authors:
5 // Toby Schneider <toby@gobysoft.org>
6 //
7 //
8 // This file is part of the Goby Underwater Autonomy Project Libraries
9 // ("The Goby Libraries").
10 //
11 // The Goby Libraries are free software: you can redistribute them and/or modify
12 // them under the terms of the GNU Lesser General Public License as published by
13 // the Free Software Foundation, either version 2.1 of the License, or
14 // (at your option) any later version.
15 //
16 // The Goby Libraries are distributed in the hope that they will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public License
22 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
23 
24 #ifndef GOBY_UTIL_AIS_DECODE_H
25 #define GOBY_UTIL_AIS_DECODE_H
26 
27 #include <memory> // for unique_ptr
28 #include <ostream> // for operator<<
29 #include <stdexcept> // for runtime_error
30 #include <string> // for string
31 #include <vector> // for vector
32 
33 #include <ais.h> // for string, ostream
34 #include <boost/algorithm/string/classification.hpp> // for pred_orF, is_...
35 #include <boost/algorithm/string/predicate_facade.hpp> // for predicate_facade
36 #include <boost/algorithm/string/trim.hpp> // for trim_if
37 #include <boost/units/base_unit.hpp> // for base_unit<>::...
38 #include <boost/units/base_units/metric/knot.hpp> // for knot_base_unit
39 #include <boost/units/operators.hpp> // for units
40 #include <boost/units/systems/angle/degrees.hpp> // for degrees
41 #include <boost/units/systems/si/length.hpp> // for meters
42 #include <boost/units/systems/si/time.hpp> // for seconds
43 #include <vdm.h> // for VdmStream
44 
45 #include "goby/util/linebasedcomms/nmea_sentence.h" // for NMEASentence
46 #include "goby/util/protobuf/ais.pb.h" // for Voyage, Position
47 
48 namespace goby
49 {
50 namespace util
51 {
52 namespace ais
53 {
54 class DecoderException : public std::runtime_error
55 {
56  public:
57  DecoderException(const std::string& what) : std::runtime_error(what) {}
58 };
59 
60 class Decoder
61 {
62  public:
63  Decoder() {}
64  Decoder(const NMEASentence& nmea) : Decoder(std::vector<NMEASentence>(1, nmea)) {}
65  Decoder(const std::vector<NMEASentence>& nmeas);
66 
67  // returns true if message is complete
68  bool push(const NMEASentence& nmea);
69 
70  bool complete() { return ais_msg_ != nullptr; }
71 
72  int message_id()
73  {
74  if (complete())
75  return ais_msg_->message_id;
76  else
77  throw(DecoderException("Message not complete: missing NMEA sentences?"));
78  }
79 
80  enum class ParsedType
81  {
83  POSITION,
84  VOYAGE
85  };
86 
88  {
89  switch (message_id())
90  {
91  case 1:
92  case 2:
93  case 3:
94  case 18:
95  case 19: return ParsedType::POSITION;
96  case 5:
97  case 24: return ParsedType::VOYAGE;
98  default: return ParsedType::NOT_SUPPORTED;
99  }
100  }
101 
104 
105  libais::AisMsg& as_libais_msg()
106  {
107  if (complete())
108  return *ais_msg_;
109  else
110  throw(DecoderException("Message not complete: missing NMEA sentences?"));
111  }
112 
113  private:
114  std::string trim_ais_string(std::string in)
115  {
116  boost::trim_if(in, boost::algorithm::is_space() || boost::algorithm::is_any_of("@"));
117  return in;
118  }
119 
120  template <typename LibAisMessage>
121  void set_shared_fields(goby::util::ais::protobuf::Voyage& /*voy*/, const LibAisMessage& ais,
122  int part_num)
123  {
124  using namespace boost::units;
125 
126  voy_.set_message_id(ais.message_id);
127  voy_.set_mmsi(ais.mmsi);
128 
129  if (part_num == 0)
130  {
131  std::string name = trim_ais_string(ais.name);
132  if (!name.empty())
133  voy_.set_name(name);
134  }
135  else if (part_num == 1)
136  {
137  std::string callsign = trim_ais_string(ais.callsign);
138  if (!callsign.empty())
139  voy_.set_callsign(callsign);
140 
141  if (protobuf::Voyage::ShipType_IsValid(ais.type_and_cargo))
142  voy_.set_type(static_cast<protobuf::Voyage::ShipType>(ais.type_and_cargo));
143  voy_.set_to_bow_with_units(ais.dim_a * si::meters);
144  voy_.set_to_stern_with_units(ais.dim_b * si::meters);
145  voy_.set_to_port_with_units(ais.dim_c * si::meters);
146  voy_.set_to_starboard_with_units(ais.dim_d * si::meters);
147  }
148  }
149 
150  template <typename LibAisMessage>
151  void set_shared_fields(goby::util::ais::protobuf::Position& pos, const LibAisMessage& ais)
152  {
153  using namespace boost::units;
154  pos.set_message_id(ais.message_id);
155  pos.set_mmsi(ais.mmsi);
156  metric::knot_base_unit::unit_type knots;
157  pos.set_speed_over_ground_with_units(ais.sog * knots);
158  pos.set_lat_with_units(ais.position.lat_deg * degree::degrees);
159  pos.set_lon_with_units(ais.position.lng_deg * degree::degrees);
160  pos.set_course_over_ground_with_units(ais.cog * degree::degrees);
161  if (ais.true_heading >= 0 && ais.true_heading < 360)
162  pos.set_true_heading_with_units(ais.true_heading * degree::degrees);
163  pos.set_report_second_with_units(ais.timestamp * si::seconds);
164  pos.set_raim(ais.raim);
165 
166  if (protobuf::Position::PositionAccuracy_IsValid(ais.position_accuracy))
167  pos_.set_position_accuracy(
168  static_cast<protobuf::Position::PositionAccuracy>(ais.position_accuracy));
169  }
170 
171  void decode_position();
172  void decode_voyage();
173 
174  private:
175  libais::VdmStream ais_stream_decoder_;
176  std::unique_ptr<libais::AisMsg> ais_msg_;
177 
180 };
181 
182 inline ostream& operator<<(ostream& os, Decoder::ParsedType t)
183 {
184  switch (t)
185  {
186  default:
187  case Decoder::ParsedType::NOT_SUPPORTED: return os << "NOT_SUPPORTED";
188  case Decoder::ParsedType::VOYAGE: return os << "VOYAGE";
189  case Decoder::ParsedType::POSITION: return os << "POSITION";
190  }
191 }
192 
193 } // namespace ais
194 } // namespace util
195 } // namespace goby
196 
197 #endif
goby::util::ais::Decoder::as_libais_msg
libais::AisMsg & as_libais_msg()
Definition: decode.h:105
goby::util::ais::protobuf::Position::set_mmsi
void set_mmsi(::google::protobuf::int32 value)
Definition: ais.pb.h:1387
goby::util::ais::Decoder::ParsedType::VOYAGE
@ VOYAGE
goby::util::ais::protobuf::Position::set_raim
void set_raim(bool value)
Definition: ais.pb.h:1654
goby
The global namespace for the Goby project.
Definition: acomms_constants.h:33
goby::util::ais::Decoder::ParsedType::POSITION
@ POSITION
goby::util::ais::operator<<
ostream & operator<<(ostream &os, Decoder::ParsedType t)
Definition: decode.h:182
goby::util::ais::Decoder::Decoder
Decoder()
Definition: decode.h:63
goby::util::ais::protobuf::Voyage::ShipType
Voyage_ShipType ShipType
Definition: ais.pb.h:792
goby::util::ais::protobuf::Position::set_lon_with_units
void set_lon_with_units(Quantity value_w_units)
Definition: ais.pb.h:596
nmea_sentence.h
goby::util::ais::Decoder
Definition: decode.h:60
goby::util::ais::protobuf::Position::PositionAccuracy
Position_PositionAccuracy PositionAccuracy
Definition: ais.pb.h:426
goby::util::ais::protobuf::Position::set_true_heading_with_units
void set_true_heading_with_units(Quantity value_w_units)
Definition: ais.pb.h:626
goby::util::ais::DecoderException
Definition: decode.h:54
goby::util::ais::protobuf::Voyage::ShipType_IsValid
static bool ShipType_IsValid(int value)
Definition: ais.pb.h:993
goby::util::ais::protobuf::Position::set_lat_with_units
void set_lat_with_units(Quantity value_w_units)
Definition: ais.pb.h:581
goby::util::ais::protobuf::Position
Definition: ais.pb.h:302
goby::util::ais::Decoder::ParsedType::NOT_SUPPORTED
@ NOT_SUPPORTED
goby::util::ais::Decoder::ParsedType
ParsedType
Definition: decode.h:80
goby::util::ais::protobuf::Position::set_course_over_ground_with_units
void set_course_over_ground_with_units(Quantity value_w_units)
Definition: ais.pb.h:611
goby::util::ais::Decoder::message_id
int message_id()
Definition: decode.h:72
goby::util::ais::protobuf::Position::PositionAccuracy_IsValid
static bool PositionAccuracy_IsValid(int value)
Definition: ais.pb.h:431
ais.pb.h
goby::util::ais::Decoder::complete
bool complete()
Definition: decode.h:70
goby::util::ais::DecoderException::DecoderException
DecoderException(const std::string &what)
Definition: decode.h:57
goby::util::ais::Decoder::Decoder
Decoder(const NMEASentence &nmea)
Definition: decode.h:64
goby::util::ais::Decoder::parsed_type
ParsedType parsed_type()
Definition: decode.h:87
goby::util::ais::Decoder::as_voyage
goby::util::ais::protobuf::Voyage as_voyage()
goby::util::ais::protobuf::Position::set_speed_over_ground_with_units
void set_speed_over_ground_with_units(Quantity value_w_units)
Definition: ais.pb.h:566
goby::util::ais::protobuf::Position::set_message_id
void set_message_id(::google::protobuf::int32 value)
Definition: ais.pb.h:1363
goby::util::ais::protobuf::Position::set_report_second_with_units
void set_report_second_with_units(Quantity value_w_units)
Definition: ais.pb.h:641
boost::units
Definition: time.hpp:18
goby::util::ais::protobuf::Voyage
Definition: ais.pb.h:700
goby::util::ais::Decoder::as_position
goby::util::ais::protobuf::Position as_position()
time.hpp
goby::util::ais::Decoder::push
bool push(const NMEASentence &nmea)
goby::util::NMEASentence
Definition: nmea_sentence.h:51