Cannot call member function without object - PX4 I2C

171 views Asked by At

I inherited I2C API to PX4 for reading data from magnetometer, but when I compile the project, an error occurs. Here is my code and error message:

class BNO055 : public device::I2C, public I2CSPIDriver<BNO055>
   {
    public:
    BNO055(I2CSPIBusOption bus_option, int bus, int bus_frequency);
    virtual ~BNO055();

    static I2CSPIDriverBase *instantiate(const BusCLIArguments &cli, const 
    BusInstanceIterator &iterator,
                         int runtime_instance);


    int init() override;

    /**
     * Starts polling the sensor
     *
     * @todo why is this a separate function?
     */
    void start();

    /**
     * The function that polls the sensors and updates their values
     */
    void RunImpl();

    static void print_usage();

    private:

    PX4Accelerometer _px4_accel;
    PX4Gyroscope _px4_gyro;
    PX4Magnetometer _px4_mag;

    // most recent data
    struct bno055_accel_double_t accel_xyz;
    struct bno055_gyro_double_t gyro_xyz;
    struct bno055_mag_double_t mag_xyz;

    // TODO check (and tweak) those values
    // cutoff freqs for the internal low pass filters
    const uint8_t ACCEL_BW_REGVAL = BNO055_ACCEL_BW_125HZ;
    const uint8_t GYRO_BW_REGVAL = BNO055_GYRO_BW_116HZ;
    // update freq for the magnetometer
    const uint8_t MAG_RATE_REGVAL = BNO055_MAG_DATA_OUTRATE_30HZ;
    // poll at 250 Hz to match other sensors, this should probably be 
    about 2x the low pass bandwidth
    const uint32_t POLLING_INTERVAL_US = uint32_t(1000000 / 250);
    // the magnetometer is slower than the other sensors, so don't fetch 
    it every time
    const uint32_t MAG_INTERVAL_US = uint32_t(1000000 / 30);
    // save the last time the magnetometer was read
    uint32_t mag_last_read = 0;

    /**
     * Completely resets chip
     *
     * @note init() must have been called before, and since the chip is 
     now reset, init() should be called again
     */
    int reset();

    /**
     * Read a register from the BNO055, this is used by the Bosch lib
     *
     * @param dev_addr this is <b>not used</b>, it is only there because 
     the library needs it in its signature
     * @param reg_addr the (starting) register to read from
     * @param reg_data returned data
     * @param count amount of bytes to read
     * @return 0 on success
     */
    static int8_t read_reg(uint8_t dev_addr, uint8_t reg_addr, uint8_t 
    *reg_data, uint8_t cnt);
    /**
     * Write a register from the BNO055, this is used by the Bosch lib
     *
     * @param dev_addr this is <b>not used</b>, it is only there because 
     the library needs it in its signature
     * @param reg_addr the (starting) register to write to
     * @param reg_data the data to send
     * @param count amount of bytes to send
     * @return 0 on success
     */
    static int8_t write_reg(uint8_t dev_addr, uint8_t reg_addr, uint8_t 
    *reg_data, uint8_t cnt);

    /** Bosch lib main data struct */
    struct bno055_t bno055_struct;

    /**
     * This exists because the lib needs a pointer to a sleep(ms) function
     *
     * @param ms sleep time in millis
     *
     * @todo does this work with Nuttx?
     * @todo replace with workqueue sleep
     */
    inline static void bno_msleep(uint32_t ms) { usleep(ms * 1000); }
    };

in .cpp file:

BNO055::BNO055(I2CSPIBusOption bus_option, int bus, int bus_frequency) :
I2C(DRV_IMU_DEVTYPE_BNO055, MODULE_NAME, bus, BNO055_I2C_ADDR1, bus_frequency),
I2CSPIDriver(MODULE_NAME, px4::device_bus_to_wq(get_device_id()), bus_option, bus),
_px4_accel(get_device_id()),
_px4_gyro(get_device_id()),
_px4_mag(get_device_id())
{
}

and I'm using transfer function in I2C.

int8_t BNO055::read_reg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t cnt)
{
    return transfer(&reg_addr, 1, reg_data, cnt);
}

the transfer function:

int I2C::transfer(const uint8_t *send, const unsigned send_len, uint8_t *recv, const 
                  unsigned recv_len)
{
    int ret = PX4_ERROR;
    unsigned retry_count = 0;

    .
    .
    .

Finally, here is the error message:

../../src/drivers/imu/bosch/bno055/bno055.cpp:147:45: error: cannot call member function 
'int device::I2C::transfer(const uint8_t*, unsigned int, uint8_t*, unsigned int)' without 
object
147 |  return transfer(&reg_addr, 1, reg_data, cnt);

Edit: I'm using these functions as static functions because of this:

    bno055_struct.bus_write = &BNO055::write_reg;
    bno055_struct.bus_read = &BNO055::read_reg;

struct bno055_t
{
    u8 chip_id; /**< chip_id of bno055 */
    u16 sw_rev_id; /**< software revision id of bno055 */
    u8 page_id; /**< page_id of bno055 */
    u8 accel_rev_id; /**< accel revision id of bno055 */
    u8 mag_rev_id; /**< mag revision id of bno055 */
    u8 gyro_rev_id; /**< gyro revision id of bno055 */
    u8 bl_rev_id; /**< boot loader revision id of bno055 */
    u8 dev_addr; /**< i2c device address of bno055 */
    s8 (*bus_write)(u8, u8, u8 *, u8); /**< bus write function pointer */
    s8 (*bus_read)(u8, u8, u8 *, u8); /**<bus read function pointer */
    void (*delay_msec)(BNO055_MDELAY_DATA_TYPE); /**< delay function pointer */
};

When I don't use static, I'm getting this error:

error: cannot convert 'int8_t (BNO055::*)(uint8_t, uint8_t, uint8_t*, uint8_t)' {aka 'signed char (BNO055::*)(unsigned char, unsigned char, unsigned char*, unsigned char)'} to 's8 (*)(u8, u8, u8*, u8)' {aka 'signed char (*)(unsigned char, unsigned char, unsigned char*, unsigned char)'} in assignment
   63 |  bno055_struct.bus_write = &BNO055::write_reg;
      |                                     ^~~~~~~~~
0

There are 0 answers