• S曲线控制


     关于运动控制中S型速度曲线的简单演示(C++实现)_速度曲线算位置曲线-CSDN博客

    步进电机有很多种算法,主要集中在速度的控制,其中S比较常见。上边是其他作者的作品, 这里截取一段代码 作为记录。

    1. #include
    2. #include
    3. #define FP64 double
    4. int main(void)
    5. {
    6. /**************************** 定义相关变量(需要映射到PLC寄存器才能进行监控) ***********************/
    7. FP64 v_start; //初速度
    8. FP64 v_end; //末速度
    9. FP64 v_max = 0; //最大速度(有匀速段时,v_max = v_target)
    10. /*根据需要修改*/
    11. v_start = 100;
    12. v_end = 150;
    13. FP64 s_target; //目标位移量
    14. FP64 v_target; //目标速度
    15. FP64 a_target; //目标加速度
    16. FP64 d_target; //目标减速度
    17. FP64 j_max; //目标加加速度
    18. FP64 t_sum;
    19. FP64 L; //算出的位移量
    20. FP64 v_real; //实际的最大速度
    21. FP64 s_max; //L>s_target时候规划的位移
    22. /*可以根据需要修改*/
    23. j_max = 2000; //目标加加速度
    24. a_target = 2000; //目标加速度
    25. d_target = 3000; //目标减速度
    26. v_target = 5000; //目标速度
    27. s_target = 3000; //目标位移
    28. int t; //运行时间
    29. FP64 t_aver; //匀速区时间
    30. FP64 t1; //加加速时间
    31. FP64 t2; //匀加速时间
    32. FP64 t3; //减加速时间
    33. FP64 t4; //匀速运行时间
    34. FP64 t5;
    35. FP64 t6;
    36. FP64 t7;
    37. FP64 v1;
    38. FP64 v2;
    39. FP64 v3;
    40. FP64 v4;
    41. FP64 v5;
    42. FP64 v6;
    43. FP64 v7;
    44. FP64 a_max; //加速度最大值(拥有匀加速段时 a_max = a_target)
    45. FP64 d_max;
    46. FP64 s1; //加加速位移 s1
    47. FP64 s2; //匀加速位移 s2
    48. FP64 s3; //减加速位移 s3
    49. FP64 s4; //匀速位移 s4
    50. FP64 s5; //加减速位移 s5
    51. FP64 s6; //匀减速位移 s6
    52. FP64 s7; //减减速位移 s7
    53. FP64 s_acc; //加速区位移
    54. FP64 s_dec; //减速区位移
    55. FP64 j_cur; //当前加加速度
    56. FP64 a_cur; //当前加速度
    57. FP64 v_cur; //当前速度
    58. FP64 s_cur; //当前位移量
    59. FP64 v_down;
    60. FP64 v_low;
    61. FP64 v_high;
    62. short int end_count=0;
    63. short int flag = 0;
    64. short int flag1 = 0;
    65. short int count=0;
    66. for (t = 0; t < 10000000000; t++)
    67. {
    68. if (v_max == 0) //只有第一遍
    69. {
    70. /***********************************根据目标速度,加速度,加加速度等规划出加速区和减速区******************/
    71. if ((v_target - v_start) > a_target * a_target / j_max) //匀加速段
    72. {
    73. a_max = a_target;
    74. t1 = a_max / j_max;
    75. v1 = v_start + 0.5 * j_max * t1 * t1;
    76. s1 = v_start * t1 + (j_max * t1 * t1 * t1) / 6;
    77. t2 = (v_target - v_start) / a_max - t1;
    78. v2 = v1 + a_target * t2;
    79. s2 = v1 * t2 + 0.5 * a_max * t2 * t2;
    80. t3 = t1;
    81. v3 = v2 + a_max * t3 - 0.5 * j_max * t3 * t3;
    82. s3 = v2 * t3 + j_max * t3 * t3 * t3 / 3;
    83. }
    84. else
    85. {
    86. a_max = sqrt((v_target - v_start) * j_max);
    87. t1 = sqrt((v_target - v_start) / j_max);
    88. s1 = v_start * t1 + (j_max * t1 * t1 * t1) / 6;
    89. v1 = v_start + 0.5 * j_max * t1 * t1;
    90. t2 = 0;
    91. v2 = v1;
    92. s2 = 0;
    93. t3 = t1;
    94. s3 = v2 * t3 + j_max * t3 * t3 * t3 / 3;
    95. v3 = v2 + a_max * t3 - 0.5 * j_max * t3 * t3;
    96. }
    97. if (v_target - v_end > (d_target * d_target) / j_max)
    98. {
    99. d_max = d_target;
    100. t7 = d_max / j_max;
    101. s7 = v_end * t7 + (j_max * t7 * t7 * t7) / 6;
    102. v6 = v_end + 0.5 * j_max * t7 * t7;
    103. t6 = (v_target - v_end) / d_max - t7;
    104. s6 = v6 * t6 + 0.5 * d_max * t6 * t6;
    105. v5 = v6 + d_target * t6;
    106. t5 = t7;
    107. s5 = v5 * t5 + j_max * t5 * t5 * t5 / 3;
    108. }
    109. else
    110. {
    111. d_max = sqrt((v_target - v_end) * j_max);
    112. t7 = sqrt((v_target - v_end) / j_max);
    113. s7 = v_end * t7 + (j_max * t7 * t7 * t7) / 6;
    114. v6 = v_end + 0.5 * j_max * t7 * t7;
    115. t6 = 0;
    116. s6 = 0;
    117. t5 = t7;
    118. v5 = v6;
    119. s5 = v3 * t5 - j_max * t5 * t5 * t5 / 6;
    120. }
    121. L = 0.5 * ((v_start + v_target) * (t1 + t2 + t3) + (v_end + v_target) * (t5 + t6 + t7));
    122. }
    123. if (L >= s_target && v_max == 0) //如果 L >= s_target,那么达不到目标速度,需要规划出实际最大速度,只有第一遍循环会进这个程序
    124. {
    125. t4 = 0;
    126. s4 = 0;
    127. v4 = v3;
    128. v_high = v_target;
    129. /*初速度较大*/
    130. if (v_start > v_end)
    131. {
    132. v_low = v_start;
    133. }
    134. /*末速度较大*/
    135. else if (v_end > v_start)
    136. {
    137. v_low = v_end;
    138. end_count += 1;
    139. }
    140. v_max = 0.5 * (v_low + v_high);
    141. }
    142. /*如果 L < s_target 那么可以正常进行规划(有匀速段),标志位flag1=1*/
    143. else if (L < s_target)
    144. {
    145. v_max = v_target;
    146. flag1 = 1;
    147. }
    148. /*********************************** 根据二分处理后的速度再算位移 ******************/
    149. if ((v_max - v_start) > a_target * a_target / j_max) //匀加速段
    150. {
    151. a_max = a_target;
    152. t1 = a_max / j_max;
    153. v1 = v_start + 0.5 * j_max * t1 * t1;
    154. s1 = v_start * t1 + (j_max * t1 * t1 * t1) / 6;
    155. t2 = (v_max - v_start) / a_max - t1;
    156. v2 = v1 + a_target * t2;
    157. s2 = v1 * t2 + 0.5 * a_max * t2 * t2;
    158. t3 = t1;
    159. v3 = v2 + a_max * t3 - 0.5 * j_max * t3 * t3;
    160. s3 = v2 * t3 + j_max * t3 * t3 * t3 / 3;
    161. }
    162. else
    163. {
    164. a_max = sqrt((v_max - v_start) * j_max);
    165. t1 = sqrt((v_max - v_start) / j_max);
    166. s1 = v_start * t1 + (j_max * t1 * t1 * t1) / 6;
    167. v1 = v_start + 0.5 * j_max * t1 * t1;
    168. t2 = 0;
    169. v2 = v1;
    170. s2 = 0;
    171. t3 = t1;
    172. s3 = v2 * t3 + j_max * t3 * t3 * t3 / 3;
    173. v3 = v2 + a_max * t3 - 0.5 * j_max * t3 * t3;
    174. }
    175. if (v_max - v_end > (d_target * d_target) / j_max) //匀减速段
    176. {
    177. d_max = d_target;
    178. t7 = d_max / j_max;
    179. s7 = v_end * t7 + (j_max * t7 * t7 * t7) / 6;
    180. v6 = v_end + 0.5 * j_max * t7 * t7;
    181. t6 = (v_max - v_end) / d_max - t7;
    182. s6 = v6 * t6 + 0.5 * d_max * t6 * t6;
    183. v5 = v6 + d_target * t6;
    184. t5 = t7;
    185. s5 = v5 * t5 + j_max * t5 * t5 * t5 / 3;
    186. }
    187. else
    188. {
    189. d_max = sqrt((v_max - v_end) * j_max);
    190. t7 = sqrt((v_max - v_end) / j_max);
    191. s7 = v_end * t7 + (j_max * t7 * t7 * t7) / 6;
    192. v6 = v_end + 0.5 * j_max * t7 * t7;
    193. t6 = 0;
    194. s6 = 0;
    195. t5 = t7;
    196. v5 = v6;
    197. s5 = v3 * t5 - j_max * t5 * t5 * t5 / 6;
    198. }
    199. s_max = s1 + s2 + s3 + s5 + s6 + s7; //s_max是二分后的位移
    200. /*二分后的位移无限接近目标位移,则标志位flag=1,开始规划*/
    201. if (s_max - s_target < 0.001 && s_max - s_target > 0)
    202. {
    203. flag = 1;
    204. }
    205. /*否则继续二分*/
    206. else
    207. {
    208. //二分法思想:改变上下限
    209. if (s_max < s_target) //如果规划出来的位移偏小
    210. {
    211. v_low = v_max;
    212. }
    213. else { //如果规划出来的位移偏大
    214. v_high = v_max;
    215. }
    216. v_max = 0.5 * (v_low + v_high);
    217. }
    218. /*********************************** 只有在标志位置位时才规划(画图) ******************/
    219. if (flag == 1 || flag1 == 1)
    220. {
    221. if (flag1 == 1 )
    222. {
    223. /*正常进行规划*/
    224. t4 = (s_target - L) / v_max;
    225. v4 = v3;
    226. s4 = v4 * t4;
    227. }
    228. else if (flag == 1)
    229. {
    230. t4 = 0;
    231. v4 = v3;
    232. s4 = 0;
    233. }
    234. t_sum = t1 + t2 + t3 + t4 + t5 + t6 + t7;
    235. if (t >= 0 && t < t1)
    236. {
    237. j_cur = j_max;
    238. a_cur = j_cur * t;
    239. v_cur = v_start + 0.5 * j_cur * t * t;
    240. s_cur = v_start * t + j_cur * t * t * t / 6;
    241. }
    242. else if (t >= t1 && t < t1 + t2 && t2 != 0)
    243. {
    244. j_cur = 0;
    245. a_cur = a_max;
    246. v_cur = v1 + a_cur * (t - t1);
    247. s_cur = s1 + v1 * (t - t1) + 0.5 * a_cur * (t - t1) * (t - t1);
    248. }
    249. else if (t >= t1 + t2 && t < t1 + t2 + t3)
    250. {
    251. j_cur = -j_max;
    252. a_cur = a_max - j_max * (t - t1 - t2);
    253. v_cur = v2 + a_max * (t - t1 - t2) - 0.5 * j_max * (t - t1 - t2) * (t - t1 - t2);
    254. s_cur = s1 + s2 + v2 * (t - t1 - t2) + 0.5 * a_max * (t - t1 - t2) * (t - t1 - t2) - j_max * (t - t1 - t2) * (t - t1 - t2) * (t - t1 - t2) / 6;
    255. }
    256. else if (t >= t1 + t2 + t3 && t < t1 + t2 + t3 + t4 && t4 != 0)
    257. {
    258. j_cur = 0;
    259. a_cur = 0;
    260. v_cur = v3;
    261. s_cur = s1 + s2 + s3 + v3 * (t - t1 - t2 - t3);
    262. }
    263. else if (t >= t1 + t2 + t3 + t4 && t < t1 + t2 + t3 + t4 + t5)
    264. {
    265. j_cur = -j_max;
    266. a_cur = -j_max * (t - t1 - t2 - t3 - t4);
    267. v_cur = v4 - 0.5 * j_max * (t - t1 - t2 - t3 - t4) * (t - t1 - t2 - t3 - t4);
    268. s_cur = s1 + s2 + s3 + s4 + v4 * (t - t1 - t2 - t3 - t4) - j_max * (t - t1 - t2 - t3 - t4) * (t - t1 - t2 - t3 - t4) * (t - t1 - t2 - t3 - t4) / 6;
    269. }
    270. else if (t >= t1 + t2 + t3 + t4 + t5 && t < t1 + t2 + t3 + t4 + t5 + t6 && t6 != 0)
    271. {
    272. j_cur = 0;
    273. a_cur = -d_max;
    274. v_cur = v5 - d_target * (t - t1 - t2 - t3 - t4 - t5);
    275. s_cur = s1 + s2 + s3 + s4 + s5 + v5 * (t - t1 - t2 - t3 - t4 - t5) - 0.5 * d_target * (t - t1 - t2 - t3 - t4 - t5) * (t - t1 - t2 - t3 - t4 - t5);
    276. }
    277. else if (t >= t1 + t2 + t3 + t4 + t5 + t6 && t < t1 + t2 + t3 + t4 + t5 + t6 + t7)
    278. {
    279. j_cur = j_max;
    280. a_cur = -d_max + j_max * (t - t1 - t2 - t3 - t4 - t5 - t6);
    281. v_cur = v6 - d_max * (t - t1 - t2 - t3 - t4 - t5 - t6) + 0.5 * j_max * (t - t1 - t2 - t3 - t4 - t5 - t6) * (t - t1 - t2 - t3 - t4 - t5 - t6);
    282. s_cur = s1 + s2 + s3 + s4 + s5 + s6 + v6 * (t - t1 - t2 - t3 - t4 - t5 - t6) - 0.5 * d_max * (t - t1 - t2 - t3 - t4 - t5 - t6) * (t - t1 - t2 - t3 - t4 - t5 - t6) + j_max * (t - t1 - t2 - t3 - t4 - t5 - t6) * (t - t1 - t2 - t3 - t4 - t5 - t6) * (t - t1 - t2 - t3 - t4 - t5 - t6) / 6;
    283. }
    284. else if (t > t1 + t2 + t3 + t4 + t5 + t6 + t7)
    285. {
    286. a_cur = 0;
    287. j_cur = 0;
    288. v_cur = v_end;
    289. return;
    290. }
    291. }
    292. }
    293. }

  • 相关阅读:
    websocket与Socket的区别
    Axure绘制星级评分
    Go 微服务开发框架 DMicro 的设计思路
    在3+1的方向上展开结构加法4a3+4a14
    通过Shell脚本自动安装Hive&JDBC测试&提供CDH5网盘地址
    Java Properties类
    Java——》JVM对原生的锁做了哪些优化
    终日乾乾,夕惕若厉
    NIFI实现数据库数据增量同步
    [ 红队知识库 ] 常见防火墙(WAF)拦截页面
  • 原文地址:https://blog.csdn.net/david10000/article/details/133852909