18a90e6e3174083f274538567d851f98478fc83e9Jeff Brown/*
28a90e6e3174083f274538567d851f98478fc83e9Jeff Brown * Copyright (C) 2012 The Android Open Source Project
38a90e6e3174083f274538567d851f98478fc83e9Jeff Brown *
48a90e6e3174083f274538567d851f98478fc83e9Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
58a90e6e3174083f274538567d851f98478fc83e9Jeff Brown * you may not use this file except in compliance with the License.
68a90e6e3174083f274538567d851f98478fc83e9Jeff Brown * You may obtain a copy of the License at
78a90e6e3174083f274538567d851f98478fc83e9Jeff Brown *
88a90e6e3174083f274538567d851f98478fc83e9Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
98a90e6e3174083f274538567d851f98478fc83e9Jeff Brown *
108a90e6e3174083f274538567d851f98478fc83e9Jeff Brown * Unless required by applicable law or agreed to in writing, software
118a90e6e3174083f274538567d851f98478fc83e9Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
128a90e6e3174083f274538567d851f98478fc83e9Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138a90e6e3174083f274538567d851f98478fc83e9Jeff Brown * See the License for the specific language governing permissions and
148a90e6e3174083f274538567d851f98478fc83e9Jeff Brown * limitations under the License.
158a90e6e3174083f274538567d851f98478fc83e9Jeff Brown */
168a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
178a90e6e3174083f274538567d851f98478fc83e9Jeff Brown#define LOG_TAG "VelocityControl"
188a90e6e3174083f274538567d851f98478fc83e9Jeff Brown//#define LOG_NDEBUG 0
198a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
208a90e6e3174083f274538567d851f98478fc83e9Jeff Brown// Log debug messages about acceleration.
218a90e6e3174083f274538567d851f98478fc83e9Jeff Brown#define DEBUG_ACCELERATION 0
228a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
238a90e6e3174083f274538567d851f98478fc83e9Jeff Brown#include <math.h>
248a90e6e3174083f274538567d851f98478fc83e9Jeff Brown#include <limits.h>
258a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
268a90e6e3174083f274538567d851f98478fc83e9Jeff Brown#include <androidfw/VelocityControl.h>
278a90e6e3174083f274538567d851f98478fc83e9Jeff Brown#include <utils/BitSet.h>
288a90e6e3174083f274538567d851f98478fc83e9Jeff Brown#include <utils/Timers.h>
298a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
308a90e6e3174083f274538567d851f98478fc83e9Jeff Brownnamespace android {
318a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
328a90e6e3174083f274538567d851f98478fc83e9Jeff Brown// --- VelocityControl ---
338a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
348a90e6e3174083f274538567d851f98478fc83e9Jeff Brownconst nsecs_t VelocityControl::STOP_TIME;
358a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
368a90e6e3174083f274538567d851f98478fc83e9Jeff BrownVelocityControl::VelocityControl() {
378a90e6e3174083f274538567d851f98478fc83e9Jeff Brown    reset();
388a90e6e3174083f274538567d851f98478fc83e9Jeff Brown}
398a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
408a90e6e3174083f274538567d851f98478fc83e9Jeff Brownvoid VelocityControl::setParameters(const VelocityControlParameters& parameters) {
418a90e6e3174083f274538567d851f98478fc83e9Jeff Brown    mParameters = parameters;
428a90e6e3174083f274538567d851f98478fc83e9Jeff Brown    reset();
438a90e6e3174083f274538567d851f98478fc83e9Jeff Brown}
448a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
458a90e6e3174083f274538567d851f98478fc83e9Jeff Brownvoid VelocityControl::reset() {
468a90e6e3174083f274538567d851f98478fc83e9Jeff Brown    mLastMovementTime = LLONG_MIN;
478a90e6e3174083f274538567d851f98478fc83e9Jeff Brown    mRawPosition.x = 0;
488a90e6e3174083f274538567d851f98478fc83e9Jeff Brown    mRawPosition.y = 0;
498a90e6e3174083f274538567d851f98478fc83e9Jeff Brown    mVelocityTracker.clear();
508a90e6e3174083f274538567d851f98478fc83e9Jeff Brown}
518a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
528a90e6e3174083f274538567d851f98478fc83e9Jeff Brownvoid VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) {
538a90e6e3174083f274538567d851f98478fc83e9Jeff Brown    if ((deltaX && *deltaX) || (deltaY && *deltaY)) {
548a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        if (eventTime >= mLastMovementTime + STOP_TIME) {
558a90e6e3174083f274538567d851f98478fc83e9Jeff Brown#if DEBUG_ACCELERATION
568a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            ALOGD("VelocityControl: stopped, last movement was %0.3fms ago",
578a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                    (eventTime - mLastMovementTime) * 0.000001f);
588a90e6e3174083f274538567d851f98478fc83e9Jeff Brown#endif
598a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            reset();
608a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        }
618a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
628a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        mLastMovementTime = eventTime;
638a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        if (deltaX) {
648a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            mRawPosition.x += *deltaX;
658a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        }
668a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        if (deltaY) {
678a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            mRawPosition.y += *deltaY;
688a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        }
698a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), &mRawPosition);
708a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
718a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        float vx, vy;
728a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        float scale = mParameters.scale;
738a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        if (mVelocityTracker.getVelocity(0, &vx, &vy)) {
748a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            float speed = hypotf(vx, vy) * scale;
758a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            if (speed >= mParameters.highThreshold) {
768a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                // Apply full acceleration above the high speed threshold.
778a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                scale *= mParameters.acceleration;
788a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            } else if (speed > mParameters.lowThreshold) {
798a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                // Linearly interpolate the acceleration to apply between the low and high
808a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                // speed thresholds.
818a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                scale *= 1 + (speed - mParameters.lowThreshold)
828a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                        / (mParameters.highThreshold - mParameters.lowThreshold)
838a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                        * (mParameters.acceleration - 1);
848a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            }
858a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
868a90e6e3174083f274538567d851f98478fc83e9Jeff Brown#if DEBUG_ACCELERATION
878a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): "
888a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                    "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f",
898a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                    mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
908a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                    mParameters.acceleration,
918a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                    vx, vy, speed, scale / mParameters.scale);
928a90e6e3174083f274538567d851f98478fc83e9Jeff Brown#endif
938a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        } else {
948a90e6e3174083f274538567d851f98478fc83e9Jeff Brown#if DEBUG_ACCELERATION
958a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity",
968a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                    mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
978a90e6e3174083f274538567d851f98478fc83e9Jeff Brown                    mParameters.acceleration);
988a90e6e3174083f274538567d851f98478fc83e9Jeff Brown#endif
998a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        }
1008a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
1018a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        if (deltaX) {
1028a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            *deltaX *= scale;
1038a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        }
1048a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        if (deltaY) {
1058a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            *deltaY *= scale;
1068a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        }
1078a90e6e3174083f274538567d851f98478fc83e9Jeff Brown    }
1088a90e6e3174083f274538567d851f98478fc83e9Jeff Brown}
1098a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
1108a90e6e3174083f274538567d851f98478fc83e9Jeff Brown} // namespace android
111