您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 

230 行
9.0 KiB

using System.Collections;
using System.Linq;
using RosMessageTypes.Geometry;
using RosMessageTypes.NiryoMoveit;
using UnityEngine;
using ROSGeometry;
using Quaternion = UnityEngine.Quaternion;
using RosImage = RosMessageTypes.Sensor.Image;
using Transform = UnityEngine.Transform;
using Vector3 = UnityEngine.Vector3;
public class TrajectoryPlanner : MonoBehaviour
{
// ROS Connector
public ROSConnection ros;
private int numRobotJoints = 6;
// Hardcoded variables
private readonly float jointAssignmentWait = 0.1f;
private readonly float poseAssignmentWait = 0.5f;
private readonly Vector3 pickPoseOffset = Vector3.up * 0.1f;
// 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 rosServiceName = "niryo_moveit";
public GameObject niryoOne;
public GameObject target;
public GameObject targetPlacement;
// Articulation Bodies
private ArticulationBody[] jointArticulationBodies;
private ArticulationBody leftGripper;
private ArticulationBody rightGripper;
private Transform gripperBase;
private Transform leftGripperGameObject;
private Transform rightGripperGameObject;
private enum Poses
{
PreGrasp,
Grasp,
PickUp,
Place
};
/// <summary>
/// Close the gripper
/// </summary>
private void CloseGripper()
{
var leftDrive = leftGripper.xDrive;
var rightDrive = rightGripper.xDrive;
leftDrive.target = 0.01f;
rightDrive.target = -0.01f;
leftGripper.xDrive = leftDrive;
rightGripper.xDrive = rightDrive;
}
/// <summary>
/// Open the gripper
/// </summary>
private void OpenGripper()
{
var leftDrive = leftGripper.xDrive;
var rightDrive = rightGripper.xDrive;
leftDrive.target = -0.01f;
rightDrive.target = 0.01f;
leftGripper.xDrive = leftDrive;
rightGripper.xDrive = rightDrive;
}
/// <summary>
/// Get the current values of the robot's joint angles.
/// </summary>
/// <returns>NiryoMoveitJoints</returns>
NiryoMoveitJoints CurrentJointConfig()
{
NiryoMoveitJoints joints = new NiryoMoveitJoints();
joints.joint_00 = jointArticulationBodies[0].xDrive.target;
joints.joint_01 = jointArticulationBodies[1].xDrive.target;
joints.joint_02 = jointArticulationBodies[2].xDrive.target;
joints.joint_03 = jointArticulationBodies[3].xDrive.target;
joints.joint_04 = jointArticulationBodies[4].xDrive.target;
joints.joint_05 = jointArticulationBodies[5].xDrive.target;
return joints;
}
/// <summary>
/// Create a new MoverServiceRequest with the current values of the robot's joint angles,
/// the target cube's current position and rotation, and the targetPlacement position and rotation.
///
/// Call the MoverService using the ROSConnection and if a trajectory is successfully planned,
/// execute the trajectories in a coroutine.
/// </summary>
public void PublishJoints()
{
MoverServiceRequest request = new MoverServiceRequest();
request.joints_input = CurrentJointConfig();
// Pick Pose
request.pick_pose = new RosMessageTypes.Geometry.Pose
{
position = (target.transform.position + pickPoseOffset).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
request.place_pose = new RosMessageTypes.Geometry.Pose
{
position = (targetPlacement.transform.position + pickPoseOffset).To<FLU>(),
orientation = pickOrientation.To<FLU>()
};
ros.SendServiceMessage<MoverServiceResponse>(rosServiceName, request, TrajectoryResponse);
}
void TrajectoryResponse(MoverServiceResponse response)
{
if (response.trajectories != null)
{
Debug.Log("Trajectory returned.");
StartCoroutine(ExecuteTrajectories(response));
}
else
{
Debug.LogError("No trajectory returned from MoverService.");
}
}
/// <summary>
/// Execute the returned trajectories from the MoverService.
///
/// The expectation is that the MoverService will return four trajectory plans,
/// PreGrasp, Grasp, PickUp, and Place,
/// where each plan is an array of robot poses. A robot pose is the joint angle values
/// of the six robot joints.
///
/// Executing a single trajectory will iterate through every robot pose in the array while updating the
/// joint values on the robot.
///
/// </summary>
/// <param name="response"> MoverServiceResponse received from niryo_moveit mover service running in ROS</param>
/// <returns></returns>
private IEnumerator ExecuteTrajectories(MoverServiceResponse response)
{
if (response.trajectories != null)
{
// For every trajectory plan returned
for (int poseIndex = 0 ; poseIndex < response.trajectories.Length; poseIndex++)
{
// For every robot pose in trajectory plan
for (int jointConfigIndex = 0 ; jointConfigIndex < response.trajectories[poseIndex].joint_trajectory.points.Length; jointConfigIndex++)
{
var jointPositions = response.trajectories[poseIndex].joint_trajectory.points[jointConfigIndex].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(jointAssignmentWait);
}
// Close the gripper if completed executing the trajectory for the Grasp pose
if (poseIndex == (int)Poses.Grasp)
CloseGripper();
// Wait for the robot to achieve the final pose from joint assignment
yield return new WaitForSeconds(poseAssignmentWait);
}
// All trajectories have been executed, open the gripper to place the target cube
OpenGripper();
}
}
/// <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[numRobotJoints];
string shoulder_link = "world/base_link/shoulder_link";
jointArticulationBodies[0] = niryoOne.transform.Find(shoulder_link).GetComponent<ArticulationBody>();
string arm_link = shoulder_link + "/arm_link";
jointArticulationBodies[1] = niryoOne.transform.Find(arm_link).GetComponent<ArticulationBody>();
string elbow_link = arm_link + "/elbow_link";
jointArticulationBodies[2] = niryoOne.transform.Find(elbow_link).GetComponent<ArticulationBody>();
string forearm_link = elbow_link + "/forearm_link";
jointArticulationBodies[3] = niryoOne.transform.Find(forearm_link).GetComponent<ArticulationBody>();
string wrist_link = forearm_link + "/wrist_link";
jointArticulationBodies[4] = niryoOne.transform.Find(wrist_link).GetComponent<ArticulationBody>();
string hand_link = wrist_link + "/hand_link";
jointArticulationBodies[5] = niryoOne.transform.Find(hand_link).GetComponent<ArticulationBody>();
// Find left and right fingers
string right_gripper = hand_link + "/tool_link/gripper_base/servo_head/control_rod_right/right_gripper";
string left_gripper = hand_link + "/tool_link/gripper_base/servo_head/control_rod_left/left_gripper";
string gripper_base = hand_link + "/tool_link/gripper_base/Collisions/unnamed";
gripperBase = niryoOne.transform.Find(gripper_base);
leftGripperGameObject = niryoOne.transform.Find(left_gripper);
rightGripperGameObject = niryoOne.transform.Find(right_gripper);
rightGripper = rightGripperGameObject.GetComponent<ArticulationBody>();
leftGripper = leftGripperGameObject.GetComponent<ArticulationBody>();
}
}