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.
183 lines
5.2 KiB
183 lines
5.2 KiB
#include "AP_Proximity_Cygbot_D1.h" |
|
|
|
#if HAL_PROXIMITY_ENABLED && AP_PROXIMITY_CYGBOT_ENABLED |
|
|
|
// update the state of the sensor |
|
void AP_Proximity_Cygbot_D1::update() |
|
{ |
|
if (!_initialized) { |
|
send_sensor_start(); |
|
_temp_boundary.reset(); |
|
_initialized = true; |
|
_last_init_ms = AP_HAL::millis(); |
|
} |
|
|
|
if ((AP_HAL::millis() - _last_init_ms) < CYGBOT_INIT_TIMEOUT_MS) { |
|
// just initialized |
|
set_status(AP_Proximity::Status::NoData); |
|
return; |
|
} |
|
|
|
// read data |
|
read_sensor_data(); |
|
|
|
if (AP_HAL::millis() - _last_distance_received_ms < CYGBOT_TIMEOUT_MS) { |
|
set_status(AP_Proximity::Status::Good); |
|
} else { |
|
// long time since we received any valid sensor data |
|
// try sending the sensor the "send data" message |
|
_initialized = false; |
|
set_status(AP_Proximity::Status::NoData); |
|
} |
|
} |
|
|
|
// send message to the sensor to start streaming 2-D data |
|
void AP_Proximity_Cygbot_D1::send_sensor_start() |
|
{ |
|
// this message corresponds to "start message" |
|
const uint8_t packet_start_2d[8] = { CYGBOT_PACKET_HEADER_0, CYGBOT_PACKET_HEADER_1, CYGBOT_PACKET_HEADER_2, 0x02, 0x00, 0x01, 0x00, 0x03 }; |
|
_uart->write(packet_start_2d, 8); |
|
} |
|
|
|
void AP_Proximity_Cygbot_D1::read_sensor_data() |
|
{ |
|
uint32_t nbytes = _uart->available(); |
|
while (nbytes-- > 0) { |
|
uint8_t byte = _uart->read(); |
|
if (!parse_byte(byte)) { |
|
// reset |
|
reset(); |
|
} |
|
} |
|
} |
|
|
|
// parse one byte from the sensor. Return false on error. |
|
// Message format is: header1 + header2 + header3 + length1 + length2 + PayloadCommand + checksum |
|
bool AP_Proximity_Cygbot_D1::parse_byte(uint8_t data) |
|
{ |
|
switch (_parse_state) { |
|
case Header1: |
|
if (data == CYGBOT_PACKET_HEADER_0) { |
|
_parse_state = Header2; |
|
return true; |
|
} |
|
|
|
return false; |
|
|
|
case Header2: |
|
if (data == CYGBOT_PACKET_HEADER_1) { |
|
_parse_state = Header3; |
|
return true; |
|
} |
|
return false; |
|
|
|
case Header3: |
|
if (data == CYGBOT_PACKET_HEADER_2) { |
|
_parse_state = Length1; |
|
return true; |
|
} |
|
return false; |
|
|
|
case Length1: |
|
_msg.payload_len_flags_low = data; |
|
_parse_state = Length2; |
|
return true; |
|
|
|
case Length2: |
|
_msg.payload_len_flags_high = data; |
|
_msg.payload_len = UINT16_VALUE(data, _msg.payload_len_flags_low); |
|
if (_msg.payload_len > CYGBOT_MAX_MSG_SIZE) { |
|
return false; |
|
} |
|
_parse_state = Payload_Header; |
|
return true; |
|
|
|
case Payload_Header: |
|
if (data == CYGBOT_PAYLOAD_HEADER) { |
|
_parse_state = Payload_Data; |
|
_msg.payload_counter = 1; |
|
_msg.payload[_msg.payload_counter] = data; |
|
return true; |
|
} |
|
return false; |
|
|
|
case Payload_Data: |
|
if (_msg.payload_counter < (_msg.payload_len)) { |
|
_msg.payload_counter++; |
|
_msg.payload[_msg.payload_counter] = data; |
|
return true; |
|
} |
|
_parse_state = CheckSum; |
|
FALLTHROUGH; |
|
|
|
case CheckSum: { |
|
const uint8_t checksum_num = calc_checksum(_msg.payload, _msg.payload_len); |
|
if (data != checksum_num) { |
|
return false; |
|
} |
|
// checksum is valid, parse payload |
|
_last_distance_received_ms = AP_HAL::millis(); |
|
parse_payload(); |
|
_temp_boundary.update_3D_boundary(boundary); |
|
reset(); |
|
return true; |
|
} |
|
break; |
|
|
|
default: |
|
return false; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
// parse payload, to pick out distances, and feed them to the correct faces |
|
void AP_Proximity_Cygbot_D1::parse_payload() |
|
{ |
|
// current horizontal angle in the payload |
|
float sampled_angle = CYGBOT_2D_START_ANGLE; |
|
|
|
// start from second byte as first byte is part of the header |
|
for (uint16_t i = 2; i < _msg.payload_len; i += 2) { |
|
const uint16_t distance_mm = UINT16_VALUE(_msg.payload[i], _msg.payload[i+1]); |
|
float distance_m = distance_mm * 0.001f; |
|
if (distance_m > distance_min() && distance_m < distance_max()) { |
|
if (ignore_reading(sampled_angle, distance_m)) { |
|
// ignore this angle |
|
sampled_angle += CYGBOT_2D_ANGLE_STEP; |
|
continue; |
|
} |
|
// convert angle to face |
|
const AP_Proximity_Boundary_3D::Face face = boundary.get_face(sampled_angle); |
|
// push face to temp boundary |
|
_temp_boundary.add_distance(face, sampled_angle, distance_m); |
|
// push to OA_DB |
|
database_push(sampled_angle, distance_m); |
|
} |
|
// increment sampled angle |
|
sampled_angle += CYGBOT_2D_ANGLE_STEP; |
|
} |
|
} |
|
|
|
// Checksum |
|
uint8_t AP_Proximity_Cygbot_D1::calc_checksum(uint8_t *buff, int buffSize) |
|
{ |
|
uint8_t check_sum_num = 0; |
|
check_sum_num ^= _msg.payload_len_flags_high; |
|
check_sum_num ^= _msg.payload_len_flags_low; |
|
for (uint16_t i = 0; i <= buffSize; i++) { |
|
check_sum_num ^= buff[i]; |
|
} |
|
return check_sum_num; |
|
} |
|
|
|
// reset all variables and flags |
|
void AP_Proximity_Cygbot_D1::reset() |
|
{ |
|
_parse_state = Header1; |
|
_msg.payload_counter = 0; |
|
_msg.payload_len = 0; |
|
_temp_boundary.reset(); |
|
} |
|
|
|
#endif // HAL_PROXIMITY_ENABLED
|
|
|