logo头像
Snippet 博客主题

遇到的坑

2019\02\12

  1. 切换分支后,./waf 编译出来报错–上一个分支的头文件在这边没有,就报编译错误。

    解决方法:
    配置(configure): 配置工程,找到依赖项的位置
    编译(build): 将源文件转换为生成文件
    清理(clean): 删除生成文件
    用 ./waf clean 删除生成文件即可。

  2. gitlab.mmc.com 不能访问但是192.168.4.85能访问。

    解决方法:
    hosts 里面的映射没通,加了几个回车,重启电脑即可。

  3. 源文件更新子目录时候有部分子目录由于翻墙软件导致端口不能访问。

    解决方法:
    关掉网络设置中的翻墙代理,重启即可。

  4. 无论怎么配平 PWM输出曲线还是不行,最后导致有个水平速度时候下降则航向锁不住。

    解决方法:
    机臂能转动或是松动情况直接导致PWM输出曲线
    把机肚子上的6个卡扣全部换掉即可。
    2019年2月14日把悬停油门设为0.4即可解决后拉下降时候油门触底导致的航向控不住的问题。

  5. C++ 报错 invalid types ‘float [7][float]’ for array subscript
    FilterSamples[currentFilterSampleIndex] = newdistanceReading;

    解决方法:
    数组中的变量不能为float型,应该为int型。

  1. 罗盘2 噪点过大导致校准从第二步直接跳为第一步,明天注意查找_fit_step的含义。打出曲线看看。
  1. 自己拉APM仓时遇到的坑。

    1. 如何只拉一个分支下来并且去掉tags?
      先建一个仓和远端关联,再关联一个git remote upstream 接着fetch下来,然后删掉upstream,然后用此命令删除标签tags: git tag | xargs -I {} git tag -d {}
      如何加tags:git tag Copter-3.6.6 链接:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/001376951758572072ce1dc172b4178b910d31bc7521ee4000
  2. 出现loit模式推杆没反应情况。
    发现把那个会侧翻的bug解决后,又出现这个改回去后就行了。为啥会这样,后续再研究。

  3. APM装毫米波雷达定高时,需要修改的参数:

    EK2_RNG_USE_HGT 50 RNGFND2_TYPE 21 RNGFND_MAX_CM 2000 RNGFND_MIN_CM 60 RNGFND_TYPE 21
    SERIAL4_BAUD 57 SERIAL4_PROTOCOL 9 EK2_ALT_SOURCE 1

  4. 安装ubuntu16.04遇到的坑

    分盘: 分你的ram大小的swap: 16G主分区 分512M的/boot 非主分区 其余全部给/
    安装时候最好是联网安装而且把需要下载的MP3那部分也点着下载,不然之后会折腾很久。比如登录不进去,再比如显示的很多问题。
    千万不要卸载ubuntu下的Python3.5,卸载了之后会把所有的应用都卸载掉。
    选镜像aliyun 不然下载很慢

  5. px4io start failed 的原因以及解决方法。
    由于小io起不来,让晶振48M起振,或者删掉能让其卡死的地方。

  6. eclipse 的编译仿真环境搭建。

  7. 由于参数太大会导致高度降不下来的原因是我们自主学习了油门的值,会突然变得很大。

  8. 安装ubuntu18.04 遇到的坑,在没有分/home,只分了swap、/boot、/ 时,不能自动安装ubuntu软件。导致选择nvidia 390显卡会导致突然关机。

    现在分了swap、/boot、/、/home 这四个,且/sur(文件安装盘)在/里面,然后再更新软件,再自动安装ubuntu软件 sudo ubuntu-drivers
    autoinstall 执行完这一切然后重启你会发现,已经自动选上了nvidia 390 驱动。完毕。

  • 然而此部分又进行重启,按照上面处理不行。故又开始折腾,使用Xorg进入系统总是不到5s就死机,但是通过Wayland启动就不会,现在在Wayland里更新了nvidia官方推荐的驱动,自己手动安装没毛病,不要用ubuntu系统推荐的nvidia驱动,选这个就会自动关机。
  1. 总是报错“No IO Thread Heartbeat write”

    只要超过5s没进入_io_timer(); 就会报这个错误,报这个错误有几种可能1. 这个值 _write_fd 长时间为-1 或者_initialised没初始化 或者 _open_error = 1 再或者 _writebuf.available() = 0;

  • 为什么_write_fd = -1 ?

  • 什么情况_initialised = 0; 未初始化?

最终得出结论为SD卡格式化为FAT16就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL || CONFIG_HAL_BOARD == HAL_BOARD_LINUX
void DataFlash_File::flush(void)
#if APM_BUILD_TYPE(APM_BUILD_Replay) || APM_BUILD_TYPE(APM_BUILD_UNKNOWN)
{
uint32_t tnow = AP_HAL::millis();
while (_write_fd != -1 && _initialised && !_open_error && _writebuf.available()) {
// convince the IO timer that it really is OK to write out
// less than _writebuf_chunk bytes:
if (tnow > 2001) { // avoid resetting _last_write_time to 0
_last_write_time = tnow - 2001;
}
_io_timer();
}
if (write_fd_semaphore->take(1)) {
if (_write_fd != -1) {
::fsync(_write_fd);
}
write_fd_semaphore->give();
} else {
_internal_errors++;
}
}
#else
{
// flush is for replay and examples only
}
#endif // APM_BUILD_TYPE(APM_BUILD_Replay) || APM_BUILD_TYPE(APM_BUILD_UNKNOWN)
#endif
  1. 为什么悬停油门值会突然给很大?

    此时AP_MOTORS_THST_HOVER_MIN = 0.125 AP_MOTORS_THST_HOVER_MAX = 0.6875f AP_MOTORS_THST_HOVER_TC = 10。此时判断所有的上升从get_throttle()里获得高值。然而此时的油门值只是通过摇杆油门输入,中间会不会有什么影响到这个值了?

1
_throttle_hover = constrain_float(_throttle_hover + (dt/(dt+AP_MOTORS_THST_HOVER_TC))*(get_throttle()-_throttle_hover), AP_MOTORS_THST_HOVER_MIN, AP_MOTORS_THST_HOVER_MAX);

发现中间由于开了个_angle_boost_enabled (此部分为有倾角时飞机进行油门补偿),我发现这部分完全为鸡肋,在平常有倾角时候倒没有进行补偿,在激烈晃动时候才补偿,导致失控时候。此部分为鸡肋故可以先去掉此值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// returns a throttle including compensation for roll/pitch angle
// throttle value should be 0 ~ 1
float AC_AttitudeControl_Multi::get_throttle_boosted(float throttle_in)
{
if (!_angle_boost_enabled) {
_angle_boost = 0;
return throttle_in;
}
// inverted_factor is 1 for tilt angles below 60 degrees
// inverted_factor reduces from 1 to 0 for tilt angles between 60 and 90 degrees

float cos_tilt = _ahrs.cos_pitch() * _ahrs.cos_roll();
float inverted_factor = constrain_float(2.0f*cos_tilt, 0.0f, 1.0f);
float boost_factor = 1.0f/constrain_float(cos_tilt, 0.5f, 1.0f);

float throttle_out = throttle_in*inverted_factor*boost_factor;
_angle_boost = constrain_float(throttle_out - throttle_in,-1.0f,1.0f);
return throttle_out;
}

  1. 明天毫米波雷达的人过来对接,我希望我能搞定,现在开始写那个nra24的驱动,好像这个固件有点问题?

    先把那个nra24毫米波雷达数据读出来再作处理,最后证明固件没问题。

  2. 对于飞控板主控芯片安装超级电容的理由?

    对于飞机在空中就收到电压在减小就说明电没了。
    对于飞控在空中没收到电压减小就掉下来了,在下来后飞控电路通的情况下,可以断定为飞控挂掉了。
    用二极管配合一块小电池也可以达到这个效果。

  3. 为什么会出现电机不能自动停下了的现象?

  • 分析 auto_disarm_check();

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    // auto_disarm_check - disarms the copter if it has been sitting on the ground in manual mode with throttle low for at least 15 seconds
    void Copter::auto_disarm_check()
    {
    uint32_t tnow_ms = millis();
    uint32_t disarm_delay_ms = 1000*constrain_int16(g.disarm_delay, 0, 127);

    // exit immediately if we are already disarmed, or if auto
    // disarming is disabled
    // 发现此处的 disarm_delay_ms = 4s
    if (!motors->armed() || disarm_delay_ms == 0 || control_mode == THROW) {
    auto_disarm_begin = tnow_ms;
    return;
    }

    #if FRAME_CONFIG == HELI_FRAME
    // if the rotor is still spinning, don't initiate auto disarm
    if (motors->rotor_speed_above_critical()) {
    auto_disarm_begin = tnow_ms;
    return;
    }
    #endif

    // always allow auto disarm if using interlock switch or motors are Emergency Stopped
    if ((ap.using_interlock && !motors->get_interlock()) || ap.motor_emergency_stop) {
    #if FRAME_CONFIG != HELI_FRAME
    // use a shorter delay if using throttle interlock switch or Emergency Stop, because it is less
    // obvious the copter is armed as the motors will not be spinning
    disarm_delay_ms /= 2;
    #endif
    } else {
    bool sprung_throttle_stick = (g.throttle_behavior & THR_BEHAVE_FEEDBACK_FROM_MID_STICK) != 0;
    bool thr_low;
    if (flightmode->has_manual_throttle() || !sprung_throttle_stick) {
    // 摇杆操作进入这里
    thr_low = ap.throttle_zero;
    } else {
    float deadband_top = get_throttle_mid() + g.throttle_deadzone;
    thr_low = channel_throttle->get_control_in() <= deadband_top;
    }
    // 能自动上锁的前提,第一、油门低位。第二、检测到着陆完成。目前的问题就是起飞有时候完成不了,啥情况?
    if (!thr_low || !ap.land_complete) {
    // reset timer
    auto_disarm_begin = tnow_ms;
    }
    }

    // disarm once timer expires
    if ((tnow_ms-auto_disarm_begin) >= disarm_delay_ms) {
    init_disarm_motors();
    auto_disarm_begin = tnow_ms;
    }
    }
  • 接下来分析,为啥起飞着陆不能检测到?

有如下几个需要:
第一个: land不能检测到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// update_land_detector - checks if we have landed and updates the ap.land_complete flag
// called at MAIN_LOOP_RATE
void Copter::update_land_detector()
{
// land detector can not use the following sensors because they are unreliable during landing
// barometer altitude : ground effect can cause errors larger than 4m
// EKF vertical velocity or altitude : poor barometer and large acceleration from ground impact
// earth frame angle or angle error : landing on an uneven surface will force the airframe to match the ground angle
// gyro output : on uneven surface the airframe may rock back an forth after landing
// range finder : tend to be problematic at very short distances
// input throttle : in slow land the input throttle may be only slightly less than hover

if (!motors->armed()) {
// if disarmed, always landed.
set_land_complete(true);
} else if (ap.land_complete) {
#if FRAME_CONFIG == HELI_FRAME
// if rotor speed and collective pitch are high then clear landing flag
if (motors->get_throttle() > get_non_takeoff_throttle() && !motors->limit.throttle_lower && motors->rotor_runup_complete()) {
#else
// if throttle output is high then clear landing flag
if (motors->get_throttle() > get_non_takeoff_throttle()) {
#endif
set_land_complete(false);
}
} else {

#if FRAME_CONFIG == HELI_FRAME
// check that collective pitch is on lower limit (should be constrained by LAND_COL_MIN)
bool motor_at_lower_limit = motors->limit.throttle_lower;
#else
// check that the average throttle output is near minimum (less than 12.5% hover throttle)
// 检查平均油门输出是否接近最小值
bool motor_at_lower_limit = motors->limit.throttle_lower && attitude_control->is_throttle_mix_min();
#endif

// check that the airframe is not accelerating (not falling or braking after fast forward flight)
// 检查机身没有加速
bool accel_stationary = (land_accel_ef_filter.get().length() <= LAND_DETECTOR_ACCEL_MAX);

// check that vertical speed is within 1m/s of zero
// 检查垂直速度是否在零的1米/秒范围内 (看了数据OK)
bool descent_rate_low = fabsf(inertial_nav.get_velocity_z()) < 100;

// if we have a healthy rangefinder only allow landing detection below 2 meters
// 如果我们有一个健康的测距仪,只允许2米以下才能着陆
bool rangefinder_check = (!rangefinder_alt_ok() || rangefinder_state.alt_cm_filt.get() < LAND_RANGEFINDER_MIN_ALT_CM);

if (motor_at_lower_limit && accel_stationary && descent_rate_low && rangefinder_check) {
// landed criteria met - increment the counter and check if we've triggered
if( land_detector_count < ((float)LAND_DETECTOR_TRIGGER_SEC)*scheduler.get_loop_rate_hz()) {
land_detector_count++;
} else {
set_land_complete(true);
}
} else {
// we've sensed movement up or down so reset land_detector
land_detector_count = 0;
}
}

set_land_complete_maybe(ap.land_complete || (land_detector_count >= LAND_DETECTOR_MAYBE_TRIGGER_SEC*scheduler.get_loop_rate_hz()));
}

第二个:throttle_zero 没有被置一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// set_throttle_zero_flag - set throttle_zero flag from debounced throttle control
// throttle_zero is used to determine if the pilot intends to shut down the motors
// Basically, this signals when we are not flying. We are either on the ground
// or the pilot has shut down the copter in the air and it is free-falling
// throttle_control的范围为:0-1000;(输入为1000-2000)
void Copter::set_throttle_zero_flag(int16_t throttle_control)
{
static uint32_t last_nonzero_throttle_ms = 0;
uint32_t tnow_ms = millis();
display_zero = throttle_control;
// if not using throttle interlock and non-zero throttle and not E-stopped,
// or using motor interlock and it's enabled, then motors are running,
// and we are flying. Immediately set as non-zero
if ((!ap.using_interlock && (throttle_control > 50) && !ap.motor_emergency_stop) ||
(ap.using_interlock && motors->get_interlock()) ||
ap.armed_with_switch) {
last_nonzero_throttle_ms = tnow_ms;
ap.throttle_zero = false;
} else if (tnow_ms - last_nonzero_throttle_ms > THROTTLE_ZERO_DEBOUNCE_TIME_MS) {
ap.throttle_zero = true;
}
}
  1. 现在需要加入坠机后蜂鸣器报警。
  • 需要了解的东西为:1. 炸机判断标志。 2. 蜂鸣器发出声音的操作。
    20.1. 炸机判断标志?
    在Copter::crash_check()可以申明一个变量,当此标志被置一后一直不释放,直到下一次初始化后才释放。这个函数一直在fast_loop里跑。

20.2. 找到蜂鸣器长期发声的操作?
pixhawk1的蜂鸣器定义在ToneAlarm_PX4.cpp中,现在需要在坠机后给一个信号过来,让无人机一直响,除非关机。根据user_mode_change_failed这个标志打一个过来即可。

  1. 现在加入歌尔气压计,貌似这个协议和DPS280一样,故现在我们开始对比协议咯。
  2. 首先对比协议
  3. 再来看如何调用一个IIC的气压计

  4. 出现一个pwm输出最后为定值然后就直接翻转下降。

    如果px4io给了我们一个这个通道的值,那么使用这个值,否则使用上次发送的值。这样便于观察PX4IO中的故障保护行为。
    其实此时小IO已经没有输出了,然后飞控没死。初步判断硬件挂了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
uint16_t PX4RCOutput::read(uint8_t ch) 
{
if (ch >= PX4_NUM_OUTPUT_CHANNELS) {
return 0;
}

for (uint8_t i=0; i<ORB_MULTI_MAX_INSTANCES; i++) {
if (_outputs[i].pwm_sub >= 0 &&
ch < _outputs[i].outputs.noutputs &&
_outputs[i].outputs.output[ch] > 0) {
return _outputs[i].outputs.output[ch];
}
}
return _period[ch];
}
  1. RTL降落时,分段速度。
    23.1 LAND_SPEED:着地第二阶段速度cm/s
    23.2 LAND_SPEED_HIGH:着地第一阶段速度cm/s。第一阶段着陆的下降速度,单位为cm/s。如果为零,则使用WPNAV_SPEED_DN。

24 挂载需要适配多一些挂载,且发送GPS信息请求与发送有些问题。
24.1 有个挂载ID为19A,现在不能识别。

24.2 拍照指令都应该发送GPS信息,B、D、3结尾的指令都应该发送GPS信息。

目前来说无人机在触发拍照,是通过辅助通道打高低电平来实现拍照,不通过can。
在触发拍照时候,同时把gps经纬度信息发送下去。

1
2
3
4
5
6
7
8
9
10
11
12
13
#if HAL_WITH_UAVCAN
cam_pos_info_t cam_pos;
cam_pos.head = 0xA5;
cam_pos.length = 16;
cam_pos.type =0x01;
cam_pos.lat = current_loc.lat;
cam_pos.lng = current_loc.lng;
cam_pos.alt = current_loc.alt;
cam_pos.cam_index = _image_index;
cam_pos.crc = CRC8Software(&cam_pos.type,cam_pos.length);
if( hal.can_mgr[0] != nullptr && hal.can_mgr[0]->get_MMCCAN() != nullptr)
hal.can_mgr[0]->get_MMCCAN()->cam_trigger((uint8_t *)&cam_pos,sizeof(cam_pos));
#endif

  1. 航线定点抛投。
    先看一下cam_trigger用到相机触发的函数在trigger_pic里面
  1. ubuntu 16.04 nvidia显卡驱动选不合适的,会出现登录页面循环登录不进去。
    解决方法: 26.1. 同时按下 CTRL+ALT+F1 进入命令行模式。
    26.2. 关闭显卡驱动,输入:sudo service lightdm stop
    26.3. 卸载NVIDIA驱动,输入:sudo apt-get purge nvidia*

  2. 查找出现“Critical: PreArm: Polygon boundary invalid”。

从这个链接可知,我们需要设置一个Set Return Location http://ardupilot.org/copter/docs/polygon_fence.html#overview 但是现在他们没有设置,先把这个设置了再去查看代码问题。
报这个错误原因:

  1. 如果没有点。
  2. 默认你的设置里包含返回点,这个设置也没用,只不过同一套底层,设置可以不用。
  3. 现在默认必须打5个点才不报错,现在我不知道四边型你传给我的是5个点还是4个点。
  4. 第0个点默认为返回点,若是返回点在围栏外则也是报错。
  1. hardfault 里面有堆栈信息,哪个函数到哪里了。做个串口打印出来就可以查到哪里死机了。
  1. 这两天遇到一个问题:ardupilot中的libraries中新建一个文件夹,定义在.cpp中,但是声明却在.h中,最后在arducopter.cpp中用,但是死活都链接不起来,后来发现在waf中有个包含文件夹,没加入waf的Python自动链接里去,故会产生此现象,现在把此文件夹加入就ok了。

  2. 今天过来想把国网协议加到frsky中,但是发现frsky的初始化数据都跑不起来,后来发现是因为:#define FRSKY_TELEM_ENABLED ENABLED没开。加入既OK。