moveitServer2.py 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # 导入基本ros和moveit库
  4. from logging.handlers import RotatingFileHandler
  5. import os
  6. import rospy, sys
  7. import moveit_commander
  8. import moveit_msgs
  9. from moveit_commander import MoveGroupCommander, PlanningSceneInterface, RobotCommander
  10. from moveit_msgs.msg import PlanningScene, ObjectColor,CollisionObject, AttachedCollisionObject,RobotTrajectory
  11. from moveit_msgs.msg import RobotState
  12. from moveit_msgs.msg import Constraints, PositionConstraint, OrientationConstraint
  13. from shape_msgs.msg import SolidPrimitive
  14. from sensor_msgs.msg import JointState
  15. import tf.transformations
  16. from trajectory_msgs.msg import JointTrajectory,JointTrajectoryPoint
  17. from geometry_msgs.msg import PoseStamped, Pose,Point,Vector3
  18. from copy import deepcopy
  19. import numpy as np
  20. import tf
  21. from tf.transformations import euler_from_quaternion,quaternion_from_euler,quaternion_from_euler, quaternion_multiply
  22. import math
  23. import traceback
  24. import check
  25. from lstrobot_planning.msg import JointTrajectoryPoint_ex,JointTrajectory_ex
  26. pi = np.pi
  27. class MoveIt_Control:
  28. # 初始化程序
  29. def __init__(self, is_use_gripper=False):
  30. self.home_pose=[]
  31. # Init ros config
  32. moveit_commander.roscpp_initialize(sys.argv)
  33. # 初始化ROS节点
  34. rospy.init_node('moveit_control_server', anonymous=False)
  35. self.arm = moveit_commander.MoveGroupCommander('manipulator')
  36. self.arm.set_goal_joint_tolerance(0.0001)
  37. self.arm.set_goal_position_tolerance(0.0005)
  38. self.arm.set_goal_orientation_tolerance(0.1)
  39. self.end_effector_link = self.arm.get_end_effector_link()
  40. # 设置机械臂基座的参考系
  41. self.reference_frame = 'base_link'
  42. self.arm.set_pose_reference_frame(self.reference_frame)
  43. # # 设置最大规划时间和是否允许重新规划
  44. self.arm.set_planning_time(10)
  45. self.arm.allow_replanning(True)
  46. planner_id = rospy.get_param("planner_id")
  47. # self.arm.set_planner_id(planner_id)
  48. # self.arm.set_planner_id("RRTstar")
  49. # self.arm.set_planner_id("SBL")
  50. # self.arm.set_planner_id("BKPIECE")#速度快,比较稳定
  51. # self.arm.set_planner_id("BiEST")#还不错
  52. # 设置允许的最大速度和加速度(范围:0~1)
  53. robot_params = {
  54. 'velocity_limits': True,
  55. 'joint_max_velocity': [3.541, 3.541, 3.733, 6.838, 4.815, 23.655],
  56. 'acceleration_limits': False,
  57. 'joint_max_acceleration': [0, 0, 0, 0, 0, 0]
  58. }
  59. self.arm.set_max_acceleration_scaling_factor(1)
  60. self.arm.set_max_velocity_scaling_factor(1)
  61. # 机械臂初始姿态
  62. self.go_home()
  63. home_pose=self.get_now_pose()
  64. def get_now_pose(self):
  65. # 获取机械臂当前位姿
  66. current_pose = self.arm.get_current_pose(self.end_effector_link).pose
  67. pose=[]
  68. pose.append(current_pose.position.x)
  69. pose.append(current_pose.position.y)
  70. pose.append(current_pose.position.z)
  71. pose.append(current_pose.orientation.x)
  72. pose.append(current_pose.orientation.y)
  73. pose.append(current_pose.orientation.z)
  74. pose.append(current_pose.orientation.w)
  75. # 打印位姿信息
  76. #rospy.lohome_poseinfo("Current Pose: {}".format(pose))
  77. return pose
  78. def close(self):
  79. moveit_commander.roscpp_shutdown()
  80. moveit_commander.os._exit(0)
  81. def create_path_constraints2(self,start_point,end_point,r):#创建路径约束
  82. #计算起点指向终点的向量
  83. vector = np.array([end_point[0]- start_point[0], end_point[1]- start_point[1], end_point[2]- start_point[2]])
  84. height = np.linalg.norm(vector)+0.006 #计算向量或矩阵的范数 用于度量向量或矩阵的大小或长度
  85. radius = r
  86. # 位置约束
  87. position_constraint = PositionConstraint()#创建点位约束
  88. position_constraint.header.frame_id = "base_link"#此约束所指的机器人链接
  89. position_constraint.link_name = self.end_effector_link
  90. position_constraint.target_point_offset = Vector3(0, 0, 0)#目标点的偏移量
  91. position_constraint.weight = 1.0#质量 OR 加权因子?
  92. #构建 shape_msgs/SolidPrimitive 消息
  93. bounding_volume = SolidPrimitive()
  94. bounding_volume.type = SolidPrimitive.CYLINDER#圆柱
  95. # bounding_volume.dimensions = [0.003,1]
  96. bounding_volume.dimensions = [height,radius]#尺寸 高度 半径
  97. position_constraint.constraint_region.primitives.append(bounding_volume)
  98. #构建 geometry_msgs/Pose 消息,用于指定圆柱体在空间中的位置和姿态
  99. pose = Pose()
  100. pose.position.x = start_point[0] + vector[0] / 2#定义位置(找了个几何中心)
  101. pose.position.y = start_point[1] + vector[1] / 2
  102. pose.position.z = start_point[2] + vector[2] / 2
  103. # 计算圆柱体的姿态
  104. z_axis = np.array([0, 0, 1])
  105. axis = np.cross(z_axis, vector) #计算两个向量(向量数组)的叉乘 叉乘返回的数组既垂直于a,又垂直于b
  106. angle = np.arccos(np.dot(z_axis, vector) / np.linalg.norm(vector))#反余弦求角度
  107. q = tf.transformations.quaternion_about_axis(angle, axis)#通过旋转轴和旋转角返回四元数
  108. pose.orientation.x = q[0]
  109. pose.orientation.y = q[1]
  110. pose.orientation.z = q[2]
  111. pose.orientation.w = q[3]
  112. position_constraint.constraint_region.primitive_poses.append(pose)
  113. constraints = Constraints()#创建一个新的约束信息
  114. constraints.position_constraints.append(position_constraint)
  115. # constraints.orientation_constraints.append(orientation_constraint)
  116. return constraints
  117. def move_p_flexible(self,point,points,trajectory,trajectory_with_type,a=1,v=1):
  118. self.arm.set_max_acceleration_scaling_factor(a)
  119. self.arm.set_max_velocity_scaling_factor(v)
  120. rrr=0.05#初始允许半径
  121. if trajectory:
  122. #起点位置设置为规划组最后一个点
  123. state = self.arm.get_current_state()
  124. state.joint_state.position = trajectory[-1].joint_trajectory.points[-1].positions
  125. # 创建路径约束
  126. path_constraints = self.create_path_constraints2(points[-1],point,rrr)#将最后一个点和输入的点(焊缝的起始点)做圆柱轨迹约束
  127. self.arm.set_path_constraints(path_constraints)#设定约束
  128. else:
  129. #起点位置设定为当前状态 按理来说是home点
  130. self.go_home()
  131. self.home_pose=self.get_now_pose()
  132. #rospy.loginfo(self.home_pose)
  133. state = self.arm.get_current_state()
  134. # 创建路径约束
  135. path_constraints = self.create_path_constraints2(self.home_pose,point,rrr)#将当前的点和输入的点(焊缝的起始点)做圆柱轨迹约束
  136. self.arm.set_path_constraints(path_constraints)#设定约束
  137. self.arm.set_pose_target(point, self.end_effector_link)#设定目标点为传入的点
  138. self.arm.set_start_state(state)#起点位置设置为规划组最后一个点 或者当前状态(第一个点时)
  139. #当前起点规划次数
  140. #尝试规划次数
  141. b = 16 #尝试规划10次
  142. for i in range(b):
  143. traj = self.arm.plan()#调用plan进行规划
  144. trajj = traj[1] #取出规划的信息
  145. error,Limit_margin = check.check_joint_positions(trajj)#检查关节状态 就是检测规划的轨迹有没有“摇花手”
  146. if not error:#如果没有摇花手 接受规划
  147. rospy.loginfo("本次移动 OK")
  148. break
  149. else:
  150. rospy.loginfo("移动规划失败-开始第{}次重新规划".format(i+1))
  151. if i%2==0 and i!=0:#10次了都没成功 重新修改约束
  152. self.arm.clear_path_constraints()
  153. rrr=rrr+0.1#每次增加10厘米
  154. path_constraints = self.create_path_constraints2(self.home_pose,point,rrr)#将最后一个点和输入的点(焊缝的起始点)做圆柱轨迹约束
  155. self.arm.set_path_constraints(path_constraints)#设定约束
  156. #规划失败
  157. if error:
  158. rospy.loginfo("{}次移动规划失败,进程终止".format(b))
  159. sys.exit()
  160. #清除约束
  161. self.arm.clear_path_constraints()
  162. trajj_with_type = mark_the_traj(trajj,"during-l",welding_sequence)
  163. trajj_with_type.points[-len(trajj.joint_trajectory.points)].type = "start"
  164. trajj_with_type.points[-1].type = "end"
  165. trajectory_with_type.append(trajj_with_type)
  166. points.append(point)
  167. trajectory.append(trajj)
  168. return points,trajectory,trajectory_with_type
  169. # 测试程序用
  170. def testRobot(self):
  171. try:
  172. rospy.loginfo("Test for robot...")
  173. file_path_result = os.path.join(folder_path, 'result.txt')
  174. all_data = process_welding_data(file_path_result)
  175. points,trajectory,trajectory_with_type = [],[],[]
  176. for i in range(len(all_data)):
  177. rospy.loginfo("共读取到%d条焊缝,开始规划第%d条",len(all_data),i+1)
  178. start_point = all_data[i][0]
  179. end_point = all_data[i][1]
  180. q1 = all_data[i][2]
  181. q2 = all_data[i][3]
  182. point11 = [start_point[0]/1000, start_point[1]/1000, start_point[2]/1000, q1[0],q1[1],q1[2],q1[3]]
  183. self.move_p(point11)
  184. point22 = [end_point[0]/1000, end_point[1]/1000, end_point[2]/1000, q2[0],q2[1],q2[2],q2[3]]
  185. self.move_p(point22)
  186. rospy.loginfo("第%d条焊缝规划完毕",i+1)
  187. # joint_position = [x * math.pi / 180 for x in [11.016, 3.716, -19.553, -5.375, -32.4173, 109.158]]
  188. # self.move_j(joint_position)
  189. # self.show_current_pose()
  190. print("Test OK")
  191. rospy.sleep(1)
  192. except Exception as e:
  193. print("Test fail! Exception:", str(e))
  194. traceback.print_exc()
  195. # except:
  196. # print("Test fail! ")
  197. def show_current_pose(self):
  198. # 获取机械臂当前位姿
  199. current_pose = self.arm.get_current_pose(self.end_effector_link).pose
  200. pose=[]
  201. pose.append(current_pose.position.x)
  202. pose.append(current_pose.position.y)
  203. pose.append(current_pose.position.z)
  204. pose.append(current_pose.orientation.x)
  205. pose.append(current_pose.orientation.y)
  206. pose.append(current_pose.orientation.z)
  207. # 打印位姿信息
  208. rospy.loginfo("Current Pose: {}".format(pose))
  209. def set_scene(self):
  210. rospy.loginfo("set scene")
  211. ## set table
  212. self.scene = PlanningSceneInterface()
  213. self.scene_pub = rospy.Publisher('planning_scene', PlanningScene, queue_size=5)
  214. self.colors = dict()
  215. # rospy.sleep(1)
  216. table_id = 'table'
  217. self.scene.remove_world_object(table_id)
  218. rospy.sleep(1)
  219. table_size = [2, 2, 0.01]
  220. table_pose = PoseStamped()
  221. table_pose.header.frame_id = self.reference_frame
  222. table_pose.pose.position.x = 0.0
  223. table_pose.pose.position.y = 0.0
  224. table_pose.pose.position.z = -table_size[2]/2
  225. table_pose.pose.orientation.w = 1.0
  226. box2_id = 'box2'
  227. self.scene.remove_world_object(box2_id)
  228. rospy.sleep(1)
  229. box2_size = [0.01, 0.6, 0.4]
  230. box2_pose = PoseStamped()
  231. box2_pose.header.frame_id = self.reference_frame
  232. box2_pose.pose.position.x = 1.15194-box2_size[0]/2-0.005
  233. box2_pose.pose.position.y = -0.707656
  234. box2_pose.pose.position.z = 0.4869005
  235. box2_pose.pose.orientation.w = 1.0
  236. box3_id = 'box3'
  237. self.scene.remove_world_object(box3_id)
  238. rospy.sleep(1)
  239. box3_size = [0.2, 0.01, 0.4]
  240. box3_pose = PoseStamped()
  241. box3_pose.header.frame_id = self.reference_frame
  242. box3_pose.pose.position.x = 1.15194+box3_size[0]/2
  243. box3_pose.pose.position.y = -0.707656-box3_size[1]/2-0.005
  244. box3_pose.pose.position.z = 0.4869005
  245. box3_pose.pose.orientation.w = 1.0
  246. # self.scene.add_box(table_id, table_pose, table_size)
  247. # self.scene.add_box(box2_id, box2_pose, box2_size)
  248. # self.scene.add_box(box3_id, box3_pose, box3_size)
  249. self.setColor(table_id, 0.5, 0.5, 0.5, 1.0)
  250. self.sendColors()
  251. rospy.loginfo("set scene end")
  252. def plan_cartesian_path(self,waypoints):
  253. fraction = 0.0 # 路径规划覆盖率
  254. maxtries = 100 # 最大尝试规划次数
  255. attempts = 0 # 已经尝试规划次数
  256. # 尝试规划一条笛卡尔空间下的路径,依次通过所有路点
  257. while fraction < 1.0 and attempts < maxtries:
  258. (plan, fraction) = self.arm.compute_cartesian_path(
  259. waypoints, # waypoint poses,路点列表
  260. 0.001, # eef_step,终端步进值
  261. 0.0, # jump_threshold,跳跃阈值
  262. True) # avoid_collisions,避障规划
  263. attempts += 1
  264. if fraction == 1.0:
  265. rospy.loginfo("Path computed successfully.")
  266. traj = plan
  267. else:
  268. rospy.loginfo(
  269. "Path planning failed with only " + str(fraction) +
  270. " success after " + str(maxtries) + " attempts.")
  271. return fraction,plan
  272. # 关节规划,输入6个关节角度(单位:弧度)
  273. def move_j(self, joint_configuration=None,a=1,v=1):
  274. # 设置机械臂的目标位置,使用六轴的位置数据进行描述(单位:弧度)
  275. if joint_configuration==None:
  276. joint_configuration = [0, -1.5707, 0, -1.5707, 0, 0]
  277. self.arm.set_max_acceleration_scaling_factor(a)
  278. self.arm.set_max_velocity_scaling_factor(v)
  279. self.arm.set_joint_value_target(joint_configuration)
  280. rospy.loginfo("move_j:"+str(joint_configuration))
  281. self.arm.go()
  282. rospy.sleep(1)
  283. # 空间规划,输入xyzRPY
  284. def move_p(self, tool_configuration=None,a=1,v=1):
  285. if tool_configuration==None:
  286. tool_configuration = [0.3,0,0.3,0,-np.pi/2,0]
  287. self.arm.set_max_acceleration_scaling_factor(a)
  288. self.arm.set_max_velocity_scaling_factor(v)
  289. target_pose = PoseStamped()
  290. target_pose.header.frame_id = 'base_link'
  291. target_pose.header.stamp = rospy.Time.now()
  292. target_pose.pose.position.x = tool_configuration[0]
  293. target_pose.pose.position.y = tool_configuration[1]
  294. target_pose.pose.position.z = tool_configuration[2]
  295. if len(tool_configuration) == 6:
  296. q = quaternion_from_euler(tool_configuration[3],tool_configuration[4],tool_configuration[5])
  297. target_pose.pose.orientation.x = q[0]
  298. target_pose.pose.orientation.y = q[1]
  299. target_pose.pose.orientation.z = q[2]
  300. target_pose.pose.orientation.w = q[3]
  301. else:
  302. target_pose.pose.orientation.x = tool_configuration[3]
  303. target_pose.pose.orientation.y = tool_configuration[4]
  304. target_pose.pose.orientation.z = tool_configuration[5]
  305. target_pose.pose.orientation.w = tool_configuration[6]
  306. self.arm.set_start_state_to_current_state()
  307. self.arm.set_pose_target(target_pose, self.end_effector_link)
  308. rospy.loginfo("move_p:" + str(tool_configuration))
  309. traj = self.arm.plan()
  310. path = traj[1]
  311. # file_path = "/home/chen/catkin_ws/src/lstrobot_planning/date/p_traj.txt"
  312. # if os.path.exists(file_path):
  313. # os.remove(file_path)
  314. # with open(file_path, "w") as file:
  315. # file.write(str(path))
  316. self.arm.execute(path)
  317. # rospy.sleep(1)
  318. def move_p2(self,point,points,trajectory,trajectory_with_type,a=1,v=1):
  319. self.arm.set_max_acceleration_scaling_factor(a)
  320. self.arm.set_max_velocity_scaling_factor(v)
  321. # self.arm.set_start_state_to_current_state()
  322. if trajectory:
  323. state = self.arm.get_current_state()
  324. state.joint_state.position = trajectory[-1].joint_trajectory.points[-1].positions
  325. self.arm.set_start_state(state)
  326. self.arm.set_pose_target(point, self.end_effector_link)
  327. rospy.loginfo("move_p:" + str(point))
  328. traj = self.arm.plan()
  329. trajj = traj[1]
  330. error_code =traj[3]
  331. rospy.loginfo("Move to start point planned successfully")
  332. trajj_with_type = mark_the_traj(trajj,"during-p",welding_sequence)
  333. points.append(point)
  334. trajectory.append(trajj)
  335. trajectory_with_type.append(trajj_with_type)
  336. return points,trajectory,trajectory_with_type
  337. def move_pl(self,point,points,trajectory,trajectory_with_type,a=1,v=1):
  338. self.arm.set_max_acceleration_scaling_factor(a)
  339. self.arm.set_max_velocity_scaling_factor(v)
  340. #设定约束
  341. if trajectory:
  342. #起点位置设置为规划组最后一个点
  343. state = self.arm.get_current_state()
  344. state.joint_state.position = trajectory[-1].joint_trajectory.points[-1].positions
  345. self.arm.set_start_state(state)#起点位置设置为规划组最后一个点
  346. self.arm.set_pose_target(point, self.end_effector_link)#设定目标点为传入的点
  347. # 创建路径约束
  348. path_constraints = self.create_path_constraints(points[-1],point)#将最后一个点和输入的点(焊缝的起始点)做圆柱轨迹约束
  349. self.arm.set_path_constraints(path_constraints)#设定约束
  350. #当前起点规划次数
  351. #尝试规划次数
  352. b = 20 #最多尝试规划10次
  353. for i in range(b):
  354. traj = self.arm.plan()#调用plan进行规划
  355. trajj = traj[1] #取出规划的信息
  356. error,Limit_margin = check.check_joint_positions(trajj)#检查关节状态 就是检测规划的轨迹有没有“摇花手”
  357. if not error:#如果没有摇花手 接受规划
  358. rospy.loginfo("本次焊缝规划 OK")
  359. break
  360. else:
  361. rospy.loginfo("焊缝规划失败-开始第{}次重新规划".format(i+1))
  362. # if i%10==0 and i!=0:#10次了都没成功 将这个点用p2规划
  363. # prePoint = points.pop()#移除列表中最后一个元素 返回被移除的对象
  364. # trajectory.pop()
  365. # trajectory_with_type.pop()
  366. # #清除约束
  367. # self.arm.clear_path_constraints()
  368. # points,trajectory,trajectory_with_type = self.move_p2(prePoint,points,trajectory,trajectory_with_type)
  369. # rospy.loginfo("第{}次尝试使用p2".format((i/10)%1))
  370. #规划失败
  371. if error:
  372. rospy.loginfo("{}次焊缝规划失败,进程终止".format(b))
  373. sys.exit()
  374. #清除约束
  375. self.arm.clear_path_constraints()
  376. trajj_with_type = mark_the_traj(trajj,"during-l",welding_sequence)
  377. trajj_with_type.points[-len(trajj.joint_trajectory.points)].type = "start"
  378. trajj_with_type.points[-1].type = "end"
  379. #如果调用了P2函数 那么这段代码不会导致重复添加?
  380. points.append(point)
  381. trajectory.append(trajj)
  382. trajectory_with_type.append(trajj_with_type)
  383. return points,trajectory,trajectory_with_type
  384. def create_path_constraints(self,start_point,end_point):
  385. #计算起点指向终点的向量
  386. vector = np.array([end_point[0]- start_point[0], end_point[1]- start_point[1], end_point[2]- start_point[2]])
  387. height = np.linalg.norm(vector)+0.002
  388. radius = 0.001
  389. constraints = Constraints()
  390. # 位置约束
  391. position_constraint = PositionConstraint()
  392. position_constraint.header.frame_id = "base_link"
  393. position_constraint.link_name = self.end_effector_link
  394. position_constraint.target_point_offset = Vector3(0, 0, 0)
  395. #构建 shape_msgs/SolidPrimitive 消息
  396. bounding_volume = SolidPrimitive()
  397. bounding_volume.type = SolidPrimitive.CYLINDER
  398. # bounding_volume.dimensions = [0.003,1]
  399. bounding_volume.dimensions = [height,radius]
  400. #构建 geometry_msgs/Pose 消息,用于指定圆柱体在空间中的位置和姿态
  401. pose = Pose()
  402. pose.position.x = start_point[0] + vector[0] / 2
  403. pose.position.y = start_point[1] + vector[1] / 2
  404. pose.position.z = start_point[2] + vector[2] / 2
  405. # 计算圆柱体的旋转矩阵
  406. z_axis = np.array([0, 0, 1])
  407. axis = np.cross(z_axis, vector)
  408. angle = np.arccos(np.dot(z_axis, vector) / np.linalg.norm(vector))
  409. q = tf.transformations.quaternion_about_axis(angle, axis)
  410. pose.orientation.x = q[0]
  411. pose.orientation.y = q[1]
  412. pose.orientation.z = q[2]
  413. pose.orientation.w = q[3]
  414. position_constraint.constraint_region.primitives.append(bounding_volume)
  415. position_constraint.constraint_region.primitive_poses.append(pose)
  416. position_constraint.weight = 1.0
  417. # 姿态约束
  418. # orientation_constraint = OrientationConstraint()
  419. # orientation_constraint.header.frame_id = "base_link"
  420. # orientation_constraint.link_name = self.end_effector_link
  421. # orientation_constraint.orientation = target_pose.orientation
  422. # orientation_constraint.absolute_x_axis_tolerance = 0.01
  423. # orientation_constraint.absolute_y_axis_tolerance = 0.01
  424. # orientation_constraint.absolute_z_axis_tolerance = 0.01
  425. # orientation_constraint.weight = 1.0
  426. constraints.position_constraints.append(position_constraint)
  427. # constraints.orientation_constraints.append(orientation_constraint)
  428. return constraints
  429. def move_l(self, tool_configuration,waypoints_number=1,a=0.5,v=0.5):
  430. if tool_configuration==None:
  431. tool_configuration = [0.3,0,0.3,0,-np.pi/2,0]
  432. self.arm.set_max_acceleration_scaling_factor(a)
  433. self.arm.set_max_velocity_scaling_factor(v)
  434. # 设置路点
  435. waypoints = []
  436. for i in range(waypoints_number):
  437. target_pose = PoseStamped()
  438. target_pose.header.frame_id = self.reference_frame
  439. target_pose.header.stamp = rospy.Time.now()
  440. target_pose.pose.position.x = tool_configuration[6*i+0]
  441. target_pose.pose.position.y = tool_configuration[6*i+1]
  442. target_pose.pose.position.z = tool_configuration[6*i+2]
  443. q = quaternion_from_euler(tool_configuration[6*i+3],tool_configuration[6*i+4],tool_configuration[6*i+5])
  444. target_pose.pose.orientation.x = q[0]
  445. target_pose.pose.orientation.y = q[1]
  446. target_pose.pose.orientation.z = q[2]
  447. target_pose.pose.orientation.w = q[3]
  448. waypoints.append(target_pose.pose)
  449. rospy.loginfo("move_l:" + str(tool_configuration))
  450. self.arm.set_start_state_to_current_state()
  451. fraction = 0.0 # 路径规划覆盖率
  452. maxtries = 100 # 最大尝试规划次数
  453. attempts = 0 # 已经尝试规划次数
  454. # 设置机器臂当前的状态作为运动初始状态
  455. self.arm.set_start_state_to_current_state()
  456. # 尝试规划一条笛卡尔空间下的路径,依次通过所有路点
  457. while fraction < 1.0 and attempts < maxtries:
  458. (plan, fraction) = self.arm.compute_cartesian_path(
  459. waypoints, # waypoint poses,路点列表
  460. 0.001, # eef_step,终端步进值
  461. 0.00, # jump_threshold,跳跃阈值
  462. True) # avoid_collisions,避障规划
  463. attempts += 1
  464. if fraction == 1.0:
  465. rospy.loginfo("Path computed successfully. Moving the arm.")
  466. self.arm.execute(plan)
  467. rospy.loginfo("Path execution complete.")
  468. else:
  469. rospy.loginfo(
  470. "Path planning failed with only " + str(fraction) +
  471. " success after " + str(maxtries) + " attempts.")
  472. rospy.sleep(1)
  473. def move_l22(self,point,points,trajectory,trajectory_with_type,a=0.5,v=0.5):
  474. self.arm.set_max_acceleration_scaling_factor(a)
  475. self.arm.set_max_velocity_scaling_factor(v)
  476. if trajectory:
  477. state = self.arm.get_current_state()
  478. state.joint_state.position = trajectory[-1].joint_trajectory.points[-1].positions
  479. self.arm.set_start_state(state)
  480. start_rotation_angle,end_rotation_angle = 0,0
  481. new_start_pose,new_end_pose = 0,0
  482. num_planed = 0
  483. while not start_rotation_angle == 2*pi:
  484. waypoints = []
  485. target_pose = point_to_PoseStamped(point,self.reference_frame)
  486. waypoints.append(target_pose.pose)
  487. rospy.loginfo("move_l2:" )
  488. num_remake = 2
  489. for _ in range(num_remake):
  490. num_planed +=1
  491. rospy.loginfo("第{}次规划".format(num_planed))
  492. rospy.loginfo("new_start_pose:{} new_end_pose:{}".format(new_start_pose,new_end_pose))
  493. fraction,traj = self.plan_cartesian_path(waypoints)
  494. if fraction == 1:
  495. error,percentage = check.check_joint_positions(traj)
  496. if not error:
  497. break
  498. if fraction != 1:
  499. break
  500. error,percentage = check.check_joint_positions(traj)
  501. if error:
  502. #三次重规划结束,仍然不符合,插点或转点
  503. angle_list = ([0,pi/4,-pi/4,pi/2,-pi/2,pi*3/4,-pi*3/4,pi,2*pi])
  504. if start_rotation_angle < pi:
  505. if end_rotation_angle < pi:
  506. index = angle_list.index(end_rotation_angle)
  507. end_rotation_angle = angle_list[index+1]
  508. new_end_pose = check.angle_adjustment(point,'z', start_rotation_angle) # 将目标位姿旋转一定角度
  509. point = new_end_pose # 将新的点替换原来位姿
  510. else:
  511. index = angle_list.index(start_rotation_angle)
  512. start_rotation_angle = angle_list[index+1]
  513. new_start_pose = check.angle_adjustment(points[-1],'z', start_rotation_angle) # 将目标位姿旋转一定角度
  514. #go home,plan p
  515. state = self.arm.get_current_state()
  516. state.joint_state.position = trajectory[-1].joint_trajectory.points[0].positions
  517. self.arm.set_start_state(state)
  518. del points[-1]
  519. del trajectory[-1]
  520. points,trajectory,trajectory_with_type = self.move_p2(new_start_pose,points,trajectory,trajectory_with_type)
  521. state.joint_state.position = trajectory[-1].joint_trajectory.points[-1].positions
  522. self.arm.set_start_state(state)
  523. end_rotation_angle = 0
  524. else:
  525. break
  526. if fraction != 1:
  527. rospy.loginfo("Plan Fail,Error code 1")
  528. sys.exit()
  529. elif error:
  530. rospy.loginfo("Plan Fail,Error code 2")
  531. sys.exit()
  532. else:
  533. traj_with_type = mark_the_traj(traj,"during-l",welding_sequence)
  534. traj_with_type.points[-len(traj.joint_trajectory.points)].type = "start"
  535. traj_with_type.points[-1].type = "end"
  536. points.append(point)
  537. trajectory.append(traj)
  538. trajectory_with_type.append(traj_with_type)
  539. return points,trajectory,trajectory_with_type
  540. def go_home(self,a=1,v=1):
  541. rospy.loginfo("go_home start")
  542. self.arm.set_max_acceleration_scaling_factor(a)
  543. self.arm.set_max_velocity_scaling_factor(v)
  544. # “up”为自定义姿态,你可以使用“home”或者其他姿态
  545. self.arm.set_named_target('home')
  546. self.arm.go()
  547. rospy.loginfo("go_home end")
  548. # rospy.sleep(1)
  549. def go_home_justplan(self,trajectory,trajectory_with_type,a=1,v=1):
  550. self.arm.set_max_acceleration_scaling_factor(a)
  551. self.arm.set_max_velocity_scaling_factor(v)
  552. # “up”为自定义姿态,你可以使用“home”或者其他姿态
  553. state = self.arm.get_current_state()
  554. state.joint_state.position = trajectory[-1].joint_trajectory.points[-1].positions
  555. self.arm.set_start_state(state)
  556. self.arm.set_named_target('home')
  557. traj = self.arm.plan()
  558. trajj = traj[1]
  559. traj_with_type = mark_the_traj(trajj,"go-home",welding_sequence)
  560. trajectory.append(trajj)
  561. trajectory_with_type.append(traj_with_type)
  562. return trajectory,trajectory_with_type
  563. def setColor(self, name, r, g, b, a=0.9):
  564. # 初始化moveit颜色对象
  565. color = ObjectColor()
  566. # 设置颜色值
  567. color.id = name
  568. color.color.r = r
  569. color.color.g = g
  570. color.color.b = b
  571. color.color.a = a
  572. # 更新颜色字典
  573. self.colors[name] = color
  574. # 将颜色设置发送并应用到moveit场景当中
  575. def sendColors(self):
  576. # 初始化规划场景对象
  577. p = PlanningScene()
  578. # 需要设置规划场景是否有差异
  579. p.is_diff = True
  580. # 从颜色字典中取出颜色设置
  581. for color in self.colors.values():
  582. p.object_colors.append(color)
  583. # 发布场景物体颜色设置
  584. self.scene_pub.publish(p)
  585. def path_planning(self,folder_path,gohome=True):
  586. file_path_result = os.path.join(folder_path, 'result.txt')
  587. all_data = process_welding_data(file_path_result)
  588. points,trajectory,trajectory_with_type = [],[],[]
  589. for i in range(len(all_data)):
  590. rospy.loginfo("共读取到%d条焊缝,开始规划第%d条",len(all_data),i+1)
  591. start_point = all_data[i][0]
  592. end_point = all_data[i][1]
  593. q1 = all_data[i][2]
  594. q2 = all_data[i][3]
  595. point11 = [start_point[0]/1000, start_point[1]/1000, start_point[2]/1000, q1[0],q1[1],q1[2],q1[3]]
  596. points,trajectory,trajectory_with_type = self.move_p_flexible(point11,points,trajectory,trajectory_with_type)
  597. point22 = [end_point[0]/1000, end_point[1]/1000, end_point[2]/1000, q2[0],q2[1],q2[2],q2[3]]
  598. points,trajectory,trajectory_with_type = self.move_pl(point22,points,trajectory,trajectory_with_type)
  599. rospy.loginfo("第%d条焊缝规划完毕",i+1)
  600. if gohome:
  601. points,trajectory,trajectory_with_type = self.move_p_flexible(self.home_pose,points,trajectory,trajectory_with_type)
  602. trajectory,trajectory_with_type = self.go_home_justplan(trajectory,trajectory_with_type)
  603. traj_merge= merge_trajectories(trajectory)
  604. trajectory_with_type_merge= merge_trajectories_with_type(trajectory_with_type)
  605. rospy.loginfo("All of The trajectory Plan successfully")
  606. return trajectory,traj_merge,trajectory_with_type_merge
  607. def path_planning_test(self,folder_path,i,reverse=False,gohome=True):
  608. file_path_result = os.path.join(folder_path, 'result.txt')
  609. all_data = process_welding_data(file_path_result)
  610. points,trajectory,trajectory_with_type = [],[],[]
  611. i -= 1
  612. rospy.loginfo("共读取到%d条焊缝,开始规划第%d条",len(all_data),i+1)
  613. start_point = all_data[i][0]
  614. end_point = all_data[i][1]
  615. q1 = all_data[i][2]
  616. q2 = all_data[i][3]
  617. if reverse:
  618. start_point = all_data[i][1]
  619. end_point = all_data[i][0]
  620. q1 = all_data[i][3]
  621. q2 = all_data[i][2]
  622. point11 = [start_point[0]/1000, start_point[1]/1000, start_point[2]/1000, q1[0],q1[1],q1[2],q1[3]]
  623. points,trajectory,trajectory_with_type = self.move_p2(point11,points,trajectory,trajectory_with_type)
  624. point22 = [end_point[0]/1000, end_point[1]/1000, end_point[2]/1000, q2[0],q2[1],q2[2],q2[3]]
  625. points,trajectory,trajectory_with_type = self.move_pl(point22,points,trajectory,trajectory_with_type)
  626. rospy.loginfo("第%d条焊缝规划完毕",i+1)
  627. if gohome:
  628. trajectory,trajectory_with_type = self.go_home_justplan(trajectory,trajectory_with_type)
  629. traj_merge= merge_trajectories(trajectory)
  630. trajectory_with_type_merge= merge_trajectories_with_type(trajectory_with_type)
  631. rospy.loginfo("All of The trajectory Plan successfully")
  632. return trajectory,traj_merge,trajectory_with_type_merge
  633. def point_to_PoseStamped(point,reference_frame):
  634. target_pose = PoseStamped()
  635. target_pose.header.frame_id = reference_frame
  636. target_pose.header.stamp = rospy.Time.now()
  637. target_pose.pose.position.x = point[0]
  638. target_pose.pose.position.y = point[1]
  639. target_pose.pose.position.z = point[2]
  640. if len(point) == 6:
  641. q = quaternion_from_euler(point[3],point[4],point[5])
  642. target_pose.pose.orientation.x = q[0]
  643. target_pose.pose.orientation.y = q[1]
  644. target_pose.pose.orientation.z = q[2]
  645. target_pose.pose.orientation.w = q[3]
  646. else:
  647. target_pose.pose.orientation.x = point[3]
  648. target_pose.pose.orientation.y = point[4]
  649. target_pose.pose.orientation.z = point[5]
  650. target_pose.pose.orientation.w = point[6]
  651. return target_pose
  652. def calculate_waypoints(start_pose,end_pose,spacing):
  653. start_position = np.array([start_pose.pose.position.x, start_pose.pose.position.y, start_pose.pose.position.z])
  654. start_orientation = euler_from_quaternion([start_pose.pose.orientation.x,start_pose.pose.orientation.y,start_pose.pose.orientation.z,start_pose.pose.orientation.w])
  655. end_position = np.array([end_pose.pose.position.x, end_pose.pose.position.y, end_pose.pose.position.z])
  656. end_orientation = euler_from_quaternion([end_pose.pose.orientation.x,end_pose.pose.orientation.y,end_pose.pose.orientation.z,end_pose.pose.orientation.w])
  657. distance = np.linalg.norm(np.array(end_position) - np.array(start_position))
  658. num_points = int(distance/spacing)
  659. trajectory = []
  660. for i in range(num_points + 1):
  661. alpha = float(i) / num_points
  662. position = [start + alpha * (end - start) for start, end in zip(start_position, end_position)]
  663. orientation = [start + alpha * (end - start) for start, end in zip(start_orientation, end_orientation)]
  664. trajectory.append(position + orientation)
  665. return trajectory,num_points + 1
  666. def process_welding_data(filename):
  667. all_data = [] # 用来存储每一行处理后的数据
  668. with open(filename, 'r') as file:
  669. for line in file:
  670. parts = line.strip().split('/')
  671. coordinates_and_poses = [part.split(',') for part in parts[1:]]
  672. start_point = tuple(map(float, coordinates_and_poses[0][:3])) # 使用元组以避免修改
  673. end_point = tuple(map(float, coordinates_and_poses[1][:3]))
  674. q1 = tuple(map(float, coordinates_and_poses[2][:4]))
  675. q2 = tuple(map(float, coordinates_and_poses[3][:4]))
  676. # 收集每行处理后的数据
  677. all_data.append((start_point, end_point, q1, q2))
  678. return all_data
  679. def mark_the_traj(traj,TYPE,SEQUENCE):
  680. traj_with_type = JointTrajectory_ex()
  681. traj_with_type.header = traj.joint_trajectory.header
  682. traj_with_type.joint_names = traj.joint_trajectory.joint_names
  683. traj_with_type.points = [
  684. JointTrajectoryPoint_ex(
  685. positions=point.positions,
  686. velocities=point.velocities,
  687. accelerations=point.accelerations,
  688. effort=point.effort,
  689. type=TYPE,
  690. sequence=SEQUENCE
  691. ) for point in traj.joint_trajectory.points
  692. ]
  693. return traj_with_type
  694. def merge_trajectories(trajectories):
  695. if not trajectories:
  696. return None
  697. # 创建一个新的 JointTrajectory 对象
  698. merged_trajectory = JointTrajectory()
  699. merged_trajectory.header = trajectories[0].joint_trajectory.header
  700. merged_trajectory.joint_names = trajectories[0].joint_trajectory.joint_names
  701. # 初始化时间累加器
  702. last_time_from_start = rospy.Duration(0)
  703. # 合并所有 trajectories 的 points
  704. for traj in trajectories:
  705. for point in traj.joint_trajectory.points:
  706. # 创建新的轨迹点
  707. new_point = deepcopy(point)
  708. # 累加时间
  709. new_point.time_from_start += last_time_from_start
  710. merged_trajectory.points.append(new_point)
  711. # 更新时间累加器为当前轨迹的最后一个点的时间
  712. if traj.joint_trajectory.points:
  713. last_time_from_start = traj.joint_trajectory.points[-1].time_from_start + last_time_from_start
  714. return merged_trajectory
  715. def merge_trajectories_with_type(trajectory_with_type):
  716. if not trajectory_with_type:
  717. return None
  718. # 创建一个新的 JointTrajectory 对象
  719. merged_trajectory_with_type = JointTrajectory_ex()
  720. merged_trajectory_with_type.header = trajectory_with_type[0].header
  721. merged_trajectory_with_type.joint_names = trajectory_with_type[0].joint_names
  722. # 初始化时间累加器
  723. last_time_from_start = rospy.Duration(0)
  724. # 合并所有 trajectories 的 points
  725. for traj in trajectory_with_type:
  726. for point in traj.points:
  727. # 创建新的轨迹点
  728. new_point = deepcopy(point)
  729. # 累加时间
  730. new_point.time_from_start += last_time_from_start
  731. merged_trajectory_with_type.points.append(new_point)
  732. # 更新时间累加器为当前轨迹的最后一个点的时间
  733. if traj.points:
  734. last_time_from_start = traj.points[-1].time_from_start + last_time_from_start
  735. return merged_trajectory_with_type
  736. def pub_trajectories(trajectory_with_type_merge):
  737. pub = rospy.Publisher("/joint_path", JointTrajectory_ex, queue_size=5)
  738. count = 1
  739. rate = rospy.Rate(1)
  740. rospy.loginfo("正在发布轨迹信息..")
  741. while not rospy.is_shutdown():
  742. #轨迹接受完毕,关闭当前发布
  743. sign_traj_accepted = str(rospy.get_param("sign_traj_accepted"))
  744. if sign_traj_accepted == "1":
  745. rospy.set_param("sign_traj_accepted",0)
  746. break
  747. pub.publish(trajectory_with_type_merge)
  748. # rospy.loginfo("发布计数,count = %d",count)
  749. # count += 1
  750. rate.sleep()
  751. if __name__ =="__main__":
  752. folder_path = rospy.get_param("folder_path")
  753. moveit_server = MoveIt_Control(is_use_gripper=False)
  754. moveit_server.arm.set_num_planning_attempts(10)
  755. #获取规划信息,并规划
  756. # folder_path = ("/home/chen/catkin_ws/data/0412")
  757. welding_sequence = rospy.get_param('welding_sequence')
  758. trajectory,trajectory_merge,trajectory_with_type_merge = moveit_server.path_planning(folder_path)
  759. # trajectory,trajectory_merge,trajectory_with_type_merge = moveit_server.path_planning_test(folder_path,1,True)
  760. #执行动作
  761. moveit_server.arm.execute(trajectory_merge)
  762. # for i in range(1 * 2 - 0): #执行到第i条焊缝
  763. # moveit_server.arm.execute(trajectory[i])
  764. #发布规划完毕的轨迹信息
  765. pub_trajectories(trajectory_with_type_merge)