moveitServer2.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. # 导入基本ros和moveit库
  2. from logging.handlers import RotatingFileHandler
  3. import os
  4. import moveit_msgs.msg
  5. import rospy, sys
  6. import moveit_commander
  7. import moveit_msgs
  8. from moveit_commander import MoveGroupCommander, PlanningSceneInterface, RobotCommander
  9. from moveit_msgs.msg import PlanningScene, ObjectColor,CollisionObject, AttachedCollisionObject,RobotTrajectory
  10. from moveit_msgs.msg import RobotState
  11. from moveit_msgs.msg import Constraints, PositionConstraint, OrientationConstraint
  12. from shape_msgs.msg import SolidPrimitive
  13. from sensor_msgs.msg import JointState
  14. import tf.transformations
  15. from trajectory_msgs.msg import JointTrajectory,JointTrajectoryPoint
  16. from geometry_msgs.msg import PoseStamped, Pose,Point,Vector3
  17. from copy import deepcopy
  18. import numpy as np
  19. import tf
  20. from tf.transformations import euler_from_quaternion,quaternion_from_euler,quaternion_from_euler, quaternion_multiply
  21. import math
  22. import traceback
  23. from lstrobot_planning.msg import JointTrajectoryPoint_ex,JointTrajectory_ex
  24. pi = np.pi
  25. class MoveIt_Control:
  26. # 初始化程序
  27. def __init__(self, is_use_gripper=False):
  28. self.home_pose=[]
  29. self.hf_num=0#焊缝计数 从0开始
  30. self.hf_fail=[]
  31. # Init ros config
  32. moveit_commander.roscpp_initialize(sys.argv)
  33. self.arm = moveit_commander.MoveGroupCommander('manipulator')
  34. self.arm.set_goal_joint_tolerance(0.0001)
  35. self.arm.set_goal_position_tolerance(0.0005)
  36. self.arm.set_goal_orientation_tolerance(0.1)
  37. #self.arm.set_planner_id("RRTConnet")#不知道能不能用
  38. self.end_effector_link = self.arm.get_end_effector_link()
  39. # 设置机械臂基座的参考系
  40. self.reference_frame = 'base_link'
  41. self.arm.set_pose_reference_frame(self.reference_frame)
  42. # # 设置最大规划时间和是否允许重新规划
  43. self.arm.set_planning_time(10.0)
  44. self.arm.allow_replanning(True)
  45. self.arm.set_max_acceleration_scaling_factor(1)
  46. self.arm.set_max_velocity_scaling_factor(1)
  47. self.arm.set_num_planning_attempts(10)
  48. # 机械臂初始姿态
  49. #self.move_j()
  50. self.go_home()
  51. self.home_pose=self.get_now_pose()
  52. # 关节规划,输入6个关节角度(单位:弧度)
  53. def move_j(self, joint_configuration=None,a=1,v=1):
  54. # 设置机械臂的目标位置,使用六轴的位置数据进行描述(单位:弧度)
  55. if joint_configuration==None:
  56. joint_configuration = [0, 0, 0, 0, 0, 0]
  57. self.arm.set_max_acceleration_scaling_factor(a)
  58. self.arm.set_max_velocity_scaling_factor(v)
  59. self.arm.set_joint_value_target(joint_configuration)
  60. rospy.loginfo("move_j:"+str(joint_configuration))
  61. self.arm.go()
  62. #rospy.sleep(1)
  63. def get_now_pose(self):
  64. # 获取机械臂当前位姿
  65. current_pose = self.arm.get_current_pose(self.end_effector_link).pose
  66. pose=[]
  67. pose.append(current_pose.position.x)
  68. pose.append(current_pose.position.y)
  69. pose.append(current_pose.position.z)
  70. pose.append(current_pose.orientation.x)
  71. pose.append(current_pose.orientation.y)
  72. pose.append(current_pose.orientation.z)
  73. pose.append(current_pose.orientation.w)
  74. # 打印位姿信息
  75. #rospy.lohome_poseinfo("Current Pose: {}".format(pose))
  76. return pose
  77. def create_path_constraints2(self,start_point,end_point,r):#创建路径约束
  78. #计算起点指向终点的向量
  79. vector = np.array([end_point[0]- start_point[0], end_point[1]- start_point[1], end_point[2]- start_point[2]])
  80. height = np.linalg.norm(vector)+0.16 #高度延长16cm
  81. radius = r
  82. # 位置约束
  83. position_constraint = PositionConstraint()#创建点位约束
  84. position_constraint.header.frame_id = "base_link"#此约束所指的机器人链接
  85. position_constraint.link_name = self.end_effector_link
  86. position_constraint.target_point_offset = Vector3(0, 0, 0)#目标点的偏移量
  87. position_constraint.weight = 1.0#质量 OR 加权因子?
  88. #构建 shape_msgs/SolidPrimitive 消息
  89. bounding_volume = SolidPrimitive()
  90. bounding_volume.type = SolidPrimitive.CYLINDER#圆柱
  91. # bounding_volume.dimensions = [0.003,1]
  92. bounding_volume.dimensions = [height,radius]#尺寸 高度 半径
  93. position_constraint.constraint_region.primitives.append(bounding_volume)
  94. #构建 geometry_msgs/Pose 消息,用于指定圆柱体在空间中的位置和姿态
  95. pose = Pose()
  96. pose.position.x = start_point[0] + vector[0] / 2#定义位置(找了个几何中心)
  97. pose.position.y = start_point[1] + vector[1] / 2
  98. pose.position.z = start_point[2] + vector[2] / 2
  99. # 计算圆柱体的姿态
  100. z_axis = np.array([0, 0, 1])
  101. axis = np.cross(z_axis, vector) #计算两个向量(向量数组)的叉乘 叉乘返回的数组既垂直于a,又垂直于b
  102. angle = np.arccos(np.dot(z_axis, vector) / np.linalg.norm(vector))#反余弦求角度
  103. q = tf.transformations.quaternion_about_axis(angle, axis)#通过旋转轴和旋转角返回四元数
  104. pose.orientation.x = q[0]
  105. pose.orientation.y = q[1]
  106. pose.orientation.z = q[2]
  107. pose.orientation.w = q[3]
  108. position_constraint.constraint_region.primitive_poses.append(pose)
  109. constraints = Constraints()#创建一个新的约束信息
  110. constraints.position_constraints.append(position_constraint)
  111. # constraints.orientation_constraints.append(orientation_constraint)
  112. return constraints
  113. def move_p_flexible(self,point,points,trajectory,trajectory_with_type,a=1,v=1):
  114. self.arm.set_max_acceleration_scaling_factor(a)
  115. self.arm.set_max_velocity_scaling_factor(v)
  116. rrr=0.05#初始允许半径
  117. if trajectory:
  118. #起点位置设置为规划组最后一个点
  119. state = self.arm.get_current_state()
  120. state.joint_state.position = trajectory[-1].joint_trajectory.points[-1].positions
  121. path_constraints = self.create_path_constraints2(points[-1],point,rrr)#将当前的点和输入的点(焊缝的起始点)做圆柱轨迹约束
  122. else:
  123. #刚开始规划 起点位置设定为当前状态 按理来说是home点
  124. self.go_home()
  125. self.home_pose=self.get_now_pose()
  126. state = self.arm.get_current_state()
  127. path_constraints = self.create_path_constraints2(self.home_pose,point,rrr)#将当前的点和输入的点(焊缝的起始点)做圆柱轨迹约束
  128. self.arm.set_path_constraints(path_constraints)#设定约束
  129. self.arm.set_pose_target(point, self.end_effector_link)#设定目标点为传入的点
  130. self.arm.set_start_state(state)#起点位置设置为规划组最后一个点 或者当前状态(第一个点时)
  131. #尝试规划次数
  132. b = 10 #尝试规划5次 无约束5次
  133. for i in range(b):
  134. traj = self.arm.plan()#调用plan进行规划
  135. error=traj[3]
  136. if error.val == moveit_msgs.msg._MoveItErrorCodes.MoveItErrorCodes.SUCCESS:
  137. rospy.loginfo("本次移动OK")
  138. trajj = traj[1] #取出规划的信息
  139. trajj_with_type = mark_the_traj(trajj,"during-p",welding_sequence)
  140. trajj_with_type.points[-len(trajj.joint_trajectory.points)].type = "start"
  141. trajj_with_type.points[-1].type = "end"
  142. trajectory_with_type.append(trajj_with_type)
  143. points.append(point)
  144. trajectory.append(trajj)
  145. break
  146. else:
  147. rospy.loginfo(error)
  148. rospy.loginfo("移动规划失败-开始第{}次重新规划".format(i+1))
  149. self.arm.clear_path_constraints()
  150. rrr=rrr+0.2#每次增加10厘米
  151. rospy.loginfo("R值:{}".format(rrr))
  152. if trajectory:
  153. path_constraints = self.create_path_constraints2(points[-1],point,rrr)#将最后一个点和输入的点(焊缝的起始点)做圆柱轨迹约束
  154. else:
  155. path_constraints = self.create_path_constraints2(self.home_pose,point,rrr)#将最后一个点和起点(焊缝的起始点)做圆柱轨迹约束
  156. self.arm.set_path_constraints(path_constraints)#设定约束
  157. if(i>=(b-5)):
  158. rospy.loginfo("所有移动规划尝试失败 取消路径约束")
  159. self.arm.clear_path_constraints()
  160. if(i==(b-1)):
  161. rospy.loginfo("所有移动规划尝试失败 程序退出")
  162. rospy.set_param("sign_control",0)
  163. sys.exit(0)
  164. #清除约束
  165. self.arm.clear_path_constraints()
  166. return points,trajectory,trajectory_with_type
  167. def move_pl(self,point,points,trajectory,trajectory_with_type,a=1,v=1):#焊缝的规划 只规划当前的点到上一个点
  168. self.arm.set_max_acceleration_scaling_factor(a)
  169. self.arm.set_max_velocity_scaling_factor(v)
  170. #设定约束
  171. if trajectory:
  172. #起点位置设置为规划组最后一个点
  173. state = self.arm.get_current_state()
  174. state.joint_state.position = trajectory[-1].joint_trajectory.points[-1].positions
  175. self.arm.set_start_state(state)
  176. self.arm.set_pose_target(point, self.end_effector_link)#设定目标点为传入的点
  177. # 创建路径约束
  178. path_constraints = self.create_path_constraints(points[-1],point)#将最后一个点和输入的点(焊缝的起始点)做圆柱轨迹约束
  179. self.arm.set_path_constraints(path_constraints)#设定约束
  180. traj = self.arm.plan()#调用plan进行规划
  181. error=traj[3]
  182. if error.val == moveit_msgs.msg._MoveItErrorCodes.MoveItErrorCodes.SUCCESS:
  183. rospy.loginfo("本次焊缝规划 OK")
  184. trajj = traj[1] #取出规划的信息
  185. trajj_with_type = mark_the_traj(trajj,"during-l",welding_sequence)
  186. trajj_with_type.points[-len(trajj.joint_trajectory.points)].type = "start"
  187. trajj_with_type.points[-1].type = "end"
  188. points.append(point)
  189. trajectory.append(trajj)
  190. trajectory_with_type.append(trajj_with_type)
  191. else:
  192. rospy.loginfo("本次焊缝规划失败")
  193. points.pop()#将本条焊缝的起点从规划中删除
  194. trajectory.pop()
  195. trajectory_with_type.pop()
  196. self.hf_fail.append(welding_sequence[self.hf_num])
  197. #清除约束
  198. self.arm.clear_path_constraints()
  199. self.hf_num=self.hf_num+1#焊缝计数
  200. return points,trajectory,trajectory_with_type
  201. def create_path_constraints(self,start_point,end_point):
  202. #计算起点指向终点的向量
  203. vector = np.array([end_point[0]- start_point[0], end_point[1]- start_point[1], end_point[2]- start_point[2]])
  204. height = np.linalg.norm(vector)+0.002
  205. radius = 0.001
  206. constraints = Constraints()
  207. # 位置约束
  208. position_constraint = PositionConstraint()
  209. position_constraint.header.frame_id = "base_link"
  210. position_constraint.link_name = self.end_effector_link
  211. position_constraint.target_point_offset = Vector3(0, 0, 0)
  212. #构建 shape_msgs/SolidPrimitive 消息
  213. bounding_volume = SolidPrimitive()
  214. bounding_volume.type = SolidPrimitive.CYLINDER
  215. # bounding_volume.dimensions = [0.003,1]
  216. bounding_volume.dimensions = [height,radius]
  217. #构建 geometry_msgs/Pose 消息,用于指定圆柱体在空间中的位置和姿态
  218. pose = Pose()
  219. pose.position.x = start_point[0] + vector[0] / 2
  220. pose.position.y = start_point[1] + vector[1] / 2
  221. pose.position.z = start_point[2] + vector[2] / 2
  222. # 计算圆柱体的旋转矩阵
  223. z_axis = np.array([0, 0, 1])
  224. axis = np.cross(z_axis, vector)
  225. angle = np.arccos(np.dot(z_axis, vector) / np.linalg.norm(vector))
  226. q = tf.transformations.quaternion_about_axis(angle, axis)
  227. pose.orientation.x = q[0]
  228. pose.orientation.y = q[1]
  229. pose.orientation.z = q[2]
  230. pose.orientation.w = q[3]
  231. position_constraint.constraint_region.primitives.append(bounding_volume)
  232. position_constraint.constraint_region.primitive_poses.append(pose)
  233. position_constraint.weight = 1.0
  234. constraints.position_constraints.append(position_constraint)
  235. return constraints
  236. def go_home(self,a=1,v=1):
  237. rospy.loginfo("go_home start")
  238. self.arm.set_max_acceleration_scaling_factor(a)
  239. self.arm.set_max_velocity_scaling_factor(v)
  240. self.arm.set_named_target('home')
  241. rospy.loginfo("get_home end")
  242. self.arm.go()
  243. rospy.loginfo("go_home end")
  244. # rospy.sleep(1)
  245. def go_home_justplan(self,trajectory,trajectory_with_type,a=1,v=1):
  246. self.arm.set_max_acceleration_scaling_factor(a)
  247. self.arm.set_max_velocity_scaling_factor(v)
  248. state = self.arm.get_current_state()
  249. state.joint_state.position = trajectory[-1].joint_trajectory.points[-1].positions
  250. self.arm.set_start_state(state)
  251. self.arm.set_named_target('home')
  252. traj = self.arm.plan()
  253. trajj = traj[1]
  254. traj_with_type = mark_the_traj(trajj,"go-home",welding_sequence)
  255. trajectory.append(trajj)
  256. trajectory_with_type.append(traj_with_type)
  257. return trajectory,trajectory_with_type
  258. def path_planning(self,folder_path,gohome=True):
  259. file_path_result = os.path.join(folder_path, 'result.txt')
  260. all_data = process_welding_data(file_path_result)
  261. points,trajectory,trajectory_with_type = [],[],[]
  262. for i in range(len(all_data)):
  263. rospy.loginfo("共读取到%d条焊缝,开始规划第%d条",len(all_data),i+1)
  264. start_point = all_data[i][0]
  265. end_point = all_data[i][1]
  266. q1 = all_data[i][2]
  267. q2 = all_data[i][3]
  268. point11 = [start_point[0]/1000, start_point[1]/1000, start_point[2]/1000, q1[0],q1[1],q1[2],q1[3]]
  269. points,trajectory,trajectory_with_type = self.move_p_flexible(point11,points,trajectory,trajectory_with_type)
  270. point22 = [end_point[0]/1000, end_point[1]/1000, end_point[2]/1000, q2[0],q2[1],q2[2],q2[3]]
  271. points,trajectory,trajectory_with_type = self.move_pl(point22,points,trajectory,trajectory_with_type)
  272. rospy.loginfo("第%d条焊缝规划完毕",i+1)
  273. if gohome:
  274. points,trajectory,trajectory_with_type = self.move_p_flexible(self.home_pose,points,trajectory,trajectory_with_type)
  275. trajectory,trajectory_with_type = self.go_home_justplan(trajectory,trajectory_with_type)
  276. traj_merge= merge_trajectories(trajectory)
  277. trajectory_with_type_merge= merge_trajectories_with_type(trajectory_with_type)
  278. rospy.loginfo("All of The trajectory Plan successfully")
  279. return trajectory,traj_merge,trajectory_with_type_merge
  280. ###########################################################class end#############################################################
  281. def process_welding_data(filename):
  282. all_data = [] # 用来存储每一行处理后的数据
  283. with open(filename, 'r') as file:
  284. for line in file:
  285. parts = line.strip().split('/')
  286. coordinates_and_poses = [part.split(',') for part in parts[1:]]
  287. start_point = tuple(map(float, coordinates_and_poses[0][:3])) # 使用元组以避免修改
  288. end_point = tuple(map(float, coordinates_and_poses[1][:3]))
  289. q1 = tuple(map(float, coordinates_and_poses[2][:4]))
  290. q2 = tuple(map(float, coordinates_and_poses[3][:4]))
  291. # 收集每行处理后的数据
  292. all_data.append((start_point, end_point, q1, q2))
  293. return all_data
  294. def mark_the_traj(traj,TYPE,SEQUENCE):
  295. traj_with_type = JointTrajectory_ex()
  296. traj_with_type.header = traj.joint_trajectory.header
  297. traj_with_type.joint_names = traj.joint_trajectory.joint_names
  298. traj_with_type.points = [
  299. JointTrajectoryPoint_ex(
  300. positions=point.positions,
  301. velocities=point.velocities,
  302. accelerations=point.accelerations,
  303. effort=point.effort,
  304. type=TYPE,
  305. sequence=SEQUENCE
  306. ) for point in traj.joint_trajectory.points
  307. ]
  308. return traj_with_type
  309. def merge_trajectories(trajectories):
  310. if not trajectories:
  311. return None
  312. # 创建一个新的 JointTrajectory 对象
  313. merged_trajectory = JointTrajectory()
  314. merged_trajectory.header = trajectories[0].joint_trajectory.header
  315. merged_trajectory.joint_names = trajectories[0].joint_trajectory.joint_names
  316. # 初始化时间累加器
  317. last_time_from_start = rospy.Duration(0)
  318. # 合并所有 trajectories 的 points
  319. for traj in trajectories:
  320. for point in traj.joint_trajectory.points:
  321. # 创建新的轨迹点
  322. new_point = deepcopy(point)
  323. # 累加时间
  324. new_point.time_from_start += last_time_from_start
  325. merged_trajectory.points.append(new_point)
  326. # 更新时间累加器为当前轨迹的最后一个点的时间
  327. if traj.joint_trajectory.points:
  328. last_time_from_start = traj.joint_trajectory.points[-1].time_from_start + last_time_from_start
  329. return merged_trajectory
  330. def merge_trajectories_with_type(trajectory_with_type):
  331. if not trajectory_with_type:
  332. return None
  333. # 创建一个新的 JointTrajectory 对象
  334. merged_trajectory_with_type = JointTrajectory_ex()
  335. merged_trajectory_with_type.header = trajectory_with_type[0].header
  336. merged_trajectory_with_type.joint_names = trajectory_with_type[0].joint_names
  337. # 初始化时间累加器
  338. last_time_from_start = rospy.Duration(0)
  339. # 合并所有 trajectories 的 points
  340. for traj in trajectory_with_type:
  341. for point in traj.points:
  342. # 创建新的轨迹点
  343. new_point = deepcopy(point)
  344. # 累加时间
  345. new_point.time_from_start += last_time_from_start
  346. merged_trajectory_with_type.points.append(new_point)
  347. # 更新时间累加器为当前轨迹的最后一个点的时间
  348. if traj.points:
  349. last_time_from_start = traj.points[-1].time_from_start + last_time_from_start
  350. return merged_trajectory_with_type
  351. def pub_trajectories(trajectory_with_type_merge):
  352. pub = rospy.Publisher("/joint_path", JointTrajectory_ex, queue_size=5)
  353. count = 1
  354. rate = rospy.Rate(1)
  355. rospy.loginfo("正在发布轨迹信息..")
  356. while not rospy.is_shutdown():
  357. #轨迹接受完毕,关闭当前发布
  358. sign_traj_accepted = str(rospy.get_param("sign_traj_accepted"))
  359. if sign_traj_accepted == "1":
  360. rospy.set_param("sign_traj_accepted",0)
  361. break
  362. pub.publish(trajectory_with_type_merge)
  363. # rospy.loginfo("发布计数,count = %d",count)
  364. # count += 1
  365. rate.sleep()
  366. class py_msgs():
  367. fial=[]
  368. shun_xv=[]
  369. class point():
  370. xyz_list=[]
  371. type=[]
  372. def ROS2PY_msgs(msgs,m_sr):
  373. for i in range(len(msgs.points)):
  374. py_msgs.point.xyz_list.append(msgs.points[i].positions)
  375. py_msgs.point.type.append(msgs.points[i].type)
  376. py_msgs.fail=m_sr.hf_fail.copy()
  377. py_msgs.shun_xv=msgs.points[0].sequence.copy()
  378. # for i in range(len(py_msgs.point.type)):
  379. # print(py_msgs.point.xyz_list[i])
  380. # print(py_msgs.point.type[i])
  381. print(py_msgs.shun_xv)
  382. print(py_msgs.fial)
  383. # for i in range(len(py_msgs.point.type)):
  384. # moveit_server.move_j(py_msgs.point.xyz_list[i])
  385. # #input("任意键继续")
  386. if __name__ =="__main__":
  387. folder_path = rospy.get_param("folder_path")
  388. # 初始化ROS节点
  389. rospy.init_node('moveit_control_server', anonymous=False)
  390. moveit_server = MoveIt_Control(is_use_gripper=False)
  391. welding_sequence = rospy.get_param('welding_sequence')
  392. trajectory,trajectory_merge,trajectory_with_type_merge = moveit_server.path_planning(folder_path)
  393. # trajectory,trajectory_merge,trajectory_with_type_merge = moveit_server.path_planning_test(folder_path,1,True)
  394. #执行动作
  395. #ROS2PY_msgs(trajectory_with_type_merge,moveit_server)
  396. #moveit_server.arm.execute(trajectory_merge)
  397. # for i in range(1 * 2 - 0): #执行到第i条焊缝
  398. # moveit_server.arm.execute(trajectory[i])
  399. #发布规划完毕的轨迹信息
  400. #pub_trajectories(trajectory_with_type_merge)
  401. rospy.set_param("sign_control",0)