File size: 5,254 Bytes
37d995a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import json
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

# --- 配置 ---
import json
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# --- 配置 ---
import json
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# --- 配置 ---
# ------------
file_path = 'data_inference/inference_reward_record_20260104_105636/episode_0001/data.jsonl'  # 你的文件名

def visualize_trajectory(filename):
    timestamps = []
    # 假设 states 有两个列表,分别对应 state 0 和 state 1
    states_0 = []
    states_1 = []
    # Actions 分别对应 left 和 right
    actions_left = []
    actions_right = []
    # Grippers
    gripper_left = []
    gripper_right = []
    LIMIT = 100
    print(f"正在读取文件: {filename} ...")
    try:
        count = 0
        with open(filename, 'r') as f:
            for line in f:
                d = json.loads(line)
                timestamps.append(d['timestamp'])
                
                # 提取 State 的前3个值 (XYZ)
                # 注意:根据您的数据结构,states是一个包含两个列表的列表
                # 这里假设 states[0] 和 states[1] 分别对应两个实体的状态
                states_0.append(d['states'][0][:3])
                states_1.append(d['states'][1][:3])
                
                # 提取 Action 的前3个值 (XYZ)
                actions_left.append(d['actions']['left_arm']['pose'][:3])
                actions_right.append(d['actions']['right_arm']['pose'][:3])
                
                # 提取 Gripper
                gripper_left.append(d['actions']['left_gripper'][0])
                gripper_right.append(d['actions']['right_gripper'][0])
                count += 1
                if count > LIMIT:
                    break
    except FileNotFoundError:
        print(f"错误: 找不到文件 {filename}。请确保文件在当前目录下或路径正确。")
        return

    # 转换为 numpy 数组方便处理
    timestamps = np.array(timestamps)
    # 将时间戳转换为相对时间(从0开始)
    rel_time = timestamps - timestamps[0]
    
    states_0 = np.array(states_0)
    states_1 = np.array(states_1)
    actions_left = np.array(actions_left)
    actions_right = np.array(actions_right)
    gripper_left = np.array(gripper_left)
    gripper_right = np.array(gripper_right)

    # 1. 绘制 XYZ 分量对比图 (State vs Action)
    fig1, axes = plt.subplots(3, 1, figsize=(12, 10), sharex=True)
    labels = ['X', 'Y', 'Z']
    
    for i in range(3):
        # 绘制 State
        axes[i].plot(rel_time, states_0[:, i], label='State[0]', linestyle='--', alpha=0.7)
        axes[i].plot(rel_time, states_1[:, i], label='State[1]', linestyle='--', alpha=0.7)
        # 绘制 Action
        axes[i].plot(rel_time, actions_left[:, i], label='Action Left', linewidth=1.5)
        axes[i].plot(rel_time, actions_right[:, i], label='Action Right', linewidth=1.5)
        
        axes[i].set_ylabel(f'{labels[i]} (m)')
        axes[i].grid(True, alpha=0.3)
        if i == 0:
            axes[i].legend(loc='upper right')
            axes[i].set_title('XYZ Position: State vs Action')

    axes[2].set_xlabel('Time (s)')
    plt.tight_layout()
    plt.savefig('1_xyz_comparison.png')
    print("已保存: 1_xyz_comparison.png")

    # 2. 绘制 3D 轨迹图
    fig2 = plt.figure(figsize=(10, 8))
    ax = fig2.add_subplot(111, projection='3d')

    # 为了图表清晰,这里只画出轨迹,不画时间点
    ax.plot(states_0[:, 0], states_0[:, 1], states_0[:, 2], label='State[0]', linestyle='--')
    ax.plot(states_1[:, 0], states_1[:, 1], states_1[:, 2], label='State[1]', linestyle='--')
    ax.plot(actions_left[:, 0], actions_left[:, 1], actions_left[:, 2], label='Action Left')
    ax.plot(actions_right[:, 0], actions_right[:, 1], actions_right[:, 2], label='Action Right')

    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')
    ax.set_title('3D Trajectories')
    ax.legend()
    plt.savefig('2_3d_trajectory.png')
    print("已保存: 2_3d_trajectory.png")

    # 3. 绘制 Gripper 状态
    plt.figure(figsize=(12, 4))
    plt.plot(rel_time, gripper_left, label='Left Gripper')
    plt.plot(rel_time, gripper_right, label='Right Gripper')
    plt.xlabel('Time (s)')
    plt.ylabel('Value')
    plt.title('Gripper State')
    plt.legend()
    plt.grid(True, alpha=0.3)
    plt.savefig('3_gripper.png')
    print("已保存: 3_gripper.png")

    # 4. 绘制 Timestamp 频率 (Delta Time)
    plt.figure(figsize=(12, 4))
    dt = np.diff(timestamps)
    # 移除异常大的跳跃点以便观察(可选)
    # dt = dt[dt < 0.5] 
    
    plt.plot(rel_time[1:], dt, marker='.', linestyle='-', linewidth=0.5, markersize=3)
    mean_dt = np.mean(dt)
    freq = 1.0 / mean_dt if mean_dt > 0 else 0
    
    plt.xlabel('Time (s)')
    plt.ylabel('Delta Time (s)')
    plt.title(f'Control Frequency Stability (Mean dt: {mean_dt:.4f}s, ~{freq:.1f} Hz)')
    plt.grid(True, alpha=0.3)
    plt.savefig('4_frequency.png')
    print("已保存: 4_frequency.png")

    plt.show()

if __name__ == "__main__":
    visualize_trajectory(file_path)