在Xcode中使用GPX来模拟位置变化时,有没有办法控制速度?

时间:2012-02-24 23:26:28

标签: iphone ios xcode location gpx

我在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>

6 个答案:

答案 0 :(得分:20)

Xcode支持使用GPX文件模拟速度变化。

  

提供包含纬度/经度对的一个或多个航路点。如果您提供一个航点,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;
}

答案 1 :(得分:14)

我认为你不能用GPX文件做到这一点。但是Intruments中的自动化工具很容易。以下是我自己用于应用测试和截图收集的脚本之一:

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);
}

我创建step by step walkthrough,了解我如何使用自动化和泄漏的位置模拟来抓取屏幕截图并找到泄漏

答案 2 :(得分:11)

我不认为(知道)这可以直接在GPX中进行,但您可以使用Instruments / Automation测试位置变化。

您使用的脚本如下:

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

等等。我从WWDC11 video(测试您的位置感知应用程序)

中获取了此示例

我知道这实际上并没有让你定义速度,但延迟某种程度上是我希望的。也许那会对你有帮助。

答案 3 :(得分:9)

如果您不想处理automator,可以使用GPX文件。诀窍是创建一堆点。

例如,不是仅创建从A到B的2个点,而是在它们之间创建一堆中间点。这是因为无论两点之间的距离如何,位置模拟器都需要从一个点到另一个点的恒定时间。

您可以使用以下代码,而不必手动创建一堆点。

<强>说明:

  1. 粘贴下面的代码,根据自己的喜好调整kDesiredSpeed常量。
  2. 将UITapGestureRecognizer添加到地图视图中,将其链接到mapViewTapped:
  3. 添加调用startRecordingPoints和stopRecordingPoints的按钮。
  4. 运行应用程序。
  5. 点击startRecordingPoints按钮。
  6. 点击路线的起点。
  7. 点按地图中的其他位置。这将在最后一个节点和新节点之间生成X个点,以使其看起来以您想要的速度移动。
  8. 根据需要多次重复上一步。
  9. 按停止录制。
  10. 复制控制台输出。
  11. 文件&gt;新文件......
  12. 选择资源&gt; GPX文件
  13. 粘贴内容并保存文件。
  14. 点击调试器中的位置箭头,然后选择您的GPX文件。
  15. 坐下来观看位置是否以您想要的速度更新!
  16. <强>代码:

    @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只是猜测。如果您有更准确的价值,请在评论中发布。

答案 4 :(得分:2)

还有一种方法可以让你传递速度和其他一些属性:

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

(查看此AppleDoc了解更多详情)

您仍然可以在控制台应用程序中看到您的NSLog(/Applications/Utilities/Console.app)。只需添加一个过滤器即可获得正确的结果。

答案 5 :(得分:0)

更新:2018年10月(Swift 4,Xcode 9.4)

我找到了一个非常简单的解决方案。尽管不允许指定精确的速度,但是可以通过指定gps点之间的距离来控制速度。速度与两个gps点之间的距离成正比。

  1. gpxGenerator.com生成GPX点
  2. 在Xcode中,从文件->新建文件(或命令N)创建新的GPX。搜索gpx
  3. 将您从gpxGenerator.com获得的GPX点粘贴到该gpx文件中
  4. 删除所有时间标签(这就是它的实质。不要忽略这一步)
  5. 运行您的应用,然后从调试菜单中选择gpx文件。 (请参见屏幕截图) 就我而言,它的名称为SanFranciscoToNewYork

仅此而已。现在,模拟器或真实设备应该使用sp

模拟gpx文件中的点

Select your gpx file from menu


演示

enter image description here

如您在演示中所见,标记移动非常快。这不是默认的慢速速度。我

注意:This是我用于演示的示例GPX文件