从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、气压计惯导融合 的相关文章

  • 如何在android中离线获取纬度和经度?

    我想在 WiFi 和 Gps 关闭时获取当前位置 纬度和经度 可以从移动 SIM 网络获取纬度和经度 我在谷歌上搜索了更多 但没有得到满意的答案 从我昨天的经验来看question https stackoverflow com q 220
  • 动态更改 GPS LocationListener 的 minTime

    我正在编写的应用程序使用 GPS 位置管理器服务 requestLocationUpdates 但我希望能够更改整个程序中的最小时间和最小距离参数 我在创建时初始化位置侦听器 但我不知道如何更改这些参数 甚至不知道是否可以这样做 这样做的主
  • GPS/GIS 计算:根据运动/每小时预测未来位置的算法?

    寻找资源或算法来在导航应用程序中计算以下内容 如果我当前的 GPS 位置为 0 0 并且我以 15 英里 小时的速度前进 32 度 我如何计算 10 秒后我的位置 i e GPSCoordinate predictedCoord GPSCo
  • 信号好的情况下GPS更新间隔越快?

    我试图限制我的程序每 10 秒更新一次位置 而不是不断更新 以减少电池消耗 当我在室内调试且信号较弱 即 GPS 图标闪烁 时 此方法工作正常 但如果手机得到正确修复 即 GPS 图标静态 更新间隔会增加到大约一秒 我知道代码mLocati
  • 如何在 Android 中找到附近的应用程序用户?

    我正在制作一个应用程序 需要能够找到附近的人 他们是我的应用程序的用户 我看了很多类似问题的答案 似乎我别无选择 只能不断将用户的当前位置上传到服务器 并在必要时获取附近的用户列表 那么我的问题是 1 要获取附近的列表 应该有一些计算距离的
  • 如何确定当前用户位置是否在我的 MKCooperativeRegion 内?

    我有一个坐标区域 我已确定该区域包含我想要为我的应用程序显示的内容的限制 我已将其设置为具有中心点纬度 经度和跨度的 MKCooperativeRegion 如何确定当前 userLocation 是否在我的坐标区域内 使用地图矩形 这是使
  • GMSPolyline 非常大的内存峰值

    在允许用户在各种不同类型的地图上显示我们称之为轨迹的复杂位置点列表的 GPS 应用程序中 每个轨迹可以包含 2k 到 10k 个位置点 当轨迹在非 Google 地图类型上呈现时 它们会被大量剪切 修剪和路径简化 这是为了降低内存使用量并提
  • Android 中如何在不使用 getLastKnownLocation 方法的情况下获取当前的纬度和经度?

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

    我的清单中有以下内容
  • 在不改变我的位置的情况下获取当前位置的经度和纬度

    我可以找到当前位置的纬度和经度 但是这些数据在更改我的当前位置之前不会显示 我想在不更改我的位置的情况下获取当前位置的经度和纬度 package com example gps import android app Activity imp
  • 使用纬度/经度计算从 A 点到线段的距离

    我正在开发一个使用 GPS 的 Android 应用程序 我想知道如果 新位置 C 点 距离线段 AB 太远 是否有办法可以丢弃 GPS 位置数据 我正在使用发现的点到线段公式在维基百科上 http en wikipedia org wik
  • GPS 坐标(以度为单位)来计算距离

    在iPhone上 我以十进制度数获取用户的位置 例如 纬度39 470920和经度 0 373192 也就是A点 我需要用另一个 GPS 坐标 同样以十进制表示 B 点创建一条线 然后 计算从 A 到 B 的线与另一个点 C 之间的距离 垂
  • 检测wifi是否启用(无论是否连接)

    对于 GPS 跟踪应用程序来说 在打开 WIFI 的情况下记录位置信号会导致数据非常不精确或存在间隙 在开始跟踪之前 我已使用可达性查询来检测 wifi 是否可用 问题是 如果进行该查询时 wifi 已启用但未连接到网络 则表明无法通过 w
  • 向 tk103 GPS 跟踪器发送命令

    我正在使用 php 开发实时 GPS 跟踪器 Web 应用程序 跟踪器参考号是tk103 我可以从跟踪器接收信息并将其存储到数据库中 设备的 GPRS 模式已启用 我的问题是 如何使用 php ini 将命令从服务器发送到设备 提前致谢 这
  • 关闭应用程序后如何调试

    我正在尝试重现问题 这需要在特定位置关闭并重新打开我的应用程序 这是我的问题 1 如何查看我的日志 使用NSLog命令 当我的 iPhone 未连接到 XCode 时 2 是否可以将iPhone模拟器的特定位置 例如市中心 设置为默认位置
  • python:查找围绕某个 GPS 位置的圆的 GPS 坐标的优雅方法

    我有一组以十进制表示的 GPS 坐标 并且我正在寻找一种方法来查找每个位置周围半径可变的圆中的坐标 这是一个例子 http green and energy com downloads test circle html我需要什么 这是一个圆
  • 如何在从另一个活动调用一个活动时延迟一些?

    我有一个应用程序 其中我正在接收包含他的位置的短信 收到短信后 它会调用另一个活动来启动并将该位置传递给该活动以将其绘制在地图上 在调用第二个活动之前 它会显示一个类似于通知的吐司在屏幕上 但由于调用第二个活动 吐司没有出现 我的问题是我们
  • 我可以使用手机信号塔的信息在没有 GPS 服务的 j2me 中获取移动设备的位置吗

    我可以通过 j2me 编程获取未安装 GPS 装置的移动设备的位置吗 我可以使用手机信号塔信息获取位置吗 我听说过三角测量 https stackoverflow com a 9820133 839601 method 并且经历了http
  • 以编程方式激活 GPS

    我的应用程序需要打开 GPS 有什么方法可以检查 GPS 当前是否启用 如果没有 那么如何启用 我使用的是安卓2 3 Android 不允许你这样做 您能做的最好的事情就是检查 GPS 是否已启用 如果未启用 请要求用户激活它 您可以在此处
  • .isProviderEnabled(LocationManager.NETWORK_PROVIDER) 在 Android 中始终为 true

    我不知道为什么 但我的变量isNetowrkEnabled总是返回 true 我的设备上是否启用互联网并不重要 这是我的GPSTracker class public class GPSTracker extends Service imp

随机推荐

  • Spring注解

    注解介绍 注解有两个作用 xff1a 标注和注入 标注 xff1a 类路径下自动扫描 xff0c 减少在xml中配置bean 例如 64 Component 64 Service注入 xff1a 自动装配 xff0c 需要类的地方直接加注解
  • akka基础

    基本概念消息传递API 通用API消息传递方式 Future机制Actor生命周期处理状态和错误 监督kill actor生命周期监控和DeathWatch安全重启状态 纵向扩展 Router调度方式使用策略 横向扩展 订阅集群事件启动 退
  • Ubuntu使用root登录系统界面、免密码、添加开机启动

    以下测试环境为Ubuntu 16 04 一 使用root登录系统界面 Ubuntu在命令行模式下 xff0c 是可以登录root的 为了安全 xff0c 在图形界面模式下 xff0c 默认不允许使用root登录系统 可以通过修改50 uni
  • 线程(Thread)的三种等待唤醒机制详解

    1 为什么需要线程的等待和唤醒 线程的等待唤醒机制是一种经典的 生产者和消费者 模型 例如食品加工厂 xff0c 食品加工人员和原料补给人员 xff0c 在有充足原料时 xff0c 补给人员是在等待 xff0c 等到原料不够时 xff0c
  • Linux常用终端命令之cat、grep、echo

    这三个指令 xff0c 每一个都很常用 xff0c 用法也都很多 作为一个linux初学者 xff0c 我还不能很好的掌握三个命令的用法 xff0c 于是先在这篇博客里做一个简单的整理和总结 xff0c 以加深对三个指令的理解 grep 先
  • Python+Pycharm使用opencv

    http blog csdn net whykifan article details 66478421 在这个配置过程中 xff0c 遇到了不少的问题 xff0c 于是就写了这篇博文 xff0c 希望可以帮到遇到相同问题的人 主要步骤 x
  • Linux启动流程rcN.d rcS.d rc.local等

    1 环境 当前系统环境为 xff1a Linux mint mate 17 1 基于ubuntu14 04的衍生版 备注 xff1a etc rc d文件夹中的脚本文件的链接目标为 xff1a etc init d文件夹下的脚本 为系统运行
  • Ubuntu 启用root账户并开启远程登录

    生产环境尽量不要如下操作 生产环境尽量不要如下操作 生产环境尽量不要如下操作 本地虚拟机 xff0c 为了方便 xff0c 直接root远程登录 Ubuntu 20 4 1 启用root账户 sudo passwd root 2 开启远程登
  • datatable中报错 table.XXX is not a function的解决方法

    在datatable中可以通过三种不同的方式为一个或多个表获取一个新的Datatables API实例 xff1a xff08 1 xff09 selector DataTable xff08 2 xff09 selector dataTa
  • 在ubuntu下安装libpcap库

    这两天公司里要我了解一下pcap xff0c 但是还不知道它是干什么的 首先 xff0c 我从网上查到了 xff0c pcap实际上是抓包库 这个抓包库给抓包系统提供了一个高层次的接口 所有网络上的数据包 xff0c 甚至是那些发送给其他主
  • Python 获取当前路径(文件及所在文件夹,正斜线)

    参考博客 xff1a http www cnblogs com wind wang p 5822192 html 更多路径读取请参照上述博客 xff08 使用Python 2 x版本 xff09 xff0c 这里只挑出个人认为最直接 常用的
  • 基于docker搭建mysql,redis,mongo,gitlab,wiki等开发环境

    今天基于docker搭建一整套开发环境 首先安装docker yum y install docker io 使用加速器 xff1a vim etc docker daemon json 添加163的加速地址 xff1a 34 regist
  • Android编译系统分析五:system.img的生成过程

    Android编译系统分析系列文章 xff1a android编译系统分析 xff08 一 xff09 source build envsetup sh与lunch Android编译系统 xff08 二 xff09 mm编译单个模块 an
  • linux学习笔记--Xshell远程登陆linux

    1 登录xshell官网XSHELL NetSarang Website xff0c 输入姓名和邮箱 xff0c 下载免费版的Xshell xff0c 下载链接会发送到邮箱中 下载完成后直接安装即可 2 双击打开安装完成的Xshell xf
  • Apache使用localhost可以访问但使用本机IP(局域网)不能访问

    Apache使用localhost可以访问但使用本机IP 局域网 不能访问 Apache 使用localhost 127 0 0 1 可以访问 xff0c 使用本机IP 局域网 不能访问 xff0c 为什么本机ip地址不能访问localho
  • ubuntu14.04LTS命令行安装xfce4桌面

    安装ubuntu14 04LTS后 xff0c 需要一个桌面 xff0c 因此选择安装xfce4 1 安装 1 1 安装默认版本4 10 sudo apt get install xfce4 1 2 安装版本4 12 1 sudo add
  • OCLint的部分规则(Convention 部分)

    OCLint的部分规则 xff08 Convention 部分 xff09 对OCLint的部分规则进行简单翻译解释 xff0c 有部分进行了验证以及进一步分析 测试 OCLint其他相关内容如下 xff1a OCLint iOS OC项目
  • 修改virualbox下的虚拟系统Ubuntu的内存

    VBoxManage exe在VirtualBox 安装目录下 xff0c 如下图 xff0c 我们进VirtualBox 安装目录查看到VBoxManage exe 要使用这个工具 xff0c 就先了解一下这个工具吧 xff0c 要用命令
  • 四旋翼定高篇之惯导加速度+速度+位置三阶互补融合方案

    笔者最近正在做四旋翼惯性导航的部分 xff0c 利用加速度计进行速度估计 位置估计 xff0c 从而实现四旋翼的垂直方向上的定高 水平方向上的定点控制 首先在这里引用学长之前参考APM飞控里面互补滤波惯导融合方案 xff1a 原文见四旋翼位
  • 从APM源码分析GPS、气压计惯导融合

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