aboutsummaryrefslogtreecommitdiff
path: root/src/drivers/px4flow/px4flow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/px4flow/px4flow.cpp')
-rw-r--r--src/drivers/px4flow/px4flow.cpp568
1 files changed, 333 insertions, 235 deletions
diff --git a/src/drivers/px4flow/px4flow.cpp b/src/drivers/px4flow/px4flow.cpp
index f214b5964..09ec4bf96 100644
--- a/src/drivers/px4flow/px4flow.cpp
+++ b/src/drivers/px4flow/px4flow.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * Copyright (c) 2013 PX4 Development Team. All rights reserved.
+ * Copyright (c) 2013, 2014 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,7 +37,7 @@
*
* Driver for the PX4FLOW module connected via I2C.
*/
-
+
#include <nuttx/config.h>
#include <drivers/device/i2c.h>
@@ -68,20 +68,18 @@
#include <uORB/uORB.h>
#include <uORB/topics/subsystem_info.h>
-//#include <uORB/topics/optical_flow.h>
+#include <uORB/topics/optical_flow.h>
#include <board_config.h>
/* Configuration Constants */
-#define PX4FLOW_BUS PX4_I2C_BUS_EXPANSION
#define I2C_FLOW_ADDRESS 0x42 //* 7-bit address. 8-bit address is 0x84
//range 0x42 - 0x49
/* PX4FLOW Registers addresses */
-#define PX4FLOW_REG 0x00 /* Measure Register */
-
-#define PX4FLOW_CONVERSION_INTERVAL 8000 /* 8ms 125Hz
+#define PX4FLOW_REG 0x16 /* Measure Register 22*/
+#define PX4FLOW_CONVERSION_INTERVAL 20000 //in microseconds! 20000 = 50 Hz 100000 = 10Hz
/* oddly, ERROR is not defined for c++ */
#ifdef ERROR
# undef ERROR
@@ -92,40 +90,54 @@ static const int ERROR = -1;
# error This requires CONFIG_SCHED_WORKQUEUE.
#endif
-//struct i2c_frame
-//{
-// uint16_t frame_count;
-// int16_t pixel_flow_x_sum;
-// int16_t pixel_flow_y_sum;
-// int16_t flow_comp_m_x;
-// int16_t flow_comp_m_y;
-// int16_t qual;
-// int16_t gyro_x_rate;
-// int16_t gyro_y_rate;
-// int16_t gyro_z_rate;
-// uint8_t gyro_range;
-// uint8_t sonar_timestamp;
-// int16_t ground_distance;
-//};
-//
-//struct i2c_frame f;
-
-class PX4FLOW : public device::I2C
+struct i2c_frame {
+ uint16_t frame_count;
+ int16_t pixel_flow_x_sum;
+ int16_t pixel_flow_y_sum;
+ int16_t flow_comp_m_x;
+ int16_t flow_comp_m_y;
+ int16_t qual;
+ int16_t gyro_x_rate;
+ int16_t gyro_y_rate;
+ int16_t gyro_z_rate;
+ uint8_t gyro_range;
+ uint8_t sonar_timestamp;
+ int16_t ground_distance;
+};
+struct i2c_frame f;
+
+typedef struct i2c_integral_frame {
+ uint16_t frame_count_since_last_readout;
+ int16_t pixel_flow_x_integral;
+ int16_t pixel_flow_y_integral;
+ int16_t gyro_x_rate_integral;
+ int16_t gyro_y_rate_integral;
+ int16_t gyro_z_rate_integral;
+ uint32_t integration_timespan;
+ uint32_t time_since_last_sonar_update;
+ uint16_t ground_distance;
+ int16_t gyro_temperature;
+ uint8_t qual;
+} __attribute__((packed));
+struct i2c_integral_frame f_integral;
+
+
+class PX4FLOW: public device::I2C
{
public:
- PX4FLOW(int bus = PX4FLOW_BUS, int address = I2C_FLOW_ADDRESS);
+ PX4FLOW(int bus, int address = I2C_FLOW_ADDRESS);
virtual ~PX4FLOW();
-
+
virtual int init();
-
+
virtual ssize_t read(struct file *filp, char *buffer, size_t buflen);
virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
-
+
/**
- * Diagnostics - print some basic information about the driver.
- */
+ * Diagnostics - print some basic information about the driver.
+ */
void print_info();
-
+
protected:
virtual int probe();
@@ -136,51 +148,50 @@ private:
bool _sensor_ok;
int _measure_ticks;
bool _collect_phase;
-
+
orb_advert_t _px4flow_topic;
perf_counter_t _sample_perf;
perf_counter_t _comms_errors;
perf_counter_t _buffer_overflows;
-
+
/**
- * Test whether the device supported by the driver is present at a
- * specific address.
- *
- * @param address The I2C bus address to probe.
- * @return True if the device is present.
- */
+ * Test whether the device supported by the driver is present at a
+ * specific address.
+ *
+ * @param address The I2C bus address to probe.
+ * @return True if the device is present.
+ */
int probe_address(uint8_t address);
-
+
/**
- * Initialise the automatic measurement state machine and start it.
- *
- * @note This function is called at open and error time. It might make sense
- * to make it more aggressive about resetting the bus in case of errors.
- */
+ * Initialise the automatic measurement state machine and start it.
+ *
+ * @note This function is called at open and error time. It might make sense
+ * to make it more aggressive about resetting the bus in case of errors.
+ */
void start();
-
+
/**
- * Stop the automatic measurement state machine.
- */
+ * Stop the automatic measurement state machine.
+ */
void stop();
-
+
/**
- * Perform a poll cycle; collect from the previous measurement
- * and start a new one.
- */
+ * Perform a poll cycle; collect from the previous measurement
+ * and start a new one.
+ */
void cycle();
int measure();
int collect();
/**
- * Static trampoline from the workq context; because we don't have a
- * generic workq wrapper yet.
- *
- * @param arg Instance pointer for the driver that is polling.
- */
- static void cycle_trampoline(void *arg);
-
-
+ * Static trampoline from the workq context; because we don't have a
+ * generic workq wrapper yet.
+ *
+ * @param arg Instance pointer for the driver that is polling.
+ */
+ static void cycle_trampoline(void *arg);
+
};
/*
@@ -189,7 +200,7 @@ private:
extern "C" __EXPORT int px4flow_main(int argc, char *argv[]);
PX4FLOW::PX4FLOW(int bus, int address) :
- I2C("PX4FLOW", PX4FLOW_DEVICE_PATH, bus, address, 400000),//400khz
+ I2C("PX4FLOW", PX4FLOW_DEVICE_PATH, bus, address, 400000), //400khz
_reports(nullptr),
_sensor_ok(false),
_measure_ticks(0),
@@ -200,8 +211,8 @@ PX4FLOW::PX4FLOW(int bus, int address) :
_buffer_overflows(perf_alloc(PC_COUNT, "px4flow_buffer_overflows"))
{
// enable debug() calls
- _debug_enabled = true;
-
+ _debug_enabled = false;
+
// work_cancel in the dtor will explode if we don't do this...
memset(&_work, 0, sizeof(_work));
}
@@ -212,8 +223,9 @@ PX4FLOW::~PX4FLOW()
stop();
/* free any existing reports */
- if (_reports != nullptr)
+ if (_reports != nullptr) {
delete _reports;
+ }
}
int
@@ -222,22 +234,16 @@ PX4FLOW::init()
int ret = ERROR;
/* do I2C init (and probe) first */
- if (I2C::init() != OK)
+ if (I2C::init() != OK) {
goto out;
+ }
/* allocate basic report buffers */
- _reports = new RingBuffer(2, sizeof(px4flow_report));
+ _reports = new RingBuffer(2, sizeof(optical_flow_s));
- if (_reports == nullptr)
+ if (_reports == nullptr) {
goto out;
-
- /* get a publish handle on the px4flow topic */
- struct px4flow_report zero_report;
- memset(&zero_report, 0, sizeof(zero_report));
- _px4flow_topic = orb_advertise(ORB_ID(optical_flow), &zero_report);
-
- if (_px4flow_topic < 0)
- debug("failed to create px4flow object. Did you start uOrb?");
+ }
ret = OK;
/* sensor is ok, but we don't really know if it is within range */
@@ -249,6 +255,17 @@ out:
int
PX4FLOW::probe()
{
+ uint8_t val[22];
+
+ // to be sure this is not a ll40ls Lidar (which can also be on
+ // 0x42) we check if a 22 byte transfer works from address
+ // 0. The ll40ls gives an error for that, whereas the flow
+ // happily returns some data
+ if (transfer(nullptr, 0, &val[0], 22) != OK) {
+ return -EIO;
+ }
+
+ // that worked, so start a measurement cycle
return measure();
}
@@ -260,20 +277,20 @@ PX4FLOW::ioctl(struct file *filp, int cmd, unsigned long arg)
case SENSORIOCSPOLLRATE: {
switch (arg) {
- /* switching to manual polling */
+ /* switching to manual polling */
case SENSOR_POLLRATE_MANUAL:
stop();
_measure_ticks = 0;
return OK;
- /* external signalling (DRDY) not supported */
+ /* external signalling (DRDY) not supported */
case SENSOR_POLLRATE_EXTERNAL:
- /* zero would be bad */
+ /* zero would be bad */
case 0:
return -EINVAL;
- /* set default/max polling rate */
+ /* set default/max polling rate */
case SENSOR_POLLRATE_MAX:
case SENSOR_POLLRATE_DEFAULT: {
/* do we need to start internal polling? */
@@ -283,13 +300,14 @@ PX4FLOW::ioctl(struct file *filp, int cmd, unsigned long arg)
_measure_ticks = USEC2TICK(PX4FLOW_CONVERSION_INTERVAL);
/* if we need to start the poll state machine, do it */
- if (want_start)
+ if (want_start) {
start();
+ }
return OK;
}
- /* adjust to a legal polling interval in Hz */
+ /* adjust to a legal polling interval in Hz */
default: {
/* do we need to start internal polling? */
bool want_start = (_measure_ticks == 0);
@@ -298,15 +316,17 @@ PX4FLOW::ioctl(struct file *filp, int cmd, unsigned long arg)
unsigned ticks = USEC2TICK(1000000 / arg);
/* check against maximum rate */
- if (ticks < USEC2TICK(PX4FLOW_CONVERSION_INTERVAL))
+ if (ticks < USEC2TICK(PX4FLOW_CONVERSION_INTERVAL)) {
return -EINVAL;
+ }
/* update interval for next measurement */
_measure_ticks = ticks;
/* if we need to start the poll state machine, do it */
- if (want_start)
+ if (want_start) {
start();
+ }
return OK;
}
@@ -314,33 +334,37 @@ PX4FLOW::ioctl(struct file *filp, int cmd, unsigned long arg)
}
case SENSORIOCGPOLLRATE:
- if (_measure_ticks == 0)
+ if (_measure_ticks == 0) {
return SENSOR_POLLRATE_MANUAL;
+ }
return (1000 / _measure_ticks);
case SENSORIOCSQUEUEDEPTH: {
- /* lower bound is mandatory, upper bound is a sanity check */
- if ((arg < 1) || (arg > 100))
- return -EINVAL;
-
- irqstate_t flags = irqsave();
- if (!_reports->resize(arg)) {
+ /* lower bound is mandatory, upper bound is a sanity check */
+ if ((arg < 1) || (arg > 100)) {
+ return -EINVAL;
+ }
+
+ irqstate_t flags = irqsave();
+
+ if (!_reports->resize(arg)) {
+ irqrestore(flags);
+ return -ENOMEM;
+ }
+
irqrestore(flags);
- return -ENOMEM;
+
+ return OK;
}
- irqrestore(flags);
-
- return OK;
- }
case SENSORIOCGQUEUEDEPTH:
return _reports->size();
-
+
case SENSORIOCRESET:
/* XXX implement this */
return -EINVAL;
-
+
default:
/* give it to the superclass */
return I2C::ioctl(filp, cmd, arg);
@@ -350,13 +374,14 @@ PX4FLOW::ioctl(struct file *filp, int cmd, unsigned long arg)
ssize_t
PX4FLOW::read(struct file *filp, char *buffer, size_t buflen)
{
- unsigned count = buflen / sizeof(struct px4flow_report);
- struct px4flow_report *rbuf = reinterpret_cast<struct px4flow_report *>(buffer);
+ unsigned count = buflen / sizeof(struct optical_flow_s);
+ struct optical_flow_s *rbuf = reinterpret_cast<struct optical_flow_s *>(buffer);
int ret = 0;
/* buffer must be large enough */
- if (count < 1)
+ if (count < 1) {
return -ENOSPC;
+ }
/* if automatic measurement is enabled */
if (_measure_ticks > 0) {
@@ -387,9 +412,6 @@ PX4FLOW::read(struct file *filp, char *buffer, size_t buflen)
break;
}
- /* wait for it to complete */
- usleep(PX4FLOW_CONVERSION_INTERVAL);
-
/* run the collection phase */
if (OK != collect()) {
ret = -EIO;
@@ -417,68 +439,110 @@ PX4FLOW::measure()
uint8_t cmd = PX4FLOW_REG;
ret = transfer(&cmd, 1, nullptr, 0);
- if (OK != ret)
- {
+ if (OK != ret) {
perf_count(_comms_errors);
- log("i2c::transfer returned %d", ret);
- printf("i2c::transfer flow returned %d");
+ debug("i2c::transfer returned %d", ret);
return ret;
}
+
ret = OK;
-
+
return ret;
}
int
PX4FLOW::collect()
{
- int ret = -EIO;
-
+ int ret = -EIO;
+
/* read from the sensor */
- uint8_t val[22] = {0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0};
-
+ uint8_t val[47] = { 0 };
+
perf_begin(_sample_perf);
-
- ret = transfer(nullptr, 0, &val[0], 22);
-
- if (ret < 0)
- {
- log("error reading from sensor: %d", ret);
+
+ if (PX4FLOW_REG == 0x00) {
+ ret = transfer(nullptr, 0, &val[0], 47); // read 47 bytes (22+25 : frame1 + frame2)
+ }
+
+ if (PX4FLOW_REG == 0x16) {
+ ret = transfer(nullptr, 0, &val[0], 25); // read 25 bytes (only frame2)
+ }
+
+ if (ret < 0) {
+ debug("error reading from sensor: %d", ret);
perf_count(_comms_errors);
perf_end(_sample_perf);
return ret;
}
-
-// f.frame_count = val[1] << 8 | val[0];
-// f.pixel_flow_x_sum= val[3] << 8 | val[2];
-// f.pixel_flow_y_sum= val[5] << 8 | val[4];
-// f.flow_comp_m_x= val[7] << 8 | val[6];
-// f.flow_comp_m_y= val[9] << 8 | val[8];
-// f.qual= val[11] << 8 | val[10];
-// f.gyro_x_rate= val[13] << 8 | val[12];
-// f.gyro_y_rate= val[15] << 8 | val[14];
-// f.gyro_z_rate= val[17] << 8 | val[16];
-// f.gyro_range= val[18];
-// f.sonar_timestamp= val[19];
-// f.ground_distance= val[21] << 8 | val[20];
-
- int16_t flowcx = val[7] << 8 | val[6];
- int16_t flowcy = val[9] << 8 | val[8];
- int16_t gdist = val[21] << 8 | val[20];
-
- struct px4flow_report report;
- report.flow_comp_x_m = float(flowcx)/1000.0f;
- report.flow_comp_y_m = float(flowcy)/1000.0f;
- report.flow_raw_x= val[3] << 8 | val[2];
- report.flow_raw_y= val[5] << 8 | val[4];
- report.ground_distance_m =float(gdist)/1000.0f;
- report.quality= val[10];
- report.sensor_id = 0;
+
+ if (PX4FLOW_REG == 0) {
+ f.frame_count = val[1] << 8 | val[0];
+ f.pixel_flow_x_sum = val[3] << 8 | val[2];
+ f.pixel_flow_y_sum = val[5] << 8 | val[4];
+ f.flow_comp_m_x = val[7] << 8 | val[6];
+ f.flow_comp_m_y = val[9] << 8 | val[8];
+ f.qual = val[11] << 8 | val[10];
+ f.gyro_x_rate = val[13] << 8 | val[12];
+ f.gyro_y_rate = val[15] << 8 | val[14];
+ f.gyro_z_rate = val[17] << 8 | val[16];
+ f.gyro_range = val[18];
+ f.sonar_timestamp = val[19];
+ f.ground_distance = val[21] << 8 | val[20];
+
+ f_integral.frame_count_since_last_readout = val[23] << 8 | val[22];
+ f_integral.pixel_flow_x_integral = val[25] << 8 | val[24];
+ f_integral.pixel_flow_y_integral = val[27] << 8 | val[26];
+ f_integral.gyro_x_rate_integral = val[29] << 8 | val[28];
+ f_integral.gyro_y_rate_integral = val[31] << 8 | val[30];
+ f_integral.gyro_z_rate_integral = val[33] << 8 | val[32];
+ f_integral.integration_timespan = val[37] << 24 | val[36] << 16
+ | val[35] << 8 | val[34];
+ f_integral.time_since_last_sonar_update = val[41] << 24 | val[40] << 16
+ | val[39] << 8 | val[38];
+ f_integral.ground_distance = val[43] << 8 | val[42];
+ f_integral.gyro_temperature = val[45] << 8 | val[44];
+ f_integral.qual = val[46];
+ }
+
+ if (PX4FLOW_REG == 0x16) {
+ f_integral.frame_count_since_last_readout = val[1] << 8 | val[0];
+ f_integral.pixel_flow_x_integral = val[3] << 8 | val[2];
+ f_integral.pixel_flow_y_integral = val[5] << 8 | val[4];
+ f_integral.gyro_x_rate_integral = val[7] << 8 | val[6];
+ f_integral.gyro_y_rate_integral = val[9] << 8 | val[8];
+ f_integral.gyro_z_rate_integral = val[11] << 8 | val[10];
+ f_integral.integration_timespan = val[15] << 24 | val[14] << 16 | val[13] << 8 | val[12];
+ f_integral.time_since_last_sonar_update = val[19] << 24 | val[18] << 16 | val[17] << 8 | val[16];
+ f_integral.ground_distance = val[21] << 8 | val[20];
+ f_integral.gyro_temperature = val[23] << 8 | val[22];
+ f_integral.qual = val[24];
+ }
+
+
+ struct optical_flow_s report;
+
report.timestamp = hrt_absolute_time();
+ report.pixel_flow_x_integral = static_cast<float>(f_integral.pixel_flow_x_integral) / 10000.0f;//convert to radians
+ report.pixel_flow_y_integral = static_cast<float>(f_integral.pixel_flow_y_integral) / 10000.0f;//convert to radians
+ report.frame_count_since_last_readout = f_integral.frame_count_since_last_readout;
+ report.ground_distance_m = static_cast<float>(f_integral.ground_distance) / 1000.0f;//convert to meters
+ report.quality = f_integral.qual; //0:bad ; 255 max quality
+ report.gyro_x_rate_integral = static_cast<float>(f_integral.gyro_x_rate_integral) / 10000.0f; //convert to radians
+ report.gyro_y_rate_integral = static_cast<float>(f_integral.gyro_y_rate_integral) / 10000.0f; //convert to radians
+ report.gyro_z_rate_integral = static_cast<float>(f_integral.gyro_z_rate_integral) / 10000.0f; //convert to radians
+ report.integration_timespan = f_integral.integration_timespan; //microseconds
+ report.time_since_last_sonar_update = f_integral.time_since_last_sonar_update;//microseconds
+ report.gyro_temperature = f_integral.gyro_temperature;//Temperature * 100 in centi-degrees Celsius
+ report.sensor_id = 0;
+
+ if (_px4flow_topic < 0) {
+ _px4flow_topic = orb_advertise(ORB_ID(optical_flow), &report);
- /* publish it */
- orb_publish(ORB_ID(optical_flow), _px4flow_topic, &report);
+ } else {
+ /* publish it */
+ orb_publish(ORB_ID(optical_flow), _px4flow_topic, &report);
+ }
/* post a report to the ring */
if (_reports->force(&report)) {
@@ -503,17 +567,19 @@ PX4FLOW::start()
/* schedule a cycle to start things */
work_queue(HPWORK, &_work, (worker_t)&PX4FLOW::cycle_trampoline, this, 1);
-
+
/* notify about state change */
struct subsystem_info_s info = {
true,
true,
true,
- SUBSYSTEM_TYPE_OPTICALFLOW};
+ SUBSYSTEM_TYPE_OPTICALFLOW
+ };
static orb_advert_t pub = -1;
if (pub > 0) {
orb_publish(ORB_ID(subsystem_info), pub, &info);
+
} else {
pub = orb_advertise(ORB_ID(subsystem_info), &info);
}
@@ -536,49 +602,21 @@ PX4FLOW::cycle_trampoline(void *arg)
void
PX4FLOW::cycle()
{
- /* collection phase? */
- if (_collect_phase) {
-
- /* perform collection */
- if (OK != collect()) {
- log("collection error");
- /* restart the measurement state machine */
- start();
- return;
- }
-
- /* next phase is measurement */
- _collect_phase = false;
-
- /*
- * Is there a collect->measure gap?
- */
- if (_measure_ticks > USEC2TICK(PX4FLOW_CONVERSION_INTERVAL)) {
-
- /* schedule a fresh cycle call when we are ready to measure again */
- work_queue(HPWORK,
- &_work,
- (worker_t)&PX4FLOW::cycle_trampoline,
- this,
- _measure_ticks - USEC2TICK(PX4FLOW_CONVERSION_INTERVAL));
-
- return;
- }
+ if (OK != measure()) {
+ debug("measure error");
}
- /* measurement phase */
- if (OK != measure())
- log("measure error");
+ /* perform collection */
+ if (OK != collect()) {
+ debug("collection error");
+ /* restart the measurement state machine */
+ start();
+ return;
+ }
- /* next phase is collection */
- _collect_phase = true;
+ work_queue(HPWORK, &_work, (worker_t)&PX4FLOW::cycle_trampoline, this,
+ _measure_ticks);
- /* schedule a fresh cycle call when the measurement is done */
- work_queue(HPWORK,
- &_work,
- (worker_t)&PX4FLOW::cycle_trampoline,
- this,
- USEC2TICK(PX4FLOW_CONVERSION_INTERVAL));
}
void
@@ -619,33 +657,64 @@ start()
{
int fd;
- if (g_dev != nullptr)
+ if (g_dev != nullptr) {
errx(1, "already started");
+ }
/* create the driver */
- g_dev = new PX4FLOW(PX4FLOW_BUS);
+ g_dev = new PX4FLOW(PX4_I2C_BUS_EXPANSION);
- if (g_dev == nullptr)
+ if (g_dev == nullptr) {
goto fail;
+ }
- if (OK != g_dev->init())
- goto fail;
+ if (OK != g_dev->init()) {
+
+ #ifdef PX4_I2C_BUS_ESC
+ delete g_dev;
+ /* try 2nd bus */
+ g_dev = new PX4FLOW(PX4_I2C_BUS_ESC);
+
+ if (g_dev == nullptr) {
+ goto fail;
+ }
+
+ if (OK != g_dev->init()) {
+ #endif
+
+ delete g_dev;
+ /* try 3rd bus */
+ g_dev = new PX4FLOW(PX4_I2C_BUS_ONBOARD);
+
+ if (g_dev == nullptr) {
+ goto fail;
+ }
+
+ if (OK != g_dev->init()) {
+ goto fail;
+ }
+
+ #ifdef PX4_I2C_BUS_ESC
+ }
+ #endif
+ }
/* set the poll rate to default, starts automatic data collection */
fd = open(PX4FLOW_DEVICE_PATH, O_RDONLY);
- if (fd < 0)
+ if (fd < 0) {
goto fail;
+ }
- if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_MAX) < 0)
+ if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_MAX) < 0) {
goto fail;
+ }
exit(0);
fail:
- if (g_dev != nullptr)
- {
+ if (g_dev != nullptr) {
delete g_dev;
g_dev = nullptr;
}
@@ -656,17 +725,17 @@ fail:
/**
* Stop the driver
*/
-void stop()
+void
+stop()
{
- if (g_dev != nullptr)
- {
+ if (g_dev != nullptr) {
delete g_dev;
g_dev = nullptr;
- }
- else
- {
+
+ } else {
errx(1, "driver not running");
}
+
exit(0);
}
@@ -678,33 +747,38 @@ void stop()
void
test()
{
- struct px4flow_report report;
+ struct optical_flow_s report;
ssize_t sz;
int ret;
int fd = open(PX4FLOW_DEVICE_PATH, O_RDONLY);
- if (fd < 0)
+ if (fd < 0) {
err(1, "%s open failed (try 'px4flow start' if the driver is not running", PX4FLOW_DEVICE_PATH);
+ }
+
/* do a simple demand read */
sz = read(fd, &report, sizeof(report));
if (sz != sizeof(report))
- // err(1, "immediate read failed");
+ {
+ warnx("immediate read failed");
+ }
warnx("single read");
- warnx("flowx: %0.2f m/s", (double)report.flow_comp_x_m);
- warnx("flowy: %0.2f m/s", (double)report.flow_comp_y_m);
- warnx("time: %lld", report.timestamp);
-
-
- /* start the sensor polling at 2Hz */
- if (OK != ioctl(fd, SENSORIOCSPOLLRATE, 2))
- errx(1, "failed to set 2Hz poll rate");
+ warnx("pixel_flow_x_integral: %i", f_integral.pixel_flow_x_integral);
+ warnx("pixel_flow_y_integral: %i", f_integral.pixel_flow_y_integral);
+ warnx("framecount_integral: %u",
+ f_integral.frame_count_since_last_readout);
+
+ /* start the sensor polling at 10Hz */
+ if (OK != ioctl(fd, SENSORIOCSPOLLRATE, 10)) {
+ errx(1, "failed to set 10Hz poll rate");
+ }
/* read the sensor 5x and report each value */
- for (unsigned i = 0; i < 5; i++) {
+ for (unsigned i = 0; i < 10; i++) {
struct pollfd fds;
/* wait for data to be ready */
@@ -712,19 +786,34 @@ test()
fds.events = POLLIN;
ret = poll(&fds, 1, 2000);
- if (ret != 1)
+ if (ret != 1) {
errx(1, "timed out waiting for sensor data");
+ }
/* now go get it */
sz = read(fd, &report, sizeof(report));
- if (sz != sizeof(report))
+ if (sz != sizeof(report)) {
err(1, "periodic read failed");
+ }
warnx("periodic read %u", i);
- warnx("flowx: %0.2f m/s", (double)report.flow_comp_x_m);
- warnx("flowy: %0.2f m/s", (double)report.flow_comp_y_m);
- warnx("time: %lld", report.timestamp);
+
+ warnx("framecount_total: %u", f.frame_count);
+ warnx("framecount_integral: %u",
+ f_integral.frame_count_since_last_readout);
+ warnx("pixel_flow_x_integral: %i", f_integral.pixel_flow_x_integral);
+ warnx("pixel_flow_y_integral: %i", f_integral.pixel_flow_y_integral);
+ warnx("gyro_x_rate_integral: %i", f_integral.gyro_x_rate_integral);
+ warnx("gyro_y_rate_integral: %i", f_integral.gyro_y_rate_integral);
+ warnx("gyro_z_rate_integral: %i", f_integral.gyro_z_rate_integral);
+ warnx("integration_timespan [us]: %u", f_integral.integration_timespan);
+ warnx("ground_distance: %0.2f m",
+ (double) f_integral.ground_distance / 1000);
+ warnx("time since last sonar update [us]: %i",
+ f_integral.time_since_last_sonar_update);
+ warnx("quality integration average : %i", f_integral.qual);
+ warnx("quality : %i", f.qual);
}
@@ -740,14 +829,17 @@ reset()
{
int fd = open(PX4FLOW_DEVICE_PATH, O_RDONLY);
- if (fd < 0)
+ if (fd < 0) {
err(1, "failed ");
+ }
- if (ioctl(fd, SENSORIOCRESET, 0) < 0)
+ if (ioctl(fd, SENSORIOCRESET, 0) < 0) {
err(1, "driver reset failed");
+ }
- if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0)
+ if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) {
err(1, "driver poll restart failed");
+ }
exit(0);
}
@@ -758,8 +850,9 @@ reset()
void
info()
{
- if (g_dev == nullptr)
+ if (g_dev == nullptr) {
errx(1, "driver not running");
+ }
printf("state @ %p\n", g_dev);
g_dev->print_info();
@@ -775,32 +868,37 @@ px4flow_main(int argc, char *argv[])
/*
* Start/load the driver.
*/
- if (!strcmp(argv[1], "start"))
+ if (!strcmp(argv[1], "start")) {
px4flow::start();
-
- /*
- * Stop the driver
- */
- if (!strcmp(argv[1], "stop"))
- px4flow::stop();
+ }
+
+ /*
+ * Stop the driver
+ */
+ if (!strcmp(argv[1], "stop")) {
+ px4flow::stop();
+ }
/*
* Test the driver/device.
*/
- if (!strcmp(argv[1], "test"))
+ if (!strcmp(argv[1], "test")) {
px4flow::test();
+ }
/*
* Reset the driver.
*/
- if (!strcmp(argv[1], "reset"))
+ if (!strcmp(argv[1], "reset")) {
px4flow::reset();
+ }
/*
* Print driver information.
*/
- if (!strcmp(argv[1], "info") || !strcmp(argv[1], "status"))
+ if (!strcmp(argv[1], "info") || !strcmp(argv[1], "status")) {
px4flow::info();
+ }
errx(1, "unrecognized command, try 'start', 'test', 'reset' or 'info'");
}