Hello all. If you havent kept up with my progress in the shoutbox, I am in the process of finishing a highly advanced head mod ( the "advanced inmoov head"). I have to control 28 servos using, for now, 2 16-channel servo drivers.
However, i need a service that will allow for the many servos ( there are at least 8 in the lips) in the head to be controlled simultaneously. I also need to be able to save the positions of servos in a way similar to the InmoovGestureCreator and have the ability to chain these "gestures" together to make complexed emotional movements on inmoov's face.
Along with this advanced control over multiple servos, I need a to be able to dynamically change the limits of a servo depending on the position of another servo. For example, my advanced inmoov eyes have mechanical limits due to the eyelids. When the eye is horizontally in one of the corners of the eye socket, it is unable to move much, if at all in the vertical direction without hitting the eyelids (just like a human eyeball). Thus, it is necessary to be able to change the limits of a servo (say the up and down servo for the eyes), depending on the position of another servo.
@Calamity, I heard from Kwatters that you've made great progress on an integrated movement service and he suggested I make this post so that all of us could discuss how to make this service a reality. A lot of us here on MRL, including myself, would appreciate any assistance you could offer.
In any case, lets get to work ! :)
A github ticket was made
A github ticket was made about a week ago for brainstorming this concept. Comments can either be post here or there.
https://github.com/MyRobotLab/myrobotlab/issues/228
Hi Alexinator I would gladly
Hi Alexinator
I would gladly assist anyone who want assistance, be with the integrated movement service or any thing that I have some knowledge.
To do what you want with your advanced head, you could use a structure similar to what I have done with integrated movement service (or I think it sould be fairly easy to add it the the integrated movement service.
So to be more specific with your case, you could have a service that define and keep track of the position and current limits of your 'eyes' servo and a thread that compute the position and limits of the servo based on what your service know. ie if servo A is in position x, set the limits of servo B to x/y then move it to be inside those limits.
I hope I'm somewhat clear the the strategy I describe. Personnaly, I like this because it could easily create behaviour instead of scripted gestures
Hey Calamity. I didnt
Hey Calamity. I didnt remember to ask this to you last night. Do you have source code for your integrated movement service you could provide us to look over? We want to see if we could use your code as a basis for a dynamic limits service, a servo orchestrator service, or both. We also would possibly like to generalize your code from just inmoov to any robot that uses mrl so many other users can improve their robots' movements.
the
the service https://github.com/MyRobotLab/myrobotlab/blob/develop/src/main/java/org…
all the other class relate to it
https://github.com/MyRobotLab/myrobotlab/tree/develop/src/main/java/org…
Hello, Because you mention in
Hello,
Because you mention in the shoutbox not having played with codes yet, here is a script you could use to run some tests on your 27 servo head. This is not relevant with integrated movement service, but there is servo syncing for the eyelids.
It also can be usefull before the refactor of the servoOrchestrator is fully working.
#########################################
# Servo test by Gael For Alexinator40.py
# more info @: http://myrobotlab.org/service/Servo
#########################################
# uncomment for virtual hardware
# virtual = True
eyeXPin = 22
eyeYPin = 24
eyeLidRightPin = 12
eyeLidLeftPin = 13
# port = "/dev/ttyUSB0"
port = "COM15"
# start optional virtual arduino service, used for test
if ('virtual' in globals() and virtual):
virtualArduino = Runtime.start("virtualArduino", "VirtualArduino")
virtualArduino.connect(port)
# create a servo controller and a servo
arduino = Runtime.start("arduino","Arduino")
eyeX = Runtime.start("eyeX","Servo")
eyeY = Runtime.start("eyeY","Servo")
eyeLidRight = Runtime.start("eyeLidRight","Servo")
eyeLidLeft = Runtime.start("eyeLidLeft","Servo")
# initialize arduino
# linux or macos -> arduino.connect("/dev/ttyUSB0")
print("connecting arduino to serial port")
arduino.connect(port)
# servo01.setMinMax(0, 180)
eyeX.map(0, 180, 0, 180)
eyeY.map(0, 180, 0, 180)
eyeLidRight.map(0, 180, 0, 180)
eyeLidLeft.map(0, 180, 0, 180)
# set rest position
eyeX.setRest(90)
eyeY.setRest(90)
eyeLidRight.setRest(90)
eyeLidLeft.setRest(90)
# attach servo
print("attaching servo with pins to controller")
eyeX.attach(arduino.getName(), eyeXPin)
eyeY.attach(arduino.getName(), eyeYPin)
eyeLidRight.attach(arduino.getName(), eyeLidRightPin)
eyeLidLeft.attach(arduino.getName(), eyeLidLeftPin)
# auto disable - this enables (starts pwm) before a movement
# and disables (stops pwm) after a movement
eyeX.setAutoDisable(True)
eyeX.disableDelayIfVelocity=1000 # grace period for autoDisable
eyeY.setAutoDisable(True)
eyeY.disableDelayIfVelocity=1000
eyeLidRight.setAutoDisable(True)
eyeLidRight.disableDelayIfVelocity=1000
eyeLidLeft.setAutoDisable(True)
eyeLidLeft.disableDelayIfVelocity=1000
# speed changes
print("speed changes")
eyeX.setVelocity(80) ## Low velocity
eyeY.setVelocity(80)
eyeLidRight.setVelocity(80)
eyeLidLeft.setVelocity(80)
eyeX.moveTo(0) # we cannot use moveToBlocking if servo velocity is set to -1 ( max ) !!
eyeY.moveTo(180)
sleep(2)
# sync eyeLidRight with eyeLidLeft
# now eyeLidRight will be a slave to eyeLidLeft
print("syncing eyeLidRight with eyeLidLeft")
eyeLidRight.sync(eyeLidLeft)
eyeLidLeft.moveTo(10)
sleep(0.5)
eyeLidLeft.moveTo(179)
sleep(0.5)
eyeLidLeft.moveTo(10)
sleep(0.5)
# moving to rest position
print("eyeLidLeft rest")
eyeLidLeft.rest()
sleep(2)
Hey Gael! Thanks for
Hey Gael! Thanks for commenting and providing this helpful script ! :) Although the advanced head actually has 4 eyelids that can be controlled, I am sure I can figure out how to edit the code you provided to test the eyelid and eye functionality! I hope you will like my mod when its released! By the way, my advanced head will support your new neck, though i might have to make a minor modification or two to the neck base (where the pistons attach to) so that I can fit all the servos in :)
Adafruit16
Tried to get this script working with the Adafruit16 servo controller, but with my python skill's (read none)
it throws me errors, and no line numbers :/
Could someone take a look at it:
error:
Script:
Hello Spawn32, You need to
Hello Spawn32,
You need to specify in your script that you want to use the Adafruit pins.
@Alexinator40, what is the skin going to be made with for your 27 servo head?
As a professionnal, I use silicone casting to create skin effects. Nowadays, silicone and latex foam are pretty much the only materials that can be used to create skin to be soft enough to give realistic human facial movements.
I have tested Ninjaflex or Filaflex a while back, but there is no way it can be used for face movements. (Maybe in the future)
I have seen a prototype 3D printer that could print silicone Soft Touch texture surface. The Soft Touch Effect can be found on many devices nowadays, phone, remote controller, car key holder...
I am truly wondering what is your plan.
:)
#########################################
# Servo test by Gael For Spawn32Adafruit16C.py
# more info @: http://myrobotlab.org/service/Servo
# more info @: http://myrobotlab.org/service/Adafruit16CServoDriver
#########################################
# uncomment for virtual hardware
# virtual = True
# eyeXPin = 22
# eyeYPin = 24
# eyeLidRightPin = 12
# eyeLidLeftPin = 13
# port = "/dev/ttyUSB0"
port = "COM15"
# start optional virtual arduino service, used for test
if ('virtual' in globals() and virtual):
virtualArduino = Runtime.start("virtualArduino", "VirtualArduino")
virtualArduino.connect(port)
adaFruit16c = Runtime.start("AdaFruit16C","Adafruit16CServoDriver")
# create a servo controller and a servo
arduino = Runtime.start("arduino","Arduino")
eyeX = Runtime.start("eyeX","Servo")
eyeY = Runtime.start("eyeY","Servo")
eyeLidRight = Runtime.start("eyeLidRight","Servo")
eyeLidLeft = Runtime.start("eyeLidLeft","Servo")
# initialize arduino
# linux or macos -> arduino.connect("/dev/ttyUSB0")
print("connecting arduino to serial port")
arduino.connect(port)
adaFruit16c.attach("arduino","0","0x40")
# servo01.setMinMax(0, 180)
eyeX.map(0, 180, 0, 180)
eyeY.map(0, 180, 0, 180)
eyeLidRight.map(0, 180, 0, 180)
eyeLidLeft.map(0, 180, 0, 180)
# set rest position
eyeX.setRest(90)
eyeY.setRest(90)
eyeLidRight.setRest(90)
eyeLidLeft.setRest(90)
# attach servo to the Adafruit16CServoDriver
print("attaching servo to the Adafruit16CServoDriver")
eyeX.attach(adaFruit16c,22)
eyeY.attach(adaFruit16c,24)
eyeLidRight.attach(adaFruit16c,12)
eyeLidLeft.attach(adaFruit16c,13)
# auto disable - this enables (starts pwm) before a movement
# and disables (stops pwm) after a movement
eyeX.setAutoDisable(True)
eyeX.disableDelayIfVelocity=1000 # grace period for autoDisable
eyeY.setAutoDisable(True)
eyeY.disableDelayIfVelocity=1000
eyeLidRight.setAutoDisable(True)
eyeLidRight.disableDelayIfVelocity=1000
eyeLidLeft.setAutoDisable(True)
eyeLidLeft.disableDelayIfVelocity=1000
# speed changes
print("speed changes")
eyeX.setVelocity(80) ## Low velocity
eyeY.setVelocity(80)
eyeLidRight.setVelocity(80)
eyeLidLeft.setVelocity(80)
eyeX.moveTo(0) # we cannot use moveToBlocking if servo velocity is set to -1 ( max ) !!
eyeY.moveTo(180)
sleep(2)
# sync eyeLidRight with eyeLidLeft
# now eyeLidRight will be a slave to eyeLidLeft
print("syncing eyeLidRight with eyeLidLeft")
eyeLidRight.sync(eyeLidLeft)
eyeLidLeft.moveTo(10)
sleep(0.5)
eyeLidLeft.moveTo(179)
sleep(0.5)
eyeLidLeft.moveTo(10)
sleep(0.5)
# moving to rest position
print("eyeLidLeft rest")
eyeLidLeft.rest()
sleep(2)
Still same error :/
Hi Gael :)
Thanks for your help, but i still get the same exact error :/
Not sure what is wrong whit the script, btw we / i use Nixie...
just for test i used this, and that works:
Update:
Hi Gael,
The scrip works like it should if i start it from the command line, but gives the error above if i run it in the "python" window in the GUI, no ider why, but at least it works, thanks, now we have somwthing to test the servos with :)
/Spawn
I suspect a Nixie issue. It
I suspect a Nixie issue.
It works in real and virtualy in the Manticore.
Mouth Mechanism
Wow, this is impressive
Wow, this is impressive video.
Adjusting all those servos and pices within InMoov head is going to be a real challenge.
Eager to see the results!