openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

228 lines
6.1 KiB

#include <cutils/log.h>
#include <hardware/sensors.h>
#include <sys/cdefs.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <utils/Timers.h>
#include <cassert>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include "cereal/messaging/messaging.h"
#include "selfdrive/common/swaglog.h"
#include "selfdrive/common/timing.h"
#include "selfdrive/common/util.h"
// ACCELEROMETER_UNCALIBRATED is only in Android O
// https://developer.android.com/reference/android/hardware/Sensor.html#STRING_TYPE_ACCELEROMETER_UNCALIBRATED
#define SENSOR_ACCELEROMETER 1
#define SENSOR_MAGNETOMETER 2
#define SENSOR_GYRO 4
#define SENSOR_MAGNETOMETER_UNCALIBRATED 3
#define SENSOR_GYRO_UNCALIBRATED 5
#define SENSOR_PROXIMITY 6
#define SENSOR_LIGHT 7
ExitHandler do_exit;
volatile sig_atomic_t re_init_sensors = 0;
namespace {
void sigpipe_handler(int sig) {
LOGE("SIGPIPE received");
re_init_sensors = true;
}
void sensor_loop() {
LOG("*** sensor loop");
uint64_t frame = 0;
bool low_power_mode = false;
while (!do_exit) {
SubMaster sm({"deviceState"});
PubMaster pm({"sensorEvents"});
struct sensors_poll_device_t* device;
struct sensors_module_t* module;
hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
sensors_open(&module->common, &device);
// required
struct sensor_t const* list;
int count = module->get_sensors_list(module, &list);
LOG("%d sensors found", count);
if (getenv("SENSOR_TEST")) {
exit(count);
}
for (int i = 0; i < count; i++) {
LOGD("sensor %4d: %4d %60s %d-%ld us", i, list[i].handle, list[i].name, list[i].minDelay, list[i].maxDelay);
}
std::set<int> sensor_types = {
SENSOR_TYPE_ACCELEROMETER,
SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED,
SENSOR_TYPE_MAGNETIC_FIELD,
SENSOR_TYPE_GYROSCOPE_UNCALIBRATED,
SENSOR_TYPE_GYROSCOPE,
SENSOR_TYPE_PROXIMITY,
SENSOR_TYPE_LIGHT,
};
std::map<int, int64_t> sensors = {
{SENSOR_GYRO_UNCALIBRATED, ms2ns(10)},
{SENSOR_MAGNETOMETER_UNCALIBRATED, ms2ns(100)},
{SENSOR_ACCELEROMETER, ms2ns(10)},
{SENSOR_GYRO, ms2ns(10)},
{SENSOR_MAGNETOMETER, ms2ns(100)},
{SENSOR_PROXIMITY, ms2ns(100)},
{SENSOR_LIGHT, ms2ns(100)}
};
// sensors needed while offroad
std::set<int> offroad_sensors = {
SENSOR_LIGHT,
SENSOR_ACCELEROMETER,
SENSOR_GYRO_UNCALIBRATED,
};
// init all the sensors
for (auto &s : sensors) {
device->activate(device, s.first, 0);
device->activate(device, s.first, 1);
device->setDelay(device, s.first, s.second);
}
// TODO: why is this 16?
static const size_t numEvents = 16;
sensors_event_t buffer[numEvents];
while (!do_exit) {
int n = device->poll(device, buffer, numEvents);
if (n == 0) continue;
if (n < 0) {
LOG("sensor_loop poll failed: %d", n);
continue;
}
int log_events = 0;
for (int i=0; i < n; i++) {
if (sensor_types.find(buffer[i].type) != sensor_types.end()) {
log_events++;
}
}
MessageBuilder msg;
auto sensor_events = msg.initEvent().initSensorEvents(log_events);
int log_i = 0;
for (int i = 0; i < n; i++) {
const sensors_event_t& data = buffer[i];
if (sensor_types.find(data.type) == sensor_types.end()) {
continue;
}
auto log_event = sensor_events[log_i];
log_event.setSource(cereal::SensorEventData::SensorSource::ANDROID);
log_event.setVersion(data.version);
log_event.setSensor(data.sensor);
log_event.setType(data.type);
log_event.setTimestamp(data.timestamp);
switch (data.type) {
case SENSOR_TYPE_ACCELEROMETER: {
auto svec = log_event.initAcceleration();
svec.setV(data.acceleration.v);
svec.setStatus(data.acceleration.status);
break;
}
case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED: {
auto svec = log_event.initMagneticUncalibrated();
// assuming the uncalib and bias floats are contiguous in memory
kj::ArrayPtr<const float> vs(&data.uncalibrated_magnetic.uncalib[0], 6);
svec.setV(vs);
break;
}
case SENSOR_TYPE_MAGNETIC_FIELD: {
auto svec = log_event.initMagnetic();
svec.setV(data.magnetic.v);
svec.setStatus(data.magnetic.status);
break;
}
case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED: {
auto svec = log_event.initGyroUncalibrated();
// assuming the uncalib and bias floats are contiguous in memory
kj::ArrayPtr<const float> vs(&data.uncalibrated_gyro.uncalib[0], 6);
svec.setV(vs);
break;
}
case SENSOR_TYPE_GYROSCOPE: {
auto svec = log_event.initGyro();
svec.setV(data.gyro.v);
svec.setStatus(data.gyro.status);
break;
}
case SENSOR_TYPE_PROXIMITY: {
log_event.setProximity(data.distance);
break;
}
case SENSOR_TYPE_LIGHT:
log_event.setLight(data.light);
break;
}
log_i++;
}
pm.send("sensorEvents", msg);
if (re_init_sensors) {
LOGE("Resetting sensors");
re_init_sensors = false;
break;
}
// Check whether to go into low power mode at 5Hz
if (frame % 20 == 0) {
sm.update(0);
bool offroad = !sm["deviceState"].getDeviceState().getStarted();
if (low_power_mode != offroad) {
for (auto &s : sensors) {
device->activate(device, s.first, 0);
if (!offroad || offroad_sensors.find(s.first) != offroad_sensors.end()) {
device->activate(device, s.first, 1);
}
}
low_power_mode = offroad;
}
}
frame++;
}
sensors_close(device);
}
}
}// Namespace end
int main(int argc, char *argv[]) {
setpriority(PRIO_PROCESS, 0, -18);
signal(SIGPIPE, (sighandler_t)sigpipe_handler);
sensor_loop();
return 0;
}