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

245 行
8.7 KiB

#if UNITY_EDITOR
using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
using Unity.Robotics.ROSTCPConnector;
using Unity.Robotics.ROSTCPConnector.MessageGeneration;
using Unity.Robotics.UrdfImporter;
using Unity.Robotics.UrdfImporter.Control;
public class Demo : MonoBehaviour
{
public string hostIP = "127.0.0.1";
public bool generateRosMessages = true;
public bool deleteRosMessagesAfterSimulation = true;
string prefabDirectory = "Assets/Prefabs";
string prefabSuffix = ".prefab";
string tableName = "Table";
string targetName = "Target";
string targetPlacementName = "TargetPlacement";
string cameraName = "Main Camera";
Vector3 cameraPosition = new Vector3(0, 1.4f, -0.7f);
Quaternion cameraRotation = Quaternion.Euler(new Vector3(45, 0, 0));
string urdfRelativeFilepath = "URDF/niryo_one/niryo_one.urdf";
string niryoOneName = "niryo_one";
string baseLinkName = "base_link";
float controllerStiffness = 10000;
float controllerDamping = 100;
float controllerForceLimit = 1000;
float controllerSpeed = 30;
float controllerAcceleration = 10;
string rosMessagesDirectory = "Assets/Scripts/RosMessages";
string rosSrcDirectory = "../ROS/src";
string msgDirectory = "msg";
string srvDirectory = "srv";
string moveitMsgPackageName = "moveit_msgs";
string niryoMoveitPackageName = "niryo_moveit";
string robotTrajectoryMessageFileName = "RobotTrajectory.msg";
string moverServiceFileName = "MoverService.srv";
string scriptPattern = "*.cs";
string registerMethodName = "Register";
string[] rosGeneratedTypeFullName = new string[]
{
"RosMessageTypes.Moveit.RobotTrajectoryMsg",
"RosMessageTypes.NiryoMoveit.NiryoMoveitJointsMsg",
"RosMessageTypes.NiryoMoveit.NiryoTrajectoryMsg",
"RosMessageTypes.NiryoMoveit.MoverServiceResponse",
"RosMessageTypes.NiryoMoveit.MoverServiceRequest"
};
string externalScriptsDirectory = "../Scripts";
//string scriptsDirectory = "Assets/Scripts";
string rosConnectName = "ROSConnect";
string publisherName = "Publisher";
int hostPort = 10000;
string trajectoryPlannerType = "TrajectoryPlanner";
string rosServiceName = "niryo_moveit";
bool hasPublished = false;
Assembly assembly;
ROSConnection rosConnection;
void Awake()
{
EditorApplication.LockReloadAssemblies();
SetupScene();
AddRosMessages();
ImportRobot();
CreateRosConnection();
CreateTrajectoryPlannerPublisher();
}
void Update()
{
// Make sure to publish only once in the demo
if (!hasPublished)
{
dynamic publisher = GameObject.Find(publisherName).GetComponent(assembly.GetType(trajectoryPlannerType));
publisher.PublishJoints();
hasPublished = true;
}
}
void OnApplicationQuit()
{
if (deleteRosMessagesAfterSimulation)
{
Directory.Delete(rosMessagesDirectory, recursive: true);
File.Delete($"{rosMessagesDirectory}.meta");
}
EditorApplication.UnlockReloadAssemblies();
}
// Tutorial Part 1
private void SetupScene()
{
// Instantiate the table, target, and target placement
InstantiatePrefab(tableName);
InstantiatePrefab(targetName);
InstantiatePrefab(targetPlacementName);
// Adjust main camera
GameObject camera = GameObject.Find(cameraName);
camera.transform.position = cameraPosition;
camera.transform.rotation = cameraRotation;
}
// Tutorial Part 2 without the Publisher object
private void AddRosMessages()
{
if (generateRosMessages)
{
// Generate ROS messages
MessageAutoGen.GenerateSingleMessage(
Path.Combine(rosSrcDirectory, moveitMsgPackageName, msgDirectory, robotTrajectoryMessageFileName),
rosMessagesDirectory, moveitMsgPackageName);
MessageAutoGen.GenerateDirectoryMessages(
Path.Combine(rosSrcDirectory, niryoMoveitPackageName, msgDirectory),
rosMessagesDirectory);
// Generate ROS services
ServiceAutoGen.GenerateSingleService(
Path.Combine(rosSrcDirectory, niryoMoveitPackageName, srvDirectory, moverServiceFileName),
rosMessagesDirectory, niryoMoveitPackageName);
}
// Recompile ROS message scripts and external scripts
List<string> scripts = new List<string>();
scripts.AddRange(Directory.GetFiles(rosMessagesDirectory, scriptPattern, SearchOption.AllDirectories));
scripts.AddRange(Directory.GetFiles(externalScriptsDirectory));
RecompileScripts(scripts.ToArray());
// Register Ros message names and their deserialize function
foreach (var typeFullName in rosGeneratedTypeFullName)
{
assembly.GetType(typeFullName).GetMethod(registerMethodName).Invoke(null, null);
}
}
private void CreateTrajectoryPlannerPublisher()
{
GameObject publisher = new GameObject(publisherName);
dynamic planner = publisher.AddComponent(assembly.GetType(trajectoryPlannerType));
planner.rosServiceName = rosServiceName;
planner.niryoOne = GameObject.Find(niryoOneName);
planner.target = GameObject.Find(targetName);
planner.targetPlacement = GameObject.Find(targetPlacementName);
}
private GameObject InstantiatePrefab(string name)
{
string filepath = Path.Combine(prefabDirectory, $"{name}{prefabSuffix}");
GameObject gameObject = Instantiate(AssetDatabase.LoadAssetAtPath<GameObject>(filepath));
gameObject.name = name;
return gameObject;
}
private void CreateRosConnection()
{
// Create RosConnect
GameObject rosConnect = new GameObject(rosConnectName);
rosConnection = rosConnect.AddComponent<ROSConnection>();
rosConnection.RosIPAddress = hostIP;
rosConnection.RosPort = hostPort;
}
private void ImportRobot()
{
ImportSettings urdfImportSettings = new ImportSettings
{
choosenAxis = ImportSettings.axisType.yAxis,
convexMethod = ImportSettings.convexDecomposer.unity
};
// Import Niryo One with URDF importer
string urdfFilepath = Path.Combine(Application.dataPath, urdfRelativeFilepath);
// Create is a coroutine that would usually run only in EditMode, so we need to force its execution here
var robotImporter = UrdfRobotExtensions.Create(urdfFilepath, urdfImportSettings, false);
while (robotImporter.MoveNext()) { }
// Adjust robot parameters
Controller controller = GameObject.Find(niryoOneName).GetComponent<Controller>();
controller.stiffness = controllerStiffness;
controller.damping = controllerDamping;
controller.forceLimit = controllerForceLimit;
controller.speed = controllerSpeed;
controller.acceleration = controllerAcceleration;
GameObject.Find(baseLinkName).GetComponent<ArticulationBody>().immovable = true;
}
// Credit to https://www.codeproject.com/Tips/715891/Compiling-Csharp-Code-at-Runtime
// and https://gamedev.stackexchange.com/questions/130268/how-do-i-compile-a-c-script-at-runtime-and-attach-it-as-a-component-to-a-game-o
private void RecompileScripts(string[] filepaths)
{
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
foreach (Assembly unityAssembly in AppDomain.CurrentDomain.GetAssemblies())
{
parameters.ReferencedAssemblies.Add(unityAssembly.Location);
}
parameters.GenerateInMemory = true;
parameters.GenerateExecutable = false;
string[] texts = new string[filepaths.Length];
for (int i = 0; i < filepaths.Length; i++)
{
texts[i] = File.ReadAllText(filepaths[i]);
}
CompilerResults results = provider.CompileAssemblyFromSource(parameters, texts);
checkCompileErrors(results);
// Update the assembly
assembly = results.CompiledAssembly;
}
private void checkCompileErrors(CompilerResults results)
{
if (results.Errors.HasErrors)
{
StringBuilder stringBuilder = new StringBuilder();
foreach (CompilerError error in results.Errors)
{
stringBuilder.AppendLine($"Error {error.ErrorNumber} {error.ErrorText}");
}
throw new InvalidOperationException(stringBuilder.ToString());
}
}
}
#endif