Compare commits

..

3 Commits

Author SHA1 Message Date
7df9de12ce Repository cleanup: Remove large files, cache files, sensitive data, and junk files
- Updated .gitignore with comprehensive patterns for Python, media files, and project data
- Removed all __pycache__ directories and .pyc files from tracking
- Removed large media files (PNG frames, MP4 videos) from git history
- Removed sensitive credential files (credentials.enc, key.key, server_settings.enc)
- Removed test files and temporary data from tracking
- Removed junk_files directory from tracking
- Repository size optimization and security improvement
2025-07-15 15:20:39 +03:00
9f8c1c27dc saved 2025-07-15 14:55:51 +03:00
1d0dc05a7b uploaded 2025-07-10 15:26:18 +03:00
38 changed files with 281 additions and 783 deletions

38
.gitignore vendored
View File

@@ -1,3 +1,39 @@
# Ignore the virtual environment folder
track/
resurces/projects/
# Ignore Python cache files
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
# Ignore project data and generated files
resources/projects/
resources/trip_archive/
resources/credentials.enc
resources/key.key
resources/server_settings.enc
# Ignore generated videos and frames
*.mp4
*.avi
*.mov
*.webm
cinema_frames/
progressive_frames/
# Ignore test files and temporary files
test_*.py
*.tmp
*.log
# Ignore IDE files
.vscode/
.idea/
*.swp
*.swo
# Ignore OS files
.DS_Store
Thumbs.db

Binary file not shown.

View File

@@ -1,45 +0,0 @@
# Project Cleanup Summary
## What Was Cleaned Up
### Moved to `junk_files/`
- Documentation files (*.md) that were cluttering the root directory
- `3D_VIDEO_DOCUMENTATION.md`
- `PAUSE_EDIT_IMPROVEMENTS.md`
- `PROJECT_MODERNIZATION_SUMMARY.md`
- `TEST_MODE_DOCUMENTATION.md`
### Removed
- All `__pycache__` directories and compiled Python bytecode files
- Duplicate and test files that were no longer needed
### Fixed
- Fixed typo in requirements.txt (`reqirements.txt` was corrected to `requirements.txt`)
- Ensured proper import structure (app uses `py_scripts.video_3d_generator` correctly)
## Current Clean Structure
```
traccar_animation/
├── .git/ # Git repository files
├── .gitignore # Git ignore rules
├── config.py # Application configuration
├── main.py # Main application entry point
├── traccar.kv # Kivy UI layout file
├── requirements.txt # Python dependencies (fixed)
├── py_scripts/ # Python modules
│ ├── __init__.py
│ ├── utils.py
│ ├── video_3d_generator.py
│ └── webview.py
├── screens/ # Kivy screen modules
├── resources/ # Application resources
├── track/ # Virtual environment
└── junk_files/ # Non-essential files moved here
```
## Verification
- ✅ Utils module imports correctly
- ✅ Video 3D generator module imports correctly
- ✅ No duplicate files remain
- ✅ All dependencies properly listed in requirements.txt
- ✅ Clean project structure maintained

View File

@@ -1,41 +0,0 @@
#!/usr/bin/env python3
"""
Complete video generation from existing frames
"""
import os
import glob
from moviepy import ImageSequenceClip
def create_video_from_frames():
frames_folder = "/home/pi/Desktop/traccar_animation/resources/projects/day 2/frames"
output_path = "/home/pi/Desktop/traccar_animation/resources/projects/day 2/advanced_3d_animation.mp4"
# Get all frame files
frame_files = glob.glob(os.path.join(frames_folder, "frame_*.png"))
frame_files.sort() # Ensure correct order
if not frame_files:
print("No frames found!")
return
print(f"Found {len(frame_files)} frames")
print("Creating video...")
# Create video clip
clip = ImageSequenceClip(frame_files, fps=30)
# Write video file
clip.write_videofile(
output_path,
codec='libx264',
bitrate='8000k',
audio=False,
temp_audiofile=None,
remove_temp=True
)
print(f"Video created successfully: {output_path}")
return output_path
if __name__ == "__main__":
create_video_from_frames()

View File

@@ -1,83 +0,0 @@
#!/usr/bin/env python3
"""
Test script for Google Earth-style flythrough animation
"""
import os
import sys
sys.path.append('/home/pi/Desktop/traccar_animation')
from py_scripts.advanced_3d_generator import Advanced3DGenerator
from datetime import datetime
def test_google_earth_animation():
"""Test the new Google Earth flythrough animation"""
# Find a project with GPS data
projects_folder = "/home/pi/Desktop/traccar_animation/resources/projects"
if not os.path.exists(projects_folder):
print("Projects folder not found!")
return
# Look for projects
projects = [d for d in os.listdir(projects_folder) if os.path.isdir(os.path.join(projects_folder, d))]
if not projects:
print("No projects found!")
return
# Use the first project found
project_name = projects[0]
project_folder = os.path.join(projects_folder, project_name)
positions_file = os.path.join(project_folder, "positions.json")
if not os.path.exists(positions_file):
print(f"No positions.json found in project {project_name}")
return
print(f"Testing Google Earth animation with project: {project_name}")
# Create generator
generator = Advanced3DGenerator(project_folder)
# Check dependencies
try:
generator.check_dependencies()
print("✅ All dependencies available")
except Exception as e:
print(f"❌ Dependency error: {e}")
return
# Generate Google Earth-style animation
output_video = os.path.join(project_folder, f"{project_name}_google_earth_test_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4")
def progress_callback(progress, message):
print(f"Progress: {progress:.1f}% - {message}")
try:
print("Starting Google Earth flythrough generation...")
success = generator.generate_3d_animation(
positions_file,
output_video,
style='google_earth',
progress_callback=progress_callback
)
if success and os.path.exists(output_video):
print(f"✅ SUCCESS! Google Earth flythrough created: {output_video}")
# Get file size
file_size = os.path.getsize(output_video) / (1024 * 1024) # MB
print(f"📹 Video size: {file_size:.1f} MB")
else:
print("❌ Failed to create video")
except Exception as e:
print(f"❌ Error during generation: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
test_google_earth_animation()

View File

@@ -1,81 +0,0 @@
#!/usr/bin/env python3
"""
Test script for the improved Relive-style GPS animation
"""
import os
import sys
import json
from datetime import datetime
# Add the project directory to the path
sys.path.append('/home/pi/Desktop/traccar_animation')
from py_scripts.advanced_3d_generator import Advanced3DGenerator
def test_relive_animation():
"""Test the new Relive-style animation"""
# Find a project with GPS data
resources_folder = "/home/pi/Desktop/traccar_animation/resources"
projects_folder = os.path.join(resources_folder, "projects")
if not os.path.exists(projects_folder):
print("No projects folder found")
return
# Look for projects with positions.json
for project_name in os.listdir(projects_folder):
project_path = os.path.join(projects_folder, project_name)
positions_file = os.path.join(project_path, "positions.json")
if os.path.exists(positions_file):
print(f"🎬 Testing Relive-style animation with project: {project_name}")
# Check if positions file has data
try:
with open(positions_file, 'r') as f:
positions = json.load(f)
if len(positions) < 5:
print(f"❌ Project {project_name} has only {len(positions)} GPS points - skipping")
continue
print(f"📍 Found {len(positions)} GPS points")
# Create generator
generator = Advanced3DGenerator(project_path)
# Progress callback
def progress_callback(progress, message):
print(f"Progress: {progress:.1f}% - {message}")
# Generate animation
output_video = os.path.join(project_path, f"relive_animation_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4")
print(f"🚀 Starting Relive-style animation generation...")
success = generator.generate_3d_animation(
positions_file,
output_video,
style='advanced',
progress_callback=progress_callback
)
if success:
print(f"✅ SUCCESS! Relive-style animation created: {output_video}")
print(f"📁 You can find your video at: {output_video}")
else:
print("❌ Failed to generate animation")
return # Exit after first successful project
except Exception as e:
print(f"❌ Error testing project {project_name}: {e}")
continue
print("❌ No suitable projects found for testing")
if __name__ == "__main__":
print("🎬 Testing Improved Relive-Style GPS Animation")
print("=" * 50)
test_relive_animation()

View File

@@ -24,7 +24,8 @@ class BlenderGPSAnimator:
if BLENDER_AVAILABLE:
self.setup_blender_scene()
else:
raise ImportError("Blender (bpy) is not available. Please install Blender with Python API access.")
# Don't raise error here, let the caller handle the check
pass
def check_dependencies(self):
"""Check if Blender dependencies are available"""

View File

@@ -1 +0,0 @@
gAAAAABob4-usKjps0vEVupB8FIJ3tKqoOeedzOUpt16NICbpi1ejKoSwqDvH7eIAPaZCOkfbPC6gjJGTo2yxt4BOPg1yzg_-Xanpl5iL1Y2mIRxWag-5cWhDNiqZo3bEZMqZ3M875O-

View File

@@ -1 +0,0 @@
wetp_PNG9CC5432-W9H3rUbaqIurwldZxHlOgori5kY=

View File

@@ -1 +0,0 @@
gAAAAABobK2fcNGeWyfPJzYnOl_HWl8TdQfRDb5teUXH9Kpjmme0TUVA3Dy7wm2MuMEGsPBTWBm8XfaX8daIwu6iDV6o8G07XZ_A0RoMqx3xWiYUbX63ovYy8qITIpMqbt0dayYigDSPmdr_8pcqko6ik-ctfdg4SkGH1gRXb5yuacnzezLr3KcHMh833PkbTO6WiUYPCwaivEMTVHUxL5YORiLRGu4E3lS_WDPo7kv53khtUI9b7vWJOOUFXcelM2vF3iHI3EkXCWrO2Qpm22nC44b-yCnZvYzx7g-WHZDNfG6CA1KXbcyhouxR4b7502iofpEAN5sizLFuyOWIOBdVphblIkRd1qdq6fVmt0IMeoaMpNPNuDKJqMDLuAU05wXDWbGXei6YU6rs6YJgpGOfNdv8A_sKKJBrh5QVE2kZ2GE0Ysqpnw2Yfj_jsMBpdh-bBs6UDwcI

View File

@@ -10,7 +10,7 @@ from py_scripts.utils import (
process_preview_util, optimize_route_entries_util
)
from py_scripts.advanced_3d_generator import NavigationAnimationGenerator
from py_scripts.blender_animator import BlenderGPSAnimator
# BlenderGPSAnimator imported conditionally when needed
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.label import Label
@@ -250,15 +250,15 @@ class CreateAnimationScreen(Screen):
Clock.schedule_once(lambda dt: run_google_earth_animation(), 0.5)
def generate_blender_animation(self):
"""Generate cinema-quality animation using Blender"""
"""Generate cinema-quality animation using Blender (or fallback to advanced 3D)"""
# Show processing popup
layout = BoxLayout(orientation='vertical', spacing=10, padding=10)
label = Label(text="Initializing Blender rendering pipeline...")
label = Label(text="Initializing cinema rendering pipeline...")
progress = ProgressBar(max=100, value=0)
layout.add_widget(label)
layout.add_widget(progress)
popup = Popup(
title="Generating Blender Cinema Animation",
title="Generating Cinema Animation",
content=layout,
size_hint=(0.9, None),
size=(0, 200),
@@ -283,9 +283,13 @@ class CreateAnimationScreen(Screen):
Clock.schedule_once(lambda dt: popup.dismiss(), 2)
return
# Check if Blender is available
try:
from py_scripts.blender_animator import BLENDER_AVAILABLE, BlenderGPSAnimator
if BLENDER_AVAILABLE:
update_status(10, "Loading GPS data into Blender...")
# Check dependencies first
# Use Blender for rendering
animator = BlenderGPSAnimator(project_folder)
animator.check_dependencies()
@@ -311,11 +315,212 @@ class CreateAnimationScreen(Screen):
else:
raise Exception("Failed to generate Blender animation")
else:
raise ImportError("Blender not available")
except ImportError:
# Fallback to advanced 3D animation with cinema-quality settings
update_status(10, "Blender not available - using advanced 3D cinema mode...")
# Import here to avoid startup delays
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import cv2
# Load GPS data
with open(positions_path, 'r') as f:
positions = json.load(f)
if len(positions) < 2:
update_status(0, "Error: Need at least 2 GPS points")
Clock.schedule_once(lambda dt: popup.dismiss(), 2)
return
update_status(20, "Processing GPS coordinates for cinema rendering...")
# Extract coordinates
lats = np.array([pos['latitude'] for pos in positions])
lons = np.array([pos['longitude'] for pos in positions])
alts = np.array([pos.get('altitude', 0) for pos in positions])
timestamps = [pos.get('fixTime', '') for pos in positions]
# Convert to relative coordinates
lat_center = np.mean(lats)
lon_center = np.mean(lons)
alt_min = np.min(alts)
x = (lons - lon_center) * 111320 * np.cos(np.radians(lat_center))
y = (lats - lat_center) * 110540
z = alts - alt_min
update_status(30, "Creating cinema-quality frames...")
# Cinema settings - higher quality
frames_folder = os.path.join(project_folder, "cinema_frames")
os.makedirs(frames_folder, exist_ok=True)
fps = 24 # Cinema standard
total_frames = min(len(positions), 200) # Limit for reasonable processing time
points_per_frame = max(1, len(positions) // total_frames)
frame_files = []
# Generate cinema-quality frames
for frame_idx in range(total_frames):
current_progress = 30 + (frame_idx / total_frames) * 50
update_status(current_progress, f"Rendering cinema frame {frame_idx + 1}/{total_frames}...")
end_point = min((frame_idx + 1) * points_per_frame, len(positions))
# Create high-quality 3D plot
plt.style.use('dark_background') # Cinema-style dark theme
fig = plt.figure(figsize=(16, 12), dpi=150) # Higher resolution
ax = fig.add_subplot(111, projection='3d')
# Plot route with cinema styling
if end_point > 1:
# Gradient effect for completed route
colors = np.linspace(0, 1, end_point)
ax.scatter(x[:end_point], y[:end_point], z[:end_point],
c=colors, cmap='plasma', s=30, alpha=0.8)
ax.plot(x[:end_point], y[:end_point], z[:end_point],
color='cyan', linewidth=3, alpha=0.9)
# Current position with glow effect
if end_point > 0:
current_idx = end_point - 1
# Multiple layers for glow effect
for size, alpha in [(200, 0.3), (150, 0.5), (100, 0.8)]:
ax.scatter(x[current_idx], y[current_idx], z[current_idx],
c='yellow', s=size, alpha=alpha, marker='o')
# Trail effect
trail_start = max(0, current_idx - 10)
if current_idx > trail_start:
trail_alpha = np.linspace(0.3, 1.0, current_idx - trail_start + 1)
for i, alpha in enumerate(trail_alpha):
idx = trail_start + i
ax.scatter(x[idx], y[idx], z[idx],
c='orange', s=60, alpha=alpha)
# Remaining route preview
if end_point < len(positions):
ax.plot(x[end_point:], y[end_point:], z[end_point:],
color='gray', linewidth=1, alpha=0.4, linestyle='--')
# Cinema-style labels and styling
ax.set_xlabel('East-West (m)', color='white', fontsize=14)
ax.set_ylabel('North-South (m)', color='white', fontsize=14)
ax.set_zlabel('Elevation (m)', color='white', fontsize=14)
# Progress and time info
progress_percent = (end_point / len(positions)) * 100
timestamp_str = timestamps[end_point-1] if end_point > 0 else "Start"
ax.set_title(f'CINEMA GPS JOURNEY\nProgress: {progress_percent:.1f}% • Point {end_point}/{len(positions)}{timestamp_str}',
color='white', fontsize=16, pad=20, weight='bold')
# Consistent view with cinematic angle
margin = max(np.ptp(x), np.ptp(y)) * 0.15
ax.set_xlim(np.min(x) - margin, np.max(x) + margin)
ax.set_ylim(np.min(y) - margin, np.max(y) + margin)
ax.set_zlim(np.min(z) - 20, np.max(z) + 20)
# Dynamic camera movement for cinematic effect
azim = 45 + (frame_idx * 0.5) % 360 # Slowly rotating view
ax.view_init(elev=25, azim=azim)
# Cinema-style grid
ax.grid(True, alpha=0.2, color='white')
ax.xaxis.pane.fill = False
ax.yaxis.pane.fill = False
ax.zaxis.pane.fill = False
# Make pane edges more subtle
ax.xaxis.pane.set_edgecolor('gray')
ax.yaxis.pane.set_edgecolor('gray')
ax.zaxis.pane.set_edgecolor('gray')
ax.xaxis.pane.set_alpha(0.1)
ax.yaxis.pane.set_alpha(0.1)
ax.zaxis.pane.set_alpha(0.1)
# Save high-quality frame
frame_path = os.path.join(frames_folder, f"cinema_frame_{frame_idx:04d}.png")
try:
plt.savefig(frame_path, dpi=150, bbox_inches='tight',
facecolor='black', edgecolor='none', format='png')
plt.close(fig)
if os.path.exists(frame_path) and os.path.getsize(frame_path) > 1024:
test_frame = cv2.imread(frame_path)
if test_frame is not None:
frame_files.append(frame_path)
if frame_idx == 0:
h, w, c = test_frame.shape
update_status(current_progress, f"Cinema quality: {w}x{h} at {fps} FPS")
except Exception as frame_error:
update_status(current_progress, f"Error creating frame {frame_idx}: {str(frame_error)}")
plt.close(fig)
continue
plt.style.use('default') # Reset style
# Create cinema video
if not frame_files:
raise Exception("No valid cinema frames were generated")
update_status(80, f"Creating cinema video from {len(frame_files)} frames...")
output_video_path = os.path.join(project_folder, f"{self.project_name}_cinema_3d_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4")
# Cinema video creation with higher quality
first_frame = cv2.imread(frame_files[0])
height, width, layers = first_frame.shape
# Try to create high-quality video
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
video_writer = cv2.VideoWriter(output_video_path, fourcc, fps, (width, height))
if video_writer.isOpened():
for i, frame_file in enumerate(frame_files):
frame = cv2.imread(frame_file)
if frame is not None:
video_writer.write(frame)
if i % 10 == 0:
progress = 80 + (i / len(frame_files)) * 8
update_status(progress, f"Encoding cinema frame {i+1}/{len(frame_files)}")
video_writer.release()
if os.path.exists(output_video_path) and os.path.getsize(output_video_path) > 1024:
update_status(90, "Cinema video created successfully")
output_path = output_video_path
else:
raise Exception("Cinema video creation failed")
else:
raise Exception("Could not initialize cinema video writer")
# Clean up frames
for frame_file in frame_files:
try:
os.remove(frame_file)
except:
pass
try:
os.rmdir(frames_folder)
except:
pass
update_status(100, "Cinema animation complete!")
def show_success(dt):
popup.dismiss()
self.show_success_popup(
"Blender Cinema Animation Complete!",
f"Your cinema-quality animation has been saved to:\n{output_path}",
"Cinema Animation Complete!",
f"Your cinema-quality animation has been saved to:\n{output_path}\n\nNote: Blender was not available, so advanced 3D cinema mode was used instead.",
output_path
)
@@ -323,9 +528,12 @@ class CreateAnimationScreen(Screen):
except Exception as e:
error_message = str(e)
print(f"DEBUG: Cinema animation error: {error_message}")
import traceback
traceback.print_exc()
def show_error(dt):
popup.dismiss()
self.show_error_popup("Blender Animation Error", error_message)
self.show_error_popup("Cinema Animation Error", error_message)
Clock.schedule_once(show_error, 0)

View File

@@ -1,97 +0,0 @@
#!/usr/bin/env python3
"""
Test script for Google Earth-style flythrough animation
"""
import os
import sys
sys.path.append('/home/pi/Desktop/traccar_animation')
from py_scripts.advanced_3d_generator import NavigationAnimationGenerator
from datetime import datetime
def test_google_earth_animation():
"""Test the new Google Earth flythrough animation"""
# Find a project with GPS data
projects_folder = "/home/pi/Desktop/traccar_animation/resources/projects"
if not os.path.exists(projects_folder):
print("Projects folder not found!")
return
# Look for projects
projects = [d for d in os.listdir(projects_folder) if os.path.isdir(os.path.join(projects_folder, d))]
if not projects:
print("No projects found!")
return
# Use the first project found
project_name = projects[0]
project_folder = os.path.join(projects_folder, project_name)
positions_file = os.path.join(project_folder, "positions.json")
if not os.path.exists(positions_file):
print(f"No positions.json found in project {project_name}")
return
print(f"Testing Google Earth animation with project: {project_name}")
# Create generator
generator = NavigationAnimationGenerator(project_folder)
# Check dependencies
try:
generator.check_dependencies()
print("✅ All dependencies available")
except Exception as e:
print(f"❌ Dependency error: {e}")
return
# Generate Google Earth-style animation
output_video = os.path.join(project_folder, f"{project_name}_google_earth_test_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4")
def progress_callback(progress, message):
print(f"Progress: {progress:.1f}% - {message}")
try:
print("Starting Google Earth flythrough generation...")
# Generate frames
frame_paths = generator.generate_frames(
positions_file,
style='google_earth',
progress_callback=progress_callback
)
if frame_paths and len(frame_paths) > 0:
print(f"✅ Generated {len(frame_paths)} frames")
# Create video
success = generator.create_video(
frame_paths,
output_video,
progress_callback=progress_callback
)
if success and os.path.exists(output_video):
print(f"✅ SUCCESS! Google Earth flythrough created: {output_video}")
# Get file size
file_size = os.path.getsize(output_video) / (1024 * 1024) # MB
print(f"📹 Video size: {file_size:.1f} MB")
# Clean up frames
generator.cleanup_frames()
else:
print("❌ Failed to create video from frames")
else:
print("❌ Failed to generate frames")
except Exception as e:
print(f"❌ Error during generation: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
test_google_earth_animation()

View File

@@ -1,69 +0,0 @@
#!/usr/bin/env python3
"""
Test script for progressive 3D animation function
"""
import os
import sys
sys.path.append('/home/pi/Desktop/traccar_animation')
def test_progressive_3d_animation():
"""Test the progressive 3D animation dependencies"""
print("Testing progressive 3D animation dependencies...")
try:
# Test matplotlib with 3D
import matplotlib
matplotlib.use('Agg') # Non-interactive backend
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
print("✅ Matplotlib with 3D support available")
# Test OpenCV (instead of MoviePy)
import cv2
print("✅ OpenCV available for video creation")
# Test numpy
import numpy as np
print("✅ NumPy available")
# Test basic 3D plot creation
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
# Create simple test data
x = np.array([0, 1, 2, 3, 4])
y = np.array([0, 1, 0, 1, 0])
z = np.array([0, 0, 1, 1, 2])
ax.plot(x, y, z, 'b-', linewidth=2)
ax.scatter(x, y, z, c='red', s=50)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Test 3D Plot')
# Save test plot
test_path = '/tmp/test_3d_plot.png'
plt.savefig(test_path, dpi=100, bbox_inches='tight')
plt.close(fig)
if os.path.exists(test_path):
print("✅ 3D plot creation and saving works")
os.remove(test_path)
else:
print("❌ Failed to create 3D plot")
except ImportError as e:
print(f"❌ Import error: {e}")
return False
except Exception as e:
print(f"❌ Error: {e}")
return False
print("🎉 All dependencies for progressive 3D animation are working!")
return True
if __name__ == "__main__":
test_progressive_3d_animation()

View File

@@ -1,202 +0,0 @@
#!/usr/bin/env python3
"""
Test script for progressive 3D animation with debugging
"""
import os
import sys
sys.path.append('/home/pi/Desktop/traccar_animation')
def test_progressive_animation_debug():
"""Test the progressive animation with a simple GPS dataset"""
print("Testing progressive 3D animation with debug output...")
# Find a project with GPS data
projects_folder = "/home/pi/Desktop/traccar_animation/resources/projects"
if not os.path.exists(projects_folder):
print("❌ Projects folder not found!")
return
# Look for projects
projects = [d for d in os.listdir(projects_folder) if os.path.isdir(os.path.join(projects_folder, d))]
if not projects:
print("❌ No projects found!")
return
# Use the first project found
project_name = projects[0]
project_folder = os.path.join(projects_folder, project_name)
positions_file = os.path.join(project_folder, "positions.json")
if not os.path.exists(positions_file):
print(f"❌ No positions.json found in project {project_name}")
return
print(f"✅ Testing with project: {project_name}")
try:
# Import the animation generation code
import json
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import cv2
from datetime import datetime
# Load GPS data
with open(positions_file, 'r') as f:
positions = json.load(f)
print(f"✅ Loaded {len(positions)} GPS points")
if len(positions) < 2:
print("❌ Need at least 2 GPS points")
return
# Test creating just 3 frames
test_frames_folder = os.path.join(project_folder, "test_frames")
os.makedirs(test_frames_folder, exist_ok=True)
# Extract coordinates
lats = np.array([pos['latitude'] for pos in positions[:10]]) # Just first 10 points
lons = np.array([pos['longitude'] for pos in positions[:10]])
alts = np.array([pos.get('altitude', 0) for pos in positions[:10]])
# Convert to relative coordinates
lat_center = np.mean(lats)
lon_center = np.mean(lons)
alt_min = np.min(alts)
x = (lons - lon_center) * 111320 * np.cos(np.radians(lat_center))
y = (lats - lat_center) * 110540
z = alts - alt_min
print(f"✅ Processed coordinates: x={x.min():.1f} to {x.max():.1f}, y={y.min():.1f} to {y.max():.1f}")
frame_files = []
# Create 3 test frames
for frame_idx in range(3):
end_point = (frame_idx + 1) * 3
end_point = min(end_point, len(x))
print(f"Creating frame {frame_idx + 1}, showing {end_point} points...")
# Create 3D plot
fig = plt.figure(figsize=(10, 8), dpi=100)
ax = fig.add_subplot(111, projection='3d')
# Plot route up to current point
if end_point > 1:
ax.plot(x[:end_point], y[:end_point], z[:end_point], 'b-', linewidth=2)
ax.scatter(x[:end_point], y[:end_point], z[:end_point], c='blue', s=20)
# Current position
if end_point > 0:
current_idx = end_point - 1
ax.scatter(x[current_idx], y[current_idx], z[current_idx],
c='red', s=100, marker='o')
# Remaining route
if end_point < len(x):
ax.plot(x[end_point:], y[end_point:], z[end_point:],
'lightgray', linewidth=1, alpha=0.3)
ax.set_xlabel('East-West (m)')
ax.set_ylabel('North-South (m)')
ax.set_zlabel('Elevation (m)')
ax.set_title(f'Test Frame {frame_idx + 1} - Point {end_point}/{len(x)}')
# Set view
margin = max(np.ptp(x), np.ptp(y)) * 0.1 if np.ptp(x) > 0 else 100
ax.set_xlim(np.min(x) - margin, np.max(x) + margin)
ax.set_ylim(np.min(y) - margin, np.max(y) + margin)
ax.set_zlim(np.min(z) - 10, np.max(z) + 10)
ax.view_init(elev=20, azim=45)
ax.grid(True)
# Save frame
frame_path = os.path.join(test_frames_folder, f"test_frame_{frame_idx:03d}.png")
try:
plt.savefig(frame_path, dpi=100, bbox_inches='tight',
facecolor='white', edgecolor='none', format='png')
plt.close(fig)
# Check frame
if os.path.exists(frame_path):
file_size = os.path.getsize(frame_path)
print(f"✅ Frame {frame_idx + 1} saved: {file_size} bytes")
# Test OpenCV reading
test_img = cv2.imread(frame_path)
if test_img is not None:
h, w, c = test_img.shape
print(f"✅ Frame {frame_idx + 1} readable by OpenCV: {w}x{h}")
frame_files.append(frame_path)
else:
print(f"❌ Frame {frame_idx + 1} not readable by OpenCV")
else:
print(f"❌ Frame {frame_idx + 1} not created")
except Exception as e:
print(f"❌ Error creating frame {frame_idx + 1}: {e}")
plt.close(fig)
print(f"Created {len(frame_files)} valid frames")
# Test video creation
if frame_files:
output_video = os.path.join(project_folder, f"test_progressive_{datetime.now().strftime('%H%M%S')}.mp4")
# Read first frame for dimensions
first_frame = cv2.imread(frame_files[0])
height, width, layers = first_frame.shape
print(f"Video dimensions: {width}x{height}")
# Create video
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
video_writer = cv2.VideoWriter(output_video, fourcc, 2.0, (width, height))
if video_writer.isOpened():
for i, frame_file in enumerate(frame_files):
frame = cv2.imread(frame_file)
if frame is not None:
video_writer.write(frame)
print(f"✅ Added frame {i+1} to video")
else:
print(f"❌ Could not read frame {i+1}")
video_writer.release()
if os.path.exists(output_video):
file_size = os.path.getsize(output_video)
print(f"✅ Video created: {output_video} ({file_size} bytes)")
else:
print("❌ Video file not created")
else:
print("❌ Could not open video writer")
# Clean up
for frame_file in frame_files:
try:
os.remove(frame_file)
except:
pass
try:
os.rmdir(test_frames_folder)
except:
pass
except Exception as e:
print(f"❌ Error: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
test_progressive_animation_debug()

View File

@@ -1,126 +0,0 @@
#!/usr/bin/env python3
"""
Test script for video creation functionality
"""
import os
import sys
sys.path.append('/home/pi/Desktop/traccar_animation')
import cv2
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
def test_video_creation():
"""Test video creation with sample frames"""
print("Testing video creation functionality...")
# Create test directory
test_dir = "/tmp/video_test"
os.makedirs(test_dir, exist_ok=True)
try:
# Create sample frames
frame_files = []
for i in range(10):
# Create a simple test plot
fig, ax = plt.subplots(figsize=(8, 6))
# Simple animation - moving dot
x = np.linspace(0, 10, 100)
y = np.sin(x + i * 0.5)
ax.plot(x, y, 'b-', linewidth=2)
ax.scatter([i], [np.sin(i * 0.5)], c='red', s=100)
ax.set_xlim(0, 10)
ax.set_ylim(-2, 2)
ax.set_title(f'Test Frame {i+1}/10')
ax.grid(True)
# Save frame
frame_path = os.path.join(test_dir, f"frame_{i:03d}.png")
plt.savefig(frame_path, dpi=100, bbox_inches='tight')
plt.close(fig)
frame_files.append(frame_path)
print(f"Created frame {i+1}/10")
print(f"Created {len(frame_files)} test frames")
# Test video creation with different codecs
codecs_to_test = [
('mp4v', '.mp4'),
('XVID', '.avi'),
('MJPG', '.avi')
]
for codec, ext in codecs_to_test:
try:
output_path = os.path.join(test_dir, f"test_video_{codec}{ext}")
# Read first frame for dimensions
first_frame = cv2.imread(frame_files[0])
if first_frame is None:
print(f"❌ Could not read first frame")
continue
height, width, layers = first_frame.shape
print(f"Frame dimensions: {width}x{height}")
# Create video writer
fourcc = cv2.VideoWriter_fourcc(*codec)
video_writer = cv2.VideoWriter(output_path, fourcc, 5.0, (width, height))
if not video_writer.isOpened():
print(f"❌ Could not open video writer with {codec}")
continue
# Write frames
frames_written = 0
for frame_file in frame_files:
frame = cv2.imread(frame_file)
if frame is not None:
video_writer.write(frame)
frames_written += 1
video_writer.release()
# Check result
if os.path.exists(output_path):
file_size = os.path.getsize(output_path)
if file_size > 1024: # At least 1KB
print(f"{codec} video created: {output_path} ({file_size} bytes, {frames_written} frames)")
else:
print(f"{codec} video too small: {file_size} bytes")
else:
print(f"{codec} video not created")
except Exception as e:
print(f"❌ Error with {codec}: {e}")
# Check OpenCV version and capabilities
print(f"\nOpenCV version: {cv2.__version__}")
print(f"OpenCV build info available: {hasattr(cv2, 'getBuildInformation')}")
except Exception as e:
print(f"❌ Error: {e}")
import traceback
traceback.print_exc()
finally:
# Clean up
for frame_file in frame_files:
try:
os.remove(frame_file)
except:
pass
try:
os.rmdir(test_dir)
except:
pass
if __name__ == "__main__":
test_video_creation()