Tools/AntennaTracker: completed intial tracker code

Now works with 2 servo alt-azimuth mounted antenna tracking mount. Tested
on Flymaple, with Eagle Tree antenna tracker.
This commit is contained in:
Mike McCauley 2014-03-02 17:00:37 +10:00 committed by Andrew Tridgell
parent 8251cf32fb
commit 0885d55905
8 changed files with 476 additions and 31 deletions

View File

@ -28,9 +28,9 @@ static NOINLINE void send_heartbeat(mavlink_channel_t chan)
chan, chan,
MAV_TYPE_ANTENNA_TRACKER, MAV_TYPE_ANTENNA_TRACKER,
MAV_AUTOPILOT_ARDUPILOTMEGA, MAV_AUTOPILOT_ARDUPILOTMEGA,
MAV_MODE_FLAG_AUTO_ENABLED,
0, 0,
0, MAV_STATE_ACTIVE);
0);
} }
static NOINLINE void send_attitude(mavlink_channel_t chan) static NOINLINE void send_attitude(mavlink_channel_t chan)
@ -56,16 +56,12 @@ static void NOINLINE send_location(mavlink_channel_t chan)
} else { } else {
fix_time = hal.scheduler->millis(); fix_time = hal.scheduler->millis();
} }
Location loc;
ahrs.get_position(loc);
mavlink_msg_global_position_int_send( mavlink_msg_global_position_int_send(
chan, chan,
fix_time, fix_time,
loc.lat, // in 1E7 degrees current_loc.lat, // in 1E7 degrees
loc.lng, // in 1E7 degrees current_loc.lng, // in 1E7 degrees
g_gps->altitude_cm * 10, // millimeters above sea level current_loc.alt * 10, // millimeters above sea level
0, 0,
g_gps->velocity_north() * 100, // X speed cm/s (+ve North) g_gps->velocity_north() * 100, // X speed cm/s (+ve North)
g_gps->velocity_east() * 100, // Y speed cm/s (+ve East) g_gps->velocity_east() * 100, // Y speed cm/s (+ve East)
@ -75,6 +71,11 @@ static void NOINLINE send_location(mavlink_channel_t chan)
static void NOINLINE send_gps_raw(mavlink_channel_t chan) static void NOINLINE send_gps_raw(mavlink_channel_t chan)
{ {
static uint32_t last_send_time;
if (last_send_time != 0 && last_send_time == g_gps->last_fix_time && g_gps->status() >= GPS::GPS_OK_FIX_3D) {
return;
}
last_send_time = g_gps->last_fix_time;
mavlink_msg_gps_raw_int_send( mavlink_msg_gps_raw_int_send(
chan, chan,
g_gps->last_fix_time*(uint64_t)1000, g_gps->last_fix_time*(uint64_t)1000,
@ -209,6 +210,14 @@ static void NOINLINE send_hwstatus(mavlink_channel_t chan)
hal.i2c->lockup_count()); hal.i2c->lockup_count());
} }
static void NOINLINE send_waypoint_request(mavlink_channel_t chan)
{
if (chan == MAVLINK_COMM_0)
gcs0.queued_waypoint_send();
else
gcs3.queued_waypoint_send();
}
static void NOINLINE send_statustext(mavlink_channel_t chan) static void NOINLINE send_statustext(mavlink_channel_t chan)
{ {
mavlink_statustext_t *s = (chan == MAVLINK_COMM_0?&gcs0.pending_status:&gcs3.pending_status); mavlink_statustext_t *s = (chan == MAVLINK_COMM_0?&gcs0.pending_status:&gcs3.pending_status);
@ -292,6 +301,11 @@ static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id,
} }
break; break;
case MSG_NEXT_WAYPOINT:
CHECK_PAYLOAD_SIZE(MISSION_REQUEST);
send_waypoint_request(chan);
break;
case MSG_STATUSTEXT: case MSG_STATUSTEXT:
CHECK_PAYLOAD_SIZE(STATUSTEXT); CHECK_PAYLOAD_SIZE(STATUSTEXT);
send_statustext(chan); send_statustext(chan);
@ -315,7 +329,6 @@ static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id,
case MSG_VFR_HUD: case MSG_VFR_HUD:
case MSG_RADIO_IN: case MSG_RADIO_IN:
case MSG_SYSTEM_TIME: case MSG_SYSTEM_TIME:
case MSG_NEXT_WAYPOINT:
case MSG_LIMITS_STATUS: case MSG_LIMITS_STATUS:
case MSG_FENCE_STATUS: case MSG_FENCE_STATUS:
case MSG_SIMSTATE: case MSG_SIMSTATE:
@ -514,6 +527,7 @@ GCS_MAVLINK::update(void)
// Update packet drops counter // Update packet drops counter
packet_drops += status.packet_rx_drop_count; packet_drops += status.packet_rx_drop_count;
} }
// see if we should send a stream now. Called at 50Hz // see if we should send a stream now. Called at 50Hz
@ -624,6 +638,8 @@ GCS_MAVLINK::send_text_P(gcs_severity severity, const prog_char_t *str)
void GCS_MAVLINK::handleMessage(mavlink_message_t* msg) void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
{ {
// hal.uartA->printf("handleMessage %d\n", msg->msgid);
switch (msg->msgid) { switch (msg->msgid) {
case MAVLINK_MSG_ID_REQUEST_DATA_STREAM: case MAVLINK_MSG_ID_REQUEST_DATA_STREAM:
@ -811,7 +827,182 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
break; break;
} }
case MAVLINK_MSG_ID_GLOBAL_POSITION_INT: { case MAVLINK_MSG_ID_COMMAND_LONG:
{
// decode
mavlink_command_long_t packet;
mavlink_msg_command_long_decode(msg, &packet);
if (mavlink_check_target(packet.target_system, packet.target_component)) break;
uint8_t result = MAV_RESULT_UNSUPPORTED;
// do command
send_text_P(SEVERITY_LOW,PSTR("command received: "));
switch(packet.command) {
case MAV_CMD_PREFLIGHT_CALIBRATION:
{
if (packet.param1 == 1 ||
packet.param2 == 1) {
calibrate_ins();
} else if (packet.param3 == 1) {
init_barometer();
}
if (packet.param4 == 1) {
// Cant trim radio
}
#if !defined( __AVR_ATmega1280__ )
if (packet.param5 == 1) {
float trim_roll, trim_pitch;
AP_InertialSensor_UserInteract_MAVLink interact(chan);
if(ins.calibrate_accel(&interact, trim_roll, trim_pitch)) {
// reset ahrs's trim to suggested values from calibration routine
ahrs.set_trim(Vector3f(trim_roll, trim_pitch, 0));
}
}
#endif
result = MAV_RESULT_ACCEPTED;
break;
}
case MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN:
{
if (packet.param1 == 1 || packet.param1 == 3) {
// when packet.param1 == 3 we reboot to hold in bootloader
hal.scheduler->reboot(packet.param1 == 3);
result = MAV_RESULT_ACCEPTED;
}
break;
}
default:
break;
}
mavlink_msg_command_ack_send(
chan,
packet.command,
result);
break;
}
// When mavproxy 'wp sethome'
case MAVLINK_MSG_ID_MISSION_WRITE_PARTIAL_LIST:
{
// decode
mavlink_mission_write_partial_list_t packet;
mavlink_msg_mission_write_partial_list_decode(msg, &packet);
if (mavlink_check_target(packet.target_system,packet.target_component)) break;
if (packet.start_index == 0)
{
// New home at wp index 0. Ask for it
waypoint_receiving = true;
waypoint_request_i = 0;
waypoint_request_last = 0;
send_message(MSG_NEXT_WAYPOINT);
waypoint_receiving = true;
}
break;
}
// XXX receive a WP from GCS and store in EEPROM if it is HOME
case MAVLINK_MSG_ID_MISSION_ITEM:
{
// decode
mavlink_mission_item_t packet;
uint8_t result = MAV_MISSION_ACCEPTED;
mavlink_msg_mission_item_decode(msg, &packet);
if (mavlink_check_target(packet.target_system,packet.target_component)) break;
struct Location tell_command = {};
// defaults
tell_command.id = packet.command;
switch (packet.frame)
{
case MAV_FRAME_MISSION:
case MAV_FRAME_GLOBAL:
{
tell_command.lat = 1.0e7f*packet.x; // in as DD converted to * t7
tell_command.lng = 1.0e7f*packet.y; // in as DD converted to * t7
tell_command.alt = packet.z*1.0e2f; // in as m converted to cm
tell_command.options = 0; // absolute altitude
break;
}
#ifdef MAV_FRAME_LOCAL_NED
case MAV_FRAME_LOCAL_NED: // local (relative to home position)
{
tell_command.lat = 1.0e7f*ToDeg(packet.x/
(RADIUS_OF_EARTH*cosf(ToRad(home.lat/1.0e7f)))) + home.lat;
tell_command.lng = 1.0e7f*ToDeg(packet.y/RADIUS_OF_EARTH) + home.lng;
tell_command.alt = -packet.z*1.0e2f;
tell_command.options = MASK_OPTIONS_RELATIVE_ALT;
break;
}
#endif
#ifdef MAV_FRAME_LOCAL
case MAV_FRAME_LOCAL: // local (relative to home position)
{
tell_command.lat = 1.0e7f*ToDeg(packet.x/
(RADIUS_OF_EARTH*cosf(ToRad(home.lat/1.0e7f)))) + home.lat;
tell_command.lng = 1.0e7f*ToDeg(packet.y/RADIUS_OF_EARTH) + home.lng;
tell_command.alt = packet.z*1.0e2f;
tell_command.options = MASK_OPTIONS_RELATIVE_ALT;
break;
}
#endif
case MAV_FRAME_GLOBAL_RELATIVE_ALT: // absolute lat/lng, relative altitude
{
tell_command.lat = 1.0e7f * packet.x; // in as DD converted to * t7
tell_command.lng = 1.0e7f * packet.y; // in as DD converted to * t7
tell_command.alt = packet.z * 1.0e2f;
tell_command.options = MASK_OPTIONS_RELATIVE_ALT; // store altitude relative!! Always!!
break;
}
default:
result = MAV_MISSION_UNSUPPORTED_FRAME;
break;
}
if (result != MAV_MISSION_ACCEPTED) goto mission_failed;
// Check if receiving waypoints (mission upload expected)
if (!waypoint_receiving) {
result = MAV_MISSION_ERROR;
goto mission_failed;
}
// check if this is the HOME wp
if (packet.seq == 0) {
set_home(tell_command); // New home in EEPROM
send_text_P(SEVERITY_LOW,PSTR("new HOME received"));
waypoint_receiving = false;
}
mission_failed:
// we are rejecting the mission/waypoint
mavlink_msg_mission_ack_send(
chan,
msg->sysid,
msg->compid,
result);
break;
}
case MAVLINK_MSG_ID_GLOBAL_POSITION_INT:
{
// decode // decode
mavlink_global_position_int_t packet; mavlink_global_position_int_t packet;
mavlink_msg_global_position_int_decode(msg, &packet); mavlink_msg_global_position_int_decode(msg, &packet);

View File

@ -69,7 +69,12 @@ public:
k_param_pidYaw2Srv, k_param_pidYaw2Srv,
k_param_channel_yaw = 200, k_param_channel_yaw = 200,
k_param_channel_pitch k_param_channel_pitch,
//
// 220: Waypoint data
//
k_param_command_total = 220,
// 254,255: reserved // 254,255: reserved
}; };
@ -86,6 +91,10 @@ public:
AP_Int8 compass_enabled; AP_Int8 compass_enabled;
// Waypoints
//
AP_Int8 command_total; // 1 if HOME is set
// PID controllers // PID controllers
PID pidPitch2Srv; PID pidPitch2Srv;
PID pidYaw2Srv; PID pidYaw2Srv;

View File

@ -100,6 +100,14 @@ const AP_Param::Info var_info[] PROGMEM = {
GGROUP(pidPitch2Srv, "PITCH2SRV_", PID), GGROUP(pidPitch2Srv, "PITCH2SRV_", PID),
GGROUP(pidYaw2Srv, "YAW2SRV_", PID), GGROUP(pidYaw2Srv, "YAW2SRV_", PID),
// @Param: CMD_TOTAL
// @DisplayName: Number of loaded mission items
// @Description: Set to 1 if HOME location has been loaded by the ground station. Do not change this manually.
// @Range: 1 255
// @User: Advanced
GSCALAR(command_total, "CMD_TOTAL", 0),
AP_VAREND AP_VAREND
}; };

View File

@ -81,3 +81,13 @@
#ifndef SERIAL2_BUFSIZE #ifndef SERIAL2_BUFSIZE
# define SERIAL2_BUFSIZE 256 # define SERIAL2_BUFSIZE 256
#endif #endif
//////////////////////////////////////////////////////////////////////////////
// Developer Items
//
// use this to completely disable the CLI
#ifndef CLI_ENABLED
# define CLI_ENABLED ENABLED
#endif

View File

@ -30,4 +30,25 @@
#define AP_COMPASS_PX4 2 #define AP_COMPASS_PX4 2
#define AP_COMPASS_HIL 3 #define AP_COMPASS_HIL 3
// In AntennaTracker, EEPROM is used to store waypoint 0 = HOME location, if available
// EEPROM addresses
#define EEPROM_MAX_ADDR 4096
// parameters get the first 1280 bytes of EEPROM, remainder is for waypoints
#define WP_START_BYTE 0x500 // where in memory home WP is stored + all other
// WP
#define WP_SIZE 15
// Commands - Note that APM now uses a subset of the MAVLink protocol commands. See enum MAV_CMD in the GCS_Mavlink library
#define CMD_BLANK 0 // there is no command stored in the mem location requested
#define NO_COMMAND 0
#define WAIT_COMMAND 255
// Command/Waypoint/Location Options Bitmask
//--------------------
#define MASK_OPTIONS_RELATIVE_ALT (1<<0) // 1 = Relative
// altitude
#define MASK_OPTIONS_LOITER_DIRECTION (1<<2) // 0 = CW
// 1 = CCW
#endif // _DEFINES_H #endif // _DEFINES_H

View File

@ -61,5 +61,7 @@ static void barometer_accumulate(void)
static void update_GPS(void) static void update_GPS(void)
{ {
g_gps->update(); g_gps->update();
// REVISIT: add compass variation with compass.set_initial_location(g_gps->latitude, g_gps->longitude);
// when have a solid GPS fix. Also init_home();
} }

View File

@ -63,8 +63,8 @@ static void init_tracker()
hal.uartC->set_blocking_writes(false); hal.uartC->set_blocking_writes(false);
// setup antenna control PWM channels // setup antenna control PWM channels
channel_yaw.set_angle(4500); channel_yaw.set_angle(18000); // Yaw is expected to drive antenna azimuth -180-0-180
channel_pitch.set_angle(4500); channel_pitch.set_angle(9000); // Pitch is expected to drive elevation -90-0-90
channel_yaw.output_trim(); channel_yaw.output_trim();
channel_pitch.output_trim(); channel_pitch.output_trim();
@ -75,8 +75,24 @@ static void init_tracker()
channel_yaw.enable_out(); channel_yaw.enable_out();
channel_pitch.enable_out(); channel_pitch.enable_out();
home_loc = get_home_eeprom(); // GPS may update this later
gcs_send_text_P(SEVERITY_LOW,PSTR("\nReady to track.")); gcs_send_text_P(SEVERITY_LOW,PSTR("\nReady to track."));
hal.scheduler->delay(1000); hal.scheduler->delay(1000); // Why????
}
// Level the tracker by calibrating the INS
// Requires that the tracker be physically 'level' and horizontal
static void calibrate_ins()
{
gcs_send_text_P(SEVERITY_MEDIUM, PSTR("Beginning INS calibration; do not move tracker"));
ahrs.init();
ahrs.set_fly_forward(true);
ins.init(AP_InertialSensor::COLD_START, ins_sample_rate);
ins.init_accel();
ahrs.set_trim(Vector3f(0, 0, 0));
ahrs.reset();
init_barometer();
} }
// updates the status of the notify objects // updates the status of the notify objects
@ -106,4 +122,72 @@ static uint32_t map_baudrate(int8_t rate, uint32_t default_baud)
return default_baud; return default_baud;
} }
/*
fetch HOME from EEPROM
*/
static struct Location get_home_eeprom()
{
struct Location temp;
uint16_t mem;
// Find out proper location in memory by using the start_byte position + the index
// --------------------------------------------------------------------------------
if (g.command_total.get() == 0) {
memset(&temp, 0, sizeof(temp));
temp.id = CMD_BLANK;
}else{
// read WP position
mem = WP_START_BYTE;
temp.id = hal.storage->read_byte(mem);
mem++;
temp.options = hal.storage->read_byte(mem);
mem++;
temp.p1 = hal.storage->read_byte(mem);
mem++;
temp.alt = hal.storage->read_dword(mem);
mem += 4;
temp.lat = hal.storage->read_dword(mem);
mem += 4;
temp.lng = hal.storage->read_dword(mem);
}
return temp;
}
static void set_home_eeprom(struct Location temp)
{
uint16_t mem = WP_START_BYTE;
hal.storage->write_byte(mem, temp.id);
mem++;
hal.storage->write_byte(mem, temp.options);
mem++;
hal.storage->write_byte(mem, temp.p1);
mem++;
hal.storage->write_dword(mem, temp.alt);
mem += 4;
hal.storage->write_dword(mem, temp.lat);
mem += 4;
hal.storage->write_dword(mem, temp.lng);
// Now have a home location in EEPROM
g.command_total.set_and_save(1); // At most 1 entry for HOME
}
static void set_home(struct Location temp)
{
if (g.compass_enabled)
compass.set_initial_location(temp.lat, temp.lng);
set_home_eeprom(temp);
home_loc = temp;
}

View File

@ -4,31 +4,149 @@
state of the vehicle we are tracking state of the vehicle we are tracking
*/ */
static struct { static struct {
Location location; Location location; // lat, long in degrees * 10^7; alt in meters * 100
uint32_t last_update_us; uint32_t last_update_us;
float heading; // degrees float heading; // degrees
float ground_speed; // m/s float ground_speed; // m/s
} vehicle; } vehicle;
static Location our_location;
/** /**
update the pitch servo. The aim is to drive the boards pitch to the update the pitch (elevation) servo. The aim is to drive the boards ahrs pitch to the
requested pitch requested pitch, so the board (and therefore the antenna) will be pointing at the target
*/ */
static void update_pitch_servo(float pitch) static void update_pitch_servo(float pitch)
{ {
channel_pitch.servo_out = g.pidPitch2Srv.get_pid_4500(degrees(ahrs.pitch) - pitch); // degrees(ahrs.pitch) is -90 to 90, where 0 is horizontal
// pitch argument is -90 to 90, where 0 is horizontal
// servo_out is in 100ths of a degree
float ahrs_pitch = degrees(ahrs.pitch);
int32_t err = (ahrs_pitch - pitch) * 100.0;
// Need to configure your servo so that increasing servo_out causes increase in pitch/elevation (ie pointing higher into the sky,
// above the horizon. On my antenna tracker this requires the pitch/elevation servo to be reversed
// param set RC2_REV -1
//
// The pitch servo (RC channel 2) is configured for servo_out of -9000-0-9000 servo_out,
// which will drive the servo from RC2_MIN to RC2_MAX usec pulse width.
// Therefore, you must set RC2_MIN and RC2_MAX so that your servo drives the antenna altitude between -90 to 90 exactly
// To drive my HS-645MG servos through their full 180 degrees of rotational range, I have to set:
// param set RC2_MAX 2540
// param set RC2_MIN 640
//
// You will also need to tune the pitch PID to suit your antenna and servos. I use:
// PITCH2SRV_P 0.100000
// PITCH2SRV_I 0.020000
// PITCH2SRV_D 0.000000
// PITCH2SRV_IMAX 4000.000000
int32_t new_servo_out = channel_pitch.servo_out - g.pidPitch2Srv.get_pid(err);
channel_pitch.servo_out = constrain_float(new_servo_out, -9000, 9000);
channel_pitch.calc_pwm(); channel_pitch.calc_pwm();
channel_pitch.output(); channel_pitch.output();
} }
/** /**
update the yaw servo update the yaw (azimuth) servo. The aim is to drive the boards ahrs yaw to the
requested yaw, so the board (and therefore the antenna) will be pinting at the target
*/ */
static void update_yaw_servo(float yaw) static void update_yaw_servo(float yaw)
{ {
channel_yaw.servo_out = g.pidYaw2Srv.get_pid_4500(degrees(ahrs.yaw) - yaw); // degrees(ahrs.yaw) is -180 to 180, where 0 is north
float ahrs_yaw = degrees(ahrs.yaw);
// yaw argument is 0 to 360 where 0 and 360 are north
// Make yaw -180-0-180 too
if (yaw > 180)
yaw = yaw - 360;
// Antenna as Ballerina. Use with antenna that do not have continuously rotating servos, ie at some point in rotation
// the servo limits are reached and the servo has to slew 360 degrees to the 'other side' to keep tracking.
//
// This algorithm accounts for the fact that the antenna mount may not be aligned with North
// (in fact, any alignment is permissable), and that the alignment may change (possibly rapidly) over time
// (as when the antenna is mounted on a moving, turning vehicle)
// When the servo is being forced beyond its limits, it rapidly slews to the 'other side' then normal tracking takes over.
//
// Caution: this whole system is compromised by the fact that the ahrs_yaw reported by the compass system lags
// the actual yaw by about 5 seconds, and also periodically realigns itself with about a 30 second period,
// which makes it very hard to be completely sure exactly where the antenna is _really_ pointing
// especially during the high speed slew. This can cause odd pointing artifacts from time to time. The best strategy is to
// position and point the mount so the aircraft does not 'go behind' the antenna (if possible)
//
// With my antenna mount, large pwm output drives the antenna anticlockise, so need:
// param set RC1_REV -1
// to reverse the servo. Yours may be different
//
// You MUST set RC1_MIN and RC1_MAX so that your servo drives the antenna azimuth from -180 to 180 relative
// to the mount.
// To drive my HS-645MG servos through their full 180 degrees of rotational range and therefore the
// antenna through a full 360 degrees, I have to set:
// param set RC1_MAX 2380
// param set RC1_MIN 680
// According to the specs at https://www.servocity.com/html/hs-645mg_ultra_torque.html,
// that should be 600 through 2400, but the azimuth gearing in my antenna pointer is not exactly 2:1
int32_t err = (ahrs_yaw - yaw) * 100.0;
static int32_t last_err = 0.0;
// Correct for wrapping yaw at +-180
// so we get the error to the _closest_ version of the target azimuth
// +ve error requires anticlockwise motion (ie towards more negative yaw)
if (err > 18000)
err -= 36000;
else if (err < -18000)
err += 36000;
static int32_t slew_to = 0;
int32_t servo_err = channel_yaw.servo_out - err; // Servo position we need to get to
if ( !slew_to
&& servo_err > 19000 // 10 degreee deadband
&& err < 0
&& last_err > err)
{
// We need to be beyond the servo limits and the error magnitude is increasing
// Slew most of the way to the other side at high speed...
slew_to = servo_err - 27000;
}
else if ( !slew_to
&& servo_err < -19000 // 10 degreee deadband
&& err > 0
&& last_err < err)
{
// We need to be beyond the servo limits and the error magnitude is increasing
// Slew most of the way to the other side at high speed...
slew_to = servo_err + 27000;
}
else if ( slew_to < 0
&& err > 0
&& last_err < err)
{
// ...then let normal tracking take over
slew_to = 0;
}
else if ( slew_to > 0
&& err < 0
&& last_err > err)
{
// ...then let normal tracking take over
slew_to = 0;
}
if (slew_to)
{
channel_yaw.servo_out = slew_to;
}
else
{
// Normal tracking
// You will need to tune the yaw PID to suit your antenna and servos
// For my servos, suitable PID settings are:
// param set YAW2SRV_P 0.1
// param set YAW2SRV_I 0.05
// param set YAW2SRV_D 0
// param set YAW2SRV_IMAX 4000
int32_t new_servo_out = channel_yaw.servo_out - g.pidYaw2Srv.get_pid(err);
channel_yaw.servo_out = constrain_float(new_servo_out, -18000, 18000);
}
last_err = err;
channel_yaw.calc_pwm(); channel_yaw.calc_pwm();
channel_yaw.output(); channel_yaw.output();
} }
@ -46,16 +164,17 @@ static void update_tracking(void)
// update our position if we have at least a 2D fix // update our position if we have at least a 2D fix
if (g_gps->status() >= GPS::GPS_OK_FIX_2D) { if (g_gps->status() >= GPS::GPS_OK_FIX_2D) {
our_location.lat = g_gps->latitude; current_loc.lat = g_gps->latitude;
our_location.lng = g_gps->longitude; current_loc.lng = g_gps->longitude;
our_location.alt = 0; // assume ground level for now current_loc.alt = 0; // assume ground level for now REVISIT: WHY?
}
else {
current_loc = home_loc; // dont know any better
} }
// calculate the bearing to the vehicle // calculate the bearing to the vehicle
float bearing = get_bearing_cd(our_location, vehicle.location) * 0.01f; float bearing = get_bearing_cd(current_loc, vehicle.location) * 0.01f;
float distance = get_distance(our_location, vehicle.location); float distance = get_distance(current_loc, vehicle.location);
float pitch = degrees(atan2(vehicle.location.alt - our_location.alt, distance)); float pitch = degrees(atan2((vehicle.location.alt - current_loc.alt)/100, distance));
// update the servos // update the servos
update_pitch_servo(pitch); update_pitch_servo(pitch);
update_yaw_servo(bearing); update_yaw_servo(bearing);
@ -79,3 +198,4 @@ static void tracking_update_position(const mavlink_global_position_int_t &msg)
vehicle.ground_speed = pythagorous2(msg.vx, msg.vy) * 0.01f; vehicle.ground_speed = pythagorous2(msg.vx, msg.vy) * 0.01f;
vehicle.last_update_us = hal.scheduler->micros(); vehicle.last_update_us = hal.scheduler->micros();
} }