Goby3  3.1.5a
2024.05.23
encode.h
Go to the documentation of this file.
1 // Copyright 2011-2021:
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 // Community contributors (see AUTHORS file)
5 // File authors:
6 // Toby Schneider <toby@gobysoft.org>
7 //
8 //
9 // This file is part of the Goby Underwater Autonomy Project Libraries
10 // ("The Goby Libraries").
11 //
12 // The Goby Libraries are free software: you can redistribute them and/or modify
13 // them under the terms of the GNU Lesser General Public License as published by
14 // the Free Software Foundation, either version 2.1 of the License, or
15 // (at your option) any later version.
16 //
17 // The Goby Libraries are distributed in the hope that they will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU Lesser General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public License
23 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
24 
25 #ifndef GOBY_UTIL_AIS_ENCODE_H
26 #define GOBY_UTIL_AIS_ENCODE_H
27 
28 #include <atomic> // for atomic
29 #include <cmath> // for round
30 #include <cstdint> // for uint32_t, uint8_t
31 #include <stdexcept> // for runtime_error
32 #include <string> // for string, allocator
33 #include <vector> // for vector
34 
35 #include <boost/algorithm/string/case_conv.hpp> // for to_upper
36 #include <boost/dynamic_bitset/dynamic_bitset.hpp> // for dynamic_bitset
37 #include <boost/units/base_unit.hpp> // for base_unit<>::unit...
38 #include <boost/units/base_units/metric/knot.hpp> // for knot_base_unit
39 #include <boost/units/quantity.hpp> // for quantity, operator*
40 #include <boost/units/systems/angle/degrees.hpp> // for plane_angle, degrees
41 
42 namespace goby
43 {
44 namespace util
45 {
46 class NMEASentence;
47 
48 namespace ais
49 {
50 namespace protobuf
51 {
52 class Position;
53 class Voyage;
54 } // namespace protobuf
55 
56 class EncoderException : public std::runtime_error
57 {
58  public:
59  EncoderException(const std::string& what) : std::runtime_error(what) {}
60 };
61 
62 class Encoder
63 {
64  public:
66  Encoder(const goby::util::ais::protobuf::Voyage& voy, int part_num = 0);
67 
68  boost::dynamic_bitset<> as_bitset() const { return bits_; }
69 
70  std::vector<NMEASentence> as_nmea() const;
71 
72  private:
73  void encode_msg_18(const goby::util::ais::protobuf::Position& pos);
74  void encode_msg_24(const goby::util::ais::protobuf::Voyage& voy, std::uint32_t part_num);
75 
76  boost::units::quantity<boost::units::degree::plane_angle>
77  wrap_0_360(boost::units::quantity<boost::units::degree::plane_angle> in)
78  {
79  auto full_revolution = 360 * boost::units::degree::degrees;
80  while (in < 0 * boost::units::degree::degrees) in += full_revolution;
81  while (in >= full_revolution) in -= full_revolution;
82  return in;
83  }
84 
85  // lat/lon as 1/10000 minutes
86  template <typename AngleType, typename ValueType>
87  std::uint32_t ais_latlon(boost::units::quantity<AngleType, ValueType> ll)
88  {
89  return static_cast<std::int32_t>(std::round(
90  boost::units::quantity<boost::units::degree::plane_angle>(ll).value() * 600000.0));
91  }
92 
93  // 0 - 360 as tenths
94  template <typename AngleType, typename ValueType>
95  std::uint32_t ais_angle(boost::units::quantity<AngleType, ValueType> a, int precision)
96  {
97  return static_cast<std::uint32_t>(std::round(
98  wrap_0_360(boost::units::quantity<boost::units::degree::plane_angle>(a)).value() *
99  std::pow(10, precision)));
100  }
101 
102  // 1/10 knots
103  template <typename SpeedType, typename ValueType>
104  std::uint32_t ais_speed(boost::units::quantity<SpeedType, ValueType> s)
105  {
106  return static_cast<std::uint32_t>(std::round(
107  boost::units::quantity<boost::units::metric::knot_base_unit::unit_type>(s).value() *
108  10));
109  }
110 
111  struct AISField;
112  friend std::ostream& operator<<(std::ostream& os, const Encoder::AISField& ais);
113 
114  void concatenate_bitset(const std::vector<AISField>& fields)
115  {
116  for (auto it = fields.rbegin(), end = fields.rend(); it != end; ++it)
117  {
118  auto fb = it->as_bitset();
119  for (int i = 0, n = fb.size(); i < n; ++i) bits_.push_back(fb[i]);
120  }
121  }
122 
123  private:
124  struct AISField
125  {
126  std::uint8_t len{0};
127  std::uint32_t u{0};
128  std::string s{};
129  bool is_string{false};
130 
131  boost::dynamic_bitset<> as_bitset() const
132  {
133  if (is_string)
134  {
135  constexpr int ais_bits_per_char = 6;
136  std::string ms = s;
137  ms.resize(len / ais_bits_per_char, '@');
138  boost::to_upper(ms);
139 
140  boost::dynamic_bitset<> bits(len, 0);
141  for (int i = 0, n = ms.size(); i < n; ++i)
142  {
143  char c = ms[i];
144 
145  if (c >= '@' && c <= '_')
146  c -= '@';
147  else if (c >= ' ' && c <= '?')
148  ; // no change from ascii value
149  else // other values that can't be represented
150  c = '@';
151 
152  boost::dynamic_bitset<> char_bits(len, c & 0x3F);
153  bits |= (char_bits << (n - i - 1) * ais_bits_per_char);
154  }
155  return bits;
156  }
157  else
158  {
159  return boost::dynamic_bitset<>(len, u);
160  }
161  }
162  };
163 
164  boost::dynamic_bitset<> bits_;
165  enum class RadioChannel
166  {
167  CLASS_A,
168  CLASS_B
169  };
170  RadioChannel channel_{RadioChannel::CLASS_B};
171 
172  static std::atomic<int> sequence_id_;
173 };
174 
175 std::ostream& operator<<(std::ostream& os, const Encoder::AISField& ais)
176 {
177  os << "l:" << static_cast<int>(ais.len) << ", ";
178  if (ais.is_string)
179  os << "s: " << ais.s;
180  else
181  {
182  os << "u: " << ais.u;
183  os << ", i: " << static_cast<std::int32_t>(ais.u);
184  }
185  return os;
186 }
187 
188 } // namespace ais
189 } // namespace util
190 } // namespace goby
191 
192 #endif
goby
The global namespace for the Goby project.
Definition: acomms_constants.h:33
goby::util::ais::Encoder::as_bitset
boost::dynamic_bitset as_bitset() const
Definition: encode.h:68
goby::util::ais::operator<<
ostream & operator<<(ostream &os, Decoder::ParsedType t)
Definition: decode.h:182
goby::util::ais::Encoder::Encoder
Encoder(const goby::util::ais::protobuf::Position &pos)
goby::util::ais::protobuf::Position
Definition: ais.pb.h:302
goby::util::ais::Encoder::operator<<
friend std::ostream & operator<<(std::ostream &os, const Encoder::AISField &ais)
Definition: encode.h:175
goby::util::ais::EncoderException::EncoderException
EncoderException(const std::string &what)
Definition: encode.h:59
goby::util::ais::Encoder
Definition: encode.h:62
goby::util::ais::Encoder::as_nmea
std::vector< NMEASentence > as_nmea() const
goby::util::ais::EncoderException
Definition: encode.h:56
goby::util::ais::protobuf::Voyage
Definition: ais.pb.h:700