web-dev-qa-db-fra.com

Lorsque vous utilisez GPX dans Xcode pour simuler des changements d’emplacement, existe-t-il un moyen de contrôler la vitesse?

J'utilise le fichier GPX suivant dans Xcode 4.2 pour simuler un changement d'emplacement. Cela fonctionne bien, mais je ne peux pas contrôler la vitesse du changement d’emplacement. le tampon semble ne pas fonctionner. Quelqu'un at-il une solution pour cela?

<?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>
20
lichen19853

Je ne pense pas (savoir) que cela est possible directement dans le GPX, mais vous pouvez tester le changement d'emplacement avec Instruments/Automation.

Vous utiliseriez un script du type:

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

Etc. J'ai pris cet exemple dans la vidéo WWDC11 (Test de vos applications géolocalisées)

Je suis conscient que cela ne vous permet pas de définir la vitesse, mais les retards en tiennent compte, j'espère. Peut-être que ça vous aidera.

11
JiaYow

Le support Xcode simule le changement de vitesse avec un fichier GPX.

Fournissez un ou plusieurs points de cheminement contenant une paire latitude/longitude. Si vous fournissez un point de cheminement, Xcode simulera cet emplacement spécifique. Si vous fournissez plusieurs points de cheminement, Xcode simulera une route visitant chaque point de cheminement.

Fournissez éventuellement un élément de temps pour chaque point de cheminement. Xcode interpolera les mouvements à une vitesse correspondant au temps écoulé entre chaque point de cheminement. Si vous ne fournissez pas d'élément de temps, Xcode utilisera un taux de vitesse fixe. Les points de cheminement doivent être triés par heure dans l'ordre croissant.

Écrivez comme ceci:

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

Environ -1 vitesse

La vitesse de l’objet CoreLocation sera toujours de -1 lors de la simulation. Une solution de contournement possible consiste à enregistrer un dernier emplacement, puis à calculer la vitesse nous-mêmes. Exemple de code:

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;
}
19
BB9z

Je ne pense pas que vous puissiez le faire avec des fichiers GPX. Mais c’est facile avec l’outil Automation de Intruments. Voici l'un des scripts que j'utilise moi-même pour le test de mes applications et la collecte de captures d'écran:

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

J'ai créé guide pas à pas pour expliquer comment j'ai utilisé la simulation de localisation avec Automation and Leaks pour capturer des captures d'écran et détecter les fuites.

14

Si vous ne voulez pas traiter avec automator, vous pouvez le faire fonctionner uniquement avec un fichier GPX. L'astuce consiste à créer un tas de points. 

Par exemple, au lieu de créer 2 points pour aller de A à B, créez un ensemble de points intermédiaires entre eux. Cela fonctionne car le simulateur de localisation nécessite un temps constant pour se déplacer d'un point à un autre, quelle que soit la distance entre les deux points.

Plutôt que d'avoir à créer un tas de points manuellement, vous pouvez utiliser le code suivant.

Instructions:

  1. Collez le code ci-dessous en modifiant la constante kDesiredSpeed ​​à votre convenance.
  2. Ajoutez un UITapGestureRecognizer à votre vue cartographique, en le reliant à mapViewTapped:
  3. Ajoutez des boutons qui appellent startRecordingPoints et stopRecordingPoints.
  4. Lancer l'application.
  5. Appuyez sur le bouton startRecordingPoints.
  6. Touchez où l'itinéraire doit commencer.
  7. Touchez un autre emplacement sur la carte. Cela générera une quantité X de points entre le dernier nœud et le nouveau nœud, de sorte qu'il apparaîtra se déplacer à la vitesse souhaitée.
  8. Répétez l'étape précédente autant de fois que vous le souhaitez.
  9. Appuyez sur arrêter l'enregistrement.
  10. Copiez la sortie de la console.
  11. Fichier> Nouveau fichier ...
  12. Choisissez une ressource> Fichier GPX
  13. Collez le contenu et enregistrez le fichier.
  14. Appuyez sur la flèche d'emplacement dans le débogueur et choisissez votre fichier GPX.
  15. Asseyez-vous et observez que l'emplacement est mis à jour à la vitesse que vous souhaitez!

Code:

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

Avertissement: kAppleTravelTime = 2 est juste une supposition. Si vous avez une valeur plus précise, postez-la dans un commentaire.

9
Senseful

Il existe également une méthode qui vous permet de définir la vitesse et d’autres propriétés:

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

(Cochez cette case AppleDoc pour plus de détails)

Vous pouvez toujours voir votre NSLog dans l'application console (/Applications/Utilities/Console.app). Ajoutez simplement un filtre pour obtenir des résultats corrects.

2
bernhard

Mise à jour: octobre 2018 (Swift 4, Xcode 9.4)

J'ai trouvé une solution très simple. bien qu'il ne permette pas de spécifier la vitesse exacte, la vitesse peut toutefois être contrôlée en spécifiant la distance entre les points gps. La vitesse est directement proportionnelle à la distance entre deux points gps.

  1. Générez des points GPX à partir de gpxGenerator.com
  2. Dans Xcode, créez un nouveau fichier GPX à partir d'un fichier -> Nouveau fichier (ou commande N). Recherche gpx
  3. Collez les points GPX que vous avez obtenus de gpxGenerator.com dans ce fichier gpx
  4. Supprimez toutes les marques de temps (c’est sa substance. N'ignorez pas cette étape)
  5. Exécutez votre application et sélectionnez votre fichier gpx dans le menu de débogage. (voir capture d'écran) Dans mon cas, son nom est SanFranciscoToNewYork

C'est tout. Maintenant, le simulateur ou le périphérique réel doit simuler les points de votre fichier gpx avec sp

 Select your gpx file from menu


Démo

 enter image description here

Comme vous pouvez le voir dans la démo, le marqueur avance très vite. Ce n'est pas la vitesse lente par défaut. je

Remarque: Ceci est mon exemple de fichier GPX que j’ai utilisé pour la démo 

1
Awais Fayyaz