Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
168
tools/python/ios_simulator_load_gpx.py
Normal file
168
tools/python/ios_simulator_load_gpx.py
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
GPX to iOS Simulator simctl location command
|
||||
|
||||
Converts a GPX file to simctl location start command for realistic iOS location simulation.
|
||||
|
||||
Tested with CoMaps exported tracks
|
||||
|
||||
Usage:
|
||||
python gpx_to_simctl.py test_route.gpx
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import xml.etree.ElementTree as ET
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
def extract_track_points_from_gpx(gpx_file: Path):
|
||||
"""Extract track points from GPX file."""
|
||||
tree = ET.parse(gpx_file)
|
||||
root = tree.getroot()
|
||||
|
||||
points = []
|
||||
# Find all elements with lat/lon attributes
|
||||
for elem in root.findall('.//*[@lat][@lon]'):
|
||||
lat = float(elem.get('lat'))
|
||||
lon = float(elem.get('lon'))
|
||||
points.append((lat, lon))
|
||||
|
||||
return points
|
||||
|
||||
def generate_simctl_command(points, speed_kmh=60, interval=0.1, distance=None, device="booted"):
|
||||
"""Generate simctl location start command."""
|
||||
if len(points) < 2:
|
||||
raise ValueError("Need at least 2 waypoints for simctl location start")
|
||||
|
||||
# Convert km/h to m/s
|
||||
speed_mps = speed_kmh / 3.6
|
||||
|
||||
# Format waypoints as lat,lon pairs
|
||||
waypoint_strings = [f"{lat:.6f},{lon:.6f}" for lat, lon in points]
|
||||
|
||||
# Build command
|
||||
cmd = ["xcrun", "simctl", "location", device, "start"]
|
||||
cmd.append(f"--speed={speed_mps:.2f}")
|
||||
|
||||
if distance:
|
||||
cmd.append(f"--distance={distance}")
|
||||
else:
|
||||
cmd.append(f"--interval={interval}")
|
||||
|
||||
cmd.extend(waypoint_strings)
|
||||
|
||||
return cmd
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Convert GPX file to simctl location start command",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
python gpx_to_simctl.py test_route.gpx --speed 60 --interval 0.1
|
||||
python gpx_to_simctl.py test_route.gpx --speed 80 --distance 10 --clear-first
|
||||
python gpx_to_simctl.py test_route.gpx --speed 50 --dry-run
|
||||
"""
|
||||
)
|
||||
|
||||
parser.add_argument('gpx_file', help='Input GPX file')
|
||||
parser.add_argument('--speed', type=float, default=60,
|
||||
help='Speed in km/h (default: 60)')
|
||||
parser.add_argument('--interval', type=float, default=0.1,
|
||||
help='Update interval in seconds (default: 0.1)')
|
||||
parser.add_argument('--distance', type=float,
|
||||
help='Update distance in meters (overrides --interval)')
|
||||
parser.add_argument('--device', default='booted',
|
||||
help='Target device (default: booted)')
|
||||
parser.add_argument('--dry-run', action='store_true',
|
||||
help='Show command without executing (default: execute)')
|
||||
parser.add_argument('--clear-first', action='store_true',
|
||||
help='Clear existing location before starting')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Validate input file
|
||||
gpx_file = Path(args.gpx_file)
|
||||
if not gpx_file.exists():
|
||||
print(f"Error: GPX file '{gpx_file}' not found", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
try:
|
||||
# Extract waypoints
|
||||
points = extract_track_points_from_gpx(gpx_file)
|
||||
print(f"Extracted {len(points)} waypoints from {gpx_file}")
|
||||
|
||||
if len(points) < 2:
|
||||
print("Error: Need at least 2 waypoints for location simulation", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
# Generate command
|
||||
cmd = generate_simctl_command(
|
||||
points,
|
||||
speed_kmh=args.speed,
|
||||
interval=args.interval,
|
||||
distance=args.distance,
|
||||
device=args.device
|
||||
)
|
||||
|
||||
# Show command
|
||||
print(f"\nGenerated simctl command:")
|
||||
print(" ".join(cmd))
|
||||
|
||||
# Calculate simulation info
|
||||
speed_mps = args.speed / 3.6
|
||||
total_distance = 0
|
||||
for i in range(1, len(points)):
|
||||
lat1, lon1 = points[i-1]
|
||||
lat2, lon2 = points[i]
|
||||
# Simple distance approximation
|
||||
total_distance += ((lat2-lat1)**2 + (lon2-lon1)**2)**0.5 * 111000 # rough conversion to meters
|
||||
|
||||
duration = total_distance / speed_mps
|
||||
print(f"\nSimulation info:")
|
||||
print(f" Speed: {args.speed} km/h ({speed_mps:.1f} m/s)")
|
||||
print(f" Waypoints: {len(points)}")
|
||||
print(f" Estimated distance: {total_distance/1000:.2f} km")
|
||||
print(f" Estimated duration: {duration:.0f} seconds ({duration/60:.1f} minutes)")
|
||||
if args.distance:
|
||||
print(f" Update distance: {args.distance}m")
|
||||
else:
|
||||
print(f" Update interval: {args.interval}s")
|
||||
|
||||
# Execute by default unless dry-run
|
||||
if args.dry_run:
|
||||
print(f"\n[DRY RUN] Command that would be executed:")
|
||||
print(f" {' '.join(cmd)}")
|
||||
if args.clear_first:
|
||||
clear_cmd = ["xcrun", "simctl", "location", args.device, "clear"]
|
||||
print(f" (would clear location first: {' '.join(clear_cmd)})")
|
||||
else:
|
||||
print(f"\nExecuting command...")
|
||||
|
||||
# Clear location first if requested
|
||||
if args.clear_first:
|
||||
clear_cmd = ["xcrun", "simctl", "location", args.device, "clear"]
|
||||
print("Clearing existing location...")
|
||||
subprocess.run(clear_cmd, check=True)
|
||||
|
||||
# Execute the start command
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
|
||||
if result.returncode == 0:
|
||||
print("✅ Location simulation started successfully!")
|
||||
if result.stdout.strip():
|
||||
print(result.stdout.strip())
|
||||
else:
|
||||
print(f"❌ Error executing command:")
|
||||
print(result.stderr.strip())
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue