00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <algorithm>
00035 #include <cmath>
00036 #include <ros/ros.h>
00037 #include <nodelet/nodelet.h>
00038 #include <pluginlib/class_list_macros.h>
00039 #include <diagnostic_updater/diagnostic_updater.h>
00040 #include <diagnostic_updater/update_functions.h>
00041 #include <dynamic_reconfigure/server.h>
00042 #include <starmac_robots_asctec/AscTecAdapterConfig.h>
00043 #include <string>
00044 #include <angles/angles.h>
00045
00046
00047
00048 #include "asctec_hl_comm/mav_status.h"
00049 #include "asctec_hl_comm/mav_ctrl.h"
00050 #include "std_msgs/Bool.h"
00051 #include "flyer_controller/control_mode_output.h"
00052 #include "starmac_robots_asctec/pid.h"
00053 #include <nav_msgs/Odometry.h>
00054 #include <sensor_msgs/Imu.h>
00055
00056 #include <tf/tf.h>
00057 #include <tf/transform_datatypes.h>
00058 #include "starmac_robots_asctec/misc.h"
00059
00060
00061
00062 using namespace std;
00063
00064
00065 static double ROLL_SCALE = M_PI / 180.0;
00066 static double PITCH_SCALE = M_PI / 180.0;
00067 static double MAX_ROLL_CMD = M_PI_2;
00068 static double MAX_PITCH_CMD = M_PI_2;
00069 static double MAX_YAW_RATE_CMD = 2.0 * M_PI;
00070 static double MAX_THRUST_CMD = 32;
00071
00072
00073
00074
00075 static double YAW_SCALE = M_PI / 180.0;
00076
00077 static double THRUST_SCALE = 1.0 / 32.0;
00078
00079 namespace starmac_robots_asctec
00080 {
00081
00082 class AscTecHLInterfaceAdapterNodelet : public nodelet::Nodelet
00083 {
00084 private:
00085 ros::NodeHandle nh;
00086 ros::NodeHandle nh_priv;
00087
00088 diagnostic_updater::Updater diag_updater;
00089 double min_freq;
00090 double max_freq;
00091 diagnostic_updater::FrequencyStatus freq_status;
00092
00093 dynamic_reconfigure::Server<starmac_robots_asctec::AscTecAdapterConfig> dyn_reconfig_srv;
00094
00095
00096
00097 ros::Duration deadman_timeout;
00098 double alt_KP;
00099 double alt_KI;
00100 double alt_KD;
00101 double alt_KDD;
00102 double alt_Ilimit;
00103 double yaw_KP;
00104 double yaw_KI;
00105 double yaw_KD;
00106 double yaw_Ilimit;
00107 double yaw_rate_limit;
00108 double roll_slew_rate_limit;
00109 double pitch_slew_rate_limit;
00110 double yaw_slew_rate_limit;
00111 double alt_slew_rate_limit;
00112 double nominal_thrust;
00113 double thrust_mult;
00114 double max_thrust;
00115 bool thrust_autoadjust;
00116 double accel_bias;
00117 unsigned int land_now_thrust_decrease_rate;
00118 double land_now_min_thrust_ratio;
00119 double pitch_trim;
00120 double roll_trim;
00121 double yaw_offset;
00122
00123 ros::Publisher output;
00124 ros::Publisher estop_pub;
00125 ros::Publisher imu_pub;
00126
00127 ros::Subscriber motor_enable_sub;
00128 ros::Subscriber control_input_sub;
00129 ros::Subscriber state_sub;
00130 ros::Subscriber mav_status_sub;
00131 ros::Subscriber imu_sub;
00132 ros::Subscriber land_now_sub;
00133
00134 ros::Timer deadman_timer;
00135
00136 bool latest_motor_enable;
00137 bool deadman;
00138 ros::Time prev_control_input_time;
00139 ros::Time last_motor_enable_time;
00140 ros::Time last_mav_status_time;
00141 ros::Time last_state_time;
00142 ros::Time last_imu_time;
00143 starmac_robots_asctec::Pid alt_pid;
00144 starmac_robots_asctec::Pid yaw_pid;
00145 nav_msgs::Odometry latest_state;
00146 asctec_hl_comm::mav_status latest_mav_status;
00147 flyer_controller::control_mode_output prev_control_input_msg;
00148 ros::Duration max_motor_enable_age;
00149 ros::Duration max_mav_status_age;
00150 ros::Duration max_control_input_age;
00151 ros::Duration max_state_age;
00152 double alt_p_term;
00153 double alt_i_term;
00154 double alt_d_term;
00155 double alt_dd_term;
00156 double last_z_accel;
00157 bool land_now;
00158 bool estop_sent;
00159 bool got_first_state;
00160 double latest_battery_voltage;
00161 double min_battery_voltage;
00162 bool battery_low_warning_sent;
00163 bool mav_status_cb_called;
00164 bool got_first_control_input;
00165 double last_thrust;
00166
00167 public:
00168 AscTecHLInterfaceAdapterNodelet() :
00169 diag_updater(),
00170 min_freq(0.1),
00171 max_freq(1000),
00172 freq_status(diagnostic_updater::FrequencyStatusParam(&min_freq, &max_freq)),
00173
00174
00175
00176 deadman_timeout(0.5), alt_KP(2.0),
00177 alt_KI(0.1),
00178 alt_KD(3.0),
00179 alt_KDD(0.0),
00180 alt_Ilimit(5.0),
00181 yaw_KP(1.0),
00182 yaw_KI(1.0),
00183 yaw_KD(0.0),
00184 yaw_Ilimit(5.0),
00185 yaw_rate_limit(4.0),
00186 roll_slew_rate_limit(10),
00187 pitch_slew_rate_limit(10),
00188 yaw_slew_rate_limit(5),
00189 alt_slew_rate_limit(0.1),
00190 nominal_thrust(14.0),
00191 thrust_mult(1.0),
00192 max_thrust(18.0),
00193 thrust_autoadjust(true),
00194 accel_bias(9.81),
00195 land_now_thrust_decrease_rate(200),
00196
00197 latest_motor_enable(false), deadman(false), prev_control_input_time(0), last_motor_enable_time(0),
00198 last_mav_status_time(0), last_state_time(0), max_motor_enable_age(ros::Duration(0)),
00199 max_mav_status_age(ros::Duration(0)), max_control_input_age(ros::Duration(0)), max_state_age(ros::Duration(0)),
00200 land_now_min_thrust_ratio(0.5), pitch_trim(0), roll_trim(0), yaw_offset(0),
00201 last_z_accel(0), land_now(false), estop_sent(false), got_first_state(false), latest_battery_voltage(0), min_battery_voltage(0),
00202 battery_low_warning_sent(false), mav_status_cb_called(false), got_first_control_input(false),
00203 last_thrust(0)
00204 {
00205 }
00206
00207 void onInit()
00208 {
00209 nh_priv = getPrivateNodeHandle();
00210 initDiagnostics();
00211
00212 initParameters();
00213 initPublishers();
00214 initSubscribers();
00215 initTimers();
00216 }
00217
00218 private:
00219
00220 void initDiagnostics()
00221 {
00222
00223 diag_updater.add("AscTecAdapter Status", this, &AscTecHLInterfaceAdapterNodelet::diagnostics);
00224 diag_updater.add(freq_status);
00225 diag_updater.setHardwareID("none");
00226 diag_updater.force_update();
00227 }
00228
00229 void initDynamicReconfigure()
00230 {
00231
00232 dynamic_reconfigure::Server<starmac_robots_asctec::AscTecAdapterConfig>::CallbackType f =
00233 boost::bind(&AscTecHLInterfaceAdapterNodelet::cfgCallback, this, _1, _2);
00234 dyn_reconfig_srv.setCallback(f);
00235 }
00236
00237 void initParameters()
00238 {
00239
00240
00241
00242 double temp = deadman_timeout.toSec();
00243 nh_priv.param("deadman_timeout", temp, temp);
00244 deadman_timeout.fromSec(temp);
00245 nh_priv.param("alt_KP", alt_KP, alt_KP);
00246 nh_priv.param("alt_KI", alt_KI, alt_KI);
00247 nh_priv.param("alt_KD", alt_KD, alt_KD);
00248 nh_priv.param("alt_KDD", alt_KDD, alt_KDD);
00249 nh_priv.param("alt_Ilimit", alt_Ilimit, alt_Ilimit);
00250 nh_priv.param("yaw_KP", yaw_KP, yaw_KP);
00251 nh_priv.param("yaw_KI", yaw_KI, yaw_KI);
00252 nh_priv.param("yaw_KD", yaw_KD, yaw_KD);
00253 nh_priv.param("yaw_Ilimit", yaw_Ilimit, yaw_Ilimit);
00254 nh_priv.param("yaw_rate_limit", yaw_rate_limit, yaw_rate_limit);
00255 nh_priv.param("roll_slew_rate_limit", roll_slew_rate_limit, roll_slew_rate_limit);
00256 nh_priv.param("pitch_slew_rate_limit", pitch_slew_rate_limit, pitch_slew_rate_limit);
00257 nh_priv.param("yaw_slew_rate_limit", yaw_slew_rate_limit, yaw_slew_rate_limit);
00258 nh_priv.param("alt_slew_rate_limit", alt_slew_rate_limit, alt_slew_rate_limit);
00259 nh_priv.param("nominal_thrust", nominal_thrust, nominal_thrust);
00260 nh_priv.param("thrust_mult", thrust_mult, thrust_mult);
00261 nh_priv.param("max_thrust", max_thrust, max_thrust);
00262 nh_priv.param("thrust_autoadjust", thrust_autoadjust, thrust_autoadjust);
00263 nh_priv.param("accel_bias", accel_bias, accel_bias);
00264 int temp_uint;
00265 nh_priv.param("land_now_thrust_decrease_rate", temp_uint, (int)land_now_thrust_decrease_rate);
00266 land_now_thrust_decrease_rate = (unsigned int)temp_uint;
00267 nh_priv.param("land_now_min_thrust_ratio", land_now_min_thrust_ratio, land_now_min_thrust_ratio);
00268 nh_priv.param("pitch_trim", pitch_trim, pitch_trim);
00269 nh_priv.param("roll_trim", roll_trim, roll_trim);
00270 nh_priv.param("yaw_offset", yaw_offset, yaw_offset);
00271
00272 setAltControllerParams(alt_KP, alt_KI, alt_KD, alt_Ilimit);
00273 setYawControllerParams(yaw_KP, yaw_KI, yaw_KD, yaw_Ilimit);
00274 }
00275
00276 void initPublishers()
00277 {
00278
00279 output = nh.advertise<asctec_hl_comm::mav_ctrl> ("fcu/control", 10);
00280
00281 imu_pub = nh.advertise<sensor_msgs::Imu> ("asctec/imu", 10);
00282 }
00283
00284 void initTimers()
00285 {
00286
00287 double deadman_timer_period = deadman_timeout.toSec() / 2;
00288 min_freq = 0.95 / deadman_timer_period;
00289 max_freq = 1.05 / deadman_timer_period;
00290 deadman_timer = nh.createTimer(ros::Duration(deadman_timer_period),
00291 &AscTecHLInterfaceAdapterNodelet::deadmanCallback, this);
00292 }
00293
00294 void initSubscribers()
00295 {
00296
00297 motor_enable_sub = nh.subscribe("teleop_flyer/motor_enable", 1,
00298 &AscTecHLInterfaceAdapterNodelet::motorEnableCallback, this,
00299 ros::TransportHints().tcpNoDelay());
00300 control_input_sub = nh.subscribe("controller_mux/output", 1,
00301 &AscTecHLInterfaceAdapterNodelet::controlInputCallback, this,
00302 ros::TransportHints().tcpNoDelay());
00303 state_sub = nh.subscribe("odom", 1, &AscTecHLInterfaceAdapterNodelet::stateCallback, this,
00304 ros::TransportHints().tcpNoDelay());
00305
00306 mav_status_sub = nh.subscribe("fcu/status", 1, &AscTecHLInterfaceAdapterNodelet::mavStatusCallback, this,
00307 ros::TransportHints().tcpNoDelay());
00308
00309
00310 land_now_sub = nh_priv.subscribe("land_now", 10, &AscTecHLInterfaceAdapterNodelet::landNowCallback, this,
00311 ros::TransportHints().tcpNoDelay());
00312 }
00313
00314 void cfgCallback(starmac_robots_asctec::AscTecAdapterConfig &config, uint32_t level)
00315 {
00316 ROS_INFO("Reconfigure request");
00317 if (isSafeToReconfigure())
00318 {
00319 setYawControllerParams(config.yaw_KP, config.yaw_KI, config.yaw_KD, config.yaw_Ilimit);
00320 roll_trim = config.roll_trim;
00321 pitch_trim = config.pitch_trim;
00322 }
00323 else
00324 {
00325 ROS_ERROR("Cannot reconfigure; isSafeToReconfigure() returned false");
00326 }
00327 }
00328
00329 void setAltControllerParams(double KP, double KI, double KD, double Ilimit)
00330 {
00331 alt_pid.initPid(KP, KI, KD, Ilimit, -Ilimit);
00332 ROS_INFO("Altitude controller gains set: KP=%f, KI=%f, KD=%f, Ilimit=%f", KP, KI, KD, Ilimit);
00333 }
00334
00335 void setYawControllerParams(double KP, double KI, double KD, double Ilimit)
00336 {
00337 yaw_pid.initPid(KP, KI, KD, Ilimit, -Ilimit);
00338 ROS_INFO("Yaw controller gains set: KP=%f, KI=%f, KD=%f, Ilimit=%f", KP, KI, KD, Ilimit);
00339 }
00340
00341 void diagnostics(diagnostic_updater::DiagnosticStatusWrapper& stat)
00342 {
00343 if (deadman)
00344 {
00345 stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Deadman Tripped");
00346 }
00347 else
00348 {
00349 if (min_battery_voltage < 10.0)
00350 {
00351 stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Low Battery");
00352 if (not battery_low_warning_sent)
00353 {
00354 ROS_WARN("Battery voltage below 10V");
00355 battery_low_warning_sent = true;
00356 }
00357 }
00358 else
00359 {
00360 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "OK");
00361 }
00362 }
00363 stat.add("Motor Enable", latest_motor_enable);
00364 stat.add("Deadman Tripped", deadman);
00365 stat.add("max ll_status age", max_mav_status_age);
00366 stat.add("max control inputs age", max_control_input_age);
00367 stat.add("max motor_enable age", max_motor_enable_age);
00368 stat.add("max state age", max_state_age);
00369 stat.add("alt P term", alt_p_term);
00370 stat.add("alt I term", alt_i_term);
00371 stat.add("alt D term", alt_d_term);
00372 stat.add("alt DD term", alt_dd_term);
00373 stat.add("Battery Voltage (current)", latest_battery_voltage);
00374 stat.add("Battery Voltage (minimum)", min_battery_voltage);
00375 }
00376
00377 void motorEnableCallback(const std_msgs::BoolConstPtr& msg)
00378 {
00379 static bool first = true;
00380 latest_motor_enable = msg->data;
00381 ros::Time now = ros::Time::now();
00382 if (!first)
00383 {
00384 max_motor_enable_age = max(now - last_motor_enable_time, max_motor_enable_age);
00385 }
00386 else
00387 {
00388 first = false;
00389 }
00390 last_motor_enable_time = now;
00391 }
00392
00393 void stateCallback(const nav_msgs::OdometryConstPtr& msg)
00394 {
00395 static bool first = true;
00396 latest_state = *msg;
00397 ROS_DEBUG_STREAM("Got state with z = " << latest_state.pose.pose.position.z);
00398 ros::Time now = ros::Time::now();
00399 if (!first)
00400 {
00401 max_state_age = max(now - last_state_time, max_state_age);
00402 }
00403 else
00404 {
00405 first = false;
00406 got_first_state = true;
00407 }
00408 last_state_time = now;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 void landNowCallback(const std_msgs::BoolConstPtr& msg)
00463 {
00464 land_now = msg->data;
00465 }
00466
00467 void mavStatusCallback(const asctec_hl_comm::mav_statusConstPtr& msg)
00468 {
00469 latest_mav_status = *msg;
00470 ros::Time now = ros::Time::now();
00471 if (mav_status_cb_called)
00472 {
00473 max_mav_status_age = max(now - last_mav_status_time, max_mav_status_age);
00474 }
00475 else
00476 {
00477 min_battery_voltage = 9999;
00478 mav_status_cb_called = true;
00479 }
00480 last_mav_status_time = now;
00481 latest_battery_voltage = (double)latest_mav_status.battery_voltage;
00482 min_battery_voltage = min(latest_battery_voltage, min_battery_voltage);
00483 }
00484
00485 void controlInputCallback(const flyer_controller::control_mode_outputConstPtr& msg)
00486 {
00487 ros::Time now = ros::Time::now();
00488 ros::Duration dt = now - prev_control_input_time;
00489 static bool prev_motor_enable = false;
00490 if (got_first_control_input)
00491 {
00492 max_control_input_age = max(dt, max_control_input_age);
00493 }
00494 else
00495 {
00496 got_first_control_input = true;
00497 }
00498
00499
00500 double roll_cmd_limited, pitch_cmd_limited, yaw_cmd_limited, alt_cmd_limited;
00501 double dt_sec = dt.toSec();
00502
00503
00504
00505 limitSlewRate(msg->roll_cmd, prev_control_input_msg.roll_cmd, dt_sec, roll_slew_rate_limit, roll_cmd_limited);
00506
00507
00508
00509 limitSlewRate(msg->pitch_cmd, prev_control_input_msg.pitch_cmd, dt_sec, pitch_slew_rate_limit, pitch_cmd_limited);
00510
00511 if (not msg->direct_yaw_rate_commands)
00512 limitSlewRate(msg->yaw_cmd, prev_control_input_msg.yaw_cmd, dt_sec, yaw_slew_rate_limit, yaw_cmd_limited);
00513
00514 if (not msg->direct_thrust_commands)
00515 limitSlewRate(msg->alt_cmd, prev_control_input_msg.alt_cmd, dt_sec, alt_slew_rate_limit, alt_cmd_limited);
00516
00517 if (latest_motor_enable and not prev_motor_enable)
00518 {
00519 double pe, de, ie;
00520 yaw_pid.getCurrentPIDErrors(&pe, &de, &ie);
00521 ROS_INFO_STREAM("Yaw integrator was at:" << ie);
00522 alt_pid.reset();
00523 yaw_pid.reset();
00524 ROS_INFO("Reset yaw & alt integrators");
00525 }
00526 prev_motor_enable = latest_motor_enable;
00527 double thrust_cmd = 0;
00528 if (got_first_state)
00529 {
00530 if (not msg->direct_thrust_commands)
00531 {
00532
00533 thrust_cmd = computeThrust(alt_cmd_limited, dt);
00534 }
00535 else
00536 {
00537 double yaw, pitch, roll;
00538 getLatestYPR(yaw, pitch, roll);
00539 double tfactor = 1;
00540 if (thrust_autoadjust)
00541 tfactor = 1 / (cos(pitch) * cos(roll));
00542 thrust_cmd = tfactor * msg->thrust_cmd;
00543 }
00544 }
00545 else
00546 {
00547 ROS_DEBUG("got_first_state was false..");
00548 }
00549 double yaw_rate_cmd = 0;
00550 if (not land_now)
00551 {
00552
00553
00554
00555
00556 if (msg->direct_yaw_rate_commands)
00557 yaw_rate_cmd = msg->yaw_rate_cmd;
00558 else if (got_first_state)
00559 yaw_rate_cmd = computeYawRate(yaw_cmd_limited, dt);
00560 }
00561 else
00562 {
00563
00564 roll_cmd_limited = roll_trim;
00565 pitch_cmd_limited = pitch_trim;
00566 }
00567 asctec_hl_comm::mav_ctrlPtr ctrl_msg(new asctec_hl_comm::mav_ctrl);
00568 ctrl_msg->type = asctec_hl_comm::mav_ctrl::acceleration;
00569 ctrl_msg->header.stamp = now;
00570 double roll_cmd_rotated, pitch_cmd_rotated;
00571 rotateRollAndPitch(roll_cmd_limited, pitch_cmd_limited, roll_cmd_rotated, pitch_cmd_rotated);
00572 roll_cmd_rotated += roll_trim;
00573 pitch_cmd_rotated += pitch_trim;
00574 if (!deadman && dt.toSec() < 1.0)
00575 {
00576 bool motors = msg->motors_on and latest_motor_enable;
00577 if (not motors)
00578 {
00579 thrust_cmd = 0;
00580 }
00581 assemble_command(roll_cmd_rotated, pitch_cmd_rotated, yaw_rate_cmd, thrust_cmd, ctrl_msg);
00582 }
00583 if (deadman)
00584 {
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 }
00600 ctrl_msg->header.stamp = now;
00601 output.publish(ctrl_msg);
00602 prev_control_input_time = now;
00603 prev_control_input_msg = *msg;
00604 }
00605
00606 void rotateRollAndPitch(const double roll_cmd, const double pitch_cmd, double& roll_cmd_rotated,
00607 double& pitch_cmd_rotated)
00608 {
00609 double cy = cos(angles::from_degrees(yaw_offset));
00610 double sy = sin(angles::from_degrees(yaw_offset));
00611 roll_cmd_rotated = cy * roll_cmd - sy * pitch_cmd;
00612 pitch_cmd_rotated = sy * roll_cmd + cy * pitch_cmd;
00613 }
00614
00615 double computeThrust(const double alt_cmd, ros::Duration& dt)
00616 {
00617
00618
00619
00620 static bool landing_now = false;
00621 static int land_now_start_thrust = 0;
00622 static ros::Time land_now_start_time;
00623 if (land_now)
00624 {
00625 if (!landing_now)
00626 {
00627 ROS_INFO("Received land_now instruction. Decreasing thrust at %d counts/s to %d counts",
00628 land_now_thrust_decrease_rate, int(land_now_min_thrust_ratio * double(nominal_thrust)));
00629 land_now_start_thrust = last_thrust;
00630 land_now_start_time = ros::Time::now();
00631 landing_now = true;
00632 }
00633 last_thrust = max(
00634 land_now_min_thrust_ratio * nominal_thrust,
00635 land_now_start_thrust - (ros::Time::now() - land_now_start_time).toSec()
00636 * land_now_thrust_decrease_rate);
00637 }
00638 else
00639 {
00640 if (landing_now)
00641 {
00642
00643 landing_now = false;
00644 }
00645 double alt_err = (-latest_state.pose.pose.position.z) - alt_cmd;
00646 double alt_vel_err = -latest_state.twist.twist.linear.z;
00647 alt_pid.updatePid(alt_err, alt_vel_err, dt);
00648 double pe, ie, de;
00649 alt_pid.getCurrentPIDErrors(&pe, &ie, &de);
00650 alt_p_term = alt_KP * pe;
00651 alt_i_term = alt_KI * ie;
00652 alt_d_term = alt_KD * de;
00653 alt_dd_term = alt_KDD * last_z_accel;
00654 double yaw, pitch, roll;
00655 getLatestYPR(yaw, pitch, roll);
00656 double tfactor = 1;
00657 if (thrust_autoadjust)
00658 tfactor = 1 / (cos(pitch) * cos(roll));
00659 last_thrust = tfactor * (nominal_thrust + alt_pid.getCurrentCmd() + alt_dd_term);
00660 }
00661 return last_thrust;
00662 }
00663
00664 double computeYawRate(double yaw_cmd,
00665 ros::Duration& dt)
00666 {
00667 double yaw, pitch, roll;
00668 getLatestYPR(yaw, pitch, roll);
00669
00670 double yaw_err = angles::to_degrees(
00671 angles::shortest_angular_distance(angles::from_degrees(yaw_cmd),
00672 yaw + angles::from_degrees(yaw_offset)));
00673
00674 yaw_pid.updatePid(yaw_err, dt);
00675 double yaw_rate_cmd = min(yaw_rate_limit, max(-yaw_rate_limit, yaw_pid.getCurrentCmd()));
00676
00677 return yaw_rate_cmd;
00678 }
00679
00680 void getLatestYPR(double& yaw,
00681 double& pitch,
00682 double& roll
00683 )
00684 {
00685 tf::Quaternion temp_q;
00686
00687
00688
00689
00690 tf::quaternionMsgToTF(latest_state.pose.pose.orientation, temp_q);
00691
00692 tf::Matrix3x3 temp_mat = tf::Matrix3x3(temp_q);
00693 temp_mat.getEulerYPR(yaw, pitch, roll);
00694 }
00695
00696 void assemble_command(double roll,
00697 double pitch,
00698 double yaw_rate,
00699 double thrust,
00700 asctec_hl_comm::mav_ctrlPtr ctrl_msg)
00701 {
00702 ctrl_msg->y = -float(min(MAX_ROLL_CMD, max(-MAX_ROLL_CMD, roll * ROLL_SCALE)));
00703 ctrl_msg->x = -float(min(MAX_PITCH_CMD, max(-MAX_PITCH_CMD, pitch * PITCH_SCALE)));
00704 ctrl_msg->yaw = -float(min(MAX_YAW_RATE_CMD, max(-MAX_YAW_RATE_CMD, yaw_rate * YAW_SCALE)));
00705 ctrl_msg->z = float(min(MAX_THRUST_CMD, min(max_thrust, max(0.0, thrust * thrust_mult * THRUST_SCALE))));
00706 }
00707
00708 void deadmanCallback(const ros::TimerEvent& e)
00709 {
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765 diag_updater.update();
00766 }
00767
00768 bool isSafeToReconfigure()
00769 {
00770 return (not latest_motor_enable);
00771 }
00772 };
00773 PLUGINLIB_DECLARE_CLASS(starmac_robots_asctec, AscTecHLInterfaceAdapterNodelet, starmac_robots_asctec::AscTecHLInterfaceAdapterNodelet, nodelet::Nodelet)
00774
00775 }
00776