122 lines
4.5 KiB
Python
122 lines
4.5 KiB
Python
import time
|
|
import logger
|
|
import pandas as pd
|
|
import matplotlib.pyplot as plt
|
|
import matplotlib.animation as animation
|
|
|
|
# ✅ Configure Logging for Graphing Module
|
|
LOGGING_ENABLED = True
|
|
|
|
if LOGGING_ENABLED:
|
|
logging.basicConfig(
|
|
filename="graphing.log",
|
|
level=logging.DEBUG,
|
|
format="%(asctime)s [%(levelname)s] %(message)s",
|
|
datefmt="%d-%m-%Y %H:%M:%S"
|
|
)
|
|
|
|
class RSIGraphing:
|
|
"""Handles real-time and CSV-based graphing for RSI analysis."""
|
|
|
|
def __init__(self, csv_file=None):
|
|
"""Initialize graphing for real-time plotting or CSV replay."""
|
|
self.csv_file = csv_file
|
|
self.fig, self.ax = plt.subplots(1, 2, figsize=(12, 5)) # ✅ Two subplots: Time-Series & X-Y Trajectory
|
|
|
|
# ✅ Titles and Labels
|
|
self.ax[0].set_title("Real-Time Position Tracking")
|
|
self.ax[0].set_xlabel("Time")
|
|
self.ax[0].set_ylabel("Position (mm)")
|
|
self.ax[1].set_title("2D Trajectory (X-Y)")
|
|
self.ax[1].set_xlabel("X Position")
|
|
self.ax[1].set_ylabel("Y Position")
|
|
|
|
# ✅ Data storage for plotting
|
|
self.time_data = []
|
|
self.x_data, self.y_data, self.z_data = [], [], []
|
|
self.actual_x, self.actual_y, self.actual_z = [], [], []
|
|
self.trajectory_x, self.trajectory_y = [], []
|
|
|
|
self.plot_mode = "TCP" # ✅ Toggle between "TCP" and "Joints"
|
|
|
|
if csv_file:
|
|
self.load_csv_log(csv_file)
|
|
self.plot_csv_data()
|
|
else:
|
|
self.ani = animation.FuncAnimation(self.fig, self.update_graph, interval=500, save_count=100)
|
|
|
|
plt.show()
|
|
|
|
def update_graph(self, frame):
|
|
"""Update the live graph with new position data."""
|
|
timestamp = time.strftime("%H:%M:%S")
|
|
self.time_data.append(timestamp)
|
|
|
|
# ✅ Simulated Data for Testing (Replace with real-time data)
|
|
self.x_data.append(len(self.time_data) * 10)
|
|
self.y_data.append(len(self.time_data) * 5)
|
|
self.z_data.append(len(self.time_data) * 2)
|
|
|
|
self.actual_x.append(len(self.time_data) * 9.8)
|
|
self.actual_y.append(len(self.time_data) * 4.9)
|
|
self.actual_z.append(len(self.time_data) * 1.8)
|
|
|
|
# ✅ 2D Trajectory (X-Y)
|
|
self.trajectory_x.append(len(self.time_data) * 9.8)
|
|
self.trajectory_y.append(len(self.time_data) * 4.9)
|
|
|
|
# ✅ Clear and replot data
|
|
self.ax[0].clear()
|
|
self.ax[0].plot(self.time_data, self.x_data, label="Planned X", linestyle="dashed")
|
|
self.ax[0].plot(self.time_data, self.y_data, label="Planned Y", linestyle="dashed")
|
|
self.ax[0].plot(self.time_data, self.z_data, label="Planned Z", linestyle="dashed")
|
|
|
|
self.ax[0].plot(self.time_data, self.actual_x, label="Actual X", marker="o")
|
|
self.ax[0].plot(self.time_data, self.actual_y, label="Actual Y", marker="o")
|
|
self.ax[0].plot(self.time_data, self.actual_z, label="Actual Z", marker="o")
|
|
|
|
self.ax[0].legend()
|
|
self.ax[0].set_title(f"Real-Time {self.plot_mode} Position")
|
|
self.ax[0].set_xlabel("Time")
|
|
self.ax[0].set_ylabel("Position (mm)")
|
|
|
|
# ✅ 2D Trajectory (X-Y)
|
|
self.ax[1].clear()
|
|
self.ax[1].plot(self.trajectory_x, self.trajectory_y, label="Actual Path", marker="o")
|
|
self.ax[1].set_title("2D Trajectory (X-Y)")
|
|
self.ax[1].set_xlabel("X Position")
|
|
self.ax[1].set_ylabel("Y Position")
|
|
self.ax[1].legend()
|
|
|
|
def load_csv_log(self, filename):
|
|
"""Load a CSV log and replay motion."""
|
|
df = pd.read_csv(filename)
|
|
self.time_data = df["Timestamp"].tolist()
|
|
self.trajectory_x = df["Receive.RIst.X"].tolist()
|
|
self.trajectory_y = df["Receive.RIst.Y"].tolist()
|
|
|
|
logging.info(f"Loaded CSV log: {filename}")
|
|
|
|
def plot_csv_data(self):
|
|
"""Plot data from a CSV file for post-analysis."""
|
|
plt.figure(figsize=(10, 5))
|
|
plt.plot(self.trajectory_x, self.trajectory_y, label="Planned Path", linestyle="dashed")
|
|
plt.scatter(self.trajectory_x, self.trajectory_y, color='red', label="Actual Path", marker="o")
|
|
plt.title("CSV Replay: 2D Trajectory (X-Y)")
|
|
plt.xlabel("X Position")
|
|
plt.ylabel("Y Position")
|
|
plt.legend()
|
|
plt.show()
|
|
|
|
if __name__ == "__main__":
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(description="RSI Graphing Utility")
|
|
parser.add_argument("--csv", help="Path to CSV file for replay mode", type=str)
|
|
args = parser.parse_args()
|
|
|
|
if args.csv:
|
|
RSIGraphing(csv_file=args.csv)
|
|
else:
|
|
RSIGraphing() # Run in live mode if no CSV is provided
|