Go to the documentation of this file.00001
00013 #include <dji_sdk/dji_sdk_node.h>
00014 #include <functional>
00015 #include <dji_sdk/DJI_LIB_ROS_Adapter.h>
00016
00017
00018
00019
00020 void DJISDKNode::transparent_transmission_callback(uint8_t *buf, uint8_t len)
00021 {
00022 dji_sdk::TransparentTransmissionData transparent_transmission_data;
00023 transparent_transmission_data.data.resize(len);
00024 memcpy(&transparent_transmission_data.data[0], buf, len);
00025 data_received_from_remote_device_publisher.publish(transparent_transmission_data);
00026
00027 }
00028 void DJISDKNode::broadcast_callback()
00029 {
00030 DJI::onboardSDK::BroadcastData bc_data = rosAdapter->coreAPI->getBroadcastData();
00031
00032 DJI::onboardSDK::Version version = rosAdapter->coreAPI->getSDKVersion();
00033 unsigned short msg_flags = bc_data.dataFlag;
00034
00035 static int frame_id = 0;
00036 frame_id ++;
00037
00038 auto current_time = ros::Time::now();
00039
00040 if(msg_flags & HAS_TIME){
00041 time_stamp.header.frame_id = "/time";
00042 time_stamp.header.stamp = current_time;
00043 time_stamp.time = bc_data.timeStamp.time;
00044 time_stamp.time_ns = bc_data.timeStamp.nanoTime;
00045 time_stamp.sync_flag = bc_data.timeStamp.syncFlag;
00046 time_stamp_publisher.publish(time_stamp);
00047 }
00048
00049
00050 if ( (msg_flags & HAS_Q) && (msg_flags & HAS_W) ) {
00051 attitude_quaternion.header.frame_id = "/world";
00052 attitude_quaternion.header.stamp = current_time;
00053 attitude_quaternion.q0 = bc_data.q.q0;
00054 attitude_quaternion.q1 = bc_data.q.q1;
00055 attitude_quaternion.q2 = bc_data.q.q2;
00056 attitude_quaternion.q3 = bc_data.q.q3;
00057 attitude_quaternion.wx = bc_data.w.x;
00058 attitude_quaternion.wy = bc_data.w.y;
00059 attitude_quaternion.wz = bc_data.w.z;
00060 attitude_quaternion.ts = bc_data.timeStamp.time;
00061 attitude_quaternion_publisher.publish(attitude_quaternion);
00062 }
00063
00064
00065 if (msg_flags & HAS_POS) {
00066 global_position.header.frame_id = "/world";
00067 global_position.header.stamp = current_time;
00068 global_position.ts = bc_data.timeStamp.time;
00069 global_position.latitude = bc_data.pos.latitude * 180.0 / C_PI;
00070 global_position.longitude = bc_data.pos.longitude * 180.0 / C_PI;
00071 global_position.height = bc_data.pos.height;
00072 global_position.altitude = bc_data.pos.altitude;
00073 global_position.health = bc_data.pos.health;
00074 global_position_publisher.publish(global_position);
00075
00076
00077
00078 if (global_position.ts != 0 && global_position_ref_seted == 0 && global_position.latitude != 0 && global_position.health > 3) {
00079 global_position_ref = global_position;
00080 global_position_ref_seted = 1;
00081 }
00082
00083
00084 local_position.header.frame_id = "/world";
00085 local_position.header.stamp = current_time;
00086 gps_convert_ned(
00087 local_position.x,
00088 local_position.y,
00089 global_position.longitude,
00090 global_position.latitude,
00091 global_position_ref.longitude,
00092 global_position_ref.latitude
00093 );
00094 local_position.z = global_position.height;
00095 local_position.ts = global_position.ts;
00096 local_position_ref = local_position;
00097 local_position_publisher.publish(local_position);
00098 }
00099
00100
00101
00102 if (msg_flags & HAS_V) {
00103 velocity.header.frame_id = "/world";
00104 velocity.header.stamp = current_time;
00105 velocity.ts = bc_data.timeStamp.time;
00106 velocity.vx = bc_data.v.x;
00107 velocity.vy = bc_data.v.y;
00108 velocity.vz = bc_data.v.z;
00109 velocity.health_flag = bc_data.v.health;
00110 velocity_publisher.publish(velocity);
00111 }
00112
00113
00114 if (msg_flags & HAS_A) {
00115 acceleration.header.frame_id = "/world";
00116 acceleration.header.stamp = current_time;
00117 acceleration.ts = bc_data.timeStamp.time;
00118 acceleration.ax = bc_data.a.x;
00119 acceleration.ay = bc_data.a.y;
00120 acceleration.az = bc_data.a.z;
00121 acceleration_publisher.publish(acceleration);
00122 }
00123
00124
00125
00126 if ( (msg_flags & HAS_POS) && (msg_flags & HAS_Q) && (msg_flags & HAS_W) && (msg_flags & HAS_V) ) {
00127 odometry.header.frame_id = "/world";
00128 odometry.header.stamp = current_time;
00129 odometry.pose.pose.position.x = local_position.x;
00130 odometry.pose.pose.position.y = local_position.y;
00131 odometry.pose.pose.position.z = local_position.z;
00132 odometry.pose.pose.orientation.w = attitude_quaternion.q0;
00133 odometry.pose.pose.orientation.x = attitude_quaternion.q1;
00134 odometry.pose.pose.orientation.y = attitude_quaternion.q2;
00135 odometry.pose.pose.orientation.z = attitude_quaternion.q3;
00136 odometry.twist.twist.angular.x = attitude_quaternion.wx;
00137 odometry.twist.twist.angular.y = attitude_quaternion.wy;
00138 odometry.twist.twist.angular.z = attitude_quaternion.wz;
00139 odometry.twist.twist.linear.x = velocity.vx;
00140 odometry.twist.twist.linear.y = velocity.vy;
00141 odometry.twist.twist.linear.z = velocity.vz;
00142 odometry_publisher.publish(odometry);
00143 }
00144
00145
00146
00147
00148
00149 if(version == DJI::onboardSDK::versionA3_31 || DJI::onboardSDK::versionA3_32) {
00150
00151
00152 if (msg_flags & A3_HAS_GIMBAL) {
00153 gimbal.header.frame_id = "/gimbal";
00154 gimbal.header.stamp= current_time;
00155 gimbal.ts = bc_data.timeStamp.time;
00156 gimbal.roll = bc_data.gimbal.roll;
00157 gimbal.pitch = bc_data.gimbal.pitch;
00158 gimbal.yaw = bc_data.gimbal.yaw;
00159 gimbal_publisher.publish(gimbal);
00160 }
00161
00162
00163 if (msg_flags & A3_HAS_RC) {
00164 rc_channels.header.frame_id = "/rc";
00165 rc_channels.header.stamp = current_time;
00166 rc_channels.ts = bc_data.timeStamp.time;
00167 rc_channels.pitch = bc_data.rc.pitch;
00168 rc_channels.roll = bc_data.rc.roll;
00169 rc_channels.mode = bc_data.rc.mode;
00170 rc_channels.gear = bc_data.rc.gear;
00171 rc_channels.throttle = bc_data.rc.throttle;
00172 rc_channels.yaw = bc_data.rc.yaw;
00173 rc_channels_publisher.publish(rc_channels);
00174 }
00175
00176
00177 if (msg_flags & A3_HAS_GPS){
00178 A3_GPS.date = bc_data.gps.date;
00179 A3_GPS.time = bc_data.gps.time;
00180 A3_GPS.longitude = bc_data.gps.longitude;
00181 A3_GPS.latitude = bc_data.gps.latitude;
00182 A3_GPS.height_above_sea = bc_data.gps.Hmsl;
00183 A3_GPS.velocity_north = bc_data.gps.velocityNorth;
00184 A3_GPS.velocity_east= bc_data.gps.velocityEast;
00185 A3_GPS.velocity_ground = bc_data.gps.velocityGround;
00186 A3_GPS_info_publisher.publish(A3_GPS);
00187 }
00188 if (msg_flags & A3_HAS_RTK)
00189 A3_RTK.date = bc_data.rtk.date;
00190 A3_RTK.time = bc_data.rtk.time;
00191 A3_RTK.longitude_RTK = bc_data.rtk.longitude;
00192 A3_RTK.latitude_RTK = bc_data.rtk.latitude;
00193 A3_RTK.height_above_sea_RTK = bc_data.rtk.Hmsl;
00194 A3_RTK.velocity_north = bc_data.rtk.velocityNorth;
00195 A3_RTK.velocity_east = bc_data.rtk.velocityEast;
00196 A3_RTK.velocity_ground = bc_data.rtk.velocityGround;
00197 A3_RTK.yaw = bc_data.rtk.yaw;
00198 A3_RTK.position_flag = bc_data.rtk.posFlag;
00199 A3_RTK.yaw_flag = bc_data.rtk.yawFlag;
00200 A3_RTK_info_publisher.publish(A3_RTK);
00201
00202
00203 if (msg_flags & A3_HAS_MAG) {
00204 compass.header.frame_id = "/world";
00205 compass.header.stamp = current_time;
00206 compass.ts = bc_data.timeStamp.time;
00207 compass.x = bc_data.mag.x;
00208 compass.y = bc_data.mag.y;
00209 compass.z = bc_data.mag.z;
00210 compass_publisher.publish(compass);
00211 }
00212
00213
00214 if (msg_flags & A3_HAS_STATUS) {
00215 std_msgs::UInt8 msg;
00216 flight_status = bc_data.status;
00217 msg.data = flight_status;
00218 flight_status_publisher.publish(msg);
00219 }
00220
00221
00222 if (msg_flags & A3_HAS_BATTERY) {
00223 power_status.percentage = bc_data.battery;
00224 power_status_publisher.publish(power_status);
00225 }
00226
00227
00228 if (msg_flags & A3_HAS_DEVICE) {
00229 flight_control_info.control_mode = bc_data.ctrlInfo.mode;
00230 flight_control_info.cur_ctrl_dev_in_navi_mode = bc_data.ctrlInfo.deviceStatus;
00231 flight_control_info.serial_req_status = bc_data.ctrlInfo.flightStatus;
00232 flight_control_info.virtual_rc_status = bc_data.ctrlInfo.vrcStatus;
00233 flight_control_info_publisher.publish(flight_control_info);
00234 }
00235
00236 }
00237
00238
00239
00240
00241
00242 else {
00243
00244 if (msg_flags & HAS_GIMBAL) {
00245 gimbal.header.frame_id = "/gimbal";
00246 gimbal.header.stamp= current_time;
00247 gimbal.ts = bc_data.timeStamp.time;
00248 gimbal.roll = bc_data.gimbal.roll;
00249 gimbal.pitch = bc_data.gimbal.pitch;
00250 gimbal.yaw = bc_data.gimbal.yaw;
00251 gimbal_publisher.publish(gimbal);
00252 }
00253
00254
00255 if (msg_flags & HAS_RC) {
00256 rc_channels.header.frame_id = "/rc";
00257 rc_channels.header.stamp = current_time;
00258 rc_channels.ts = bc_data.timeStamp.time;
00259 rc_channels.pitch = bc_data.rc.pitch;
00260 rc_channels.roll = bc_data.rc.roll;
00261 rc_channels.mode = bc_data.rc.mode;
00262 rc_channels.gear = bc_data.rc.gear;
00263 rc_channels.throttle = bc_data.rc.throttle;
00264 rc_channels.yaw = bc_data.rc.yaw;
00265 rc_channels_publisher.publish(rc_channels);
00266 }
00267
00268
00269
00270
00271 if (msg_flags & HAS_MAG) {
00272 compass.header.frame_id = "/world";
00273 compass.header.stamp = current_time;
00274 compass.ts = bc_data.timeStamp.time;
00275 compass.x = bc_data.mag.x;
00276 compass.y = bc_data.mag.y;
00277 compass.z = bc_data.mag.z;
00278 compass_publisher.publish(compass);
00279 }
00280
00281
00282 if (msg_flags & HAS_STATUS) {
00283 std_msgs::UInt8 msg;
00284 flight_status = bc_data.status;
00285 msg.data = flight_status;
00286 flight_status_publisher.publish(msg);
00287 }
00288
00289
00290 if (msg_flags & HAS_BATTERY) {
00291 power_status.percentage = bc_data.battery;
00292 power_status_publisher.publish(power_status);
00293 }
00294
00295
00296 if (msg_flags & HAS_DEVICE) {
00297 flight_control_info.control_mode = bc_data.ctrlInfo.mode;
00298 flight_control_info.cur_ctrl_dev_in_navi_mode = bc_data.ctrlInfo.deviceStatus;
00299 flight_control_info.serial_req_status = bc_data.ctrlInfo.flightStatus;
00300 flight_control_info.virtual_rc_status = bc_data.ctrlInfo.vrcStatus;
00301 flight_control_info_publisher.publish(flight_control_info);
00302 }
00303
00304 }
00305
00306
00307
00308
00309 std_msgs::UInt8 msg;
00310 activation_result = bc_data.activation;
00311 msg.data = bc_data.activation;
00312 activation_publisher.publish(msg);
00313
00314 }
00315
00316
00317
00318 int DJISDKNode::init_parameters(ros::NodeHandle& nh_private)
00319 {
00320 std::string drone_version;
00321 std::string serial_name;
00322 int baud_rate;
00323 int app_id;
00324 int app_version;
00325 std::string app_bundle_id;
00326 std::string enc_key;
00327 int uart_or_usb;
00328
00329
00330 nh_private.param("serial_name", serial_name, std::string("/dev/ttyTHS1"));
00331 nh_private.param("baud_rate", baud_rate, 230400);
00332 nh_private.param("app_id", app_id, 1022384);
00333 nh_private.param("app_version", app_version, 1);
00334 nh_private.param("enc_key", enc_key,
00335 std::string("e7bad64696529559318bb35d0a8c6050d3b88e791e1808cfe8f7802150ee6f0d"));
00336
00337 nh_private.param("uart_or_usb", uart_or_usb, 0);
00338 nh_private.param("drone_version", drone_version, std::string("M100"));
00339
00340
00341 user_act_data.ID = app_id;
00342
00343 if((uart_or_usb)&&(drone_version.compare("M100")))
00344 {
00345 printf("M100 does not support USB API.\n");
00346 return -1;
00347 }
00348
00349 if(!drone_version.compare("M100"))
00350 {
00351 user_act_data.version = versionM100_31;
00352 }
00353 else if (!drone_version.compare("A3_31"))
00354 {
00355 user_act_data.version = versionA3_31;
00356 }
00357 else if (!drone_version.compare("A3_32"))
00358 {
00359 user_act_data.version = versionA3_32;
00360 }
00361 user_act_data.encKey = app_key;
00362 strcpy(user_act_data.encKey, enc_key.c_str());
00363
00364 printf("=================================================\n");
00365 printf("app id: %d\n", user_act_data.ID);
00366 printf("app version: 0x0%X\n", user_act_data.version);
00367 printf("app key: %s\n", user_act_data.encKey);
00368 printf("=================================================\n");
00369
00370 if(uart_or_usb)
00371 {
00372 rosAdapter->usbHandshake(serial_name);
00373 }
00374
00375 rosAdapter->init(serial_name, baud_rate);
00376 rosAdapter->activate(&user_act_data, NULL);
00377 rosAdapter->setBroadcastCallback(&DJISDKNode::broadcast_callback, this);
00378 rosAdapter->setFromMobileCallback(&DJISDKNode::transparent_transmission_callback,this);
00379
00380 return 0;
00381 }
00382
00383
00384
00385 DJISDKNode::DJISDKNode(ros::NodeHandle& nh, ros::NodeHandle& nh_private) : dji_sdk_mission(nullptr)
00386 {
00387
00388 init_publishers(nh);
00389 init_services(nh);
00390 init_actions(nh);
00391
00392
00393 init_parameters(nh_private);
00394
00395 int groundstation_enable;
00396 nh_private.param("groundstation_enable", groundstation_enable, 1);
00397 if(groundstation_enable)
00398 {
00399 dji_sdk_mission = new DJISDKMission(nh);
00400 }
00401
00402 }
00403
00404
00405 void DJISDKNode::gps_convert_ned(float &ned_x, float &ned_y,
00406 double gps_t_lon, double gps_t_lat,
00407 double gps_r_lon, double gps_r_lat)
00408 {
00409 double d_lon = gps_t_lon - gps_r_lon;
00410 double d_lat = gps_t_lat - gps_r_lat;
00411 ned_x = DEG2RAD(d_lat) * C_EARTH;
00412 ned_y = DEG2RAD(d_lon) * C_EARTH * cos(DEG2RAD(gps_t_lat));
00413 };
00414
00415 dji_sdk::LocalPosition DJISDKNode::gps_convert_ned(dji_sdk::GlobalPosition loc)
00416 {
00417 dji_sdk::LocalPosition local;
00418 gps_convert_ned(local.x, local.y,
00419 loc.longitude, loc.latitude,
00420 global_position_ref.longitude, global_position_ref.latitude
00421 );
00422 local.z = loc.height;
00423 return local;
00424 }
00425