In this demo we will analyze the mechanical vibration of a quadrotor during flight using publicly available logs.

We obtain the logs from review.px4.io, https://review.px4.io/plot_app?log=8aa57955-db73-46d5-8800-17903bbc3575

Open the file

In [1]:
%pylab inline

import pyulog

with open('data/8aa57955-db73-46d5-8800-17903bbc3575.ulg', 'rb') as f:
    log = pyulog.ULog(f)
Populating the interactive namespace from numpy and matplotlib

List the Data Topics

In [2]:
for data in log.data_list:
    print(data.name)
vehicle_local_position_setpoint
vehicle_magnetometer
vehicle_air_data
ekf2_timestamps
vehicle_status_flags
vehicle_status
vehicle_rates_setpoint
vehicle_local_position
vehicle_land_detected
vehicle_gps_position
vehicle_global_position
vehicle_attitude_setpoint
vehicle_attitude
telemetry_status
system_power
sensor_preflight
sensor_combined
safety
rate_ctrl_status
manual_control_setpoint
input_rc
home_position
estimator_status
ekf2_innovations
distance_sensor
cpuload
battery_status
actuator_outputs
actuator_outputs
actuator_controls_0
In [3]:
d = log.get_dataset('actuator_controls_0')
plt.plot(d.data['control[1]'])
Out[3]:
[<matplotlib.lines.Line2D at 0x7f1617717d30>]
In [4]:
import re
import sys

search_term = sys.argv[1]
f = sys.argv[2]

for k in log.initial_parameters.keys():
    if re.search('LOG', k):
        print(k)
SDLOG_DIRS_MAX
SDLOG_MODE
SDLOG_PROFILE
SDLOG_UTC_OFFSET
SDLOG_UUID
SYS_LOGGER
In [5]:
log.initial_parameters['SDLOG_PROFILE']
Out[5]:
3
In [6]:
1/(np.diff(log.get_dataset('vehicle_attitude').data['timestamp'])/1e6)
Out[6]:
array([31.09646122, 31.41887646, 31.18762475, ..., 31.23145632,
       34.59369703, 31.43467874])
In [7]:
for topic in log.data_list:
    print(topic.name)
    for k in log.get_dataset(topic.name).data.keys():
        print('\t', k)
vehicle_local_position_setpoint
	 timestamp
	 x
	 y
	 z
	 yaw
	 yawspeed
	 vx
	 vy
	 vz
	 acc_x
	 acc_y
	 acc_z
	 thrust[0]
	 thrust[1]
	 thrust[2]
vehicle_magnetometer
	 timestamp
	 magnetometer_ga[0]
	 magnetometer_ga[1]
	 magnetometer_ga[2]
vehicle_air_data
	 timestamp
	 baro_alt_meter
	 baro_temp_celcius
	 baro_pressure_pa
	 rho
ekf2_timestamps
	 timestamp
	 airspeed_timestamp_rel
	 distance_sensor_timestamp_rel
	 gps_timestamp_rel
	 optical_flow_timestamp_rel
	 vehicle_air_data_timestamp_rel
	 vehicle_magnetometer_timestamp_rel
	 vision_attitude_timestamp_rel
	 vision_position_timestamp_rel
vehicle_status_flags
	 timestamp
	 condition_calibration_enabled
	 condition_system_sensors_initialized
	 condition_system_hotplug_timeout
	 condition_system_returned_to_home
	 condition_auto_mission_available
	 condition_global_position_valid
	 condition_home_position_valid
	 condition_local_position_valid
	 condition_local_velocity_valid
	 condition_local_altitude_valid
	 condition_power_input_valid
	 circuit_breaker_engaged_power_check
	 circuit_breaker_engaged_airspd_check
	 circuit_breaker_engaged_enginefailure_check
	 circuit_breaker_engaged_gpsfailure_check
	 circuit_breaker_flight_termination_disabled
	 circuit_breaker_engaged_usb_check
	 circuit_breaker_engaged_posfailure_check
	 offboard_control_signal_found_once
	 offboard_control_signal_lost
	 offboard_control_set_by_command
	 offboard_control_loss_timeout
	 rc_signal_found_once
	 rc_input_blocked
	 rc_calibration_valid
	 vtol_transition_failure
	 usb_connected
vehicle_status
	 timestamp
	 onboard_control_sensors_present
	 onboard_control_sensors_enabled
	 onboard_control_sensors_health
	 nav_state
	 arming_state
	 hil_state
	 failsafe
	 system_type
	 system_id
	 component_id
	 is_rotary_wing
	 is_vtol
	 vtol_fw_permanent_stab
	 in_transition_mode
	 in_transition_to_fw
	 rc_signal_lost
	 rc_input_mode
	 data_link_lost
	 high_latency_data_link_active
	 data_link_lost_counter
	 engine_failure
	 mission_failure
vehicle_rates_setpoint
	 timestamp
	 roll
	 pitch
	 yaw
	 thrust
vehicle_local_position
	 timestamp
	 ref_timestamp
	 ref_lat
	 ref_lon
	 x
	 y
	 z
	 delta_xy[0]
	 delta_xy[1]
	 delta_z
	 vx
	 vy
	 vz
	 z_deriv
	 delta_vxy[0]
	 delta_vxy[1]
	 delta_vz
	 ax
	 ay
	 az
	 yaw
	 ref_alt
	 dist_bottom
	 dist_bottom_rate
	 eph
	 epv
	 evh
	 evv
	 vxy_max
	 vz_max
	 hagl_min
	 hagl_max
	 xy_valid
	 z_valid
	 v_xy_valid
	 v_z_valid
	 xy_reset_counter
	 z_reset_counter
	 vxy_reset_counter
	 vz_reset_counter
	 xy_global
	 z_global
	 dist_bottom_valid
vehicle_land_detected
	 timestamp
	 alt_max
	 landed
	 freefall
	 ground_contact
	 maybe_landed
vehicle_gps_position
	 timestamp
	 time_utc_usec
	 lat
	 lon
	 alt
	 alt_ellipsoid
	 s_variance_m_s
	 c_variance_rad
	 eph
	 epv
	 hdop
	 vdop
	 noise_per_ms
	 jamming_indicator
	 vel_m_s
	 vel_n_m_s
	 vel_e_m_s
	 vel_d_m_s
	 cog_rad
	 timestamp_time_relative
	 fix_type
	 vel_ned_valid
	 satellites_used
vehicle_global_position
	 timestamp
	 lat
	 lon
	 alt
	 delta_alt
	 vel_n
	 vel_e
	 vel_d
	 yaw
	 eph
	 epv
	 terrain_alt
	 lat_lon_reset_counter
	 alt_reset_counter
	 terrain_alt_valid
	 dead_reckoning
vehicle_attitude_setpoint
	 timestamp
	 roll_body
	 pitch_body
	 yaw_body
	 yaw_sp_move_rate
	 q_d[0]
	 q_d[1]
	 q_d[2]
	 q_d[3]
	 thrust
	 landing_gear
	 q_d_valid
	 roll_reset_integral
	 pitch_reset_integral
	 yaw_reset_integral
	 fw_control_yaw
	 disable_mc_yaw_control
	 apply_flaps
vehicle_attitude
	 timestamp
	 rollspeed
	 pitchspeed
	 yawspeed
	 q[0]
	 q[1]
	 q[2]
	 q[3]
	 delta_q_reset[0]
	 delta_q_reset[1]
	 delta_q_reset[2]
	 delta_q_reset[3]
	 quat_reset_counter
telemetry_status
	 timestamp
	 heartbeat_time
	 telem_time
	 rxerrors
	 fixed
	 type
	 rssi
	 remote_rssi
	 noise
	 remote_noise
	 txbuf
	 system_id
	 component_id
system_power
	 timestamp
	 voltage5V_v
	 voltage3V3_v
	 v3v3_valid
	 usb_connected
	 brick_valid
	 usb_valid
	 servo_valid
	 periph_5V_OC
	 hipower_5V_OC
sensor_preflight
	 timestamp
	 accel_inconsistency_m_s_s
	 gyro_inconsistency_rad_s
	 mag_inconsistency_ga
sensor_combined
	 timestamp
	 gyro_rad[0]
	 gyro_rad[1]
	 gyro_rad[2]
	 gyro_integral_dt
	 accelerometer_timestamp_relative
	 accelerometer_m_s2[0]
	 accelerometer_m_s2[1]
	 accelerometer_m_s2[2]
	 accelerometer_integral_dt
safety
	 timestamp
	 safety_switch_available
	 safety_off
	 override_available
	 override_enabled
rate_ctrl_status
	 timestamp
	 rollspeed
	 pitchspeed
	 yawspeed
	 rollspeed_integ
	 pitchspeed_integ
	 yawspeed_integ
	 additional_integ1
manual_control_setpoint
	 timestamp
	 x
	 y
	 z
	 r
	 flaps
	 aux1
	 aux2
	 aux3
	 aux4
	 aux5
	 mode_switch
	 return_switch
	 rattitude_switch
	 posctl_switch
	 loiter_switch
	 acro_switch
	 offboard_switch
	 kill_switch
	 arm_switch
	 transition_switch
	 gear_switch
	 mode_slot
	 data_source
	 stab_switch
	 man_switch
input_rc
	 timestamp
	 timestamp_last_signal
	 channel_count
	 rssi
	 rc_lost_frame_count
	 rc_total_frame_count
	 rc_ppm_frame_length
	 values[0]
	 values[1]
	 values[2]
	 values[3]
	 values[4]
	 values[5]
	 values[6]
	 values[7]
	 values[8]
	 values[9]
	 values[10]
	 values[11]
	 values[12]
	 values[13]
	 values[14]
	 values[15]
	 values[16]
	 values[17]
	 rc_failsafe
	 rc_lost
	 input_source
home_position
	 timestamp
	 lat
	 lon
	 alt
	 x
	 y
	 z
	 yaw
	 valid_alt
	 valid_hpos
	 manual_home
estimator_status
	 timestamp
	 states[0]
	 states[1]
	 states[2]
	 states[3]
	 states[4]
	 states[5]
	 states[6]
	 states[7]
	 states[8]
	 states[9]
	 states[10]
	 states[11]
	 states[12]
	 states[13]
	 states[14]
	 states[15]
	 states[16]
	 states[17]
	 states[18]
	 states[19]
	 states[20]
	 states[21]
	 states[22]
	 states[23]
	 n_states
	 vibe[0]
	 vibe[1]
	 vibe[2]
	 covariances[0]
	 covariances[1]
	 covariances[2]
	 covariances[3]
	 covariances[4]
	 covariances[5]
	 covariances[6]
	 covariances[7]
	 covariances[8]
	 covariances[9]
	 covariances[10]
	 covariances[11]
	 covariances[12]
	 covariances[13]
	 covariances[14]
	 covariances[15]
	 covariances[16]
	 covariances[17]
	 covariances[18]
	 covariances[19]
	 covariances[20]
	 covariances[21]
	 covariances[22]
	 covariances[23]
	 control_mode_flags
	 pos_horiz_accuracy
	 pos_vert_accuracy
	 mag_test_ratio
	 vel_test_ratio
	 pos_test_ratio
	 hgt_test_ratio
	 tas_test_ratio
	 hagl_test_ratio
	 beta_test_ratio
	 time_slip
	 gps_check_fail_flags
	 filter_fault_flags
	 innovation_check_flags
	 solution_status_flags
	 nan_flags
	 health_flags
	 timeout_flags
	 pre_flt_fail
ekf2_innovations
	 timestamp
	 vel_pos_innov[0]
	 vel_pos_innov[1]
	 vel_pos_innov[2]
	 vel_pos_innov[3]
	 vel_pos_innov[4]
	 vel_pos_innov[5]
	 mag_innov[0]
	 mag_innov[1]
	 mag_innov[2]
	 heading_innov
	 airspeed_innov
	 beta_innov
	 flow_innov[0]
	 flow_innov[1]
	 hagl_innov
	 vel_pos_innov_var[0]
	 vel_pos_innov_var[1]
	 vel_pos_innov_var[2]
	 vel_pos_innov_var[3]
	 vel_pos_innov_var[4]
	 vel_pos_innov_var[5]
	 mag_innov_var[0]
	 mag_innov_var[1]
	 mag_innov_var[2]
	 heading_innov_var
	 airspeed_innov_var
	 beta_innov_var
	 flow_innov_var[0]
	 flow_innov_var[1]
	 hagl_innov_var
	 output_tracking_error[0]
	 output_tracking_error[1]
	 output_tracking_error[2]
	 drag_innov[0]
	 drag_innov[1]
	 drag_innov_var[0]
	 drag_innov_var[1]
	 aux_vel_innov[0]
	 aux_vel_innov[1]
distance_sensor
	 timestamp
	 min_distance
	 max_distance
	 current_distance
	 covariance
	 type
	 id
	 orientation
cpuload
	 timestamp
	 load
	 ram_usage
battery_status
	 timestamp
	 voltage_v
	 voltage_filtered_v
	 current_a
	 current_filtered_a
	 average_current_a
	 discharged_mah
	 remaining
	 scale
	 temperature
	 cell_count
	 capacity
	 cycle_count
	 run_time_to_empty
	 average_time_to_empty
	 serial_number
	 connected
	 system_source
	 priority
	 is_powering_off
	 warning
actuator_outputs
	 timestamp
	 noutputs
	 output[0]
	 output[1]
	 output[2]
	 output[3]
	 output[4]
	 output[5]
	 output[6]
	 output[7]
	 output[8]
	 output[9]
	 output[10]
	 output[11]
	 output[12]
	 output[13]
	 output[14]
	 output[15]
actuator_outputs
	 timestamp
	 noutputs
	 output[0]
	 output[1]
	 output[2]
	 output[3]
	 output[4]
	 output[5]
	 output[6]
	 output[7]
	 output[8]
	 output[9]
	 output[10]
	 output[11]
	 output[12]
	 output[13]
	 output[14]
	 output[15]
actuator_controls_0
	 timestamp
	 timestamp_sample
	 control[0]
	 control[1]
	 control[2]
	 control[3]
	 control[4]
	 control[5]
	 control[6]
	 control[7]
In [8]:
ld = log.get_dataset('vehicle_land_detected').data
plt.plot(ld['timestamp']/1e6, ld['landed'])
Out[8]:
[<matplotlib.lines.Line2D at 0x7f160f3ef760>]
In [9]:
log.get_dataset('vehicle_status').data.keys()
Out[9]:
dict_keys(['timestamp', 'onboard_control_sensors_present', 'onboard_control_sensors_enabled', 'onboard_control_sensors_health', 'nav_state', 'arming_state', 'hil_state', 'failsafe', 'system_type', 'system_id', 'component_id', 'is_rotary_wing', 'is_vtol', 'vtol_fw_permanent_stab', 'in_transition_mode', 'in_transition_to_fw', 'rc_signal_lost', 'rc_input_mode', 'data_link_lost', 'high_latency_data_link_active', 'data_link_lost_counter', 'engine_failure', 'mission_failure'])

Plot the raw x acceleration, about the aircraft roll axis

In [10]:
sensor = log.get_dataset('sensor_combined')
In [11]:
accx = sensor.data['accelerometer_m_s2[0]']
t = sensor.data['timestamp']/1.0e6
plt.figure(figsize=(10, 5))
plt.plot(t, accx)
plt.gca().set_ylim(-10, 10)
plt.grid()
plt.xlabel('t, sec')
plt.ylabel('accel m/s^2')
Out[11]:
Text(0, 0.5, 'accel m/s^2')

Compute the Sample Time

In [12]:
plt.plot(np.diff(t))
Ts = np.mean(np.diff(t))
Ts, 1/Ts
Out[12]:
(0.004021126940387619, 248.68650376493818)

Find the Vibrational Frequencies

In [13]:
plot(accx)
Out[13]:
[<matplotlib.lines.Line2D at 0x7f160f332eb0>]
In [14]:
ak = fft.ifft(accx)
plot(abs(ak)**2)
ak[1]
Out[14]:
(0.01587309348631112+0.06375614616420029j)
In [15]:
def power_spectrum(t, y, dB=False):
    n = len(y)
    ak = np.fft.ifft(y)
    n_half = int(np.ceil(n/2))
    freq = np.fft.fftfreq(n, Ts)
    
    if dB:
        amp_dB = 20*np.log10(np.abs(ak[:n_half]))
        plt.plot(freq[:n_half], amp_dB)
        plt.ylabel('dB')
    else:
        amp_power = np.abs(np.abs(ak[:n_half]))**2
        plt.plot(freq[:n_half], amp_power)
        plt.ylabel('power')
    
    plt.xlabel('freq, Hz')
    plt.title('power spectrum')
    plt.grid()
In [16]:
power_spectrum(t, accx)
In [17]:
power_spectrum(t, accx, dB=True)
In [18]:
test_sig = 0.5 + np.sin(2*np.pi*20*t) + np.sin(2*np.pi*10*t)
power_spectrum(t, test_sig)