diff --git a/guided_mrmp/controllers/multi_mpc.py b/guided_mrmp/controllers/multi_mpc.py
index f589655192b21a652ab8d824064853f0a61f4e82..2295bb548c2a9ee08c5b8f98892eac0ce6dff073 100644
--- a/guided_mrmp/controllers/multi_mpc.py
+++ b/guided_mrmp/controllers/multi_mpc.py
@@ -5,7 +5,7 @@ from guided_mrmp.controllers.optimizer import Optimizer
 np.seterr(divide="ignore", invalid="ignore")
 
 class MultiMPC:
-    def __init__(self, num_robots, model, T, DT, state_cost, final_state_cost, input_cost, input_rate_cost, settings, circle_obs):
+    def __init__(self, num_robots, model, T, DT, settings, circle_obs):
         """
         Initializes the MPC controller.
         """
@@ -19,6 +19,11 @@ class MultiMPC:
 
         self.circle_obs = circle_obs
 
+        state_cost = settings['model_predictive_controller']['Q']  # state error cost
+        final_state_cost = settings['model_predictive_controller']['Qf']  # state final error cost
+        input_cost = settings['model_predictive_controller']['R']  # input cost
+        input_rate_cost = settings['model_predictive_controller']['P']  # input rate of change cost
+
         # how far we can look into the future divided by our dt 
         # is the number of control intervals
         self.control_horizon = int(T / DT) 
@@ -33,10 +38,14 @@ class MultiMPC:
         self.R = np.diag(input_cost)
         self.P = np.diag(input_rate_cost)
 
-        self.acceptable_tol = settings['acceptable_tol']
-        self.acceptable_iter = settings['acceptable_iter']
-        self.print_level = settings['print_level']
-        self.print_time = settings['print_time']
+        # Optimization settings
+        self.robot_robot_collision_weight = settings['model_predictive_controller']['robot_robot_collision_weight']
+        self.obstacle_collision_weight = settings['model_predictive_controller']['obstacle_collision_weight']
+        self.acceptable_tol = settings['model_predictive_controller']['acceptable_tol']
+        self.acceptable_iter = settings['model_predictive_controller']['acceptable_iter']
+        self.print_level = settings['model_predictive_controller']['print_level']
+        self.print_time = settings['model_predictive_controller']['print_time']
+
 
     def apply_quadratic_barrier(self, d_max, d, c):
         """
@@ -131,7 +140,7 @@ class MultiMPC:
                     d = ca.sqrt(d)
                     obstacle_cost += self.apply_quadratic_barrier(6*self.robot_radius, d-self.robot_radius*2, 1)
 
-        opti.minimize(cost + .5*dist_to_other_robots + .5*obstacle_cost)
+        opti.minimize(cost + self.robot_robot_collision_weight*dist_to_other_robots + self.obstacle_collision_weight*obstacle_cost)
 
         # Constraints
         for i in range(self.num_robots):
diff --git a/guided_mrmp/controllers/multi_path_tracking.py b/guided_mrmp/controllers/multi_path_tracking.py
index ab5c28d3fe22d0b2eeda8300185e9278bebf5bd6..2ac036eba608a858a09d0f6f529a87f1faf7d815 100644
--- a/guided_mrmp/controllers/multi_path_tracking.py
+++ b/guided_mrmp/controllers/multi_path_tracking.py
@@ -18,7 +18,6 @@ class MultiPathTracker:
         """
         # State of the robot [x,y, heading]
         self.env = env
-
         self.states = initial_positions
         self.num_robots = len(initial_positions)
         self.dynamics = dynamics
@@ -37,25 +36,14 @@ class MultiPathTracker:
 
         self.K = int(T / DT)
 
-        # For a car model 
-        # Q = [20, 20, 10, 20]  # state error cost
-        # Qf = [30, 30, 30, 30]  # state final error cost
-        # R = [10, 10]  # input cost
-        # P = [10, 10]  # input rate of change cost
-        # self.mpc = MPC(VehicleModel(), T, DT, Q, Qf, R, P)
-
         # libraries for the discrete solver
         self.lib_2x3 = lib_2x3
         self.lib_3x3 = lib_3x3
         self.lib_2x5 = lib_2x5
 
+        self.settings = settings
 
-        # For a circular robot (easy dynamics)
-        Q = settings['model_predictive_controller']['Q']  # state error cost
-        Qf = settings['model_predictive_controller']['Qf']  # state final error cost
-        R = settings['model_predictive_controller']['R']  # input cost
-        P = settings['model_predictive_controller']['P']  # input rate of change cost
-        self.mpc = MultiMPC(self.num_robots, dynamics, T, DT, Q, Qf, R, P, settings['model_predictive_controller'], settings['environment']['circle_obstacles'])
+        self.mpc = MultiMPC(self.num_robots, dynamics, T, DT, settings, settings['environment']['circle_obstacles'])
 
         self.circle_obs = settings['environment']['circle_obstacles']
 
@@ -80,7 +68,6 @@ class MultiPathTracker:
         self.optimized_trajectories_hist = [ [] for _ in range(self.num_robots) ]
         self.optimized_trajectory = None
 
-
     def trajectories_overlap(self, traj1, traj2, threshold):
         """
         Checks if two trajectories overlap. We only care about xy positions.
@@ -99,7 +86,6 @@ class MultiPathTracker:
                     return True
         return False
     
-
     def ego_to_global_roomba(self, state, mpc_out):
         """
         Transforms optimized trajectory XY points from ego (robot) reference
@@ -134,7 +120,7 @@ class MultiPathTracker:
 
         return trajectory
     
-    def advance(self, state, show_plots=False):
+    def advance(self, screen, state, show_plots=False):
         # optimization loop
         # start=time.time()
 
@@ -142,8 +128,16 @@ class MultiPathTracker:
         # 1. Get the reference trajectory for each robot
         targets = []
         for i in range(self.num_robots):
-            targets.append(get_ref_trajectory(np.array(state[i]), np.array(self.paths[i]), self.target_v, self.T, self.DT, len(self.x_history[i])+1))
+            ref, visited_guide_points = get_ref_trajectory(np.array(state[i]), 
+                                                           np.array(self.paths[i]), 
+                                                           self.target_v, 
+                                                           self.T, 
+                                                           self.DT, 
+                                                           [])
+            
+            self.visited_points_on_guide_paths[i] = visited_guide_points
 
+            targets.append(ref)
         # dynamycs w.r.t robot frame
         # curr_state = np.array([0, 0, self.state[2], 0])
         curr_states = np.zeros((self.num_robots, 3))
@@ -162,7 +156,6 @@ class MultiPathTracker:
 
         return x_mpc, self.control
     
-
     def done(self):
         for i in range(self.num_robots):
             # print(f"state = {self.states[i]}")
@@ -183,6 +176,11 @@ class MultiPathTracker:
         # x_history, y_history, and h_history
         colors = cm.rainbow(np.linspace(0, 1, self.num_robots))
 
+        # plot the obstacles
+        for obs in self.circle_obs:
+            circle1 = plt.Circle((obs[0], obs[1]), obs[2], color='k', fill=True)
+            plt.gca().add_artist(circle1)
+
         for i in range(self.num_robots):
             plot_roomba(self.x_history[i][-1], self.y_history[i][-1], self.h_history[i][-1], colors[i], False, self.radius)
 
@@ -195,7 +193,7 @@ class MultiPathTracker:
 
         # plot the ref path of each robot
         for i in range(self.num_robots):
-            plt.plot(self.paths[i][0, :], self.paths[i][1, :], '--', color=colors[i])
+            plt.plot(self.paths[i][0, :], self.paths[i][1, :], 'o-', color=colors[i], alpha=0.5)
 
 
         # set the size of the plot to be 10x10
@@ -250,10 +248,6 @@ class MultiPathTracker:
                 self.x_history[i].append(self.states[i, 0])
                 self.y_history[i].append(self.states[i, 1])
                 self.h_history[i].append(self.states[i, 2])
-            
-            if self.update_ref_paths:
-                self.update_reference_paths()
-                self.update_ref_paths = False            
 
             # use the optimizer output to preview the predicted state trajectory
             # self.optimized_trajectory = self.ego_to_global(x_mpc.value)
diff --git a/guided_mrmp/controllers/multi_path_tracking_db.py b/guided_mrmp/controllers/multi_path_tracking_db.py
index d5cccdcde534033ef873f62e0f95bf5b81f67050..a425dda1e8cffed1d4028675e8423eced309118b 100644
--- a/guided_mrmp/controllers/multi_path_tracking_db.py
+++ b/guided_mrmp/controllers/multi_path_tracking_db.py
@@ -105,7 +105,7 @@ class MultiPathTrackerDB(MultiPathTracker):
         print(f"all conflicts = {all_conflicts}")
 
         # visualize the grid
-        self.draw_grid()
+        self.draw_grid(self.states)
 
         grid_solver = DiscreteResolver(disc_conflict, disc_robots, starts, goals, disc_all_conflicts,grid, self.lib_2x3, self.lib_3x3, self.lib_2x5)
         subproblem = grid_solver.find_subproblem()
@@ -234,7 +234,7 @@ class MultiPathTrackerDB(MultiPathTracker):
         print(f"self.grid_size = {self.grid_size}")
         print(f"top_left_grid = {self.top_left_grid}")
         
-        self.draw_grid()
+        self.draw_grid(self.states)
 
         # Check if, for every robot, the cell value of the start and the cell value 
         # of the goal are the same. If they are, then we can't find a discrete solution that 
@@ -316,7 +316,7 @@ class MultiPathTrackerDB(MultiPathTracker):
         y = self.top_left_grid[1] - (cell_y + 0.5) * self.cell_size
         return x, y
   
-    def plot_trajs(self, traj1, traj2, radius):
+    def plot_trajs(self, state, traj1, traj2, radius):
         """
         Plot the trajectories of two robots.
         """
@@ -328,7 +328,7 @@ class MultiPathTrackerDB(MultiPathTracker):
         colors = cm.rainbow(np.linspace(0, 1, self.num_robots))
 
         for i in range(self.num_robots):
-            plot_roomba(self.x_history[i][-1], self.y_history[i][-1], self.h_history[i][-1], colors[i], False, self.radius)
+            plot_roomba(state[i][0], state[i][1], state[i][2], colors[i], False, self.radius)
 
         # plot the goal of each robot with solid circle
         for i in range(self.num_robots):
@@ -358,7 +358,7 @@ class MultiPathTrackerDB(MultiPathTracker):
 
         plt.show()
 
-    def draw_grid(self):
+    def draw_grid(self,state):
         starts, goals = self.get_temp_starts_and_goals()
 
         # draw the whole environment with the local grid drawn on top
@@ -370,7 +370,7 @@ class MultiPathTrackerDB(MultiPathTracker):
         colors = cm.rainbow(np.linspace(0, 1, self.num_robots))
 
         for i in range(self.num_robots):
-            plot_roomba(self.x_history[i][-1], self.y_history[i][-1], self.h_history[i][-1], colors[i], False, self.radius)
+            plot_roomba(self.states[i][0], self.states[i][1], self.states[i][2], colors[i], False, self.radius)
 
         # plot the goal of each robot with solid circle
         for i in range(self.num_robots):
@@ -413,7 +413,7 @@ class MultiPathTrackerDB(MultiPathTracker):
 
         plt.show()
 
-    def draw_grid_solution(self, state):
+    def draw_grid_solution(self, state, state_of_robots):
         
         # draw the whole environment with the local grid drawn on top
         import matplotlib.pyplot as plt
@@ -424,7 +424,7 @@ class MultiPathTrackerDB(MultiPathTracker):
         colors = cm.rainbow(np.linspace(0, 1, self.num_robots))
 
         for i in range(self.num_robots):
-            plot_roomba(self.x_history[i][-1], self.y_history[i][-1], self.h_history[i][-1], colors[i], False, self.radius)
+            plot_roomba(state_of_robots[i][0], state_of_robots[i][1], state_of_robots[i][2], colors[i], False, self.radius)
 
         # plot the goal of each robot with solid circle
         for i in range(self.num_robots):
@@ -497,6 +497,7 @@ class MultiPathTrackerDB(MultiPathTracker):
     def advance(self, state, show_plots=False):
         # optimization loop
         # start=time.time()
+        self.states = state
 
         self.update_ref_paths = False
 
@@ -528,7 +529,7 @@ class MultiPathTrackerDB(MultiPathTracker):
                 if self.trajectories_overlap(traj1, traj2, self.radius):
                     # plot the trajectories
                     
-                    self.plot_trajs(traj1, traj2, self.radius)
+                    self.plot_trajs(state, traj1, traj2, self.radius)
 
 
                     print(f"Collision detected between robot {i} and robot {j}")
@@ -571,7 +572,7 @@ class MultiPathTrackerDB(MultiPathTracker):
                 initial_guess = self.get_initial_guess(grid_solution, self.num_robots, 20, 1)
                 initial_guess_state = initial_guess['X']
 
-                self.draw_grid_solution(initial_guess_state)
+                self.draw_grid_solution(initial_guess_state, self.states)
                 
                 print(f"initial_guess_state shape = {initial_guess_state.shape}")
                 print(f"initial_guess_state = {initial_guess_state}")
diff --git a/guided_mrmp/controllers/utils.py b/guided_mrmp/controllers/utils.py
index cc243e82b1d3f89e7163beedf940f29cd4d25de8..29d541c20dd707af417ed41399a3bc4abcb60793 100644
--- a/guided_mrmp/controllers/utils.py
+++ b/guided_mrmp/controllers/utils.py
@@ -99,14 +99,11 @@ def get_ref_trajectory(state, path, target_v, T, DT, path_visited_points=[]):
     """
     K = int(T / DT)
 
-    print(f"path_visited_points = {path_visited_points}")
-
     xref = np.zeros((3, K))  # Reference trajectory for [x, y, theta]
 
     # find the nearest path point to the current state
     ind = get_nn_idx(state, path, path_visited_points)
 
-    print(f"closest point = {path[:, ind]}")
     path_visited_points.append([path[0, ind], path[1, ind]])
 
     # calculate the cumulative distance along the path
@@ -133,6 +130,4 @@ def get_ref_trajectory(state, path, target_v, T, DT, path_visited_points=[]):
     xref[2, :] = (xref[2, :] + np.pi) % (2.0 * np.pi) - np.pi
     xref[2, :] = fix_angle_reference(xref[2, :], xref[2, 0])
 
-    print(f"returning path_visited_points = {path_visited_points}")
-
     return xref, path_visited_points
\ No newline at end of file
diff --git a/guided_mrmp/main.py b/guided_mrmp/main.py
index 822348fd346c6d8cf3415a3cf322376b6597b616..778002cf6c699d4684590659e142fe124c1faa20 100644
--- a/guided_mrmp/main.py
+++ b/guided_mrmp/main.py
@@ -2,7 +2,6 @@ import yaml
 import os
 import random
 import numpy as np
-import pygame
 import time
 from guided_mrmp.utils import Env, Roomba, Robot, create_random_starts_and_goals
 from guided_mrmp.planners import RRT
@@ -33,7 +32,7 @@ def set_python_seed(seed):
     random.seed(seed)
 
 def plan_decoupled_path(env, start, goal, solver="RRT*", 
-                        step_length=20, goal_sample_rate=.5, num_samples=500000, r=80):
+                        step_length=.5, goal_sample_rate=.05, num_samples=500, r=2):
     """
     Plan decoupled path from a given start to a given goal, using a single-agent solver.
 
@@ -82,9 +81,7 @@ def initialize_robots(starts, goals, dynamics_models, radii, target_v, env):
 
         waypoints = [xs,ys]
 
-        # print(f"waypoints = {waypoints}")
-
-        start_heading = np.arctan2(goal[1] - start[1], goal[0] - start[0])
+        start_heading = np.arctan2(ys[1] - start[1], xs[1] - start[0])
         start = [start[0], start[1], start_heading]
         
         r = Robot(i,color,radius,start,goal,dynamics_model,target_v,rrtpath,waypoints, tree)
@@ -92,9 +89,8 @@ def initialize_robots(starts, goals, dynamics_models, radii, target_v, env):
 
     return robots
 
-
 if __name__ == "__main__":
-
+    
     # get the name of the settings file from the command line
     import sys
     if len(sys.argv) < 2:
@@ -136,7 +132,7 @@ if __name__ == "__main__":
     # Create the Guided MRMP policy
     T = settings['prediction_horizon']
     DT = settings['discretization_step']
-    policy = MultiPathTrackerDB(env=env, 
+    policy = MultiPathTrackerDB(env=env,
                                  initial_positions=robot_starts, 
                                  dynamics=dynamics_models[0], # NOTE: Using the same dynamics model for all robots for now
                                  target_v=target_v, 
@@ -150,19 +146,12 @@ if __name__ == "__main__":
                                 )
 
     # Create the simulator
-    scaling_factor = settings['simulator']['scaling_factor']
-    show_vis = True
-    if show_vis:
-        pygame.init()
-        screen = pygame.display.set_mode((x_range[1]*scaling_factor, y_range[1]*scaling_factor)) 
-
-    else: screen = None
-
+    show_vis = False
     sim = Simulator(robots, dynamics_models, env, policy, settings)
 
     # Run the simulation
     start = time.time()
-    sim.run(screen, show_vis)
+    sim.run(show_vis)
     end = time.time()
     print(f"Simulation took {end-start} seconds")
 
diff --git a/guided_mrmp/planners/db_guided_mrmp.py b/guided_mrmp/planners/db_guided_mrmp.py
index d16cd914d28947d2e3c1034e04254153cf678784..d359d764573c2f352947289b428f07fbb4b612a0 100644
--- a/guided_mrmp/planners/db_guided_mrmp.py
+++ b/guided_mrmp/planners/db_guided_mrmp.py
@@ -12,16 +12,18 @@ from shapely.geometry import Polygon, Point
 from guided_mrmp.utils import Env
 from guided_mrmp.utils.helpers import *
 
-from guided_mrmp.conflict_resolvers import TrajOptResolver,TrajOptDBResolver
 
 from guided_mrmp.controllers.utils import get_ref_trajectory, compute_path_from_wp
 
+from guided_mrmp.planners import RRT
+from guided_mrmp.planners import RRTStar
 from guided_mrmp.controllers.mpc import MPC
+from guided_mrmp.controllers.multi_mpc import MultiMPC 
+# from guided_mrmp.controllers.multi_path_tracking import MultiPathTracker
 
 def plan_decoupled_path(env, start, goal, solver="RRT*", 
-                        step_length=20, goal_sample_rate=.5, num_samples=500000, r=80):
-    from guided_mrmp.planners import RRT
-    from guided_mrmp.planners import RRTStar
+                        step_length=20, goal_sample_rate=.5, num_samples=500000, r=10):
+    
     """
     Plan decoupled path from a given start to a given goal, using a single-agent solver.
 
@@ -38,15 +40,15 @@ def plan_decoupled_path(env, start, goal, solver="RRT*",
     """
     if solver == "RRT":
         rrt = RRT(env, start, goal, step_length, goal_sample_rate, num_samples)
-        path = rrt.run()
+        path,tree = rrt.run()
     elif solver == "RRT*":
         rrtstar = RRTStar(env, start, goal, step_length, goal_sample_rate, num_samples,r)
-        path = rrtstar.run()
+        path,tree = rrtstar.run()
     else:
         print(f"Solver {solver} is not yet implemented. Choose something else.")
         return None
 
-    return list(reversed(path))
+    return list(reversed(path)), tree
 
 class GuidedMRMP:
     def __init__(self, env, robots, dynamics_models, T, DT, libs,settings):
@@ -207,7 +209,7 @@ class GuidedMRMP:
 
 
         return next_controls, next_trajs
-    
+        
     def get_next_controls_and_trajectories(self,screen):
         """
         Get the next control for each robot.
@@ -233,8 +235,7 @@ class GuidedMRMP:
             curr_state = np.array([0, 0, 0])
             x_mpc, u_mpc = mpc.step(curr_state, target_traj, np.array(r.control))
 
-            
-
+        
             self.add_vis_target_traj(screen, self.scaling_factor, r, x_mpc)
             
             # only the first one is used to advance the simulation
@@ -242,7 +243,7 @@ class GuidedMRMP:
             
             next_controls.append(np.asarray(control))
 
-            # print(f"control = {u_mpc}")
+            print(f"x_mpc = {x_mpc}")
             next_trajs.append(self.ego_to_global(r, x_mpc))
 
         # use matplotlib to plot the trajectories
@@ -252,6 +253,52 @@ class GuidedMRMP:
         # plt.show()
         return next_controls, next_trajs
 
+    def get_next_controls_and_trajectories_multi_robot(self,screen):
+        """
+        Get the next control for each robot, but use MPC that considers all robots at once.
+        """
+
+        multiMPC = MultiMPC(len(self.robots), self.dynamics_models[0], self.T, self.DT, self.Q, self.Qf, self.R, self.P, self.settings['model_predictive_controller'])
+        
+        # 1. Get the reference trajectory for each robot
+        targets = []
+        state = []
+        for r in self.robots:
+            state.append(r.current_position)
+        for i in range(len(self.robots)):
+            print(f"state i = {state[i]}")
+            # print(f"path i = {self.paths[i]}")
+            targets.append(get_ref_trajectory(np.array(state[i]), np.array(self.guide_paths[i]), self.robots[i].target_v, self.T, self.DT))
+
+
+        # dynamycs w.r.t robot frame
+        # curr_state = np.array([0, 0, self.state[2], 0])
+        curr_states = np.zeros((len(self.robots), 3))
+        controls = []
+        for r in self.robots:
+            controls.append(r.control)
+        x_mpc, u_mpc = multiMPC.step(
+            curr_states,
+            targets,
+            controls
+        )
+        
+        # only the first one is used to advance the simulation
+        # self.control[:] = [u_mpc[0, 0], u_mpc[1, 0]]
+
+        next_controls = []
+        for i in range(len(self.robots)):
+            next_controls.append([u_mpc[i*2, 0], u_mpc[i*2+1, 0]])
+
+        next_trajs = []
+        for i in range(len(self.robots)):
+            print([x_mpc[i*3,:], x_mpc[i*3+1,:], x_mpc[i*3+2,:]])
+            next_trajs.append(self.ego_to_global(self.robots[i], np.array([x_mpc[i*3,:], x_mpc[i*3+1,:], x_mpc[i*3+2,:]])))
+
+
+        return next_controls, next_trajs
+
+
     def advance(self, screen, state, time, dt=0.1):
         """
         Advance the simulation by one timestep.
@@ -263,122 +310,147 @@ class GuidedMRMP:
         """
 
         # update the guide paths of each robot
-        for idx, r in enumerate(self.robots):
-            start = r.current_position
-            goal = r.goal
-            xs = []
-            ys = []
-            rrtpath = plan_decoupled_path(self.env, (start[0],start[1]), (goal[0],goal[1]))
-            for node in rrtpath:
-                xs.append(node[0])
-                ys.append(node[1])
+        # for idx, r in enumerate(self.robots):
+        #     start = r.current_position
+        #     goal = r.goal
+        #     xs = []
+        #     ys = []
+        #     rrtpath, tree = plan_decoupled_path(self.env, (start[0],start[1]), (goal[0],goal[1]))
+        #     for node in rrtpath:
+        #         xs.append(node[0])
+        #         ys.append(node[1])
 
-            waypoints = [xs,ys]
+        #     waypoints = [xs,ys]
+
+        #     self.guide_paths[idx] = compute_path_from_wp(waypoints[0], waypoints[1], .05)
 
-            self.guide_paths[idx] = compute_path_from_wp(waypoints[0], waypoints[1], .05)
 
         # get the next control for each robot
-        if self.settings['model_predictive_controller']['parallelize']:
+        # if self.settings['model_predictive_controller']['parallelize']:
+        if False:
             next_desired_controls, trajectories = self.get_next_controls_and_trajectories_parallel(screen)
         else:
-            next_desired_controls, trajectories = self.get_next_controls_and_trajectories(screen)
+            next_desired_controls, trajectories = self.get_next_controls_and_trajectories_multi_robot(screen)
 
         # find all the conflicts at the next time horizon
         conflicts = self.find_all_conflicts(trajectories, dt)
-        # conflicts=[]
 
-        if len(conflicts) == 0:
+        print(f"conflicts = {conflicts}")
+
+        if True:
             # no conflicts, return the desired controls
             controls = []
 
             for control in next_desired_controls:
-                next_controls = [control[0][0], control[1][0]]
-                controls.append(np.asarray(next_controls))
+                # print(control)
+                # next_controls = [control[0][0], control[1][0]]
+                controls.append(np.asarray(control))
 
             for r, next_control in zip(self.robots, controls):
                 r.control = next_control
             return False, controls
 
         # resolve the conflicts using the database
-        # resolver = TrajOptDBResolver(10, 60, conflicts, self.robots)
         rad = self.robots[0].radius
-        # resolver = TrajOptDBResolver(rad*2, 5, conflicts, self.robots, trajectories, dt, rad,self.env,10,10,5,self.libs[0],self.libs[1],self.libs[2]) 
-        # num_robots, robot_radius, starts, goals, circle_obstacles, rectangle_obstacles,
-        #          rob_dist_weight, obs_dist_weight, control_weight, time_weight, goal_weight)
-        
-        # the starts are the current positions of all robots
-        starts = []
-        for r in self.robots:
-            starts.append(r.current_position)
 
-        # the goals are the last point on the desired trajectory of all robots
-        goals = []
-        for r in trajectories:
-            goals.append(r[:,-1])
+        # resolver = TrajOptResolver(len(starts), rad, starts, goals, self.env.circle_obs, self.env.rect_obs, 
+        #                            self.rob_dist_weight, self.obstacle_weight, self.control_weight, 
+        #                            self.time_weight, self.goal_weight, conflicts, self.robots)
+        # resolver = TrajOptDBResolver(cell_size = rad*2.5, 
+        #                              grid_size = 5, 
+        #                              all_conflicts = conflicts, 
+        #                              all_robots=self.robots, 
+        #                              trajs=trajectories,
+        #                              robot_radius=rad, 
+        #                              env=self.env, 
+        #                              rob_dist_weight=self.rob_dist_weight, 
+        #                              obs_dist_weight=self.obstacle_weight, 
+        #                              control_weight=self.control_weight, 
+        #                              time_weight=self.time_weight, 
+        #                              goal_weight=self.goal_weight, 
+        #                              lib_2x3=self.libs[0], 
+        #                              lib_3x3=self.libs[1], 
+        #                              lib_2x5=self.libs[2])
+
+
+        starts = [r.current_position for r in self.robots]
+        print(f"starts = {starts}")
+        print(f"trajs = {trajectories}")
+        resolver = MultiPathTracker(starts, self.dynamics_models[0], 3.0, self.T, self.DT, trajectories, self.settings)
+
+        # get the current positiosn
+        # starts = [r.current_position for r in self.robots]
+        # goals = [r.goal for r in self.robots]
+        
+        # dump all the data need for trajoptDBresolver to a yaml file for debugging
+        # data = {
+        #     "conflicts": conflicts,
+        #     "dt": dt,
+        #     "env": self.env,
+        #     "next_desired_controls": next_desired_controls,
+        #     "robots": self.robots,
+        #     "trajectories": trajectories,
+        #     "starts": starts,
+        #     "goals": goals,
+        #     "rad": rad,
+        #     "rob_dist_weight": self.rob_dist_weight,
+        #     "obstacle_weight": self.obstacle_weight,
+        #     "control_weight": self.control_weight,
+        #     "time_weight": self.time_weight,
+        #     "goal_weight": self.goal_weight
+        # }
+
+        # import yaml
+        # with open("guided_mrmp/tests/db_opt_data1.yaml", "w") as file:
+        #     yaml.dump(data, file)
+
+        # get the local controls
+        # next_desired_controls, trajs = resolver.get_local_controls(next_desired_controls)
+        resolver.run()
+
+        vs = resolver.v_history
+        omegas = resolver.a_history
+
+        next_desired_controls = []
+        for v, omega in zip(vs, omegas):
+            next_desired_controls.append([v[1], omega[1]])
+
+
+
+        # # get the goals that were used by the resolver
+        # starts, goals = resolver.get_temp_starts_and_goals()
+        # # get the continuous space values of these goals
+        # continuous_subgoals = []
+        # for g in goals:
+        #     continuous_subgoals.append(resolver.get_grid_cell_location(g[0], g[1]))
+
+        # reroute the robots' guide paths to include the new subgoals in the guidepaths
+        # update the guide paths of each robot
+        # for idx, r in enumerate(self.robots):
+        #     subgoal = continuous_subgoals[idx]
+        #     start = r.current_position
+        #     goal = r.goal
+        #     xs = []
+        #     ys = []
+        #     # rrtpath, tree = plan_decoupled_path(self.env, (subgoal[0],subgoal[1]), (goal[0],goal[1]))
+        #     rrtstar = RRTStar(self.env, (subgoal[0],subgoal[1]), (goal[0],goal[1]), step_len=20, goal_sample_rate=.5, iter_max=500000, r=80, sampled_vertices=r.tree)
+        #     rrtpath,tree = rrtstar.run()
+        #     rrtpath = list(reversed(rrtpath))
+        #     print(f"rrtpath = {rrtpath}")
+        #     for node in rrtpath:
+        #         print(f"node = {node}")
+        #         xs.append(node[0])
+        #         ys.append(node[1])
+
+        #     xs.insert(0,start[0])
+        #     ys.insert(0,start[1])
+
+        #     waypoints = [xs,ys]
+
+        #     self.guide_paths[idx] = compute_path_from_wp(waypoints[0], waypoints[1], .05)
 
         
-        def check_goal_overlap(goal1, goal2, rad):
-            """
-            Check if the goals overlap
-            """
-            # get the vector between the two goals
-            v = np.array(goal2) - np.array(goal1)
-
-            # check if the distance between the two goals is less than 2*rad
-            if np.linalg.norm(v) < 2*rad:
-                return True
-
-            return False
-
-        def fix_goal_overlap(goal1, goal2):
-            """
-            Fix the goal overlap
-            """
-            # get the vector between the two goals
-            v = np.array(goal2) - np.array(goal1)
-
-            # move goal2 in the positive direction of the vector
-            goal2 = goal2 + .5*v
-
-            # move goal1 in the negative direction of the vector
-            goal1 = goal1 - .5*v
-
-            return goal1, goal2
-
-
-        if check_goal_overlap(goals[0], goals[1], rad):
-            print("fixing goal overlap")
-            goals[0], goals[1] = fix_goal_overlap(goals[0], goals[1])
-
-        resolver = TrajOptResolver(len(starts), rad, starts, goals, self.env.circle_obs, self.env.rect_obs, 
-                                   self.rob_dist_weight, self.obstacle_weight, self.control_weight, 
-                                   self.time_weight, self.goal_weight, conflicts, self.robots)
-        next_desired_controls, trajs = resolver.get_local_controls(next_desired_controls)
-
-        self.add_vis_conflict_free_traj(screen, self.scaling_factor, trajs)
-
-
-        # dump all the data need for trajoptresolver to a yaml file for debugging
-        data = {
-            "conflicts": conflicts,
-            "dt": dt,
-            "env": self.env,
-            "next_desired_controls": next_desired_controls,
-            "robots": self.robots,
-            "trajectories": trajectories,
-            "starts": starts,
-            "goals": goals,
-            "rad": rad,
-            "rob_dist_weight": self.rob_dist_weight,
-            "obstacle_weight": self.obstacle_weight,
-            "control_weight": self.control_weight,
-            "time_weight": self.time_weight,
-            "goal_weight": self.goal_weight
-        }
-
-        import yaml
-        with open("guided_mrmp/tests/db_opt_data2.yaml", "w") as file:
-            yaml.dump(data, file)
+        # self.add_vis_conflict_free_traj(screen, self.scaling_factor, trajs)
             
 
         # return the valid controls
@@ -394,14 +466,23 @@ class GuidedMRMP:
         """
         
         for r in self.robots:
-            path = self.guide_paths[r.label]
-            xs = path[0]
-            ys = path[1]
-            # for node in path:
-            #     pygame.draw.circle(screen, r.color, (int(node[0]), int(node[1])), 2)
-            for i in range(len(xs)-1):
-                pygame.draw.line(screen, r.color, (xs[i]*scaling_factor,ys[i]*scaling_factor), 
-                                 (xs[i+1]*scaling_factor,ys[i+1]*scaling_factor), 2)
+            # path = self.guide_paths[r.label]
+            # xs = path[0]
+            # ys = path[1]
+            # # for node in path:
+            # #     pygame.draw.circle(screen, r.color, (int(node[0]), int(node[1])), 2)
+            # for i in range(len(xs)-1):
+            #     pygame.draw.line(screen, r.color, (xs[i]*scaling_factor,ys[i]*scaling_factor), 
+            #                      (xs[i+1]*scaling_factor,ys[i+1]*scaling_factor), 2)
+                
+            tree = r.tree
+            for node in tree:
+                # draw a line from the node to its parent
+                print(f"node = {node}")
+                if node.parent is not None:
+                    print(f"parent = {node.parent}")
+                    pygame.draw.line(screen, r.color, (node.current[0]*scaling_factor,node.current[1]*scaling_factor), 
+                                     (node.parent[0]*scaling_factor,node.parent[1]*scaling_factor), 2)
 
     def add_vis_grid(self, screen, grid_size, top_left, cell_size):
         """
@@ -446,16 +527,3 @@ class GuidedMRMP:
                 next_y = traj[1][i+1]
                 pygame.draw.line(screen, (0,255,0), (x*scaling_factor,y*scaling_factor), 
                                 (next_x*scaling_factor,next_y*scaling_factor), 2)
-
-
-if __name__ == "__main__":
-
-    # create the environment
-    env = Env()
-
-    # starts, goals = create_random_starts_and_goals(env, 4)
-    starts = [[0,0.1,0],[10,5.1,0]]
-    goals = [[10,3,0],[5,1,0]]
-
-    alg = GuidedMRMP(Env)
-    alg.run(starts, goals)
\ No newline at end of file
diff --git a/guided_mrmp/simulator.py b/guided_mrmp/simulator.py
index 4f9e2b3d2e931b325a0f2e5806ecf4c8e1fd42d9..58d0f25ef61c8697445306a22784b70c203b9990 100644
--- a/guided_mrmp/simulator.py
+++ b/guided_mrmp/simulator.py
@@ -1,4 +1,5 @@
-import pygame
+import matplotlib.pyplot as plt
+import matplotlib.cm as cm
 import numpy as np
 
 # Simulator class:
@@ -15,6 +16,7 @@ class Simulator:
         time: the current time
         """
         self.robots = robots
+        self.env = env
         self.circ_obstacles = env.circle_obs
         self.rect_obstacles = env.rect_obs
         self.policy = policy 
@@ -25,12 +27,19 @@ class Simulator:
         self.dynamics_models = dynamics_models
         self.time = 0
 
-        # scaling factor used to adjust the size of the pygame window
         self.scaling_factor = settings['simulator']['scaling_factor']
 
+        # Helper variables to keep track of the sim
+        self.sim_time = 0
+        self.x_history = [ [] for _ in range(self.num_robots) ]
+        self.y_history = [ [] for _ in range(self.num_robots) ]
+        self.h_history = [ [] for _ in range(self.num_robots) ]
+        self.optimized_trajectories_hist = [ [] for _ in range(self.num_robots) ]
+        self.optimized_trajectory = None
+
     def all_robots_at_goal(self):
-        for r in self.robots:
-            if (np.sqrt((r.current_position[0] - r.goal[0]) ** 2 + (r.current_position[1] - r.goal[1]) ** 2) > 10):
+        for i in range(self.num_robots):
+            if (np.sqrt((self.state[i][0] - self.robots[i].goal[0]) ** 2 + (self.state[i][1] - self.robots[i].goal[1]) ** 2) > .5):
                 return False
         return True
 
@@ -40,62 +49,127 @@ class Simulator:
         """
 
         # Get the controls from the policy
-        x_mpc, controls = self.policy.advance(self.state)
+        x_mpc, controls = self.policy.advance(screen, self.state)
 
-        # Update the state of each robot
-        for i in range(self.num_robots):
-            new_state = self.dynamics_models[i].next_state(self.state[i], controls[i], dt)
-            self.robots[i].current_position = new_state
-            self.state[i] = new_state
+        # # Update the state of each robot
+        # for i in range(self.num_robots):
+        #     new_state = self.dynamics_models[i].next_state(self.state[i], controls[i], dt)
+        #     self.robots[i].current_position = new_state
+        #     self.state[i] = new_state
 
         # Update the time
         self.time += dt
+        return x_mpc, controls
+
+    def run(self, show_plots=False):
+        """
+        Run the path tracker algorithm.
+        Parameters:
+        - show_plots (bool): Flag indicating whether to show plots during the simulation. Default is False.
+        Returns:
+        - numpy.ndarray: Array containing the history of x, y, and h coordinates.
+        """
+
+        # Add the initial state to the histories
+        self.state = np.array(self.state)
+        for i in range(self.num_robots):
+            self.x_history[i].append(self.state[i, 0])
+            self.y_history[i].append(self.state[i, 1])
+            self.h_history[i].append(self.state[i, 2])
+        # if show_plots: self.plot_sim()
+
+        self.plot_current_world_state()
+        
+        while 1:
+            # check if all robots have reached their goal
+            if self.all_robots_at_goal():
+                print("Success! Goal Reached")
+                return np.asarray([self.x_history, self.y_history, self.h_history])
+            
+            # plot the current state of the robots
+            self.plot_current_world_state()
+            
+            # get the next control for all robots
+            x_mpc, controls = self.advance(self.state, self.policy.DT)
+
+            next_states = []
+            for i in range(self.num_robots):
+                next_states.append(self.policy.dynamics.next_state(self.state[i], controls[i], self.policy.DT))
+
+            self.state = next_states
+
+            self.state = np.array(self.state)
+            for i in range(self.num_robots):
+                self.x_history[i].append(self.state[i, 0])
+                self.y_history[i].append(self.state[i, 1])
+                self.h_history[i].append(self.state[i, 2])
+
+            # use the optimizer output to preview the predicted state trajectory
+            # self.optimized_trajectory = self.ego_to_global(x_mpc.value)
+            # if show_plots: self.optimized_trajectory = self.ego_to_global_roomba(x_mpc)
+            # if show_plots: self.plot_sim()
+
+
+  
+    def plot_current_world_state(self):
+        """
+        Plot the current state of the world.
+        """
+        colors = cm.rainbow(np.linspace(0, 1, self.num_robots))
 
-    def draw_environment(self, screen):
-        """ Draw the environment on the screen """
-        screen.fill((255,255,255))
+        # plot the obstacles
         for obs in self.circ_obstacles:
-            pygame.draw.circle(screen, (0,0,0), (obs[0]*self.scaling_factor,obs[1]*self.scaling_factor), obs[2]*self.scaling_factor)
-        for obs in self.rect_obstacles:
-            pygame.draw.rect(screen, (0,0,0), obs)
-
-    def draw_robots(self, screen):
-        """ Draw the robots on the screen """
-        for robot in self.robots:
-            x,y,yaw = robot.current_position
-            pygame.draw.circle(screen, robot.color, (x*self.scaling_factor,y*self.scaling_factor), robot.radius*self.scaling_factor)
-            # Plot direction marker
-            dx = robot.radius * np.cos(robot.current_position[2])
-            dy = robot.radius * np.sin(robot.current_position[2])
-            pygame.draw.line(screen, (0,0,0), (x*self.scaling_factor,y*self.scaling_factor), (x*self.scaling_factor+dx*self.scaling_factor,y*self.scaling_factor+dy*self.scaling_factor), width=2)
-
-    def run(self, screen, show_vis=False):
-        clock = pygame.time.Clock()
-        pause = False
-        while not self.all_robots_at_goal():
-            clock.tick(30)
-            if show_vis:
-                for event in pygame.event.get():
-                    if event.type == pygame.QUIT:
-                        return
-                    if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
-                        return
-                    if event.type == pygame.KEYDOWN and event.key == pygame.K_p:
-                        pause = not pause
-                    if event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT and pause:
-                        self.draw_environment(screen)
-                        self.policy.add_vis_guide_paths(screen, self.scaling_factor)
-                        self.draw_robots(screen)
-                        
-                        self.advance(screen,self.policy.DT)
-            if not pause:
-                if show_vis: 
-                    self.draw_environment(screen)
-                    # self.policy.add_vis_guide_paths(screen, self.scaling_factor)
-                    self.draw_robots(screen)
-                
-                self.advance(screen,self.policy.DT)
-
-            if show_vis: 
-                pygame.display.flip()
+            circle1 = plt.Circle((obs[0], obs[1]), obs[2], color='k', fill=True)
+            plt.gca().add_artist(circle1)
+
+        # Plot the current state of each robot using the most recent values from
+        # x_history, y_history, and h_history
+        for i in range(self.num_robots):
+            self.plot_roomba(self.x_history[i][-1], self.y_history[i][-1], self.h_history[i][-1], colors[i], False, self.policy.radius)
+
+            
+            x, y, theta = self.policy.paths[i][:, -1]
+            plt.plot(x, y, 'o', color=colors[i])
+            circle1 = plt.Circle((x, y), self.policy.radius, color=colors[i], fill=False)
+            plt.gca().add_artist(circle1)
+
+
+        # plot the ref path of each robot
+        for i in range(self.num_robots):
+            plt.plot(self.policy.paths[i][0, :], self.policy.paths[i][1, :], '--', color=colors[i])
+
+        x_range = self.env.boundary[0]
+        y_range = self.env.boundary[1]
+        plt.xlim(x_range[0], x_range[1])
+        plt.ylim(y_range[0], y_range[1])
+
+        # force equal aspect ratio
+        plt.gca().set_aspect('equal', adjustable='box')
+
+        plt.tight_layout()
+
+
+        plt.show()
+        # plt.draw()
+        # plt.pause(0.1)
+        # plt.clf()
+
+    def plot_roomba(self, x, y, yaw, color, fill, radius):
+        """
+
+        Args:
+            x ():
+            y ():
+            yaw ():
+        """
+        ax = plt.gca()
+        if fill: alpha = .3
+        else: alpha = 1
+        circle = plt.Circle((x, y), radius, color=color, fill=fill, alpha=alpha)
+        ax.add_patch(circle)
+
+        # Plot direction marker
+        dx = 1 * np.cos(yaw)
+        dy = 1 * np.sin(yaw)
+        ax.arrow(x, y, dx, dy, head_width=0.1, head_length=0.1, fc='r', ec='r')