Asked — Edited
Resolved Resolved by WBS00001!

Camera Interference With Servo Movement?

Hey guys, I was trying to script some animation for my robot...trying to figure out how to make smooth animations which will run correctly timed and without getting jumpy servos!

I experienced that my script is running smooth if it is the only thing running, once I start the camera the movement gets really choppy/jumpy...is this because the camera takes too much bandwidth, is the communication to the board being flooded? It does not happen if I use the Laptops Webcam!

How do I workaround this?

Is my approach of scripting animation wrong? My idea was to animate 30FPS and point out the specific servo position for every frame, followed by a pause...

like this

ServoSpeed(D8,0) ServoSpeed(D6,0)

Servo(D8,39.417) Servo(D6,96.2251) Sleep(33.3333) Servo(D8,35.6368) Servo(D6,99.7181) Sleep(33.3333) Servo(D8,30.7226) Servo(D6,104.559) Sleep(33.3333) Servo(D8,25.8083) Servo(D6,109.944) Sleep(33.3333)

etc...


ARC Pro

Upgrade to ARC Pro

Stay at the forefront of robot programming innovation with ARC Pro, ensuring your robot is always equipped with the latest advancements.

PRO
Synthiam
#1  

The camera and servo communication are on separate tcp connections - it's unlikely that the wifi is the cause. Although you can investigate further by performing a wifi scan to see if there's a free wifi channel to switch to.

I would suspect the PC/cpu is causing the jerkiness by having many tasks/threads running. Specifically if any tracking methods are enabled.

Do you have a faster computer to try your program on?

#2  

Hey, thanks for suggesting to check the tasks...its always something to keep in mind I guess, and also good to know that the camera is on a different port!

The laptop is quiet fast... Intel i7

I set my router to an unpolluted Wifi channel

But actually the animation is being made in another application before, this application writes a textfile which I copy and paste into an EZ-Script...so there is no other application involved, only ARC!

It runs smooth, but when the camera is turned on it gets choppy/jumpy...I will check the tasks once more because there might be one thing on the PC side polluting the Wifi connectifity, I will keep you updated!

Thanks for helping to push this into the right direction!:)

PRO
Synthiam
#3  

:) anytime!

tasks sometimes are limited due to the application as well. This is something that can be controlled by the application - Windows manages priorities of tasks.

The accuracy of the sleep() command uses a thread sleep, which isn't real time due to windows not being a realtime OS. So there is a high probability that the thread.sleep running in the background might not be 33.3 ms but 50ms or even 100ms if the thread manager is being fussy.

What program are you using to create the animations? I wonder if a plugin would suit your needs to parse the data before rather than running as a script. I might be able to help you with that

#4  

This is actually something that I did not think of....so it could be the priority of tasks which messes with my animation timing hmmmm....

I have build a little Lego Robot to test out animation, I also build and rigged this robot in 3ds max...it is connected directly to the real world model with ARCs HTTP Server ( you helped me to connect 3ds max using max script some time ago).

So I can build an animation inside of 3ds max (which is free for three years if you want to study and personally use it by the way...), and playback the animation on my real world model to check for unwanted collisions or weird stuff that could cause damage to the servos!

Also while doing the playback 3ds max writes all the animation into a .txt file that I can copy and past into my EZ-Script to use the animation directly within ARC...

If the data can be pre-processed or parsed in any other way, I would be really interested in how this can be done!:)

#5  

I made a short clip on how far I got till now, next steps will be making a better model and working more on animation and timing!:)

#6  

@Mickey666Maus I was thinking about adding to this topic but I want to make sure I understand what is happening first.

It appears you have created an image of a robot in 3DS Max which you have "rigged" such that you can move various parts of it (probably with the mouse). Each movable part corresponds to a movable part of the actual robot and a servo which drives that part. When you move the part in 3DS, something is sent to ARC via the HTTP Server which causes the actual robot to move in the same way. In addition, 3DS generates a text file which is a record of the moves. The text file can be placed into a script by a copy and paste operation, allowing the robot to play back the movements.

Is this correct?

#7  

@WBS00001 That is correct, with this method I would like to create animations for my robot which can be played back in ARC, 3ds max offers a wide range of animation controls which is the reason I would like to use it for that specific purpose!

Also the next step will be to build the robot directly in 3ds max and use a printer to create the real world robot, contrary to what I was doing this time...which was building the robot first and making the digital counterpart second!:)

#9  

Excellent work and a fascinating project. I had something like that in the back of my mind for some time. The controlling part that is, not the designing and printing part. Anyway, here are my thoughts.

What you seem to be trying to do is similar to stop motion animation. That sort of animation requires an accurate frame rate to achieve fluid motion. As DJ mentioned, the timers in the script are software based and not real-time based, with interrupts and all that. You cannot rely on the sleep command to provide a steady, accurate frame rate or even an accurate timing from Sleep function call to Sleep function call. Especially at very short times.

One way to perhaps compensate for it's lack of accuracy in most cases could be to perform a running calculation such that the script can come up with a variable delay (sleep value) so as to try to maintain a given frame rate, despite changing conditions. The problem with this solution, however, is that there could still be some jerkiness as the new value is calculated and the algorithm might not not be very responsive to these changes.

It may be better to use a vector approach. That is to say, instead of many small movements, timed to a particular frame rate, go with a series of start and end positions. Most of them would be relative. For example, if a given servo starts at 10 degrees, then this becomes the start point. If the next movement is to go to 20 degrees then the next point to be recorded is "+10", and added to the previous position to cause the servo to go to the new position, and so on. The same for any other servo being moved at the same time. All these points go into one long string, along with appropriate characters to tell a reader script how to move the servos.

For example, something like this: "D0|10,D1|30,S+1000,D0+10,D1+15,S+1000,D0-10," ....

What this would be saying is, Set D0 to 10 degrees and D1 to 30 degrees initially. Then sleep for 1000ms. Then move D0 +10 degrees from where it is right now and move D1 +15 degrees from where it is now. Then Sleep for another 1000 ms, Then move D0 back 10 degrees (-10), and so on. In this case the Vertical Line character "|" (also called vertical-bar, vbar, vertical line or vertical slash) would be used to represent an absolute position. "+" and "-" would represent relative positions. Your 3DS program would create the string as you move the 3DS robot to its' various positions. Then, at some point, save it to a text file.

Basically a "Reader" script would take the information in the string and execute the commands described in it to move the robot where it is to go for that particular sequences of movements. Something like this:


ClearVariables()
$TheIndex =0
$TheDataStr ="D0|10,D1|30,S+1000,D0+10,D1+15,S+1000,D0-10,"
$TheData =Split($TheDataStr,",",$TheIndex ) #Get first group

RepeatUntil($TheData = "")
  $AbsPos =IndexOf($TheData, "|") #Check for any of these symbols
  $PlusPos =IndexOf($TheData, "+")
  $MinusPos =IndexOf($TheData, "-")
  $NextChar =1
  
  $TheChar =GetCharAt($TheData,0) #Get the command character
  If ($TheChar ="D") #It's a servo instruction
    If ($AbsPos >0) #This is an absolute position setting
      $TheData =$TheData+"|" #Add separator char for Split to work right.
      $TheServo =Split($TheData,"|",0) #Data on left (Servo Port)
      $TheValue =Split($TheData,"|",1) #Data on Right (Degrees to move)
      Servo($TheServo,$TheValue) #Move servo to this position
      
    ElseIf ($PlusPos > 0)  #This is a positive relative position setting
      $TheData =$TheData+"+"
      $TheServo =Split($TheData,"+",0)
      $TheValue =Split($TheData,"+",1)
      Servo($TheServo,GetServo($TheServo)+$TheValue) #Add to current position
    
    ElseIf ($MinusPos > 0)  #This is a negative relative position setting
      $TheData =$TheData+"-"
      $TheServo =Split($TheData,"-",0)
      $TheValue =Split($TheData,"-",1)
      Servo($TheServo,GetServo($TheServo)-$TheValue)
    EndIf
  ElseIf($TheChar ="S") #Process a Sleep command
    $TheData =$TheData+"+"
    $TheValue =Split($TheData,"+",1)
    Sleep($TheValue)    
  EndIf
  $TheIndex++
  $TheData =Split($TheDataStr,",",$TheIndex)
EndRepeatUntil

This sort of thing is easier to use since it requires no copy and paste to get it into the script. You can directly load the text file into a variable ($TheDataStr, above) from the disk using The FileReadLine or FileReadAll script instruction, then have the Reader code read it and move the servos accordingly. NOTE: The above code is just off the top of my head and may not be bug free as I haven't actually tested it.

Additionally, other commands can be added as needed such as one that will use the ServoSpeed instruction. Something like "R|D0|100" for example. Using the letter "R" to stand for "Rate", since "S" is already used for "Sleep". This would say... Set the servo speed of D0 to 100. It would be broken down like this:


  $TheData =$TheData+"|" #Add separator char for Split to work right.
  $TheServo =Split($TheData,"|",1) #Get servo Port
  $TheValue =Split($TheData,"|",2) #Amount to set it to.
  ServoSpeed($TheServo,$TheValue)

So, basically you have a comma separated variables string that is broken apart by the Split function with each group used to do something with the robot. This method also helps insure you don't flood the channel by sending many small increments.

Hope you find this helpful.

#11  

@WBS00001 Thank you so much for this awesome reply! And thanks for making the effort to put all that code together for me! I am really bad when it comes to coding, it takes me forever...:D

I was actually thinking to reduce the frames in my animation to lighten communication between ARC and my servos, but your approach makes a lot more sense! I guess this is kind of how the Auto Position in ARC works, right?

I do not have the time to check this right now, but I will try your approach asap!

The rigging in the 3D application is a bit complicated, to extract all the rotational values from an object is kind of tedious because of the rotation matrix they use...but once it is done it is also rewarding. You can playback and modify your animation in a nondestructive way to tighten your movements, and the timing controls are helping to make readable motion!;)

Also your way of sending the data thru a variable could help for directly controlling the robot live thru the 3D application, this always caused a lot of jerky movement...it could be used as a buffer I guess? Just tossing ideas around in my head already!

Thanks so much for your help guys! You are great!:D

#13  

Got my first 3D printed servo brackets today...still not perfect, but I hope to get my K[8] up an running soon!:)

User-inserted image

#14  

Glad you might find the method useful. I'll be happy to help with more coding as needed. Just let me know what you require.

A few points. I don't know about 3DS or what it takes to write something to create the control string from it. However, if it is easier to create all absolute positions rather than mixture of absolute and relative positions, that should be fine. Also, other characters can be used to separate the characters within a given group, such as a space. For instance, the group D0|100 could also be be D0 100, using a space as the separator. Even the groups currently using a plus or a minus character (Relative movements) could use a space: D0+100 could be done as D0 +100 with a space separator between the D0 and the +100. It's all a question of appropriate grouping. Come to think of it, a uniform separator would simplify the code in some ways. I'll have to ponder that a bit more. I had one more point to make but I've forgotten what it was at the moment. I'll post again when it comes to me.

Yes, you're right. It is something like how the Auto Position control works. Of course, the Auto Positioner directly controls the servos with a series of commands sent to the EZB-4 through the underlying C# code. In the case of this method, the comma separated groups are somewhat like parts of a Frame. I suppose the analogy could be carried further by using parenthesis to separate groups of groups and call each a complete Frame. Something like: (D0|10 D1|30 S+1000 D0+10 D1+15 S+1000 D0-10).(D0|10 D1|30 S+1000 D0+10 D1+15 S+1000 D0-10). etc. Each group in the Frame would be separated by a space (or whatever). While that might make it easier to read and manipulate after generation, it might make things more complicated than it's worth.

Anyway, just let me know what you would like to see changed in the code and I'll be glad to do it.

#15  

@WBS00001 It should be fairly easy to create any type of control string to be send out from 3ds max via HTTP or into a .txt document...

So I would create the absolute position of the servo once, which would be the starting position...and after I would jump to the next keyframe in 3dsmax and write this position as the next relative position right? Then jump to the next keyframe etc...

Right now I was sending the position of each servo every frame, which was a lot more data obviously.

But how would I calculate the sleep, meaning the delay which the script needs until the servo has reached its position? Right now I am using a 33ms on every frame...so I would need to check how many keys it took from one keyframe to the next and muliply this times 33? This would need some digging, but I guess I could find out how to do this in maxscript!

I could start to test your approach by having my keyframes set to fixed intervals, just to check how it works...:)

PRO
USA
#16  

I just found this thread. I've been hoping to get something like this to work except I use Lightwave not Max. I did manage a few years ago to get Maya to connect via Python to an ardurino to control servo's live or recorded. All the programs and sketches were written by an Australian author in 2009. He never explained how to make a set up with more than 4 servo's and dropped off the earth.

So I could use various means to control the servo via motion capture, or a virtual dial or joystick with the rotational values out putted to the servo. I've built a lot of animatronics over the years and pre recording playing back and tweeking the animations is the only thing missing in ARC to take it to the next level. But using an animation package is the way to go until/ if that happens. I'm extremely interested in what you guys come up with. I can't code so I have to depend on others. But I can contribute ideas :D

#17  

@fxrtst Any and all ideas welcome, thanks.

@Mickey666Maus

Quote:

It should be fairly easy to create any type of control string to be send out from 3ds max via HTTP or into a .txt document...
That's good to hear since it may take a few revisions in the software and what goes into the control string before it all works satisfactorily.

Quote:

So I would create the absolute position of the servo once, which would be the starting position...and after I would jump to the next keyframe in 3dsmax and write this position as the next relative position right? Then jump to the next keyframe etc...
Yes. However, you could make all the movements from keyframe to keyframe absolute if that is easier. It's up to you.

Quote:

But how would I calculate the sleep, meaning the delay which the script needs until the servo has reached its position? Right now I am using a 33ms on every frame...so I would need to check how many keys it took from one keyframe to the next and muliply this times 33? This would need some digging, but I guess I could find out how to do this in maxscript!
Yes, that seems right.

The need for knowing where a given servo is as it is moving from one position to another is one that cannot be fulfilled with the EZB servos. At least not without modifications. This is because there is no feedback available to tell where the servo is at any given moment in time as it is moving. Any sleep time you put in is, at best, a guess. You could calculate about what it may be, based on whatever servo Speed is currently programmed in. Additionally, the maximum rate at which the servo can move is also affected by whatever load is on it. That load can even change as it is moving. As mentioned before, the actual time a sleep timer takes to execute can vary a lot, especially at small times. I think, however, that the longer the sleep period, the more accurate will be the timing. A 250ms time will be more accurate than a 33ms time, and a 500ms time more accurate still.

Fundamentally, there is no easy way to pinpoint how long it will take for a given servo to move a given distance. Therefore the sleep period needed for it to do so has to be an estimate with a bit extra thrown in to be sure enough time is allotted to the action, even in varying conditions.

Some other ideas I had on this method would be to allow for things like running Frames or Actions from a Auto Position control via additional commands to the reader. For instance, to run an Action is basically done with a Command control. Such as: CommandControl("Auto Position", AutoPositionAction, "Bow") (From JD). To make this a command in the string could be done like this: "C|AP|Auto Position|AutoPositionAction|Bow" This Could be handled in EZ-Script something like this:


If ($TheChar ="C") #Command Control Statement
  $TheType = Split($TheData,"|",1) #The type of Command control=AP 
  If($TheType = AP) # (Auto Positioner)
    $TheName =Split($TheData,"|",2) #Auto Position control name=Auto Position.
    $TheCommand  =Split($TheData,"|",3) #Type of command=AutoPositionAction
    $TheMotion =Split($TheData,"|",4) #The Name=Bow
    If($TheCommand = "AutoPositionAction")  
      CC($TheName,AutoPositionAction,$TheMotion)
    ElseIf($TheCommand =  "AutoPositionFrame") 
      CC($TheName,AutoPositionFrame,$TheMotion)
                               |
                          And so on
    EndIf
  EndIf
EndIf  

Unfortunately the command in the Command Control for the Auto Position control can't be a string like the other arguments, so we have to spell out each possibility in an If-ElseIf list. The same method can be used to run scripts. Likewise to run Say and SayEZB commands. No doubt many other useful Script commands as well.

Finally, it occurred to me that the commands could be made board (connection) dependent as well by using the same notation as is normally used to select a specific board when specifying a servo instruction for example. This is done in the Script by prefixing the board number on the servo port. Such as: Servo(1.D0,100) to send that instruction to whatever is being accessed through Connection 1. I'll leave out that level of complexity for now though. As well as leave out the Command control additions for now.

Quote:

I could start to test your approach by having my keyframes set to fixed intervals, just to check how it works...
Sounds good to me.

#18  

@WBS00001 After a night of sleep and my morning coffee something else crossed my mind... 3ds max only knows the absolute position of the servos at any given keyframe, so I would need to calculate the relative positions according to the absolute position to run the script properly! This could also be done in 3ds max but I would surely have to grind my brains to get it coded right, so it would be of great help if this could be implemented in the code you gave me!:D:D:D

@fxrtst Giving readable motion to my robot is what I am aiming for...of course any other way to create or transfer motion is of interest to me! The most believable gestures are those ones resembling our own motion, those are the ones which will draw us emotionally closer to the animated object! Good timing and knowing how motion works is the key!

I also want to transfer Mocap data to my robot, either way directly wired or just animating it by hand and using the Mocap as a reference, lets see...

I came across a good TED Talk a while ago which describes what I am trying to achieve!:)

#20  

@WBS00001

Quote:

Yes. However, you could make all the movements from keyframe to keyframe absolute if that is easier. It's up to you.
This would be awesome...3ds max obviously only stores the absolute position in every frame, I guess there are other options but this could end up getting messy on my side! I am superslow at scripting!:D

And yes, this is what I hope for using your method...longer sleep periods to equal out variations which could cause erratic servo movements!:)

Anything that would let me run other scripts from within this movement script would be highly appreciated!

To address different boards would be a good aim for the future, e.g. for those that might have an InMoov or any other type of robot using a bunch of servos!;)

Thanks man, you are awesome, this is great help!:D

#21  

@Mickey666Maus

Quote:

After a night of sleep and my morning coffee something else crossed my mind... 3ds max only knows the absolute position of the servos at any given keyframe, so I would need to calculate the relative positions according to the absolute position to run the script properly!
That's not a problem. Just use the absolute position notation for every frame. That is to say, the notation which uses the Vertical Line Character. Such as: D0|10 or D1|35. Don't bother with the relative notation at all. That way every position change will be an absolute position automatically. No modification to the code will be necessary.

Using the previous example: D0|10, D1|30, S+1000, D0+10, D1+15, S+1000, D0-10. Would instead be: D0|10, D1|30, S+1000, D0|20, D1|45, S+1000, D0|10.

Either would make the servos move in the same pattern. Also, if you find it more convenient, the S+1000 (Sleep) notation could be S|1000 instead to make it more like the servo notation. That would be a very easy change. Just let me know.

Just read your latest post. You are quite welcome. I enjoy the challenge. Programming is my thing. If it becomes necessary I can also create Windows programs outside of ARC for specialty functions. So far I don't think that will be necessary, however. Especially since DJ has made changes to how the scripts are executed that has sped them up considerably. So, even though a given script may seem lengthy, it will still execute fast.

Feel free to ask questions any time. :)

#22  

@WBS00001 Thanks a lot, this should work like a charm!:D I was at work until now and will be traveling to Berlin tonight where I will stay for a little over than a week, but this got me really excited...so I figured as I will be taking my laptop anyways, I could also just take the EZ-B with me to do some testing!

I will let you know how it goes!:D

Actually it would be of great help if you could take a look at the terrible coding I did to connect 3ds max to ARC, there is still some stuff that I would want to change...since I had trouble putting my variables in a string and reading them back out, I had to manually spell them out one by one. Also I guess there is a lot of stuff that could be improved.

I could share my code here, or if this would be too off topic I could also send it to you directly?

Great help! Should I leave the red lantern hanging for a bit or just close this as resolved!;)

#23  

@Mickey666Maus Sure, no problem, I'll be happy to look at your code.

Probably the best thing to do is close this thread and start a new one with a name more descriptive of what you are doing now. In fact, I'll just do that now. I'll call it Robot Design and Control Using 3ds Max and ARC and I'll put in a link to this thread. You can close this one. Then you could start things off by putting your 3ds code in the next post in the new thread. Perhaps also a description of how it is supposed to work.

#24  

@WBS00001 Was on my way to Berlin Yesterday....good idea to re-open! I will close this one and see you over at the other thread!;)

Thanks again for all the support!:D