Compare commits
2 Commits
97e3cc00d3
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 9119837294 | |||
| 120a252ccc |
@ -3,7 +3,7 @@ from Robotic_Arm.rm_robot_interface import *
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import math
|
import math
|
||||||
|
|
||||||
class rm75_kine_api():
|
class KinematicsSolver_RM():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# ---------- rm75 official algorithm -----------
|
# ---------- rm75 official algorithm -----------
|
||||||
print(f'------- the realman official kinematic initialising -------')
|
print(f'------- the realman official kinematic initialising -------')
|
||||||
|
|||||||
@ -16,20 +16,39 @@ from harvest_arm_ctrl.rm75_kine_rm import KinematicsSolver_RM as kine_rm
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class KinematicsSolver():
|
class KinematicsSolver(Node):
|
||||||
def __init__(self, node_name="kine_run_node"):
|
def __init__(self):
|
||||||
super().__init__('realman_run_node')
|
super().__init__('kine_arm_node')
|
||||||
self.config, self.sts, self.arm_arg = self.get_arg()
|
self.config, self.sts= self.get_arg()
|
||||||
|
|
||||||
# ----------- rm75 qp based kine ------------
|
# ----------- rm75 qp based kine ------------
|
||||||
self.robot_kine_qp = kine_qp(urdf_path='/home/zl/Downloads/urdf_rm75/RM75-B.urdf', mesh_dir='/home/zl/Downloads/urdf_rm75')
|
self.robot_kine_qp = kine_qp(urdf_path=self.config['urdf_path'], mesh_dir=self.config['mesh_dir'])
|
||||||
self.robot_kine_qp.add_tool_frames(tools_in_ee)
|
self.robot_kine_qp.add_tool_frames(self.config['tools_in_ee'])
|
||||||
self.robot_kine_qp.cfg_j_limit(min_j=lb, max_j=ub, rad_flag=True)
|
self.robot_kine_qp.cfg_j_limit(min_j=self.config['min_joint'], max_j=self.config['max_joint'], rad_flag=False)
|
||||||
|
|
||||||
# ---------- rm75 official algorithm -----------
|
# ---------- rm75 official algorithm -----------
|
||||||
self.robot_kine_rm = kine_rm()
|
self.robot_kine_rm = kine_rm()
|
||||||
self.robot_kine_rm.add_tool_frames(tools_in_ee)
|
self.robot_kine_rm.add_tool_frames(self.config['tools_in_ee'])
|
||||||
self.robot_kine_rm.cfg_j_limit(min_j=lb, max_j=ub, rad_flag=True)
|
self.robot_kine_rm.cfg_j_limit(min_j=self.config['min_joint'], max_j=self.config['max_joint'], rad_flag=False)
|
||||||
|
|
||||||
|
# pub, arm joint command
|
||||||
|
self.action_arm_pub = self.create_publisher(JointState, self.config["action_arm_topic"], 10)
|
||||||
|
|
||||||
|
# sub, get the desired pose command in task frame
|
||||||
|
self.action_pose_sub = self.create_subscription(PoseStamped, self.config["action_pose_topic"], self.pose_callback, 10)
|
||||||
|
# sub, get the desired tool command
|
||||||
|
self.action_tool_sub = self.create_subscription(Bool, self.config["action_tool_topic"], self.tool_callback, 10)
|
||||||
|
# sub, get the teleoperation enable command
|
||||||
|
self.action_enable_sub = self.create_subscription(Bool, self.config["action_arm_enable_topic"], self.arm_enable_callback, 10)
|
||||||
|
# sub, get the joint sts from arm
|
||||||
|
self.obser_arm_sub = self.create_subscription(JointState, self.config["observation_topic"], self.arm_observation_callback, 10)
|
||||||
|
|
||||||
|
self.timer = self.create_timer(
|
||||||
|
self.config["interval"],
|
||||||
|
self.kine_timer
|
||||||
|
)
|
||||||
|
|
||||||
|
self.get_logger().info(f'the config is {self.config}')
|
||||||
|
|
||||||
def get_arg(self):
|
def get_arg(self):
|
||||||
"""
|
"""
|
||||||
@ -38,77 +57,203 @@ class KinematicsSolver():
|
|||||||
dict: Configuration dictionary containing robot IP, host IP, prefix, left/right status, port, savefile flag, and scissor gripper status.
|
dict: Configuration dictionary containing robot IP, host IP, prefix, left/right status, port, savefile flag, and scissor gripper status.
|
||||||
"""
|
"""
|
||||||
tool_name = self.declare_parameter('tool_name', "no_tool").value
|
tool_name = self.declare_parameter('tool_name', "no_tool").value
|
||||||
tool_name_param = 'tools_in_ee.' + tool_name
|
tools_in_ee = {}
|
||||||
try:
|
tool_names = self.declare_parameter('tool_names', ["scissor", "omnipic", "minisci", "no_tool"]).value
|
||||||
tool_offset_list = self.declare_parameter(tool_name_param, [0.0] * 11).value
|
for name in tool_names:
|
||||||
except:
|
param_name = 'tools_in_ee.' + name
|
||||||
self.get_logger().error(f"Tool name '{tool_name}' not found in parameters. Please check the configuration.")
|
try:
|
||||||
|
tool_frame = self.declare_parameter(param_name, [0.0] * 11).value
|
||||||
|
tools_in_ee[name] = np.zeros((2,7))
|
||||||
acc_lmt = self.declare_parameter('max_joint_acc', 600.0).value
|
tools_in_ee[name][0, :] = tool_frame[0:7]
|
||||||
interval = self.declare_parameter('interval', 0.02).value
|
tools_in_ee[name][1, 0:4] = tool_frame[7:11]
|
||||||
|
except:
|
||||||
|
self.get_logger().error(f"Tool name '{name}' not found in parameters. Please check the configuration.")
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
"robot_ip": self.declare_parameter('robot_ip', "192.168.1.18").value,
|
|
||||||
"host_ip": self.declare_parameter('host_ip', "192.168.1.101").value,
|
|
||||||
"port": self.declare_parameter('port', 8089).value,
|
|
||||||
|
|
||||||
"max_joint": self.declare_parameter('max_joint', [0.0] * 7).value,
|
"max_joint": self.declare_parameter('max_joint', [0.0] * 7).value,
|
||||||
"min_joint": self.declare_parameter('min_joint', [0.0] * 7).value,
|
"min_joint": self.declare_parameter('min_joint', [0.0] * 7).value,
|
||||||
"max_joint_speed": self.declare_parameter('max_joint_speed', 180.0).value,
|
|
||||||
"lmt_05att": acc_lmt * interval * interval * 0.5,
|
|
||||||
|
|
||||||
"max_cartesian_speed": self.declare_parameter('max_cartesian_speed', 1.0).value,
|
|
||||||
"max_cartesian_angular_speed": self.declare_parameter('max_cartesian_angular_speed', 1.5).value,
|
|
||||||
"max_cartesian_acc": self.declare_parameter('max_cartesian_acc', 1.5).value,
|
|
||||||
"max_cartesian_angular_acc": self.declare_parameter('max_cartesian_angular_acc', 2.0).value,
|
|
||||||
"bound_cartesian": self.declare_parameter('bound_cartesian', [-0.3, -0.5, -0.1, 0.3, 0.5, 0.6]).value,
|
"bound_cartesian": self.declare_parameter('bound_cartesian', [-0.3, -0.5, -0.1, 0.3, 0.5, 0.6]).value,
|
||||||
|
|
||||||
"arm_installation": self.declare_parameter('arm_installation', [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]).value,
|
"arm_installation": self.declare_parameter('arm_installation', [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]).value,
|
||||||
"tool_name": tool_name,
|
"tool_name": tool_name,
|
||||||
"tool_offset": tool_offset_list,
|
"tools_in_ee": tools_in_ee,
|
||||||
"tool_names": self.declare_parameter('tool_names', ["scissor", "omnipic", "minisci", "no_tool"]).value,
|
|
||||||
|
|
||||||
"initial_joint": self.declare_parameter('initial_joint', [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]).value,
|
|
||||||
"kp_j": self.declare_parameter('kp_j', 1.0).value,
|
|
||||||
|
|
||||||
"interval": interval,
|
"interval": self.declare_parameter('interval', 0.02).value,
|
||||||
"action_topic": self.declare_parameter('action_topic', "/action/arm").value,
|
|
||||||
|
"urdf_path": self.declare_parameter('urdf_path', "/home/zl/Downloads/urdf_rm75/RM75-B.urdf").value,
|
||||||
|
"mesh_dir": self.declare_parameter('mesh_dir', "/home/zl/Downloads/urdf_rm75").value,
|
||||||
|
|
||||||
|
"action_arm_topic": self.declare_parameter('action_topic', "/action/arm").value,
|
||||||
"observation_topic": self.declare_parameter('observation_topic', "/observation/arm").value,
|
"observation_topic": self.declare_parameter('observation_topic', "/observation/arm").value,
|
||||||
"action_rviz_topic": self.declare_parameter('action_rviz_topic', "/action/arm_rviz").value,
|
"action_pose_topic": self.declare_parameter('action_pose_topic', "/action/pose").value,
|
||||||
"observation_rviz_topic": self.declare_parameter('observation_rviz_topic', "/observation/arm_rviz").value,
|
"action_tool_topic": self.declare_parameter('action_tool_topic', "/action/tool").value,
|
||||||
|
"action_arm_enable_topic": self.declare_parameter('action_arm_enable_topic', "/action/arm_enable").value,
|
||||||
"arm_ctrl_voltage": self.declare_parameter('arm_ctrl_voltage', 2).value,
|
|
||||||
"arm_ctrl_io_mode": self.declare_parameter('arm_ctrl_io_mode', [0, 0, 1, 1]).value,
|
|
||||||
"arm_tool_io_voltage": self.declare_parameter('arm_tool_io_voltage', 2).value,
|
|
||||||
"arm_tool_io_mode": self.declare_parameter('arm_tool_io_mode', [1, 1]).value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sts = {
|
sts = {
|
||||||
"joint_cmd": [0.0] * 7,
|
|
||||||
"joint_target": [0.0] * 7,
|
|
||||||
"joint_pos_sts": [0.0] * 7,
|
"joint_pos_sts": [0.0] * 7,
|
||||||
"joint_speed_sts": [0.0] * 7,
|
"pose_target": [0.0] * 7,
|
||||||
"arm_enable": int(0),
|
"joint_solved": [0.0] * 7,
|
||||||
"tool_cmd": [int(0), int(0)],
|
"arm_enable": 0,
|
||||||
|
"tool_cmd": 0,
|
||||||
"pose_sts": [0.0] * 6,
|
"pose_sts": [0.0] * 6,
|
||||||
"timer_cnt": 0,
|
"pose_target_timestamp": 0.0,
|
||||||
"action_timestamp": 0.0,
|
"ik_ret": 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
arm_arg = {
|
return config, sts
|
||||||
"arm" : None,
|
|
||||||
"arm_handle" : None,
|
def update_msg(self):
|
||||||
}
|
msg = JointState()
|
||||||
|
msg.header.stamp = self.get_clock().now().to_msg()
|
||||||
|
msg.position = [float(self.sts["arm_enable"])] + [float(self.sts["ik_ret"])] + self.sts["joint_solved"] + [float(self.sts["tool_cmd"])]
|
||||||
|
return msg
|
||||||
|
|
||||||
|
def kine_timer(self):
|
||||||
|
msg = self.update_msg()
|
||||||
|
self.action_arm_pub.publish(msg)
|
||||||
|
|
||||||
|
def arm_enable_callback(self, msg):
|
||||||
|
if msg.data:
|
||||||
|
self.sts["arm_enable"] = 1
|
||||||
|
else:
|
||||||
|
self.sts["arm_enable"] = 0
|
||||||
|
|
||||||
return config, sts, arm_arg
|
def tool_callback(self, msg):
|
||||||
|
if msg.data:
|
||||||
|
self.sts["tool_cmd"] = 1
|
||||||
|
else:
|
||||||
|
self.sts["tool_cmd"] = 0
|
||||||
|
|
||||||
|
def arm_observation_callback(self, msg):
|
||||||
|
if isinstance(msg, JointState):
|
||||||
|
self.sts["joint_pos_sts"] = list(msg.position[2:9])
|
||||||
|
else:
|
||||||
|
self.get_logger().error("Received message of unsupported type.")
|
||||||
|
|
||||||
|
def pose_callback(self, msg):
|
||||||
|
if isinstance(msg, PoseStamped):
|
||||||
|
timestamp = msg.header.stamp.sec + msg.header.stamp.nanosec * 1e-9
|
||||||
|
if timestamp < self.sts["pose_target_timestamp"]:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
# get the desired pose command in task frame
|
||||||
|
self.sts["pose_target_timestamp"] = timestamp
|
||||||
|
t_position = [msg.pose.position.x, msg.pose.position.y, msg.pose.position.z]
|
||||||
|
t_quat = [msg.pose.orientation.x, msg.pose.orientation.y, msg.pose.orientation.z, msg.pose.orientation.w]
|
||||||
|
|
||||||
|
# transform the pose from task frame to arm base frame
|
||||||
|
t_pos_arm, t_quat_arm = self.pose_transform(pos=t_position, quat=t_quat, pos_frame=self.config['arm_installation'][0:3], quat_frame=self.config['arm_installation'][3:7])
|
||||||
|
t_rpy_arm = self.quaternion_to_euler(t_quat_arm)
|
||||||
|
|
||||||
|
# call the inverse kinematics solver
|
||||||
|
self.inverse_kine(target_position=t_pos_arm, target_rpy=t_rpy_arm, initial_guess=self.sts["joint_pos_sts"], tool=self.config['tool_name'], work='base')
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.get_logger().error("Received message of unsupported type.")
|
||||||
|
|
||||||
|
def inverse_kine(self, target_position, target_rpy, initial_guess, tool="no_tool", work='base'):
|
||||||
|
ret_rm_ik, q_out = self.robot_kine_rm.inverse_kinematics(target_position, target_rpy, initial_guess, tool)
|
||||||
|
if ret_rm_ik == 0:
|
||||||
|
self.sts["joint_solved"] = q_out
|
||||||
|
self.sts["ik_ret"] = 1
|
||||||
|
else:
|
||||||
|
ret_qp_ik, q_out = self.robot_kine_qp.inverse_kinematics(target_position= target_position, target_rpy=target_rpy, initial_guess=initial_guess, tool=tool, max_iter=300, work=work)
|
||||||
|
if ret_qp_ik == 0:
|
||||||
|
self.sts["joint_solved"] = q_out
|
||||||
|
self.sts["ik_ret"] = 1
|
||||||
|
else:
|
||||||
|
self.sts["ik_ret"] = 0
|
||||||
|
|
||||||
|
def pose_transform(self, pos, quat, pos_frame, quat_frame):
|
||||||
|
'''
|
||||||
|
pos: position in the task frame
|
||||||
|
quat: quaternion in the task frame
|
||||||
|
pos_frame: task frame position in the arm base frame
|
||||||
|
quat_frame: task framequaternion in the arm base frame
|
||||||
|
'''
|
||||||
|
pos_frame = np.asarray(pos_frame, dtype=np.float32)
|
||||||
|
quat_frame = np.asarray(quat_frame, dtype=np.float32)
|
||||||
|
pos = np.asarray(pos, dtype=np.float32)
|
||||||
|
quat = np.asarray(quat, dtype=np.float32)
|
||||||
|
|
||||||
|
pos_arm = rotate_vector_by_quaternion( quat=quat_frame, v=pos) + pos_frame
|
||||||
|
quat_arm = quaternion_multiply(quat_frame, quat)
|
||||||
|
return pos_arm, quat_arm
|
||||||
|
|
||||||
|
def quaternion_to_euler(q):
|
||||||
|
"""
|
||||||
|
Convert quaternion to Euler angles (roll, pitch, yaw)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
qx, qy, qz, qw: quaternion components
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: [roll, pitch, yaw] in radians
|
||||||
|
"""
|
||||||
|
# Roll (x-axis rotation)
|
||||||
|
sinr_cosp = 2.0 * (q[3] * q[0] + q[1] * q[2])
|
||||||
|
cosr_cosp = 1.0 - 2.0 * (q[0] * q[0] + q[1] * q[1])
|
||||||
|
roll = np.arctan2(sinr_cosp, cosr_cosp)
|
||||||
|
|
||||||
|
# Pitch (y-axis rotation)
|
||||||
|
sinp = 2.0 * (q[3] * q[1] - q[2] * q[0])
|
||||||
|
if abs(sinp) >= 1:
|
||||||
|
pitch = np.copysign(np.pi / 2, sinp) # Use 90 degrees if out of range
|
||||||
|
else:
|
||||||
|
pitch = np.arcsin(sinp)
|
||||||
|
|
||||||
|
# Yaw (z-axis rotation)
|
||||||
|
siny_cosp = 2.0 * (q[3] * q[2] + q[0] * q[1])
|
||||||
|
cosy_cosp = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2])
|
||||||
|
yaw = np.arctan2(siny_cosp, cosy_cosp)
|
||||||
|
|
||||||
|
return [roll, pitch, yaw]
|
||||||
|
|
||||||
|
|
||||||
|
def rotate_vector_by_quaternion(quat, v):
|
||||||
|
"""
|
||||||
|
Rotate vector v by quaternion quat.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
v : numpy array (3,) - vector in original frame (frame0)
|
||||||
|
quat : numpy array (4,) - quaternion [x, y, z, w] representing rotation from frame0 to frame1
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
v_rotated : numpy array (3,) - vector expressed in frame1
|
||||||
|
"""
|
||||||
|
# Ensure quaternion is normalized
|
||||||
|
q = quat / np.linalg.norm(quat)
|
||||||
|
x, y, z, w = q
|
||||||
|
|
||||||
|
# Extract vector part of quaternion
|
||||||
|
q_vec = np.array([x, y, z])
|
||||||
|
|
||||||
|
# Compute using vector formula
|
||||||
|
v_rotated = (w * w - np.dot(q_vec, q_vec)) * v \
|
||||||
|
+ 2 * np.dot(q_vec, v) * q_vec \
|
||||||
|
+ 2 * w * np.cross(q_vec, v)
|
||||||
|
|
||||||
|
return v_rotated
|
||||||
|
|
||||||
|
def quaternion_multiply( q1, q2):
|
||||||
|
'''
|
||||||
|
return x, y, z, w
|
||||||
|
'''
|
||||||
|
x1, y1, z1, w1 = q1
|
||||||
|
x2, y2, z2, w2 = q2
|
||||||
|
|
||||||
|
w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2
|
||||||
|
x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2
|
||||||
|
y = w1 * y2 - x1 * z2 + y1 * w2 + z1 * x2
|
||||||
|
z = w1 * z2 + x1 * y2 - y1 * x2 + z1 * w2
|
||||||
|
|
||||||
|
return np.array([x, y, z, w], dtype=np.float32)
|
||||||
|
|
||||||
def main(args=None):
|
def main(args=None):
|
||||||
rclpy.init(args=args)
|
rclpy.init(args=args)
|
||||||
arm_node = RM_Arm()
|
arm_node = KinematicsSolver()
|
||||||
executor = MultiThreadedExecutor()
|
executor = MultiThreadedExecutor()
|
||||||
executor.add_node(arm_node)
|
executor.add_node(arm_node)
|
||||||
|
|
||||||
|
|||||||
63
harvest_arm_ctrl/launch/kine_arm.launch.py
Normal file
63
harvest_arm_ctrl/launch/kine_arm.launch.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from launch import LaunchDescription
|
||||||
|
from launch_ros.actions import Node
|
||||||
|
from ament_index_python.packages import get_package_share_directory
|
||||||
|
|
||||||
|
|
||||||
|
def generate_launch_description():
|
||||||
|
package_share_dir_rm = get_package_share_directory("harvest_arm_rm")
|
||||||
|
package_share_dir = get_package_share_directory("harvest_arm_ctrl")
|
||||||
|
|
||||||
|
config_file = os.path.join(
|
||||||
|
package_share_dir_rm,
|
||||||
|
"config",
|
||||||
|
"config.yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
urdf_file = os.path.join(
|
||||||
|
package_share_dir_rm,
|
||||||
|
"urdf",
|
||||||
|
"urdf_rm75",
|
||||||
|
"RM75.urdf"
|
||||||
|
)
|
||||||
|
meshes_dir = str(Path(urdf_file).parent)
|
||||||
|
|
||||||
|
|
||||||
|
kine_arm_node = Node(
|
||||||
|
package="harvest_arm_ctrl",
|
||||||
|
executable="kine_arm",
|
||||||
|
name="kine_arm_node",
|
||||||
|
output="screen",
|
||||||
|
parameters=[
|
||||||
|
config_file,
|
||||||
|
{
|
||||||
|
"urdf_path": urdf_file,
|
||||||
|
"mesh_dir": meshes_dir,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return LaunchDescription([
|
||||||
|
kine_arm_node,
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
colcon build --packages-select harvest_arm_ctrl --symlink-install
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
@ -1,4 +1,6 @@
|
|||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
|
import os
|
||||||
|
from glob import glob
|
||||||
|
|
||||||
package_name = 'harvest_arm_ctrl'
|
package_name = 'harvest_arm_ctrl'
|
||||||
|
|
||||||
@ -10,6 +12,9 @@ setup(
|
|||||||
('share/ament_index/resource_index/packages',
|
('share/ament_index/resource_index/packages',
|
||||||
['resource/' + package_name]),
|
['resource/' + package_name]),
|
||||||
('share/' + package_name, ['package.xml']),
|
('share/' + package_name, ['package.xml']),
|
||||||
|
|
||||||
|
(os.path.join('share', package_name, 'launch'),
|
||||||
|
glob('launch/*.launch.py')),
|
||||||
],
|
],
|
||||||
install_requires=['setuptools'],
|
install_requires=['setuptools'],
|
||||||
zip_safe=True,
|
zip_safe=True,
|
||||||
@ -24,7 +29,7 @@ setup(
|
|||||||
},
|
},
|
||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': [
|
'console_scripts': [
|
||||||
'kinematics_arm = harvest_arm_ctrl.run_kinematics_arm:main',
|
'kine_arm = harvest_arm_ctrl.run_kinematics_arm:main',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -6,23 +6,37 @@
|
|||||||
min_joint: [-155.0, -30.0, -172.0, -130.0, -175.0, -125.0, -179.0]
|
min_joint: [-155.0, -30.0, -172.0, -130.0, -175.0, -125.0, -179.0]
|
||||||
|
|
||||||
interval: 0.02
|
interval: 0.02
|
||||||
|
tool_name: "scissor"
|
||||||
|
|
||||||
|
action_topic: "/action/arm"
|
||||||
|
observation_topic: "/observation/arm"
|
||||||
|
|
||||||
|
action_pose_topic: "/action/pose"
|
||||||
|
action_tool_topic: "/action/tool"
|
||||||
|
action_arm_enable_topic: "/action/arm_enable"
|
||||||
|
|
||||||
|
|
||||||
harvest_arm_ctrl:
|
harvest_arm_ctrl:
|
||||||
ros__parameters:
|
ros__parameters:
|
||||||
|
|
||||||
tool_name: "scissor"
|
|
||||||
|
|
||||||
tool_names: ["scissor", "omnipic", "minisci", "vacuum", "no_tool"]
|
|
||||||
|
# set the position and quaternion of the task frame in the base frame.
|
||||||
|
arm_installation : [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
|
||||||
|
|
||||||
|
|
||||||
|
tool_names: ["scissor", "omnipic", "minisci", "camera", "gripper_bh", "no_tool"]
|
||||||
|
|
||||||
qp_iteration: 200
|
qp_iteration: 200
|
||||||
|
|
||||||
arm_installation: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
|
arm_installation: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
|
||||||
|
|
||||||
# 0~2 position, x, y, z, m
|
# The tool parameters are defined in the following order:
|
||||||
# 3~6 orientation, quaternion, x, y, z, w
|
# 0~2 position, x, y, z, m
|
||||||
# 7 mass, kg
|
# 3~6 orientation, quaternion, x, y, z, w
|
||||||
# 8~10 center of mass, x, y, z, m
|
# 7 mass, kg
|
||||||
|
# 8~10 center of mass, x, y, z, m
|
||||||
tools_in_ee.scissor: [
|
tools_in_ee.scissor: [
|
||||||
0.0, 0.0, 0.19, 0.0, 0.0, 0.0, 1.0,
|
0.0, 0.0, 0.19, 0.0, 0.0, 0.0, 1.0,
|
||||||
0.66, 0.0, 0.0, 0.06
|
0.66, 0.0, 0.0, 0.06
|
||||||
@ -38,11 +52,24 @@ harvest_arm_ctrl:
|
|||||||
0.46, 0.0, 0.0, 0.06
|
0.46, 0.0, 0.0, 0.06
|
||||||
]
|
]
|
||||||
|
|
||||||
|
tools_in_ee.camera: [
|
||||||
|
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
|
||||||
|
0.0, 0.0, 0.0, 0.0
|
||||||
|
]
|
||||||
|
|
||||||
|
tools_in_ee.gripper_bh: [
|
||||||
|
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
|
||||||
|
0.0, 0.0, 0.0, 0.0
|
||||||
|
]
|
||||||
|
|
||||||
tools_in_ee.no_tool: [
|
tools_in_ee.no_tool: [
|
||||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
|
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
|
||||||
0.0, 0.0, 0.0, 0.0
|
0.0, 0.0, 0.0, 0.0
|
||||||
]
|
]
|
||||||
|
|
||||||
|
bound_cartesian: [ -0.3, -0.5, -0.1, 0.3, 0.5, 0.6 ]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
harvest_arm_rm:
|
harvest_arm_rm:
|
||||||
ros__parameters:
|
ros__parameters:
|
||||||
@ -60,15 +87,6 @@ harvest_arm_rm:
|
|||||||
max_cartesian_acc: 1.0
|
max_cartesian_acc: 1.0
|
||||||
max_cartesian_angular_acc: 2.0
|
max_cartesian_angular_acc: 2.0
|
||||||
|
|
||||||
bound_cartesian: [
|
|
||||||
-0.3, -0.5, -0.1, 0.3, 0.5, 0.6
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
action_topic: "/action/arm"
|
|
||||||
observation_topic: "/observation/arm"
|
|
||||||
action_rviz_topic: "/action/arm_rviz"
|
action_rviz_topic: "/action/arm_rviz"
|
||||||
observation_rviz_topic: "/observation/arm_rviz"
|
observation_rviz_topic: "/observation/arm_rviz"
|
||||||
|
|
||||||
|
|||||||
@ -66,11 +66,11 @@ class RM_Arm(Node):
|
|||||||
dict: Configuration dictionary containing robot IP, host IP, prefix, left/right status, port, savefile flag, and scissor gripper status.
|
dict: Configuration dictionary containing robot IP, host IP, prefix, left/right status, port, savefile flag, and scissor gripper status.
|
||||||
"""
|
"""
|
||||||
tool_name = self.declare_parameter('tool_name', "no_tool").value
|
tool_name = self.declare_parameter('tool_name', "no_tool").value
|
||||||
tool_name_param = 'tools_in_ee.' + tool_name
|
# tool_name_param = 'tools_in_ee.' + tool_name
|
||||||
try:
|
# try:
|
||||||
tool_offset_list = self.declare_parameter(tool_name_param, [0.0] * 11).value
|
# tool_offset_list = self.declare_parameter(tool_name_param, [0.0] * 11).value
|
||||||
except:
|
# except:
|
||||||
self.get_logger().error(f"Tool name '{tool_name}' not found in parameters. Please check the configuration.")
|
# self.get_logger().error(f"Tool name '{tool_name}' not found in parameters. Please check the configuration.")
|
||||||
|
|
||||||
|
|
||||||
acc_lmt = self.declare_parameter('max_joint_acc', 600.0).value
|
acc_lmt = self.declare_parameter('max_joint_acc', 600.0).value
|
||||||
@ -91,12 +91,12 @@ class RM_Arm(Node):
|
|||||||
"max_cartesian_angular_speed": self.declare_parameter('max_cartesian_angular_speed', 1.5).value,
|
"max_cartesian_angular_speed": self.declare_parameter('max_cartesian_angular_speed', 1.5).value,
|
||||||
"max_cartesian_acc": self.declare_parameter('max_cartesian_acc', 1.5).value,
|
"max_cartesian_acc": self.declare_parameter('max_cartesian_acc', 1.5).value,
|
||||||
"max_cartesian_angular_acc": self.declare_parameter('max_cartesian_angular_acc', 2.0).value,
|
"max_cartesian_angular_acc": self.declare_parameter('max_cartesian_angular_acc', 2.0).value,
|
||||||
"bound_cartesian": self.declare_parameter('bound_cartesian', [-0.3, -0.5, -0.1, 0.3, 0.5, 0.6]).value,
|
# "bound_cartesian": self.declare_parameter('bound_cartesian', [-0.3, -0.5, -0.1, 0.3, 0.5, 0.6]).value,
|
||||||
|
|
||||||
"arm_installation": self.declare_parameter('arm_installation', [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]).value,
|
# "arm_installation": self.declare_parameter('arm_installation', [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]).value,
|
||||||
"tool_name": tool_name,
|
"tool_name": tool_name,
|
||||||
"tool_offset": tool_offset_list,
|
# "tool_offset": tool_offset_list,
|
||||||
"tool_names": self.declare_parameter('tool_names', ["scissor", "omnipic", "minisci", "no_tool"]).value,
|
# "tool_names": self.declare_parameter('tool_names', ["scissor", "omnipic", "minisci", "no_tool"]).value,
|
||||||
|
|
||||||
"initial_joint": self.declare_parameter('initial_joint', [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]).value,
|
"initial_joint": self.declare_parameter('initial_joint', [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]).value,
|
||||||
"kp_j": self.declare_parameter('kp_j', 1.0).value,
|
"kp_j": self.declare_parameter('kp_j', 1.0).value,
|
||||||
@ -113,12 +113,20 @@ class RM_Arm(Node):
|
|||||||
"arm_tool_io_mode": self.declare_parameter('arm_tool_io_mode', [1, 1]).value
|
"arm_tool_io_mode": self.declare_parameter('arm_tool_io_mode', [1, 1]).value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# joint_cmd: the joint command to the arm, unit: degree;
|
||||||
|
# joint_target: the joint target from the /action/arm, unit: degree;
|
||||||
|
# joint_pos_sts: the joint position from the arm udp (real robot) or from the /observation/arm_rviz (if no real robot), unit: degree;
|
||||||
|
# joint_speed_sts: the joint speed from the arm udp (real robot) or from the /observation/arm_rviz (if no real robot), unit: degree/s;
|
||||||
|
# arm_enable: 1 or 0, the arm enable status from the /action/arm;
|
||||||
|
# tool_cmd: the tool command from the /action/arm, 1 or 0;
|
||||||
|
# pose_sts: the pose from the arm udp (real robot), unit: m and rad;
|
||||||
sts = {
|
sts = {
|
||||||
"joint_cmd": [0.0] * 7,
|
"joint_cmd": [0.0] * 7,
|
||||||
"joint_target": [0.0] * 7,
|
"joint_target": [0.0] * 7,
|
||||||
"joint_pos_sts": [0.0] * 7,
|
"joint_pos_sts": [0.0] * 7,
|
||||||
"joint_speed_sts": [0.0] * 7,
|
"joint_speed_sts": [0.0] * 7,
|
||||||
"arm_enable": int(0),
|
"arm_enable": int(0),
|
||||||
|
"ik_ret": int(0),
|
||||||
"tool_cmd": [int(0), int(0)],
|
"tool_cmd": [int(0), int(0)],
|
||||||
"pose_sts": [0.0] * 6,
|
"pose_sts": [0.0] * 6,
|
||||||
"timer_cnt": 0,
|
"timer_cnt": 0,
|
||||||
@ -157,13 +165,14 @@ class RM_Arm(Node):
|
|||||||
|
|
||||||
action_list = list(msg.position)
|
action_list = list(msg.position)
|
||||||
self.sts["arm_enable"] = int(action_list[0])
|
self.sts["arm_enable"] = int(action_list[0])
|
||||||
self.sts["joint_target"] = action_list[1:8]
|
self.sts["ik_ret"] = int(action_list[1])
|
||||||
self.sts["tool_cmd"][0] = int(action_list[8])
|
self.sts["joint_target"] = action_list[2:9]
|
||||||
|
self.sts["tool_cmd"][0] = int(action_list[9])
|
||||||
|
|
||||||
|
|
||||||
def arm_observation_relay_pub(self):
|
def arm_observation_relay_pub(self):
|
||||||
"""
|
"""
|
||||||
Publish the current state of the robotic arm.
|
Publish the current state of the robotic arm to rviz.
|
||||||
"""
|
"""
|
||||||
msg0= JointState()
|
msg0= JointState()
|
||||||
msg0.header.stamp = self.get_clock().now().to_msg()
|
msg0.header.stamp = self.get_clock().now().to_msg()
|
||||||
@ -173,7 +182,9 @@ class RM_Arm(Node):
|
|||||||
self.action_rviz_pub.publish(msg0)
|
self.action_rviz_pub.publish(msg0)
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
publish the joint state to the harvest_arm_ctrl pkg.
|
||||||
|
'''
|
||||||
msg = JointState()
|
msg = JointState()
|
||||||
msg.header.stamp = self.get_clock().now().to_msg()
|
msg.header.stamp = self.get_clock().now().to_msg()
|
||||||
arm_real = self.arm_arg['arm_handle'].id
|
arm_real = self.arm_arg['arm_handle'].id
|
||||||
@ -283,9 +294,9 @@ class RM_Arm(Node):
|
|||||||
send joint command to the arm
|
send joint command to the arm
|
||||||
"""
|
"""
|
||||||
############# movej --> arm
|
############# movej --> arm
|
||||||
if self.sts["arm_enable"] == 1:
|
if self.sts["arm_enable"] == 1 and self.sts["ik_ret"] == 1:
|
||||||
dis_max_vt = self.config["max_joint_speed"] * self.config["interval"]
|
dis_max_vt = self.config["max_joint_speed"] * self.config["interval"]
|
||||||
dis_vt = np.array(self.sts["joint_speed_sts"]) * self.config["interval"] * 0.75
|
dis_vt = np.array(self.sts["joint_speed_sts"]) * self.config["interval"] * 0.8
|
||||||
d_j = np.clip(a=(np.array(self.sts["joint_target"]) - np.array(self.sts["joint_pos_sts"])) * self.config["kp_j"],
|
d_j = np.clip(a=(np.array(self.sts["joint_target"]) - np.array(self.sts["joint_pos_sts"])) * self.config["kp_j"],
|
||||||
a_min= dis_vt - self.config["lmt_05att"] ,
|
a_min= dis_vt - self.config["lmt_05att"] ,
|
||||||
a_max=dis_vt + self.config["lmt_05att"])
|
a_max=dis_vt + self.config["lmt_05att"])
|
||||||
@ -314,7 +325,7 @@ class RM_Arm(Node):
|
|||||||
arm (RoboticArm): Instance of the RoboticArm class.
|
arm (RoboticArm): Instance of the RoboticArm class.
|
||||||
config (dict): Configuration dictionary containing tool offsets.
|
config (dict): Configuration dictionary containing tool offsets.
|
||||||
"""
|
"""
|
||||||
self.frame_cfg()
|
# self.frame_cfg()
|
||||||
self.connector_cfg()
|
self.connector_cfg()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -89,7 +89,7 @@ header:
|
|||||||
nanosec: $(date +%N)
|
nanosec: $(date +%N)
|
||||||
frame_id: ''
|
frame_id: ''
|
||||||
name: []
|
name: []
|
||||||
position: [1.0, 82.6, -20.28, 32.15, -50.28, -17.28, -64.055, 20.62, 1.0]
|
position: [1.0, 1.0, 82.6, -20.28, 32.15, -50.28, -17.28, -64.055, 20.62, 1.0]
|
||||||
velocity: []
|
velocity: []
|
||||||
effort: []
|
effort: []
|
||||||
" --once
|
" --once
|
||||||
|
|||||||
Reference in New Issue
Block a user