1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import math
from collections import defaultdict
 
def analyze_speeds(filepath):
    print(f"Analyzing speeds in {filepath}...")
    
    state_data = defaultdict(list)
    
    prev_x = None
    prev_y = None
    prev_time = None
    prev_heading = None
    
    with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
        lines = f.readlines()
        
    for line in lines:
        line = line.strip()
        if not line.startswith('$CAL'):
            continue
            
        parts = line.split(',')
        if len(parts) < 10:
            continue
            
        try:
            time_ms = int(parts[2])
            state = parts[3]
            pwm_thr = int(parts[4])
            pwm_str = int(parts[5])
            x = float(parts[6])
            y = float(parts[7])
            heading = float(parts[9])
            
            if prev_x is not None and prev_y is not None:
                dx = x - prev_x
                dy = y - prev_y
                dist = math.sqrt(dx*dx + dy*dy)
                dt = (time_ms - prev_time) / 1000.0
                
                if dt > 0:
                    speed = dist / dt
                    
                    # Calculate yaw rate
                    d_head = heading - prev_heading
                    if d_head > 180: d_head -= 360
                    if d_head < -180: d_head += 360
                    yaw_rate = d_head / dt # deg/s
                    
                    if 0 < dt < 0.5: 
                        state_data[state].append({
                            'speed': speed,
                            'yaw_rate': yaw_rate,
                            'pwm_thr': pwm_thr,
                            'pwm_str': pwm_str,
                            'heading': heading
                        })
            
            prev_x = x
            prev_y = y
            prev_time = time_ms
            prev_heading = heading
            
        except ValueError:
            continue
 
    print("\n=== Average Speeds per State ===")
    sorted_states = sorted(state_data.keys())
    
    for state in sorted_states:
        if 'REST' in state or 'IDLE' in state or 'BRAKE' in state or 'WARMUP' in state:
            continue
            
        speeds = [d['speed'] for d in state_data[state]]
        yaw_rates = [d['yaw_rate'] for d in state_data[state]]
        pwms_t = [d['pwm_thr'] for d in state_data[state]]
        # pwm_str is 6th column in log, but 4th in parts (0-based index: 0=$CAL, 1=cnt, 2=time, 3=state, 4=thr, 5=str)
        # Wait, in the code: pwm_thr = int(parts[4]), pwm_str = int(parts[5])
        pwms_s = [d['pwm_str'] for d in state_data[state]]
        
        if not speeds:
            continue
            
        avg_speed = sum(speeds) / len(speeds)
        avg_yaw = sum(yaw_rates) / len(yaw_rates)
        avg_pwm_t = sum(pwms_t) / len(pwms_t)
        avg_pwm_s = sum(pwms_s) / len(pwms_s)
        count = len(speeds)
        
        print(f"{state:<15} | Thr: {avg_pwm_t:.0f} | Str: {avg_pwm_s:.0f} | Speed: {avg_speed:.3f} m/s | Yaw: {avg_yaw:.3f} deg/s | N: {count}")
 
if __name__ == "__main__":
    analyze_speeds("python/calibration_20251205_105312.log")