├── Adaptive LQR ├── odeFuncSLine2d_integral.m ├── point_to_line.m └── sl_2d_multi_wp_integral.m ├── Carrot Chase ├── carrot_chase.png ├── carrot_chase_path_following.m ├── carrot_chase_single_line.m └── ode_carrot_chase.m ├── LQR ├── LQR.png ├── intersection_pt.m ├── lqr_straight_line.m ├── ode_lqr.m └── point_to_line.m └── README.md /Adaptive LQR/odeFuncSLine2d_integral.m: -------------------------------------------------------------------------------- 1 | function [dydt] = odeFuncSLine2d_integral(t,y,w1_x,w1_y,w1_z,w2_x,w2_y,w2_z,c) 2 | 3 | dydt = zeros(4,1); 4 | 5 | v = 25; 6 | 7 | si_w = 1.57; % wind direction 8 | vw = c*v; 9 | v_wx = c*v*cos(si_w); 10 | v_wy = c*v*sin(si_w); 11 | 12 | Rmin = 75; 13 | 14 | %% XY Controller 15 | 16 | % Computing the position error 17 | % Distance of point to line (UAV Position - Desired path) 18 | 19 | pt = [y(1) y(2) 0]; % UAV Positon vector 20 | a1 = [w1_x w1_y 0]; % Waypoint 1 Vector 21 | a2 = [w2_x w2_y 0]; % Waypoint 2 Vector 22 | 23 | tmp = (y(1) - w1_x)*(w2_y - w1_y) - (y(2) - w1_y)*(w2_x - w1_x); 24 | % To check whether the point is left or right of the desired path 25 | if(tmp < 0) 26 | d_xy = point_to_line(pt,a1,a2) 27 | else 28 | d_xy = -point_to_line(pt,a1,a2) 29 | end 30 | 31 | % LQR Formualtion 32 | 33 | % -------------- Old Gain ------------------ 34 | % db = 4; 35 | % q1 = sqrt(abs(db/(db - d_xy))); 36 | q2 = 1; 37 | % -------------- Exponential Gain ------------- 38 | k = 0.001; 39 | q1 = sqrt(exp(k*(abs(d_xy)))); 40 | 41 | si = y(3); 42 | 43 | v_x = v*cos(si) + vw*cos(si_w); 44 | v_y = v*sin(si) + vw*sin(si_w); 45 | 46 | course_angle = atan2(v_y,v_x); 47 | si_p = atan2((w2_y - w1_y),(w2_x - w1_x)); % si desired 48 | vd = v*sin(course_angle - si_p); % d_dot 49 | 50 | % A = [0,1;0,0]; 51 | % B = [0;(cos(si - si_p))]; 52 | % Q = [q1,0;0,q2]; 53 | % R = [1]; 54 | % X = [d_xy;vd]; 55 | % [K] = lqr(A,B,Q,R); 56 | % 57 | % u = -K*X; 58 | % u = -(q1*d_xy + sqrt(2*q1 + q2^2)*vd + igain_xy*i_xy); 59 | 60 | p12 = q1/abs(cos(si-si_p)); 61 | p22 = sqrt(2*p12 + q2)/(cos(si)*cos(si_p)+sin(si)*sin(si_p)); 62 | cos(si - si_p); 63 | u = -(d_xy*p12*cos(si - si_p) + p22*vd*cos(si - si_p)); 64 | 65 | 66 | 67 | if(abs(u) > (v^2)/Rmin) 68 | if (u > 0) 69 | u = (v^2)/Rmin; 70 | else 71 | u = -(v^2)/Rmin; 72 | end 73 | end 74 | 75 | % Finally heading angle 76 | si_dot = u/v; 77 | 78 | dydt(1) = v*cos(si) + v_wx; % y(1) -> uav_x 79 | dydt(2) = v*sin(si) + v_wy; % y(2) -> uav_y 80 | dydt(3) = si_dot; % y(3) -> si 81 | dydt(4) = vd; % y(4) -> d -------------------------------------------------------------------------------- /Adaptive LQR/point_to_line.m: -------------------------------------------------------------------------------- 1 | function d = point_to_line(pt, v1, v2) 2 | a = v1 - v2; 3 | b = pt - v2; 4 | d = norm(cross(a,b)) / norm(a); -------------------------------------------------------------------------------- /Adaptive LQR/sl_2d_multi_wp_integral.m: -------------------------------------------------------------------------------- 1 | clc; clear all; 2 | close all; 3 | 4 | %% Initialization of params 5 | waypoints = [[0, 0, 0]; [600, 0, 100]; [600, 600, 100];[0,600,100]; [0, 0, 100]; [600,0,0]; [0,0,0]]; 6 | % waypoints = [[0, 0, 0]; [600, 0, 30]; [600, 600, 30];[0,600,30]; [0, 0, 30]; [600,0,0]; [0,0,0]]; 7 | global control_effort; 8 | control_effort = []; 9 | global q1_z_arr; 10 | q1_z_arr = []; 11 | global dz_arr; 12 | dz_arr = []; 13 | global dxy_arr; 14 | dxy_arr = []; 15 | 16 | global si_z_arr; 17 | global prev_d; 18 | prev_d = 0; 19 | 20 | si_z_arr = []; 21 | z_profile =[]; 22 | time = []; 23 | counter = 0; 24 | w_spd_ratio = 0.2; 25 | 26 | wp_1 = waypoints(1,:); 27 | w1_x = wp_1(1); w1_y = wp_1(2); w1_z = wp_1(3); 28 | 29 | wp_2 = waypoints(2,:); 30 | w2_x = wp_2(1); w2_y = wp_2(2); w2_z = wp_2(3); 31 | 32 | lw = 1; 33 | tspan = 0:0.05:0.2; 34 | 35 | % Straight Line Initial Condition 36 | curr_x = 0; 37 | curr_y = 1000; 38 | curr_si = 0; 39 | curr_d = 0; 40 | dist_wp = sqrt((w2_x - curr_x)^2 + (w2_y - curr_y)^2 ); 41 | delta = 25; 42 | 43 | [sphere_x,sphere_y,sphere_z] = sphere; 44 | % figure 45 | % surf(sphere_x*5 + w2_x , sphere_y * 5 + w2_y, sphere_z * 5 + w2_z); 46 | % grid on 47 | % hold on 48 | 49 | %% Plotting Reference Trajectory 50 | wp = 1; 51 | fprintf("Plotting trajectories\n"); 52 | 53 | %% Path following begins 54 | 55 | %% ------------------------No wind Plot--------------------------- 56 | last_wp = 6; 57 | wp = 2; 58 | while ( dist_wp > delta && wp <= last_wp) 59 | % y0 = [curr_x curr_y curr_si curr_d curr_z curr_si_z curr_d_z] ; 60 | % [t,y] = ode45(@(t,y) odeFuncSLine3d(t,y,w1_x,w1_y,w1_z,w2_x,w2_y,w2_z,0.3), tspan, y0); 61 | y0 = [curr_x curr_y curr_si curr_d] ; 62 | wind_ratio = 0; 63 | [t,y] = ode45(@(t,y) odeFuncSLine2d_integral(t,y,w1_x,w1_y,w1_z,w2_x,w2_y,w2_z,wind_ratio), tspan, y0); 64 | curr_x = y(end,1); 65 | curr_y = y(end,2); 66 | curr_si = y(end,3); 67 | curr_d = y(end,4); 68 | 69 | % fprintf('x : %f, y : %f, z: %f, dist_wp: %f\n', curr_x,curr_y,curr_z,dist_wp); 70 | dist_wp = sqrt((w2_x - curr_x)^2 + (w2_y - curr_y)^2); 71 | 72 | if(dist_wp < delta) 73 | % surf(sphere_x*5+w2_x,sphere_y*5+w2_y,sphere_z*5+w2_z); 74 | fprintf("waypoint reached: %d \n", wp); 75 | wp_1 = waypoints(wp,:); 76 | w1_x = wp_1(1); w1_y = wp_1(2); w1_z = wp_1(3); 77 | 78 | wp_2 = waypoints(wp+1,:); 79 | w2_x = wp_2(1); w2_y = wp_2(2); w2_z = wp_2(3); 80 | 81 | pt = [curr_x,curr_y, 0]; 82 | v1 = [w1_x w1_y 0]; 83 | v2 = [w2_x w2_y 0]; 84 | d = point_to_line(pt,v1,v2); 85 | 86 | pt = [curr_x,curr_y,0]; 87 | v1 = [w1_x w1_y 0]; 88 | v2 = [w2_x w2_y 0]; 89 | d_3d = point_to_line(pt,v1,v2); 90 | 91 | dz = sqrt((d_3d)^2 - d^2); 92 | dist_wp = sqrt((w2_x - curr_x)^2 + (w2_y - curr_y)^2); 93 | wp = wp + 1; 94 | curr_si = y(end,3); 95 | curr_d = d; 96 | end 97 | % 98 | % plot3(y(:,1),y(:,2),y(:,5),'-m','LineWidth',lw); 99 | hold on 100 | plot(y(:,1),y(:,2),'-m','LineWidth',lw); 101 | 102 | % arrow_x = [y(end,1)]; 103 | % arrow_y = [y(end,2)]; 104 | % arrow_u = [25*cos(curr_si)]; 105 | % arrow_v = [25*sin(curr_si)]; 106 | % quiver(arrow_x,arrow_y,arrow_u,arrow_v,0); 107 | % plot([y(end,1),(y(end,1)+10*cos(curr_si))],[y(end,2),(y(end,2)+10*sin(curr_si))],'-m') 108 | 109 | if(wp <= last_wp) 110 | p1 = [waypoints(wp-1,1),waypoints(wp,1)]; 111 | p2 = [waypoints(wp-1,2),waypoints(wp,2)]; 112 | p3 = [waypoints(wp-1,3),waypoints(wp,3)]; 113 | % plot3(p1,p2,p3,'--k'); 114 | plot(p1,p2,'--k','LineWidth',1); 115 | end 116 | pause(0.01); 117 | grid on 118 | end 119 | -------------------------------------------------------------------------------- /Carrot Chase/carrot_chase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HobbySingh/Path-Following-Algorithms/07de288ebc82c12c6f573673fc5ab2057bbd0f07/Carrot Chase/carrot_chase.png -------------------------------------------------------------------------------- /Carrot Chase/carrot_chase_path_following.m: -------------------------------------------------------------------------------- 1 | %% Author - Mandeep Singh 2 | % email - mandeep14145@iiitd.ac.in 3 | 4 | %% Clear All 5 | clc; clear all; 6 | close all; 7 | 8 | %% Initialization of params 9 | waypoints = [[0, 0, 0]; [300, 300, 0]; [150, 600, 0];[-300,600,0]; [0, 0, 0]; [300,0,0]; [0, 0, 0];]; 10 | 11 | wp_1 = waypoints(1,:); 12 | w1_x = wp_1(1); w1_y = wp_1(2); 13 | 14 | wp_2 = waypoints(2,:); 15 | w2_x = wp_2(1); w2_y = wp_2(2); 16 | 17 | lw = 1; 18 | tspan = 0:0.01:1; 19 | 20 | % Straight Line Initial Condition 21 | curr_x = 50; 22 | curr_y = 0; 23 | curr_si =0; 24 | dist_wp = sqrt((w2_x - curr_x)^2 + (w2_y - curr_y)^2); 25 | delta = 5; 26 | 27 | %% Plotting Reference Trajectory 28 | fprintf("Plotting trajectories\n"); 29 | 30 | %% Path following begins 31 | wp = 2; 32 | while ( dist_wp > delta && wp <= 5) 33 | y0 = [curr_x curr_y curr_si] ; 34 | [t,y] = ode45(@(t,y) ode_carrot_chase(t,y,w1_x,w1_y,w2_x,w2_y), tspan, y0); 35 | curr_x = y(end,1); 36 | curr_y = y(end,2); 37 | curr_si = y(end,3); 38 | 39 | dist_wp = sqrt((w2_x - curr_x)^2 + (w2_y - curr_y)^2); 40 | 41 | if(dist_wp < delta) 42 | fprintf("waypoint reached: %d \n", wp); 43 | 44 | wp_1 = waypoints(wp,:); 45 | w1_x = wp_1(1); w1_y = wp_1(2); 46 | 47 | wp_2 = waypoints(wp+1,:); 48 | w2_x = wp_2(1); w2_y = wp_2(2); 49 | 50 | dist_wp = sqrt((w2_x - curr_x)^2 + (w2_y - curr_y)^2 ); 51 | 52 | wp = wp + 1; 53 | 54 | end 55 | % hold on 56 | plot(y(:,1),y(:,2),'-m','LineWidth',lw); 57 | if(wp <= 5) 58 | p1 = [waypoints(wp-1,1),waypoints(wp,1)]; 59 | p2 = [waypoints(wp-1,2),waypoints(wp,2)]; 60 | p3 = [waypoints(wp-1,3),waypoints(wp,3)]; 61 | plot(p1,p2,'--k','LineWidth',1); 62 | end 63 | pause(0.01); 64 | hold on 65 | grid on 66 | end 67 | % hold on 68 | title('Carrot Chase based Path Following') 69 | legend ('Desired Path','Path (delta = 10,k = 60)'); 70 | xlabel('X(m)') % x-axis label 71 | ylabel('Y(m)') % y-axis label 72 | xlim([-400 400]) 73 | ylim([-100 750]) 74 | -------------------------------------------------------------------------------- /Carrot Chase/carrot_chase_single_line.m: -------------------------------------------------------------------------------- 1 | clc; clear all; 2 | close all; 3 | 4 | %% Initialization of params 5 | waypoints = [[300, 300, 0]; [0, 0, 0]; [150, 600, 0];[-300,600,0]; [0, 0, 0]; [300,0,0]; [0, 0, 0];]; 6 | 7 | wp_1 = waypoints(1,:); 8 | w1_x = wp_1(1); w1_y = wp_1(2); 9 | 10 | wp_2 = waypoints(2,:); 11 | w2_x = wp_2(1); w2_y = wp_2(2); 12 | 13 | lw = 1; 14 | tspan = 0:0.1:25; 15 | 16 | %% Straight Line Initial Condition 17 | curr_x = 200; 18 | curr_y = 300; 19 | curr_si= 1.57; 20 | delta = 25; 21 | 22 | %% Plotting Reference Trajectory 23 | fprintf("Plotting trajectories\n"); 24 | % arr_x = (300:-0.5:150); 25 | % arr_y = (300:1:600); 26 | arr_x = (0:1:300); 27 | arr_y = (0:1:300); 28 | 29 | plot(arr_x(1,:),arr_y(1,:),'--k'); 30 | 31 | %% Path following begins 32 | y0 = [curr_x curr_y curr_si] ; 33 | [t,y] = ode45(@(t,y) ode_carrot_chase(t,y,w1_x,w1_y,w2_x,w2_y), tspan, y0); 34 | 35 | hold on 36 | grid on 37 | for i = 1:length(y(:,1))-1 38 | plot(y(i:i+1,1),y(i:i+1,2),'-m','LineWidth',lw); 39 | pause(0.01) 40 | end 41 | 42 | % title('LQR based Path Following') 43 | % legend ('Desired Path','Path (Adaptive Optimal Guidance Law)'); 44 | xlabel('X(m)') % x-axis label 45 | ylabel('Y(m)') % y-axis label 46 | -------------------------------------------------------------------------------- /Carrot Chase/ode_carrot_chase.m: -------------------------------------------------------------------------------- 1 | function [dydt] = ode_carrot_chase(t,y,w1_x,w1_y,w2_x,w2_y) 2 | 3 | %% Author - Mandeep Singh 4 | % email - mandeep14145@iiitd.ac.in 5 | 6 | %% Initializing Params 7 | dydt = zeros(3,1); 8 | 9 | v = 10; 10 | delta = 10; 11 | k = 60; 12 | 13 | ugv_x = y(1); 14 | ugv_y = y(2); 15 | si = y(3); 16 | 17 | %% XY Controller 18 | 19 | % Computing the position error 20 | % Distance of point to line (UGV Position - Desired path) 21 | 22 | R_u = sqrt((w1_x - ugv_x)^2 + (w1_y - ugv_y)^2); 23 | theta = atan2((w2_y - w1_y),(w2_x - w1_x)); 24 | theta_u = atan2(ugv_y - w1_y,ugv_x - w1_x); 25 | beta = theta - theta_u; 26 | R = sqrt(R_u^2 - (R_u*sin(beta))^2); 27 | x_target = w1_x + (R+delta)*cos(theta); 28 | y_target = w1_y + (R+delta)*sin(theta); 29 | % pause(0.01) 30 | si_d = atan2(y_target - ugv_y, x_target - ugv_x); 31 | u = k*(si_d - si); 32 | %% Non-Holonomic COnstraints 33 | % Constraining the control input 34 | % Rmin = 125; 35 | % if(abs(u) > (v^2)/Rmin) 36 | % if (u > 0) 37 | % u = (v^2)/Rmin; 38 | % else 39 | % u = -(v^2)/Rmin; 40 | % end 41 | % end 42 | 43 | % Finally heading angle 44 | si_dot = u; 45 | 46 | %% STATE EQUATIONS 47 | dydt(1) = v*cos(si); % y(1) -> uav_x 48 | dydt(2) = v*sin(si); % y(2) -> uav_y 49 | dydt(3) = si_dot; % y(3) -> si -------------------------------------------------------------------------------- /LQR/LQR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HobbySingh/Path-Following-Algorithms/07de288ebc82c12c6f573673fc5ab2057bbd0f07/LQR/LQR.png -------------------------------------------------------------------------------- /LQR/intersection_pt.m: -------------------------------------------------------------------------------- 1 | function x_y_z_d = intersection_pt(pt,v1,v2) 2 | 3 | %% Author : Mandeep Singh 4 | % email : mandeep14145@iiitd.ac.in 5 | 6 | %% 7 | syms t 8 | 9 | a = v1 - v2; 10 | r = v2 + t*a; 11 | 12 | normal_vector = r - pt; 13 | 14 | eq = dot(normal_vector,a) == 0; 15 | 16 | t_ = solve(eq,t); 17 | 18 | r = v2 + t_*a; 19 | 20 | % d = sqrt((r(1) - pt(1))^2 + (r(2) - pt(2))^2 + (r(3) - pt(3))^2); 21 | x = double(r(1)); y = double(r(2)); z = double(r(3)); 22 | x_y_z_d = [x y z]; 23 | -------------------------------------------------------------------------------- /LQR/lqr_straight_line.m: -------------------------------------------------------------------------------- 1 | %% 2 | % Coded by : Mandeep Singh 3 | % Institue : IIITD 4 | 5 | %% Clear All 6 | clc; clear all; 7 | close all; 8 | 9 | %% Initialization of params 10 | waypoints = [[0, 0, 0]; [300, 300, 0]; [150, 600, 0];[-300,600,0]; [0, 0, 0]; [300,0,0]; [0, 0, 0];]; 11 | counter = 0; 12 | w_spd_ratio = 0.2; 13 | 14 | wp_1 = waypoints(1,:); 15 | w1_x = wp_1(1); w1_y = wp_1(2); w1_z = wp_1(3); 16 | 17 | wp_2 = waypoints(2,:); 18 | w2_x = wp_2(1); w2_y = wp_2(2); w2_z = wp_2(3); 19 | 20 | lw = 1; 21 | tspan = 0:0.05:0.2; 22 | 23 | % Straight Line Initial Condition 24 | curr_x = 50; 25 | curr_y = 0; 26 | curr_si =0; 27 | curr_d = 0; 28 | curr_z = 0; 29 | curr_si_z = 0; 30 | curr_d_z = 0; 31 | dist_wp = sqrt((w2_x - curr_x)^2 + (w2_y - curr_y)^2 + (w2_z - curr_z)^2); 32 | delta = 4; 33 | 34 | %% Plotting Reference Trajectory 35 | wp = 1; 36 | fprintf("Plotting trajectories\n"); 37 | 38 | %% Path following begins 39 | wp = 2; 40 | while ( dist_wp > delta && wp <= 5) 41 | y0 = [curr_x curr_y curr_si curr_d] ; 42 | [t,y] = ode45(@(t,y) ode_lqr(t,y,w1_x,w1_y,w2_x,w2_y,0), tspan, y0); 43 | curr_x = y(end,1); 44 | curr_y = y(end,2); 45 | curr_si = y(end,3); 46 | curr_d = y(end,4); 47 | 48 | dist_wp = sqrt((w2_x - curr_x)^2 + (w2_y - curr_y)^2 + (w2_z - curr_z)^2); 49 | 50 | if(dist_wp < delta) 51 | fprintf("waypoint reached: %d \n", wp); 52 | wp_1 = waypoints(wp,:); 53 | w1_x = wp_1(1); w1_y = wp_1(2); 54 | 55 | wp_2 = waypoints(wp+1,:); 56 | w2_x = wp_2(1); w2_y = wp_2(2); 57 | 58 | pt = [curr_x,curr_y, 0]; 59 | v1 = [w1_x w1_y 0]; 60 | v2 = [w2_x w2_y 0]; 61 | d = point_to_line(pt,v1,v2); 62 | 63 | dist_wp = sqrt((w2_x - curr_x)^2 + (w2_y - curr_y)^2 ); 64 | 65 | wp = wp + 1; 66 | curr_si = y(end,3); 67 | curr_d = d; 68 | end 69 | % hold on 70 | plot(y(:,1),y(:,2),'-m','LineWidth',lw); 71 | counter = counter + 1; 72 | if(wp <= 5) 73 | p1 = [waypoints(wp-1,1),waypoints(wp,1)]; 74 | p2 = [waypoints(wp-1,2),waypoints(wp,2)]; 75 | p3 = [waypoints(wp-1,3),waypoints(wp,3)]; 76 | plot(p1,p2,'--k','LineWidth',1); 77 | end 78 | pause(0.01); 79 | hold on 80 | grid on 81 | end 82 | hold on 83 | title('LQR based Path Following') 84 | legend ('Desired Path','Path (Adaptive Optimal Guidance Law)'); 85 | xlabel('X(m)') % x-axis label 86 | ylabel('Y(m)') % y-axis label 87 | xlim([-400 400]) 88 | ylim([-100 750]) 89 | -------------------------------------------------------------------------------- /LQR/ode_lqr.m: -------------------------------------------------------------------------------- 1 | function [dydt] = ode_lqr(t,y,w1_x,w1_y,w2_x,w2_y,c) 2 | 3 | %% Author - Mandeep Singh 4 | % Email - mandeep14145@iiitd.ac.in 5 | 6 | %% Initializating Params 7 | dydt = zeros(4,1); 8 | 9 | v = 10; 10 | 11 | db = 4; 12 | q2 = 1; 13 | Rmin = 75; 14 | 15 | %% XY Controller 16 | 17 | % Computing the position error 18 | % Distance of point to line (UGV Position - Desired path) 19 | 20 | pt = [y(1) y(2) 0]; % UGV Positon vector 21 | a1 = [w1_x w1_y 0]; % Waypoint 1 Vector 22 | a2 = [w2_x w2_y 0]; % Waypoint 2 Vector 23 | 24 | tmp = (y(1) - w1_x)*(w2_y - w1_y) - (y(2) - w1_y)*(w2_x - w1_x); 25 | % To check whether the point is left or right of the desired path 26 | if(tmp < 0) 27 | d = point_to_line(pt,a1,a2); 28 | else 29 | d = -point_to_line(pt,a1,a2); 30 | end 31 | % d = y(4) 32 | 33 | % LQR Formualtion 34 | q1 = sqrt(abs(db/(db - d))); 35 | % k = 0.0001; 36 | % q1 = sqrt(exp(k*(abs(d)))); 37 | si = y(3); 38 | si_p = atan2((w2_y - w1_y),(w2_x - w1_x)); % si desired 39 | vd = v*sin(si - si_p); % d_dot 40 | u = -(q1*d + sqrt(2*q1 + q2^2)*vd); 41 | 42 | % Constraining the control input 43 | % if(abs(u) > (v^2)/Rmin) 44 | % if (u > 0) 45 | % u = (v^2)/Rmin; 46 | % else 47 | % u = -(v^2)/Rmin; 48 | % end 49 | % end 50 | 51 | % Finally heading angle 52 | si_dot = u; 53 | 54 | %% STATE EQUATIONS 55 | dydt(1) = v*cos(si); % y(1) -> uav_x 56 | dydt(2) = v*sin(si); % y(2) -> uav_y 57 | dydt(3) = si_dot; % y(3) -> si 58 | dydt(4) = vd; % y(4) -> d -------------------------------------------------------------------------------- /LQR/point_to_line.m: -------------------------------------------------------------------------------- 1 | function d = point_to_line(pt, v1, v2) 2 | a = v1 - v2; 3 | b = pt - v2; 4 | d = norm(cross(a,b)) / norm(a); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Path-Following-Algorithms 2 | Carrot Chase, Linear Quadratic Regualtor Control (LQR), PID Control 3 | 4 | ![Image of Carrot Chase Results](https://github.com/HobbySingh/Path-Following-Algorithms/blob/master/Carrot%20Chase/carrot_chase.png) 5 | ![Image of LQR Control](https://github.com/HobbySingh/Path-Following-Algorithms/blob/master/LQR/LQR.png) 6 | --------------------------------------------------------------------------------