int m_cd(t_data *data) { char *pwd_asked; char *start_pwd; int ret; bool go_home; if (data->env == NULL || data->env[0] == NULL || data->env[1] == NULL) return (0); go_home = false; pwd_asked = data->cmd[1]; pwd_asked = set_home(data, &go_home, pwd_asked); if (data->old_pwd == NULL && pwd_asked[0] == '-') return (0); if (pwd_asked[0] == '-') pwd_asked = data->old_pwd; data->old_pwd = my_strdup(&data->pwd[4]); ret = chdir(pwd_asked); if (ret == 0) { start_pwd = data->pwd; change_path(data, pwd_asked, start_pwd, go_home); } else cannot_access(pwd_asked); return (0); }
/* read the GPS */ void Tracker::update_GPS(void) { gps.update(); static uint32_t last_gps_msg_ms; static uint8_t ground_start_count = 5; if (gps.last_message_time_ms() != last_gps_msg_ms && gps.status() >= AP_GPS::GPS_OK_FIX_3D) { last_gps_msg_ms = gps.last_message_time_ms(); if (ground_start_count > 1) { ground_start_count--; } else if (ground_start_count == 1) { // We countdown N number of good GPS fixes // so that the altitude is more accurate // ------------------------------------- if (current_loc.lat == 0 && current_loc.lng == 0) { ground_start_count = 5; } else { // Now have an initial GPS position // use it as the HOME position in future startups current_loc = gps.location(); set_home(current_loc); if (g.compass_enabled) { // Set compass declination automatically compass.set_initial_location(gps.location().lat, gps.location().lng); } ground_start_count = 0; } } } }
int YARPMEIDeviceDriver::setHomeProcedure(void *cmd) { int16 rc = 0; SingleAxisParameters *tmp = (SingleAxisParameters *) cmd; int16 ev = _events[*(ControlBoardEvents *)tmp->parameters]; SingleAxisParameters x; int ipar; double dpar; x.axis = tmp->axis; x.parameters = &ipar; ipar = CBIndexOnly; // index_only setHomeIndexConfig(&cmd); ipar = 0; // (active low) setHomeLevel(&cmd); rc = set_home(tmp->axis, ev); x.parameters = &dpar; dpar = 50000.0; // stop rate (acc) setStopRate(&cmd); return rc; }
void Rover::do_set_home(const AP_Mission::Mission_Command& cmd) { if (cmd.p1 == 1 && have_position) { set_home_to_current_location(false); } else { set_home(cmd.content.location, false); } }
// set_home_to_current_location - set home to current GPS location bool Copter::set_home_to_current_location() { // get current location from EKF Location temp_loc; if (inertial_nav.get_location(temp_loc)) { return set_home(temp_loc); } return false; }
// set_home_and_lock - sets ahrs home (used for RTL) to specified location and locks so it cannot be moved // unless this function is called again bool Copter::set_home_and_lock(const Location& loc) { if (set_home(loc)) { set_home_state(HOME_SET_AND_LOCKED); return true; } return false; }
// set_home_to_current_location_inflight - set home to current GPS location (horizontally) and EKF origin vertically void Copter::set_home_to_current_location_inflight() { // get current location from EKF Location temp_loc; if (inertial_nav.get_location(temp_loc)) { const struct Location &ekf_origin = inertial_nav.get_origin(); temp_loc.alt = ekf_origin.alt; set_home(temp_loc); } }
// set ahrs home to current location from EKF reported location or GPS bool Rover::set_home_to_current_location(bool lock) { // use position from EKF if available otherwise use GPS Location temp_loc; if (ahrs.get_position(temp_loc)) { return set_home(temp_loc, lock); } return false; }
void Copter::do_set_home(const AP_Mission::Mission_Command& cmd) { if(cmd.p1 == 1 || (cmd.content.location.lat == 0 && cmd.content.location.lng == 0 && cmd.content.location.alt == 0)) { set_home_to_current_location(); } else { if (!far_from_EKF_origin(cmd.content.location)) { set_home(cmd.content.location); } } }
int YARPMEIDeviceDriver::setHome(void *cmd) { int16 rc = 0; SingleAxisParameters *tmp = (SingleAxisParameters *) cmd; int axis = tmp->axis; ControlBoardEvents *event = (ControlBoardEvents *) tmp->parameters; int16 ev = _events[*event]; rc = set_home(axis, ev); return rc; }
// set ahrs home to current location from inertial-nav location bool Rover::set_home_to_current_location(bool lock) { Location temp_loc; if (ahrs.have_inertial_nav() && ahrs.get_position(temp_loc)) { if (!set_home(temp_loc, lock)) { return false; } // we have successfully set AHRS home, set it for SmartRTL g2.smart_rtl.set_home(true); return true; } return false; }
void Sub::do_set_home(const AP_Mission::Mission_Command& cmd) { if (cmd.p1 == 1 || (cmd.content.location.lat == 0 && cmd.content.location.lng == 0 && cmd.content.location.alt == 0)) { if (!set_home_to_current_location(false)) { // silently ignore this failure } } else { if (!far_from_EKF_origin(cmd.content.location)) { if (!set_home(cmd.content.location, false)) { // silently ignore this failure } } } }
// set_home_to_current_location_inflight - set home to current GPS location (horizontally) and EKF origin vertically void Copter::set_home_to_current_location_inflight() { // get current location from EKF Location temp_loc; if (inertial_nav.get_location(temp_loc)) { const struct Location &ekf_origin = inertial_nav.get_origin(); temp_loc.alt = ekf_origin.alt; if (!set_home(temp_loc, false)) { return; } // we have successfully set AHRS home, set it for SmartRTL #if MODE_SMARTRTL_ENABLED == ENABLED g2.smart_rtl.set_home(true); #endif } }
// set_home_to_current_location - set home to current GPS location bool Copter::set_home_to_current_location(bool lock) { // get current location from EKF Location temp_loc; if (inertial_nav.get_location(temp_loc)) { if (!set_home(temp_loc, lock)) { return false; } // we have successfully set AHRS home, set it for SmartRTL #if MODE_SMARTRTL_ENABLED == ENABLED g2.smart_rtl.set_home(true); #endif return true; } return false; }
// set_home_to_current_location - set home to current GPS location bool Sub::set_home_to_current_location(bool lock) { // get current location from EKF Location temp_loc; if (inertial_nav.get_location(temp_loc)) { // Make home always at the water's surface. // This allows disarming and arming again at depth. // This also ensures that mission items with relative altitude frame, are always // relative to the water's surface, whether in a high elevation lake, or at sea level. temp_loc.alt -= barometer.get_altitude() * 100.0f; return set_home(temp_loc, lock); } return false; }
/* read the GPS */ void Tracker::update_GPS(void) { gps.update(); static uint32_t last_gps_msg_ms; static uint8_t ground_start_count = 5; if (gps.last_message_time_ms() != last_gps_msg_ms && gps.status() >= AP_GPS::GPS_OK_FIX_3D) { last_gps_msg_ms = gps.last_message_time_ms(); if (ground_start_count > 1) { ground_start_count--; } else if (ground_start_count == 1) { // We countdown N number of good GPS fixes // so that the altitude is more accurate // ------------------------------------- if (current_loc.lat == 0 && current_loc.lng == 0) { ground_start_count = 5; } else { // Now have an initial GPS position // use it as the HOME position in future startups current_loc = gps.location(); set_home(current_loc); // set system clock for log timestamps uint64_t gps_timestamp = gps.time_epoch_usec(); hal.util->set_system_clock(gps_timestamp); // update signing timestamp GCS_MAVLINK::update_signing_timestamp(gps_timestamp); if (g.compass_enabled) { // Set compass declination automatically compass.set_initial_location(gps.location().lat, gps.location().lng); } ground_start_count = 0; } } // log GPS data if (should_log(MASK_LOG_GPS)) { DataFlash.Log_Write_GPS(gps, 0); } } }
static void stats_convert(struct stats_file *file) { struct stats_file temp_file; int err; DBG("converting data file %s", file->name); stats_file_update_cache32(file); bzero(&temp_file, sizeof(struct stats_file)); err = stats_open_temp(&temp_file); if (err < 0) { connman_error("failed to open temporary file during data conversion"); return; } stats_file_setup(&temp_file); struct stats_iter32 data_iter; struct stats_record32 *record; data_iter.file = file; data_iter.begin = get_iterator_begin32(data_iter.file); data_iter.end = get_iterator_end32(data_iter.file); data_iter.it = data_iter.begin; record = get_next_record32(&data_iter); while (record) { struct stats_record *next; if (temp_file.last == get_end(&temp_file)) { err = stats_file_remap(&temp_file, temp_file.len + sysconf(_SC_PAGESIZE)); if (err < 0) { connman_error("failed to extend file %s", temp_file.name); unlink(temp_file.name); stats_file_unmap(&temp_file); TFR(close(temp_file.fd)); stats_file_cleanup(&temp_file); return; } stats_file_update_cache(&temp_file); } next = get_next(&temp_file, get_end(&temp_file)); if (next == get_begin(&temp_file)) { connman_error("ring buffer is full"); unlink(temp_file.name); stats_file_unmap(&temp_file); TFR(close(temp_file.fd)); stats_file_cleanup(&temp_file); return; } next->ts = record->ts; next->roaming = record->roaming; next->data.rx_packets = record->data.rx_packets; next->data.tx_packets = record->data.tx_packets; next->data.rx_bytes = record->data.rx_bytes; next->data.tx_bytes = record->data.tx_bytes; next->data.rx_errors = record->data.rx_errors; next->data.tx_errors = record->data.tx_errors; next->data.rx_dropped = record->data.rx_dropped; next->data.tx_dropped = record->data.tx_dropped; next->data.time = record->data.time; if (next->roaming) set_roaming(&temp_file, next); else set_home(&temp_file, next); set_end(&temp_file, next); record = get_next_record32(&data_iter); } // close and swap stats_file_unmap(file); TFR(close(file->fd)); err = rename(temp_file.name, file->name); if (err < 0) connman_error("failed to rename converted data file %s to %s", temp_file.name, file->name); g_free(temp_file.name); temp_file.name = file->name; memcpy(file, &temp_file, sizeof(struct stats_file)); }
MAV_RESULT GCS_MAVLINK_Plane::handle_command_long_packet(const mavlink_command_long_t &packet) { switch(packet.command) { case MAV_CMD_DO_CHANGE_SPEED: { // if we're in failsafe modes (e.g., RTL, LOITER) or in pilot // controlled modes (e.g., MANUAL, TRAINING) // this command should be ignored since it comes in from GCS // or a companion computer: if ((plane.control_mode != &plane.mode_guided) && (plane.control_mode != &plane.mode_auto) && (plane.control_mode != &plane.mode_avoidADSB)) { // failed return MAV_RESULT_FAILED; } AP_Mission::Mission_Command cmd; if (AP_Mission::mavlink_cmd_long_to_mission_cmd(packet, cmd) == MAV_MISSION_ACCEPTED) { plane.do_change_speed(cmd); return MAV_RESULT_ACCEPTED; } return MAV_RESULT_FAILED; } case MAV_CMD_NAV_LOITER_UNLIM: plane.set_mode(plane.mode_loiter, MODE_REASON_GCS_COMMAND); return MAV_RESULT_ACCEPTED; case MAV_CMD_NAV_RETURN_TO_LAUNCH: plane.set_mode(plane.mode_rtl, MODE_REASON_GCS_COMMAND); return MAV_RESULT_ACCEPTED; case MAV_CMD_NAV_TAKEOFF: { // user takeoff only works with quadplane code for now // param7 : altitude [metres] float takeoff_alt = packet.param7; if (plane.quadplane.available() && plane.quadplane.do_user_takeoff(takeoff_alt)) { return MAV_RESULT_ACCEPTED; } return MAV_RESULT_FAILED; } case MAV_CMD_MISSION_START: plane.set_mode(plane.mode_auto, MODE_REASON_GCS_COMMAND); return MAV_RESULT_ACCEPTED; case MAV_CMD_COMPONENT_ARM_DISARM: if (is_equal(packet.param1,1.0f)) { // run pre_arm_checks and arm_checks and display failures const bool do_arming_checks = !is_equal(packet.param2,magic_force_arm_value); if (plane.arm_motors(AP_Arming::Method::MAVLINK, do_arming_checks)) { return MAV_RESULT_ACCEPTED; } return MAV_RESULT_FAILED; } else if (is_zero(packet.param1)) { if (plane.disarm_motors()) { return MAV_RESULT_ACCEPTED; } return MAV_RESULT_FAILED; } return MAV_RESULT_UNSUPPORTED; case MAV_CMD_DO_LAND_START: // attempt to switch to next DO_LAND_START command in the mission if (plane.mission.jump_to_landing_sequence()) { plane.set_mode(plane.mode_auto, MODE_REASON_UNKNOWN); return MAV_RESULT_ACCEPTED; } return MAV_RESULT_FAILED; case MAV_CMD_DO_GO_AROUND: { uint16_t mission_id = plane.mission.get_current_nav_cmd().id; bool is_in_landing = (plane.flight_stage == AP_Vehicle::FixedWing::FLIGHT_LAND) || (mission_id == MAV_CMD_NAV_LAND) || (mission_id == MAV_CMD_NAV_VTOL_LAND); if (is_in_landing) { // fly a user planned abort pattern if available if (plane.mission.jump_to_abort_landing_sequence()) { return MAV_RESULT_ACCEPTED; } // only fly a fixed wing abort if we aren't doing quadplane stuff, or potentially // shooting a quadplane approach if ((!plane.quadplane.available()) || ((!plane.quadplane.in_vtol_auto()) && (!(plane.quadplane.options & QuadPlane::OPTION_MISSION_LAND_FW_APPROACH)))) { // Initiate an aborted landing. This will trigger a pitch-up and // climb-out to a safe altitude holding heading then one of the // following actions will occur, check for in this order: // - If MAV_CMD_CONTINUE_AND_CHANGE_ALT is next command in mission, // increment mission index to execute it // - else if DO_LAND_START is available, jump to it // - else decrement the mission index to repeat the landing approach if (!is_zero(packet.param1)) { plane.auto_state.takeoff_altitude_rel_cm = packet.param1 * 100; } if (plane.landing.request_go_around()) { plane.auto_state.next_wp_crosstrack = false; return MAV_RESULT_ACCEPTED; } } } } return MAV_RESULT_FAILED; case MAV_CMD_DO_FENCE_ENABLE: if (!plane.geofence_present()) { gcs().send_text(MAV_SEVERITY_NOTICE,"Fence not configured"); return MAV_RESULT_FAILED; } switch((uint16_t)packet.param1) { case 0: if (! plane.geofence_set_enabled(false, GCS_TOGGLED)) { return MAV_RESULT_FAILED; } return MAV_RESULT_ACCEPTED; case 1: if (! plane.geofence_set_enabled(true, GCS_TOGGLED)) { return MAV_RESULT_FAILED; } return MAV_RESULT_ACCEPTED; case 2: //disable fence floor only if (! plane.geofence_set_floor_enabled(false)) { return MAV_RESULT_FAILED; } gcs().send_text(MAV_SEVERITY_NOTICE,"Fence floor disabled"); return MAV_RESULT_ACCEPTED; default: break; } return MAV_RESULT_FAILED; case MAV_CMD_DO_SET_HOME: { // param1 : use current (1=use current location, 0=use specified location) // param5 : latitude // param6 : longitude // param7 : altitude (absolute) if (is_equal(packet.param1,1.0f)) { if (!plane.set_home_persistently(AP::gps().location())) { return MAV_RESULT_FAILED; } AP::ahrs().lock_home(); return MAV_RESULT_ACCEPTED; } else { // ensure param1 is zero if (!is_zero(packet.param1)) { return MAV_RESULT_FAILED; } Location new_home_loc {}; new_home_loc.lat = (int32_t)(packet.param5 * 1.0e7f); new_home_loc.lng = (int32_t)(packet.param6 * 1.0e7f); new_home_loc.alt = (int32_t)(packet.param7 * 100.0f); if (!set_home(new_home_loc, true)) { return MAV_RESULT_FAILED; } return MAV_RESULT_ACCEPTED; } break; } case MAV_CMD_DO_AUTOTUNE_ENABLE: // param1 : enable/disable plane.autotune_enable(!is_zero(packet.param1)); return MAV_RESULT_ACCEPTED; #if PARACHUTE == ENABLED case MAV_CMD_DO_PARACHUTE: // configure or release parachute switch ((uint16_t)packet.param1) { case PARACHUTE_DISABLE: plane.parachute.enabled(false); return MAV_RESULT_ACCEPTED; case PARACHUTE_ENABLE: plane.parachute.enabled(true); return MAV_RESULT_ACCEPTED; case PARACHUTE_RELEASE: // treat as a manual release which performs some additional check of altitude if (plane.parachute.released()) { gcs().send_text(MAV_SEVERITY_NOTICE, "Parachute already released"); return MAV_RESULT_FAILED; } if (!plane.parachute.enabled()) { gcs().send_text(MAV_SEVERITY_NOTICE, "Parachute not enabled"); return MAV_RESULT_FAILED; } if (!plane.parachute_manual_release()) { return MAV_RESULT_FAILED; } return MAV_RESULT_ACCEPTED; default: break; } return MAV_RESULT_FAILED; #endif case MAV_CMD_DO_MOTOR_TEST: // param1 : motor sequence number (a number from 1 to max number of motors on the vehicle) // param2 : throttle type (0=throttle percentage, 1=PWM, 2=pilot throttle channel pass-through. See MOTOR_TEST_THROTTLE_TYPE enum) // param3 : throttle (range depends upon param2) // param4 : timeout (in seconds) // param5 : motor count (number of motors to test in sequence) return plane.quadplane.mavlink_motor_test_start(chan, (uint8_t)packet.param1, (uint8_t)packet.param2, (uint16_t)packet.param3, packet.param4, (uint8_t)packet.param5); case MAV_CMD_DO_VTOL_TRANSITION: if (!plane.quadplane.handle_do_vtol_transition((enum MAV_VTOL_STATE)packet.param1)) { return MAV_RESULT_FAILED; } return MAV_RESULT_ACCEPTED; case MAV_CMD_DO_ENGINE_CONTROL: if (!plane.g2.ice_control.engine_control(packet.param1, packet.param2, packet.param3)) { return MAV_RESULT_FAILED; } return MAV_RESULT_ACCEPTED; default: return GCS_MAVLINK::handle_command_long_packet(packet); } }
void GCS_MAVLINK_Plane::handleMessage(mavlink_message_t* msg) { switch (msg->msgid) { #if GEOFENCE_ENABLED == ENABLED // receive a fence point from GCS and store in EEPROM case MAVLINK_MSG_ID_FENCE_POINT: { mavlink_fence_point_t packet; mavlink_msg_fence_point_decode(msg, &packet); if (plane.g.fence_action != FENCE_ACTION_NONE) { send_text(MAV_SEVERITY_WARNING,"Fencing must be disabled"); } else if (packet.count != plane.g.fence_total) { send_text(MAV_SEVERITY_WARNING,"Bad fence point"); } else if (!check_latlng(packet.lat,packet.lng)) { send_text(MAV_SEVERITY_WARNING,"Invalid fence point, lat or lng too large"); } else { plane.set_fence_point_with_index(Vector2l(packet.lat*1.0e7f, packet.lng*1.0e7f), packet.idx); } break; } // send a fence point to GCS case MAVLINK_MSG_ID_FENCE_FETCH_POINT: { mavlink_fence_fetch_point_t packet; mavlink_msg_fence_fetch_point_decode(msg, &packet); if (packet.idx >= plane.g.fence_total) { send_text(MAV_SEVERITY_WARNING,"Bad fence point"); } else { Vector2l point = plane.get_fence_point_with_index(packet.idx); mavlink_msg_fence_point_send_buf(msg, chan, msg->sysid, msg->compid, packet.idx, plane.g.fence_total, point.x*1.0e-7f, point.y*1.0e-7f); } break; } #endif // GEOFENCE_ENABLED case MAVLINK_MSG_ID_MANUAL_CONTROL: { if (msg->sysid != plane.g.sysid_my_gcs) { break; // only accept control from our gcs } mavlink_manual_control_t packet; mavlink_msg_manual_control_decode(msg, &packet); if (packet.target != plane.g.sysid_this_mav) { break; // only accept messages aimed at us } uint32_t tnow = AP_HAL::millis(); manual_override(plane.channel_roll, packet.y, 1000, 2000, tnow); manual_override(plane.channel_pitch, packet.x, 1000, 2000, tnow, true); manual_override(plane.channel_throttle, packet.z, 0, 1000, tnow); manual_override(plane.channel_rudder, packet.r, 1000, 2000, tnow); // a manual control message is considered to be a 'heartbeat' from the ground station for failsafe purposes plane.failsafe.last_heartbeat_ms = tnow; break; } case MAVLINK_MSG_ID_HEARTBEAT: { // We keep track of the last time we received a heartbeat from // our GCS for failsafe purposes if (msg->sysid != plane.g.sysid_my_gcs) break; plane.failsafe.last_heartbeat_ms = AP_HAL::millis(); break; } case MAVLINK_MSG_ID_HIL_STATE: { #if HIL_SUPPORT if (plane.g.hil_mode != 1) { break; } mavlink_hil_state_t packet; mavlink_msg_hil_state_decode(msg, &packet); // sanity check location if (!check_latlng(packet.lat, packet.lon)) { break; } last_hil_state = packet; // set gps hil sensor const Location loc{packet.lat, packet.lon, packet.alt/10, Location::AltFrame::ABSOLUTE}; Vector3f vel(packet.vx, packet.vy, packet.vz); vel *= 0.01f; // setup airspeed pressure based on 3D speed, no wind plane.airspeed.setHIL(sq(vel.length()) / 2.0f + 2013); plane.gps.setHIL(0, AP_GPS::GPS_OK_FIX_3D, packet.time_usec/1000, loc, vel, 10, 0); // rad/sec Vector3f gyros; gyros.x = packet.rollspeed; gyros.y = packet.pitchspeed; gyros.z = packet.yawspeed; // m/s/s Vector3f accels; accels.x = packet.xacc * GRAVITY_MSS*0.001f; accels.y = packet.yacc * GRAVITY_MSS*0.001f; accels.z = packet.zacc * GRAVITY_MSS*0.001f; plane.ins.set_gyro(0, gyros); plane.ins.set_accel(0, accels); plane.barometer.setHIL(packet.alt*0.001f); plane.compass.setHIL(0, packet.roll, packet.pitch, packet.yaw); plane.compass.setHIL(1, packet.roll, packet.pitch, packet.yaw); // cope with DCM getting badly off due to HIL lag if (plane.g.hil_err_limit > 0 && (fabsf(packet.roll - plane.ahrs.roll) > ToRad(plane.g.hil_err_limit) || fabsf(packet.pitch - plane.ahrs.pitch) > ToRad(plane.g.hil_err_limit) || wrap_PI(fabsf(packet.yaw - plane.ahrs.yaw)) > ToRad(plane.g.hil_err_limit))) { plane.ahrs.reset_attitude(packet.roll, packet.pitch, packet.yaw); } #endif break; } case MAVLINK_MSG_ID_RADIO: case MAVLINK_MSG_ID_RADIO_STATUS: { handle_radio_status(msg, plane.should_log(MASK_LOG_PM)); break; } case MAVLINK_MSG_ID_DISTANCE_SENSOR: plane.rangefinder.handle_msg(msg); break; case MAVLINK_MSG_ID_TERRAIN_DATA: case MAVLINK_MSG_ID_TERRAIN_CHECK: #if AP_TERRAIN_AVAILABLE plane.terrain.handle_data(chan, msg); #endif break; case MAVLINK_MSG_ID_SET_ATTITUDE_TARGET: { // Only allow companion computer (or other external controller) to // control attitude in GUIDED mode. We DON'T want external control // in e.g., RTL, CICLE. Specifying a single mode for companion // computer control is more safe (even more so when using // FENCE_ACTION = 4 for geofence failures). if ((plane.control_mode != &plane.mode_guided) && (plane.control_mode != &plane.mode_avoidADSB)) { // don't screw up failsafes break; } mavlink_set_attitude_target_t att_target; mavlink_msg_set_attitude_target_decode(msg, &att_target); // Mappings: If any of these bits are set, the corresponding input should be ignored. // NOTE, when parsing the bits we invert them for easier interpretation but transport has them inverted // bit 1: body roll rate // bit 2: body pitch rate // bit 3: body yaw rate // bit 4: unknown // bit 5: unknown // bit 6: reserved // bit 7: throttle // bit 8: attitude // if not setting all Quaternion values, use _rate flags to indicate which fields. // Extract the Euler roll angle from the Quaternion. Quaternion q(att_target.q[0], att_target.q[1], att_target.q[2], att_target.q[3]); // NOTE: att_target.type_mask is inverted for easier interpretation att_target.type_mask = att_target.type_mask ^ 0xFF; uint8_t attitude_mask = att_target.type_mask & 0b10000111; // q plus rpy uint32_t now = AP_HAL::millis(); if ((attitude_mask & 0b10000001) || // partial, including roll (attitude_mask == 0b10000000)) { // all angles plane.guided_state.forced_rpy_cd.x = degrees(q.get_euler_roll()) * 100.0f; // Update timer for external roll to the nav control plane.guided_state.last_forced_rpy_ms.x = now; } if ((attitude_mask & 0b10000010) || // partial, including pitch (attitude_mask == 0b10000000)) { // all angles plane.guided_state.forced_rpy_cd.y = degrees(q.get_euler_pitch()) * 100.0f; // Update timer for external pitch to the nav control plane.guided_state.last_forced_rpy_ms.y = now; } if ((attitude_mask & 0b10000100) || // partial, including yaw (attitude_mask == 0b10000000)) { // all angles plane.guided_state.forced_rpy_cd.z = degrees(q.get_euler_yaw()) * 100.0f; // Update timer for external yaw to the nav control plane.guided_state.last_forced_rpy_ms.z = now; } if (att_target.type_mask & 0b01000000) { // throttle plane.guided_state.forced_throttle = att_target.thrust * 100.0f; // Update timer for external throttle plane.guided_state.last_forced_throttle_ms = now; } break; } case MAVLINK_MSG_ID_SET_HOME_POSITION: { mavlink_set_home_position_t packet; mavlink_msg_set_home_position_decode(msg, &packet); Location new_home_loc {}; new_home_loc.lat = packet.latitude; new_home_loc.lng = packet.longitude; new_home_loc.alt = packet.altitude / 10; if (!set_home(new_home_loc, false)) { // silently fails... break; } break; } case MAVLINK_MSG_ID_SET_POSITION_TARGET_LOCAL_NED: { // decode packet mavlink_set_position_target_local_ned_t packet; mavlink_msg_set_position_target_local_ned_decode(msg, &packet); // exit if vehicle is not in Guided mode if (plane.control_mode != &plane.mode_guided) { break; } // only local moves for now if (packet.coordinate_frame != MAV_FRAME_LOCAL_OFFSET_NED) { break; } // just do altitude for now plane.next_WP_loc.alt += -packet.z*100.0; gcs().send_text(MAV_SEVERITY_INFO, "Change alt to %.1f", (double)((plane.next_WP_loc.alt - plane.home.alt)*0.01)); break; } case MAVLINK_MSG_ID_SET_POSITION_TARGET_GLOBAL_INT: { // Only want to allow companion computer position control when // in a certain mode to avoid inadvertently sending these // kinds of commands when the autopilot is responding to problems // in modes such as RTL, CIRCLE, etc. Specifying ONLY one mode // for companion computer control is more safe (provided // one uses the FENCE_ACTION = 4 (RTL) for geofence failures). if (plane.control_mode != &plane.mode_guided && plane.control_mode != &plane.mode_avoidADSB) { //don't screw up failsafes break; } mavlink_set_position_target_global_int_t pos_target; mavlink_msg_set_position_target_global_int_decode(msg, &pos_target); // Unexpectedly, the mask is expecting "ones" for dimensions that should // be IGNORNED rather than INCLUDED. See mavlink documentation of the // SET_POSITION_TARGET_GLOBAL_INT message, type_mask field. const uint16_t alt_mask = 0b1111111111111011; // (z mask at bit 3) bool msg_valid = true; AP_Mission::Mission_Command cmd = {0}; if (pos_target.type_mask & alt_mask) { cmd.content.location.alt = pos_target.alt * 100; cmd.content.location.relative_alt = false; cmd.content.location.terrain_alt = false; switch (pos_target.coordinate_frame) { case MAV_FRAME_GLOBAL_INT: break; //default to MSL altitude case MAV_FRAME_GLOBAL_RELATIVE_ALT_INT: cmd.content.location.relative_alt = true; break; case MAV_FRAME_GLOBAL_TERRAIN_ALT_INT: cmd.content.location.relative_alt = true; cmd.content.location.terrain_alt = true; break; default: gcs().send_text(MAV_SEVERITY_WARNING, "Invalid coord frame in SET_POSTION_TARGET_GLOBAL_INT"); msg_valid = false; break; } if (msg_valid) { handle_change_alt_request(cmd); } } // end if alt_mask break; } case MAVLINK_MSG_ID_ADSB_VEHICLE: case MAVLINK_MSG_ID_UAVIONIX_ADSB_OUT_CFG: case MAVLINK_MSG_ID_UAVIONIX_ADSB_OUT_DYNAMIC: case MAVLINK_MSG_ID_UAVIONIX_ADSB_TRANSCEIVER_HEALTH_REPORT: plane.adsb.handle_message(chan, msg); break; default: handle_common_message(msg); break; } // end switch } // end handle mavlink