Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/release_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,29 @@ jobs:
name: python_dist
path: python/dist

# Check autogenerated signal definitions.
test_signal_defs:
name: GNSS Signal Definitions
runs-on: ubuntu-latest
defaults:
run:
working-directory: python
steps:
- uses: actions/checkout@v2

- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.x'

- name: Install Python Requirements
run: |
pip install -r requirements.txt

- name: Check Signal Definitions
run: |
python fusion_engine_client/messages/signal_def_gen.py --check-only

# Create a release only on a tag (not on a branch push).
release:
name: Create Release
Expand Down
2 changes: 1 addition & 1 deletion python/examples/binary_message_decode.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
payload.unpack(buffer=contents, offset=header.calcsize(),
message_version=header.message_version)
logger.info("Decoded payload contents: %s" % str(payload))
except ValueError as e:
except Exception as e:
logger.warning(str(e))
logger.warning("Unable to decode payload contents.")
else:
Expand Down
623 changes: 464 additions & 159 deletions python/fusion_engine_client/analysis/analyzer.py

Large diffs are not rendered by default.

31 changes: 23 additions & 8 deletions python/fusion_engine_client/analysis/data_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,24 @@ def to_numpy(self, remove_nan_times: bool = True,
self.message_bytes = np.array(self.message_bytes, dtype=np.uint64)
self.message_index = np.array(self.message_index, dtype=int)

if remove_nan_times and 'p1_time' in self.__dict__:
is_nan = np.isnan(self.p1_time)
# Helper function for removing entries with NAN timestamps.
def _remove_nan_from_dict(data_dict):
if 'p1_time' not in data_dict:
return

is_nan = np.isnan(data_dict['p1_time'])
if np.any(is_nan):
keep_idx = ~is_nan
for key, value in self.__dict__.items():
for key, value in data_dict.items():
if (key not in ('message_type', 'message_class', 'params', 'messages') and
isinstance(value, np.ndarray)):
if key in self.__dict__.get('__metadata__', {}).get('not_time_dependent', []):
if key in data_dict.get('__metadata__', {}).get('not_time_dependent', []):
# Data is not time-dependent, even if it happens to have the same number of elements
# as the time vector.
pass
elif len(value.shape) == 1:
if len(value) == len(keep_idx):
self.__dict__[key] = value[keep_idx]
data_dict[key] = value[keep_idx]
else:
# Field has a different length than the time vector. It is likely a
# non-time-varying element (e.g., a position std dev threshold).
Expand All @@ -113,21 +117,32 @@ def to_numpy(self, remove_nan_times: bool = True,
# along the columns.
if value.shape[1] == len(is_nan):
# Assuming second dimension (columns) is time.
self.__dict__[key] = value[:, keep_idx]
data_dict[key] = value[:, keep_idx]
# Otherwise, check to see if the data is transposed as NxA.
elif value.shape[0] == len(is_nan):
# Assuming first dimension is time.
self.__dict__[key] = value[keep_idx, :]
data_dict[key] = value[keep_idx, :]
elif value.shape[1] == len(is_nan):
# Assuming second dimension is time.
self.__dict__[key] = value[:, keep_idx]
data_dict[key] = value[:, keep_idx]
else:
# Unrecognized data shape.
pass
else:
# Unrecognized data shape.
pass

# If requested, remove any entries with NAN P1 timestamps.
if remove_nan_times:
# Remove NANs from top-level numpy data.
_remove_nan_from_dict(self.__dict__)

# Special cast: also remove NANs from nested satellite/signal data elements.
if self.message_type == MessageType.GNSS_SIGNALS:
_remove_nan_from_dict(self.sv_data)
_remove_nan_from_dict(self.signal_data)


if not keep_messages:
self.messages = []
if not keep_message_bytes:
Expand Down
28 changes: 28 additions & 0 deletions python/fusion_engine_client/analysis/plotly_data_support.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
var figure = document.getElementsByClassName("plotly-graph-div js-plotly-plot")[0];

function GetTimeText(time_sec) {
if (p1_time_axis_rel) {
return `Rel: ${time_sec.toFixed(3)} sec (P1: ${(time_sec + p1_t0_sec).toFixed(3)} sec)`;
}
else {
return `Rel: ${(time_sec - p1_t0_sec).toFixed(3)} sec (P1: ${time_sec.toFixed(3)} sec)`;
}
}

function ChangeHoverText(point, new_text) {
// Note: Technically calling restyle() is more correct, however it can only restyle an entire trace, not just one
// point in a trace, and in practice it's very sluggish. Manually modifying fullData.text is much faster. Both options
// seem to have a small race condition and occasionally the text does not change before the hover div becomes visible.
// Nothing we can do about that right now.
// let text_array = point.data.text;
// text_array[point.pointNumber] = new_text;
// Plotly.restyle(d, {'text': text_array}, [point.curveNumber]);
point.fullData.text = new_text;
}

function GetCustomData(point, row) {
let customdata = point.data.customdata.hasOwnProperty("_inputArray") ?
point.data.customdata._inputArray :
point.data.customdata;
return customdata[row][point.pointNumber];
}
1 change: 1 addition & 0 deletions python/fusion_engine_client/messages/defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class MessageType(IntEnum):
POSE_AUX = 10003
CALIBRATION_STATUS = 10004
RELATIVE_ENU_POSITION = 10005
GNSS_SIGNALS = 10006

# Device status messages.
SYSTEM_STATUS = 10500
Expand Down
Loading
Loading