Esempio n. 1
0
static uint16_t wheel_predict(
        odometry_wheel_t *wheel,
        const uint32_t time_now)
{
    if (wheel->samples[2].timestamp != time_now) {
        float acc, vel, pos, tau1, tau2, dt1, dt2, dt;
        int16_t dy1, dy2;
        uint16_t prediction;

        // Fit a parabola to the wheel's motion
        dt1 = timestamp_duration_s(wheel->samples[0].timestamp,
                                   wheel->samples[1].timestamp);
        dt2 = timestamp_duration_s(wheel->samples[0].timestamp,
                                   wheel->samples[2].timestamp);
        dy1 = (int16_t) (wheel->samples[1].value - wheel->samples[0].value);
        dy2 = (int16_t) (wheel->samples[2].value - wheel->samples[0].value);

        // Avoid division by zero
        if (dt1 <= MINIMUM_DELTA_T) {
            dt2 = MINIMUM_DELTA_T;
        }
        if (dt2 <= MINIMUM_DELTA_T) {
            dt2 = MINIMUM_DELTA_T;
        }

        tau1 = dy1 / (- dt1 * dt1 + dt1 * dt2);
        tau2 = dy2 / (- dt2 * dt2 + dt1 * dt2);

        acc = - tau1 - tau2;
        vel = tau1 * dt2 + tau2 * dt1;
        pos = wheel->samples[0].value;

        // Predict using fitted parabola
        dt = timestamp_duration_s(wheel->samples[0].timestamp, time_now);
        prediction = pos + (int16_t) (vel * dt + acc * dt * dt);

        return prediction;
    } else {
        return wheel->samples[2].value;
    }
}
Esempio n. 2
0
void odometry_base_update(
        odometry_differential_base_t *robot,
        const odometry_encoder_sample_t right_wheel_sample,
        const odometry_encoder_sample_t left_wheel_sample)
{
    wheel_update(&robot->right_wheel, right_wheel_sample);
    wheel_update(&robot->left_wheel, left_wheel_sample);

    // Choose wheel with most recent timestamp as reference
    uint32_t time_now;
    if (0.0f >= timestamp_duration_s(right_wheel_sample.timestamp,
                                     left_wheel_sample.timestamp)) {
        time_now = right_wheel_sample.timestamp;
    } else {
        time_now = left_wheel_sample.timestamp;
    }

    // Wheel prediction
    float delta_right_wheel = wheel_get_delta_meter(&robot->right_wheel, time_now);
    float delta_left_wheel = wheel_get_delta_meter(&robot->left_wheel, time_now);

    // Base prediction
    float dt = timestamp_duration_s(robot->time_last_estim, time_now);
    float delta_fwd = 0.5f * (delta_right_wheel + delta_left_wheel);
    float delta_rot = (delta_right_wheel - delta_left_wheel) / robot->wheelbase;

    float cos_theta = cosf(robot->pose.theta + 0.5f * delta_rot);
    float sin_theta = sinf(robot->pose.theta + 0.5f * delta_rot);

    if (dt >= MINIMUM_DELTA_T) {
        robot->velocity.x = delta_fwd * cos_theta / dt;
        robot->velocity.y = delta_fwd * sin_theta / dt;
        robot->velocity.omega = delta_rot / dt;
    }

    robot->pose.x += delta_fwd * cos_theta;
    robot->pose.y += delta_fwd * sin_theta;
    robot->pose.theta += delta_rot;

    robot->time_last_estim = time_now;
}
Esempio n. 3
0
bool rate_limiter_should_run(rate_limiter_t *rl)
{
    bool should_run = true;
    timestamp_t now = timestamp_get();

    if (timestamp_duration_s(rl->last_update, now) >= 1.0f/parameter_scalar_read(&rl->rate)) {
        should_run = true;
        rl->last_update = now;
    } else {
        should_run = false;
    }
    return should_run;
}