00001 #include "ardrone_driver.h"
00002 #include "teleop_twist.h"
00003 #include "video.h"
00004 #include <signal.h>
00005
00007
00009
00010 ARDroneDriver::ARDroneDriver()
00011 : image_transport(node_handle),
00012
00013 initialized_navdata_publishers(false)
00014 {
00015 inited = false;
00016 last_frame_id = -1;
00017 last_navdata_id = -1;
00018 cmd_vel_sub = node_handle.subscribe("cmd_vel", 1, &cmdVelCallback);
00019 takeoff_sub = node_handle.subscribe("ardrone/takeoff", 1, &takeoffCallback);
00020 reset_sub = node_handle.subscribe("ardrone/reset", 1, &resetCallback);
00021 land_sub = node_handle.subscribe("ardrone/land", 1, &landCallback);
00022 image_pub = image_transport.advertiseCamera("ardrone/image_raw", 10);
00023 hori_pub = image_transport.advertiseCamera("ardrone/front/image_raw", 10);
00024 vert_pub = image_transport.advertiseCamera("ardrone/bottom/image_raw", 10);
00025 toggleCam_service = node_handle.advertiseService("ardrone/togglecam", toggleCamCallback);
00026 setCamChannel_service = node_handle.advertiseService("ardrone/setcamchannel",setCamChannelCallback );
00027 setLedAnimation_service = node_handle.advertiseService("ardrone/setledanimation", setLedAnimationCallback);
00028 flatTrim_service = node_handle.advertiseService("ardrone/flattrim", flatTrimCallback);
00029 setFlightAnimation_service = node_handle.advertiseService("ardrone/setflightanimation", setFlightAnimationCallback);
00030 setRecord_service = node_handle.advertiseService("ardrone/setrecord", setRecordCallback );
00031
00032
00033
00034
00035
00036 imuReCalib_service = node_handle.advertiseService<std_srvs::Empty::Request, std_srvs::Empty::Response>
00037 ("ardrone/imu_recalib", boost::bind(&ARDroneDriver::imuReCalibCallback, this, _1, _2));
00038
00039
00040
00041
00042 droneFrameId = (ros::param::get("~drone_frame_id", droneFrameId)) ? droneFrameId : "ardrone_base";
00043 droneFrameBase = droneFrameId + "_link";
00044 droneFrameIMU = droneFrameId + "_imu";
00045 droneFrameFrontCam = droneFrameId + "_frontcam";
00046 droneFrameBottomCam = droneFrameId + "_bottomcam";
00047
00048 drone_root_frame = (ros::param::get("~root_frame", drone_root_frame)) ? drone_root_frame : ROOT_FRAME_BASE;
00049 drone_root_frame = drone_root_frame % ROOT_FRAME_NUM;
00050 ROS_INFO("Root Frame is: %d", drone_root_frame);
00051
00052
00053
00054
00055 for (int i = 0; i < 9; i++)
00056 {
00057 imu_msg.linear_acceleration_covariance[i] = 0.0;
00058 imu_msg.angular_velocity_covariance[i] = 0.0;
00059 imu_msg.orientation_covariance[i] = 0.0;
00060 }
00061 readCovParams("~cov/imu_la", imu_msg.linear_acceleration_covariance);
00062 readCovParams("~cov/imu_av", imu_msg.angular_velocity_covariance);
00063 readCovParams("~cov/imu_or", imu_msg.orientation_covariance);
00064
00065
00066 max_num_samples = 50;
00067 do_caliberation = (ros::param::get("~do_imu_caliberation", do_caliberation)) ? do_caliberation : false;
00068 if (do_caliberation) {
00069 resetCaliberation();
00070 ROS_WARN("Automatic IMU Caliberation is active.");
00071 }
00072
00073
00074 cinfo_hori_ = new camera_info_manager::CameraInfoManager(ros::NodeHandle("ardrone/front"), "ardrone_front");
00075 cinfo_vert_ = new camera_info_manager::CameraInfoManager(ros::NodeHandle("ardrone/bottom"), "ardrone_bottom");
00076
00077
00078
00079
00080
00081
00082 tf_base_front = tf::StampedTransform(
00083 tf::Transform(
00084 tf::createQuaternionFromRPY(-90.0 * _DEG2RAD, 0.0, -90.0 * _DEG2RAD),
00085 tf::Vector3(0.21, 0.0, 0.0)),
00086 ros::Time::now(), droneFrameBase, droneFrameFrontCam
00087 );
00088
00089
00090
00091
00092 tf_base_bottom = tf::StampedTransform(
00093 tf::Transform(
00094 tf::createQuaternionFromRPY(180.0 * _DEG2RAD, 0.0, 90.0 * _DEG2RAD),
00095 tf::Vector3(0.0, -0.02, 0.0)),
00096 ros::Time::now(), droneFrameBase, droneFrameBottomCam
00097 );
00098
00099
00100 if (drone_root_frame == ROOT_FRAME_FRONT)
00101 {
00102 tf_base_front.setData(tf_base_front.inverse());
00103 tf_base_front.child_frame_id_.swap(tf_base_front.frame_id_);
00104 }
00105 else if (drone_root_frame == ROOT_FRAME_BOTTOM)
00106 {
00107 tf_base_bottom.setData(tf_base_bottom.inverse());
00108 tf_base_bottom.child_frame_id_.swap(tf_base_bottom.frame_id_);
00109 }
00110
00111 }
00112
00113 ARDroneDriver::~ARDroneDriver()
00114 {
00115 delete cinfo_hori_;
00116 delete cinfo_vert_;
00117 }
00118
00119 void ARDroneDriver::run()
00120 {
00121 ros::Rate loop_rate(looprate);
00122 const ros::Time startTime = ros::Time::now();
00123 static int freq_dev = 0;
00124 while (node_handle.ok())
00125 {
00126 if (!inited)
00127 {
00128 if (((ros::Time::now() - startTime).toSec()) > 5.0)
00129 {
00130 inited = true;
00131
00132
00133 configureDrone();
00134
00135 vp_os_mutex_lock(&navdata_lock);
00136 ROS_INFO("Successfully connected to '%s' (AR-Drone %d.0 - Firmware: %s) - Battery(\%): %d",
00137 ardrone_control_config.ardrone_name,
00138 (IS_ARDRONE1) ? 1 : 2,
00139 ardrone_control_config.num_version_soft,
00140 shared_raw_navdata->navdata_demo.vbat_flying_percentage);
00141 ROS_INFO("Navdata Publish Settings:");
00142 ROS_INFO(" Legacy Navdata Mode: %s", enabled_legacy_navdata ? "On" : "Off");
00143 ROS_INFO(" ROS Loop Rate: %d Hz", looprate);
00144 ROS_INFO(" Realtime Navdata Publish: %s", realtime_navdata ? "On" : "Off");
00145 ROS_INFO(" Realtime Video Publish: %s", realtime_video ? "On" : "Off");
00146 ROS_INFO(" Drone Navdata Send Speed: %s", ardrone_application_default_config.navdata_demo==0 ? "200Hz (navdata_demo=0)" : "15Hz (navdata_demo=1)");
00147
00148 vp_os_mutex_unlock(&navdata_lock);
00149 if (ardrone_control_config.num_version_soft[0] == '0')
00150 {
00151 ROS_WARN("The AR-Drone has a suspicious Firmware number. It usually means the network link is unreliable.");
00152 }
00153 }
00154 } else {
00155 if (!realtime_video)
00156 {
00157 vp_os_mutex_lock(&video_lock);
00158 copy_current_frame_id = current_frame_id;
00159 vp_os_mutex_unlock(&video_lock);
00160 if (copy_current_frame_id != last_frame_id)
00161 {
00162 last_frame_id = copy_current_frame_id;
00163 publish_video();
00164 }
00165 }
00166
00167 if (!realtime_navdata)
00168 {
00169 vp_os_mutex_lock(&navdata_lock);
00170 copy_current_navdata_id = current_navdata_id;
00171 vp_os_mutex_unlock(&navdata_lock);
00172 if (copy_current_navdata_id != last_navdata_id)
00173 {
00174 vp_os_mutex_lock(&navdata_lock);
00175 last_navdata_id = copy_current_navdata_id;
00176
00177
00178
00179
00180 navdata_unpacked_t navdata_raw = *shared_raw_navdata;
00181 ros::Time navdata_receive_time = shared_navdata_receive_time;
00182 vp_os_mutex_unlock(&navdata_lock);
00183
00184 PublishNavdataTypes(navdata_raw, navdata_receive_time);
00185 publish_navdata(navdata_raw, navdata_receive_time);
00186 }
00187 }
00188 if (freq_dev == 0) publish_tf();
00189
00190 freq_dev = (freq_dev + 1) % 5;
00191 }
00192 ros::spinOnce();
00193 loop_rate.sleep();
00194 }
00195 printf("ROS loop terminated ... \n");
00196 }
00197
00198 void ARDroneDriver::configureDrone()
00199 {
00200
00201
00202 #undef ARDRONE_CONFIG_KEY_IMM_a10
00203 #undef ARDRONE_CONFIG_KEY_REF_a10
00204 #undef ARDRONE_CONFIG_KEY_STR_a10
00205 #undef LOAD_PARAM_STR
00206 #undef LOAD_PARAM_NUM
00207
00208 #define SEND_PARAM_NUM(NAME,CATEGORY,DEFAULT) \
00209 { \
00210 if(ardrone_application_default_config.NAME!=DEFAULT) \
00211 { \
00212 ROS_INFO(" SEND: "#CATEGORY"/"#NAME" = %f (DEFAULT = %f)", (float)ardrone_application_default_config.NAME, (float)DEFAULT); \
00213 ARDRONE_TOOL_CONFIGURATION_ADDEVENT (NAME, &ardrone_application_default_config.NAME, NULL); \
00214 } \
00215 }
00216
00217 #define SEND_PARAM_STR(NAME,CATEGORY,DEFAULT) \
00218 { \
00219 if(0!=strcmp(ardrone_application_default_config.NAME,DEFAULT)) \
00220 { \
00221 ROS_INFO("SEND: "#CATEGORY"/"#NAME" = %s (DEFAULT = %s)", ardrone_application_default_config.NAME, DEFAULT); \
00222 ARDRONE_TOOL_CONFIGURATION_ADDEVENT (NAME, ardrone_application_default_config.NAME, NULL); \
00223 } \
00224 }
00225
00226
00227 #define ARDRONE_CONFIG_KEY_REF_a10(KEY, NAME, INI_TYPE, C_TYPE, C_TYPE_PTR, RW, RW_CUSTOM, DEFAULT, CALLBACK, CATEGORY) //do nothing for reference-only parameters
00228 #define ARDRONE_CONFIG_KEY_IMM_a10(KEY, NAME, INI_TYPE, C_TYPE, C_TYPE_PTR, RW, RW_CUSTOM, DEFAULT, CALLBACK, CATEGORY) { if(0!=strcmp(KEY,"custom") && CATEGORY==CAT_COMMON && ((RW & K_WRITE) != 0 || (RW_CUSTOM & K_WRITE) != 0)) SEND_PARAM_NUM(NAME,CATEGORY,DEFAULT) } // parameters under the custom key are for control of application/user/session, we don't want to change these!
00229 #define ARDRONE_CONFIG_KEY_STR_a10(KEY, NAME, INI_TYPE, C_TYPE, C_TYPE_PTR, RW, RW_CUSTOM, DEFAULT, CALLBACK, CATEGORY) { if(0!=strcmp(KEY,"custom") && CATEGORY==CAT_COMMON && ((RW & K_WRITE) != 0 || (RW_CUSTOM & K_WRITE) != 0)) SEND_PARAM_STR(NAME,CATEGORY,DEFAULT) }
00230
00231 #include <config_keys.h>
00232
00233 #undef ARDRONE_CONFIG_KEY_IMM_a10
00234 #undef ARDRONE_CONFIG_KEY_STR_a10
00235
00236
00237
00238 #define ARDRONE_CONFIG_KEY_IMM_a10(KEY, NAME, INI_TYPE, C_TYPE, C_TYPE_PTR, RW, RW_CUSTOM, DEFAULT, CALLBACK, CATEGORY) { if(0!=strcmp(KEY,"custom") && CATEGORY!=CAT_COMMON && ((RW & K_WRITE) != 0 || (RW_CUSTOM & K_WRITE) != 0)) SEND_PARAM_NUM(NAME,CATEGORY,DEFAULT) } // parameters under the custom key are for control of application/user/session, we don't want to change these!
00239 #define ARDRONE_CONFIG_KEY_STR_a10(KEY, NAME, INI_TYPE, C_TYPE, C_TYPE_PTR, RW, RW_CUSTOM, DEFAULT, CALLBACK, CATEGORY) { if(0!=strcmp(KEY,"custom") && CATEGORY!=CAT_COMMON && ((RW & K_WRITE) != 0 || (RW_CUSTOM & K_WRITE) != 0)) SEND_PARAM_STR(NAME,CATEGORY,DEFAULT) }
00240
00241 #include <config_keys.h>
00242
00243 #undef SEND_PARAM_NUM
00244 #undef SEND_PARAM_STR
00245 #undef ARDRONE_CONFIG_KEY_IMM_a10
00246 #undef ARDRONE_CONFIG_KEY_REF_a10
00247 #undef ARDRONE_CONFIG_KEY_STR_a10
00248
00249
00250 #define NAVDATA_STRUCTS_INITIALIZE
00251 #include "NavdataMessageDefinitions.h"
00252 #undef NAVDATA_STRUCTS_INITIALIZE
00253 }
00254
00255 void ARDroneDriver::resetCaliberation()
00256 {
00257 caliberated = false;
00258 acc_samples.clear();
00259 gyro_samples.clear();
00260 vel_samples.clear();
00261 for (int i = 0; i < 3; i++)
00262 {
00263 acc_bias[i] = 0.0;
00264 vel_bias[i] = 0.0;
00265 gyro_bias[i] = 0.0;
00266 acc_samples.push_back(std::vector<double> ());
00267 gyro_samples.push_back(std::vector<double> ());
00268 vel_samples.push_back(std::vector<double> ());
00269 }
00270 }
00271
00272 double ARDroneDriver::calcAverage(std::vector<double> &vec)
00273 {
00274 double ret = 0.0;
00275 for (unsigned int i = 0; i < vec.size(); i++)
00276 {
00277 ret += vec.at(i);
00278 }
00279 return (ret / vec.size());
00280 }
00281
00282 bool ARDroneDriver::readCovParams(std::string param_name, boost::array<double, 9> &cov_array)
00283 {
00284 XmlRpc::XmlRpcValue cov_list;
00285 std::stringstream str_stream;
00286 if (ros::param::get(param_name, cov_list))
00287 {
00288 if (cov_list.getType() != XmlRpc::XmlRpcValue::TypeArray)
00289 {
00290 ROS_WARN("Covariance values for %s is not a list", param_name.c_str());
00291 return false;
00292 }
00293
00294 if (cov_list.size() != 9)
00295 {
00296 ROS_WARN("Covariance list size for %s is not of size 9 (Size: %d)", param_name.c_str(), cov_list.size());
00297 return false;
00298 }
00299 str_stream << param_name << " set to [";
00300 for (int32_t i = 0; i < cov_list.size(); i++)
00301 {
00302 ROS_ASSERT(cov_list[i].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00303 cov_array[i] = static_cast<double> (cov_list[i]);
00304 str_stream << cov_array[i] << ((i < 8) ? ", " : "");
00305 }
00306 str_stream << "]";
00307 ROS_INFO(str_stream.str().c_str());
00308 return true;
00309
00310 }
00311 else
00312 {
00313 ROS_INFO("No values found for `%s` in parameters, set all to zero.", param_name.c_str());
00314 return false;
00315 }
00316
00317 }
00318
00319 double ARDroneDriver::getRosParam(char* param, double defaultVal)
00320 {
00321 std::string name(param);
00322 double res, ret;
00323 ret = (ros::param::get(name, res)) ? res : defaultVal;
00324 ROS_INFO("SET %-30s: %4.2f", param, ret);
00325 return ret;
00326 }
00327
00328 void ARDroneDriver::publish_video()
00329 {
00330 if (
00331 (image_pub.getNumSubscribers() == 0) &&
00332 (hori_pub.getNumSubscribers() == 0) &&
00333 (vert_pub.getNumSubscribers() == 0)
00334 ) return;
00335
00336
00337
00338 sensor_msgs::CameraInfo cinfo_msg_hori = cinfo_hori_->getCameraInfo();
00339 sensor_msgs::CameraInfo cinfo_msg_vert = cinfo_vert_->getCameraInfo();
00340
00341 cinfo_msg_hori.header.frame_id = droneFrameFrontCam;
00342 cinfo_msg_vert.header.frame_id = droneFrameBottomCam;
00343
00344 if (IS_ARDRONE1)
00345 {
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 sensor_msgs::Image image_msg;
00365 sensor_msgs::Image::_data_type::iterator _it;
00366
00367 image_msg.header.stamp = ros::Time::now();
00368 if ((cam_state == ZAP_CHANNEL_HORI) || (cam_state == ZAP_CHANNEL_LARGE_HORI_SMALL_VERT))
00369 {
00370 image_msg.header.frame_id = droneFrameFrontCam;
00371 }
00372 else if ((cam_state == ZAP_CHANNEL_VERT) || (cam_state == ZAP_CHANNEL_LARGE_VERT_SMALL_HORI))
00373 {
00374 image_msg.header.frame_id = droneFrameBottomCam;
00375 }
00376 else
00377 {
00378 ROS_WARN_ONCE("Something is wrong with camera channel config.");
00379 }
00380
00381 image_msg.width = D1_STREAM_WIDTH;
00382 image_msg.height = D1_STREAM_HEIGHT;
00383 image_msg.encoding = "rgb8";
00384 image_msg.is_bigendian = false;
00385 image_msg.step = D1_STREAM_WIDTH*3;
00386 image_msg.data.resize(D1_STREAM_WIDTH*D1_STREAM_HEIGHT*3);
00387
00388 if(!realtime_video) vp_os_mutex_lock(&video_lock);
00389 std::copy(buffer, buffer+(D1_STREAM_WIDTH*D1_STREAM_HEIGHT*3), image_msg.data.begin());
00390 if(!realtime_video) vp_os_mutex_unlock(&video_lock);
00391
00392 if (cam_state == ZAP_CHANNEL_HORI)
00393 {
00394
00395
00396
00397 cinfo_msg_hori.width = D1_STREAM_WIDTH;
00398 cinfo_msg_hori.height = D1_STREAM_HEIGHT;
00399
00400 image_pub.publish(image_msg, cinfo_msg_hori);
00401 hori_pub.publish(image_msg, cinfo_msg_hori);
00402 }
00403 else if (cam_state == ZAP_CHANNEL_VERT)
00404 {
00405
00406
00407
00408 image_msg.width = D1_VERTSTREAM_WIDTH;
00409 image_msg.height = D1_VERTSTREAM_HEIGHT;
00410 image_msg.encoding = "rgb8";
00411 image_msg.is_bigendian = false;
00412 image_msg.step = D1_VERTSTREAM_WIDTH*3;
00413 image_msg.data.clear();
00414 image_msg.data.resize(D1_VERTSTREAM_WIDTH*D1_VERTSTREAM_HEIGHT*3);
00415 _it = image_msg.data.begin();
00416 if(!realtime_video) vp_os_mutex_lock(&video_lock);
00417 for (int row = 0; row < D1_VERTSTREAM_HEIGHT ; row++)
00418 {
00419 int _b = row * D1_STREAM_WIDTH * 3;
00420 int _e = _b + image_msg.step;
00421 _it = std::copy(buffer + _b, buffer + _e, _it);
00422 }
00423 if(!realtime_video) vp_os_mutex_unlock(&video_lock);
00424
00425 cinfo_msg_vert.width = D1_VERTSTREAM_WIDTH;
00426 cinfo_msg_vert.height = D1_VERTSTREAM_HEIGHT;
00427 image_pub.publish(image_msg, cinfo_msg_vert);
00428 vert_pub.publish(image_msg, cinfo_msg_vert);
00429 }
00430 else if (cam_state == ZAP_CHANNEL_LARGE_HORI_SMALL_VERT)
00431 {
00432
00433
00434
00435
00436
00437
00438 image_msg.width = D1_STREAM_WIDTH - D1_MODE2_PIP_WIDTH;
00439 image_msg.height = D1_STREAM_HEIGHT;
00440 image_msg.encoding = "rgb8";
00441 image_msg.is_bigendian = false;
00442 image_msg.step = (D1_STREAM_WIDTH-D1_MODE2_PIP_WIDTH)*3;
00443 image_msg.data.clear();
00444 image_msg.data.resize((D1_STREAM_WIDTH - D1_MODE2_PIP_WIDTH)*D1_STREAM_HEIGHT*3);
00445 _it = image_msg.data.begin();
00446 if(!realtime_video) vp_os_mutex_lock(&video_lock);
00447 for (int row = 0; row < D1_STREAM_HEIGHT; row++)
00448 {
00449 int _b = (row * D1_STREAM_WIDTH * 3) + (D1_MODE2_PIP_WIDTH * 3);
00450 int _e = _b + image_msg.step;
00451 _it = std::copy(buffer + _b, buffer + _e, _it);
00452 }
00453 if(!realtime_video) vp_os_mutex_unlock(&video_lock);
00454
00455 cinfo_msg_hori.width = D1_STREAM_WIDTH - D1_MODE2_PIP_WIDTH;
00456 cinfo_msg_hori.height = D1_STREAM_HEIGHT;
00457 hori_pub.publish(image_msg, cinfo_msg_hori);
00458
00459
00460 image_msg.width = D1_MODE2_PIP_WIDTH;
00461 image_msg.height = D1_MODE2_PIP_HEIGHT;
00462 image_msg.encoding = "rgb8";
00463 image_msg.is_bigendian = false;
00464 image_msg.step = D1_MODE2_PIP_WIDTH * 3;
00465 image_msg.data.clear();
00466 image_msg.data.resize(D1_MODE2_PIP_WIDTH * D1_MODE2_PIP_HEIGHT * 3);
00467 _it = image_msg.data.begin();
00468 if(!realtime_video) vp_os_mutex_lock(&video_lock);
00469 for (int row = 0; row < D1_MODE2_PIP_HEIGHT; row++)
00470 {
00471 int _b = row * D1_STREAM_WIDTH * 3;
00472 int _e = _b + image_msg.step;
00473 _it = std::copy(buffer + _b, buffer + _e, _it);
00474 }
00475 if(!realtime_video) vp_os_mutex_unlock(&video_lock);
00476
00477 cinfo_msg_vert.width = D1_MODE2_PIP_WIDTH;
00478 cinfo_msg_vert.height = D1_MODE2_PIP_HEIGHT;
00479 vert_pub.publish(image_msg, cinfo_msg_vert);
00480 }
00481 else if (cam_state == ZAP_CHANNEL_LARGE_VERT_SMALL_HORI)
00482 {
00483
00484
00485
00486
00487
00488
00489 image_msg.width = D1_VERTSTREAM_WIDTH - D1_MODE3_PIP_WIDTH;
00490 image_msg.height = D1_VERTSTREAM_HEIGHT;
00491 image_msg.encoding = "rgb8";
00492 image_msg.is_bigendian = false;
00493 image_msg.step = (D1_VERTSTREAM_WIDTH - D1_MODE3_PIP_WIDTH)*3;
00494 image_msg.data.clear();
00495 image_msg.data.resize((D1_VERTSTREAM_WIDTH - D1_MODE3_PIP_WIDTH)* D1_VERTSTREAM_HEIGHT*3);
00496 _it = image_msg.data.begin();
00497 for (int row = 0; row < D1_VERTSTREAM_HEIGHT; row++)
00498 {
00499 int _b = (row * (D1_STREAM_WIDTH * 3)) + (D1_MODE3_PIP_WIDTH * 3);
00500 int _e = _b + image_msg.step;
00501 if(!realtime_video) vp_os_mutex_lock(&video_lock);
00502 _it = std::copy(buffer + _b, buffer + _e, _it);
00503 if(!realtime_video) vp_os_mutex_unlock(&video_lock);
00504 }
00505
00506 cinfo_msg_vert.width = D1_VERTSTREAM_WIDTH - D1_MODE3_PIP_WIDTH;
00507 cinfo_msg_vert.height = D1_VERTSTREAM_HEIGHT;
00508 vert_pub.publish(image_msg, cinfo_msg_vert);
00509
00510
00511 image_msg.width = D1_MODE3_PIP_WIDTH;
00512 image_msg.height = D1_MODE3_PIP_HEIGHT;
00513 image_msg.encoding = "rgb8";
00514 image_msg.is_bigendian = false;
00515 image_msg.step = D1_MODE3_PIP_WIDTH * 3;
00516 image_msg.data.clear();
00517 image_msg.data.resize(D1_MODE3_PIP_WIDTH * D1_MODE3_PIP_HEIGHT * 3);
00518 _it = image_msg.data.begin();
00519 if(!realtime_video) vp_os_mutex_lock(&video_lock);
00520 for (int row = 0; row < D1_MODE3_PIP_HEIGHT; row++)
00521 {
00522 int _b = row * D1_STREAM_WIDTH * 3;
00523 int _e = _b + image_msg.step;
00524 _it = std::copy(buffer + _b, buffer + _e, _it);
00525 }if(!realtime_video) vp_os_mutex_unlock(&video_lock);
00526
00527 cinfo_msg_hori.width = D1_MODE3_PIP_WIDTH;
00528 cinfo_msg_hori.height = D1_MODE3_PIP_HEIGHT;
00529 hori_pub.publish(image_msg, cinfo_msg_hori);
00530 }
00531 }
00532
00538 if (IS_ARDRONE2)
00539 {
00540 sensor_msgs::Image image_msg;
00541 sensor_msgs::Image::_data_type::iterator _it;
00542
00543 image_msg.header.stamp = ros::Time::now();
00544 cinfo_msg_hori.header.stamp = image_msg.header.stamp;
00545 cinfo_msg_vert.header.stamp = image_msg.header.stamp;
00546
00547 if (cam_state == ZAP_CHANNEL_HORI)
00548 {
00549 image_msg.header.frame_id = droneFrameFrontCam;
00550 }
00551 else if (cam_state == ZAP_CHANNEL_VERT)
00552 {
00553 image_msg.header.frame_id = droneFrameBottomCam;
00554 }
00555 else
00556 {
00557 ROS_WARN_ONCE("Something is wrong with camera channel config.");
00558 }
00559
00560 image_msg.width = D2_STREAM_WIDTH;
00561 image_msg.height = D2_STREAM_HEIGHT;
00562 image_msg.encoding = "rgb8";
00563 image_msg.is_bigendian = false;
00564 image_msg.step = D2_STREAM_WIDTH*3;
00565 image_msg.data.resize(D2_STREAM_WIDTH*D2_STREAM_HEIGHT*3);
00566 if(!realtime_video) vp_os_mutex_lock(&video_lock);
00567 std::copy(buffer, buffer+(D2_STREAM_WIDTH*D2_STREAM_HEIGHT*3), image_msg.data.begin());
00568 if(!realtime_video) vp_os_mutex_unlock(&video_lock);
00569
00570
00571
00572 if (cam_state == ZAP_CHANNEL_HORI)
00573 {
00574
00575
00576
00577 cinfo_msg_hori.width = D2_STREAM_WIDTH;
00578 cinfo_msg_hori.height = D2_STREAM_HEIGHT;
00579 image_pub.publish(image_msg, cinfo_msg_hori);
00580 hori_pub.publish(image_msg, cinfo_msg_hori);
00581 }
00582 else if (cam_state == ZAP_CHANNEL_VERT)
00583 {
00584
00585
00586
00587 cinfo_msg_vert.width = D2_STREAM_WIDTH;
00588 cinfo_msg_vert.height = D2_STREAM_HEIGHT;
00589 image_pub.publish(image_msg, cinfo_msg_vert);
00590 vert_pub.publish(image_msg, cinfo_msg_vert);
00591 }
00592 }
00593
00594 }
00595
00596 void ARDroneDriver::publish_navdata(navdata_unpacked_t &navdata_raw, const ros::Time &navdata_receive_time)
00597 {
00598 if ((do_caliberation) && (!caliberated))
00599 {
00600 acc_samples[0].push_back(navdata_raw.navdata_phys_measures.phys_accs[ACC_X]);
00601 acc_samples[1].push_back(navdata_raw.navdata_phys_measures.phys_accs[ACC_Y]);
00602 acc_samples[2].push_back(navdata_raw.navdata_phys_measures.phys_accs[ACC_Z]);
00603 gyro_samples[0].push_back(navdata_raw.navdata_phys_measures.phys_gyros[GYRO_X]);
00604 gyro_samples[1].push_back(navdata_raw.navdata_phys_measures.phys_gyros[GYRO_Y]);
00605 gyro_samples[2].push_back(navdata_raw.navdata_phys_measures.phys_gyros[GYRO_Z]);
00606 vel_samples[0].push_back(navdata_raw.navdata_demo.vx);
00607 vel_samples[1].push_back(navdata_raw.navdata_demo.vy);
00608 vel_samples[2].push_back(navdata_raw.navdata_demo.vz);
00609 if (acc_samples[0].size() == max_num_samples)
00610 {
00611 for (int j = 0; j < 3; j++)
00612 {
00613 acc_bias[j] = calcAverage(acc_samples[j]);
00614 gyro_bias[j] = calcAverage(gyro_samples[j]);
00615 vel_bias[j] = calcAverage(vel_samples[j]);
00616 }
00617 ROS_INFO("Bias in linear acceleration (mg): [%4.4lf, %4.4lf, %4.4lf]", acc_bias[0], acc_bias[1], acc_bias[2]);
00618 ROS_INFO("Bias in angular velocity (deg/s): [%4.4lf, %4.4lf, %4.4lf]", gyro_bias[0], gyro_bias[1], gyro_bias[2]);
00619 ROS_INFO("Bias in linear velocity (mm/s): [%4.4lf, %4.4lf, %4.4lf]", vel_bias[0], vel_bias[1], vel_bias[2]);
00620 ROS_INFO("Above values (except z-axis accel) will be substracted from actual IMU data in `navdata_raw.navdata_demo` and `imu` topic.");
00621 ROS_INFO("This feature can be disabled using `do_imu_caliberation` parameter. Recaliberate using `imu_recalib` service.");
00622 caliberated = true;
00623 }
00624 }
00625 if ((do_caliberation) && (caliberated))
00626 {
00627 for (int j = 0; j < 3; j++)
00628 {
00629 if (j != 2) navdata_raw.navdata_phys_measures.phys_accs[j] -= acc_bias[j];
00630 navdata_raw.navdata_phys_measures.phys_gyros[j] -= gyro_bias[j];
00631 }
00632 navdata_raw.navdata_demo.vx -= vel_bias[0];
00633 navdata_raw.navdata_demo.vy -= vel_bias[1];
00634 navdata_raw.navdata_demo.vz -= vel_bias[2];
00635
00636 }
00637
00638 if (!enabled_legacy_navdata || ((navdata_pub.getNumSubscribers() == 0) && (imu_pub.getNumSubscribers() == 0) && (mag_pub.getNumSubscribers() == 0)))
00639 return;
00640
00641 legacynavdata_msg.header.stamp = navdata_receive_time;
00642 legacynavdata_msg.header.frame_id = droneFrameBase;
00643 legacynavdata_msg.batteryPercent = navdata_raw.navdata_demo.vbat_flying_percentage;
00644 legacynavdata_msg.state = (navdata_raw.navdata_demo.ctrl_state >> 16);
00645
00646
00647 legacynavdata_msg.rotX = navdata_raw.navdata_demo.phi / 1000.0;
00648 legacynavdata_msg.rotY = -navdata_raw.navdata_demo.theta / 1000.0;
00649 legacynavdata_msg.rotZ = -navdata_raw.navdata_demo.psi / 1000.0;
00650
00651 legacynavdata_msg.altd = navdata_raw.navdata_demo.altitude;
00652 legacynavdata_msg.vx = navdata_raw.navdata_demo.vx;
00653 legacynavdata_msg.vy = -navdata_raw.navdata_demo.vy;
00654 legacynavdata_msg.vz = -navdata_raw.navdata_demo.vz;
00655
00656
00657 legacynavdata_msg.tm = (navdata_raw.navdata_time.time & 0x001FFFFF) + (navdata_raw.navdata_time.time >> 21)*1000000;
00658 legacynavdata_msg.ax = navdata_raw.navdata_phys_measures.phys_accs[ACC_X] / 1000.0;
00659 legacynavdata_msg.ay = -navdata_raw.navdata_phys_measures.phys_accs[ACC_Y] / 1000.0;
00660 legacynavdata_msg.az = -navdata_raw.navdata_phys_measures.phys_accs[ACC_Z] / 1000.0;
00661
00662 legacynavdata_msg.motor1 = navdata_raw.navdata_pwm.motor1;
00663 legacynavdata_msg.motor2 = navdata_raw.navdata_pwm.motor2;
00664 legacynavdata_msg.motor3 = navdata_raw.navdata_pwm.motor3;
00665 legacynavdata_msg.motor4 = navdata_raw.navdata_pwm.motor4;
00666
00667
00668
00669 if (IS_ARDRONE2)
00670 {
00671 legacynavdata_msg.magX = (int32_t)navdata_raw.navdata_magneto.mx;
00672 legacynavdata_msg.magY = (int32_t)navdata_raw.navdata_magneto.my;
00673 legacynavdata_msg.magZ = (int32_t)navdata_raw.navdata_magneto.mz;
00674
00675 legacynavdata_msg.pressure = navdata_raw.navdata_pressure_raw.Pression_meas;
00676 legacynavdata_msg.temp = navdata_raw.navdata_pressure_raw.Temperature_meas;
00677
00678 legacynavdata_msg.wind_speed = navdata_raw.navdata_wind_speed.wind_speed;
00679 legacynavdata_msg.wind_angle = navdata_raw.navdata_wind_speed.wind_angle;
00680 legacynavdata_msg.wind_comp_angle = navdata_raw.navdata_wind_speed.wind_compensation_phi;
00681 }
00682 else
00683 {
00684 legacynavdata_msg.magX = legacynavdata_msg.magY = legacynavdata_msg.magZ = 0;
00685 legacynavdata_msg.pressure = 0.0;
00686 legacynavdata_msg.temp = 0.0;
00687 legacynavdata_msg.wind_speed = 0.0;
00688 legacynavdata_msg.wind_angle = 0.0;
00689 legacynavdata_msg.wind_comp_angle = 0.0;
00690 }
00691
00692
00693 legacynavdata_msg.tags_type.clear();
00694 legacynavdata_msg.tags_xc.clear();
00695 legacynavdata_msg.tags_yc.clear();
00696 legacynavdata_msg.tags_width.clear();
00697 legacynavdata_msg.tags_height.clear();
00698 legacynavdata_msg.tags_orientation.clear();
00699 legacynavdata_msg.tags_distance.clear();
00700
00701 legacynavdata_msg.tags_count = navdata_raw.navdata_vision_detect.nb_detected;
00702 for (int i = 0; i < navdata_raw.navdata_vision_detect.nb_detected; i++)
00703 {
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 legacynavdata_msg.tags_type.push_back(navdata_raw.navdata_vision_detect.type[i]);
00716 legacynavdata_msg.tags_xc.push_back(navdata_raw.navdata_vision_detect.xc[i]);
00717 legacynavdata_msg.tags_yc.push_back(navdata_raw.navdata_vision_detect.yc[i]);
00718 legacynavdata_msg.tags_width.push_back(navdata_raw.navdata_vision_detect.width[i]);
00719 legacynavdata_msg.tags_height.push_back(navdata_raw.navdata_vision_detect.height[i]);
00720 legacynavdata_msg.tags_orientation.push_back(navdata_raw.navdata_vision_detect.orientation_angle[i]);
00721 legacynavdata_msg.tags_distance.push_back(navdata_raw.navdata_vision_detect.dist[i]);
00722 }
00723
00724
00725 imu_msg.header.frame_id = droneFrameBase;
00726 imu_msg.header.stamp = navdata_receive_time;
00727
00728
00729 imu_msg.linear_acceleration.x = legacynavdata_msg.ax * 9.8;
00730 imu_msg.linear_acceleration.y = legacynavdata_msg.ay * 9.8;
00731 imu_msg.linear_acceleration.z = legacynavdata_msg.az * 9.8;
00732
00733
00734 tf::Quaternion q;
00735 q.setEulerZYX(legacynavdata_msg.rotZ * _DEG2RAD, legacynavdata_msg.rotY * _DEG2RAD, legacynavdata_msg.rotX * _DEG2RAD);
00736 tf::quaternionTFToMsg(q, imu_msg.orientation);
00737
00738
00739
00740 imu_msg.angular_velocity.x = navdata_raw.navdata_phys_measures.phys_gyros[GYRO_X] * DEG_TO_RAD;
00741 imu_msg.angular_velocity.y = -navdata_raw.navdata_phys_measures.phys_gyros[GYRO_Y] * DEG_TO_RAD;
00742 imu_msg.angular_velocity.z = -navdata_raw.navdata_phys_measures.phys_gyros[GYRO_Z] * DEG_TO_RAD;
00743
00744 mag_msg.header.frame_id = droneFrameBase;
00745 mag_msg.header.stamp = navdata_receive_time;
00746 const float mag_normalizer = sqrt( legacynavdata_msg.magX * legacynavdata_msg.magX + legacynavdata_msg.magY * legacynavdata_msg.magY + legacynavdata_msg.magZ * legacynavdata_msg.magZ );
00747
00748
00749 if (fabs(mag_normalizer) > 1e-9f)
00750 {
00751 mag_msg.vector.x = legacynavdata_msg.magX / mag_normalizer;
00752 mag_msg.vector.y = legacynavdata_msg.magY / mag_normalizer;
00753 mag_msg.vector.z = legacynavdata_msg.magZ / mag_normalizer;
00754 mag_pub.publish(mag_msg);
00755 }
00756 else
00757 {
00758 ROS_WARN_THROTTLE(1, "There is something wrong with the magnetometer readings (Magnitude is extremely small).");
00759 }
00760
00761 navdata_pub.publish(legacynavdata_msg);
00762 imu_pub.publish(imu_msg);
00763 }
00764
00765
00766 #define NAVDATA_STRUCTS_SOURCE
00767 #include "NavdataMessageDefinitions.h"
00768 #undef NAVDATA_STRUCTS_SOURCE
00769
00770 void ARDroneDriver::publish_tf()
00771 {
00772 tf_base_front.stamp_ = ros::Time::now();
00773 tf_base_bottom.stamp_ = ros::Time::now();
00774 tf_broad.sendTransform(tf_base_front);
00775 tf_broad.sendTransform(tf_base_bottom);
00776 }
00777
00778 bool ARDroneDriver::imuReCalibCallback(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
00779 {
00780 if (!do_caliberation)
00781 {
00782 ROS_WARN("Automatic IMU Caliberation is not active. Activate first using `do_imu_caliberation` parameter");
00783 return false;
00784 }
00785 else
00786 {
00787 ROS_WARN("Recaliberating IMU, please do not move the drone for a couple of seconds.");
00788 resetCaliberation();
00789 return true;
00790 }
00791 }
00792
00793 void controlCHandler (int signal)
00794 {
00795 ros::shutdown();
00796 should_exit = 1;
00797 }
00799
00801
00802
00803 int main(int argc, char** argv)
00804 {
00805 C_RESULT res = C_FAIL;
00806 char * drone_ip_address = NULL;
00807
00808
00809
00810
00811 ros::init(argc, argv, "ardrone_driver", ros::init_options::NoSigintHandler);
00812
00813 signal (SIGABRT, &controlCHandler);
00814 signal (SIGTERM, &controlCHandler);
00815 signal (SIGINT, &controlCHandler);
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826 argc--; argv++;
00827 while( argc && *argv[0] == '-' )
00828 {
00829 if( !strcmp(*argv, "-ip") && ( argc > 1 ) )
00830 {
00831 drone_ip_address = *(argv+1);
00832 printf("Using custom ip address %s\n",drone_ip_address);
00833 argc--; argv++;
00834 }
00835 argc--; argv++;
00836 }
00837
00838
00839 vp_com_wifi_config_t *config = (vp_com_wifi_config_t*)wifi_config();
00840
00841 if(config)
00842 {
00843
00844 vp_os_memset( &wifi_ardrone_ip[0], 0, ARDRONE_IPADDRESS_SIZE );
00845
00846
00847 if(drone_ip_address)
00848 {
00849 printf("===================+> %s\n", drone_ip_address);
00850 strncpy( &wifi_ardrone_ip[0], drone_ip_address, ARDRONE_IPADDRESS_SIZE - 1);
00851 }
00852 else
00853 {
00854 printf("===================+> %s\n", config->server);
00855 strncpy( &wifi_ardrone_ip[0], config->server, ARDRONE_IPADDRESS_SIZE - 1);
00856 }
00857 }
00858
00859 while (-1 == getDroneVersion (".", wifi_ardrone_ip, &ardroneVersion))
00860 {
00861 printf ("Getting AR.Drone version ...\n");
00862 vp_os_delay (250);
00863 }
00864
00865
00866 res = ardrone_tool_setup_com( NULL );
00867 if( FAILED(res) )
00868 {
00869 PRINT("Wifi initialization failed. It means either:\n");
00870 PRINT("\t* you're not root (it's mandatory because you can set up wifi connection only as root)\n");
00871 PRINT("\t* wifi device is not present (on your pc or on your card)\n");
00872 PRINT("\t* you set the wrong name for wifi interface (for example rausb0 instead of wlan0) \n");
00873 PRINT("\t* ap is not up (reboot card or remove wifi usb dongle)\n");
00874 PRINT("\t* wifi device has no antenna\n");
00875 }
00876 else
00877 {
00878
00879
00880 char* appname = DRIVER_APPNAME;
00881 char* usrname = DRIVER_USERNAME;
00882 ardrone_gen_appid (appname, "2.0", app_id, app_name, APPLI_NAME_SIZE);
00883 ardrone_gen_usrid (usrname, usr_id, usr_name, USER_NAME_SIZE);
00884
00885
00886
00887
00888 res = ardrone_tool_init(wifi_ardrone_ip, strlen(wifi_ardrone_ip), NULL, app_name, usr_name, NULL, NULL, MAX_FLIGHT_STORING_SIZE, NULL);
00889
00890 while( SUCCEED(res) && ardrone_tool_exit() == FALSE )
00891 {
00892 res = ardrone_tool_update();
00893 }
00894 res = ardrone_tool_shutdown();
00895 }
00896 return SUCCEED(res) ? 0 : -1;
00897 }
00898
00899