2015-07-02 55 views
2

我想寫一些簡單的循環來控制Pygazebo中的對象,但是它只會調用一次方法,然後循環出現阻塞。爲什麼不讓這個循環異步運行?

# -*- coding: utf-8 -*- 
""" 
Created on Thu Jul 2 12:52:50 2015 

@author: skylion 
""" 

import trollius #NOTE: Trollius requires protobuffer from Google 
from trollius import From 

import pygazebo 
import pygazebo.msg.joint_cmd_pb2 
import time 

def apply_joint_force(world_name, robot_name, joint_name, force, duration=-1): 


    @trollius.coroutine 
    def joint_force_loop(): 
     manager = yield From(pygazebo.connect()) 
     print("connected") 


     publisher = yield From(
      manager.advertise('/gazebo/' + world_name + '/' + robot_name + '/joint_cmd', 
           'gazebo.msgs.JointCmd')) 

     message = pygazebo.msg.joint_cmd_pb2.JointCmd() 
     message.name = robot_name + '::' + joint_name #format should be: name_of_robot + '::name_of_joint' 
     message.force = force 


     #t_end = time.time() + duration # The time that you want the controller to stop 
     while True: #time.time() < t_end or duration == -1: 
      try: 
       yield From(publisher.publish(message)) 
       yield From(trollius.sleep(1.0)) 
      except: 
       pass 
      #Nothing 
     print("Connection closed") 

    wait_net_service('localhost',11345) 


    loop = trollius.new_event_loop() 
    loop.run_until_complete(joint_force_loop()) 
    raise  


def wait_net_service(server, port, timeout=None): 
    """ Wait for network service to appear 
     @param timeout: in seconds, if None or 0 wait forever 
     @return: True of False, if timeout is None may return only True or 
       throw unhandled network exception 
    """ 
    import socket 
    import errno 

    s = socket.socket() 
    if timeout: 
     from time import time as now 
     # time module is needed to calc timeout shared between two exceptions 
     end = now() + timeout 

    while True: 
     try: 
      if timeout: 
       next_timeout = end - now() 
       if next_timeout < 0: 
        return False 
       else: 
        s.settimeout(next_timeout) 
      s.connect((server, port)) 
      time.sleep(1) 
     except socket.timeout, err: 
      # this exception occurs only if timeout is set 
      if timeout: 
       return False 

     except socket.error, err: 
      # catch timeout exception from underlying network library 
      # this one is different from socket.timeout 
      if type(err.args) != tuple or (err[0] != errno.ETIMEDOUT and err[0] != errno.ECONNREFUSED): 
       raise err 
     else: 
      s.close() 
      return True 

我以爲@病例假設是異步包裝?我是否誤解了使用此代碼?還是我在做其他事情?這是我第一次在Python中使用併發。

而且這是怎麼了調用該函數:

counter = 0 
    for joint_def in self.all_joint_props: 
     print("each joint_def") 
     apply_joint_force(world_name, robot_name, "hingejoint" + str(counter), joint_def[2]) 
     #print("Appliing joint force") 

任何想法,爲什麼它保持阻塞線程?我應該使用不同的方法嗎?任何幫助,將不勝感激

+0

我認爲你需要改變'wait_net_service(「localhost」的,11345)'來'產量來自wait_net_service('localhost',11345)' –

+0

我甚至在我添加該方法之前就有這個問題。所以這不是問題。 – Skylion

回答

1

所以,真的很簡單的答案。在啓動對象之前,您必須排隊運行多個Trollius.Tasks作爲列表,並將其與Trollius.wait()結合以實現此目的。爲了確保線程非阻塞然後您使用以下method

這裏是我到目前爲止的代碼:

tasks = [] 
for joint_name in joint_names: 
    tasks.append(trollius.Task(joint_force_loop(world_name, robot_name, joint_name, force, duration)) 
loop = trollius.get_event_loop() 
loop.run_until_complete(trollius.wait(tasks))