123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- #include "AP_Beacon.h"
- #include "AP_Beacon_Backend.h"
- #include "AP_Beacon_Pozyx.h"
- #include "AP_Beacon_Marvelmind.h"
- #include "AP_Beacon_SITL.h"
- #include <AP_Common/Location.h>
- extern const AP_HAL::HAL &hal;
- const AP_Param::GroupInfo AP_Beacon::var_info[] = {
-
-
-
-
-
- AP_GROUPINFO("_TYPE", 0, AP_Beacon, _type, 0),
-
-
-
-
-
-
-
- AP_GROUPINFO("_LATITUDE", 1, AP_Beacon, origin_lat, 0),
-
-
-
-
-
-
-
- AP_GROUPINFO("_LONGITUDE", 2, AP_Beacon, origin_lon, 0),
-
-
-
-
-
-
-
- AP_GROUPINFO("_ALT", 3, AP_Beacon, origin_alt, 0),
-
-
-
-
-
-
-
- AP_GROUPINFO("_ORIENT_YAW", 4, AP_Beacon, orient_yaw, 0),
- AP_GROUPEND
- };
- AP_Beacon::AP_Beacon(AP_SerialManager &_serial_manager) :
- serial_manager(_serial_manager)
- {
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- if (_singleton != nullptr) {
- AP_HAL::panic("Fence must be singleton");
- }
- #endif
- _singleton = this;
- AP_Param::setup_object_defaults(this, var_info);
- }
- void AP_Beacon::init(void)
- {
- if (_driver != nullptr) {
-
- return;
- }
-
- if (_type == AP_BeaconType_Pozyx) {
- _driver = new AP_Beacon_Pozyx(*this, serial_manager);
- } else if (_type == AP_BeaconType_Marvelmind) {
- _driver = new AP_Beacon_Marvelmind(*this, serial_manager);
- }
- #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
- if (_type == AP_BeaconType_SITL) {
- _driver = new AP_Beacon_SITL(*this);
- }
- #endif
- }
- bool AP_Beacon::enabled(void)
- {
- return (_type != AP_BeaconType_None);
- }
- bool AP_Beacon::healthy(void)
- {
- if (!device_ready()) {
- return false;
- }
- return _driver->healthy();
- }
- void AP_Beacon::update(void)
- {
- if (!device_ready()) {
- return;
- }
- _driver->update();
-
- update_boundary_points();
- }
- bool AP_Beacon::get_origin(Location &origin_loc) const
- {
- if (!device_ready()) {
- return false;
- }
-
- if (is_zero(origin_lat) && is_zero(origin_lon) && is_zero(origin_alt)) {
- return false;
- }
-
- origin_loc = {};
- origin_loc.lat = origin_lat * 1.0e7f;
- origin_loc.lng = origin_lon * 1.0e7f;
- origin_loc.alt = origin_alt * 100;
- return true;
- }
- bool AP_Beacon::get_vehicle_position_ned(Vector3f &position, float& accuracy_estimate) const
- {
- if (!device_ready()) {
- return false;
- }
-
- if (AP_HAL::millis() - veh_pos_update_ms > AP_BEACON_TIMEOUT_MS) {
- return false;
- }
-
- position = veh_pos_ned;
- accuracy_estimate = veh_pos_accuracy;
- return true;
- }
- uint8_t AP_Beacon::count() const
- {
- if (!device_ready()) {
- return 0;
- }
- return num_beacons;
- }
- bool AP_Beacon::get_beacon_data(uint8_t beacon_instance, struct BeaconState& state) const
- {
- if (!device_ready() || beacon_instance >= num_beacons) {
- return false;
- }
- state = beacon_state[beacon_instance];
- return true;
- }
- uint8_t AP_Beacon::beacon_id(uint8_t beacon_instance) const
- {
- if (beacon_instance >= num_beacons) {
- return 0;
- }
- return beacon_state[beacon_instance].id;
- }
- bool AP_Beacon::beacon_healthy(uint8_t beacon_instance) const
- {
- if (beacon_instance >= num_beacons) {
- return false;
- }
- return beacon_state[beacon_instance].healthy;
- }
- float AP_Beacon::beacon_distance(uint8_t beacon_instance) const
- {
- if (!beacon_state[beacon_instance].healthy || beacon_instance >= num_beacons) {
- return 0.0f;
- }
- return beacon_state[beacon_instance].distance;
- }
- Vector3f AP_Beacon::beacon_position(uint8_t beacon_instance) const
- {
- if (!device_ready() || beacon_instance >= num_beacons) {
- Vector3f temp = {};
- return temp;
- }
- return beacon_state[beacon_instance].position;
- }
- uint32_t AP_Beacon::beacon_last_update_ms(uint8_t beacon_instance) const
- {
- if (_type == AP_BeaconType_None || beacon_instance >= num_beacons) {
- return 0;
- }
- return beacon_state[beacon_instance].distance_update_ms;
- }
- void AP_Beacon::update_boundary_points()
- {
-
-
- if (!device_ready() || num_beacons < AP_BEACON_MINIMUM_FENCE_BEACONS || boundary_num_beacons == num_beacons) {
- return;
- }
-
- boundary_num_beacons = num_beacons;
-
- Vector2f beacon_points[AP_BEACON_MAX_BEACONS];
- for (uint8_t index = 0; index < num_beacons; index++) {
- const Vector3f& point_3d = beacon_position(index);
- beacon_points[index].x = point_3d.x;
- beacon_points[index].y = point_3d.y;
- }
-
-
-
-
-
-
- Vector2f boundary_points[AP_BEACON_MAX_BEACONS+1];
- uint8_t curr_boundary_idx = 0;
- uint8_t curr_beacon_idx = 0;
-
- boundary_points[curr_boundary_idx] = beacon_points[curr_beacon_idx];
- bool boundary_success = false;
- bool boundary_failure = false;
- float start_angle = 0.0f;
- while (!boundary_success && !boundary_failure) {
-
- uint8_t next_idx;
- float next_angle;
- if (get_next_boundary_point(beacon_points, num_beacons, curr_beacon_idx, start_angle, next_idx, next_angle)) {
-
- curr_boundary_idx++;
- boundary_points[curr_boundary_idx] = beacon_points[next_idx];
- curr_beacon_idx = next_idx;
- start_angle = next_angle;
-
- uint8_t dup_idx = 0;
- bool dup_found = false;
- while (dup_idx < curr_boundary_idx && !dup_found) {
- dup_found = (boundary_points[dup_idx] == boundary_points[curr_boundary_idx]);
- if (!dup_found) {
- dup_idx++;
- }
- }
-
- if (dup_found) {
-
-
- const uint8_t num_pts = curr_boundary_idx - dup_idx;
- if (num_pts >= AP_BEACON_MINIMUM_FENCE_BEACONS) {
-
- for (uint8_t j = 0; j < num_pts; j++) {
- boundary[j] = boundary_points[j+dup_idx] * 100.0f;
- }
- boundary_num_points = num_pts;
- boundary_success = true;
- } else {
-
- boundary_failure = true;
- }
- }
- } else {
-
- boundary_failure = true;
- }
- }
-
- if (boundary_failure) {
- boundary_num_points = 0;
- }
- }
- bool AP_Beacon::get_next_boundary_point(const Vector2f* boundary_pts, uint8_t num_points, uint8_t current_index, float start_angle, uint8_t& next_index, float& next_angle)
- {
-
- if (boundary_pts == nullptr || current_index >= num_points) {
- return false;
- }
-
- Vector2f curr_point = boundary_pts[current_index];
-
- float lowest_angle = M_PI_2;
- float lowest_angle_relative = M_PI_2;
- bool lowest_found = false;
- uint8_t lowest_index = 0;
- for (uint8_t i=0; i < num_points; i++) {
- if (i != current_index) {
- Vector2f vec = boundary_pts[i] - curr_point;
- if (!vec.is_zero()) {
- float angle = wrap_2PI(atan2f(vec.y, vec.x));
- float angle_relative = wrap_2PI(angle - start_angle);
- if ((angle_relative < lowest_angle_relative) || !lowest_found) {
- lowest_angle = angle;
- lowest_angle_relative = angle_relative;
- lowest_index = i;
- lowest_found = true;
- }
- }
- }
- }
-
- if (lowest_found) {
- next_index = lowest_index;
- next_angle = lowest_angle;
- }
- return lowest_found;
- }
- const Vector2f* AP_Beacon::get_boundary_points(uint16_t& num_points) const
- {
- if (!device_ready()) {
- num_points = 0;
- return nullptr;
- }
- num_points = boundary_num_points;
- return boundary;
- }
- bool AP_Beacon::device_ready(void) const
- {
- return ((_driver != nullptr) && (_type != AP_BeaconType_None));
- }
- AP_Beacon *AP_Beacon::_singleton;
- namespace AP {
- AP_Beacon *beacon()
- {
- return AP_Beacon::get_singleton();
- }
- }
|