datasourcemodules/simulationpositioningmodule/src/EPos_TPosDataSimulator.cpp
changeset 0 9cfd9a3ee49c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/datasourcemodules/simulationpositioningmodule/src/EPos_TPosDataSimulator.cpp	Tue Feb 02 01:50:39 2010 +0200
@@ -0,0 +1,578 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+
+
+// INCLUDE FILES
+#include <e32math.h>
+#include <lbspositioninfo.h>
+#include "EPos_TPosDataSimulator.h"
+#include "EPos_TDesTokeniser.h"
+#include "EPos_SimPsyConstants.h"
+
+// CONSTANTS
+const TUint8 KPosDataSeparator = '=';
+const TUint8 KPosDefaultDataEndMarker = ';';
+
+_LIT8(KHacc, "Horizontal accuracy");
+_LIT8(KVacc, "Vertical accuracy");
+_LIT8(KPowerupTime, "Powerup time");
+_LIT8(KLongitude, "Longitude");
+_LIT8(KLatitude, "Latitude");
+_LIT8(KSpeed, "Speed");
+_LIT8(KCourse, "Course");
+_LIT8(KRandom, "Random");
+_LIT8(KDeterministic, "Deterministic");
+_LIT8(KTimeToFixMin, "TimeToFix min");
+_LIT8(KTimeToFixMax, "TimeToFix max");
+
+// ================= MEMBER FUNCTIONS =======================
+
+// C++ default constructor can NOT contain any code, that
+// might leave.
+//
+TPosDataSimulator::TPosDataSimulator() :
+    iHAcc(0),
+    iVAcc(0),
+    iLonErrorRadius(0),
+    iLatErrorRadius(0),
+    iErrorAngle(0),
+    iSpeed(0),
+    iTrueCourse(0),
+    iOrigLatitude(0),
+    iOrigLongitude(0),
+    iLatitude(0),
+    iLongitude(0),
+    iAltError(0),
+    iPowerupTime(0),
+    iRandomMode(EFalse),
+    iTTFMin(0),
+    iTTFMax(0),
+    iFailFrequency(0),
+    iRandomTTF(0),
+    iSeed(0)
+    {
+    TTime time;
+    time.UniversalTime();
+    iSeed = time.Int64();
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::ComputeNewPositionL
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt TPosDataSimulator::ComputeNewPositionL(
+    TPosition& aPosition,
+    const TTime& aRequestStartTime,
+    const TTime& aLastRequestTime)
+    {
+    if (iSpeed != 0)
+        {
+        TReal cHdng1;
+        TReal cLat1;
+        TReal sAlpha;
+        TReal sLat1;
+        TReal cAlpha;
+
+        TReal latitude = aPosition.Latitude() - iLatErrorRadius;
+        TReal delay = (static_cast<TReal>
+            (aRequestStartTime.MicroSecondsFrom(aLastRequestTime).
+            Int64()))/KToSeconds;
+        if (delay == 0)
+            {
+            delay = 1;
+            }
+        TReal alpha = (iSpeed*delay)/KEarthRadius;
+
+        // Compute new latitude
+        User::LeaveIfError(Math::Cos(cHdng1, iTrueCourse * KToRadians));
+        User::LeaveIfError(Math::Cos(cLat1,  latitude * KToRadians));
+        User::LeaveIfError(Math::Sin(sAlpha, alpha));
+        User::LeaveIfError(Math::Sin(sLat1,  latitude * KToRadians));
+        User::LeaveIfError(Math::Cos(cAlpha, alpha));
+
+        TReal sLat2 = cHdng1 * cLat1 * sAlpha + sLat1 * cAlpha;
+        TReal lat2;
+        User::LeaveIfError(Math::ASin(lat2, sLat2));
+
+        iLatitude = lat2 * KToDegrees;
+
+        // Compute new longitude
+        TReal cLat2;
+        User::LeaveIfError(Math::Cos(cLat2, lat2));
+        TReal tmp =(cAlpha - sLat1 * sLat2) / (cLat1 * cLat2);
+        TReal newLong;
+        ModifyCosArgIfNeeded(tmp);
+        User::LeaveIfError(Math::ACos(newLong, tmp));
+
+        newLong *= KToDegrees;
+
+        // newLong will always be positive. If the course indicates that
+        // longitude should be decreased (sin(course) < 0), the sign should
+        // be changed.
+        TReal sCourse;
+        User::LeaveIfError(Math::Sin(sCourse, iTrueCourse * KToRadians));
+        if (sCourse < 0)
+            {
+            newLong = -newLong;
+            }
+
+        iLongitude = aPosition.Longitude() + newLong;
+        LongitudeBoundsCheck(iLongitude);
+
+        ComputeNewErrorForLatLonAltL(iLatitude, iLongitude,
+            iLatitude, iLongitude);
+
+        // Compute new course
+        TReal newCourse;
+        tmp = (sLat1 - sLat2*cAlpha) / (cLat2 * sAlpha);
+        ModifyCosArgIfNeeded(tmp);
+        User::LeaveIfError(Math::ACos(newCourse, tmp));
+        newCourse *= KToDegrees;
+        }
+    else
+        {
+        ComputeNewErrorForLatLonAltL(iOrigLatitude, iOrigLongitude,
+            iLatitude, iLongitude);
+        }
+
+    // Set position
+    aPosition.SetCoordinate(iLatitude, iLongitude, iAltError);
+    aPosition.SetAccuracy(iHAcc, iVAcc);
+
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::ParseAndCreatePosObjectL
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void TPosDataSimulator::ParseAndCreatePosObjectL(
+    TPosition& aPosition,
+    const CDesC8Array* aDataArray)
+    {
+    TInt itemsFound = 0;
+    for (TInt i = 0; i < aDataArray->Count(); i++)
+        {
+        TDesTokeniser tokeniser(aDataArray->MdcaPoint(i));
+        TPtrC8 field = tokeniser.NextToken(KPosDataSeparator);
+        TPtrC8 value = tokeniser.NextToken(KPosDefaultDataEndMarker);
+        
+        // trim any trailing spaces off the field:
+        const TText8* first = field.Ptr();
+        const TText8* last = first + field.Length() - 1;
+
+        while ((last >= first) && TChar(*last).IsSpace() )
+        	{
+        	last--;
+        	}
+
+        TUint8 len = (last + 1 - first);
+        TPtrC8  fieldTrimmed(first, len);   
+        
+        if (fieldTrimmed.MatchF(KHacc) == 0)
+            { // {float} 0 -
+            LeaveIfNegativeRealL(value);
+            iHAcc = DesToFloatL(value);
+            itemsFound++;
+            }
+        else if (fieldTrimmed.MatchF(KVacc) == 0)
+            { // {float} 0 -
+            LeaveIfNegativeRealL(value);
+            iVAcc = DesToFloatL(value);
+            itemsFound++;
+            }
+        else if (fieldTrimmed.MatchF(KTimeToFixMin) == 0)
+            { // {integer} 0 -
+            LeaveIfNegativeIntL(value);
+            iTTFMin = DesToIntL(value);
+            itemsFound++;
+            }
+        else if (fieldTrimmed.MatchF(KTimeToFixMax) == 0)
+            { // {integer} 0 -
+            LeaveIfNegativeIntL(value);
+            iTTFMax = DesToIntL(value);
+            itemsFound++;
+            }
+        else if (fieldTrimmed.MatchF(KPowerupTime) == 0)
+            { // {integer} 0 -
+            LeaveIfNegativeIntL(value);
+            iPowerupTime = DesToIntL(value);
+            itemsFound++;
+            }
+        else if (fieldTrimmed.MatchF(KLongitude) == 0)
+            { // {float} - 180 - 180
+            CheckLatLonBoundariesL(value, TReal(180));
+            iOrigLongitude = DesToRealL(value);
+            LongitudeBoundsCheck(iOrigLongitude);
+            itemsFound++;
+            }
+        else if (fieldTrimmed.MatchF(KLatitude) == 0)
+            { // {float} - 90 - 90
+            CheckLatLonBoundariesL(value, TReal(90));
+            iOrigLatitude = DesToRealL(value);
+            if (iOrigLatitude == 90 || iOrigLatitude == -90)
+                {
+                iOrigLatitude = 89.9999;
+                }
+            itemsFound++;
+            }
+        else if (fieldTrimmed.MatchF(KSpeed) == 0)
+            { // {float} 0 -
+            LeaveIfNegativeRealL(value);
+            // Speed NOT used in current supported classes
+            iSpeed = DesToFloatL(value);
+            itemsFound++;
+            }
+        else if (fieldTrimmed.MatchF(KCourse) == 0)
+            { // {float} 0 - 360
+            // TrueCourse NOT used in current supported classes
+            CheckCourseBoundariesL(value);
+            iTrueCourse = DesToFloatL(value);
+            itemsFound++;
+            }
+        else if (fieldTrimmed.MatchF(KRandom) == 0)
+            { // {integer} 0 -
+            LeaveIfNegativeIntL(value);
+            iFailFrequency = DesToIntL(value);
+            iRandomMode = ETrue;
+            itemsFound++;
+            }
+        else if (fieldTrimmed.MatchF(KDeterministic) == 0)
+            { // {integer} 0 -
+            LeaveIfNegativeIntL(value);
+            iFailFrequency = DesToIntL(value);
+            iRandomMode = EFalse;
+            itemsFound++;
+            }
+        }
+
+    if (itemsFound != KNoOfSimulatedDataItems)
+        {
+        User::Leave(KErrCorrupt);
+        }
+
+    aPosition.SetCoordinate(iOrigLatitude, iOrigLongitude, iAltError);
+    aPosition.SetAccuracy(iHAcc, iVAcc);
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::TimeToWait
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TTimeIntervalMicroSeconds TPosDataSimulator::TimeToWait(
+    const TTime& aRequestStartTime)
+    {
+    // 500 ms as execution time after wait.
+    //
+    TInt executionTimeAfterWait = 500000;
+    TInt timetowait = iTTFMin;
+
+    iRandomTTF = (iTTFMin + (Math::Rand(iSeed) % (iTTFMax-iTTFMin+1)))
+        * KToMicroSeconds;
+    TTime now;
+    now.UniversalTime();
+    TInt delay = I64INT(now.MicroSecondsFrom(aRequestStartTime).Int64());
+    if (delay < iRandomTTF)
+        {
+        timetowait = Min(iTTFMax * KToMicroSeconds - executionTimeAfterWait,
+                        Max(iTTFMin * KToMicroSeconds + executionTimeAfterWait,
+                            iRandomTTF - delay));
+        }
+    else
+        {
+        timetowait = Max(iTTFMin * KToMicroSeconds + executionTimeAfterWait,
+            iRandomTTF - delay);
+        }
+    return TTimeIntervalMicroSeconds(TInt64(timetowait));
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::FailThisRequest
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt TPosDataSimulator::FailThisRequest(TInt aNumberOfRequests)
+    {
+    TInt err = KErrNone;
+    if (iFailFrequency != 0)
+        {
+        if (iRandomMode)
+            {
+            TInt randomNum = Math::Rand(iSeed);
+            TInt res = KMaxTInt/iFailFrequency;
+            if (randomNum < res)
+                {
+                err = KErrorCodeForFailedRequest;
+                }
+            }
+        else
+            {
+            if (aNumberOfRequests % iFailFrequency == 0)
+                {
+                err = KErrorCodeForFailedRequest;
+                }
+            }
+        }
+    return err;
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::PowerupTime
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TTimeIntervalMicroSeconds TPosDataSimulator::PowerupTime()
+    {
+    TInt powerUp = iPowerupTime * KToMicroSeconds;
+    return TTimeIntervalMicroSeconds(TInt64(powerUp));
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::GetRandomError
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TReal TPosDataSimulator::GetRandomError()
+    {
+    TReal error = 0;
+    for (TInt j = 0; j < KTimesToRandom; j++)
+        {
+        error += Math::FRand(iSeed);
+        }
+    error -= KTimesToRandom/2;
+    return error;
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::ComputeNewErrorForLatLonAltL
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void TPosDataSimulator::ComputeNewErrorForLatLonAltL(
+    TReal& aFromLatitude,
+    TReal& aFromLongitude,
+    TReal& aToLatitude,
+    TReal& aToLongitude)
+    {
+    // Add random error to lon and lat
+    // Latitude
+    TReal error = GetRandomError();
+    error *= iHAcc;
+    iLatErrorRadius = (error * 360) / (2 * KEarthRadius * KPi);
+
+    // Longitude
+    error = GetRandomError();
+    error *= iHAcc;
+    iLonErrorRadius = (error * 360) / (2 * KEarthRadius * KPi);
+
+    // Angle
+    TReal rand = Math::FRand(iSeed);
+    iErrorAngle = rand * 360;
+
+    TReal cosAlpha;
+    User::LeaveIfError(Math::Cos(cosAlpha, iErrorAngle * KToRadians));
+    TReal sinAlpha;
+    User::LeaveIfError(Math::Sin(sinAlpha, iErrorAngle * KToRadians));
+
+    // Add error to latitude
+    aToLatitude = aFromLatitude + iLatErrorRadius * sinAlpha;
+    // Add error to longitude
+    aToLongitude = aFromLongitude + iLonErrorRadius * cosAlpha;
+
+    // Add random error to altitude
+    iAltError = (TReal32) GetRandomError();
+    iAltError *= iVAcc;
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::DesToIntL
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt TPosDataSimulator::DesToIntL(const TDesC8& aDes)
+    {
+    TLex8   lexer(aDes);
+    TInt    integer;
+    User::LeaveIfError(lexer.Val(integer));
+    return integer;
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::DesToFloatL
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TReal32 TPosDataSimulator::DesToFloatL(const TDesC8& aDes)
+    {
+    TLex8       lexer(aDes);
+    TReal32     floatNumber;
+    User::LeaveIfError(lexer.Val(floatNumber, TChar('.')));
+    return floatNumber;
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::DesToRealL
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TReal TPosDataSimulator::DesToRealL(const TDesC8& aDes)
+    {
+    TLex8 lexer(aDes);
+    TReal realNumber;
+    User::LeaveIfError(lexer.Val(realNumber, TChar('.')));
+    return realNumber;
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::LeaveIfNegativeIntL
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void TPosDataSimulator::LeaveIfNegativeIntL(const TDesC8& aDes)
+    {
+    TLex8 lexer(aDes);
+    TInt  number;
+    User::LeaveIfError(lexer.Val(number));
+    if (number < 0)
+        {
+        User::Leave(KErrCorrupt);
+        }
+    CheckEosL(lexer);
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::LeaveIfNegativeRealL
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void TPosDataSimulator::LeaveIfNegativeRealL(const TDesC8& aDes)
+    {
+    TLex8 lexer(aDes);
+    TReal  number;
+    User::LeaveIfError(lexer.Val(number, TChar('.')));
+    if (number < 0)
+        {
+        User::Leave(KErrCorrupt);
+        }
+    CheckEosL(lexer);
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::CheckLatLonBoundariesL
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void TPosDataSimulator::CheckLatLonBoundariesL(
+    const TDesC8& aDes, TReal aMinMaxValue)
+    {
+    TLex8 lexer(aDes);
+    TReal lat;
+    User::LeaveIfError(lexer.Val(lat, TChar('.')));
+    if (lat < -aMinMaxValue || lat > aMinMaxValue)
+        {
+        User::Leave(KErrCorrupt);
+        }
+    CheckEosL(lexer);
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::CheckEosL
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void TPosDataSimulator::CheckEosL(TLex8& aLexer)
+    {
+    aLexer.SkipSpace();
+    if (!aLexer.Eos())
+        {
+        User::Leave(KErrCorrupt);
+        }
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::CheckCourseBoundariesL
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void TPosDataSimulator::CheckCourseBoundariesL(
+    const TDesC8& aDes)
+    {
+    TLex8 lexer(aDes);
+    TReal32  course;
+    User::LeaveIfError(lexer.Val(course, TChar('.')));
+    if (course < 0 || course > 360)
+        {
+        User::Leave(KErrCorrupt);
+        }
+    CheckEosL(lexer);
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::ModifyCosArgIfNeeded
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void TPosDataSimulator::ModifyCosArgIfNeeded(TReal& aCosArg)
+    {
+    if (aCosArg > 1.0)
+        {
+        aCosArg = 1.0;
+        }
+    else if (aCosArg < -1.0)
+        {
+        aCosArg = -1.0;
+        }
+    }
+
+// ---------------------------------------------------------
+// TPosDataSimulator::LongitudeBoundsCheck
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void TPosDataSimulator::LongitudeBoundsCheck(TReal& aLong)
+    {
+    // Make sure -180.0 < aLong =< 180.0
+    while (aLong < -KLongitudeUpperBound)
+        {
+        aLong += KFullCircle;
+        }
+    while (aLong >= KLongitudeUpperBound)
+        {
+        aLong -= KFullCircle;
+        }
+    }
+
+//  End of File