25 #ifndef GOBY_UTIL_AIS_ENCODE_H
26 #define GOBY_UTIL_AIS_ENCODE_H
35 #include <boost/algorithm/string/case_conv.hpp>
36 #include <boost/dynamic_bitset/dynamic_bitset.hpp>
37 #include <boost/units/base_unit.hpp>
38 #include <boost/units/base_units/metric/knot.hpp>
39 #include <boost/units/quantity.hpp>
40 #include <boost/units/systems/angle/degrees.hpp>
68 boost::dynamic_bitset<>
as_bitset()
const {
return bits_; }
70 std::vector<NMEASentence>
as_nmea()
const;
76 boost::units::quantity<boost::units::degree::plane_angle>
77 wrap_0_360(boost::units::quantity<boost::units::degree::plane_angle> in)
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;
86 template <
typename AngleType,
typename ValueType>
87 std::uint32_t ais_latlon(boost::units::quantity<AngleType, ValueType> ll)
89 return static_cast<std::int32_t
>(std::round(
90 boost::units::quantity<boost::units::degree::plane_angle>(ll).value() * 600000.0));
94 template <
typename AngleType,
typename ValueType>
95 std::uint32_t ais_angle(boost::units::quantity<AngleType, ValueType> a,
int precision)
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)));
103 template <
typename SpeedType,
typename ValueType>
104 std::uint32_t ais_speed(boost::units::quantity<SpeedType, ValueType> s)
106 return static_cast<std::uint32_t
>(std::round(
107 boost::units::quantity<boost::units::metric::knot_base_unit::unit_type>(s).value() *
112 friend std::ostream&
operator<<(std::ostream& os,
const Encoder::AISField& ais);
114 void concatenate_bitset(
const std::vector<AISField>& fields)
116 for (
auto it = fields.rbegin(), end = fields.rend(); it != end; ++it)
118 auto fb = it->as_bitset();
119 for (
int i = 0, n = fb.size(); i < n; ++i) bits_.push_back(fb[i]);
129 bool is_string{
false};
131 boost::dynamic_bitset<>
as_bitset()
const
135 constexpr
int ais_bits_per_char = 6;
137 ms.resize(len / ais_bits_per_char,
'@');
140 boost::dynamic_bitset<> bits(len, 0);
141 for (
int i = 0, n = ms.size(); i < n; ++i)
145 if (c >=
'@' && c <=
'_')
147 else if (c >=
' ' && c <=
'?')
152 boost::dynamic_bitset<> char_bits(len, c & 0x3F);
153 bits |= (char_bits << (n - i - 1) * ais_bits_per_char);
159 return boost::dynamic_bitset<>(len, u);
164 boost::dynamic_bitset<> bits_;
165 enum class RadioChannel
170 RadioChannel channel_{RadioChannel::CLASS_B};
172 static std::atomic<int> sequence_id_;
175 std::ostream&
operator<<(std::ostream& os,
const Encoder::AISField& ais)
177 os <<
"l:" <<
static_cast<int>(ais.len) <<
", ";
179 os <<
"s: " << ais.s;
182 os <<
"u: " << ais.u;
183 os <<
", i: " <<
static_cast<std::int32_t
>(ais.u);