Monday, 11 February 2013

Working at Aldebaran Robotics this week: Programming Action Molecules

Action Molecule Programming

Quite inspiring being here in Paris at Aldebaran. Now in my hotel room trying to work out how to do multiple threads in Python for NAO. This is required when an actor atom calls another actor atom using post. The other actor atom must simultaneously execute in a way that is precisely specified by the connection between atoms (bond) which may be parallel, serial, synchronised or unsynchronised. I think these will be critical parameters of a action atom bond.

It is only when motor atoms can link to each other in this way, and have fitness distributed between them that we can get truly syntactic and open-ended action, that is quite clear to me now.

"post" only works with modules with proxies I think, and I'm not sure how to construct these so maybe multi-threading of action atoms is not the right way to go? Perhaps the whole action molecule should simply be executed by the same thread synchronously for now, with the final processed motor commands being determined at each time-step after having run through the whole motor molecule that is currently active.

The function runAllActors needs to be re-written as runActorMolecules to permit the execution of entire networks of actor atoms, coupled by specific kinds of bond/link.


       #self.runAllActors()
          self.runActorMolecules()
          
          pass

     def runAllActors(self):#RUN all CODN Actors
     #This STARTS and runs actors until actor STOP is signalled, one at a time.        
          for i in range(len(self.codn.popActors)):
               #self.rest()
               self.sMemory = np.array([1]*INPUTSIZE)
               self.mMemory = np.array([0]*OUTPUTSIZE)
               if(self.codn.popActors[i].type is 0 and self.codn.popActors[i].initiator is 1):
                    self.codn.popActors[i].start = 1
                    while self.codn.popActors[i].stop is 0:
                         #Get sensory inputs from the robot
                         self.codn.popActors[i].updateTimes()
                         sensedAngles = self.get_sensor_values()
                         self.codn.popActors[i].getInputs(sensedAngles) #Actor updates its sensory input data structures.
                         self.codn.popActors[i].calcOutputs() #Actor specific calculations
                         motorRaw = self.codn.popActors[i].putOutputs() #Output raw motor values.
                         motorProcessed = self.set_motor_values(motorRaw, self.codn.popActors[i].motorDimensions)
                         sleep(0.1)
                         #Save SM state into a matrix for fitness assessment.
                         self.addToMemory(np.array(sensedAngles), np.array(motorProcessed))
                         #Note that OTHER actors may also be activated using post (new thread) if pointed to by this actor.
                         
          pass
     
     def runActorMolecules(self):#Run actor molecules (not just atomic actions)
          
OK, today (13th Feb 2013) I told Jean-Christophe Baillie (Chief Science Officer) at Aldebaran robotics all about the above algorithm for co-evolution of games and solutions, and the concept of game fitness being due to variance of actor fitness, and how this beautifully links with Fisher's Fundamental Theorum of natural selection. Nice that he used to work with Luc Steels. Hope Jean-Christophe can help me with this research. But must admit, I had the feeling that he didn't really grasp the importance of what I was saying, and felt he was slightly how should I say, inattentive or vague in his engagement with me. Anyway, not to worry that Aldebaran don't totally stop working on everything and concentrate purely on my algorithm, which would be a modestly successful interaction... :) 

Here is the outline from runActorMolecules

     def runActorMolecules(self):#Run actor molecules (not just atomic actions)
          #First choose which 'root' actor atom to activate using some action selection method,
          #Simplest possibility is to just systematically iterate throguh ALL root atoms
          for i in range(len(self.codn.popActors)):
               if self.codn.popActors[i].root is 1:
                    #1. Reset actor atoms and initialize network with activation of this single chosen actor atom.
                    #2. Update the activation state of the actor network synchronously, i.e. set actor atoms on/off, to create an actor molecule
                    #3. Get current sensory state and generate compositional motor behaviour by summing outputs proposed by all active actor atoms.
                    #4. Execute this behaviour step and sleep (0.1)
                    #5. Add sensedAngles and motorProcessed to memory
                    #6. Goto 2, activating new actors if instructed to do so by currently active actor atoms (possibly probabalistically)
          pass


So, lets get on and code the bloody thing.OK, its done... 


     def runActorMolecules(self):#Run actor molecules (not just atomic actions)
          #First choose which 'root' actor atom to activate using some action selection method,
          #Simplest possibility is to just systematically iterate throguh ALL root atoms
          for i in range(len(self.codn.popActors)):
               if self.codn.popActors[i].root is 1:
                    print i
                    #1. Reset actor atoms and initialize network with activation of this single chosen actor atom.
                    self.codn.resetActorAtoms()
                    self.codn.popActors[i].active = 1
                    AtLeastOneActorActive = 1
                    while AtLeastOneActorActive is 1:
                         #2. Update the activation state of the actor network synchronously, i.e. set actor atoms on/off, to create an actor molecule
                         self.codn.updateActorNetwork()
                         #3. Get current sensory state and generate compositional motor behaviour by summing outputs proposed by all active actor atoms.
                         sensedAngles = self.get_sensor_values()
                         motorAngles = self.codn.calcOutputsActiveAtoms(sensedAngles)
                         print(len(motorAngles))
                         if len(motorAngles) > 0:#if some motor angles have been set.
                              for index,i in enumerate(self.Body):
                                   if motorAngles[index] < i[0]/2:
                                        motorAngles[index] = i[0]/2
                                   if motorAngles[index] > i[1]/2:
                                        motorAngles[index] = i[1]/2
                              #4. Execute this behaviour step and sleep (0.1)
                              fractionMaxSpeed  = 1.0
                              self.motionProxy.setAngles("Body", motorAngles, fractionMaxSpeed)
                              sleep(0.1)
                              #5. Add sensedAngles and motorProcessed to memory
                              self.addToMemory(np.array(sensedAngles), np.array(motorAngles))
                              #6. Goto 2, if there are still actors active.
                         AtLeastOneActorActive = self.codn.checkAtLeastOneActorActive()
                   
          pass


Whats happening back home? 

The nappy rash is back. Hope its better tomorrow. Esther is getting a frog. How? You can buy them in pet shops. Really. Why? Because she likes pets. Everyone likes pets, especially biologist girls. Where is she going to keep the frog? Just, in a cage. She wanted a reptile, but they are too difficult. Except for snakes, which can be fed rarely. But J refused. Anna had all kinds of pets too. Collected many animals, carried them home in a jar, and released them. A Catapiller, let it grow. bloody good idea. They arent much into children Anna and Esther. Maybe because they are not related. Its very different if the baby belongs to your family, otherwise they are just cute, unless you are pregnant, which I presume they are not therefore.





No comments:

Post a Comment