Canada
Asked — Edited
Resolved Resolved by Rich!

Trying To Do A Video Recording

Not having any luck with this script! The head isn't turning as it should. The Camera Control indicates that it is recording, however, I can't find the recording where it says it should be. Any help appreciated. Thanks


#start head in this position
servo(D1,110)
servospeed(D1,0)
sleep(500)
#start video recording
ControlCommand("Camera", CameraRecordStart)

sleep(50)
#head should move to the left in increments of 10 degrees
ServoUP(D1,10)
servospeed(D1,2)
sleep(5000)
$x=Getservo(D1)
sleep(500)
#when the head gets to 150 degrees it should move to the right
if($x > 150)
servoDown(D1,10)
servospeed(D1,2)
sleep(5000)
#when the head gets to 50 degrees it should go back to starting position
elseif($x < 50)
servo(D1,110)
endif
#stop video recording
ControlCommand("Camera", CameraRecordStop)
Stop()


ARC Pro

Upgrade to ARC Pro

Join the ARC Pro community and gain access to a wealth of resources and support, ensuring your robot's success.

#2  

Ok, thanks. That explains that problem. Any idea why the servo down and servo up isn't working?

United Kingdom
#3  

Your script doesn't have any loops around the IF which checks the position of the servo, it moves the servo UP 10 degrees and checks for it's position but doesn't move the servo again unless it's at > 150 or < 50.

Since it starts at 110 and moves up by 10, so to 120, it doesn't match either > 150 or < 50 so will only move to 110 then up by 10 degrees before the script stops.

Add a repeat or loop in around where it's checking and moving the servo up/down by increments.

#4  

Thanks Rich. That made sense. I've got it working now, here's what I came up with;


#start head in this position
servo(D1,110)
servospeed(D1,0)
sleep(500)
#start video recording
ControlCommand(&quot;Camera&quot;, CameraRecordStart)
:start
sleep(50)
#head moves to the left in increments of 10 degrees
ServoUP(D1,10)
servospeed(D1,2)
sleep(500)
$x=Getservo(D1)
#sleep(50)
#when the head gets to 150 degrees it moves to the right
if($x &gt; 150)
Goto(step2)
else
Goto(start)
:step2
endif
servoDown(D1,10)
servospeed(D1,2)
$x=Getservo(D1)
sleep(500)
#when the head gets to 50 degrees it goes back to starting position
if($x &lt; 70)
servo(D1,110)
else
Goto(step2)
endif
#stop video recording
ControlCommand(&quot;Camera&quot;, CameraRecordStop)

Hopefully, the video recording bug will be fixed soon. (hint, hint, wink, wink, DJ ) I'm planning to use this as part of a security system for my house. For now I'll have it take snapshots.

United Kingdom
#5  

If it works that's great, however in the interests of giving more information for a wider audience and covering the many methods, I would have written it like this;


#start head in this position
servo(D1,110)
servospeed(D1,0)
sleep(500)

#start video recording
ControlCommand(&quot;Camera&quot;, CameraRecordStart)
sleep(50)

$x=Getservo(D1)
RepeatUntil($x = 150)
  #head moves to the left in increments of 10 degrees
  ServoUP(D1,10)
  servospeed(D1,2)
  $x=Getservo(D1)
  sleep(500)
EndRepeatUntil

#when the head gets to 150 degrees it moves to the right
RepeatUntil($x = 50)
  servoDown(D1,10)
  servospeed(D1,2)
  $x=Getservo(D1)
  sleep(500)
EndRepeatUntil

#when the head gets to 50 degrees it goes back to starting position
servo(D1,110)

#stop video recording
ControlCommand(&quot;Camera&quot;, CameraRecordStop)

Neither way is wrong nor is either better, just a different solution to the same problem:)

Note: My code wasn't written in ARC and is unchecked therefore there may be some slight syntax errors.

#6  

That's a cool thing about ARC - there are different ways to write a script to achieve the same thing. Here's another way using Auto Positions and Control Commands;


ControlCommand(&quot;Auto Position&quot;, AutoPositionFrameJump, &quot;Rest&quot;)
sleep(500)
ControlCommand(&quot;Camera&quot;, CameraSnapshot)
sleep(500)
ControlCommand(&quot;Auto Position&quot;, AutoPositionFrame, &quot;Head Right&quot;,25,3,4)
sleep(3000)
ControlCommand(&quot;Camera&quot;, CameraSnapshot)
sleep(500)
ControlCommand(&quot;Auto Position&quot;, AutoPositionFrame, &quot;Head Left&quot;, 25,3,4)
sleep(3000)
ControlCommand(&quot;Camera&quot;, CameraSnapshot)
sleep(500)
ControlCommand(&quot;Auto Position&quot;, AutoPositionFrame, &quot;Rest&quot;, 25,3,4)

When the video recording is up and running I'll replace the "Camera Snapshot" with the "Camera Record" CC.

#7  

I was looking at the code used in scripts, and not just this one. All the ones I have seen tend to do things the same way. But this code brings up one of the things I have seen often. That is, using sleep delays as the way of giving the servo time to do it's movement. This just seems too imprecise to me. Maybe I'm just being picky (I am a long time programmer (Modula2, ADA, Delphi) and tend to see things in a highly structured and precise way. Anyhow, I'm referring to this section:


$x=Getservo(D1)
RepeatUntil($x = 150)
      #head moves to the left in increments of 10 degrees
   ServoUP(D1,10)
   servospeed(D1,2)
   $x=Getservo(D1)
   sleep(500)
EndRepeatUntil

As I see it, the statement sleep(500) is there to give the servo time to move to the new position and keep the system from checking the servo position hundreds (thousands?) of times needlessly. Thing is, how long it takes to get there is entirely predicated on the ServoSpeed set. Unless calculated, the sleep time would be a guess or fudge factor at best. Also the servo is going to be commanded to move another 10 degrees from it's current position regardless of whether the servo has made it to the last place it was commanded to go at that moment.

Instead, I was wondering if it might be better to do something like this:


$CurrPos =Getservo(D1)
$PrevPos =$CurrPos
RepeatUntil($CurrPos &gt;=150)
      #head moves to the left in increments of 10 degrees
    ServoUP(D1,10)
    ServoSpeed(D1,2)
       #Now, wait for the head get into position
    RepeatUntil($CurrPos &gt;=$PrevPos+10)
        $CurrPos =Getservo(D1)
        Sleep(100)
    EndRepeatUntil
    $PrevPos=Getservo(D1)
EndRepeatUntil

Darn code brackets! Takes out all my lovely formatting.

Here the sleep statement is there only to prevent needless checking of the servo position. In this case limiting it to 10 times a second. There is also the issue of getting out of the loop in case of failure, as well as, favoring RepeatWhile over RepeatUntil but those are other topics. No sense in clouding the issue with that here.

Please let me know of any flaws in my thinking, thanks.

BTW, To whom it may concern ... there is a mistake in the Script manual concerning the RepeatWhile statement definition. The example shows a RepeatUntil statement instead of RepeatWhile. Also both commands show EndRepeat in both instead of EndRepeatUntil and EndRepeatWhile. EndRepeat may be valid for either, but the definition says to use EndRepeatUntil or EndRepeatWhile. Consistency may be the hobgoblin of little minds, but in programming it's a virtue.:) (yeah I know, the quote is Foolish Consistency, just go with me here)

United Kingdom
#8  

On my phone so going to be brief and only touch on one thing. The sleep is not for waiting for the servo but to help reduce the demand on resources.

Also, the servo position is not read from the servo but from the software. Repeating until a variable or command which reads the servo position meets the specified position is redundant since, as far as ARC (and any other software) is concerned, it's already at that position the instance you send the Servo() command.

PRO
Synthiam
#9  

Wbs, those old languages with a single threaded approach is what makes relearning coding today difficult. The approach you wrote is incredibly inefficient and very expensive on processor and network resources.

First, you only need to assign a servo speed once, not looping.

Second, the threaded approach is to set the speed and servo position once and let the processing be offloaded onto the ezb and servo. Releasing cpu cycles for other threaded tasks.

The Auto Position is a good tool to begin using. Specifically for poses.

For the last 10-15 years, cpu processing has been approaching speed limitations. The approach of using multiple cores has become what the operating system and newer programming languages rely on. At the heart of the kernel (in any current OS) is a layer which distributes instructions across multiple cores and creates a threading interface for the OS and programs. There are a few different approaches during programming for using threads which evolve with compilers and libraries.

ARC and other robot software/libraries (such as ROS) use a an approach which run processes separately as jobs. Each "job" in ARC is a control. They run parallel and communicate using ControlCommands().

While you can surely hack EZ-Script (or any current language) to write old school code, it's not going to always work as expected once you start adding additional processes (controls).

For example, the correct approach for you script to simply move a servo to a pose would be to create Auto Position poses and execute them with the ControlCommand(), accessible from the Cheat Sheet (see the LEARN section and the ACTIVITIES course) for information on how it works.

If you were to do something like this...


ServoSpeed(d2, 4)
Servo(d2, 120)

Soon as you execute the Servo() command, it is non-blocking (as all commands in EZ-Script are non-blocking unless stated with the word WAIT). This means the Servo() command will instruct the EZ-B to begin moving the servo to position 120. The servo is a WRITE only device, meaning it doesn't report back the position of itself. It only moves when told - so there is no way to know it has moved unless you use the Auto Position. The Auto Position is a very very easy control with very very very very complicated code in the backend. It will report when an action has been completed executing, which you can monitor by using the following command after initiating a ControlCommand() on an Auto Position Action.


WaitUntil( $AutoPositionStatus = 0)

For more information on the dozens and dozens of example projects demonstrating EZ-Script, check the EXAMPLES in ARC. There is an entire lesson in the LEARN section located under ACTIVITIES regarding the Examples in ARC.

#10  

@WBS00001 You PC programmers think differently than us (me specifically) robot programmers... I learned "robot" style programming first (if you can call robot programming a type of programming that is) 20 years ago messing with the Basic Stamp/Basic Atom microcontrollers. Those old school micros had very slow processors, limited code space and were not capable of multi threading.... Your code had to be small, super efficient and compact. You had to do things like read your pings or IR sensors in between motor pulsing ... Anyway, I later learned some PC programming.... What I am trying to say is I think there is a different approach when programming for robotics....

Yeah, to state what has already been mentioned... the

Getservo()

command is only a value established by the software or in other words the last position that ARC told the servo to got to.... whether the servo made it to that position is a different story.... As mentioned, the basic hobby servo is a "dumb" device which unless you hack it to read the internal pot there is no way for it to report back to ARC it's actual position....

@Bob, sorry for getting side tracked here....:)

#11  

Thank you both for responding.

@Rich Okay, so if it's redundant, why was it done every iteration in the original code loop? I mean, isn't that the same thing; checking a value using GetServo every half second? Repeating that loop until $X gets to 157? Or am I missing something here?

@DJ Sures Yes, the really "old" languages used a single thread approach (Modula 2, early Basic, early C) but the more modern ones I mentioned (Delphi, ADA) did not just use a single threaded approach. They were multi-threaded from the get-go. As were the programs I wrote with them. Multi-core is one of the latest darlings of the industry, along with Object Oriented design, Composites, Patterns, and distributed processing. All of those things have been incorporated into them for some time now.

Thing is, the Script manual makes no reference to it's true nature and gives the impression of being single threaded. Especially considering it's linear nature of code construction. The system is mulit-threaded, multi-core in nature, fine. That would be something nice to be included in the Script manual right up front. It's the sort of information someone like me needs as opposed to going through dozens and dozens of examples. Though I have to wonder if that information is in any of them either. That bit of knowledge would have put an entirely different light on my thinking about the code.

And, I have looked at several of the examples and the Script course but nowhere was any of this mentioned. No introduction. No "Advanced Concepts," nothing of that sort. How is one supposed to know this? The closest I came to a hint about it was in the Personality Generator section with the single line " This control can run in the background while your robot operates. " And that was specific to the example.

Finally, please keep in mind this is not "my" script. I merely addressed one aspect of what was happening and copied the rest as is. For instance, setting the servo speed on every iteration of the loop is not part of what I was pointing out. I merely copied the given section of code for that part. I had no idea why that was done in the original code so I just copied that part as it was. For all I knew, that was necessary to do on every iteration.

#12  

@WBS00001 Dude LOL.... If I had a nickel for every "I am an experience PC programmer since forever" guy to come on here and have issue with the way things are done with ARC and the ezb, I would be... well you know the saying....:) You're not the first let's just say, but eventually they all come around. Most of them, anyway..... Anyway, stick around (by the way I am not criticising you at all) you'll see that you might be over thinking things a bit.... Remember, we're programming robots not PCs....:D

#13  

@Richard R Thanks for your comments. I understand what you're saying about the different philosophies when it comes to different programming environments. But, to me, programming is programming with a certain set of best practices associated with it regardless of implementation and point of view. This environment, for example, is simply a multi-threaded, multi-core approach. While it's called blocking and non-blocking here, it's still just multi-processing/multi-tasking vs single tasking. The same practices can be applied to both. The main difference here is that the robot's processing is transitory in large measure. Move this servo to here, rotate that one to there, get an A-D value, etc. No big time on-going processing for the most part. The scripting language is great in that it hides the dirty details and grunt work and I intend to use it in my own development environment.

Just saw your new post. I don't have a problem with the way things are done here. In fact, if there had been an explanation of how the the scripting language actually performed it's tasks, I would have never presented the example I did and all this would have never have been posted. But there wasn't. I have no intention of trying to change anything, nor will I ever post anything on the subject again. I'll just keep my opinions to myself and stroll merrily on my way doing my own thing.

United Kingdom
#14  

Quote:

@Rich Okay, so if it's redundant, why was it done every iteration in the original code loop? I mean, isn't that the same thing; checking a value using GetServo every half second? Repeating that loop until $X gets to 157? Or am I missing something here?

I could have sworn your code used the Servo() command not ServoUp(). With the Servo() command it's redundant.

ServoUp() or ServoDown() in a loop to move servos in increments until a position does not make repeating until it's at position redundant and the position is changing and can be tracked in the software.

This is an example of redundant code, which I thought I was commenting on (possibly in my haste as I was on my phone at the time).


Servo(D1, 0)
Sleep(1000)
Print(&quot;Moving servo&quot;)
Servo(D1, 180)
$x = GetServo(D1)
RepeatUntil($x = 180)
$x = GetServo(D1)
Sleep(10)
EndRepeatUntil
Print(&quot;Servo in position&quot;)

Basically, the code (which is pointless) would presume the servo position is read from the servo and polled every 10ms until it reaches position 180 and then reports that it's in position. The reality is the repeat part of the code wouldn't repeat since the software, as soon as you send the Servo(D1, 180) command, would think the servo is at position 180 even if servo speed was so slow it took 10 seconds to get there.

#15  

@WBS00001 You got it all wrong, we don't want you to keep your opinions to yourself.... Nobody learns anything that way.... What I was trying to say was... "it is better to sand with the grain not against it".... You have to keep an open mind to different ways here (me included) because as I mentioned programming robotics is different than PC software development....

I had to change the way I thought about programming when I first came here too... I was programming old style micros ... ez robot had a weird new multi tasking controller that I had trouble understanding the why's and how's at first.... Once I got that "eureka" moment the Basic Atom microcontroller I was using for the past few years quickly got tossed.... Now almost 2 years on I am still in the ez robot "honeymoon" phase....:)

#16  

@Rich Ah, I see what you're saying. Yes, a simple servo command would be redundant and pointless as opposed to ServoUp. Okay, that clears that up, thanks.

The GetServo command is inadequately explained in the Script manual it would seem. The description leads one to believe it gets the current mechanical position of the servo in that it says "Returns the servo Position value of the specified port." I gather it actually returns the value of where it's supposed to be as opposed to where it actually is. The manual also says "Servo position is between 0 and 100". To me that says it returns a value in the range of 0 to 100 (percentage?) and not 0 to 180. Which makes me wonder how it ever gets to the value of 150 as presented in the example? Is that a mistake in the manual or am I not reading it right?

#17  

Quote:

"Servo position is between 0 and 100". To me that says it returns a value in the range of 0 to 100 (percentage?) and not 0 to 180. Which makes me wonder how it ever gets to the value of 150 as presented in the example? Is that a mistake in the manual or am I not reading it right?

Needs to be updated. The EZ-B v3 supported 100 servo positions. The V4 supports 180 to make it closer to degrees (although some servos have more than 180 degrees of rotation, so you may still need to interpolate desired degrees to a servo position command).

I no longer have a V3, this change could have just been in ARC and not a difference in the hardware......

Alan

#18  

@thetechguru Thanks for the quick clarification. Probably a lot of that in there. I guess I'll just have to try each command and see what it actually does.

#19  

Quote:

Thanks for the quick clarification. Probably a lot of that in there. I guess I'll just have to try each command and see what it actually does.

Yeah, or ask and someone will jump in with clarification. DJ codes a lot faster than he writes, so there are several area the documentation has fallen behind. Now that you are a member of the community, a good thing to do is read the release note posts whenever an update cones out. DJ is pretty good at listing what is new/changed.

Alan

Canada
#20  

Guys, tanks for this discussion I was puzzled about"GetServo" command, now it's clear.

PRO
Synthiam
#21  
  1. all code, whether threaded or not still executes in a linear fashion.

  2. the "process" explanation of controls are mentioned in the activity tutorial of the learn section. Please read the tutorials, as they will help you. The phrase "Behaviors" best describes the approach. Each control is a behavior for your robot - referenced in intro videos and tutorials:)

As for the struggles you are experiencing, it may be because you're over complicating things due to what you learned years ago. With tens of thousands of users, there are only a handful per month who experience the similar struggled as this - which is a very low ratio, even though i'm part of it. I also come from the single threaded blocking code approach. We respond to all inquiries to help educate users, such as yourself. However, we can only help those who are willing to be helped:). As stated earlier, don't look for similarities between 1990's Delphi and ADA with newer languages - that will hold you back in learning the current way computers work.

Very rarely does someone relate the old school single thread approach (warning: this does not mean linear, as I have mentioned is irrelevant attribute). The software that you are using right now is multi threaded. Every programming language in windows and Linux and OS X is multi threaded. Stating that ARC is multi threaded development is like putting an "electric starter" on a car advertisement. To anyone born in the last few decades, the term electric starter would mean remote-control starter, I suppose. But to anyone who remembers the day of having to manually crank their car engine will think differently. So the term multi-threaded is inherit to all programming languages today. The mere mention of such an attribute opens a whole new whack of questions and confusion to 99.9% of users who are so used to multi threaded apps, that the term isn't even in their vocabulary... because it's an everyday expectation of software.

Documentation is an interesting challenge when balancing between technical education and ease-of-use. While you're looking for a lengthy explanation about multi threaded approach, ironically using a multi threaded pc and quoting Delphi and ADA. It's a chicken and the egg perspective, with a twist... in today's age, there's a new challenge in knowing where the egg came from; the chicken or the carton!:)

The best part about this conversation is that it compliments what I'm working on. Now remember, ezrobot isn't a big company with a bunch of employees and such - there is 5 of us, so we depend on the friendship and cooperation of our community. In turn, we have the lowest priced product and free software. As well as being the CEO and office cleaner and inventor and visionary and tech support and web developer and video creator and tutorial editor and and and... Im also the only programmer - for all embedded firmware and windows software. So what I'm working on this week is a new tutorial section which puts you in charge! So you will be able to be super helpful to me and contribute what you've learned in the forum of tutorials on here, very shortly.

Everything that this conversation is teaching you - and every other bit of knowledge you've learned since EZ-Robot can be shared in our new upcoming tutorial section.:D

#22  

Single thread, Multi Thread? Is that the difference between being able to run two different apps on your smart phone rather then one? :P

PRO
Synthiam
#23  

Dave - no and yes. The simplest way to describe it is by saying that multiple routines of code can run parallel with each other - and be managed by parents with a family hierarchy - and exchange data through thread safe components and channels.

It all started back in the day of C++, which become popular for the concept of "Classes", which is compartmentalizing objects within objects in a family hierarchy. That opened a huge opportunity to make parallel processing easier because each "chunk" of data was identified as a class containing objects. Each object had a data type, which could be referenced, de-reference or casted to similar/compatible object types.

Now, with parallel processing/threading happening in C++, it was a huge challenge for programmers to manage threads. And by manage, this meant how to tell the progress of a thread process, tell the state of a thread process, or stop a thread process. Stopping was always tough because you want to stop a process gracefully. The original threading model was literally "Abort!", which would just stop where it was in the linear execution of instructions. This obviously wasn't the ideal approach, but programmers used very complicated ways to get around that. They would have "state" variables that were global and static which allowed the main threads to know the state of work done by child threads.

Oh, a real challenge was having background threads interacting with variables or objects owned by other threads - specifically GUI objects, such as buttons and text boxes. This was called cross-threading and caused programmers to pull their hair out. Hacks to objects were created by overriding a system level class that would tell the compiler to "INVOKE" the function on the thread of the parent object. Also there were variable declarations, such as VOLATILE which would inform the compiler that this variable was not to be trusted:) AKA used in multiple threads.

Complicated? Hell yeah! And i'm simplifying it - so it's even more complicated than that.

Anyway, eventually the threading concept became needed because cpu processing was reaching maximum potential. This created multi core processors so parallel processing could maintain the same MHZ processing speed but increase the number of instructions executed in parallel.

Java and .Net are the two languages known for making multi threaded apps popular. This is because they were developed today, not 20 years ago like other languages (specifically ones quoted such as Delphi which is pascal for win32). And i can go on about Win32 for a lengthy rant - but it's a whole new beast. The Win32 api was created in Windows 3.11 (windows for workgroups) and hasn't changed since. Only today, in 2015 is Microsoft taking the initiative with Windows 10 to introduce UWP, which deprecates Win32 API. That is why EZ-Robot's recent work with Microsoft on UWP UniversalBot is so important. See HERE and HERE

Now days, it's practically a challenge to find a programming language that does not include threading inherit in it's native design. What i mean by that is look at .Net for example. Most programs in old .Net were blocking because threading was still complicated. Blocking means, the code runs on the GUI thread. You can tell when a program is non-threaded (blocking) because when you press a button, the entire GUI locks up. Notice how the GUI doesn't lock up on ARC functions, other than loading some GUI windows - this is because ARC is threaded. Each control runs in it's own thread.

Now, with newer versions of .Net, specifically UWP, it's almost impossible to not write a threaded app. All methods that are called from a threaded method must return a TASK<> or be labelled as async. This can be really hard to understand for someone coming from a single threaded programming language.

Yes, Delphi and other languages had "threading ability" but it wasn't built into the native structure; or better yet, the structure of the language wasn't built around threading.

Now that you can see how complicated it would be to create a threaded App in even .Net - you understand the importance of ARC. Even if you were to create a C# robot app using the EZ-SDK, you will face huge challenges with threading - otherwise each time you press a button, the code will be executed on the main GUI thread and lock up the UI - preventing more than one thing happening at a time.

ARC users are lucky and kind of spoiled - because you don't need to worry about threading:D

#24  

@Dave.... I'll translate what @DJ just said.... multitasking is like having the ability to pee, eat and scratch at the same time..... Single tasking means you have to pee first, then scratch and then eat..... :P

#25  

Wow, all I wanted was a simple script to turn my robots head from side to side while taking a video. I got it working, except for the video recording. Anyway, what an interesting discussion this has turned into, I've learned a lot. Richard R I like your translation! So back on topic - DJ, how's that video recording fix coming along?

PRO
Synthiam
#26  

bob, ha - i have huge weights on my shoulders for that video recording from different people. We have a 300 page education curriculum that is depending on it being done in the next few weeks!

#27  

Lol, thanks for the lesson guys. Actually I was just kidding around as I do know kinda what this is. In need to be carefull of what i ask for. However I didn't know all this and am truly glad I asked. Thanks again.

#28  

@Dave.... I was just kidding Dave. I knew you knew the difference....:)

@Bob.... Sorry for the hijack Dude.... So yes, video recording would be nice. I thinking of having my inMoov give out candy for Halloween this year.... I want to be able to record the looks on the kid's faces when a 6 ft tall robot answers the door instead of a human....:P