24

場所の変更をシミュレートするために、Xcode 4.2 で次の GPX ファイルを使用しています。うまく機能しますが、場所の変更の速度を制御できません。スタンプが効かないようです。誰かがこれに対する解決策を持っていますか?

<?xml version="1.0"?>
<gpx version="1.1" creator="Xcode"> 
    <wpt lat="37.331705" lon="-122.030237"></wpt>
    <wpt lat="37.331705" lon="-122.030337"></wpt>
    <wpt lat="37.331705" lon="-122.030437"></wpt>
    <wpt lat="37.331705" lon="-122.030537"></wpt>
</gpx>
4

6 に答える 6

27

Xcode サポートは、GPX ファイルを使用して速度変化をシミュレートします。

緯度/経度のペアを含む 1 つ以上のウェイポイントを提供します。ウェイポイントを 1 つ指定すると、Xcode はその特定の場所をシミュレートします。複数のウェイポイントを指定すると、Xcode は各ウェイポイントを訪れるルートをシミュレートします。

必要に応じて、各ウェイポイントに時間要素を提供します。Xcode は、各ウェイポイント間の経過時間に基づいた速度で動きを補間します。時間要素を指定しない場合、Xcode は固定レートの速度を使用します。ウェイポイントは、時間の昇順で並べ替える必要があります。

次のように書きます。

<wpt lat="39.96104510" lon="116.4450860">
    <time>2010-01-01T00:00:00Z</time>
</wpt>
<wpt lat="39.96090940" lon="116.4451400">
    <time>2010-01-01T00:00:05Z</time>
</wpt>
...
<wpt lat="39.96087240" lon="116.4450430">
    <time>2010-01-01T00:00:09Z</time>
</wpt>

-1 速度について

シミュレーション中、CoreLocation オブジェクトの速度は常に -1 になります。可能な回避策は、最後の場所を保存してから、自分で速度を計算することです。サンプルコード:

CLLocationSpeed speed = location.speed;
if (speed < 0) {
    // A negative value indicates an invalid speed. Try calculate manually.
    CLLocation *lastLocation = self.lastLocation;
    NSTimeInterval time = [location.timestamp timeIntervalSinceDate:lastLocation.timestamp];

    if (time <= 0) {
        // If there are several location manager work at the same time, an outdated cache location may returns and should be ignored.
        return;
    }

    CLLocationDistance distanceFromLast = [lastLocation distanceFromLocation:location];
    if (distanceFromLast < DISTANCE_THRESHOLD
        || time < DURATION_THRESHOLD) {
        // Optional, dont calculate if two location are too close. This may avoid gets unreasonable value.
        return;
    }
    speed = distanceFromLast/time;
    self.lastLocation = location;
}
于 2016-04-05T03:24:54.823 に答える
15

GPXファイルではできないと思います。しかし、Intruments 内の自動化ツールを使えば簡単です。アプリのテストとスクリーンショットの収集に使用するスクリプトの 1 つを次に示します。

var target = UIATarget.localTarget();

// speed is in meters/sec
var points = [
          {location:{latitude:48.8899,longitude:14.2}, options:{speed:8, altitude:200, horizontalAccuracy:10, verticalAccuracy:15}},
          {location:{latitude:48.8899,longitude:14.9}, options:{speed:11, altitude:200, horizontalAccuracy:10, verticalAccuracy:15}},
          {location:{latitude:48.8899,longitude:14.6}, options:{speed:12, altitude:200, horizontalAccuracy:10, verticalAccuracy:15}},
          {location:{latitude:48.8899,longitude:14.7}, options:{speed:13, altitude:200, horizontalAccuracy:10, verticalAccuracy:15}},
          {location:{latitude:49.2,longitude:14.10}, options:{speed:15, altitude:200, horizontalAccuracy:10, verticalAccuracy:15}},
          {location:{latitude:49.4,longitude:14.8}, options:{speed:15, altitude:200, horizontalAccuracy:10, verticalAccuracy:15}},
          {location:{latitude:48.8899,longitude:14.9}, options:{speed:9, altitude:200, horizontalAccuracy:10, verticalAccuracy:15}},
          {location:{latitude:48.8899,longitude:15.1}, options:{speed:8, altitude:200, horizontalAccuracy:10, verticalAccuracy:15}},
          {location:{latitude:48.8899,longitude:16.1}, options:{speed:3, altitude:200, horizontalAccuracy:10, verticalAccuracy:15}},
          ];

for (var i = 0; i < points.length; i++)
{
target.setLocationWithOptions(points[i].location,points[i].options);
target.captureScreenWithName(i+"_.png");
target.delay(1.0);
}

Automation と Leaks でロケーション シミュレーションを使用してスクリーンショットを取得し、リークを見つける方法について、段階的なウォークスルーを作成しました。

于 2012-07-29T12:32:25.987 に答える
13

これがGPXで直接可能であるとは思いませんが(知っています)、Instruments/Automationを使用して場所の変更をテストできます。

次のようなスクリプトを使用します。

var target = UIATarget.localTarget();
target.setLocation(<location);
target.delay(5);
target.setLocation(...);

等々。この例は、WWDC11ビデオ(位置認識アプリケーションのテスト)から抜粋したものです。

これでは実際には速度を定義できないことは承知していますが、遅延が何らかの形でそれを説明していることを願っています。多分それはあなたを助けるでしょう。

于 2012-02-24T23:35:30.300 に答える
9

automator を扱いたくない場合は、GPX ファイルだけで動作させることができます。コツは、たくさんのポイントを作成することです。

たとえば、A から B に移動する 2 つのポイントだけを作成する代わりに、それらの間に多数の中間ポイントを作成します。これが機能するのは、2 つのポイント間の距離に関係なく、ロケーション シミュレータがあるポイントから別のポイントに移動するのに一定の時間がかかるためです。

一連のポイントを手動で作成する代わりに、次のコードを使用できます。

指示:

  1. 以下のコードを貼り付け、kDesiredSpeed 定数を好みに合わせて調整します。
  2. UITapGestureRecognizer をマップ ビューに追加し、mapViewTapped にリンクします。
  3. startRecordingPoints と stopRecordingPoints を呼び出すボタンを追加します。
  4. アプリを実行します。
  5. startRecordingPoints ボタンをタップします。
  6. ルートを開始する場所をタップします。
  7. マップ内の別の場所をタップします。これにより、最後のノードと新しいノードの間に X 個のポイントが生成され、必要な速度で移動しているように見えます。
  8. 前の手順を必要な回数だけ繰り返します。
  9. 録音停止を押します。
  10. コンソール出力をコピーします。
  11. ファイル > 新しいファイル...
  12. [リソース] > [GPX ファイル] を選択します
  13. 内容を貼り付けてファイルを保存します。
  14. デバッガーで場所の矢印をタップし、GPX ファイルを選択します。
  15. 座って、ちょうどあなたが望む速度で場所が更新されるのを見てください!

コード:

@property (strong, nonatomic) CLLocation *lastRecordedPoint;
@property (strong, nonatomic) NSMutableString *recordingOutput;

...

- (IBAction)mapViewTapped:(UITapGestureRecognizer *)sender {
    if (sender.state != UIGestureRecognizerStateEnded || !self.recordingOutput) {
        return;
    }

    CLLocationCoordinate2D coord = [self.mapView convertPoint:[sender locationInView:self.mapView]
                                         toCoordinateFromView:self.mapView];
    [self recordPoint:coord];
}

- (void)recordPoint:(CLLocationCoordinate2D)newPoint {
    const CGFloat kAppleTravelTime = 2; // the default time it takes to travel from one point to another
    const CGFloat kDesiredSpeed = 6; // meters per sec
    const CGFloat kDesiredDistanceBetweenPoints = kDesiredSpeed * kAppleTravelTime;
    NSString * const kFormatString = @"    <wpt lat=\"%f\" lon=\"%f\"></wpt>\n";

    CLLocation *newLocation = [[CLLocation alloc] initWithLatitude:newPoint.latitude longitude:newPoint.longitude];
    NSInteger numberOfPoints = 1;
    if (self.lastRecordedPoint) {
        CLLocationDistance distance = [self.lastRecordedPoint distanceFromLocation:newLocation];
        numberOfPoints = MAX(round(distance / kDesiredDistanceBetweenPoints), 1);
        CGFloat deltaLatitude = newPoint.latitude - self.lastRecordedPoint.coordinate.latitude;
        CGFloat deltaLongitude = newPoint.longitude - self.lastRecordedPoint.coordinate.longitude;
        for (NSInteger i = 0; i < numberOfPoints; i++) {
            CLLocationDegrees latitude = self.lastRecordedPoint.coordinate.latitude + (numberOfPoints/distance * deltaLatitude) * (i+1);
            CLLocationDegrees longitude = self.lastRecordedPoint.coordinate.longitude + (numberOfPoints/distance * deltaLongitude) * (i+1);
            [self.recordingOutput appendFormat:kFormatString, latitude, longitude];
        }
    } else {
        [self.recordingOutput appendFormat:kFormatString, newPoint.latitude, newPoint.longitude];
    }
    NSLog(@"Recorded %ld point(s) to: %f,%f", (long)numberOfPoints, newPoint.latitude, newPoint.longitude);

    self.lastRecordedPoint = newLocation;
}


- (void)startRecordingPoints {
    NSLog(@"Started recording points. Tap anywhere on the map to begin recording points.");
    self.recordingOutput = [NSMutableString string];
    [self.recordingOutput appendString:@"<?xml version=\"1.0\"?>\n<gpx version=\"1.1\" creator=\"Xcode\">\n"];
    self.lastRecordedPoint = nil;
}

- (void)stopRecordingPoints {
    [self.recordingOutput appendString:@"</gpx>"];
    NSLog(@"Done recording, here is your gpx file: \n%@", self.recordingOutput);
    self.recordingOutput = nil;
}

免責事項: kAppleTravelTime = 2単なる推測です。より正確な値がある場合は、コメントに投稿してください。

于 2014-04-17T08:18:24.643 に答える
2

速度やその他のプロパティを渡すことができる方法もあります。

target.setLocationWithOptions({latitude: 46.546928, longitude: 11.867127}, {altitude: 200.0, speed: 5});

(詳細については、このAppleDocを確認してください)

NSLogは、コンソールアプリケーション(/Applications/Utilities/Console.app)で引き続き確認できます。フィルタを追加するだけで、適切な結果が得られます。

于 2012-03-30T09:56:10.773 に答える