您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
206 行
7.9 KiB
206 行
7.9 KiB
using System.Collections;
|
|
using System.Linq;
|
|
using RosMessageTypes.Geometry;
|
|
using RosMessageTypes.Moveit;
|
|
using RosMessageTypes.NiryoMoveit;
|
|
using RosMessageTypes.NiryoOne;
|
|
using Unity.Robotics.ROSTCPConnector;
|
|
using Unity.Robotics.ROSTCPConnector.ROSGeometry;
|
|
using UnityEngine;
|
|
|
|
public class RealSimPickAndPlace : MonoBehaviour
|
|
{
|
|
private const int OPEN_GRIPPER = 1;
|
|
private const int CLOSE_GRIPPER = 2;
|
|
private const int TOOL_COMMAND_EXECUTION = 6;
|
|
private const int TRAJECTORY_COMMAND_EXECUTION = 7;
|
|
|
|
private ROSConnection ros;
|
|
private const int NUM_ROBOT_JOINTS = 6;
|
|
|
|
// Hardcoded variables
|
|
private const float JOINT_ASSIGNMENT_WAIT = 0.038f;
|
|
private readonly Vector3 PICK_POSE_OFFSET = Vector3.up * 0.15f;
|
|
|
|
// Assures that the gripper is always positioned above the target cube before grasping.
|
|
private readonly Quaternion pickOrientation = Quaternion.Euler(90, 90, 0);
|
|
|
|
// Variables required for ROS communication
|
|
public string rosJointPublishTopicName = "sim_real_pnp";
|
|
public string rosRobotCommandsTopicName = "niryo_one/commander/robot_action/goal";
|
|
|
|
public GameObject niryoOne;
|
|
public GameObject target;
|
|
public GameObject targetPlacement;
|
|
|
|
// Articulation Bodies
|
|
private ArticulationBody[] jointArticulationBodies;
|
|
private ArticulationBody leftGripperJoint;
|
|
private ArticulationBody rightGripperJoint;
|
|
|
|
private Transform leftGripperGameObject;
|
|
private Transform rightGripperGameObject;
|
|
|
|
/// <summary>
|
|
/// Close the gripper
|
|
/// </summary>
|
|
private void CloseGripper()
|
|
{
|
|
var leftDrive = leftGripperJoint.xDrive;
|
|
var rightDrive = rightGripperJoint.xDrive;
|
|
|
|
leftDrive.target = 0.01f;
|
|
rightDrive.target = -0.01f;
|
|
|
|
leftGripperJoint.xDrive = leftDrive;
|
|
rightGripperJoint.xDrive = rightDrive;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Open the gripper
|
|
/// </summary>
|
|
private void OpenGripper()
|
|
{
|
|
var leftDrive = leftGripperJoint.xDrive;
|
|
var rightDrive = rightGripperJoint.xDrive;
|
|
|
|
leftDrive.target = -0.01f;
|
|
rightDrive.target = 0.01f;
|
|
|
|
leftGripperJoint.xDrive = leftDrive;
|
|
rightGripperJoint.xDrive = rightDrive;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Publish the robot's current joint configuration, the target object's
|
|
/// position and rotation, and the target placement for the target object's
|
|
/// position and rotation.
|
|
///
|
|
/// Includes conversion from Unity coordinates to ROS coordinates, Forward Left Up
|
|
/// </summary>
|
|
public void PublishJoints()
|
|
{
|
|
MMoverServiceRequest request = new MMoverServiceRequest
|
|
{
|
|
joints_input =
|
|
{
|
|
joint_00 = jointArticulationBodies[0].xDrive.target,
|
|
joint_01 = jointArticulationBodies[1].xDrive.target,
|
|
joint_02 = jointArticulationBodies[2].xDrive.target,
|
|
joint_03 = jointArticulationBodies[3].xDrive.target,
|
|
joint_04 = jointArticulationBodies[4].xDrive.target,
|
|
joint_05 = jointArticulationBodies[5].xDrive.target
|
|
},
|
|
pick_pose = new MPose
|
|
{
|
|
position = (target.transform.position + PICK_POSE_OFFSET).To<FLU>(),
|
|
// The hardcoded x/z angles assure that the gripper is always positioned above the target cube before grasping.
|
|
orientation = Quaternion.Euler(90, target.transform.eulerAngles.y, 0).To<FLU>()
|
|
},
|
|
place_pose = new MPose
|
|
{
|
|
position = (targetPlacement.transform.position + PICK_POSE_OFFSET).To<FLU>(),
|
|
orientation = pickOrientation.To<FLU>()
|
|
}
|
|
};
|
|
|
|
ros.Send(rosJointPublishTopicName, request);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Find all robot joints in Awake() and add them to the jointArticulationBodies array.
|
|
/// Find left and right finger joints and assign them to their respective articulation body objects.
|
|
/// </summary>
|
|
void Awake()
|
|
{
|
|
jointArticulationBodies = new ArticulationBody[NUM_ROBOT_JOINTS];
|
|
string shoulder_link = "world/base_link/shoulder_link";
|
|
jointArticulationBodies[0] = niryoOne.transform.Find(shoulder_link).GetComponent<ArticulationBody>();
|
|
|
|
string armLink = shoulder_link + "/arm_link";
|
|
jointArticulationBodies[1] = niryoOne.transform.Find(armLink).GetComponent<ArticulationBody>();
|
|
|
|
string elbowLink = armLink + "/elbow_link";
|
|
jointArticulationBodies[2] = niryoOne.transform.Find(elbowLink).GetComponent<ArticulationBody>();
|
|
|
|
string forearmLink = elbowLink + "/forearm_link";
|
|
jointArticulationBodies[3] = niryoOne.transform.Find(forearmLink).GetComponent<ArticulationBody>();
|
|
|
|
string wristLink = forearmLink + "/wrist_link";
|
|
jointArticulationBodies[4] = niryoOne.transform.Find(wristLink).GetComponent<ArticulationBody>();
|
|
|
|
string handLink = wristLink + "/hand_link";
|
|
jointArticulationBodies[5] = niryoOne.transform.Find(handLink).GetComponent<ArticulationBody>();
|
|
|
|
// Find left and right fingers
|
|
string rightGripper = handLink + "/tool_link/gripper_base/servo_head/control_rod_right/right_gripper";
|
|
string leftGripper = handLink + "/tool_link/gripper_base/servo_head/control_rod_left/left_gripper";
|
|
|
|
leftGripperGameObject = niryoOne.transform.Find(leftGripper);
|
|
rightGripperGameObject = niryoOne.transform.Find(rightGripper);
|
|
|
|
rightGripperJoint = rightGripperGameObject.GetComponent<ArticulationBody>();
|
|
leftGripperJoint = leftGripperGameObject.GetComponent<ArticulationBody>();
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
ros.Subscribe<MRobotMoveActionGoal>(rosRobotCommandsTopicName, ExecuteRobotCommands);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Execute robot commands receved from ROS Subscriber.
|
|
/// Gripper commands will be executed immeditately wihle trajectories will be
|
|
/// executed in a coroutine.
|
|
/// </summary>
|
|
/// <param name="robotAction"> RobotMoveActionGoal of trajectory or gripper commands</param>
|
|
void ExecuteRobotCommands(MRobotMoveActionGoal robotAction)
|
|
{
|
|
if (robotAction.goal.cmd.cmd_type == TRAJECTORY_COMMAND_EXECUTION)
|
|
{
|
|
StartCoroutine(ExecuteTrajectories(robotAction.goal.cmd.Trajectory.trajectory));
|
|
}
|
|
else if (robotAction.goal.cmd.cmd_type == TOOL_COMMAND_EXECUTION)
|
|
{
|
|
if (robotAction.goal.cmd.tool_cmd.cmd_type == OPEN_GRIPPER)
|
|
{
|
|
Debug.Log("Open Tool Command");
|
|
OpenGripper();
|
|
}
|
|
else if (robotAction.goal.cmd.tool_cmd.cmd_type == CLOSE_GRIPPER)
|
|
{
|
|
Debug.Log("Close Tool Command");
|
|
CloseGripper();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Execute trajectories from RobotMoveActionGoal topic.
|
|
///
|
|
/// Execution will iterate through every robot pose in the trajectory pose
|
|
/// array while updating the joint values on the simulated robot.
|
|
///
|
|
/// </summary>
|
|
/// <param name="trajectories"> The array of poses for the robot to execute</param>
|
|
private IEnumerator ExecuteTrajectories(MRobotTrajectory trajectories)
|
|
{
|
|
// For every robot pose in trajectory plan
|
|
foreach (var point in trajectories.joint_trajectory.points)
|
|
{
|
|
var jointPositions = point.positions;
|
|
float[] result = jointPositions.Select(r => (float)r * Mathf.Rad2Deg).ToArray();
|
|
|
|
// Set the joint values for every joint
|
|
for (int joint = 0; joint < jointArticulationBodies.Length; joint++)
|
|
{
|
|
var joint1XDrive = jointArticulationBodies[joint].xDrive;
|
|
joint1XDrive.target = result[joint];
|
|
jointArticulationBodies[joint].xDrive = joint1XDrive;
|
|
}
|
|
// Wait for robot to achieve pose for all joint assignments
|
|
yield return new WaitForSeconds(JOINT_ASSIGNMENT_WAIT);
|
|
}
|
|
}
|
|
}
|