Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Importing URDF from using script w/o using the editor #222

Open
Kai-X-Org opened this issue Oct 29, 2023 · 1 comment
Open

Importing URDF from using script w/o using the editor #222

Kai-X-Org opened this issue Oct 29, 2023 · 1 comment

Comments

@Kai-X-Org
Copy link

Does the current importer support importing urdf with code? i.e. is there a function I can call in a script that can just import the urdf? I am currently working on interfacing Unity to a Python-based scenario description language and would like to be able to rapidly spawn/delete robots across scenes directly from code without the user having to touch the editor. Thank you so much!

@bv-radiusmedia
Copy link

bv-radiusmedia commented Aug 23, 2024

using System.Collections;
using System.IO;
using System.IO.Compression;
using UnityEngine;
using Unity.Robotics.UrdfImporter;
using UnityEngine.Networking;
using Unity.Robotics.UrdfImporter.Control;
using TMPro;

public class UrdfRuntimeLoader : MonoBehaviour
{
public TextMeshPro DebugText;
public string zipUrl = ""; // URL to download the zip file
public string localZipFileName = "urdf_ue5.zip"; // Name of the local zip file
public string urdfFileName = "ur5e.urdf"; // Name of the URDF file inside the zip
public bool setImmovableLink = true;
public bool useVHACD = false;
public bool showProgress = false;
public bool clearOnLoad = true;

private GameObject currentRobot = null;
private bool isLoading = false;

private IEnumerator LoadUrdf()
{
    isLoading = true;

    string localZipPath = Path.Combine(Application.persistentDataPath, localZipFileName);

    UnityWebRequest zipRequest = UnityWebRequest.Get(zipUrl);
    zipRequest.downloadHandler = new DownloadHandlerFile(localZipPath);
    yield return zipRequest.SendWebRequest();

    if (zipRequest.result != UnityWebRequest.Result.Success)
    {
        Debug.LogError("Failed to download zip file: " + zipRequest.error);
        isLoading = false;
        yield break;
    }

    string extractPath = Path.Combine(Application.persistentDataPath, "ExtractedURDF");

    if (Directory.Exists(extractPath))
    {
        Directory.Delete(extractPath, true);  // Clear any existing extracted content
    }
    Directory.CreateDirectory(extractPath);

    ZipFile.ExtractToDirectory(localZipPath, extractPath);
    Debug.Log("Extracted to: " + extractPath);

    string urdfFilePath = Path.Combine(extractPath + "/URDF ur5e", urdfFileName);
    if (!File.Exists(urdfFilePath))
    {
        Debug.LogError("URDF file not found in the extracted content!");
        isLoading = false;
        yield break;
    }

    if (clearOnLoad && currentRobot != null)
    {
        currentRobot.SetActive(false);
        Destroy(currentRobot);
    }
    yield return null;

    ImportSettings settings = new ImportSettings
    {
        chosenAxis = ImportSettings.axisType.yAxis,
        convexMethod = useVHACD ? ImportSettings.convexDecomposer.vHACD : ImportSettings.convexDecomposer.unity,
    };

    GameObject robotObject = null;
    try
    {
        DebugText.text = $"Loading URDF from: {urdfFilePath}";
        robotObject = UrdfRobotExtensions.CreateRuntime(urdfFilePath, settings);
        DebugText.text = "12 - Robot creation completed";
    }
    catch (System.Exception ex)
    {
        Debug.LogError("Error during URDF creation: " + ex.Message);
        //DebugText.text = "Error during URDF creation: " + ex.Message;
        isLoading = false;
        yield break;
    }

    if (robotObject != null && robotObject.transform != null)
    {
        robotObject.transform.SetParent(transform);
        SetControllerParameters(robotObject);
        Debug.Log("Successfully Loaded URDF: " + robotObject.name);
    }

    currentRobot = robotObject;
    isLoading = false;
}

void SetControllerParameters(GameObject robot)
{
    robot.GetComponent<UrdfRobot>().SetRigidbodiesUseGravity();

    if (robot.TryGetComponent<Controller>(out Controller controller))
    {
        controller.stiffness = 10000;
        controller.damping = 100;
        controller.forceLimit = 10;
        controller.speed = 30;
        controller.acceleration = 10;
        controller.enabled = true;
    }

    if (setImmovableLink)
    {
        Transform baseNode = robot.transform.GetChild(robot.transform.childCount - 1);
        if (baseNode)
        {
            ArticulationBody baseNodeAB = baseNode.GetComponent<ArticulationBody>();
            if (baseNodeAB == null)
            {
                baseNodeAB = baseNode.gameObject.AddComponent<ArticulationBody>();
            }
            baseNodeAB.immovable = true;
        }
        else
        {
            Debug.LogWarning($"The specified immovable link was not found in the robot hierarchy.");
        }
    }
}

public void LoadModel()
{
    StartCoroutine(LoadUrdf());
}

}

I am using this script and it works in the editor to download and load the URDF models at runtime. Hope this helps

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants