dronecodeのコーディングルールを拝見いたしました。

あまりにもざっくりしていることもあり、保守性や品質まではいき渡っていなさそうと感じています。

そこで、日本には、組み込み系ソフトについて、コーディングルールというのを事細かく定義してるものがあります。

例えば、

・MISRAとか

・IPAの「組込みソフトウェア開発向けコーディング作法ガイド[C++言語版]」や

・凡ミスによる障害の回避ルール

これらのルールをベースにArduCopterのコードの品質を上げていきたい。

また、その過程で、不安なコードがあれば、不安を軽減していきたい。

その情報や修正案などのアップしたいと思い、このディスカッションを立ち上げました。

何卒、よろしくおねがいいたします。

You need to be a member of diydrones to add comments!

Join diydrones

Email me when people reply –

Replies

  • 今日、採用いただきました。

    これで、Navioで、PX4Flowが利用できると思うのですが。

    いかがでしょう。

    murata,katsutoshi said:

    Navio2PX4Flow が使えないということで調査を進めています。

    平均値「i2c_integral_frame」の値が変化しないという現象があります。

    これは、PX4Flowのダブルバッファを切り替えるために、最終レジスタまで行ったかどうかをsizeofで構造体のサイズと比較して切り替えています。

    この構造体のサイズが、AP_OpticalFlow_Linux.hi2c_frame.h で異なっています。

    1レジスタ分がLinux側が少ない、もしくは PX4Flow 側が1レジスタ分多いということが原因でした。

    PX4Flow側の定義をHPに合わせると、多数のFCに影響があるため、Linux側を修正することにしました。

    PACKED を取るとWORDバウンダリ(さらに2バイト多くなります)となって解消しません。

    そこで、1バイト分のパディング変数を追加することで対応しました。

    対応結果:

    Debug Information:
    f_integral=10 00 FB FF EB FF 00 00 04 00 00 00 E4 97 01 00 E8 94 05 00 00 00 D8 0E C3 00
    PX4FLOW id:0 qual:195 FlowRateX:-0.00 Y:-0.02 BodyRateX:0.00 y:0.00

    ===

    AP_OpticalFlow_Linux.h

        typedef struct PACKED {
            uint16_t frame_count_since_last_readout;
            int16_t pixel_flow_x_integral;
            int16_t pixel_flow_y_integral;
            int16_t gyro_x_rate_integral;
            int16_t gyro_y_rate_integral;
            int16_t gyro_z_rate_integral;
            uint32_t integration_timespan;
            uint32_t sonar_timestamp;
            uint16_t ground_distance;
            int16_t gyro_temperature;
            uint8_t qual;

      uint8_t padding_not_used; ★追加パディング変数
        } i2c_integral_frame;

    PX4Flow の i2c_frame.h 

    typedef struct i2c_integral_frame
    {
    uint16_t frame_count_since_last_readout;
    int16_t pixel_flow_x_integral;
    int16_t pixel_flow_y_integral;
    int16_t gyro_x_rate_integral;
    int16_t gyro_y_rate_integral;
    int16_t gyro_z_rate_integral;
    uint32_t integration_timespan;
    uint32_t sonar_timestamp;
    uint16_t ground_distance;
    int16_t gyro_temperature;
    uint8_t qual;
    } i2c_integral_frame;
  • Navio2 を長時間稼働させてログを取得していました。

    ファイルファイズが2Gを超えたら、新しいファイルを作成しません。

    確か電源に接続されたままホバリングさせて基地局にするシステムがあったと思います。

    こういう使い方をする場合、ログファイルを新規作成する必要あると思っています。

    3702298025?profile=original

  • 励ましありがとうございます。とても元気付けられます。

    情報ありがとうございます。

    Jiro Hattori said:

    頑張っていますね。

    ご存じのようにPixhawk本体とpx4flowは、既にDisconの風情です。 

    Pixhawk2と並行してSolo用のOptical Flow Sensor(px4flowの改良品)が、開発中なようなので、ネタをお知らせします。

    詳細は、”Optical flow on Solo” http://discuss.ardupilot.org/t/optical-flow-on-solo/8756 です。

    CANBUSになるのかなぁ?

  • 頑張っていますね。

    ご存じのようにPixhawk本体とpx4flowは、既にDisconの風情です。 

    Pixhawk2と並行してSolo用のOptical Flow Sensor(px4flowの改良品)が、開発中なようなので、ネタをお知らせします。

    詳細は、”Optical flow on Solo” http://discuss.ardupilot.org/t/optical-flow-on-solo/8756 です。

    CANBUSになるのかなぁ?

  • Navio2PX4Flow が使えないということで調査を進めています。

    平均値「i2c_integral_frame」の値が変化しないという現象があります。

    これは、PX4Flowのダブルバッファを切り替えるために、最終レジスタまで行ったかどうかをsizeofで構造体のサイズと比較して切り替えています。

    この構造体のサイズが、AP_OpticalFlow_Linux.hi2c_frame.h で異なっています。

    1レジスタ分がLinux側が少ない、もしくは PX4Flow 側が1レジスタ分多いということが原因でした。

    PX4Flow側の定義をHPに合わせると、多数のFCに影響があるため、Linux側を修正することにしました。

    PACKED を取るとWORDバウンダリ(さらに2バイト多くなります)となって解消しません。

    そこで、1バイト分のパディング変数を追加することで対応しました。

    対応結果:

    Debug Information:
    f_integral=10 00 FB FF EB FF 00 00 04 00 00 00 E4 97 01 00 E8 94 05 00 00 00 D8 0E C3 00
    PX4FLOW id:0 qual:195 FlowRateX:-0.00 Y:-0.02 BodyRateX:0.00 y:0.00

    ===

    AP_OpticalFlow_Linux.h

        typedef struct PACKED {
            uint16_t frame_count_since_last_readout;
            int16_t pixel_flow_x_integral;
            int16_t pixel_flow_y_integral;
            int16_t gyro_x_rate_integral;
            int16_t gyro_y_rate_integral;
            int16_t gyro_z_rate_integral;
            uint32_t integration_timespan;
            uint32_t sonar_timestamp;
            uint16_t ground_distance;
            int16_t gyro_temperature;
            uint8_t qual;

      uint8_t padding_not_used; ★追加パディング変数
        } i2c_integral_frame;

    PX4Flow の i2c_frame.h 

    typedef struct i2c_integral_frame
    {
    uint16_t frame_count_since_last_readout;
    int16_t pixel_flow_x_integral;
    int16_t pixel_flow_y_integral;
    int16_t gyro_x_rate_integral;
    int16_t gyro_y_rate_integral;
    int16_t gyro_z_rate_integral;
    uint32_t integration_timespan;
    uint32_t sonar_timestamp;
    uint16_t ground_distance;
    int16_t gyro_temperature;
    uint8_t qual;
    } i2c_integral_frame;
  • Pixhawk 単体でWifi接続したいと思って、Wifi TCP I2C SPIで検索しましたところ、「Wi-Fiモジュール ESP-WROOM-02」というモジュールがヒットしました。

    さらに、ardupilotで検索しましたら、すでに実証実験されておられ、WifiでMission Plannerと接続できたとの記事でした。

    早速、楽天市場でヒットした店舗へ注文しました。

    先人に感謝です。

    http://diydrones.com/group/japan-arducopter-group/forum/topics/esp8...

  • Navio2で意図的にアクティブのlogファイルを削除しました。

    この削除による異常検出しないようです。

    3702294594?profile=original

    3702294616?profile=original

  • 開始レジスタ番号が不適切という認識をいただきpr採用いただきました。


    murata,katsutoshi said:

    ジャイロ関連が「0」なんですが。。。

    これが正常なのか異常なのは。今は不明です。

    これから調査するため。

    (gdb) p *(i2c_integral_frame*)&val[22]
    $9 = {frame_count_since_last_readout = 0, pixel_flow_x_integral = 0, pixel_flow_y_integral = 0, gyro_x_rate_integral = 0, gyro_y_rate_integral = 0, gyro_z_rate_integral = 0, integration_timespan = 0, sonar_timestamp = 13040, ground_distance = 300, gyro_temperature = 4000, qual = 0 '\000'}

    (gdb) p/x val
    $10 = {0x85, 0xc2, 0x0 <repeats 17 times>, 0x47, 0x2c, 0x1, 0x0 <repeats 16 times>, 0xf0, 0x32, 0x0, 0x0, 0x2c, 0x1, 0xa0, 0xf, 0x0}

    murata,katsutoshi said:

    GDBでデバッグを進めていいます。

    下記のように定義しています。

    しかし、処理では、開始レジスタが「0」になっています。

    #define PX4FLOW_REG             0x16    // Measure Register 22

    ===

    [Thread debugging using libthread_db enabled]

    Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
    Loaded symbols for /lib/arm-linux-gnueabihf/libpthread.so.0
    Reading symbols from /lib/arm-linux-gnueabihf/libc.so.6...Reading symbols from /usr/lib/debug//lib/arm-linux-gnueabihf/libc-2.19.so...done.
    done.
    Loaded symbols for /lib/arm-linux-gnueabihf/libc.so.6
    Reading symbols from /lib/ld-linux-armhf.so.3...Reading symbols from /usr/lib/debug//lib/arm-linux-gnueabihf/ld-2.19.so...done.
    done.
    Loaded symbols for /lib/ld-linux-armhf.so.3
    0x00138700 in DataFlash_File::WritePrioritisedBlock (this=0x322c08, pBuffer=0x7ed7841c, size=47, is_critical=false) at ../../libraries/DataFlash/DataFlash_File.cpp:487
    487        uint16_t space = BUF_SPACE(_writebuf);
    (gdb) c
    Continuing.

    Breakpoint 1, AP_OpticalFlow_Linux::read (this=0x327d68, report=0x7ed78440) at ../../libraries/AP_OpticalFlow/AP_OpticalFlow_Linux.cpp:101
    101            if (!_dev->read_registers(0, val, I2C_INTEGRAL_FRAME_SIZE)) {
    (gdb) s
    AP_HAL::OwnPtr<AP_HAL::I2CDevice>::operator-> (this=0x327d70) at ../../libraries/AP_HAL/utility/OwnPtr.h:95
    95        T *operator->() const { return _ptr; }
    (gdb) s
    AP_HAL::Device::read_registers (this=0x327d00, first_reg=0 '\000', recv=0x7ed783c4 "", recv_len=25) at ../../libraries/AP_HAL/Device.h:79
    79            first_reg |= _read_flag;
    (gdb) s
    80            return transfer(&first_reg, 1, recv, recv_len);
    (gdb) s
    Linux::I2CDevice::transfer (this=0x327d00, send=0x7ed783ab "", send_len=1, recv=0x7ed783c4 "", recv_len=25) at ../../libraries/AP_HAL_Linux/I2CDevice.cpp:150
    150        struct i2c_msg msgs[2] = { };
    (gdb) s
    151        unsigned nmsgs = 0;
    (gdb) s
    153        assert(_bus.fd >= 0);
    (gdb) s
    155        if (send && send_len != 0) {
    (gdb) s
    156            msgs[nmsgs].addr = _address;
    (gdb) s
    157            msgs[nmsgs].flags = 0;
    (gdb) s
    158            msgs[nmsgs].buf = const_cast<uint8_t*>(send);
    (gdb) s
    159            msgs[nmsgs].len = send_len;
    (gdb) s
    160            nmsgs++;
    (gdb) s
    163        if (recv && recv_len != 0) {
    (gdb)
    164            msgs[nmsgs].addr = _address;
    (gdb)
    165            msgs[nmsgs].flags = I2C_M_RD;
    (gdb)
    166            msgs[nmsgs].buf = recv;
    (gdb)
    167            msgs[nmsgs].len = recv_len;
    (gdb)
    168            nmsgs++;
    (gdb)
    171        if (!nmsgs) {
    (gdb)
    175        struct i2c_rdwr_ioctl_data i2c_data = { };
    (gdb)
    177        i2c_data.msgs = msgs;
    (gdb)
    178        i2c_data.nmsgs = nmsgs;
    (gdb)
    180        int r = -EINVAL;
    (gdb)
    181        unsigned retries = _retries;
    (gdb)
    183            r = ::ioctl(_bus.fd, I2C_RDWR, &i2c_data);
    (gdb)
    ioctl () at ../sysdeps/unix/syscall-template.S:81
    81    ../sysdeps/unix/syscall-template.S: No such file or directory.
    (gdb)
    82    in ../sysdeps/unix/syscall-template.S
    (gdb)
    Linux::I2CDevice::transfer (this=0x327d00, send=0x7ed783ab "", send_len=1, recv=0x7ed783c4 "\246\203", recv_len=25) at ../../libraries/AP_HAL_Linux/I2CDevice.cpp:184
    184        } while (r < 0 && retries-- > 0);
    (gdb)
    182        do {
    (gdb)
    186        return r >= 0;
    (gdb)
    187    }
    (gdb)
    AP_HAL::Device::read_registers (this=0x327d00, first_reg=0 '\000', recv=0x7ed783c4 "\246\203", recv_len=25) at ../../libraries/AP_HAL/Device.h:81
    81        }
    (gdb)
    AP_OpticalFlow_Linux::read (this=0x327d68, report=0x7ed78440) at ../../libraries/AP_OpticalFlow/AP_OpticalFlow_Linux.cpp:104
    104            memcpy(&f_integral, val, I2C_INTEGRAL_FRAME_SIZE);
    (gdb) p val
    $1 = "\246\203", '\000' <repeats 17 times>, "'\222\f", '\000' <repeats 24 times>
    (gdb) bt
    #0  AP_OpticalFlow_Linux::read (this=0x327d68, report=0x7ed78440) at ../../libraries/AP_OpticalFlow/AP_OpticalFlow_Linux.cpp:104
    #1  0x00134bf4 in AP_OpticalFlow_Linux::update (this=0x327d68) at ../../libraries/AP_OpticalFlow/AP_OpticalFlow_Linux.cpp:153
    #2  0x000c18d4 in OpticalFlow::update (this=0x164d58 <copter+5088>) at ../../libraries/AP_OpticalFlow/OpticalFlow.cpp:83
    #3  0x0004a4d8 in Copter::update_optical_flow (this=0x163978 <copter>) at ../../ArduCopter/sensors.cpp:135
    #4  0x00014d28 in Functor<void>::method_wrapper<Copter, &Copter::update_optical_flow> (obj=0x163978 <copter>) at ../../libraries/AP_HAL/utility/functor.h:85
    #5  0x00091d54 in Functor<void>::operator() (this=0x142130 <Copter::scheduler_tasks+60>) at ../../libraries/AP_HAL/utility/functor.h:55
    #6  0x000c9018 in AP_Scheduler::run (this=0x163cb0 <copter+824>, time_available=1323) at ../../libraries/AP_Scheduler/AP_Scheduler.cpp:135
    #7  0x000139d8 in Copter::loop (this=0x163978 <copter>) at ../../ArduCopter/ArduCopter.cpp:241
    #8  0x0011d134 in HAL_Linux::run (this=0x16bf1c <AP_HAL::get_HAL()::hal>, argc=3, argv=0x7ed787d4, callbacks=0x163978 <copter>) at ../../libraries/AP_HAL_Linux/HAL_Linux_Class.cpp:360
    #9  0x00014c0c in main (argc=3, argv=0x7ed787d4) at ../../ArduCopter/ArduCopter.cpp:631

    FX4Flowの仕様

    https://pixhawk.org/modules/px4flow

    開始レジスタ0

    3702285953?profile=original

    開始レジスタ 16

    3702292920?profile=original

        // Perform the writing and reading in a single command
        if (PX4FLOW_REG == 0x00) {
            if (!_dev->read_registers(0, val, I2C_FRAME_SIZE + I2C_INTEGRAL_FRAME_SIZE)) {
                goto fail_transfer;
            }
            memcpy(&f_integral, &(val[I2C_FRAME_SIZE]), I2C_INTEGRAL_FRAME_SIZE);
        }

        if (PX4FLOW_REG == 0x16) {
            if (!_dev->read_registers(0, val, I2C_INTEGRAL_FRAME_SIZE)) {
                goto fail_transfer;
            }
            memcpy(&f_integral, val, I2C_INTEGRAL_FRAME_SIZE);
        }

        /*
         * Core transfer function. This does a single bus transaction which
         * sends send_len bytes and receives recv_len bytes back from the slave.
         *
         * Return: true on a successful transfer, false on failure.
         */
        virtual bool transfer(const uint8_t *send, uint32_t send_len,
                              uint8_t *recv, uint32_t recv_len) = 0;

        /**
         * Wrapper function over #transfer() to read recv_len registers, starting
         * by first_reg, into the array pointed by recv. The read flag passed to
         * #set_read_flag(uint8_t) is ORed with first_reg before performing the
         * transfer.
         *
         * Return: true on a successful transfer, false on failure.
         */
        bool read_registers(uint8_t first_reg, uint8_t *recv, uint32_t recv_len)
        {
            first_reg |= _read_flag;
            return transfer(&first_reg, 1, recv, recv_len);
        }

    murata,katsutoshi said:

    このことなのかなあ。

    とりあえす、GDBで動作を確認してみるとして。。。

    デバッグ環境を整えるために、下記を実施。

    cd  ./work/ardupilot
    alias waf="$PWD/modules/waf/waf-light"
    waf configure --board=navio2 --debug
    waf clean
    waf --targets bin/arducopter-hexa
    cd /home/pi/work/ardupilot/build/navio2-debug/bin
    sudo ./arducopter-hexa -A udp:192.168.0.15:14550 (mac qgroundcontol)
    or
    sudo ./arducopter-hexa -A udp:192.168.0.25:14550 (Win10 Mission Planner)

    別ターミナルで
    ps -ax

    pi@navio:~ $ ps -ax | grep ./arducopter-hexa
     3023 pts/0    S+     0:00 sudo ./arducopter-hexa -A udp:192.168.0.15:14550
     3027 pts/0    SLl+  47:31 ./arducopter-hexa -A udp:192.168.0.15:14550
     3107 pts/1    S+     0:00 grep --color=auto ./arducopter-hexa

    sudo gdb

    set target-async 1
    set pagination off
    set non-stop on

    attach 3027

    3702285692?profile=original



    murata,katsutoshi said:

    Navio2PX4Flow が使えないということを聞きました。

    このことでしょうか。

    https://community.emlid.com/t/why-doesnt-the-navio-or-navio2-suppor...

    とりあえず、FX4Flow のファームウェアのリリース版を書き込んで、カメラテストしました。

    フォーカスもちゃんときいていることを確認しました。

    ソナーについては、今、未確認にです。

    3702285710?profile=original

    3702292674?profile=original

    3702285588?profile=original

    3702285725?profile=original

  • PX4Flow がハングしただけで、本体がパニックしてしまいます。

    PX4Flowはオプションだから、ハングしても無視すればよいのに。

    pi@navio:~/work/ardupilot/build/navio2-debug/bin $ sudo ./arducopter-hexa -A u:192.168.0.15:14550
    Raspberry Pi 2/3 with BCM2709!
    PANIC: AP_Baro::read unsuccessful for more than 500ms in AP_Baro::calibrate [2]

    ===

    // calibrate the barometer. This must be called at least once before
    // the altitude() or climb_rate() interfaces can be used
    void AP_Baro::calibrate()
    {
        // reset the altitude offset when we calibrate. The altitude
        // offset is supposed to be for within a flight
        _alt_offset.set_and_save(0);

        // start by assuming all sensors are calibrated (for healthy() test)
        for (uint8_t i=0; i<_num_sensors; i++) {
            sensors[i].calibrated = true;
            sensors[i].alt_ok = true;
        }

        // let the barometer settle for a full second after startup
        // the MS5611 reads quite a long way off for the first second,
        // leading to about 1m of error if we don't wait
        for (uint8_t i = 0; i < 10; i++) {
            uint32_t tstart = AP_HAL::millis();
            do {
                update();
                if (AP_HAL::millis() - tstart > 500) {
                    AP_HAL::panic("PANIC: AP_Baro::read unsuccessful "
                            "for more than 500ms in AP_Baro::calibrate [2]\r\n"); ★ここでパニックている。
                }
                hal.scheduler->delay(10);
            } while (!healthy());
            hal.scheduler->delay(100);
        }

        // now average over 5 values for the ground pressure and
        // temperature settings
        float sum_pressure[BARO_MAX_INSTANCES] = {0};
        float sum_temperature[BARO_MAX_INSTANCES] = {0};
        uint8_t count[BARO_MAX_INSTANCES] = {0};
        const uint8_t num_samples = 5;

        for (uint8_t c = 0; c < num_samples; c++) {
            uint32_t tstart = AP_HAL::millis();
            do {
                update();
                if (AP_HAL::millis() - tstart > 500) {
                    AP_HAL::panic("PANIC: AP_Baro::read unsuccessful "
                            "for more than 500ms in AP_Baro::calibrate [3]\r\n");
                }
            } while (!healthy());
            for (uint8_t i=0; i<_num_sensors; i++) {
                if (healthy(i)) {
                    sum_pressure[i] += sensors[i].pressure;
                    sum_temperature[i] += sensors[i].temperature;
                    count[i] += 1;
                }
            }
            hal.scheduler->delay(100);
        }
        for (uint8_t i=0; i<_num_sensors; i++) {
            if (count[i] == 0) {
                sensors[i].calibrated = false;
            } else {
                sensors[i].ground_pressure.set_and_save(sum_pressure[i] / count[i]);
                sensors[i].ground_temperature.set_and_save(sum_temperature[i] / count[i]);
            }
        }

        // panic if all sensors are not calibrated
        for (uint8_t i=0; i<_num_sensors; i++) {
            if (sensors[i].calibrated) {
                return;
            }
        }
        AP_HAL::panic("AP_Baro: all sensors uncalibrated");
    }

  • PX4Flow へのアクセスでreadできない場合があるようです。

    3702290827?profile=original

    murata,katsutoshi said:

    PX4Flowのファームウェアを疑って、いろいろこねくりまわしていました。

    この結果をもとに、Linux用ドライバを再度確認してみます。


    murata,katsutoshi said:

    同じファームワエアのPX4FlowPixhawk に接続し、DISARMED状態で連続稼働を行いました。

    結果:2.9Hハングしませんでした。(ログを確認するために、電源断しました。)

    Navio2(OS Linux)のドライバ、他にもバグがありそうな感じです。

    3702290840?profile=original

This reply was deleted.