Skip to content
Merged
16 changes: 14 additions & 2 deletions libraries/AP_Arming/AP_Arming.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1220,13 +1220,25 @@ bool AP_Arming::can_checks(bool report)
#endif
break;
}
case AP_CAN::Protocol::EFI_NWPMU:
case AP_CAN::Protocol::USD1:
case AP_CAN::Protocol::TOFSenseP:
case AP_CAN::Protocol::NanoRadar_NRA24:
case AP_CAN::Protocol::Benewake:
{
for (uint8_t j = i; j; j--) {
if (AP::can().get_driver_type(i) == AP::can().get_driver_type(j-1)) {
check_failed(ARMING_CHECK_SYSTEM, report, "Same rfnd on different CAN ports");
return false;
}
}
break;
}
case AP_CAN::Protocol::EFI_NWPMU:
case AP_CAN::Protocol::None:
case AP_CAN::Protocol::Scripting:
case AP_CAN::Protocol::Scripting2:
case AP_CAN::Protocol::Benewake:
case AP_CAN::Protocol::KDECAN:

break;
}
}
Expand Down
2 changes: 2 additions & 0 deletions libraries/AP_CANManager/AP_CAN.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,7 @@ class AP_CAN {
Scripting = 10,
Benewake = 11,
Scripting2 = 12,
TOFSenseP = 13,
NanoRadar_NRA24 = 14,
};
};
2 changes: 1 addition & 1 deletion libraries/AP_CANManager/AP_CANDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const AP_Param::GroupInfo AP_CANManager::CANDriver_Params::var_info[] = {
// @Param: PROTOCOL
// @DisplayName: Enable use of specific protocol over virtual driver
// @Description: Enabling this option starts selected protocol that will use this virtual driver
// @Values: 0:Disabled,1:DroneCAN,4:PiccoloCAN,6:EFI_NWPMU,7:USD1,8:KDECAN,10:Scripting,11:Benewake,12:Scripting2
// @Values: 0:Disabled,1:DroneCAN,4:PiccoloCAN,6:EFI_NWPMU,7:USD1,8:KDECAN,10:Scripting,11:Benewake,12:Scripting2,13:TOFSenseP,14:NanoRadar_NRA24
// @User: Advanced
// @RebootRequired: True
AP_GROUPINFO("PROTOCOL", 1, AP_CANManager::CANDriver_Params, _driver_type, float(AP_CAN::Protocol::DroneCAN)),
Expand Down
51 changes: 40 additions & 11 deletions libraries/AP_RangeFinder/AP_RangeFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
#include "AP_RangeFinder_Benewake_CAN.h"
#include "AP_RangeFinder_Lua.h"
#include "AP_RangeFinder_NoopLoop.h"
#include "AP_RangeFinder_TOFSenseP_CAN.h"
#include "AP_RangeFinder_NRA24_CAN.h"

#include <AP_BoardConfig/AP_BoardConfig.h>
#include <AP_Logger/AP_Logger.h>
Expand All @@ -71,7 +73,7 @@ const AP_Param::GroupInfo RangeFinder::var_info[] = {
AP_SUBGROUPINFO(params[0], "1_", 25, RangeFinder, AP_RangeFinder_Params),

// @Group: 1_
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Benewake_CAN.cpp,AP_RangeFinder_USD1_CAN.cpp
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Backend_CAN.cpp
AP_SUBGROUPVARPTR(drivers[0], "1_", 57, RangeFinder, backend_var_info[0]),

#if RANGEFINDER_MAX_INSTANCES > 1
Expand All @@ -80,7 +82,7 @@ const AP_Param::GroupInfo RangeFinder::var_info[] = {
AP_SUBGROUPINFO(params[1], "2_", 27, RangeFinder, AP_RangeFinder_Params),

// @Group: 2_
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Benewake_CAN.cpp,AP_RangeFinder_USD1_CAN.cpp
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Backend_CAN.cpp
AP_SUBGROUPVARPTR(drivers[1], "2_", 58, RangeFinder, backend_var_info[1]),
#endif

Expand All @@ -90,7 +92,7 @@ const AP_Param::GroupInfo RangeFinder::var_info[] = {
AP_SUBGROUPINFO(params[2], "3_", 29, RangeFinder, AP_RangeFinder_Params),

// @Group: 3_
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Benewake_CAN.cpp,AP_RangeFinder_USD1_CAN.cpp
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Backend_CAN.cpp
AP_SUBGROUPVARPTR(drivers[2], "3_", 59, RangeFinder, backend_var_info[2]),
#endif

Expand All @@ -100,7 +102,7 @@ const AP_Param::GroupInfo RangeFinder::var_info[] = {
AP_SUBGROUPINFO(params[3], "4_", 31, RangeFinder, AP_RangeFinder_Params),

// @Group: 4_
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Benewake_CAN.cpp,AP_RangeFinder_USD1_CAN.cpp
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Backend_CAN.cpp
AP_SUBGROUPVARPTR(drivers[3], "4_", 60, RangeFinder, backend_var_info[3]),
#endif

Expand All @@ -110,7 +112,7 @@ const AP_Param::GroupInfo RangeFinder::var_info[] = {
AP_SUBGROUPINFO(params[4], "5_", 33, RangeFinder, AP_RangeFinder_Params),

// @Group: 5_
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Benewake_CAN.cpp,AP_RangeFinder_USD1_CAN.cpp
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Backend_CAN.cpp
AP_SUBGROUPVARPTR(drivers[4], "5_", 34, RangeFinder, backend_var_info[4]),
#endif

Expand All @@ -120,7 +122,7 @@ const AP_Param::GroupInfo RangeFinder::var_info[] = {
AP_SUBGROUPINFO(params[5], "6_", 35, RangeFinder, AP_RangeFinder_Params),

// @Group: 6_
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Benewake_CAN.cpp,AP_RangeFinder_USD1_CAN.cpp
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Backend_CAN.cpp
AP_SUBGROUPVARPTR(drivers[5], "6_", 36, RangeFinder, backend_var_info[5]),
#endif

Expand All @@ -130,7 +132,7 @@ const AP_Param::GroupInfo RangeFinder::var_info[] = {
AP_SUBGROUPINFO(params[6], "7_", 37, RangeFinder, AP_RangeFinder_Params),

// @Group: 7_
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Benewake_CAN.cpp,AP_RangeFinder_USD1_CAN.cpp
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Backend_CAN.cpp
AP_SUBGROUPVARPTR(drivers[6], "7_", 38, RangeFinder, backend_var_info[6]),
#endif

Expand All @@ -140,7 +142,7 @@ const AP_Param::GroupInfo RangeFinder::var_info[] = {
AP_SUBGROUPINFO(params[7], "8_", 39, RangeFinder, AP_RangeFinder_Params),

// @Group: 8_
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Benewake_CAN.cpp,AP_RangeFinder_USD1_CAN.cpp
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Backend_CAN.cpp
AP_SUBGROUPVARPTR(drivers[7], "8_", 40, RangeFinder, backend_var_info[7]),
#endif

Expand All @@ -150,7 +152,7 @@ const AP_Param::GroupInfo RangeFinder::var_info[] = {
AP_SUBGROUPINFO(params[8], "9_", 41, RangeFinder, AP_RangeFinder_Params),

// @Group: 9_
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Benewake_CAN.cpp,AP_RangeFinder_USD1_CAN.cpp
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Backend_CAN.cpp
AP_SUBGROUPVARPTR(drivers[8], "9_", 42, RangeFinder, backend_var_info[8]),
#endif

Expand All @@ -160,7 +162,7 @@ const AP_Param::GroupInfo RangeFinder::var_info[] = {
AP_SUBGROUPINFO(params[9], "A_", 43, RangeFinder, AP_RangeFinder_Params),

// @Group: A_
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Benewake_CAN.cpp,AP_RangeFinder_USD1_CAN.cpp
// @Path: AP_RangeFinder_Wasp.cpp,AP_RangeFinder_Backend_CAN.cpp
AP_SUBGROUPVARPTR(drivers[9], "A_", 44, RangeFinder, backend_var_info[9]),
#endif

Expand Down Expand Up @@ -537,12 +539,24 @@ void RangeFinder::detect_instance(uint8_t instance, uint8_t& serial_instance)
_add_backend(new AP_RangeFinder_Lua(state[instance], params[instance]), instance);
#endif
break;

case Type::NoopLoop_P:
#if AP_RANGEFINDER_NOOPLOOP_ENABLED
serial_create_fn = AP_RangeFinder_NoopLoop::create;
#endif
break;

case Type::TOFSenseP_CAN:
#if AP_RANGEFINDER_TOFSENSEP_CAN_ENABLED
_add_backend(new AP_RangeFinder_TOFSenseP_CAN(state[instance], params[instance]), instance);
#endif
break;
case Type::NRA24_CAN:
#if AP_RANGEFINDER_NRA24_CAN_ENABLED
_add_backend(new AP_RangeFinder_NRA24_CAN(state[instance], params[instance]), instance);
#endif
break;

case Type::NONE:
break;
}
Expand Down Expand Up @@ -780,6 +794,7 @@ bool RangeFinder::prearm_healthy(char *failure_msg, const uint8_t failure_msg_le

// backend-specific checks. This might end up drivers[i]->arming_checks(...).
switch (drivers[i]->allocated_type()) {
#if AP_RANGEFINDER_PWM_ENABLED || AP_RANGEFINDER_ANALOG_ENABLED
case Type::ANALOG:
case Type::PX4_PWM:
case Type::PWM: {
Expand All @@ -805,6 +820,20 @@ bool RangeFinder::prearm_healthy(char *failure_msg, const uint8_t failure_msg_le
}
break;
}
#endif

#if AP_RANGEFINDER_NRA24_CAN_ENABLED
case Type::NRA24_CAN: {
Comment thread
rishabsingh3003 marked this conversation as resolved.
if (drivers[i]->status() == Status::NoData) {
// This sensor stops sending data if there is no relative motion. This will mostly happen during takeoff, before arming
// To avoid pre-arm failure, return true even though there is no data.
// This sensor also sends a "heartbeat" so we can differentiate between "NoData" and "NotConnected"
return true;
}
break;
}
#endif

default:
break;
}
Expand All @@ -818,7 +847,7 @@ bool RangeFinder::prearm_healthy(char *failure_msg, const uint8_t failure_msg_le
return false;
case Status::OutOfRangeLow:
case Status::OutOfRangeHigh:
case Status::Good:
case Status::Good:
break;
}
}
Expand Down
2 changes: 2 additions & 0 deletions libraries/AP_RangeFinder/AP_RangeFinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ class RangeFinder
TeraRanger_Serial = 35,
Lua_Scripting = 36,
NoopLoop_P = 37,
TOFSenseP_CAN = 38,
NRA24_CAN = 39,
SIM = 100,
};

Expand Down
96 changes: 96 additions & 0 deletions libraries/AP_RangeFinder/AP_RangeFinder_Backend_CAN.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <AP_HAL/AP_HAL.h>
#include "AP_RangeFinder_Backend_CAN.h"

#if HAL_MAX_CAN_PROTOCOL_DRIVERS

const AP_Param::GroupInfo AP_RangeFinder_Backend_CAN::var_info[] = {

// @Param: RECV_ID
// @DisplayName: RangeFinder CAN receive ID
// @Description: The receive ID of the CAN frames. A value of zero means all IDs are accepted.
// @Range: 0 65535
// @User: Advanced
AP_GROUPINFO("RECV_ID", 10, AP_RangeFinder_Backend_CAN, receive_id, 0),

// @Param: SNR_MIN
// @DisplayName: RangeFinder Minimum signal strength
// @Description: RangeFinder Minimum signal strength (SNR) to accept distance
// @Range: 0 65535

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider normalising.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do in a follow up PR

// @User: Advanced
AP_GROUPINFO("SNR_MIN", 11, AP_RangeFinder_Backend_CAN, snr_min, 0),

AP_GROUPEND
};

// constructor
AP_RangeFinder_Backend_CAN::AP_RangeFinder_Backend_CAN(
RangeFinder::RangeFinder_State &_state, AP_RangeFinder_Params &_params) :
AP_RangeFinder_Backend(_state, _params)
{
AP_Param::setup_object_defaults(this, var_info);
state.var_info = var_info;
}

// update the state of the sensor
void AP_RangeFinder_Backend_CAN::update(void)
{
if (get_reading(state.distance_m)) {
// update range_valid state based on distance measured
state.last_reading_ms = AP_HAL::millis();
update_status();
} else if (AP_HAL::millis() - state.last_reading_ms >= read_timeout_ms()) {
set_status(RangeFinder::Status::NoData);
}
}

// get distance measurement
bool AP_RangeFinder_Backend_CAN::get_reading(float &reading_m)
{
WITH_SEMAPHORE(_sem);
if (_distance_count != 0) {
reading_m = _distance_sum / _distance_count;
_distance_sum = 0;
_distance_count = 0;
return true;
}

return false;
}

// return true if the CAN ID is correct
bool AP_RangeFinder_Backend_CAN::is_correct_id(uint32_t id) const
{
if (receive_id != 0 && id != uint32_t(receive_id.get())) {
// incorrect receive ID
return false;
}
return true;
}

// handle frames from CANSensor, passing to the drivers
void RangeFinder_MultiCAN::handle_frame(AP_HAL::CANFrame &frame)
{
WITH_SEMAPHORE(sem);
for (auto *d = drivers; d != nullptr; d=d->next) {
if (d->handle_frame(frame)) {
break;
}
}
}

#endif // HAL_MAX_CAN_PROTOCOL_DRIVERS
78 changes: 78 additions & 0 deletions libraries/AP_RangeFinder/AP_RangeFinder_Backend_CAN.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#pragma once

#include "AP_RangeFinder_Backend.h"

#if HAL_MAX_CAN_PROTOCOL_DRIVERS

#include <AP_CANManager/AP_CANSensor.h>
#include <AP_BoardConfig/AP_BoardConfig.h>

class RangeFinder_MultiCAN;

class AP_RangeFinder_Backend_CAN : public AP_RangeFinder_Backend
{
public:
// constructor
AP_RangeFinder_Backend_CAN(RangeFinder::RangeFinder_State &_state,
AP_RangeFinder_Params &_params);

friend class RangeFinder_MultiCAN;

static const struct AP_Param::GroupInfo var_info[];

protected:

// update state
virtual void update(void) override;

// get distance measurement
bool get_reading(float &reading_m);

// it is essential that anyone relying on the base-class update to implement this
virtual bool handle_frame(AP_HAL::CANFrame &frame) = 0;

// maximum time between readings before we change state to NoData:
virtual uint32_t read_timeout_ms() const { return 200; }

virtual MAV_DISTANCE_SENSOR _get_mav_distance_sensor_type() const override {
return MAV_DISTANCE_SENSOR_RADAR;
}

// return true if the CAN ID is correct
bool is_correct_id(uint32_t can_id) const;

// set distance and count
void accumulate_distance_m(float distance_m) {
_distance_sum += distance_m;
_distance_count++;
};

// linked list
AP_RangeFinder_Backend_CAN *next;

AP_Int32 receive_id; // CAN ID to receive for this backend
AP_Int32 snr_min; // minimum signal strength to accept packet

private:

float _distance_sum; // meters
uint32_t _distance_count;
};

// a class to allow for multiple CAN backends with one
// CANSensor driver
class RangeFinder_MultiCAN : public CANSensor {
public:
RangeFinder_MultiCAN(AP_CAN::Protocol can_type, const char *driver_name) : CANSensor(driver_name) {
register_driver(can_type);
}

// handler for incoming frames
void handle_frame(AP_HAL::CANFrame &frame) override;

// Semaphore for access to shared backend data
HAL_Semaphore sem;
Comment thread
rishabsingh3003 marked this conversation as resolved.
AP_RangeFinder_Backend_CAN *drivers;
};

#endif // HAL_MAX_CAN_PROTOCOL_DRIVERS
Loading