|
1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 |
|
17 |
|
18 // INCLUDE FILES |
|
19 #include <e32math.h> |
|
20 #include <lbspositioninfo.h> |
|
21 #include "EPos_TPosDataSimulator.h" |
|
22 #include "EPos_TDesTokeniser.h" |
|
23 #include "EPos_SimPsyConstants.h" |
|
24 |
|
25 // CONSTANTS |
|
26 const TUint8 KPosDataSeparator = '='; |
|
27 const TUint8 KPosDefaultDataEndMarker = ';'; |
|
28 |
|
29 _LIT8(KHacc, "Horizontal accuracy"); |
|
30 _LIT8(KVacc, "Vertical accuracy"); |
|
31 _LIT8(KPowerupTime, "Powerup time"); |
|
32 _LIT8(KLongitude, "Longitude"); |
|
33 _LIT8(KLatitude, "Latitude"); |
|
34 _LIT8(KSpeed, "Speed"); |
|
35 _LIT8(KCourse, "Course"); |
|
36 _LIT8(KRandom, "Random"); |
|
37 _LIT8(KDeterministic, "Deterministic"); |
|
38 _LIT8(KTimeToFixMin, "TimeToFix min"); |
|
39 _LIT8(KTimeToFixMax, "TimeToFix max"); |
|
40 |
|
41 // ================= MEMBER FUNCTIONS ======================= |
|
42 |
|
43 // C++ default constructor can NOT contain any code, that |
|
44 // might leave. |
|
45 // |
|
46 TPosDataSimulator::TPosDataSimulator() : |
|
47 iHAcc(0), |
|
48 iVAcc(0), |
|
49 iLonErrorRadius(0), |
|
50 iLatErrorRadius(0), |
|
51 iErrorAngle(0), |
|
52 iSpeed(0), |
|
53 iTrueCourse(0), |
|
54 iOrigLatitude(0), |
|
55 iOrigLongitude(0), |
|
56 iLatitude(0), |
|
57 iLongitude(0), |
|
58 iAltError(0), |
|
59 iPowerupTime(0), |
|
60 iRandomMode(EFalse), |
|
61 iTTFMin(0), |
|
62 iTTFMax(0), |
|
63 iFailFrequency(0), |
|
64 iRandomTTF(0), |
|
65 iSeed(0) |
|
66 { |
|
67 TTime time; |
|
68 time.UniversalTime(); |
|
69 iSeed = time.Int64(); |
|
70 } |
|
71 |
|
72 // --------------------------------------------------------- |
|
73 // TPosDataSimulator::ComputeNewPositionL |
|
74 // |
|
75 // (other items were commented in a header). |
|
76 // --------------------------------------------------------- |
|
77 // |
|
78 TInt TPosDataSimulator::ComputeNewPositionL( |
|
79 TPosition& aPosition, |
|
80 const TTime& aRequestStartTime, |
|
81 const TTime& aLastRequestTime) |
|
82 { |
|
83 if (iSpeed != 0) |
|
84 { |
|
85 TReal cHdng1; |
|
86 TReal cLat1; |
|
87 TReal sAlpha; |
|
88 TReal sLat1; |
|
89 TReal cAlpha; |
|
90 |
|
91 TReal latitude = aPosition.Latitude() - iLatErrorRadius; |
|
92 TReal delay = (static_cast<TReal> |
|
93 (aRequestStartTime.MicroSecondsFrom(aLastRequestTime). |
|
94 Int64()))/KToSeconds; |
|
95 if (delay == 0) |
|
96 { |
|
97 delay = 1; |
|
98 } |
|
99 TReal alpha = (iSpeed*delay)/KEarthRadius; |
|
100 |
|
101 // Compute new latitude |
|
102 User::LeaveIfError(Math::Cos(cHdng1, iTrueCourse * KToRadians)); |
|
103 User::LeaveIfError(Math::Cos(cLat1, latitude * KToRadians)); |
|
104 User::LeaveIfError(Math::Sin(sAlpha, alpha)); |
|
105 User::LeaveIfError(Math::Sin(sLat1, latitude * KToRadians)); |
|
106 User::LeaveIfError(Math::Cos(cAlpha, alpha)); |
|
107 |
|
108 TReal sLat2 = cHdng1 * cLat1 * sAlpha + sLat1 * cAlpha; |
|
109 TReal lat2; |
|
110 User::LeaveIfError(Math::ASin(lat2, sLat2)); |
|
111 |
|
112 iLatitude = lat2 * KToDegrees; |
|
113 |
|
114 // Compute new longitude |
|
115 TReal cLat2; |
|
116 User::LeaveIfError(Math::Cos(cLat2, lat2)); |
|
117 TReal tmp =(cAlpha - sLat1 * sLat2) / (cLat1 * cLat2); |
|
118 TReal newLong; |
|
119 ModifyCosArgIfNeeded(tmp); |
|
120 User::LeaveIfError(Math::ACos(newLong, tmp)); |
|
121 |
|
122 newLong *= KToDegrees; |
|
123 |
|
124 // newLong will always be positive. If the course indicates that |
|
125 // longitude should be decreased (sin(course) < 0), the sign should |
|
126 // be changed. |
|
127 TReal sCourse; |
|
128 User::LeaveIfError(Math::Sin(sCourse, iTrueCourse * KToRadians)); |
|
129 if (sCourse < 0) |
|
130 { |
|
131 newLong = -newLong; |
|
132 } |
|
133 |
|
134 iLongitude = aPosition.Longitude() + newLong; |
|
135 LongitudeBoundsCheck(iLongitude); |
|
136 |
|
137 ComputeNewErrorForLatLonAltL(iLatitude, iLongitude, |
|
138 iLatitude, iLongitude); |
|
139 |
|
140 // Compute new course |
|
141 TReal newCourse; |
|
142 tmp = (sLat1 - sLat2*cAlpha) / (cLat2 * sAlpha); |
|
143 ModifyCosArgIfNeeded(tmp); |
|
144 User::LeaveIfError(Math::ACos(newCourse, tmp)); |
|
145 newCourse *= KToDegrees; |
|
146 } |
|
147 else |
|
148 { |
|
149 ComputeNewErrorForLatLonAltL(iOrigLatitude, iOrigLongitude, |
|
150 iLatitude, iLongitude); |
|
151 } |
|
152 |
|
153 // Set position |
|
154 aPosition.SetCoordinate(iLatitude, iLongitude, iAltError); |
|
155 aPosition.SetAccuracy(iHAcc, iVAcc); |
|
156 |
|
157 return KErrNone; |
|
158 } |
|
159 |
|
160 // --------------------------------------------------------- |
|
161 // TPosDataSimulator::ParseAndCreatePosObjectL |
|
162 // |
|
163 // (other items were commented in a header). |
|
164 // --------------------------------------------------------- |
|
165 // |
|
166 void TPosDataSimulator::ParseAndCreatePosObjectL( |
|
167 TPosition& aPosition, |
|
168 const CDesC8Array* aDataArray) |
|
169 { |
|
170 TInt itemsFound = 0; |
|
171 for (TInt i = 0; i < aDataArray->Count(); i++) |
|
172 { |
|
173 TDesTokeniser tokeniser(aDataArray->MdcaPoint(i)); |
|
174 TPtrC8 field = tokeniser.NextToken(KPosDataSeparator); |
|
175 TPtrC8 value = tokeniser.NextToken(KPosDefaultDataEndMarker); |
|
176 |
|
177 // trim any trailing spaces off the field: |
|
178 const TText8* first = field.Ptr(); |
|
179 const TText8* last = first + field.Length() - 1; |
|
180 |
|
181 while ((last >= first) && TChar(*last).IsSpace() ) |
|
182 { |
|
183 last--; |
|
184 } |
|
185 |
|
186 TUint8 len = (last + 1 - first); |
|
187 TPtrC8 fieldTrimmed(first, len); |
|
188 |
|
189 if (fieldTrimmed.MatchF(KHacc) == 0) |
|
190 { // {float} 0 - |
|
191 LeaveIfNegativeRealL(value); |
|
192 iHAcc = DesToFloatL(value); |
|
193 itemsFound++; |
|
194 } |
|
195 else if (fieldTrimmed.MatchF(KVacc) == 0) |
|
196 { // {float} 0 - |
|
197 LeaveIfNegativeRealL(value); |
|
198 iVAcc = DesToFloatL(value); |
|
199 itemsFound++; |
|
200 } |
|
201 else if (fieldTrimmed.MatchF(KTimeToFixMin) == 0) |
|
202 { // {integer} 0 - |
|
203 LeaveIfNegativeIntL(value); |
|
204 iTTFMin = DesToIntL(value); |
|
205 itemsFound++; |
|
206 } |
|
207 else if (fieldTrimmed.MatchF(KTimeToFixMax) == 0) |
|
208 { // {integer} 0 - |
|
209 LeaveIfNegativeIntL(value); |
|
210 iTTFMax = DesToIntL(value); |
|
211 itemsFound++; |
|
212 } |
|
213 else if (fieldTrimmed.MatchF(KPowerupTime) == 0) |
|
214 { // {integer} 0 - |
|
215 LeaveIfNegativeIntL(value); |
|
216 iPowerupTime = DesToIntL(value); |
|
217 itemsFound++; |
|
218 } |
|
219 else if (fieldTrimmed.MatchF(KLongitude) == 0) |
|
220 { // {float} - 180 - 180 |
|
221 CheckLatLonBoundariesL(value, TReal(180)); |
|
222 iOrigLongitude = DesToRealL(value); |
|
223 LongitudeBoundsCheck(iOrigLongitude); |
|
224 itemsFound++; |
|
225 } |
|
226 else if (fieldTrimmed.MatchF(KLatitude) == 0) |
|
227 { // {float} - 90 - 90 |
|
228 CheckLatLonBoundariesL(value, TReal(90)); |
|
229 iOrigLatitude = DesToRealL(value); |
|
230 if (iOrigLatitude == 90 || iOrigLatitude == -90) |
|
231 { |
|
232 iOrigLatitude = 89.9999; |
|
233 } |
|
234 itemsFound++; |
|
235 } |
|
236 else if (fieldTrimmed.MatchF(KSpeed) == 0) |
|
237 { // {float} 0 - |
|
238 LeaveIfNegativeRealL(value); |
|
239 // Speed NOT used in current supported classes |
|
240 iSpeed = DesToFloatL(value); |
|
241 itemsFound++; |
|
242 } |
|
243 else if (fieldTrimmed.MatchF(KCourse) == 0) |
|
244 { // {float} 0 - 360 |
|
245 // TrueCourse NOT used in current supported classes |
|
246 CheckCourseBoundariesL(value); |
|
247 iTrueCourse = DesToFloatL(value); |
|
248 itemsFound++; |
|
249 } |
|
250 else if (fieldTrimmed.MatchF(KRandom) == 0) |
|
251 { // {integer} 0 - |
|
252 LeaveIfNegativeIntL(value); |
|
253 iFailFrequency = DesToIntL(value); |
|
254 iRandomMode = ETrue; |
|
255 itemsFound++; |
|
256 } |
|
257 else if (fieldTrimmed.MatchF(KDeterministic) == 0) |
|
258 { // {integer} 0 - |
|
259 LeaveIfNegativeIntL(value); |
|
260 iFailFrequency = DesToIntL(value); |
|
261 iRandomMode = EFalse; |
|
262 itemsFound++; |
|
263 } |
|
264 } |
|
265 |
|
266 if (itemsFound != KNoOfSimulatedDataItems) |
|
267 { |
|
268 User::Leave(KErrCorrupt); |
|
269 } |
|
270 |
|
271 aPosition.SetCoordinate(iOrigLatitude, iOrigLongitude, iAltError); |
|
272 aPosition.SetAccuracy(iHAcc, iVAcc); |
|
273 } |
|
274 |
|
275 // --------------------------------------------------------- |
|
276 // TPosDataSimulator::TimeToWait |
|
277 // |
|
278 // (other items were commented in a header). |
|
279 // --------------------------------------------------------- |
|
280 // |
|
281 TTimeIntervalMicroSeconds TPosDataSimulator::TimeToWait( |
|
282 const TTime& aRequestStartTime) |
|
283 { |
|
284 // 500 ms as execution time after wait. |
|
285 // |
|
286 TInt executionTimeAfterWait = 500000; |
|
287 TInt timetowait = iTTFMin; |
|
288 |
|
289 iRandomTTF = (iTTFMin + (Math::Rand(iSeed) % (iTTFMax-iTTFMin+1))) |
|
290 * KToMicroSeconds; |
|
291 TTime now; |
|
292 now.UniversalTime(); |
|
293 TInt delay = I64INT(now.MicroSecondsFrom(aRequestStartTime).Int64()); |
|
294 if (delay < iRandomTTF) |
|
295 { |
|
296 timetowait = Min(iTTFMax * KToMicroSeconds - executionTimeAfterWait, |
|
297 Max(iTTFMin * KToMicroSeconds + executionTimeAfterWait, |
|
298 iRandomTTF - delay)); |
|
299 } |
|
300 else |
|
301 { |
|
302 timetowait = Max(iTTFMin * KToMicroSeconds + executionTimeAfterWait, |
|
303 iRandomTTF - delay); |
|
304 } |
|
305 return TTimeIntervalMicroSeconds(TInt64(timetowait)); |
|
306 } |
|
307 |
|
308 // --------------------------------------------------------- |
|
309 // TPosDataSimulator::FailThisRequest |
|
310 // |
|
311 // (other items were commented in a header). |
|
312 // --------------------------------------------------------- |
|
313 // |
|
314 TInt TPosDataSimulator::FailThisRequest(TInt aNumberOfRequests) |
|
315 { |
|
316 TInt err = KErrNone; |
|
317 if (iFailFrequency != 0) |
|
318 { |
|
319 if (iRandomMode) |
|
320 { |
|
321 TInt randomNum = Math::Rand(iSeed); |
|
322 TInt res = KMaxTInt/iFailFrequency; |
|
323 if (randomNum < res) |
|
324 { |
|
325 err = KErrorCodeForFailedRequest; |
|
326 } |
|
327 } |
|
328 else |
|
329 { |
|
330 if (aNumberOfRequests % iFailFrequency == 0) |
|
331 { |
|
332 err = KErrorCodeForFailedRequest; |
|
333 } |
|
334 } |
|
335 } |
|
336 return err; |
|
337 } |
|
338 |
|
339 // --------------------------------------------------------- |
|
340 // TPosDataSimulator::PowerupTime |
|
341 // |
|
342 // (other items were commented in a header). |
|
343 // --------------------------------------------------------- |
|
344 // |
|
345 TTimeIntervalMicroSeconds TPosDataSimulator::PowerupTime() |
|
346 { |
|
347 TInt powerUp = iPowerupTime * KToMicroSeconds; |
|
348 return TTimeIntervalMicroSeconds(TInt64(powerUp)); |
|
349 } |
|
350 |
|
351 // --------------------------------------------------------- |
|
352 // TPosDataSimulator::GetRandomError |
|
353 // |
|
354 // (other items were commented in a header). |
|
355 // --------------------------------------------------------- |
|
356 // |
|
357 TReal TPosDataSimulator::GetRandomError() |
|
358 { |
|
359 TReal error = 0; |
|
360 for (TInt j = 0; j < KTimesToRandom; j++) |
|
361 { |
|
362 error += Math::FRand(iSeed); |
|
363 } |
|
364 error -= KTimesToRandom/2; |
|
365 return error; |
|
366 } |
|
367 |
|
368 // --------------------------------------------------------- |
|
369 // TPosDataSimulator::ComputeNewErrorForLatLonAltL |
|
370 // |
|
371 // (other items were commented in a header). |
|
372 // --------------------------------------------------------- |
|
373 // |
|
374 void TPosDataSimulator::ComputeNewErrorForLatLonAltL( |
|
375 TReal& aFromLatitude, |
|
376 TReal& aFromLongitude, |
|
377 TReal& aToLatitude, |
|
378 TReal& aToLongitude) |
|
379 { |
|
380 // Add random error to lon and lat |
|
381 // Latitude |
|
382 TReal error = GetRandomError(); |
|
383 error *= iHAcc; |
|
384 iLatErrorRadius = (error * 360) / (2 * KEarthRadius * KPi); |
|
385 |
|
386 // Longitude |
|
387 error = GetRandomError(); |
|
388 error *= iHAcc; |
|
389 iLonErrorRadius = (error * 360) / (2 * KEarthRadius * KPi); |
|
390 |
|
391 // Angle |
|
392 TReal rand = Math::FRand(iSeed); |
|
393 iErrorAngle = rand * 360; |
|
394 |
|
395 TReal cosAlpha; |
|
396 User::LeaveIfError(Math::Cos(cosAlpha, iErrorAngle * KToRadians)); |
|
397 TReal sinAlpha; |
|
398 User::LeaveIfError(Math::Sin(sinAlpha, iErrorAngle * KToRadians)); |
|
399 |
|
400 // Add error to latitude |
|
401 aToLatitude = aFromLatitude + iLatErrorRadius * sinAlpha; |
|
402 // Add error to longitude |
|
403 aToLongitude = aFromLongitude + iLonErrorRadius * cosAlpha; |
|
404 |
|
405 // Add random error to altitude |
|
406 iAltError = (TReal32) GetRandomError(); |
|
407 iAltError *= iVAcc; |
|
408 } |
|
409 |
|
410 // --------------------------------------------------------- |
|
411 // TPosDataSimulator::DesToIntL |
|
412 // |
|
413 // (other items were commented in a header). |
|
414 // --------------------------------------------------------- |
|
415 // |
|
416 TInt TPosDataSimulator::DesToIntL(const TDesC8& aDes) |
|
417 { |
|
418 TLex8 lexer(aDes); |
|
419 TInt integer; |
|
420 User::LeaveIfError(lexer.Val(integer)); |
|
421 return integer; |
|
422 } |
|
423 |
|
424 // --------------------------------------------------------- |
|
425 // TPosDataSimulator::DesToFloatL |
|
426 // |
|
427 // (other items were commented in a header). |
|
428 // --------------------------------------------------------- |
|
429 // |
|
430 TReal32 TPosDataSimulator::DesToFloatL(const TDesC8& aDes) |
|
431 { |
|
432 TLex8 lexer(aDes); |
|
433 TReal32 floatNumber; |
|
434 User::LeaveIfError(lexer.Val(floatNumber, TChar('.'))); |
|
435 return floatNumber; |
|
436 } |
|
437 |
|
438 // --------------------------------------------------------- |
|
439 // TPosDataSimulator::DesToRealL |
|
440 // |
|
441 // (other items were commented in a header). |
|
442 // --------------------------------------------------------- |
|
443 // |
|
444 TReal TPosDataSimulator::DesToRealL(const TDesC8& aDes) |
|
445 { |
|
446 TLex8 lexer(aDes); |
|
447 TReal realNumber; |
|
448 User::LeaveIfError(lexer.Val(realNumber, TChar('.'))); |
|
449 return realNumber; |
|
450 } |
|
451 |
|
452 // --------------------------------------------------------- |
|
453 // TPosDataSimulator::LeaveIfNegativeIntL |
|
454 // |
|
455 // (other items were commented in a header). |
|
456 // --------------------------------------------------------- |
|
457 // |
|
458 void TPosDataSimulator::LeaveIfNegativeIntL(const TDesC8& aDes) |
|
459 { |
|
460 TLex8 lexer(aDes); |
|
461 TInt number; |
|
462 User::LeaveIfError(lexer.Val(number)); |
|
463 if (number < 0) |
|
464 { |
|
465 User::Leave(KErrCorrupt); |
|
466 } |
|
467 CheckEosL(lexer); |
|
468 } |
|
469 |
|
470 // --------------------------------------------------------- |
|
471 // TPosDataSimulator::LeaveIfNegativeRealL |
|
472 // |
|
473 // (other items were commented in a header). |
|
474 // --------------------------------------------------------- |
|
475 // |
|
476 void TPosDataSimulator::LeaveIfNegativeRealL(const TDesC8& aDes) |
|
477 { |
|
478 TLex8 lexer(aDes); |
|
479 TReal number; |
|
480 User::LeaveIfError(lexer.Val(number, TChar('.'))); |
|
481 if (number < 0) |
|
482 { |
|
483 User::Leave(KErrCorrupt); |
|
484 } |
|
485 CheckEosL(lexer); |
|
486 } |
|
487 |
|
488 // --------------------------------------------------------- |
|
489 // TPosDataSimulator::CheckLatLonBoundariesL |
|
490 // |
|
491 // (other items were commented in a header). |
|
492 // --------------------------------------------------------- |
|
493 // |
|
494 void TPosDataSimulator::CheckLatLonBoundariesL( |
|
495 const TDesC8& aDes, TReal aMinMaxValue) |
|
496 { |
|
497 TLex8 lexer(aDes); |
|
498 TReal lat; |
|
499 User::LeaveIfError(lexer.Val(lat, TChar('.'))); |
|
500 if (lat < -aMinMaxValue || lat > aMinMaxValue) |
|
501 { |
|
502 User::Leave(KErrCorrupt); |
|
503 } |
|
504 CheckEosL(lexer); |
|
505 } |
|
506 |
|
507 // --------------------------------------------------------- |
|
508 // TPosDataSimulator::CheckEosL |
|
509 // |
|
510 // (other items were commented in a header). |
|
511 // --------------------------------------------------------- |
|
512 // |
|
513 void TPosDataSimulator::CheckEosL(TLex8& aLexer) |
|
514 { |
|
515 aLexer.SkipSpace(); |
|
516 if (!aLexer.Eos()) |
|
517 { |
|
518 User::Leave(KErrCorrupt); |
|
519 } |
|
520 } |
|
521 |
|
522 // --------------------------------------------------------- |
|
523 // TPosDataSimulator::CheckCourseBoundariesL |
|
524 // |
|
525 // (other items were commented in a header). |
|
526 // --------------------------------------------------------- |
|
527 // |
|
528 void TPosDataSimulator::CheckCourseBoundariesL( |
|
529 const TDesC8& aDes) |
|
530 { |
|
531 TLex8 lexer(aDes); |
|
532 TReal32 course; |
|
533 User::LeaveIfError(lexer.Val(course, TChar('.'))); |
|
534 if (course < 0 || course > 360) |
|
535 { |
|
536 User::Leave(KErrCorrupt); |
|
537 } |
|
538 CheckEosL(lexer); |
|
539 } |
|
540 |
|
541 // --------------------------------------------------------- |
|
542 // TPosDataSimulator::ModifyCosArgIfNeeded |
|
543 // |
|
544 // (other items were commented in a header). |
|
545 // --------------------------------------------------------- |
|
546 // |
|
547 void TPosDataSimulator::ModifyCosArgIfNeeded(TReal& aCosArg) |
|
548 { |
|
549 if (aCosArg > 1.0) |
|
550 { |
|
551 aCosArg = 1.0; |
|
552 } |
|
553 else if (aCosArg < -1.0) |
|
554 { |
|
555 aCosArg = -1.0; |
|
556 } |
|
557 } |
|
558 |
|
559 // --------------------------------------------------------- |
|
560 // TPosDataSimulator::LongitudeBoundsCheck |
|
561 // |
|
562 // (other items were commented in a header). |
|
563 // --------------------------------------------------------- |
|
564 // |
|
565 void TPosDataSimulator::LongitudeBoundsCheck(TReal& aLong) |
|
566 { |
|
567 // Make sure -180.0 < aLong =< 180.0 |
|
568 while (aLong < -KLongitudeUpperBound) |
|
569 { |
|
570 aLong += KFullCircle; |
|
571 } |
|
572 while (aLong >= KLongitudeUpperBound) |
|
573 { |
|
574 aLong -= KFullCircle; |
|
575 } |
|
576 } |
|
577 |
|
578 // End of File |