diff -r 000000000000 -r 9cfd9a3ee49c datasourcemodules/simulationpositioningmodule/src/EPos_TPosDataSimulator.cpp --- /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 +#include +#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 + (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