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 文件模拟速度变化。

提供一个或多个包含纬度/经度对的航路点。如果您提供一个航点,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 中的自动化工具很容易。这是我自己用于应用程序测试和屏幕截图收集的脚本之一:

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

我创建了一步一步的演练,了解我如何使用带有自动化和泄漏的位置模拟来抓取屏幕截图并找到泄漏

于 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 个点,而是在它们之间创建一堆中间点。这是有效的,因为无论两点之间的距离如何,位置模拟器从一个点到另一个点都需要恒定的时间。

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

指示:

  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 回答
6

更新: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 文件中的点

从菜单中选择您的 gpx 文件


演示

在此处输入图像描述

正如您在演示中看到的那样,标记移动得非常快。这不是默认的慢速。一世

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

于 2018-10-11T14:44:41.970 回答
2

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

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

(查看此AppleDoc了解更多详细信息)

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

于 2012-03-30T09:56:10.773 回答