ik_service.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 
4 # FSRobo-R Package BSDL
5 # ---------
6 # Copyright (C) 2019 FUJISOFT. All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without modification,
9 # are permitted provided that the following conditions are met:
10 # 1. Redistributions of source code must retain the above copyright notice,
11 # this list of conditions and the following disclaimer.
12 # 2. Redistributions in binary form must reproduce the above copyright notice,
13 # this list of conditions and the following disclaimer in the documentation and/or
14 # other materials provided with the distribution.
15 # 3. Neither the name of the copyright holder nor the names of its contributors
16 # may be used to endorse or promote products derived from this software without
17 # specific prior written permission.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 # --------
30 
31 import math
32 import rospy
33 import tf
34 import moveit_commander
35 from moveit_msgs.srv import GetPositionIK, GetPositionIKResponse
36 from fsrobo_r_msgs.srv import SetToolOffset, SetToolOffsetRequest
37 from fsrobo_r_driver.geometry_util import GeometryUtil
38 from fsrobo_r_driver.cc_client import CCClient
39 import time
40 import threading
41 
42 
44  def __init__(self, ip):
45  self._api = CCClient(ip_address=ip)
46  self._set_tool_offset = rospy.ServiceProxy('set_tool_offset', SetToolOffset)
47 
48  def set_tool_offset(self, offx=0, offy=0, offz=0, offrz=0, offry=0, offrx=0):
49  rospy.wait_for_service('set_tool_offset')
50 
51  req = SetToolOffsetRequest()
52  req.origin.x = offx
53  req.origin.y = offy
54  req.origin.z = offz
55  req.rotation.z = offrz
56  req.rotation.y = offry
57  req.rotation.x = offrx
58 
59  return self._set_tool_offset(req)
60 
61  def solve_ik(self, position, orientation):
62  data = {}
63  angle = list(self.quaternion_to_euler(orientation))
64 
65  pos = map(lambda x: x * 1000, [position.x, position.y, position.z])
66  deg = map(lambda x: math.degrees(x), angle)
67 
68  if self._api.position_to_joint(pos[0], pos[1], pos[2], deg[2], deg[1], deg[0], data) == 0:
69  result = map(lambda k: data['DA'][k], ['J1', 'J2', 'J3', 'J4', 'J5', 'J6'])
70  # TODO IKからジョイントの制限を超える角度が返ってくる場合がある
71  for i in range(5):
72  if result[i] > 240:
73  result[i] -= 360
74  elif result[i] < -240:
75  result[i] += 360
76  if result[5] > 360:
77  result[i] -= 360
78  elif result[5] < -360:
79  result[5] += 360
80  result = map(lambda x: math.radians(x), result)
81  else:
82  result = []
83 
84  return result
85 
86  def quaternion_to_euler(self, quaternion):
87  e = tf.transformations.euler_from_quaternion((quaternion.x, quaternion.y, quaternion.z, quaternion.w), 'rzyx')
88  return e
89 
90 
91 class RobootToolUtil(object):
92  def __init__(self):
93  self._gu = GeometryUtil()
94  self._init_commander()
95  self._tool_base_link = rospy.get_namespace() + 'Link6'
96 
97  def _init_commander(self):
98  rospy.loginfo('Wait for robot description')
99  while True:
100  if rospy.search_param('/robot_description') is not None \
101  and rospy.search_param('/robot_description_semantic') is not None:
102  break
103  time.sleep(1)
104  print('-----------------')
105  self._rc = moveit_commander.RobotCommander()
106  print('-----------------')
107  rospy.loginfo('Preload group instance')
108  while True:
109  try:
110  for group_name in self._rc.get_group_names():
111  self._rc.get_group(group_name)
112  break
113  except RuntimeError as e:
114  rospy.logwarn(e)
115  time.sleep(1)
116  print('-----------------')
117 
118  def get_tool_offset(self, group_name):
119  group = self._rc.get_group(group_name)
120 
121  ee_link = group.get_end_effector_link()
122  pose = self._gu.get_current_pose(self._tool_base_link, ee_link)
123  tool_pos = map(lambda x: x * 1000.0, pose[0])
124  tool_ori = map(lambda x: math.degrees(x), tf.transformations.euler_from_quaternion(pose[1], axes='rzyx'))
125 
126  tool_offset = tool_pos + tool_ori
127 
128  return tool_offset
129 
130 
131 class IKService:
132  def __init__(self):
133  ip = rospy.get_param('robot_ip_address', '192.168.0.23')
136 
137  default_joint_names = ["Joint1", "Joint2", "Joint3", "Joint4", "Joint5", "Joint6"]
138  self.joint_names = rospy.get_param('controller_joint_names', default_joint_names)
139 
142 
143  self._lock = threading.Lock()
144 
145  def update_tool_offset(self, group_name):
146  if group_name in self._tool_offset_cache:
147  tool_offset = self._tool_offset_cache[group_name]
148  else:
149  tool_offset = self._tool_util.get_tool_offset(group_name)
150  self._tool_offset_cache[group_name] = tool_offset
151 
152  if tool_offset != self._last_tool_offset:
153  self._rb.set_tool_offset(*tool_offset)
154  self._last_tool_offset = tool_offset
155 
156  def handle_solve_ik(self, req):
157  with self._lock:
158  #print("-----------request!")
159  pos = req.ik_request.pose_stamped.pose.position
160  ori = req.ik_request.pose_stamped.pose.orientation
161  group_name = req.ik_request.group_name
162 
163  #print(pos)
164  #print(ori)
165  #print('group_name: {}'.format(group_name))
166 
167  res = GetPositionIKResponse()
168  res.solution.joint_state.header = req.ik_request.pose_stamped.header
169 
170  self.update_tool_offset(group_name)
171  joint = self._rb.solve_ik(pos, ori)
172 
173  if len(joint) != 0:
174  #print("pose!")
175  #print(req.ik_request.pose_stamped.pose)
176  #print("req!")
177  #print(req.ik_request)
178  #print("joint!")
179  #print(joint)
180  #print("success!")
181  res.solution.joint_state.name = self.joint_names
182  res.solution.joint_state.position = joint
183  res.error_code.val = res.error_code.SUCCESS
184  print(res.solution.joint_state.position)
185  else:
186  res.error_code.val = res.error_code.NO_IK_SOLUTION
187 
188  return res
189 
190  def run(self):
191  rospy.Service('solve_ik', GetPositionIK, self.handle_solve_ik)
192  print("Ready to solve ik.")
193  rospy.spin()
194 
195 if __name__ == "__main__":
196  rospy.init_node('ik_server')
197  s = IKService()
198  s.run()
def quaternion_to_euler(self, quaternion)
Definition: ik_service.py:86
def set_tool_offset(self, offx=0, offy=0, offz=0, offrz=0, offry=0, offrx=0)
Definition: ik_service.py:48
def handle_solve_ik(self, req)
Definition: ik_service.py:156
def get_tool_offset(self, group_name)
Definition: ik_service.py:118
def solve_ik(self, position, orientation)
Definition: ik_service.py:61
def update_tool_offset(self, group_name)
Definition: ik_service.py:145


fsrobo_r_driver
Author(s): F-ROSROBO
autogenerated on Sun Feb 9 2020 03:58:29