Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions dji_sdk/include/dji_sdk/dji_sdk_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,15 @@ class DJISDKNode
};

private:
bool initVehicle(ros::NodeHandle& nh_private);
void fcCommunicationWatchdogCallback(const ros::TimerEvent& event);
bool initVehicle(int activation_timeout_sec=WAIT_TIMEOUT);
bool initServices(ros::NodeHandle& nh);
bool initFlightControl(ros::NodeHandle& nh);
bool initSubscriber(ros::NodeHandle& nh);
bool initPublisher(ros::NodeHandle& nh);
bool initActions(ros::NodeHandle& nh);
bool initDataSubscribeFromFC(ros::NodeHandle& nh);
void cleanUpSubscribeFromFC();
void cleanUpSubscribeFromFC(int timeout_sec);
bool validateSerialDevice(LinuxSerialDevice* serialDevice);
bool isM100();

Expand All @@ -147,7 +148,7 @@ class DJISDKNode
* we cannot call a service without serviceClient, which is in another
* node
*/
ACK::ErrorCode activate(int l_app_id, std::string l_enc_key);
ACK::ErrorCode activate(int l_app_id, std::string l_enc_key, int timeout_sec=WAIT_TIMEOUT);

//! flight control subscriber callbacks
void flightControlSetpointCallback(
Expand Down Expand Up @@ -315,6 +316,7 @@ class DJISDKNode
#endif

private:
ros::NodeHandle nh_;
//! OSDK core
Vehicle* vehicle;
//! general service servers
Expand Down Expand Up @@ -440,10 +442,18 @@ class DJISDKNode
ros::Publisher main_camera_stream_publisher;
ros::Publisher fpv_camera_stream_publisher;
#endif

const ros::Duration FC_COMMUNICATION_WATCHDOG_NOMINAL_PERIOD{1.0};
const ros::Duration FC_COMMUNICATION_WATCHDOG_RESTART_SUB_PERIOD{0.5};
ros::Timer fc_communication_watchdog_timer_;
std::atomic_bool has_recieved_data_since_prev_check_{false};

bool rerequest_sdk_ctrl_on_fc_coms_reestablished_{false};
Comment on lines +446 to +451

Comment on lines +448 to +452
//! constant
const int WAIT_TIMEOUT = 10;
const int MAX_SUBSCRIBE_PACKAGES = 5;
const int INVALID_VERSION = 0;
static constexpr int WAIT_TIMEOUT{10};
static constexpr int MAX_SUBSCRIBE_PACKAGES{5};
static constexpr int INVALID_VERSION{0};

//! configurations
int app_id;
Expand Down Expand Up @@ -528,6 +538,7 @@ class DJISDKNode
ros::Time& data_time_of_measurement_out
);

void setDataRecieved(void);
};

#endif // DJI_SDK_NODE_MAIN_H
116 changes: 102 additions & 14 deletions dji_sdk/src/modules/dji_sdk_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
using namespace DJI::OSDK;

DJISDKNode::DJISDKNode(ros::NodeHandle& nh, ros::NodeHandle& nh_private)
: telemetry_from_fc(USE_BROADCAST),
: nh_{nh},
telemetry_from_fc(USE_BROADCAST),
R_FLU2FRD(tf::Matrix3x3(1, 0, 0, 0, -1, 0, 0, 0, -1)),
R_ENU2NED(tf::Matrix3x3(0, 1, 0, 1, 0, 0, 0, 0, -1)),
curr_align_state(UNALIGNED)
Expand Down Expand Up @@ -50,7 +51,7 @@ DJISDKNode::DJISDKNode(ros::NodeHandle& nh, ros::NodeHandle& nh_private)

// @todo need some error handling for init functions
//! @note parsing launch file to get environment parameters
if (!initVehicle(nh_private))
if (!initVehicle())
{
ROS_ERROR("Vehicle initialization failed");
ros::shutdown();
Expand Down Expand Up @@ -126,22 +127,105 @@ DJISDKNode::DJISDKNode(ros::NodeHandle& nh, ros::NodeHandle& nh_private)
ROS_ERROR("initPublisher failed");
ros::shutdown();
}

fc_communication_watchdog_timer_ = nh_.createTimer(
FC_COMMUNICATION_WATCHDOG_NOMINAL_PERIOD,
&DJISDKNode::fcCommunicationWatchdogCallback, this
);
Comment on lines +131 to +134
}

DJISDKNode::~DJISDKNode()
{
if(!isM100())
{
cleanUpSubscribeFromFC();
cleanUpSubscribeFromFC(WAIT_TIMEOUT);
}
if (vehicle)
{
delete vehicle;
}
}

void DJISDKNode::fcCommunicationWatchdogCallback(const ros::TimerEvent& event)
{
const bool data_recieved{has_recieved_data_since_prev_check_};
has_recieved_data_since_prev_check_ = false;
Comment on lines +151 to +152
if (data_recieved)
return;

fc_communication_watchdog_timer_.stop(); // Avoid concurrent calls due to AsyncSpinner
ROS_ERROR_STREAM("No data recieved during the last " << (event.current_real - event.last_real).toSec() << " seconds.");

if (vehicle)
{
cleanUpSubscribeFromFC(1u);
delete vehicle;
vehicle = nullptr;
}
Comment on lines +159 to +164

if (!initVehicle(1))
{
delete vehicle;
vehicle = nullptr;
ROS_ERROR_STREAM("Re-initing vehicle failed. Retrying in " << FC_COMMUNICATION_WATCHDOG_RESTART_SUB_PERIOD.toSec() << " seconds.");
fc_communication_watchdog_timer_.setPeriod(FC_COMMUNICATION_WATCHDOG_RESTART_SUB_PERIOD, true);
fc_communication_watchdog_timer_.start();
return;
}

if (!initDataSubscribeFromFC(nh_))
{
ROS_ERROR_STREAM("Restarting data subscription from FC failed. Retrying in " << FC_COMMUNICATION_WATCHDOG_RESTART_SUB_PERIOD.toSec() << " seconds.");
fc_communication_watchdog_timer_.setPeriod(FC_COMMUNICATION_WATCHDOG_RESTART_SUB_PERIOD, true);
fc_communication_watchdog_timer_.start();
}
else
Comment on lines +176 to +182
{
ROS_INFO_STREAM("Data subscription from FC restarted successfully");
if (pps_sync_)
{
vehicle->hardSync->setSyncFreq(1ul);
vehicle->hardSync->subscribeNMEAMsgs(NMEACallback, this);
vehicle->hardSync->subscribeUTCTime(GPSUTCTimeCallback, this);
vehicle->hardSync->subscribeFCTimeInUTCRef(FCTimeInUTCCallback, this);
vehicle->hardSync->subscribePPSSource(PPSSourceCallback, this);
}
fc_communication_watchdog_timer_.setPeriod(FC_COMMUNICATION_WATCHDOG_NOMINAL_PERIOD, true);
fc_communication_watchdog_timer_.start();
}

if (rerequest_sdk_ctrl_on_fc_coms_reestablished_)
{
//Attempt to obtain control
dji_sdk::SDKControlAuthority::Request request;
request.control_enable = dji_sdk::SDKControlAuthorityRequest::REQUEST_CONTROL;
dji_sdk::SDKControlAuthority::Response response;
sdkCtrlAuthorityCallback(request, response);
if (!response.result)
{
// Everything else is up and running. Should the request be attempted again?
ROS_ERROR_STREAM("Failed to obtain SDK control after re-initiating FC coms.");
return;
}
// Send control command to change the display mode to SDK control mode
constexpr uint8_t CONTROL_FLAG{
Control::HORIZONTAL_POSITION |
Control::VERTICAL_VELOCITY |
Control::YAW_RATE |
Control::HORIZONTAL_BODY |
Control::STABLE_DISABLE
};
flightControl(CONTROL_FLAG, 0.0, 0.0, 0.0, 0.0);
ROS_ERROR_STREAM("SDK control regained after re-initiating FC coms.");
Comment on lines +218 to +219

// TODO: will display mode change instantly, or will a few messages containing
// a display mode other than MODE_NAVI_SDK_CTRL be published before? If so, ensure that
// the rest of the system handles it correctly
Comment on lines +221 to +223

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Needs to be tested.

}
}

bool
DJISDKNode::initVehicle(ros::NodeHandle& nh_private)
DJISDKNode::initVehicle(int activation_timeout_sec)
{
bool threadSupport = true;
bool enable_advanced_sensing = false;
Expand All @@ -159,7 +243,7 @@ DJISDKNode::initVehicle(ros::NodeHandle& nh_private)
* user can also call it as a service
* this has been tested by giving wrong appID in launch file
*/
if (ACK::getError(this->activate(this->app_id, this->enc_key)))
if (ACK::getError(this->activate(this->app_id, this->enc_key, activation_timeout_sec)))
{
ROS_ERROR("drone activation error");
return false;
Expand Down Expand Up @@ -259,17 +343,16 @@ bool DJISDKNode::isM100()


ACK::ErrorCode
DJISDKNode::activate(int l_app_id, std::string l_enc_key)
DJISDKNode::activate(int l_app_id, std::string l_enc_key, int timeout_sec)
{
usleep(1000000);
Vehicle::ActivateData testActivateData;
char app_key[65];
testActivateData.encKey = app_key;
strcpy(testActivateData.encKey, l_enc_key.c_str());
testActivateData.ID = l_app_id;

ROS_DEBUG("called vehicle->activate(&testActivateData, WAIT_TIMEOUT)");
return vehicle->activate(&testActivateData, WAIT_TIMEOUT);
ROS_DEBUG_STREAM("called vehicle->activate(&testActivateData, " << timeout_sec << ")");
return vehicle->activate(&testActivateData, timeout_sec);
}

bool
Expand Down Expand Up @@ -700,12 +783,12 @@ DJISDKNode::initDataSubscribeFromFC(ros::NodeHandle& nh)
}

void
DJISDKNode::cleanUpSubscribeFromFC()
DJISDKNode::cleanUpSubscribeFromFC(int timeout_sec)
{
vehicle->subscribe->removePackage(0, WAIT_TIMEOUT);
vehicle->subscribe->removePackage(1, WAIT_TIMEOUT);
vehicle->subscribe->removePackage(2, WAIT_TIMEOUT);
vehicle->subscribe->removePackage(3, WAIT_TIMEOUT);
vehicle->subscribe->removePackage(0, timeout_sec);
vehicle->subscribe->removePackage(1, timeout_sec);
vehicle->subscribe->removePackage(2, timeout_sec);
vehicle->subscribe->removePackage(3, timeout_sec);
if (vehicle->hardSync)
{
vehicle->hardSync->unsubscribeNMEAMsgs();
Expand Down Expand Up @@ -809,3 +892,8 @@ std::string DJISDKNode::controlAuthorityErrorString(const uint32_t error_code)
else
return "";
}

void DJISDKNode::setDataRecieved(void)
{
has_recieved_data_since_prev_check_ = true;
}
2 changes: 2 additions & 0 deletions dji_sdk/src/modules/dji_sdk_node_publisher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,8 @@ DJISDKNode::publish400HzData(Vehicle *vehicle, RecvContainer recvFrame,
p->imu_publisher.publish(synced_imu);

publishStampDiff<DJISDKNode::PACKAGE_ID_400HZ>(msg_time, p->stamp_diff_400hz_pub);

p->setDataRecieved();
}

bool DJISDKNode::get400HzTimestamp
Expand Down
3 changes: 3 additions & 0 deletions dji_sdk/src/modules/dji_sdk_node_services.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ DJISDKNode::sdkCtrlAuthorityCallback(
response.result = true;
}

if (response.result)
rerequest_sdk_ctrl_on_fc_coms_reestablished_ = (request.control_enable == dji_sdk::SDKControlAuthorityRequest::REQUEST_CONTROL);

return true;
}

Expand Down