opensistemas-hub / osbrain

osBrain - A general-purpose multi-agent system module written in Python
https://osbrain.readthedocs.io/en/stable/
Apache License 2.0
176 stars 43 forks source link

Question: I can't get request-reply to work in an OOP manner #299

Closed ileacristian closed 6 years ago

ileacristian commented 6 years ago

I want to use this method of communcation from this example: https://osbrain.readthedocs.io/en/stable/basic_patterns.html#request-reply But I want to do it in an OOP manner.

I have 2 types of agents: 1 Coordinator and 20 Passive agents. I want the Coordinator to ASK all the Passive agents to give their coordinates.

I'm probably doing something wrong 😰 because i get the following output:

Broadcast server running on 0.0.0.0:9091
NS running on 127.0.0.1:19789 (127.0.0.1)
URI = PYRO:Pyro.NameServer@127.0.0.1:19789
INFO [2018-04-23 12:29:51.348819] (Coordinator): Initialized 20 passive agents
INFO [2018-04-23 12:29:51.352668] (Coordinator): Starting step: 1
INFO [2018-04-23 12:29:51.354779] (Coordinator): Asking agent <osbrain.proxy.Proxy at 0x108a25780; connected IPv4; for PYRONAME:0@127.0.0.1:19789> for coords

And it hangs after this. 👆

Here is my code:

import time
import random
from osbrain import run_agent
from osbrain import run_nameserver
from osbrain import Agent

box_size_x = 100
box_size_y = 100

simulation_step_size = 0.5
simulation_steps = 100

passive_agents_count = 20

class Passive(Agent):
    def on_init(self):
        self.x = random.randrange(0, 100)
        self.y = random.randrange(0, 100)
        self.rep = self.bind('REP', alias='coord', handler=self.giveCoord)

    def giveCoord(self, agent, message):
        self.log_info('Need to give coords')
        return (self.x, self.y)

class Coordinator(Agent):
    def on_init(self):
        self.agents = []
        self.steps = simulation_steps
        self.stimulation_step_size = simulation_step_size
        self.current_step = 0
        self.passive_agents_count = passive_agents_count
        self.bind('PUB', alias='coordinator')

    def is_done(self):
        return self.current_step == self.steps

    def announce_agents_to_step(self):
        self.log_info('Starting step: %d' % self.current_step)
        #self.send('coordinator', self.current_step, topic="current_step")

    def start_simulation(self):
        for i in range(self.passive_agents_count):
            agent = run_agent(str(i), base=Passive)
            self.connect(agent.addr('coord'), alias='coord')  #is this correct?
            self.agents.append(agent)

        self.log_info('Initialized %d passive agents' % len(self.agents))

        for i in range(0, self.steps):
            self.current_step +=1
            self.announce_agents_to_step()
            for agent in self.agents:
                self.log_info('Asking agent %s for coords' % agent)
                reply = agent.recv('coord')

ns = run_nameserver()

coordinator = run_agent("Coordinator", base=Coordinator)

coordinator.start_simulation()

while not coordinator.is_done():
    time.sleep(1)

ns.shutdown()
Peque commented 6 years ago

I see a couple of things there.

First, you do not seem to send a request from the Coordinator, you need to do so like this:

    def start_simulation(self):                                                 
        for i in range(self.passive_agents_count):                              
            agent = run_agent(str(i), base=Passive)                             
            self.connect(agent.addr('coord'), alias='passive_%d' % i)            

        for i in range(0, self.steps):                                          
            self.current_step +=1                                               
            self.announce_agents_to_step()                                      
            for passive in range(self.passive_agents_count):                    
                self.log_info('Asking agent %s for coords' % passive)           
                self.send('passive_%d' % passive, 'Give me coordinate!')         
                reply = self.recv('passive_%d' % passive)                        
                print(reply)          

Then you need to modify your giveCoord() too:

    def giveCoord(self, message):                                        
        self.log_info('Need to give coords')                                    
        return (self.x, self.y)
ileacristian commented 6 years ago

Haha. Thank you! I knew I was doing something silly. 😝