Germany
Asked — Edited

Digital Clone Rover Roli

maybe someone can use it....

can be used with the standard project of Roli, just create an EZ-Script and run it:

$go=true
repeatwhile($go) 
$strSend = "D9@" + GetServo(d9) + ";D10@" + GetServo(d10) 
$strSend = $strSend + ";D19@" + GetServo(d19) + ";D18@" + GetServo(d18) + ";D17@" + GetServo(d17) + ";D16@" + GetServo(d16)
$strSend = $strSend + ";D15@" + GetServo(d15) + ";D14@" + GetServo(d14) + ";D13@" + GetServo(d13) + ";D12@" + GetServo(d12)
SendUDP("127.0.0.1", 11000, $strSend)
Sleep(100)
endrepeatwhile

Here is the program for download: digitalCloneRoverRoli.zip and here the Unity project data to tinker around with yourself: Unity.zip

Have fun ...

24.07.22 Update in Post #17 -  Version with moving Rover ....

.


ARC Pro

Upgrade to ARC Pro

Unlock the true power of automation and robotics by becoming a proud subscriber of Synthiam ARC Pro.

PRO
Synthiam
#1  

You are doing so well with Unity! I'm incredibly impressed. I always thought it would be neat to have a virtual robot app like that where you could program a robot without actually owning the robot. And you did it! Imagine how awesome it would be if someone could design their robot with the ez-bit parts! Have you thought of making something like that? I'd sell it for you!

PRO
Germany
#2  

thanks, I really appreciate it. Exactly this is the point, i made it exclusively with the stl fils from here, nothing is made by myself. I'm also a complete novice with unity but it's so easy. I've been thinking about doing a tutorial, are you interested? In short, assemble the stl files in tinkercad and export them as obj, import them into unity .... Whereby my c# and also e.g. the string in EZ-Script with UDP are definitely not what they should be, I am aware of this but it works :-)

PRO
Synthiam
#3  

A tutorial would be neat! I think it would be really useful for schools that can’t afford robot hardware. They could program a robot without the high cost.

i guess you could also put the robot in a 3D world and have it move too? That’s so neat!

PRO
Germany
#4   — Edited

hmm, I have to think about how to get that visualized, e.g. what if the robot reaches the limits of the world etc... I'm trying to create a tutorial, as a start, based on what I've done so far. this would be my first ever created tutorial :-)

Edit1: quick search has shown, should also be easily possible, keyword "infinite world" https://www.youtube.com/watch?v=f9uueg_AUZs https://www.youtube.com/watch?v=cUAprBYS_0Q

Edit2: hmm, another idea that just occurred to me, how about a free asset in unity with all ez-bit parts.... .

PRO
Synthiam
#5  

Oh a free asset with ezbits is brilliant. And then some code attached which allows moving the parts like you did.

I can write a class that acts as an ezb. So you actually connect ARC to it as an ezb! Wow that would be so cool.

I think by making the objects rigid that the works could have walls. Or a room. Or what ever the world is. Because there’s a number of free 3D world assets that can be downloaded from the unity store

PRO
Germany
#6   — Edited

Exactly, this should all be possible with relatively little effort.

I still have a problem that I haven't been able to solve so far, so you can certainly contribute a solution with your knowledge.

The "servo models" in Unity are at 90 degrees but the axes in Unity are of course at different degree positions, also in Unity you sometimes have negative values. I need a function that transforms the servo positions from ARC into the Unity world, here is the code from Unity, I calculated it with a try, but there should be a function for it:

if (servo[0] == "D19")
   AxisRightShoulder_Y_D19.transform.localEulerAngles = new Vector3(0, (neuPos - 180), 0);

if (servo[0] == "D18")
    AxisRightElbow_Y_D18.transform.localEulerAngles = new Vector3(-180, (neuPos - 180), 0);

if (servo[0] == "D17")
   AxisRightWrist_Y_D17.transform.localEulerAngles = new Vector3(-180, (neuPos * -1), 0);

if (servo[0] == "D16")
   AxisRightGripper_right_Claw_X_D16.transform.localEulerAngles = new Vector3(((neuPos * -1) * -1), 0, -90);
    AxisRightGripper_left_Claw_X_D16.transform.localEulerAngles = new Vector3((neuPos * -1) - 180, 0, -90);

This Parts:

neuPos - 180 or neuPos * -1 or neuPos * -1 or (neuPos * -1) * -1 or (neuPos * -1) - 180 etc.

right Elbow in Unity User-inserted image

right Shoulder in Unity User-inserted image

Do you understand what I mean ?

The UDP part would also have to be rewritten or replaced in Unity, I found something on the Internet and used it, but this is definitely too much of what we actually need, but you already have everything ready anyway Server/Client Code,

I uploaded the two unity scripts: Scripts.zip

.

PRO
Synthiam
#7  

A mapping function is useful for that.


    public static float Map(float value, float inputMin, float inputMax, float outputMin, float outputMax) {

      value = System.Math.Min(value, inputMax);
      value = System.Math.Max(value, inputMin);

      return (value - inputMin) / (inputMax - inputMin) * (outputMax - outputMin) + outputMin;
    }

You can therefore do something like...


var unityPos = Map(70, 1, 180, -1, 1);

That will map the value 70 (within the range of 1-180) to a relative value within the range of -1 to +1

PRO
Germany
#8   — Edited

perfect, exactly what I mean. I didn't know what to look for (keyword). Works great, one step further...


    void Update()
    {
        foreach (var message in connection.getMessages())
        {
           servoSet = message.Split(';');

            for (int i = 0; i < servoSet.Length; i++)
            {
                servo = servoSet[i].Split('@');
                neuPos = float.Parse(servo[1]);

                if (servo[0] == "D9")
                    AxisNeckVertical_Y_D9.transform.localEulerAngles = new Vector3(-180, Map(neuPos, 1, 180, 0, -180), 0);
                
                if (servo[0] == "D10")
                    AxisNeckHorizontal_Y_D10.transform.localEulerAngles = new Vector3(0, Map(neuPos, 1, 180, -90, 90), 0);
                

                if (servo[0] == "D19")
                    AxisRightShoulder_Y_D19.transform.localEulerAngles = new Vector3(0, Map(neuPos, 1, 180, -180, 0), 0);
                        
                if (servo[0] == "D18")
                    AxisRightElbow_Y_D18.transform.localEulerAngles = new Vector3(-180, Map(neuPos, 1, 180, -180, 0), 0);
                
                if (servo[0] == "D17")
                    AxisRightWrist_Y_D17.transform.localEulerAngles = new Vector3(-180, Map(neuPos, 1, 180, 0, -180), 0);
                
                if (servo[0] == "D16")
                    AxisRightGripper_right_Claw_X_D16.transform.localEulerAngles = new Vector3(Map(neuPos, 1, 180, 0, 180), 0, -90);
                    AxisRightGripper_left_Claw_X_D16.transform.localEulerAngles = new Vector3(Map(neuPos, 1, 180, 180, 0), 0, -90);
                
                
                if (servo[0] == "D15")
                    AxisLeftShoulder_Y_D15.transform.localEulerAngles = new Vector3(0, Map(neuPos, 1, 180, 0, 180), 0);
                
                if (servo[0] == "D14")
                    AxisLeftElbow_Y_D14.transform.localEulerAngles = new Vector3(-180, Map(neuPos, 1, 180, -180, 0), 0);
                
                if (servo[0] == "D13")
                    AxisLeftWrist_Y_D13.transform.localEulerAngles = new Vector3(-180, Map(neuPos, 1, 180, 0, -180), 0);
                
                if (servo[0] == "D12")
                    AxisLeftGripper_right_Claw_X_D12.transform.localEulerAngles = new Vector3(Map(neuPos, 1, 180, 0, 180), 0, -90);
                    AxisLeftGripper_left_Claw_X_D12.transform.localEulerAngles = new Vector3(Map(neuPos, 1, 180, 180, 0), 0, -90);
            }
        }
    }

    public static float Map(float value, float inputMin, float inputMax, float outputMin, float outputMax)
    {
        value = System.Math.Min(value, inputMax);
        value = System.Math.Max(value, inputMin);

        return (value - inputMin) / (inputMax - inputMin) * (outputMax - outputMin) + outputMin;
    }

.

PRO
Germany
#9  

how do I get the values from the HBridge? Is there something in EZ-Script, I only found GetPWM (digitalPort), how can I determine whether and in which direction the rover is driving ....

PRO
Synthiam
#10   — Edited

There’s a global variable for the current direction I believe. It doesn’t matter what type of Movement Panel is used (ie hbridge). The Movement Panel controls the movement service, which has speed and movement values.

PRO
Germany
#11  

ahh, very good, I can start with that. Sorry if I ask so much but I still lack a lot of knowledge about ARC ....

PRO
Synthiam
#12  

I don’t mind. It’s worthwhile when people ask questions and I get to see the results

PRO
Germany
#14   — Edited

is there a possibility to use the HBridge WITHOUT a connection to the EZB? It should change the $direction value in offline mode...

Edit Variable is set but there is always an error message ....

Version: 2022.06.19.00

System.Exception: Capability 'Read/Write Digital I/O Ports' is not supported on this EZB device.
   bei EZ_B.Firmware.FirmwareCls.CapabilityRequired(CapabilityCls cap)
   bei EZ_B.Digital.vrRX0N06Fl06JYjCF4W(Object , Object )
   bei EZ_B.Digital.SetDigitalPort(DigitalItem[] items)
   bei ARC.UCForms.FormHBridgePWMMovementPanel.MbDGdOsUXjKr4vAPJpUI(Object , Object )
   bei ARC.UCForms.FormHBridgePWMMovementPanel.z74iEXqo4bp(MovementDirectionEnum  , Byte  , Byte  )
   bei ARC.MovementManager.DL0Xif6reitYHi2tNXFf(Object , MovementDirectionEnum direction, Byte speedLeft, Byte speedRight)
   bei ARC.MovementManager.GoForward(Byte speedLeft, Byte speedRight)
   bei ARC.MovementManager.GoForward()
   bei ARC.UCForms.FormHBridgePWMMovementPanel.Oby20ssUTN1FImrlcEEP(Object )
   bei ARC.UCForms.FormHBridgePWMMovementPanel.forward(Object sender, EventArgs e)
   bei System.Windows.Forms.Control.OnClick(EventArgs e)
   bei System.Windows.Forms.Button.OnClick(EventArgs e)
   bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   bei System.Windows.Forms.Control.WndProc(Message& m)
   bei System.Windows.Forms.ButtonBase.WndProc(Message& m)
   bei System.Windows.Forms.Button.WndProc(Message& m)
   bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

.

PRO
Synthiam
#15  

Just remove the hbridge Movement Panel robot skill. It isn’t needed if you’re not using digital ports. All you’re doing is moving the direction. A Movement Panel is only for connecting movements to hardware.

PRO
Germany
#16  

I need something to move the robot in ARC - don't I? It works with the servo Movement Panel, there is no error if the ECB is not connected....

PRO
Germany
#17  

here is a version with moving Rover:

EZ-Script:

$go=true
$speed=10 
repeatwhile($go) 
$strSend = "D9@" + GetServo(d9) + ";D10@" + GetServo(d10) 
$strSend = $strSend + ";D19@" + GetServo(d19) + ";D18@" + GetServo(d18) + ";D17@" + GetServo(d17) + ";D16@" + GetServo(d16)
$strSend = $strSend + ";D15@" + GetServo(d15) + ";D14@" + GetServo(d14) + ";D13@" + GetServo(d13) + ";D12@" + GetServo(d12)
$strSend = $strSend + ";move@" + $Direction + ":" + $speed
SendUDP("127.0.0.1", 11000, $strSend)
Sleep(100)
endrepeatwhile

Download: digitalCloneRoverRoliMove.zip  .

PRO
Synthiam
#18   — Edited

That’s so awesome! I’m going to have fun with this :)

If you want to remove the hbridge skill, you can still control the robot by using this: https://synthiam.com/Support/Skills/Navigation/Movement-Joystick?id=19388

im seriously impressed at how fast you got that working. Your programming skills are ninja!

A neat thing about using the movement joystick above, is that you can use the speed and direction. So the movement can be smooth with speed. The speed of left and right wheels are available