Skip to content

vtol_tailsitter: copy cached ulog arrays before in-place mutation#338

Open
evanofficial wants to merge 1 commit into
PX4:mainfrom
evanofficial:fix-tailsitter-yaw-rate-mutation
Open

vtol_tailsitter: copy cached ulog arrays before in-place mutation#338
evanofficial wants to merge 1 commit into
PX4:mainfrom
evanofficial:fix-tailsitter-yaw-rate-mutation

Conversation

@evanofficial

Copy link
Copy Markdown

Fixes #324.

Root cause

tailsitter_orientation() in app/plot_app/vtol_tailsitter.py reads the angular-rate and rates-setpoint arrays directly from the cached ULog dataset:

w_r = cur_dataset.data['xyz[0]']
w_y = cur_dataset.data['xyz[2]']
...
w_r[mask] = w_r_fw[mask]
w_y[mask] = w_y_fw[mask]

cur_dataset.data['xyz[0]'] is a reference to the underlying numpy array, and load_ulog_file() in helper.py is wrapped with @lru_cache, so the same ULog object is reused across page loads. The masked assignments mutate the cached arrays in place. On the next refresh the function re-derives w_r_fw = w_y * -1 and w_y_fw = w_r * 1 from arrays that already have their FW segments swapped, producing a different (and progressively more corrupted) yaw angular rate each time.

The author was aware of the reference/aliasing trap for the two derived arrays (the # *1 to get python to copy not reference comment), but missed that w_r and w_y themselves are still references into the cache.

The attitude block at the top of the same function is unaffected because it builds new arrays via np.deg2rad(rpy[:, …]) before mutating.

Fix

np.copy() the source arrays once, right where they're pulled out of the dataset, for both the vehicle_angular_velocity and vehicle_rates_setpoint blocks. The rest of the masking logic is unchanged.

Test plan

No test infrastructure exists in this repo (no tests/ directory, no test runner in CI), so no regression test was added. Manual verification: load any tailsitter VTOL log on a flight-review instance and refresh the page repeatedly — yaw angular rate plot should now be stable instead of drifting.

tailsitter_orientation() read angular rate and rates-setpoint arrays
directly from cur_dataset.data and then wrote FW-corrected values back
into them with boolean-mask assignment. Because load_ulog_file() uses
lru_cache, the same ULog object is reused across page reloads, so the
in-place writes corrupted the cached dataset. On each refresh the
function re-derived the swapped FW values from the already-swapped
arrays, which is why the yaw angular rate plot changed value on every
refresh for tailsitter VTOL logs (PX4#324).

Copy the source arrays once with np.copy() before the masking loop so
the cache stays clean.

Fixes PX4#324
Comment on lines 86 to 87
w_r_fw = w_y*-1
w_y_fw = w_r*1 # *1 to get python to copy not reference

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use np.copy here too? And also below (setp_r_fw = ...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Each time refresh the page, yaw angular rate data changes in tailsitter VTOL mode

2 participants