Guest User

Untitled

a guest
Jan 17th, 2018
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.17 KB | None | 0 0
  1. % double pendulum on a cart
  2.  
  3. clear all;
  4. close all;
  5. clc;
  6.  
  7. N = 200; % Control discretization
  8.  
  9. opti = casadi.Opti();
  10. import casadi.*
  11.  
  12. mcart = 0.1;
  13. m1 = 1;
  14. m2 = 1;
  15. l1 = 0.3;
  16. l2 = 0.3;
  17. g = 9.81;
  18.  
  19. % declare variables
  20. % states
  21. x = opti.variable(6,N+1);
  22. pos = x(1,:); % position
  23. theta1 = x(2,:); % angle1
  24. theta2 = x(3,:); % angle2
  25. dpos = x(4,:);
  26. dtheta1 = x(5,:);
  27. dtheta2 = x(6,:);
  28.  
  29. % controls
  30. u = opti.variable(N,1); % acceleration, ddpos
  31. % time
  32. T = opti.variable(1,1); % motion time
  33.  
  34. % Todo: put in separate function
  35.  
  36. % symbolic description of Lagrangian
  37. pos_s = SX.sym('pos');
  38. theta1_s = SX.sym('theta1');
  39. theta2_s = SX.sym('theta2');
  40. dpos_s = SX.sym('dpos');
  41. dtheta1_s = SX.sym('dtheta1');
  42. dtheta2_s = SX.sym('dtheta2');
  43.  
  44. q = [pos_s;theta1_s;theta2_s];
  45. dq = [dpos_s;dtheta1_s;dtheta2_s];
  46. ddq = SX.sym('ddq',size(q));
  47.  
  48. x0 = pos_s;
  49. y0 = 0;
  50. x1 = x0+l1*sin(theta1_s);
  51. y1 = y0+l1*cos(theta1_s);
  52. x2 = x1+l2*sin(theta2_s);
  53. y2 = y1+l2*cos(theta2_s);
  54.  
  55. E_pot = m1*g*y1+m2*g*y2;
  56.  
  57. v0 = jtimes([x0;y0],q,dq);
  58. v1 = jtimes([x1;y1],q,dq);
  59. v2 = jtimes([x2;y2],q,dq);
  60.  
  61. E_kin = 1/2*mcart*(v0'*v0)+1/2*m1*(v1'*v1) + 1/2*m2*(v2'*v2);
  62.  
  63. % Lagrange function for translation part
  64. Lag = E_kin - E_pot;
  65.  
  66. u_s = SX.sym('u');
  67.  
  68. % Lagrange equations: eq(q,dq,ddq,u) == 0
  69. eq = jtimes(gradient(Lag,dq),[q;dq],[dq;ddq]) - gradient(Lag,q) - [u_s;0;0];
  70. % jtimes(f,x,y) = jacobian(f,x)*y
  71.  
  72. % Write ddq as function of q,dq,u
  73. ddqsol = -jacobian(eq,ddq)\substitute(eq,ddq,0);
  74.  
  75. % ODE rhs function
  76. ode = casadi.Function('ode',{[q;dq],u_s},{[dq;ddqsol]});
  77.  
  78. % state limits
  79. pos_lim = 2;
  80.  
  81. % input limits
  82. u_lim = 50;
  83.  
  84. % Initial and terminal constraints
  85. x_init = [0;pi;pi;0;0;0]; % stable
  86. x_final = [0;0;0;0;0;0]; % swing up
  87.  
  88. T_s = SX.sym('T');
  89.  
  90. for k=1:N
  91. % shooting constraint
  92. xf = rk4(ode,T/N,x(:,k),u(k));
  93. opti.subject_to(x(:,k+1)==xf);
  94. end
  95.  
  96. % path constraint
  97. opti.subject_to(-pos_lim <= pos <= pos_lim);
  98. opti.subject_to(-u_lim <= u <= u_lim);
  99. opti.subject_to(T >= 0);
  100.  
  101. opti.subject_to(x(:,1)==x_init);
  102. opti.subject_to(x(:,end)==x_final);
  103.  
  104. opti.minimize(T);
  105.  
  106. % set initial guess
  107. opti.set_initial(theta1,linspace(pi,0,N+1));
  108. opti.set_initial(theta2,linspace(pi,0,N+1));
  109. opti.set_initial(T,1);
  110.  
  111. opti.callback(@(i) plot( linspace(0,opti.debug.value(T), N+1) , opti.debug.value(x(1:3,:)) ) )
  112.  
  113. % solve optimization problem
  114. opti.solver('ipopt');
  115.  
  116. sol = opti.solve();
  117.  
  118. % retrieve the solution
  119. pos_opt = sol.value(pos);
  120. dpos_opt = sol.value(dpos);
  121. theta1_opt = sol.value(theta1);
  122. dtheta1_opt = sol.value(dtheta1);
  123. theta2_opt = sol.value(theta2);
  124. dtheta2_opt = sol.value(dtheta2);
  125. u_opt = sol.value(u);
  126. T_opt = sol.value(T);
  127.  
  128. % time grid for printing
  129. tgrid = linspace(0,T_opt, N+1);
  130.  
  131. figure;
  132. subplot(3,1,1)
  133. hold on
  134. plot(tgrid, pos_opt, 'b')
  135. plot(tgrid, theta1_opt, 'r')
  136. plot(tgrid, theta2_opt, 'k')
  137. legend('pos [m]','theta1 [rad]','theta2 [rad]')
  138. xlabel('Time [s]')
  139. subplot(3,1,2)
  140. hold on
  141. plot(tgrid, dpos_opt, 'b')
  142. plot(tgrid, theta1_opt, 'r')
  143. plot(tgrid, theta2_opt, 'k')
  144. legend('dpos [m/s]','dtheta1 [rad/s]','dtheta2 [rad/s]')
  145. xlabel('Time [s]')
  146. subplot(3,1,3)
  147. stairs(tgrid(1:end-1), u_opt, 'b')
  148. legend('u [m/s^2]')
  149. xlabel('Time [s]')
  150.  
  151. % make animation
  152.  
  153. x0 = pos_opt;
  154. x1 = x0+l1*sin(theta1_opt);
  155. y1 = l1*cos(theta1_opt);
  156. x2 = x1+l2*sin(theta2_opt);
  157. y2 = y1+l2*cos(theta2_opt);
  158.  
  159. figure(10)
  160. axes('nextplot','replacechildren')
  161. xlim([-0.6 0.6])
  162. ylim([-l1-l2-0.1 l1+l2+0.1])
  163. hold on
  164. line([x0(1),x1(1),x2(1)],[0,y1(1),y2(1)],'LineWidth',3);
  165. plot(x1(1),y1(1),'bo')
  166. plot(x2(1),y2(1),'bo')
  167. plot([-0.6,0.6],[0,0],'LineWidth',2, 'color','red')
  168. xlim([-3,3])
  169. ylim([-0.7,0.7])
  170. axis equal
  171. for k = 1:N+1
  172. line([x0(k),x1(k),x2(k)],[0,y1(k),y2(k)],'LineWidth',3);
  173. plot(x1(k),y1(k),'bo')
  174. plot(x2(k),y2(k),'bo')
  175. plot([-0.6,0.6],[0,0],'LineWidth',2, 'color','red')
  176. drawnow
  177. pause(0.1)
  178. cla
  179. end
  180.  
  181. % simscape validation
  182.  
  183. open_system('double_pendulum');
  184.  
  185. double_pendulum([],[],[],'compile');
  186.  
  187. s = rand(6,1);
  188.  
  189. % In the simulink model, the order is [pos;dpos;alpha1;dalpha1;alpha2;dalpha2]
  190. % with alpha1 = theta1 and alpha2 = theta2-theta1
  191. r = double_pendulum(0,[s(1);s(4);s(2);s(5);s(3)-s(2);s(6)-s(5);0;0],[],'derivs');
  192. ref=[r(1);r(3);r(3)+r(5);r(2);r(4);r(4)+r(6)];
  193. ours = full(ode(s,0));
  194.  
  195. mismatch = norm(ref-ours)
  196. assert(mismatch<1e-12)
  197.  
  198. double_pendulum(0,[],[],'term')
  199.  
  200. sim('double_pendulum')
Add Comment
Please, Sign In to add comment