|
|
|
@ -17,36 +17,6 @@
@@ -17,36 +17,6 @@
|
|
|
|
|
#include <GCS_MAVLink/GCS.h> |
|
|
|
|
#include "AP_RangeFinder_BLPing.h" |
|
|
|
|
|
|
|
|
|
#define BLPING_INIT_RATE_MS 1000 // initialise sensor at no more than 1hz
|
|
|
|
|
#define BLPING_FRAME_HEADER1 0x42 // header first byte ('B')
|
|
|
|
|
#define BLPING_FRAME_HEADER2 0x52 // header second byte ('R')
|
|
|
|
|
|
|
|
|
|
#define BLPING_SRC_ID 0 // vehicle's source id
|
|
|
|
|
#define BLPING_DEST_ID 1 // sensor's id
|
|
|
|
|
|
|
|
|
|
#define BLPING_MSGID_ACK 1 |
|
|
|
|
#define BLPING_MSGID_NACK 2 |
|
|
|
|
#define BLPING_MSGID_SET_PING_INTERVAL 1004 |
|
|
|
|
#define BLPING_MSGID_GET_DEVICE_ID 1201 |
|
|
|
|
#define BLDPIN_MSGID_DISTANCE_SIMPLE 1211 |
|
|
|
|
#define BLPING_MSGID_CONTINUOUS_START 1400 |
|
|
|
|
|
|
|
|
|
// Protocol implemented by this sensor can be found here: https://github.com/bluerobotics/ping-protocol
|
|
|
|
|
//
|
|
|
|
|
// Byte Type Name Description
|
|
|
|
|
// --------------------------------------------------------------------------------------------------------------
|
|
|
|
|
// 0 uint8_t start1 'B'
|
|
|
|
|
// 1 uint8_t start2 'R'
|
|
|
|
|
// 2-3 uint16_t payload_length number of bytes in payload (low byte, high byte)
|
|
|
|
|
// 4-5 uint16_t message id message id (low byte, high byte)
|
|
|
|
|
// 6 uint8_t src_device_id id of device sending the message
|
|
|
|
|
// 7 uint8_t dst_device_id id of device of the intended recipient
|
|
|
|
|
// 8-n uint8_t[] payload message payload
|
|
|
|
|
// (n+1)-(n+2) uint16_t checksum the sum of all the non-checksum bytes in the message (low byte, high byte)
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
update the state of the sensor |
|
|
|
|
*/ |
|
|
|
|
void AP_RangeFinder_BLPing::update(void) |
|
|
|
|
{ |
|
|
|
|
if (uart == nullptr) { |
|
|
|
@ -57,7 +27,7 @@ void AP_RangeFinder_BLPing::update(void)
@@ -57,7 +27,7 @@ void AP_RangeFinder_BLPing::update(void)
|
|
|
|
|
if (status() == RangeFinder::Status::NoData) { |
|
|
|
|
const uint32_t now = AP_HAL::millis(); |
|
|
|
|
// initialise sensor if no distances recently
|
|
|
|
|
if (now - last_init_ms > BLPING_INIT_RATE_MS) { |
|
|
|
|
if (now - last_init_ms > read_timeout_ms()) { |
|
|
|
|
last_init_ms = now; |
|
|
|
|
init_sensor(); |
|
|
|
|
} |
|
|
|
@ -66,12 +36,65 @@ void AP_RangeFinder_BLPing::update(void)
@@ -66,12 +36,65 @@ void AP_RangeFinder_BLPing::update(void)
|
|
|
|
|
|
|
|
|
|
void AP_RangeFinder_BLPing::init_sensor() |
|
|
|
|
{ |
|
|
|
|
// request distance from sensor
|
|
|
|
|
send_message(BLDPIN_MSGID_DISTANCE_SIMPLE, nullptr, 0); |
|
|
|
|
// Set message interval between pings in ms
|
|
|
|
|
uint16_t ping_interval = _sensor_rate_ms; |
|
|
|
|
protocol.send_message(uart, PingProtocol::MessageId::SET_PING_INTERVAL, reinterpret_cast<uint8_t*>(&ping_interval), sizeof(ping_interval)); |
|
|
|
|
|
|
|
|
|
// Send a message requesting a continuous
|
|
|
|
|
uint16_t continuous_message = static_cast<uint16_t>(PingProtocol::MessageId::DISTANCE_SIMPLE); |
|
|
|
|
protocol.send_message(uart, PingProtocol::MessageId::CONTINUOUS_START, reinterpret_cast<uint8_t*>(&continuous_message), sizeof(continuous_message)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// send message to sensor
|
|
|
|
|
void AP_RangeFinder_BLPing::send_message(uint16_t msgid, const uint8_t *payload, uint16_t payload_len) |
|
|
|
|
// distance returned in reading_cm, signal_ok is set to true if sensor reports a strong signal
|
|
|
|
|
bool AP_RangeFinder_BLPing::get_reading(uint16_t &reading_cm) |
|
|
|
|
{ |
|
|
|
|
if (uart == nullptr) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct { |
|
|
|
|
float sum_cm = 0; |
|
|
|
|
uint16_t count = 0; |
|
|
|
|
float mean() { return sum_cm / count; }; |
|
|
|
|
} averageStruct; |
|
|
|
|
|
|
|
|
|
// read any available lines from the lidar
|
|
|
|
|
int16_t nbytes = uart->available(); |
|
|
|
|
while (nbytes-- > 0) { |
|
|
|
|
const int16_t b = uart->read(); |
|
|
|
|
if (b < 0) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if (protocol.parse_byte(b) == PingProtocol::MessageId::DISTANCE_SIMPLE) { |
|
|
|
|
averageStruct.count++; |
|
|
|
|
averageStruct.sum_cm += protocol.get_distance_mm()/10.0f; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (averageStruct.count > 0) { |
|
|
|
|
// return average distance of readings
|
|
|
|
|
reading_cm = averageStruct.mean(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// no readings so return false
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint8_t PingProtocol::get_confidence() const |
|
|
|
|
{ |
|
|
|
|
return msg.payload[4]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t PingProtocol::get_distance_mm() const |
|
|
|
|
{ |
|
|
|
|
return (uint32_t)msg.payload[0] | |
|
|
|
|
(uint32_t)msg.payload[1] << 8 | |
|
|
|
|
(uint32_t)msg.payload[2] << 16 | |
|
|
|
|
(uint32_t)msg.payload[3] << 24; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PingProtocol::send_message(AP_HAL::UARTDriver *uart, PingProtocol::MessageId msg_id, const uint8_t *payload, uint16_t payload_len) const |
|
|
|
|
{ |
|
|
|
|
if (uart == nullptr) { |
|
|
|
|
return; |
|
|
|
@ -83,27 +106,27 @@ void AP_RangeFinder_BLPing::send_message(uint16_t msgid, const uint8_t *payload,
@@ -83,27 +106,27 @@ void AP_RangeFinder_BLPing::send_message(uint16_t msgid, const uint8_t *payload,
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// write header
|
|
|
|
|
uart->write((uint8_t)BLPING_FRAME_HEADER1); |
|
|
|
|
uart->write((uint8_t)BLPING_FRAME_HEADER2); |
|
|
|
|
uint16_t crc = BLPING_FRAME_HEADER1 + BLPING_FRAME_HEADER2; |
|
|
|
|
uart->write(_frame_header1); |
|
|
|
|
uart->write(_frame_header2); |
|
|
|
|
uint16_t crc = _frame_header1 + _frame_header2; |
|
|
|
|
|
|
|
|
|
// write payload length
|
|
|
|
|
uart->write(LOWBYTE(payload_len)); |
|
|
|
|
uart->write(HIGHBYTE(payload_len)); |
|
|
|
|
crc += LOWBYTE(payload_len) + HIGHBYTE(payload_len); |
|
|
|
|
|
|
|
|
|
// msgid
|
|
|
|
|
uart->write(LOWBYTE(msgid)); |
|
|
|
|
uart->write(HIGHBYTE(msgid)); |
|
|
|
|
crc += LOWBYTE(msgid) + HIGHBYTE(msgid); |
|
|
|
|
// message id
|
|
|
|
|
uart->write(LOWBYTE(msg_id)); |
|
|
|
|
uart->write(HIGHBYTE(msg_id)); |
|
|
|
|
crc += LOWBYTE(msg_id) + HIGHBYTE(msg_id); |
|
|
|
|
|
|
|
|
|
// src dev id
|
|
|
|
|
uart->write((uint8_t)BLPING_SRC_ID); |
|
|
|
|
crc += BLPING_SRC_ID; |
|
|
|
|
uart->write(_src_id); |
|
|
|
|
crc += _src_id; |
|
|
|
|
|
|
|
|
|
// destination dev id
|
|
|
|
|
uart->write((uint8_t)BLPING_DEST_ID); |
|
|
|
|
crc += BLPING_DEST_ID; |
|
|
|
|
uart->write(_dst_id); |
|
|
|
|
crc += _dst_id; |
|
|
|
|
|
|
|
|
|
// payload
|
|
|
|
|
if (payload != nullptr) { |
|
|
|
@ -118,105 +141,64 @@ void AP_RangeFinder_BLPing::send_message(uint16_t msgid, const uint8_t *payload,
@@ -118,105 +141,64 @@ void AP_RangeFinder_BLPing::send_message(uint16_t msgid, const uint8_t *payload,
|
|
|
|
|
uart->write(HIGHBYTE(crc)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// distance returned in reading_cm, signal_ok is set to true if sensor reports a strong signal
|
|
|
|
|
bool AP_RangeFinder_BLPing::get_reading(uint16_t &reading_cm) |
|
|
|
|
{ |
|
|
|
|
if (uart == nullptr) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
float sum_cm = 0; |
|
|
|
|
uint16_t count = 0; |
|
|
|
|
|
|
|
|
|
// read any available lines from the lidar
|
|
|
|
|
int16_t nbytes = uart->available(); |
|
|
|
|
while (nbytes-- > 0) { |
|
|
|
|
const int16_t b = uart->read(); |
|
|
|
|
if (b < 0) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if (parse_byte(b)) { |
|
|
|
|
count++; |
|
|
|
|
sum_cm += distance_cm; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (count > 0) { |
|
|
|
|
// return average distance of readings
|
|
|
|
|
reading_cm = sum_cm / count; |
|
|
|
|
|
|
|
|
|
// request another distance
|
|
|
|
|
send_message(BLDPIN_MSGID_DISTANCE_SIMPLE, nullptr, 0); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// no readings so return false
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// process one byte received on serial port
|
|
|
|
|
// returns true if a distance message has been successfully parsed
|
|
|
|
|
// state is stored in msg structure
|
|
|
|
|
bool AP_RangeFinder_BLPing::parse_byte(uint8_t b) |
|
|
|
|
PingProtocol::MessageId PingProtocol::parse_byte(uint8_t b) |
|
|
|
|
{ |
|
|
|
|
bool got_distance = false; |
|
|
|
|
|
|
|
|
|
// process byte depending upon current state
|
|
|
|
|
switch (msg.state) { |
|
|
|
|
|
|
|
|
|
case ParseState::HEADER1: |
|
|
|
|
if (b == BLPING_FRAME_HEADER1) { |
|
|
|
|
msg.crc_expected = BLPING_FRAME_HEADER1; |
|
|
|
|
msg.state = ParseState::HEADER2; |
|
|
|
|
case ParserState::HEADER1: |
|
|
|
|
if (b == _frame_header1) { |
|
|
|
|
msg.crc_expected = _frame_header1; |
|
|
|
|
msg.state = ParserState::HEADER2; |
|
|
|
|
msg.done = false; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case ParseState::HEADER2: |
|
|
|
|
if (b == BLPING_FRAME_HEADER2) { |
|
|
|
|
msg.crc_expected += BLPING_FRAME_HEADER2; |
|
|
|
|
msg.state = ParseState::LEN_L; |
|
|
|
|
case ParserState::HEADER2: |
|
|
|
|
if (b == _frame_header2) { |
|
|
|
|
msg.crc_expected += _frame_header2; |
|
|
|
|
msg.state = ParserState::LEN_L; |
|
|
|
|
} else { |
|
|
|
|
msg.state = ParseState::HEADER1; |
|
|
|
|
msg.state = ParserState::HEADER1; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case ParseState::LEN_L: |
|
|
|
|
case ParserState::LEN_L: |
|
|
|
|
msg.payload_len = b; |
|
|
|
|
msg.crc_expected += b; |
|
|
|
|
msg.state = ParseState::LEN_H; |
|
|
|
|
msg.state = ParserState::LEN_H; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case ParseState::LEN_H: |
|
|
|
|
case ParserState::LEN_H: |
|
|
|
|
msg.payload_len |= ((uint16_t)b << 8); |
|
|
|
|
msg.payload_recv = 0; |
|
|
|
|
msg.crc_expected += b; |
|
|
|
|
msg.state = ParseState::MSG_ID_L; |
|
|
|
|
msg.state = ParserState::MSG_ID_L; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case ParseState::MSG_ID_L: |
|
|
|
|
msg.msgid = b; |
|
|
|
|
case ParserState::MSG_ID_L: |
|
|
|
|
msg.id = b; |
|
|
|
|
msg.crc_expected += b; |
|
|
|
|
msg.state = ParseState::MSG_ID_H; |
|
|
|
|
msg.state = ParserState::MSG_ID_H; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case ParseState::MSG_ID_H: |
|
|
|
|
msg.msgid |= ((uint16_t)b << 8); |
|
|
|
|
case ParserState::MSG_ID_H: |
|
|
|
|
msg.id |= ((uint16_t)b << 8); |
|
|
|
|
msg.crc_expected += b; |
|
|
|
|
msg.state = ParseState::SRC_ID; |
|
|
|
|
msg.state = ParserState::SRC_ID; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case ParseState::SRC_ID: |
|
|
|
|
case ParserState::SRC_ID: |
|
|
|
|
msg.crc_expected += b; |
|
|
|
|
msg.state = ParseState::DST_ID; |
|
|
|
|
msg.state = ParserState::DST_ID; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case ParseState::DST_ID: |
|
|
|
|
case ParserState::DST_ID: |
|
|
|
|
msg.crc_expected += b; |
|
|
|
|
msg.state = ParseState::PAYLOAD; |
|
|
|
|
msg.state = ParserState::PAYLOAD; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case ParseState::PAYLOAD: |
|
|
|
|
case ParserState::PAYLOAD: |
|
|
|
|
if (msg.payload_recv < msg.payload_len) { |
|
|
|
|
if (msg.payload_recv < ARRAY_SIZE(msg.payload)) { |
|
|
|
|
msg.payload[msg.payload_recv] = b; |
|
|
|
@ -225,37 +207,22 @@ bool AP_RangeFinder_BLPing::parse_byte(uint8_t b)
@@ -225,37 +207,22 @@ bool AP_RangeFinder_BLPing::parse_byte(uint8_t b)
|
|
|
|
|
msg.crc_expected += b; |
|
|
|
|
} |
|
|
|
|
if (msg.payload_recv == msg.payload_len) { |
|
|
|
|
msg.state = ParseState::CRC_L; |
|
|
|
|
msg.state = ParserState::CRC_L; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case ParseState::CRC_L: |
|
|
|
|
case ParserState::CRC_L: |
|
|
|
|
msg.crc = b; |
|
|
|
|
msg.state = ParseState::CRC_H; |
|
|
|
|
msg.state = ParserState::CRC_H; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case ParseState::CRC_H: |
|
|
|
|
case ParserState::CRC_H: |
|
|
|
|
msg.crc |= ((uint16_t)b << 8); |
|
|
|
|
msg.state = ParseState::HEADER1; |
|
|
|
|
if (msg.crc_expected == msg.crc) { |
|
|
|
|
|
|
|
|
|
// process payload
|
|
|
|
|
switch (msg.msgid) { |
|
|
|
|
|
|
|
|
|
case BLPING_MSGID_ACK: |
|
|
|
|
case BLPING_MSGID_NACK: |
|
|
|
|
// ignore
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case BLDPIN_MSGID_DISTANCE_SIMPLE: |
|
|
|
|
const uint32_t dist_mm = (uint32_t)msg.payload[0] | (uint32_t)msg.payload[1] << 8 | (uint32_t)msg.payload[2] << 16 | (uint32_t)msg.payload[3] << 24; |
|
|
|
|
distance_cm = dist_mm / 10; |
|
|
|
|
got_distance = true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
msg.state = ParserState::HEADER1; |
|
|
|
|
msg.done = msg.crc_expected == msg.crc; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return got_distance; |
|
|
|
|
|
|
|
|
|
return msg.done ? get_message_id() : MessageId::INVALID; |
|
|
|
|
} |
|
|
|
|