Sirikata
libcore/include/sirikata/core/util/Extrapolation.hpp
Go to the documentation of this file.
00001 /*  Sirikata Utilities -- Math Library
00002  *  Extrapolation.hpp
00003  *
00004  *  Copyright (c) 2009, Daniel Reiter Horn
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions are
00009  *  met:
00010  *  * Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *  * Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in
00014  *    the documentation and/or other materials provided with the
00015  *    distribution.
00016  *  * Neither the name of Sirikata nor the names of its contributors may
00017  *    be used to endorse or promote products derived from this software
00018  *    without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00021  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00022  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00023  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00024  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 #ifndef _EXTRAPOLATION_HPP_
00033 #define _EXTRAPOLATION_HPP_
00034 
00035 #include "TemporalValue.hpp"
00036 
00037 namespace Sirikata {
00038 
00039 template<typename Value, typename TimeType>
00040 class ExtrapolatorBase {
00041 public:
00042     virtual ~ExtrapolatorBase(){}
00043     virtual bool needsUpdate(const TimeType&now, const Value&actualValue)const=0;
00044     virtual Value extrapolate(const TimeType&now)const=0;
00045     virtual TimeType lastUpdateTime()const=0;
00046     virtual const Value& lastValue()const=0;
00047     virtual ExtrapolatorBase<Value, TimeType>& resetValue(const TimeType&now, const Value&actualValue)=0;
00048     virtual ExtrapolatorBase<Value, TimeType>& updateValue(const TimeType&now, const Value&actualValue)=0;
00049     virtual bool propertyHolds(const TimeType&time, const std::tr1::function<bool(const Value&)>&)const=0;
00050 };
00051 
00052 template<typename Value>
00053 class Extrapolator : public virtual ExtrapolatorBase<Value, Time> {
00054 };
00055 
00056 
00057 template <typename Value, typename UpdatePredicate, typename TimeType, typename DurationType>
00058 class TimedWeightedExtrapolatorBase : public virtual ExtrapolatorBase<Value, TimeType>, protected UpdatePredicate { // Use protected inheritence for low cost inclusing, zero cost
00059                                                                                                                     // if the class is empty
00060 protected:
00061     enum ValueTimes{PAST=0,PRESENT=1, MAXSAMPLES};
00062     typedef TemporalValueBase<Value, TimeType> TemporalValueType;
00063     TemporalValueType mValuePast;
00064     TemporalValueType mValuePresent;
00065     DurationType mFadeTime;
00066 public:
00067     TimedWeightedExtrapolatorBase(const DurationType&fadeTime, const TimeType&t, const Value&actualValue, const UpdatePredicate&needsUpdate)
00068      : ExtrapolatorBase<Value, TimeType>(),
00069        UpdatePredicate(needsUpdate),
00070        mValuePast(t,actualValue),
00071        mValuePresent(t,actualValue),
00072        mFadeTime(fadeTime)
00073     {}
00074     virtual ~TimedWeightedExtrapolatorBase(){}
00075     virtual bool needsUpdate(const TimeType&now,const Value&actualValue) const{
00076         const UpdatePredicate* mNeedsUpdate=this;
00077         return (*mNeedsUpdate)(actualValue, extrapolate(now));
00078     }
00079     Value extrapolate(const TimeType&t) const
00080     {
00081         DurationType timeSinceUpdate = std::max(DurationType::zero(),t-lastUpdateTime());
00082         if (mFadeTime<=timeSinceUpdate) {
00083             return mValuePresent.extrapolate(t);
00084         }else{
00085             return mValuePast.extrapolate(t)
00086                 .blend(mValuePresent.extrapolate(t),
00087                        (float32)(timeSinceUpdate/mFadeTime));
00088         }
00089     }
00090     const Value& lastValue() const {
00091         return mValuePresent.value();
00092     }
00093     TimeType lastUpdateTime()const{
00094         return mValuePresent.time();
00095     }
00096     ExtrapolatorBase<Value, TimeType>& updateValue(const TimeType&t, const Value&l) {
00097         mValuePast=TemporalValueType(t,extrapolate(t));
00098         mValuePresent.updateValue(t,l);
00099         return *this;
00100     }
00101     ExtrapolatorBase<Value, TimeType>& resetValue(const TimeType&t, const Value&l) {
00102     mValuePresent.updateValue(t,l);
00103     mValuePast = mValuePresent;
00104     return *this;
00105     }
00106     template <class Functor> bool templatedPropertyHolds(const TimeType&t, const Functor &f)const{
00107         DurationType timeSinceUpdate=t-lastUpdateTime();
00108         if (timeSinceUpdate<mFadeTime) {
00109             return f(mValuePast.value())&&f(mValuePresent.value());
00110         }else {
00111             return f(mValuePresent.value());
00112         }
00113     }
00114     virtual bool propertyHolds(const TimeType&time, const std::tr1::function<bool(const Value&)>&f)const{
00115         return templatedPropertyHolds(time,f);
00116     }
00117 };
00118 
00119 template <typename Value, typename UpdatePredicate>
00120 class TimedWeightedExtrapolator : public TimedWeightedExtrapolatorBase<Value, UpdatePredicate, Time, Duration>, public Extrapolator<Value> {
00121 public:
00122     TimedWeightedExtrapolator(const Duration&fadeTime, const Time&t, const Value&actualValue, const UpdatePredicate&needsUpdate)
00123      : TimedWeightedExtrapolatorBase<Value, UpdatePredicate, Time, Duration>(fadeTime, t, actualValue, needsUpdate)
00124     {}
00125     virtual bool needsUpdate(const Time&now, const Value&actualValue) const {
00126         return this->Sirikata::TimedWeightedExtrapolatorBase<Value,UpdatePredicate,Time,Duration>::needsUpdate(now,actualValue);
00127     }
00128     virtual ExtrapolatorBase<Value, Time>& updateValue(const Time&t, const Value&l) {
00129         return this->Sirikata::TimedWeightedExtrapolatorBase<Value,UpdatePredicate,Time,Duration>::updateValue(t,l);
00130     }
00131     virtual ExtrapolatorBase<Value, Time>& resetValue(const Time&t, const Value&l) {
00132         return this->Sirikata::TimedWeightedExtrapolatorBase<Value,UpdatePredicate,Time,Duration>::resetValue(t,l);
00133     }
00134     const Value& lastValue() const {
00135         return this->Sirikata::TimedWeightedExtrapolatorBase<Value,UpdatePredicate,Time,Duration>::lastValue();
00136     }
00137     virtual bool propertyHolds(const Time&time, const std::tr1::function<bool(const Value&)>&f)const{
00138         return this->Sirikata::TimedWeightedExtrapolatorBase<Value,UpdatePredicate,Time,Duration>::propertyHolds(time,f);
00139     }
00140     virtual Value extrapolate(const Time&t) const {
00141         return this->Sirikata::TimedWeightedExtrapolatorBase<Value,UpdatePredicate,Time,Duration>::extrapolate(t);
00142     }
00143     virtual Time lastUpdateTime()const{
00144         return this->Sirikata::TimedWeightedExtrapolatorBase<Value,UpdatePredicate,Time,Duration>::lastUpdateTime();
00145     }
00146 
00147 };
00148 
00149 }
00150 #endif