Skip to content

Commit 19ca684

Browse files
authored
Add bitmask in PoseMessage to signal stationary status of device (#331)
# New Features - `PoseMessage` now has `flags member, which currently signals whether the device is stationary or not - Add `Stationary Status` plotting tool
2 parents 2330ed8 + 7ece89e commit 19ca684

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

python/fusion_engine_client/analysis/analyzer.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,39 @@ def plot_solution_type(self):
724724

725725
self._add_figure(name="solution_type", figure=figure, title="Solution Type")
726726

727+
def plot_stationary_status(self):
728+
"""!
729+
@brief Plot the staionary status over time.
730+
"""
731+
if self.output_dir is None:
732+
return
733+
734+
# Read the pose data.
735+
result = self.reader.read(message_types=[PoseMessage], source_ids=self.default_source_id, **self.params)
736+
pose_data = result[PoseMessage.MESSAGE_TYPE]
737+
738+
if len(pose_data.p1_time) == 0:
739+
self.logger.info('No pose data available. Skipping solution type plot.')
740+
return
741+
742+
# Set up the figure.
743+
figure = make_subplots(rows=1, cols=1, print_grid=False, shared_xaxes=True, subplot_titles=['Stationary Status'])
744+
745+
figure['layout']['xaxis'].update(title=self.p1_time_label)
746+
figure['layout']['yaxis1'].update(title="Stationary Status",
747+
ticktext=['Moving', 'Stationary'],
748+
tickvals=[0, PoseMessage.FLAG_STATIONARY])
749+
750+
time = pose_data.p1_time - float(self.t0)
751+
752+
# Extract the stationary status from the pose data flags.
753+
stationary_status = pose_data.flags & PoseMessage.FLAG_STATIONARY
754+
755+
text = ["Time: %.3f sec (%.3f sec)" % (t, t + float(self.t0)) for t in time]
756+
figure.add_trace(go.Scattergl(x=time, y=stationary_status, text=text, mode='markers'), 1, 1)
757+
758+
self._add_figure(name="stationary_status", figure=figure, title="Stationary Status")
759+
727760
def _plot_displacement(self, source, time, solution_type, displacement_enu_m, std_enu_m,
728761
title='Displacement'):
729762
"""!
@@ -2944,6 +2977,7 @@ def main():
29442977
analyzer.plot_time_scale()
29452978

29462979
analyzer.plot_solution_type()
2980+
analyzer.plot_stationary_status()
29472981
analyzer.plot_reset_timing()
29482982
analyzer.plot_pose()
29492983
analyzer.plot_pose_displacement()

python/fusion_engine_client/messages/solution.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,18 @@ class PoseMessage(MessagePayload):
1818

1919
INVALID_UNDULATION = -32768
2020

21-
_STRUCT = struct.Struct('<Bx h ddd fff ddd fff ddd fff fff')
21+
FLAG_STATIONARY = 0x1
22+
23+
_STRUCT = struct.Struct('<BB h ddd fff ddd fff ddd fff fff')
2224

2325
def __init__(self):
2426
self.p1_time = Timestamp()
2527
self.gps_time = Timestamp()
2628

2729
self.solution_type = SolutionType.Invalid
2830

31+
self.flags = 0x0
32+
2933
# Added in version 1.1.
3034
self.undulation_m = np.nan
3135

@@ -60,6 +64,7 @@ def pack(self, buffer: bytes = None, offset: int = 0, return_buffer: bool = True
6064
self._STRUCT.pack_into(
6165
buffer, offset,
6266
int(self.solution_type),
67+
self.flags,
6368
undulation_cm,
6469
self.lla_deg[0], self.lla_deg[1], self.lla_deg[2],
6570
self.position_std_enu_m[0], self.position_std_enu_m[1], self.position_std_enu_m[2],
@@ -84,6 +89,7 @@ def unpack(self, buffer: bytes, offset: int = 0, message_version: int = MessageP
8489
offset += self.gps_time.unpack(buffer, offset)
8590

8691
(solution_type_int,
92+
flags,
8793
undulation_cm,
8894
self.lla_deg[0], self.lla_deg[1], self.lla_deg[2],
8995
self.position_std_enu_m[0], self.position_std_enu_m[1], self.position_std_enu_m[2],
@@ -104,6 +110,8 @@ def unpack(self, buffer: bytes, offset: int = 0, message_version: int = MessageP
104110

105111
self.solution_type = SolutionType(solution_type_int)
106112

113+
self.flags = flags
114+
107115
return offset - initial_offset
108116

109117
def __repr__(self):
@@ -152,6 +160,7 @@ def to_numpy(cls, messages):
152160
'p1_time': np.array([float(m.p1_time) for m in messages]),
153161
'gps_time': np.array([float(m.gps_time) for m in messages]),
154162
'solution_type': np.array([int(m.solution_type) for m in messages], dtype=int),
163+
'flags': np.array([m.flags for m in messages], dtype=int),
155164
'undulation': np.array([m.undulation_m for m in messages]),
156165
'lla_deg': np.array([m.lla_deg for m in messages]).T,
157166
'ypr_deg': np.array([m.ypr_deg for m in messages]).T,

src/point_one/fusion_engine/messages/solution.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ struct P1_ALIGNAS(4) PoseMessage : public MessagePayload {
4242
static constexpr uint8_t MESSAGE_VERSION = 1;
4343
static constexpr int16_t INVALID_UNDULATION = INT16_MIN;
4444

45+
/** Set if the device is stationary. */
46+
static constexpr uint8_t FLAG_STATIONARY = 0x01;
47+
4548
/** The time of the message, in P1 time (beginning at power-on). */
4649
Timestamp p1_time;
4750

@@ -51,7 +54,8 @@ struct P1_ALIGNAS(4) PoseMessage : public MessagePayload {
5154
/** The type of this position solution. */
5255
SolutionType solution_type;
5356

54-
uint8_t reserved = 0;
57+
/** A bitmask of flags associated with the pose data. */
58+
uint8_t flags = 0x0;
5559

5660
/**
5761
* The geoid undulation at at the current location (i.e., the difference

0 commit comments

Comments
 (0)