Hi,

I've made a little script for move my animatronic head with a joystick ( see attachement ) . It work well but for move the eyes, i must press the joystick's arrows for each degree . How must i do for make they move until i release the button ? 

I've tried with " while " but mrl crashed, so i do something wrong but what surprise .

And another thing, i've just used the " joystick exemple " as a base, but i don't understand this :

msg_joystick_XAxisRaw.data[0]

In the javadoc,there is only " XAxisRaw", so why don't write " joystick.XAxisRaw.data[0]" ?

For information, my animatronick head is made in wood, based on one that i've seen on the web ..

 

here is a video few days ago, it doesn't worked very well lol , the mouth was a little blocked:...

http://www.youtube.com/watch?v=1L6O-kUGGnA

 

The next step will be : add webcam in the eyes and play with openCv laugh

 

beetlejuice

11 years 2 months ago

Oh, and, my joystick is on index 3 in the list . I've add the command "joystick.setController(3)" but it don't work . I must choose the joystick in the joystick tab ...

Where is the mistake please ?

GroG

11 years 2 months ago

That's Awesome BeetleJuice ! :D

Good question about the msg_joystick_XAxisRaw.data[0]

There are 2 reasons its like this.

1. Joystick data is event driven - not polled - so you create a function (in this case "input") to recieve data when it arrives from the joystick hardware.

2. The syntax is a little strange because the incoming data is from a different language - It is coming from Java and arriving in Python.  In order to get the data there, a structure is created which follows this naming convention.  msg_<sending service name> _ <sending method name>.data[0]  

 

Mech-Dickel

11 years 2 months ago

Hi beetlejuice! Nice project! It would be cool if you add in your controller routine the function for when you press some button it play some audio file (something like pre defined phrases), like "mouth talking", like this:

 

audiofile = Runtime.createAndStart("audiofile", "AudioFile")
joystick = Runtime.createAndStart("joystick","Joystick")
sleep(4)
 
def a():
    a = msg_joystick_button0.data[0]
    print a
    if (a == 1):
     print 'button pressed'
     audiofile.playFile("c:/mrlaudiofiles/youraudiofile.mp3")
    else:
     print 'button not pressed'
 
joystick.addListener("button0", python.name, "a")

Other thing.... I'm working on a project which I want to control a robot and his arms and I'm trying to do the same thing as you. I've tried with "while", which theoretically should work, but it crashes MRL (I think because for each press on button it makes too many "commands" of the same). Well, below is the code that I've tried... How are you trying?

 

joystick = Runtime.createAndStart("joystick","Joystick")
sleep(4)
 
def a():
    a = msg_joystick_button0.data[0]
    print a
    while (a == 1):
     print 'button pressed'
    else:
     print 'button not pressed'
 
joystick.addListener("button0", python.name, "a")
 

if you do this -> while (a == 1):
it's not "crashing" MRL - what is happening is your using the only thread in the program and tying it up in the while loop... since its busy there, it can not get "new" information from a=msg_joystick_button0.data[0]

It's an infinite loop.

You can start a new thread to do the while loop - this will allow the thread which gets info from the joystick to be free.

or it might be easier to check  a=msg_joystick_button0.data[0] inside the loop 

:)

GroG

11 years 2 months ago

To programmatically set the Joystick you use setController (its a 0 based array again) like this

joystick.setController(2)
 
Additionally you must start the polling of the device this way
 
joystick.startPolling()
You won't see the drop down in the gui service get updated - but all the buttons and controls will be active

beetlejuice

11 years 2 months ago

Thank you for all that, i'll try soon . Today, it' s "school start " ( i don't know if it's the right word,but i'm sure you understood lol )

So lot of things to do . After i'll have more time yes

beetlejuice

11 years 2 months ago

Still no working like i would no

I've tryed with " while ", but it block in an infinite loop . If i press one time left joystick arrow, the eyes go to the left end . And if i press right joystyck arrow, same thing to the right .

After that it block on the " protected angle " ( if angleMax is reach, angle=angle ... )

 

Here is what i did :

 

def x():
    global b
    x = msg_joystick_XAxisRaw.data[0]
    print x
 
    while (x > 0.5):
       x = msg_joystick_XAxisRaw.data[0]
       b += 1
       print b
       eyes_lr.moveTo(b)
 
     if (b > 129 ):
        b = 130
    
 
    while (x < -0.5):
       x = msg_joystick_XAxisRaw.data[0]
       b -= 1
       print b
       eyes_lr.moveTo(b)
 
     if (b < 61 ):
        b = 60
 
    return

Ya ..

so it seems that you and Mech-Dickel are trying to do similar things...  I think Al would find it helpful too..

I've thought about it a little bit and this is what I've come to..

We should not need to do this in Python (the looping part) ..  what we SHOULD do is send a signal to the servo to start moving - then send another signal to stop

Its more effecive this way because, the Python script is not telling each time to move the servo...  this wasteful communication - we want effecient communication... 

MRL can do this now EXCEPT FOR 1 MISSING PIECE ... that's the stop signal 

I propose we do it this way :

  1. Python sets speed of servo
  2. Python tells servo to begin moving
  3. Python tells servo to stop moving

This would use Servo.setSpeed() because you don't want the servo to move at full speed.  With speed control you can choose how fast / slow to move.

All would work, but I have to put in a stop :) 
After that I'll have a script which works for you.

beetlejuice

11 years 2 months ago

I've also thinked to a thing that could work for me : Use an analogic joystick and map it position on servos angles .

By exemple for a servo that move from 35° to 100° :

------------------------

x = msg_joystick_XAxisRaw.data[0]

if ( x > 0) :

  b = (100 - 35 ) * x + 35
  eyes_lr.moveTo(b)
 

elif ( x < -0 ) :

  b = (100 - 35 ) * x + 100
  eyes_lr.moveTo(b)
--------------------------
 
Of course before move the servo we need to convert b to an integer ...
How to do that in python ? b= int b ?
 
I'll try that !! 

beetlejuice

11 years 2 months ago

In reply to by GroG

That work ! but i've made a little error with my numbers . Easy to correct .

If all is ok, i'll make a video tomorrow cool

EDIT : it's ok, the numbers to add aren't servoMax and servoMin, but servoCenter .

Now i must do the same ting for up and down yes

Here is the good script for me :

def x():
    global b
    x = msg_joystick_XAxisRaw.data[0]
    print x
    if ( x > 0 ) :
     b = (130 - 60 ) * x + 90
     roundB = int(b)
     eyes_lr.moveTo(roundB)
    elif ( x < 0 ) :
     b = (130 - 60 ) * x + 90
     roundB = int(b)
     eyes_lr.moveTo(roundB)
    if (b > 129 ):
     b = 130
    if (b < 61 ):
     b = 60
    return

is the (130 - 60) * x +90 actually doing a range from 130 to 60 or is it just subtracting and getting 70 *x+90 every time?

I know there is a  range notation in Python but I forget what it is and I thought it was mostly used in control logic like loops and if statements.

70 *x+90 will work perfectly, i wrote all for better understanding .

60 is the the left end  and 130 the rignt end off the servo's liberty for move the eyes .

the " +90 " part is the centrer point in degree . Normally it must be 95°, but if i do that, the eyes look a little bit to the floor so i cheat a little lol !

For the " range " notation in python, it's just " range " !

By exemple

" range (10) " mean from 0 to 9

" range (10,100) " mean from 10 to 99

you can also do that :

>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
...     print i, a[i]