从APM源码分析GPS、气压计惯导融合

2023-05-16

最近事多,忙着开源自研飞控,现主要工作基本已经完成,代码最迟下月中旬开放,博客来不及更新,还请各位见谅,后面会抽空多更的咯!!!

自研飞控靓照如下:主控STM32F103RCT6,IMU组合:MPU6050、IST8310(DJI同款磁力计、5883已停产)SPL06_001(歌尔最新高精度气压计),GPS:M8N输出PVT



为方便大家学习,飞控工程支持Keil 、IAR两款编译器,满足不同的使用习惯


支持调试软件有:山外多功能调试助手、APM\Pixhawk\Autoquad原版地面站、ANO地面站等





最新测试视频链接附在本文最后!!!

前几篇博客都是讲的无人机惯性导航,气压计、GPS融合问题,算法参考APM的三阶互补滤波方案,也就是经典的回路反馈法。有飞控爱好者和我交流,也想使用该算法,奈何APM整个工程代码量实在太大,新手根本不知道该如何下手,下面我们就直接贴出APM源码里面的AP_InertialNav.c文件出来,逐一分析,相关算法实现步骤。

一、首先解决算法里面三个关键的参数:Ka,Kv,Ks,下面看APM源码里面相关定义:

// update_gains - update gains from time constant (given in seconds)

void AP_InertialNav::update_gains()
{
    // X & Y axis time constant
    if (_time_constant_xy == 0.0f) {
        _k1_xy = _k2_xy = _k3_xy = 0.0f;
    }else{
        _k1_xy = 3.0f / _time_constant_xy;
        _k2_xy = 3.0f / (_time_constant_xy*_time_constant_xy);
        _k3_xy = 1.0f / (_time_constant_xy*_time_constant_xy*_time_constant_xy);
    }


    // Z axis time constant
    if (_time_constant_z == 0.0f) {
        _k1_z = _k2_z = _k3_z = 0.0f;
    }else{
        _k1_z = 3.0f / _time_constant_z;
        _k2_z = 3.0f / (_time_constant_z*_time_constant_z);
        _k3_z = 1.0f / (_time_constant_z*_time_constant_z*_time_constant_z);
    }
}

源码里面的_k1为图中Ks,_k2为图中Kv,_k3为图中Ka,代码里面时间常数_time_constant为AP_InertialNav.h里面的宏定义:

#define AP_INTERTIALNAV_TC_XY   2.5f // default time constant for complementary filter's X & Y axis
#define AP_INTERTIALNAV_TC_Z    5.0f // default time constant for complementary filter's Z axis

二、解决第二个问题,惯导观测传感器数据怎么得到

1、气压计相对比较简单,通用的是采用压差法获取相对高度:

// return current scale factor that converts from equivalent to true airspeed
// valid for altitudes up to 10km AMSL
// assumes standard atmosphere lapse rate
float AP_Baro::get_EAS2TAS(void)
{
    if ((fabsf(_altitude - _last_altitude_EAS2TAS) < 100.0f) && (_EAS2TAS != 0.0f)) {
        // not enough change to require re-calculating
        return _EAS2TAS;
    }
    float tempK = ((float)_ground_temperature) + 273.15f - 0.0065f * _altitude;
    _EAS2TAS = safe_sqrt(1.225f / ((float)get_pressure() / (287.26f * tempK)));
    _last_altitude_EAS2TAS = _altitude;
    return _EAS2TAS;
}

2、GPS利用经纬度得到导航坐标系下相对Home点的正北、正东方向位置偏移量则采用球面投影的方式:

    x = (float)(lat - _ahrs.get_home().lat) * LATLON_TO_CM;
    y = (float)(lon - _ahrs.get_home().lng) * _lon_to_cm_scaling;

其中:#define LATLON_TO_CM 1.113195f

_lon_to_cm_scaling则根据飞控所处纬度相关,APM为了避免重复计算余弦值,当纬度两次纬度相差0.01度时,此值不更新。

float longitude_scale(Location loc)
{
    static int32_t last_lat;
    static float scale = 1.0;
    //比较两次纬度相差值,避免重复运算余弦函数
    if (ABS(last_lat - loc.lat) < 100000) {
    // we are within 0.01 degrees (about 1km) of the
    // same latitude. We can avoid the cos() and return
    // the same scale factor.
        return scale;
    }
    scale = cosf(loc.lat * 1.0e-7f * DEG_TO_RAD);
    scale = constrain_float(scale, 0.01f, 1.0f);
    last_lat = loc.lat;
    return scale;
}

得到的x,y分别表示无人机在导航坐标系下,相对Home点沿着正北、正东方向的位置偏移,单位为CM

3、加速度计得到运动加速度的获取请参考第一篇博客内容:

惯导运动加速度获取


三、结合APM源码,详细说明跟新过程

// update - updates velocities and positions using latest info from ahrs and barometer if new data is available;
void AP_InertialNav::update(float dt)
{
    // discard samples where dt is too large
    if( dt > 0.1f ) {
        return;
    }

    // decrement ignore error count if required
    if (_flags.ignore_error > 0) {
        _flags.ignore_error--;
    }

    // check if new baro readings have arrived and use them to correct vertical accelerometer offsets.
    check_baro();


    // check if new gps readings have arrived and use them to correct position estimates
    check_gps();


    Vector3f accel_ef = _ahrs.get_accel_ef();


    // remove influence of gravity
    accel_ef.z += GRAVITY_MSS;
    accel_ef *= 100.0f;


    // remove xy if not enabled
    if( !_xy_enabled ) {
        accel_ef.x = 0.0f;
        accel_ef.y = 0.0f;
    }


    //Convert North-East-Down to North-East-Up
    accel_ef.z = -accel_ef.z;

//首先将导航系下正北、正东、天方向上的位置观测误差,旋转机体俯仰与横滚方向上来
    // convert ef position error to horizontal body frame
    Vector2f position_error_hbf;
    position_error_hbf.x = _position_error.x * _ahrs.cos_yaw() + _position_error.y * _ahrs.sin_yaw();
    position_error_hbf.y = -_position_error.x * _ahrs.sin_yaw() + _position_error.y * _ahrs.cos_yaw();


//加速度计校正量
    float tmp = _k3_xy * dt;
    accel_correction_hbf.x += position_error_hbf.x * tmp;
    accel_correction_hbf.y += position_error_hbf.y * tmp;
    accel_correction_hbf.z += _position_error.z * _k3_z  * dt;


//上次速度加校正量
    tmp = _k2_xy * dt;
    _velocity.x += _position_error.x * tmp;
    _velocity.y += _position_error.y * tmp;
    _velocity.z += _position_error.z * _k2_z  * dt;


//导航坐标系下正北、正东、天方向上位置校正量
    tmp = _k1_xy * dt;
    _position_correction.x += _position_error.x * tmp;
    _position_correction.y += _position_error.y * tmp;
    _position_correction.z += _position_error.z * _k1_z  * dt;

//将导航系下的沿着载体俯仰、横滚方向的运动加速度计矫正量,旋转到导航坐标系正北、正东方向上
    // convert horizontal body frame accel correction to earth frame
    Vector2f accel_correction_ef;
    accel_correction_ef.x = accel_correction_hbf.x * _ahrs.cos_yaw() - accel_correction_hbf.y * _ahrs.sin_yaw();
    accel_correction_ef.y = accel_correction_hbf.x * _ahrs.sin_yaw() + accel_correction_hbf.y * _ahrs.cos_yaw();

//导航坐标系下正北、正东、天方向上,运动的速度增量更新
    // calculate velocity increase adding new acceleration from accelerometers
    Vector3f velocity_increase;
    velocity_increase.x = (accel_ef.x + accel_correction_ef.x) * dt;
    velocity_increase.y = (accel_ef.y + accel_correction_ef.y) * dt;
    velocity_increase.z = (accel_ef.z + accel_correction_hbf.z) * dt;


//导航坐标系下正北、正东、天方向上,初步位置更新,不包含本次位置校正量
    // calculate new estimate of position
    _position_base += (_velocity + velocity_increase*0.5) * dt;

//导航坐标系下正北、正东、天方向上,位置校正后更新
    // update the corrected position estimate
    _position = _position_base + _position_correction;
 //导航坐标系下正北、正东、天方向上,速度加增量后更新  
    // calculate new velocity
    _velocity += velocity_increase;

 //下面为惯导融合位置缓冲区,用于延时修正处理  
    // store 3rd order estimate (i.e. estimated vertical position) for future use
    _hist_position_estimate_z.push_back(_position_base.z);
   /* _histotic_z_counter++;
    if (_histotic_z_counter >= 4) {
        _histotic_z_counter = 0;
        _hist_position_estimate_z.push_back(_position_base.z);
    }*/


    // store 3rd order estimate (i.e. horizontal position) for future use at 10hz
    _historic_xy_counter++;
    if( _historic_xy_counter >= AP_INTERTIALNAV_SAVE_POS_AFTER_ITERATIONS ) {
        _historic_xy_counter = 0;
        _hist_position_estimate_x.push_back(_position_base.x);
        _hist_position_estimate_y.push_back(_position_base.y);
    }
}

四、延时修正处理,这里仍然看源码即可

观测传感器滞后的主要思想是,由于惯导的主体为加速度计,采样频率与更新实时性要求比较高,而观测传感器(气压计、GPS、超声波、视觉里程计等)更新相对比较慢(或者数据噪声比较大,通常需要低通造成滞后)。在无人机动态条件下,本次采样的得到的带滞后观测量(高度、水平位置)已经不能反映最新状态量(惯导位置),我们认定传感器在通带内的延时时间具有一致性(或者取有效带宽内的平均时延值),即当前观测量只能反映系统N*dt时刻前的状态,所以状态误差(在这里指的是气压计与惯导高度、GPS水平位置与惯导水平位置)采用当前观测量与当前惯导做差的方式不可取,在APM里面采用的处理方式为:将惯导的估计位置用数组存起来,更具气压计和GPS的滞后程度,选取合适的Buffer区与当前观测传感器得到位置做差得到状态误差。

// correct_with_baro - modifies accelerometer offsets using barometer.  dt is time since last baro reading
void AP_InertialNav::correct_with_baro(float baro_alt, float dt)
{
    static uint8_t first_reads = 0;
    static float store_old_alt[8] = {0,0,0,0,0,0,0,0};
    static uint8_t now_postion_count = 0;


    // discard samples where dt is too large
    if( dt > 0.5f ) {
        return;
    }


    // discard first 10 reads but perform some initialisation
    if( first_reads <= 10 ) {
        set_altitude(baro_alt);
        first_reads++;
    }


    // sanity check the baro position.  Relies on the main code calling Baro_Glitch::check_alt() immediatley after a baro update
    if (_baro_glitch.glitching()) {
        // failed sanity check so degrate position_error to 10% over 2 seconds (assumes 10hz update rate)
        _position_error.z *= 0.89715f;
    }else{
        // if our internal baro glitching flag (from previous iteration) is true we have just recovered from a glitch
        // reset the inertial nav alt to baro alt
        if (_flags.baro_glitching) {
            set_altitude(baro_alt);
            _position_error.z = 0.0f;
        }else{
            // 3rd order samples (i.e. position from baro) are delayed by 150ms (15 iterations at 100hz)
            // so we should calculate error using historical estimates
            float hist_position_base_z;
            if (_hist_position_estimate_z.is_full()) {
                hist_position_base_z = _hist_position_estimate_z.front();
            } else {
                hist_position_base_z = _position_base.z;
            }


           //**************************//
           _params.y = hist_position_base_z;


          //  hist_position_base_z = _position_base.z;


            // calculate error in position from baro with our estimate
            _position_error.z = baro_alt - (hist_position_base_z + _position_correction.z);
            //*************************************//
           /* _position_error.z = baro_alt - store_old_alt[now_postion_count];
            store_old_alt[now_postion_count] = hist_position_base_z + _position_correction.z;
            now_postion_count++;
            if (now_postion_count >= 4) now_postion_count = 0;*/
        }
    }


    // update our internal record of glitching flag so that we can notice a change
    _flags.baro_glitching = _baro_glitch.glitching();
}

// correct_with_gps - modifies accelerometer offsets using gps
void AP_InertialNav::correct_with_gps(uint32_t now, int32_t lon, int32_t lat)
{
    float dt,x,y;
    float hist_position_base_x, hist_position_base_y;


    // calculate time since last gps reading
    dt = (float)(now - _gps_last_update) * 0.001f;


    // update last gps update time
    _gps_last_update = now;


    // discard samples where dt is too large
    if( dt > 1.0f || dt == 0.0f || !_xy_enabled) {
        return;
    }


    // calculate distance from base location
    x = (float)(lat - _ahrs.get_home().lat) * LATLON_TO_CM;
    y = (float)(lon - _ahrs.get_home().lng) * _lon_to_cm_scaling;


    // sanity check the gps position.  Relies on the main code calling GPS_Glitch::check_position() immediatley after a GPS update
    if (_glitch_detector.glitching()) {
        // failed sanity check so degrate position_error to 10% over 2 seconds (assumes 5hz update rate)
        _position_error.x *= 0.7943f;
        _position_error.y *= 0.7943f;
    }else{
        // if our internal glitching flag (from previous iteration) is true we have just recovered from a glitch
        // reset the inertial nav position and velocity to gps values
        if (_flags.gps_glitching) {
            set_position_xy(x,y);
            _position_error.x = 0.0f;
            _position_error.y = 0.0f;
        }else{
            // ublox gps positions are delayed by 400ms
            // we store historical position at 10hz so 4 iterations ago
            if( _hist_position_estimate_x.is_full()) {
                hist_position_base_x = _hist_position_estimate_x.front();
                hist_position_base_y = _hist_position_estimate_y.front();
            }else{
                hist_position_base_x = _position_base.x;
                hist_position_base_y = _position_base.y;
            }


            // calculate error in position from gps with our historical estimate
            _position_error.x = x - (hist_position_base_x + _position_correction.x);
            _position_error.y = y - (hist_position_base_y + _position_correction.y);
        }
    }


    // update our internal record of glitching flag so that we can notice a change
    _flags.gps_glitching = _glitch_detector.glitching();
}

很明显可以发现:

// ublox gps positions are delayed by 400ms

// 3rd order samples (i.e. position from baro) are delayed by 150ms (15 iterations at 100hz)
 // so we should calculate error using historical estimates

关于是否使用,延时修正数据波形对比间上篇博客,链接如下:

四旋翼惯导融合之观测传感器滞后问题汇总与巴特沃斯低通滤波器设计(气压计MS5611、GPS模块M8N、超声波、PX4FLOW等)

下面给出个人飞控参考这部分的代码:

#define TIME_CONTANST_XY      2.5f
#define K_ACC_XY     (1.0f / (TIME_CONTANST_XY * TIME_CONTANST_XY * TIME_CONTANST_XY))
#define K_VEL_XY             (3.0f / (TIME_CONTANST_XY * TIME_CONTANST_XY))
#define K_POS_XY             (3.0f / TIME_CONTANST_XY)
float X_Delta=0,Y_Delta=0;
uint16_t GPS_Save_Period_Cnt=0;
uint16_t GPS_SINS_Delay_Cnt=4;//200ms
Testime SINS_Horizontal_Delta;
void Strapdown_INS_Horizontal()
{
      uint16 Cnt=0;
      GPSData_Sort();//获取相对home的水平偏移
      GPS_Save_Period_Cnt++;
      if(GPS_Save_Period_Cnt>=10)//50ms
      {
            for(Cnt=Num-1;Cnt>0;Cnt--)//100ms滑动一次
            {
              NamelessQuad.Pos_History[_PITCH][Cnt]=NamelessQuad.Pos_History[_PITCH][Cnt-1];
              NamelessQuad.Pos_History[_ROLL][Cnt]=NamelessQuad.Pos_History[_ROLL][Cnt-1];
            }
              NamelessQuad.Pos_History[_PITCH][0]=NamelessQuad.Position[_PITCH];
              NamelessQuad.Pos_History[_ROLL][0]=NamelessQuad.Position[_ROLL];
              GPS_Save_Period_Cnt=0;
      }


      //GPS导航坐标系下,正北、正东方向位置偏移与SINS估计量的差,单位cm
      X_Delta=Earth_Frame_To_XYZ.E-NamelessQuad.Pos_History[_PITCH][GPS_SINS_Delay_Cnt];
      Y_Delta=Earth_Frame_To_XYZ.N-NamelessQuad.Pos_History[_ROLL][GPS_SINS_Delay_Cnt];


      acc_correction[_PITCH] += X_Delta* K_ACC_XY*CNTLCYCLE;//加速度矫正量
      acc_correction[_ROLL] += Y_Delta* K_ACC_XY*CNTLCYCLE;//加速度矫正量


      vel_correction[_PITCH] += X_Delta* K_VEL_XY*CNTLCYCLE;//速度矫正量
      vel_correction[_ROLL] += Y_Delta* K_VEL_XY*CNTLCYCLE;//速度矫正量


      pos_correction[_PITCH] += X_Delta* K_POS_XY*CNTLCYCLE;//位置矫正量
      pos_correction[_ROLL] += Y_Delta* K_POS_XY*CNTLCYCLE;//位置矫正量


      /*************************************************************/
      //水平运动加速度计校正
      NamelessQuad.Acceleration[_PITCH]=Origion_NamelessQuad.Acceleration[_PITCH]+acc_correction[_PITCH];
      //速度增量矫正后更新,用于更新位置
      SpeedDealt[_PITCH]=NamelessQuad.Acceleration[_PITCH]*CNTLCYCLE;
      //原始位置更新
      Origion_NamelessQuad.Position[_PITCH]+=(NamelessQuad.Speed[_PITCH]+0.5*SpeedDealt[_PITCH])*CNTLCYCLE;
      //位置矫正后更新
      NamelessQuad.Position[_PITCH]=Origion_NamelessQuad.Position[_PITCH]+pos_correction[_PITCH];
      //原始速度更新
      Origion_NamelessQuad.Speed[_PITCH]+=SpeedDealt[_PITCH];
      //速度矫正后更新
      NamelessQuad.Speed[_PITCH]=Origion_NamelessQuad.Speed[_PITCH]+vel_correction[_PITCH];


      /*************************************************************/
      //水平运动加速度计校正
      NamelessQuad.Acceleration[_ROLL]=Origion_NamelessQuad.Acceleration[_ROLL]+acc_correction[_ROLL];
      //速度增量矫正后更新,用于更新位置
      SpeedDealt[_ROLL]=NamelessQuad.Acceleration[_ROLL]*CNTLCYCLE;
      //原始位置更新
      Origion_NamelessQuad.Position[_ROLL]+=(NamelessQuad.Speed[_ROLL]+0.5*SpeedDealt[_ROLL])*CNTLCYCLE;
      //位置矫正后更新
      NamelessQuad.Position[_ROLL]=Origion_NamelessQuad.Position[_ROLL]+pos_correction[_ROLL];
      //原始速度更新
      Origion_NamelessQuad.Speed[_ROLL]+=SpeedDealt[_ROLL];
      //速度矫正后更新
      NamelessQuad.Speed[_ROLL]=Origion_NamelessQuad.Speed[_ROLL]+vel_correction[_ROLL];
}






void Strapdown_INS_Reset(SINS *Ins,uint8_t Axis,float Pos_Target,float Vel_Target)
{
      uint16_t Cnt=0;
      Ins->Position[Axis]=Pos_Target;//位置重置
      Ins->Speed[Axis]=Vel_Target;//速度重置
      Ins->Acceleration[Axis]=0.0f;//加速度清零
      Ins->Acce_Bias[Axis]=0.0f;
      for(Cnt=Num-1;Cnt>0;Cnt--)//历史位置值,全部装载为当前观测值
      {
         Ins->Pos_History[Axis][Cnt]=Pos_Target;
      }
         Ins->Pos_History[Axis][0]=Pos_Target;
      for(Cnt=Num-1;Cnt>0;Cnt--)//历史速度值,全部装载为当前观测值
      {
         Ins->Vel_History[Axis][Cnt]=Vel_Target;
      }
         Ins->Vel_History[Axis][0]=Vel_Target;
      pos_correction[Axis]=0;//清空惯导融合量
      acc_correction[Axis]=0;
      vel_correction[Axis]=0;
}



个人飞控开源前测试视频,总共有三个:

个人飞控开源前综合测试


个人飞控开源前测试(定钉子)



个人飞控开源前测试(大风定点)



博客会陆续更新,个人主页有联系方式,欢迎大家一起交流,共同进步!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从APM源码分析GPS、气压计惯导融合 的相关文章

  • 位置侦听器从服务工作,但不是 IntentService

    我有一个应用程序 我试图定期获取用户位置并将其发送到服务器 我有一项服务附加到AlarmManager每分钟执行一次 用于测试 该服务正确找到用户位置并注销 GPS 坐标 一旦出现 GPS 锁定 我就会取消位置请求并停止服务 当我请求位置更
  • 信号好的情况下GPS更新间隔越快?

    我试图限制我的程序每 10 秒更新一次位置 而不是不断更新 以减少电池消耗 当我在室内调试且信号较弱 即 GPS 图标闪烁 时 此方法工作正常 但如果手机得到正确修复 即 GPS 图标静态 更新间隔会增加到大约一秒 我知道代码mLocati
  • C#:GPS跟踪系统[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 如何在 C net 中构建带有移动设备 带 GPS 的 GPS 跟踪系统 场景是 通过支持 GPS 的手机跟踪用户 服务工程师 这里没
  • 如何在 Android 中找到附近的应用程序用户?

    我正在制作一个应用程序 需要能够找到附近的人 他们是我的应用程序的用户 我看了很多类似问题的答案 似乎我别无选择 只能不断将用户的当前位置上传到服务器 并在必要时获取附近的用户列表 那么我的问题是 1 要获取附近的列表 应该有一些计算距离的
  • 在带有校准点的地图上将经度和纬度转换为 X Y

    如果我有一张尺寸为 sizeX sizeY 的 jpeg 地图 以及地图上的一些校准点 X Y 经度 纬度 使用给定的经度 纬度对计算地图中相应 XY 点的算法是什么 这对我有用 没有那么多废话 int x int MAP WIDTH 36
  • Java中的多点三边测量算法

    我正在尝试在我的 Android 应用程序中实现三边测量算法来确定用户的室内位置 我正在使用超宽带信标来获取到固定点的距离 我能够采用中建议的方法三边测量法 Android Java https stackoverflow com ques
  • 我如何从 JMapViewer 世界地图中获取鼠标单击位置

    我正在使用地图浏览器 http wiki openstreetmap org wiki JMapViewerjar 在 JPanel 上显示世界地图 在地图上我添加MapMarkerDot s这是 GPS 点 问题是当我单击MapMarke
  • 使用 LocationManager 时,为什么打开 Wifi 但未连接有助于网络定位?

    这可能是偏离主题的 如果是这样 我道歉 并很高兴接受关闭标志 但我在弄清楚为什么 WIFI 打开但未连接到任何接入点 在我的 Android 设备上 时遇到问题 它vastly提高网络提供商使用时的准确性LocationManager 如果
  • React Native Android 位置请求超时

    在 IOS 中查找 GPS 坐标时没有问题 效果很好 Android 端不如 IOS 稳定 在真机和模拟器中都会出现这个问题 有时它可以找到位置 但有时却找不到 寻找了3天 但没有找到解决方案 当我的应用程序无法找到我的位置时 我尝试通过谷
  • Android 中如何在不使用 getLastKnownLocation 方法的情况下获取当前的纬度和经度?

    我正在尝试获取current手机的位置 为此我使用GPS追踪器教程 http www androidhive info 2012 07 android gps location manager tutorial 问题总是使用该方法getLa
  • 从 GPS 点绘制线

    我有大约 100 个 GPS 坐标列表 我想画出每个列表所构成的线 使用散点图绘制的列表之一 看起来有点像这样 显然那里有一条线 我尝试了几种方法来对 GPS 位置进行排序并绘制它们 lats lngs with open filename
  • 在没有互联网的情况下使用 Javascript 获取 GPS 位置 [重复]

    这个问题在这里已经有答案了 您好 如果设备具有 GPS 硬件 我们可以在没有互联网连接的情况下使用 JavaScript 获取 GPS 位置吗 请注意谁将其标记为重复 我需要 JavaScript 在没有互联网连接的情况下工作 并使用 GP
  • 如何知道jar文件是否已经在运行?

    经过谷歌研究后 我找到了很好的答案 例如 1 using jps or jps l让 jars 在 JVM 下运行 这个答案可以 但是如果用户根本没有安装java并且我使用例如 bat文件和带有java JRE的文件夹运行我的jar 另外
  • Android 查找 GPS 位置一次,显示加载对话框

    我正在编写一个应用程序 它需要用户的当前位置 lastknownlocation 不会很有帮助 并显示从数据库中获取的所有最接近的 项目 的列表 我已经找到了最近的项目 效果很好 但暂时只使用硬编码的纬度和经度位置 但现在是时候实现查找实际
  • 使用 Google 电子表格中的脚本从手机获取我的当前位置

    有没有办法使用 Google Apps 脚本从手机的 GPS 数据中获取我的当前位置 纬度和经度 最好是十进制形式 另外 是否可以打开和关闭 GPS 或者至少检测它是否打开或关闭 这是我尝试做的 我带着电动助力车去一些地方 在每个地方我都会
  • 当我的活动结束时,如何停止 GPS/位置跟踪?

    我有一个非常简单的 Android 应用程序 它显示 Google 地图视图并使用 GPS 跟踪位置 基本上像这样 public void onCreate Bundle savedInstanceState mLocationManage
  • 在android API 23中获取用户的位置

    我可以编写获取用户位置的代码 并且在 API 更多细节 我手动启用设备的 GPS 第一次运行应用程序请求权限并且没有日志返回 在下次运行应用程序时 返回我准备好的 Toast 检查您的提供商 这是我写的代码 public class Mai
  • Android:CellID 不适用于所有运营商?

    当我请求 Cell ID 和 LAC 信息时 在某些设备上我无法检索它们 我使用这段代码 TelephonyManager tm TelephonyManager getSystemService Context TELEPHONY SER
  • GPSTracker 类不工作

    我尝试在我的应用程序中使用我在网上找到的 GPSTracker 类 并且我之前让它工作过 但现在似乎莫名其妙地不起作用 public class GPSTracker extends Service implements LocationL
  • 当我们在Android中通过GPS获取位置时,如何获取卫星名称或号码?

    我是android新手 我通过gps获取位置 我还在我们的代码中获取卫星号码 但我想获取用于获取位置的特定卫星名称或号码 我有很多谷歌 但没有得到适当的解决方案 我的问题是 1 It is possible to get a particu

随机推荐

  • ROS学习(22)TF变换

    文章目录 前言一 TF功能包二 TF工具1 tf monitor2 tf echo3 static transform publisher4 view frames 三 乌龟例程中的TF四 乌龟跟随例程代码实现1 创建TF广播器2 创建TF
  • C# winform 窗体缩放问题处理

    一 问题 xff1a 本身窗体在设计器显示没有问题 xff0c 但运行时窗口却被缩放失真 xff1a 二 解决方法 xff1a 修改项目的配置文件 xff0c 使项目运行时自动检测屏幕分辨率 xff0c 在高分辨率屏幕禁用系统缩放 xff0
  • strlen与sizeof计算char* 与char数组

    sizeof 可以计算所有类型 xff0c strlen 仅计算字符串 xff0c 至于这二者的详细区别可以看其他文章 char a char b 5 sizeof a 61 8 64位系统 xff0c 8代表的是指针的大小 xff0c 指
  • MySQL的not null default

    建表语句每行末尾的NOT NULL DEFAUTL 含义 该句的含义是 xff0c 该字段不能为null xff0c 并且设置如果插入数据的时候不设置该字段的值的时候使用的默认值 insert操作且不给该字段插值的时候 xff0c 数据库判
  • eclipse 中 中文字符变小的解决方法

    前言 xff1a 装了新版的eclipse后发现 英文代码部分正常 xff0c 但是但凡有中文的地方中文字符变小了 xff0c 若调整字体大小 xff0c 英文就更大了 xff0c 总归中英文大小不一致 推荐解决方法 xff1a 打开 ec
  • LINUX/AIX下文本DOS格式与UNIX格式互转

    LINUX AIX下文本DOS格式与UNIX格式互转 一 文本换行符简介 n 换行 newline LF LineFeed 0x0D r 回车 return CR CarrageReturn 0x0A windows dos r n uni
  • STM32F103用hal库使用DMA+串口空闲中断接收数据

    简介 xff1a 出现空闲标志时 xff0c 认为一帧报文发送完毕 xff0c 进行报文分析 xff0c 比普通的串口中断效率高很多 xff01 用到的工具 xff1a CubeMX xff0c Keil5 芯片 xff1a STM32F1
  • AIX页面空间管理

    一 页面空间相关概念及设计规则 系统中的物理内存是非常有限的 xff0c 因此大多数OS都采用了虚拟内存技术 在AIX系统中也使用分页的存储方式管理存储器 xff0c 并将虚拟内存称为页面空间 Paging space 页面空间 xff1a
  • C/C++中的double类型四舍五入

    一 前言 最近 xff0c 项目中需要对金额进行四舍五入运算 本身系统中全部使用长整型 long or long long xff0c 数据库中使用decimal xff0c 从而防止double类型的精度缺失情况以及数据库中小数点后几位的
  • CAS实现SSO单点登录-CAS Server搭建

    最近公司连续接了三四个单点登录集成的项目 xff0c 由我们公司提供CAS Server端的 xff0c 也有需要我们把Client与其他公司提供的Server端对接的 xff0c 我负责把我们公司的一个Client与另外一个公司提供的Se
  • 从高考到程序员:我的程序探险之旅

    就在今天下午 xff0c 湖南省教育考试院公布了 2017 年湖南省普通高等学校招生全国统一考试的卷面成绩 xff0c 我的微信也瞬间被各种分段统计表和喜报刷屏 xff0c 每年的这个时候总是几家欢喜几家愁 六年前的 6 月 25 日 xf
  • MatconvNet+VS2015+Matlab2018a+CUDA9+cudnn7:在matlab上搞深度学习,安装环境时遇到的大坑!

    事情发生的背景 作为刚入职的深度学习实习生 xff0c 入职第一天 xff0c 我领完电脑 xff0c 刚装完电脑 xff0c 分配好公司的ip xff0c 连chrome都还没来得及安装 xff0c 就接到任务 xff0c 需要实现给定的
  • CAS学习(一) 编译支持REST认证的cas6.2服务端并配置部署测试

    CAS 是 Yale 大学发起的一个开源项目 xff0c 旨在为 Web 应用系统提供一种可靠的单点登录方法 xff0c CAS 在 2004 年 12 月正式成为 JA SIG 的一个项目 CAS 具有以下特点 xff1a 1 开源的企业
  • QEMU

    QEMU 1 使用QEMU创建虚拟机 一 QEMU简介 QEMU是一款开源的模拟器及虚拟机监管器 Virtual Machine Monitor VMM QEMU主要提供两种功能给用户使用 一是作为用户态模拟器 xff0c 利用动态代码翻译
  • 使用virt-install手动创建qcow2镜像并安装ISO

    virt install是一个使用libvirt库构建新虚拟机的命令行工具 xff0c 此工具使用串行控制台 xff0c SDL xff08 Simple DirectMedia Layer xff09 图形或者VNC客户端 服务器 xff
  • OVN总结

    参考 xff1a https www sdnlab com 18600 html 三 OVN L3 对比 Neutron L3 Neutron 的三层功能主要有路由 xff0c SNAT 和 Floating IP xff08 也叫 DNA
  • Keil MDK5 打开MDK4项目

    安装完最新版本keil 5 38a 后 xff0c 需要打开几个MDK4的项目 xff0c 结果一打开keil就提示报错了 这里我选择的是第二种方式 xff0c 首先安装legacy support xff0c 以下是下载链接 MDK v4
  • ubuntu18.04换源及E: 仓库 “http://ppa.launchpad.net/v-launchpad-jochen-sprickerhof-de/pcl/ubuntu bionic Re

    ubuntu18 04换源E 仓库 http ppa launchpad net v launchpad jochen sprickerhof de pcl ubuntu bionic Re问题 1 备份2 修改源3 更新4 解决E 仓库
  • 图像分割2020总结:结构,损失函数,数据集和框架

    点击上方 AI公园 xff0c 关注公众号 xff0c 选择加 星标 或 置顶 作者 xff1a Derrick Mwiti 编译 xff1a ronghuaiyang 导读 一个很好的入门小短文 xff0c 内容很全 xff0c 适合上手
  • 从APM源码分析GPS、气压计惯导融合

    最近事多 xff0c 忙着开源自研飞控 xff0c 现主要工作基本已经完成 xff0c 代码最迟下月中旬开放 xff0c 博客来不及更新 xff0c 还请各位见谅 xff0c 后面会抽空多更的咯 xff01 xff01 xff01 自研飞控