|
|
from models.TD3.TD3 import TD3 |
|
|
|
|
|
import torch |
|
|
import numpy as np |
|
|
from sim import SIM_ENV |
|
|
import yaml |
|
|
import gradio as gr |
|
|
import os |
|
|
from pathlib import Path |
|
|
import matplotlib |
|
|
import random |
|
|
|
|
|
matplotlib.use('Agg') |
|
|
|
|
|
def generate_random_points(num_scenarios=2): |
|
|
"""Generate random robot poses and goals""" |
|
|
robot_poses = [] |
|
|
robot_goals = [] |
|
|
|
|
|
for _ in range(num_scenarios): |
|
|
|
|
|
pose = [ |
|
|
[random.uniform(1, 9)], |
|
|
[random.uniform(1, 9)], |
|
|
[random.uniform(0, 3.14)], |
|
|
[0] |
|
|
] |
|
|
|
|
|
|
|
|
goal = [ |
|
|
[random.uniform(1, 9)], |
|
|
[random.uniform(1, 9)], |
|
|
[0] |
|
|
] |
|
|
|
|
|
robot_poses.append(pose) |
|
|
robot_goals.append(goal) |
|
|
|
|
|
return robot_poses, robot_goals |
|
|
|
|
|
def get_predefined_scenarios(): |
|
|
"""Return predefined robot poses and goals""" |
|
|
robot_poses = [ |
|
|
[[3], [4], [0], [0]], |
|
|
[[8], [1], [1], [0]], |
|
|
[[2], [6], [1], [0]], |
|
|
[[7], [1], [0], [0]], |
|
|
[[7], [6.5], [2], [0]], |
|
|
[[9], [9], [3], [0]], |
|
|
[[2], [9], [1], [0]], |
|
|
[[3], [6], [3], [0]], |
|
|
[[1], [7], [0], [0]], |
|
|
[[5], [7], [3], [0]] |
|
|
] |
|
|
|
|
|
robot_goals = [ |
|
|
[[8], [8], [0]], |
|
|
[[2], [9], [0]], |
|
|
[[7], [1], [0]], |
|
|
[[7.2], [9], [0]], |
|
|
[[1], [1], [0]], |
|
|
[[5], [1], [0]], |
|
|
[[7], [4], [0]], |
|
|
[[9], [4], [0]], |
|
|
[[1], [9], [0]], |
|
|
[[5], [1], [0]] |
|
|
] |
|
|
|
|
|
return robot_poses, robot_goals |
|
|
|
|
|
def run_simulation(): |
|
|
"""Run the simulation and return the path to the generated GIF""" |
|
|
action_dim = 2 |
|
|
max_action = 1 |
|
|
state_dim = 25 |
|
|
device = torch.device( |
|
|
"cuda" if torch.cuda.is_available() else "cpu" |
|
|
) |
|
|
epoch = 0 |
|
|
max_steps = 300 |
|
|
|
|
|
model = TD3( |
|
|
state_dim=state_dim, |
|
|
action_dim=action_dim, |
|
|
max_action=max_action, |
|
|
device=device, |
|
|
load_model=True, |
|
|
) |
|
|
|
|
|
sim = SIM_ENV(world_file="eval_world.yaml", save_ani=True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
all_poses, all_goals = get_predefined_scenarios() |
|
|
scenario_index = random.randint(0, len(all_poses) - 1) |
|
|
|
|
|
robot_poses = [all_poses[scenario_index]] |
|
|
robot_goals = [all_goals[scenario_index]] |
|
|
|
|
|
print(f"Selected scenario {scenario_index+1} of {len(all_poses)}") |
|
|
total_reward = 0.0 |
|
|
total_steps = 0 |
|
|
col = 0 |
|
|
goals = 0 |
|
|
for idx in range(len(robot_poses)): |
|
|
count = 0 |
|
|
latest_scan, distance, cos, sin, collision, goal, a, reward = sim.reset( |
|
|
robot_state=robot_poses[idx], |
|
|
robot_goal=robot_goals[idx], |
|
|
random_obstacles=False, |
|
|
) |
|
|
done = False |
|
|
while not done and count < max_steps: |
|
|
state, terminal = model.prepare_state( |
|
|
latest_scan, distance, cos, sin, collision, goal, a |
|
|
) |
|
|
action = model.get_action(np.array(state), False) |
|
|
a_in = [(action[0] + 1) / 4, action[1]] |
|
|
latest_scan, distance, cos, sin, collision, goal, a, reward = sim.step( |
|
|
lin_velocity=a_in[0], ang_velocity=a_in[1] |
|
|
) |
|
|
total_reward += reward |
|
|
total_steps += 1 |
|
|
count += 1 |
|
|
if collision: |
|
|
col += 1 |
|
|
if goal: |
|
|
goals += 1 |
|
|
done = collision or goal |
|
|
avg_step_reward = total_reward / total_steps |
|
|
avg_reward = total_reward / len(robot_poses) |
|
|
avg_col = col / len(robot_poses) |
|
|
avg_goal = goals / len(robot_poses) |
|
|
print(f"Total Reward: {total_reward}") |
|
|
print(f"Average Reward: {avg_reward}") |
|
|
print(f"Average Step Reward: {avg_step_reward}") |
|
|
print(f"Average Collision rate: {avg_col}") |
|
|
print(f"Average Goal rate: {avg_goal}") |
|
|
print("..............................................") |
|
|
model.writer.add_scalar("test/total_reward", total_reward, epoch) |
|
|
model.writer.add_scalar("test/avg_reward", avg_reward, epoch) |
|
|
model.writer.add_scalar("test/avg_step_reward", avg_step_reward, epoch) |
|
|
model.writer.add_scalar("test/avg_col", avg_col, epoch) |
|
|
model.writer.add_scalar("test/avg_goal", avg_goal, epoch) |
|
|
|
|
|
sim.env.end(ending_time=3) |
|
|
|
|
|
|
|
|
animation_dir = Path("animation") |
|
|
if animation_dir.exists(): |
|
|
gif_files = list(animation_dir.glob("*.gif")) |
|
|
if gif_files: |
|
|
|
|
|
latest_gif = max(gif_files, key=lambda x: x.stat().st_ctime) |
|
|
return str(latest_gif), { |
|
|
"Total Reward": f"{total_reward:.2f}", |
|
|
"Average Reward": f"{avg_reward:.2f}", |
|
|
"Average Step Reward": f"{avg_step_reward:.2f}", |
|
|
"Collision Rate": f"{avg_col:.2f}", |
|
|
"Goal Rate": f"{avg_goal:.2f}" |
|
|
} |
|
|
|
|
|
return None, {"Error": "No GIF file was generated"} |
|
|
|
|
|
def get_default_data(): |
|
|
"""Return default animation and statistics data""" |
|
|
|
|
|
animation_dir = Path("animation") |
|
|
default_gif = None |
|
|
|
|
|
if animation_dir.exists(): |
|
|
gif_files = list(animation_dir.glob("*.gif")) |
|
|
if gif_files: |
|
|
|
|
|
default_gif = str(max(gif_files, key=lambda x: x.stat().st_ctime)) |
|
|
|
|
|
|
|
|
default_stats = { |
|
|
"Total Reward": "99.12", |
|
|
"Average Reward": "99.12", |
|
|
"Average Step Reward": "1.40", |
|
|
"Collision Rate": "0.00", |
|
|
"Goal Rate": "1.00" |
|
|
} |
|
|
|
|
|
return default_gif, default_stats |
|
|
|
|
|
def main(args=None): |
|
|
"""Main function with Gradio interface""" |
|
|
|
|
|
default_gif, default_stats = get_default_data() |
|
|
|
|
|
with gr.Blocks(title="Robot Navigation Simulation") as demo: |
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
run_button = gr.Button("Run Simulation", variant="primary") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
output_image = gr.Image( |
|
|
type="filepath", |
|
|
label="Simulation Animation", |
|
|
value=default_gif |
|
|
) |
|
|
|
|
|
with gr.Column(): |
|
|
output_stats = gr.JSON( |
|
|
label="Simulation Statistics", |
|
|
value=default_stats |
|
|
) |
|
|
|
|
|
run_button.click( |
|
|
fn=run_simulation, |
|
|
outputs=[output_image, output_stats] |
|
|
) |
|
|
|
|
|
demo.launch(share=False) |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |