rotate_end_effector in circular

本文深入探讨了六轴机器人手臂,如Mecademic的Meca500,在使用过程中遇到的奇点问题。奇点是特定配置下,机器人末端执行器在某些方向上运动受阻的现象,对轨迹规划造成影响。文章解释了关节空间和笛卡尔空间控制下的机器人运动,并提供了避免奇点的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

What are singularities in a six-axis robot arm?
If you intend to use a six-axis robot arm, such as Mecademic’s Meca500, the example featured in this tutorial, you will probably need to do more than just position and orient the robot end-effector in various poses. You will likely also need the end-effector to follow prescribed paths as in gluing, or when inserting a pin. If this is the case, then you must learn about robot singularities, because these special configurations will often impede the Cartesian movements of your robot end-effector. You must therefore know how to keep away from robot singularities by properly designing your robot cell.

An industrial robot can be controlled in two spaces: joint space and Cartesian space. Hence, there are two sets of position-mode motion commands that make an industrial robot move. For joint-space motion commands (sometimes incorrectly called point-to-point commands), you simply specify — directly or indirectly — a desired set of joint positions, and the robot moves by translating or rotating each joint to the desired joint position, simultaneously and in a linear fashion. For Cartesian-space motion commands, you specify a desired pose for the end-effector AND a desired Cartesian path (linear or circular). To find the necessary joint positions along the desired Cartesian path, the robot controller must calculate the inverse position and velocity kinematics of the robot. Singularities arise when this calculation fails (for example, when you have division by zero) and must therefore be avoided.

Try jogging a six-axis robot arm in joint space, and the only time the robot will stop is when a joint hits a limit or when there is a mechanical interference. In contrast, try jogging the same robot in Cartesian space and the robot will frequently stop and refuse to go in certain directions, although it seems to be far from what you think is the workspace boundary. A robot singularity is a configuration in which the robot end-effector becomes blocked in certain directions.

#include <moveit/move_group_interface/move_group_interface.h>
#include <moveit/planning_scene_interface/planning_scene_interface.h>
#include <moveit_msgs/DisplayRobotState.h>
#include <moveit_msgs/DisplayTrajectory.h>
#include <moveit_msgs/AttachedCollisionObject.h>
#include <moveit_msgs/CollisionObject.h>
#include <moveit_visual_tools/moveit_visual_tools.h>

int main(int argc, char** argv)
{
  ros::init(argc, argv, "rotate_end_effector");
  ros::NodeHandle node_handle;
  ros::AsyncSpinner spinner(1);
  spinner.start();

  // Setup
  static const std::string PLANNING_GROUP = "xarm7";
  moveit::planning_interface::MoveGroupInterface move_group(PLANNING_GROUP);

  // We will use the :planning_scene_interface:`PlanningSceneInterface`
  // class to add and remove collision objects in our "virtual world" scene
  moveit::planning_interface::PlanningSceneInterface planning_scene_interface;

  // Raw pointers are frequently used to refer to the planning group for improved performance.
  const robot_state::JointModelGroup* joint_model_group =
      move_group.getCurrentState()->getJointModelGroup(PLANNING_GROUP);


// Visualization
  // The package MoveItVisualTools provides many capabilties for visualizing objects, robots,
  // and trajectories in RViz as well as debugging tools such as step-by-step introspection of a script
  namespace rvt = rviz_visual_tools;
  moveit_visual_tools::MoveItVisualTools visual_tools("base_link");
  visual_tools.deleteAllMarkers();

  // Remote control is an introspection tool that allows users to step through a high level script
  // via buttons and keyboard shortcuts in RViz
  visual_tools.loadRemoteControl();

  // RViz provides many types of markers, in this demo we will use text, cylinders, and spheres
  Eigen::Affine3d text_pose = Eigen::Affine3d::Identity();
  text_pose.translation().z() = 1.75;
  visual_tools.publishText(text_pose, "rotate_end_effector", rvt::WHITE, rvt::XLARGE);

  // Batch publishing is used to reduce the number of messages being sent to RViz for large visualizations
  visual_tools.trigger();

  // Getting Basic Information
  // ^^^^^^^^^^^^^^^^^^^^^^^^^
  //
  // We can print the name of the reference frame for this robot.
  ROS_INFO_NAMED("tutorial", "Reference frame: %s", move_group.getPlanningFrame().c_str());

  // We can also print the name of the end-effector link for this group.
  ROS_INFO_NAMED("tutorial", "End effector link: %s", move_group.getEndEffectorLink().c_str());

  // Start the demo
  // ^^^^^^^^^^^^^^^^^^^^^^^^^
  visual_tools.prompt("Press 'next' in the RvizVisualToolsGui window to start the demo");


  geometry_msgs::Pose target_pose = move_group.getCurrentPose().pose;
  //2. Create Cartesian Paths
  std::vector<geometry_msgs::Pose> waypoints;
  geometry_msgs::Pose ee_point_goal; //end_effector_trajectory
  //ee_point_goal.orientation.w = 1;
  ee_point_goal.position.z = target_pose.position.z;
  // add the start position in path list 
  waypoints.push_back(target_pose);
  // Trajectory parameters (circle)
  double angle_resolution = 36;
  double d_angle = angle_resolution*3.14/180;
  double angle= 0;
  double radius = 0.2;
  double centerA = target_pose.position.x;
  double centerB = target_pose.position.y - radius;
  //----------------------------------------------------------------------
  //3. Plan for the trajectory
  for (int i= 0; i< (360/angle_resolution); i++)
  {
    //discretize the trajectory
    angle += i * d_angle;
    ee_point_goal.position.x = centerA + radius * cos(angle);
    ee_point_goal.position.y = centerB + radius * sin(angle);
    waypoints.push_back(ee_point_goal);
  }

  ROS_INFO("There are %d number of waypoints", waypoints.size());
  // We want cartesian path to be interpolated at a eef_resolution
  double eef_resolution = 0.01;
  moveit_msgs::RobotTrajectory trajectory;
  double jump_threshold = 0.0;
  double fraction = move_group.computeCartesianPath(waypoints, eef_resolution, jump_threshold, trajectory);

  moveit::planning_interface::MoveGroupInterface::Plan my_plan;
  my_plan.trajectory_ = trajectory;
  sleep(5.0);
  visual_tools.deleteAllMarkers();
  visual_tools.publishText(text_pose, "Cartesian Path", rvt::WHITE, rvt::XLARGE);
  visual_tools.publishTrajectoryLine(my_plan.trajectory_, joint_model_group);
    for (std::size_t i = 0; i < waypoints.size(); ++i){
         visual_tools.publishAxisLabeled(waypoints[i], "pt" + std::to_string(i), rvt::SMALL);
  }
  visual_tools.trigger();
    move_group.execute(my_plan);
}

import numpy as np from scipy.spatial.transform import Rotation as R # 相机坐标系到机械臂末端坐标系的旋转矩阵和平移向量(手眼标定得到) rotation_matrix = np.array([[-0.00235395 , 0.99988123 ,-0.01523124], [-0.99998543, -0.00227965, 0.0048937], [0.00485839, 0.01524254, 0.99987202]]) translation_vector = np.array([-0.09321419, 0.03625434, 0.02420657]) def decompose_transform(matrix): """ 将矩阵转化为位姿 """ translation = matrix[:3, 3] rotation = matrix[:3, :3] # Convert rotation matrix to euler angles (rx, ry, rz) sy = np.sqrt(rotation[0, 0] * rotation[0, 0] + rotation[1, 0] * rotation[1, 0]) singular = sy < 1e-6 if not singular: rx = np.arctan2(rotation[2, 1], rotation[2, 2]) ry = np.arctan2(-rotation[2, 0], sy) rz = np.arctan2(rotation[1, 0], rotation[0, 0]) else: rx = np.arctan2(-rotation[1, 2], rotation[1, 1]) ry = np.arctan2(-rotation[2, 0], sy) rz = 0 return translation, rx, ry, rz def convert(x,y,z,rx,ry,rz,x1,y1,z1,rx1,ry1,rz1): """ 我们需要将标定得到的旋转向量和平移向量转换为齐次变换矩阵,然后使用机械臂末端的位姿(x, y, z,rx,ry,rz)和 深度相机识别到的物体坐标(x1,y1,z1,rx1,ry1,rz1)来计算物体相对于机械臂基座的位姿 """ # 深度相机识别物体返回的坐标 obj_camera_coordinates = np.array([x1, y1, z1,rx1,ry1,rz1]) # 机械臂末端的位姿,单位为弧度 end_effector_pose = np.array([x, y, z, rx, ry, rz]) # 将旋转矩阵和平移向量转换为齐次变换矩阵 T_camera_to_end_effector = np.eye(4) T_camera_to_end_effector[:3, :3] = rotation_matrix T_camera_to_end_effector[:3, 3] = translation_vector # 机械臂末端的位姿转换为齐次变换矩阵 position = end_effector_pose[:3] orientation = R.from_euler('xyz', end_effector_pose[3:], degrees=False).as_matrix() T_end_to_base_effector = np.eye(4) T_end_to_base_effector[:3, :3] = orientation T_end_to_base_effector[:3, 3] = position # 计算物体相对于机械臂基座的位姿 # 物体相对于相机的位姿转换为齐次变换矩阵 position2 = obj_camera_coordinates[:3] orientation2 = R.from_euler('xyz', obj
03-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值