本帖最后由 wilsonleong 于 2020-8-10 15:39 编辑
下面看PX4固件是怎么用PX4FLOW的。
首先通过SENS_EN_PX4FLOW可以启用PX4FLOW模块,先看wiki的描述:
I2C1: latest Flow value (i2c_frame) and accumulated Flow (i2c_integral_frame) values since last I2C readout available for readout.
再看main.c怎么通过I2C发布出来的,这里把速度传进去了:
update_TX_buffer(pixel_flow_x, pixel_flow_y, velocity_x_sum/valid_frame_count, velocity_y_sum/valid_frame_count, qual,
ground_distance, x_rate, y_rate, z_rate, gyro_temp, uavcan_use_export(i2c_data));
进去i2c.c看看update_TX_buffer函数,只有在i2c_frame有速度数据,在i2c_integral_frame没有速度数据。
i2c_frame f;
i2c_integral_frame f_integral;
f.frame_count = frame_count;
f.pixel_flow_x_sum = pixel_flow_x * 10.0f;
f.pixel_flow_y_sum = pixel_flow_y * 10.0f;
f.flow_comp_m_x = flow_comp_m_x * 1000;
f.flow_comp_m_y = flow_comp_m_y * 1000;
f.qual = qual;
f.ground_distance = ground_distance * 1000;
f.gyro_x_rate = gyro_x_rate * getGyroScalingFactor();
f.gyro_y_rate = gyro_y_rate * getGyroScalingFactor();
f.gyro_z_rate = gyro_z_rate * getGyroScalingFactor();
f.gyro_range = getGyroRange();
/* ...... */
lasttime = get_boot_time_us();
f_integral.frame_count_since_last_readout = accumulated_framecount;
f_integral.gyro_x_rate_integral = accumulated_gyro_x * 10.0f; //mrad*10
f_integral.gyro_y_rate_integral = accumulated_gyro_y * 10.0f; //mrad*10
f_integral.gyro_z_rate_integral = accumulated_gyro_z * 10.0f; //mrad*10
f_integral.pixel_flow_x_integral = accumulated_flow_x * 10.0f; //mrad*10
f_integral.pixel_flow_y_integral = accumulated_flow_y * 10.0f; //mrad*10
f_integral.integration_timespan = integration_timespan; //microseconds
f_integral.ground_distance = ground_distance * 1000; //mmeters
f_integral.sonar_timestamp = time_since_last_sonar_update; //microseconds
f_integral.qual =
(uint8_t) (accumulated_quality / accumulated_framecount); //0-255 linear quality measurement 0=bad, 255=best
f_integral.gyro_temperature = gyro_temp;//Temperature * 100 in centi-degrees Celsius
/* ...... */
memcpy(&(txDataFrame1[notpublishedIndexFrame1]),
&f, I2C_FRAME_SIZE);
memcpy(&(txDataFrame2[notpublishedIndexFrame2]),
&f_integral, I2C_INTEGRAL_FRAME_SIZE);
再看optical_flow.msg文件,只有光流数据,没有速度:
uint64 timestamp # time since system start (microseconds)
uint8 sensor_id # id of the sensor emitting the flow value
float32 pixel_flow_x_integral # accumulated optical flow in radians where a positive value is produced by a RH rotation about the X body axis
float32 pixel_flow_y_integral # accumulated optical flow in radians where a positive value is produced by a RH rotation about the Y body axis
float32 gyro_x_rate_integral # accumulated gyro value in radians where a positive value is produced by a RH rotation about the X body axis. Set to NaN if flow sensor does not have 3-axis gyro data.
float32 gyro_y_rate_integral # accumulated gyro value in radians where a positive value is produced by a RH rotation about the Y body axis. Set to NaN if flow sensor does not have 3-axis gyro data.
float32 gyro_z_rate_integral # accumulated gyro value in radians where a positive value is produced by a RH rotation about the Z body axis. Set to NaN if flow sensor does not have 3-axis gyro data.
float32 ground_distance_m # Altitude / distance to ground in meters
uint32 integration_timespan # accumulation timespan in microseconds
uint32 time_since_last_sonar_update # time since last sonar update in microseconds
uint16 frame_count_since_last_readout # number of accumulated frames in timespan
int16 gyro_temperature # Temperature * 100 in centi-degrees Celsius
uint8 quality # Average of quality of accumulated frames, 0: bad quality, 255: maximum quality
float32 max_flow_rate # Magnitude of maximum angular which the optical flow sensor can measure reliably
float32 min_ground_distance # Minimum distance from ground at which the optical flow sensor operates reliably
float32 max_ground_distance # Maximum distance from ground at which the optical flow sensor operates reliably
再看px4flow.cpp,这里只把在i2c_integral_frame的数据发布出来了,所以是没有速度的。另外PX4FLOW不仅可以发布optical_flow.msg,还可以发布distance_sensor.msg(其实optical_flow.msg也有一个ground_distance_m),带声纳的PX4FLOW也可以通过设置SENS_EN_MB12XX来启用声纳。
if (PX4FLOW_REG == 0) {
memcpy(&_frame, val, I2C_FRAME_SIZE);
memcpy(&_frame_integral, &(val[I2C_FRAME_SIZE]), I2C_INTEGRAL_FRAME_SIZE);
}
if (PX4FLOW_REG == 0x16) {
memcpy(&_frame_integral, val, I2C_INTEGRAL_FRAME_SIZE);
}
optical_flow_s report{};
report.timestamp = hrt_absolute_time();
report.pixel_flow_x_integral = static_cast<float>(_frame_integral.pixel_flow_x_integral) / 10000.0f;//convert to radians
report.pixel_flow_y_integral = static_cast<float>(_frame_integral.pixel_flow_y_integral) / 10000.0f;//convert to radians
report.frame_count_since_last_readout = _frame_integral.frame_count_since_last_readout;
report.ground_distance_m = static_cast<float>(_frame_integral.ground_distance) / 1000.0f;//convert to meters
report.quality = _frame_integral.qual; //0:bad ; 255 max quality
report.gyro_x_rate_integral = static_cast<float>(_frame_integral.gyro_x_rate_integral) / 10000.0f; //convert to radians
report.gyro_y_rate_integral = static_cast<float>(_frame_integral.gyro_y_rate_integral) / 10000.0f; //convert to radians
report.gyro_z_rate_integral = static_cast<float>(_frame_integral.gyro_z_rate_integral) / 10000.0f; //convert to radians
report.integration_timespan = _frame_integral.integration_timespan; //microseconds
report.time_since_last_sonar_update = _frame_integral.sonar_timestamp;//microseconds
report.gyro_temperature = _frame_integral.gyro_temperature;//Temperature * 100 in centi-degrees Celsius
report.sensor_id = 0;
report.max_flow_rate = _sensor_max_flow_rate;
report.min_ground_distance = _sensor_min_range;
report.max_ground_distance = _sensor_max_range;
/* rotate measurements in yaw from sensor frame to body frame according to parameter SENS_FLOW_ROT */
float zeroval = 0.0f;
rotate_3f(_sensor_rotation, report.pixel_flow_x_integral, report.pixel_flow_y_integral, zeroval);
rotate_3f(_sensor_rotation, report.gyro_x_rate_integral, report.gyro_y_rate_integral, report.gyro_z_rate_integral);
_px4flow_topic.publish(report);
/* publish to the distance_sensor topic as well */
if (_class_instance == CLASS_DEVICE_PRIMARY) {
distance_sensor_s distance_report{};
distance_report.timestamp = report.timestamp;
distance_report.min_distance = PX4FLOW_MIN_DISTANCE;
distance_report.max_distance = PX4FLOW_MAX_DISTANCE;
distance_report.current_distance = report.ground_distance_m;
distance_report.variance = 0.0f;
distance_report.signal_quality = -1;
distance_report.type = distance_sensor_s::MAV_DISTANCE_SENSOR_ULTRASOUND;
/* TODO: the ID needs to be properly set */
distance_report.id = 0;
distance_report.orientation = _sonar_rotation;
_distance_sensor_topic.publish(distance_report);
}
最后看看EKF2,这里也是只拿光流数据用,没有拿PX4FLOW的速度:
flow.flow_xy_rad(0) = -optical_flow.pixel_flow_x_integral;
flow.flow_xy_rad(1) = -optical_flow.pixel_flow_y_integral;
flow.gyro_xyz(0) = -optical_flow.gyro_x_rate_integral;
flow.gyro_xyz(1) = -optical_flow.gyro_y_rate_integral;
flow.gyro_xyz(2) = -optical_flow.gyro_z_rate_integral;
flow.quality = optical_flow.quality;
flow.dt = 1e-6f * (float)optical_flow.integration_timespan;
flow.time_us = optical_flow.timestamp;
PX4FLOW在内部已经计算的速度,但是PX4固件只拿PX4FLOW的光流数据来用,默认情况下PX4FLOW内部默认不做角速度补偿(PX4FLOW内部参数BFLOW_GYRO_COM);另外如果有需求,PX4固件可以把声纳的数据也拿过来用,不过这算是单独的另外一个传感器使用了。