1 #include <marnav/ais/message_18.hpp>
2 #include <marnav/ais/angle.hpp>
9 constexpr message_id
message_18::ID
;
10 constexpr std::size_t message_18::SIZE_BITS
;
12 message_18::message_18()
17 message_18::message_18(message_id id
)
22 message_18::message_18(const raw
& bits
)
25 if (bits
.size() != SIZE_BITS
)
26 throw std::invalid_argument
{"invalid number of bits in message_18"};
30 void message_18::read_data(const raw
& bits
)
32 get(bits
, repeat_indicator
);
35 get(bits
, position_accuracy
);
36 get(bits
, longitude_minutes
);
37 get(bits
, latitude_minutes
);
42 get(bits
, display_flag
);
45 get(bits
, message_22_flag
);
48 get(bits
, radio_status
);
51 raw
message_18::get_data() const
55 bits
.set(type(), 0, 6);
56 set(bits
, repeat_indicator
);
59 set(bits
, position_accuracy
);
60 set(bits
, longitude_minutes
);
61 set(bits
, latitude_minutes
);
66 set(bits
, display_flag
);
69 set(bits
, message_22_flag
);
72 set(bits
, radio_status
);
77 utils::optional
<geo::longitude
> message_18::get_lon() const
79 if (longitude_minutes
== longitude_not_available
)
80 return utils::make_optional
<geo::longitude
>();
81 return to_geo_longitude(longitude_minutes
, longitude_minutes
.count
, angle_scale::I4
);
84 utils::optional
<geo::latitude
> message_18::get_lat() const
86 if (latitude_minutes
== latitude_not_available
)
87 return utils::make_optional
<geo::latitude
>();
88 return to_geo_latitude(latitude_minutes
, latitude_minutes
.count
, angle_scale::I4
);
91 void message_18::set_lon_unavailable()
93 longitude_minutes
= longitude_not_available
;
96 void message_18::set_lat_unavailable()
98 latitude_minutes
= latitude_not_available
;
101 void message_18::set_lon(const geo::longitude
& t
)
103 longitude_minutes
= to_longitude_minutes(t
, longitude_minutes
.count
, angle_scale::I4
);
106 void message_18::set_lat(const geo::latitude
& t
)
108 latitude_minutes
= to_latitude_minutes(t
, latitude_minutes
.count
, angle_scale::I4
);
111 utils::optional
<units::knots
> message_18::get_sog() const noexcept
113 // ignores special value of 1022 = 102.2 knots or faster
115 if (sog
== sog_not_available
)
117 return units::knots
{0.1 * sog
};
120 void message_18::set_sog_unavailable()
122 sog
= sog_not_available
;
125 void message_18::set_sog(units::velocity t
)
128 throw std::invalid_argument
{"SOG less than zero"};
130 const auto v
= t
.get
<units::knots
>();
131 sog
= std::min(sog_max
, static_cast<uint32_t>(round(v
* 10).value()));
134 /// Returns course over ground in degrees true north.
135 utils::optional
<double> message_18::get_cog() const noexcept
137 if (cog
== cog_not_available
)
142 void message_18::set_cog(utils::optional
<double> t
) noexcept
144 cog
= !t
? cog_not_available
: static_cast<uint32_t>(std::round(*t
/ 0.1));
147 /// Returns heading in degrees.
148 utils::optional
<uint32_t> message_18::get_hdg() const noexcept
150 if (hdg
== hdg_not_available
)
155 void message_18::set_hdg(utils::optional
<uint32_t> t
) noexcept
157 hdg
= !t
? hdg_not_available
: *t
;