|
From: <mar...@us...> - 2009-06-16 07:39:34
|
Revision: 17139
http://personalrobots.svn.sourceforge.net/personalrobots/?rev=17139&view=rev
Author: mariusmuja
Date: 2009-06-16 07:39:29 +0000 (Tue, 16 Jun 2009)
Log Message:
-----------
Added asterisk in 3rdparty.
Scripts for asterisk based navigation.
Added Paths:
-----------
pkg/trunk/3rdparty/asterisk/
pkg/trunk/3rdparty/asterisk/Makefile
pkg/trunk/3rdparty/asterisk/files/
pkg/trunk/3rdparty/asterisk/files/agi.py
pkg/trunk/3rdparty/asterisk/files/extensions.ael
pkg/trunk/3rdparty/asterisk/files/office.py
pkg/trunk/3rdparty/asterisk/manifest.xml
pkg/trunk/highlevel/executive_python/src/office_nav.py
pkg/trunk/highlevel/executive_python/src/offices.py
pkg/trunk/highlevel/executive_python/src/offices_outside.py
pkg/trunk/highlevel/executive_python/src/print_goal.py
pkg/trunk/highlevel/executive_python/src/send_to_office.py
Added: pkg/trunk/3rdparty/asterisk/Makefile
===================================================================
--- pkg/trunk/3rdparty/asterisk/Makefile (rev 0)
+++ pkg/trunk/3rdparty/asterisk/Makefile 2009-06-16 07:39:29 UTC (rev 17139)
@@ -0,0 +1,24 @@
+all: installed
+
+VERSION = 1.6.1.0
+TARBALL = build/asterisk-$(VERSION).tar.gz
+TARBALL_URL = http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-$(VERSION).tar.gz
+UNPACK_CMD = tar -xvzf
+SOURCE_DIR = build/asterisk-$(VERSION)
+
+include $(shell rospack find mk)/download_unpack_build.mk
+
+installed: wiped $(SOURCE_DIR)/unpacked
+ echo "Building Asterisk PBX..."
+ cd $(SOURCE_DIR) && ./configure --prefix=`pwd`/../asterisk && make && make install && make samples && rm main/asterisk # detele asterisk from source folder so that rosrun will not find it
+ cp files/extensions.ael build/asterisk/etc/asterisk
+ -cp files/sip.conf build/asterisk/etc/asterisk
+ cp files/*.py build/asterisk/var/lib/asterisk/agi-bin
+ touch installed
+
+wiped: Makefile
+ make wipe
+ touch wiped
+
+wipe:
+ rm -rf build installed
Added: pkg/trunk/3rdparty/asterisk/files/agi.py
===================================================================
--- pkg/trunk/3rdparty/asterisk/files/agi.py (rev 0)
+++ pkg/trunk/3rdparty/asterisk/files/agi.py 2009-06-16 07:39:29 UTC (rev 17139)
@@ -0,0 +1,665 @@
+#!/usr/bin/env python
+# vim: set et sw=4:
+"""agi
+
+This module contains functions and classes to implment AGI scripts in python.
+pyvr
+
+{'agi_callerid' : 'mars.putland.int',
+ 'agi_channel' : 'IAX[kputland@kputland]/119',
+ 'agi_context' : 'default',
+ 'agi_dnid' : '666',
+ 'agi_enhanced' : '0.0',
+ 'agi_extension': '666',
+ 'agi_language' : 'en',
+ 'agi_priority' : '1',
+ 'agi_rdnis' : '',
+ 'agi_request' : 'pyst',
+ 'agi_type' : 'IAX'}
+
+"""
+
+import sys, pprint, re
+from types import ListType
+import signal
+
+DEFAULT_TIMEOUT = 2000 # 2sec timeout used as default for functions that take timeouts
+DEFAULT_RECORD = 20000 # 20sec record time
+
+re_code = re.compile(r'(^\d*)\s*(.*)')
+re_kv = re.compile(r'(?P<key>\w+)=(?P<value>[^\s]+)\s*(?:\((?P<data>.*)\))*')
+
+class AGIException(Exception): pass
+class AGIError(AGIException): pass
+
+class AGIUnknownError(AGIError): pass
+
+class AGIAppError(AGIError): pass
+
+# there are several different types of hangups we can detect
+# they all are derrived from AGIHangup
+class AGIHangup(AGIAppError): pass
+class AGISIGHUPHangup(AGIHangup): pass
+class AGISIGPIPEHangup(AGIHangup): pass
+class AGIResultHangup(AGIHangup): pass
+
+class AGIDBError(AGIAppError): pass
+
+class AGIUsageError(AGIError): pass
+class AGIInvalidCommand(AGIError): pass
+
+class AGI:
+ """
+ This class encapsulates communication between Asterisk an a python script.
+ It handles encoding commands to Asterisk and parsing responses from
+ Asterisk.
+ """
+
+ def __init__(self):
+ self._got_sighup = False
+ signal.signal(signal.SIGHUP, self._handle_sighup) # handle SIGHUP
+ sys.stderr.write('ARGS: ')
+ sys.stderr.write(str(sys.argv))
+ sys.stderr.write('\n')
+ self.env = {}
+ self._get_agi_env()
+
+ def _get_agi_env(self):
+ while 1:
+ line = sys.stdin.readline().strip()
+ sys.stderr.write('ENV LINE: ')
+ sys.stderr.write(line)
+ sys.stderr.write('\n')
+ if line == '':
+ #blank line signals end
+ break
+ key,data = line.split(':')[0], ':'.join(line.split(':')[1:])
+ key = key.strip()
+ data = data.strip()
+ if key <> '':
+ self.env[key] = data
+ sys.stderr.write('class AGI: self.env = ')
+ sys.stderr.write(pprint.pformat(self.env))
+ sys.stderr.write('\n')
+
+ def _quote(self, string):
+ return ''.join(['"', str(string), '"'])
+
+ def _handle_sighup(self, signum, frame):
+ """Handle the SIGHUP signal"""
+ self._got_sighup = True
+
+ def test_hangup(self):
+ """This function throws AGIHangup if we have recieved a SIGHUP"""
+ if self._got_sighup:
+ raise AGISIGHUPHangup("Received SIGHUP from Asterisk")
+
+ def execute(self, command, *args):
+ self.test_hangup()
+
+ try:
+ self.send_command(command, *args)
+ return self.get_result()
+ except IOError,e:
+ if e.errno == 32:
+ # Broken Pipe * let us go
+ raise AGISIGPIPEHangup("Received SIGPIPE")
+ else:
+ raise
+
+ def send_command(self, command, *args):
+ """Send a command to Asterisk"""
+ command = command.strip()
+ command = '%s %s' % (command, ' '.join(map(str,args)))
+ command = command.strip()
+ if command[-1] != '\n':
+ command += '\n'
+ sys.stderr.write(' COMMAND: %s' % command)
+ sys.stdout.write(command)
+ sys.stdout.flush()
+
+ def get_result(self, stdin=sys.stdin):
+ """Read the result of a command from Asterisk"""
+ code = 0
+ result = {'result':('','')}
+ line = stdin.readline().strip()
+ sys.stderr.write(' RESULT_LINE: %s\n' % line)
+ m = re_code.search(line)
+ if m:
+ code, response = m.groups()
+ code = int(code)
+
+ if code == 200:
+ for key,value,data in re_kv.findall(response):
+ result[key] = (value, data)
+
+ # If user hangs up... we get 'hangup' in the data
+ if data == 'hangup':
+ raise AGIResultHangup("User hungup during execution")
+
+ if key == 'result' and value == '-1':
+ raise AGIAppError("Error executing application, or hangup")
+
+ sys.stderr.write(' RESULT_DICT: %s\n' % pprint.pformat(result))
+ return result
+ elif code == 510:
+ raise AGIInvalidCommand(response)
+ elif code == 520:
+ usage = [line]
+ line = stdin.readline().strip()
+ while line[:3] != '520':
+ usage.append(line)
+ line = stdin.readline().strip()
+ usage.append(line)
+ usage = '%s\n' % '\n'.join(usage)
+ raise AGIUsageError(usage)
+ else:
+ raise AGIUnknownError(code, 'Unhandled code or undefined response')
+
+ def _process_digit_list(self, digits):
+ if type(digits) == ListType:
+ digits = ''.join(map(str, digits))
+ return self._quote(digits)
+
+ def answer(self):
+ """agi.answer() --> None
+ Answer channel if not already in answer state.
+ """
+ self.execute('ANSWER')['result'][0]
+
+ def wait_for_digit(self, timeout=DEFAULT_TIMEOUT):
+ """agi.wait_for_digit(timeout=DEFAULT_TIMEOUT) --> digit
+ Waits for up to 'timeout' milliseconds for a channel to receive a DTMF
+ digit. Returns digit dialed
+ Throws AGIError on channel falure
+ """
+ res = self.execute('WAIT FOR DIGIT', timeout)['result'][0]
+ if res == '0':
+ return ''
+ else:
+ try:
+ return chr(int(res))
+ except ValueError:
+ raise AGIError('Unable to convert result to digit: %s' % res)
+
+ def send_text(self, text=''):
+ """agi.send_text(text='') --> None
+ Sends the given text on a channel. Most channels do not support the
+ transmission of text.
+ Throws AGIError on error/hangup
+ """
+ self.execute('SEND TEXT', self._quote(text))['result'][0]
+
+ def receive_char(self, timeout=DEFAULT_TIMEOUT):
+ """agi.receive_char(timeout=DEFAULT_TIMEOUT) --> chr
+ Receives a character of text on a channel. Specify timeout to be the
+ maximum time to wait for input in milliseconds, or 0 for infinite. Most channels
+ do not support the reception of text.
+ """
+ res = self.execute('RECEIVE CHAR', timeout)['result'][0]
+
+ if res == '0':
+ return ''
+ else:
+ try:
+ return chr(int(res))
+ except:
+ raise AGIError('Unable to convert result to char: %s' % res)
+
+ def tdd_mode(self, mode='off'):
+ """agi.tdd_mode(mode='on'|'off') --> None
+ Enable/Disable TDD transmission/reception on a channel.
+ Throws AGIAppError if channel is not TDD-capable.
+ """
+ res = self.execute('TDD MODE', mode)['result'][0]
+ if res == '0':
+ raise AGIAppError('Channel %s is not TDD-capable')
+
+ def stream_file(self, filename, escape_digits='', sample_offset=0):
+ """agi.stream_file(filename, escape_digits='', sample_offset=0) --> digit
+ Send the given file, allowing playback to be interrupted by the given
+ digits, if any. escape_digits is a string '12345' or a list of
+ ints [1,2,3,4,5] or strings ['1','2','3'] or mixed [1,'2',3,'4']
+ If sample offset is provided then the audio will seek to sample
+ offset before play starts. Returns digit if one was pressed.
+ Throws AGIError if the channel was disconnected. Remember, the file
+ extension must not be included in the filename.
+ """
+ escape_digits = self._process_digit_list(escape_digits)
+ response = self.execute('STREAM FILE', filename, escape_digits, sample_offset)
+ res = response['result'][0]
+ if res == '0':
+ return ''
+ else:
+ try:
+ return chr(int(res))
+ except:
+ raise AGIError('Unable to convert result to char: %s' % res)
+
+ def control_stream_file(self, filename, escape_digits='', skipms=3000, fwd='', rew='', pause=''):
+ """
+ Send the given file, allowing playback to be interrupted by the given
+ digits, if any. escape_digits is a string '12345' or a list of
+ ints [1,2,3,4,5] or strings ['1','2','3'] or mixed [1,'2',3,'4']
+ If sample offset is provided then the audio will seek to sample
+ offset before play starts. Returns digit if one was pressed.
+ Throws AGIError if the channel was disconnected. Remember, the file
+ extension must not be included in the filename.
+ """
+ escape_digits = self._process_digit_list(escape_digits)
+ response = self.execute('CONTROL STREAM FILE', self._quote(filename), escape_digits, self._quote(skipms), self._quote(fwd), self._quote(rew), self._quote(pause))
+ res = response['result'][0]
+ if res == '0':
+ return ''
+ else:
+ try:
+ return chr(int(res))
+ except:
+ raise AGIError('Unable to convert result to char: %s' % res)
+
+ def send_image(self, filename):
+ """agi.send_image(filename) --> None
+ Sends the given image on a channel. Most channels do not support the
+ transmission of images. Image names should not include extensions.
+ Throws AGIError on channel failure
+ """
+ res = self.execute('SEND IMAGE', filename)['result'][0]
+ if res != '0':
+ raise AGIAppError('Channel falure on channel %s' % self.env.get('agi_channel','UNKNOWN'))
+
+ def say_digits(self, digits, escape_digits=''):
+ """agi.say_digits(digits, escape_digits='') --> digit
+ Say a given digit string, returning early if any of the given DTMF digits
+ are received on the channel.
+ Throws AGIError on channel failure
+ """
+ digits = self._process_digit_list(digits)
+ escape_digits = self._process_digit_list(escape_digits)
+ res = self.execute('SAY DIGITS', digits, escape_digits)['result'][0]
+ if res == '0':
+ return ''
+ else:
+ try:
+ return chr(int(res))
+ except:
+ raise AGIError('Unable to convert result to char: %s' % res)
+
+ def say_number(self, number, escape_digits=''):
+ """agi.say_number(number, escape_digits='') --> digit
+ Say a given digit string, returning early if any of the given DTMF digits
+ are received on the channel.
+ Throws AGIError on channel failure
+ """
+ number = self._process_digit_list(number)
+ escape_digits = self._process_digit_list(escape_digits)
+ res = self.execute('SAY NUMBER', number, escape_digits)['result'][0]
+ if res == '0':
+ return ''
+ else:
+ try:
+ return chr(int(res))
+ except:
+ raise AGIError('Unable to convert result to char: %s' % res)
+
+ def say_alpha(self, characters, escape_digits=''):
+ """agi.say_alpha(string, escape_digits='') --> digit
+ Say a given character string, returning early if any of the given DTMF
+ digits are received on the channel.
+ Throws AGIError on channel failure
+ """
+ characters = self._process_digit_list(characters)
+ escape_digits = self._process_digit_list(escape_digits)
+ res = self.execute('SAY ALPHA', characters, escape_digits)['result'][0]
+ if res == '0':
+ return ''
+ else:
+ try:
+ return chr(int(res))
+ except:
+ raise AGIError('Unable to convert result to char: %s' % res)
+
+ def say_phonetic(self, characters, escape_digits=''):
+ """agi.say_phonetic(string, escape_digits='') --> digit
+ Phonetically say a given character string, returning early if any of
+ the given DTMF digits are received on the channel.
+ Throws AGIError on channel failure
+ """
+ characters = self._process_digit_list(characters)
+ escape_digits = self._process_digit_list(escape_digits)
+ res = self.execute('SAY PHONETIC', characters, escape_digits)['result'][0]
+ if res == '0':
+ return ''
+ else:
+ try:
+ return chr(int(res))
+ except:
+ raise AGIError('Unable to convert result to char: %s' % res)
+
+ def say_date(self, seconds, escape_digits=''):
+ """agi.say_date(seconds, escape_digits='') --> digit
+ Say a given date, returning early if any of the given DTMF digits are
+ pressed. The date should be in seconds since the UNIX Epoch (Jan 1, 1970 00:00:00)
+ """
+ escape_digits = self._process_digit_list(escape_digits)
+ res = self.execute('SAY DATE', seconds, escape_digits)['result'][0]
+ if res == '0':
+ return ''
+ else:
+ try:
+ return chr(int(res))
+ except:
+ raise AGIError('Unable to convert result to char: %s' % res)
+
+ def say_time(self, seconds, escape_digits=''):
+ """agi.say_time(seconds, escape_digits='') --> digit
+ Say a given time, returning early if any of the given DTMF digits are
+ pressed. The time should be in seconds since the UNIX Epoch (Jan 1, 1970 00:00:00)
+ """
+ escape_digits = self._process_digit_list(escape_digits)
+ res = self.execute('SAY TIME', seconds, escape_digits)['result'][0]
+ if res == '0':
+ return ''
+ else:
+ try:
+ return chr(int(res))
+ except:
+ raise AGIError('Unable to convert result to char: %s' % res)
+
+ def say_datetime(self, seconds, escape_digits='', format='', zone=''):
+ """agi.say_datetime(seconds, escape_digits='', format='', zone='') --> digit
+ Say a given date in the format specfied (see voicemail.conf), returning
+ early if any of the given DTMF digits are pressed. The date should be
+ in seconds since the UNIX Epoch (Jan 1, 1970 00:00:00).
+ """
+ escape_digits = self._process_digit_list(escape_digits)
+ if format: format = self._quote(format)
+ res = self.execute('SAY DATETIME', seconds, escape_digits, format, zone)['result'][0]
+ if res == '0':
+ return ''
+ else:
+ try:
+ return chr(int(res))
+ except:
+ raise AGIError('Unable to convert result to char: %s' % res)
+
+ def get_data(self, filename, timeout=DEFAULT_TIMEOUT, max_digits=255):
+ """agi.get_data(filename, timeout=DEFAULT_TIMEOUT, max_digits=255) --> digits
+ Stream the given file and receive dialed digits
+ """
+ result = self.execute('GET DATA', filename, timeout, max_digits)
+ res, value = result['result']
+ return res
+
+ def get_option(self, filename, escape_digits='', timeout=0):
+ """agi.get_option(filename, escape_digits='', timeout=0) --> digit
+ Send the given file, allowing playback to be interrupted by the given
+ digits, if any. escape_digits is a string '12345' or a list of
+ ints [1,2,3,4,5] or strings ['1','2','3'] or mixed [1,'2',3,'4']
+ Returns digit if one was pressed.
+ Throws AGIError if the channel was disconnected. Remember, the file
+ extension must not be included in the filename.
+ """
+ escape_digits = self._process_digit_list(escape_digits)
+ if timeout:
+ response = self.execute('GET OPTION', filename, escape_digits, timeout)
+ else:
+ response = self.execute('GET OPTION', filename, escape_digits)
+
+ res = response['result'][0]
+ if res == '0':
+ return ''
+ else:
+ try:
+ return chr(int(res))
+ except:
+ raise AGIError('Unable to convert result to char: %s' % res)
+
+ def set_context(self, context):
+ """agi.set_context(context)
+ Sets the context for continuation upon exiting the application.
+ No error appears to be produced. Does not set exten or priority
+ Use at your own risk. Ensure that you specify a valid context.
+ """
+ self.execute('SET CONTEXT', context)
+
+ def set_extension(self, extension):
+ """agi.set_extension(extension)
+ Sets the extension for continuation upon exiting the application.
+ No error appears to be produced. Does not set context or priority
+ Use at your own risk. Ensure that you specify a valid extension.
+ """
+ self.execute('SET EXTENSION', extension)
+
+ def set_priority(self, priority):
+ """agi.set_priority(priority)
+ Sets the priority for continuation upon exiting the application.
+ No error appears to be produced. Does not set exten or context
+ Use at your own risk. Ensure that you specify a valid priority.
+ """
+ self.execute('set priority', priority)
+
+ def goto_on_exit(self, context='', extension='', priority=''):
+ context = context or self.env['agi_context']
+ extension = extension or self.env['agi_extension']
+ priority = priority or self.env['agi_priority']
+ self.set_context(context)
+ self.set_extension(extension)
+ self.set_priority(priority)
+
+ def record_file(self, filename, format='gsm', escape_digits='#', timeout=DEFAULT_RECORD, offset=0, beep='beep'):
+ """agi.record_file(filename, format, escape_digits, timeout=DEFAULT_TIMEOUT, offset=0, beep='beep') --> None
+ Record to a file until a given dtmf digit in the sequence is received
+ The format will specify what kind of file will be recorded. The timeout
+ is the maximum record time in milliseconds, or -1 for no timeout. Offset
+ samples is optional, and if provided will seek to the offset without
+ exceeding the end of the file
+ """
+ escape_digits = self._process_digit_list(escape_digits)
+ res = self.execute('RECORD FILE', self._quote(filename), format, escape_digits, timeout, offset, beep)['result'][0]
+ try:
+ return chr(int(res))
+ except:
+ raise AGIError('Unable to convert result to digit: %s' % res)
+
+ def set_autohangup(self, secs):
+ """agi.set_autohangup(secs) --> None
+ Cause the channel to automatically hangup at <time> seconds in the
+ future. Of course it can be hungup before then as well. Setting to
+ 0 will cause the autohangup feature to be disabled on this channel.
+ """
+ self.execute('SET AUTOHANGUP', time)
+
+ def hangup(self, channel=''):
+ """agi.hangup(channel='')
+ Hangs up the specified channel.
+ If no channel name is given, hangs up the current channel
+ """
+ self.execute('HANGUP', channel)
+
+ def appexec(self, application, options=''):
+ """agi.appexec(application, options='')
+ Executes <application> with given <options>.
+ Returns whatever the application returns, or -2 on failure to find
+ application
+ """
+ result = self.execute('EXEC', application, self._quote(options))
+ res = result['result'][0]
+ if res == '-2':
+ raise AGIAppError('Unable to find application: %s' % application)
+ return res
+
+ def set_callerid(self, number):
+ """agi.set_callerid(number) --> None
+ Changes the callerid of the current channel.
+ """
+ self.execute('SET CALLERID', number)
+
+ def channel_status(self, channel=''):
+ """agi.channel_status(channel='') --> int
+ Returns the status of the specified channel. If no channel name is
+ given the returns the status of the current channel.
+
+ Return values:
+ 0 Channel is down and available
+ 1 Channel is down, but reserved
+ 2 Channel is off hook
+ 3 Digits (or equivalent) have been dialed
+ 4 Line is ringing
+ 5 Remote end is ringing
+ 6 Line is up
+ 7 Line is busy
+ """
+ try:
+ result = self.execute('CHANNEL STATUS', channel)
+ except AGIHangup:
+ raise
+ except AGIAppError:
+ result = {'result': ('-1','')}
+
+ return int(result['result'][0])
+
+ def set_variable(self, name, value):
+ """Set a channel variable.
+ """
+ self.execute('SET VARIABLE', self._quote(name), self._quote(value))
+
+ def get_variable(self, name):
+ """Get a channel variable.
+
+ This function returns the value of the indicated channel variable. If
+ the variable is not set, an empty string is returned.
+ """
+ try:
+ result = self.execute('GET VARIABLE', self._quote(name))
+ except AGIResultHangup:
+ result = {'result': ('1', 'hangup')}
+
+ res, value = result['result']
+ return value
+
+ def get_full_variable(self, name, channel = None):
+ """Get a channel variable.
+
+ This function returns the value of the indicated channel variable. If
+ the variable is not set, an empty string is returned.
+ """
+ try:
+ if channel:
+ result = self.execute('GET FULL VARIABLE', self._quote(name), self._quote(channel))
+ else:
+ result = self.execute('GET FULL VARIABLE', self._quote(name))
+
+ except AGIResultHangup:
+ result = {'result': ('1', 'hangup')}
+
+ res, value = result['result']
+ return value
+
+ def verbose(self, message, level=1):
+ """agi.verbose(message='', level=1) --> None
+ Sends <message> to the console via verbose message system.
+ <level> is the the verbose level (1-4)
+ """
+ self.execute('VERBOSE', self._quote(message), level)
+
+ def database_get(self, family, key):
+ """agi.database_get(family, key) --> str
+ Retrieves an entry in the Asterisk database for a given family and key.
+ Returns 0 if <key> is not set. Returns 1 if <key>
+ is set and returns the variable in parenthesis
+ example return code: 200 result=1 (testvariable)
+ """
+ family = '"%s"' % family
+ key = '"%s"' % key
+ result = self.execute('DATABASE GET', self._quote(family), self._quote(key))
+ res, value = result['result']
+ if res == '0':
+ raise AGIDBError('Key not found in database: family=%s, key=%s' % (family, key))
+ elif res == '1':
+ return value
+ else:
+ raise AGIError('Unknown exception for : family=%s, key=%s, result=%s' % (family, key, pprint.pformat(result)))
+
+ def database_put(self, family, key, value):
+ """agi.database_put(family, key, value) --> None
+ Adds or updates an entry in the Asterisk database for a
+ given family, key, and value.
+ """
+ result = self.execute('DATABASE PUT', self._quote(family), self._quote(key), self._quote(value))
+ res, value = result['result']
+ if res == '0':
+ raise AGIDBError('Unable to put vaule in databale: family=%s, key=%s, value=%s' % (family, key, value))
+
+ def database_del(self, family, key):
+ """agi.database_del(family, key) --> None
+ Deletes an entry in the Asterisk database for a
+ given family and key.
+ """
+ result = self.execute('DATABASE DEL', self._quote(family), self._quote(key))
+ res, value = result['result']
+ if res == '0':
+ raise AGIDBError('Unable to delete from database: family=%s, key=%s' % (family, key))
+
+ def database_deltree(self, family, key=''):
+ """agi.database_deltree(family, key='') --> None
+ Deletes a family or specific keytree with in a family
+ in the Asterisk database.
+ """
+ result = self.execute('DATABASE DELTREE', self._quote(family), self._quote(key))
+ res, value = result['result']
+ if res == '0':
+ raise AGIDBError('Unable to delete tree from database: family=%s, key=%s' % (family, key))
+
+ def noop(self):
+ """agi.noop() --> None
+ Does nothing
+ """
+ self.execute('NOOP')
+
+if __name__=='__main__':
+ agi = AGI()
+ #agi.appexec('festival','Welcome to Klass Technologies. Thank you for calling.')
+ #agi.appexec('festival','This is a test of the text to speech engine.')
+ #agi.appexec('festival','Press 1 for sales ')
+ #agi.appexec('festival','Press 2 for customer support ')
+ #agi.hangup()
+ #agi.goto_on_exit(extension='1234', priority='1')
+ #sys.exit(0)
+ #agi.say_digits([4,5,6])
+ agi.say_number(agi.env["agi_extension"])
+ #agi.say_number('01234') # 668
+ #agi.say_number('0xf5') # 245
+ #agi.get_data('demo-congrats')
+ agi.hangup()
+ sys.exit(0)
+ #agi.record_file('pyst-test') #FAILS
+ #agi.stream_file('demo-congrats', [1,2,3,4,5,6,7,8,9,0,'#','*'])
+ #agi.appexec('background','demo-congrats')
+
+ try:
+ agi.appexec('backgrounder','demo-congrats')
+ except AGIAppError:
+ sys.stderr.write("Handled exception for missing application backgrounder\n")
+
+ agi.set_variable('foo','bar')
+ agi.get_variable('foo')
+
+ try:
+ agi.get_variable('foobar')
+ except AGIAppError:
+ sys.stderr.write("Handled exception for missing variable foobar\n")
+
+ try:
+ agi.database_put('foo', 'bar', 'foobar')
+ agi.database_put('foo', 'baz', 'foobaz')
+ agi.database_put('foo', 'bat', 'foobat')
+ v = agi.database_get('foo', 'bar')
+ sys.stderr.write('DBVALUE foo:bar = %s\n' % v)
+ v = agi.database_get('bar', 'foo')
+ sys.stderr.write('DBVALUE foo:bar = %s\n' % v)
+ agi.database_del('foo', 'bar')
+ agi.database_deltree('foo')
+ except AGIDBError:
+ sys.stderr.write("Handled exception for missing database entry bar:foo\n")
+
+ agi.hangup()
Added: pkg/trunk/3rdparty/asterisk/files/extensions.ael
===================================================================
--- pkg/trunk/3rdparty/asterisk/files/extensions.ael (rev 0)
+++ pkg/trunk/3rdparty/asterisk/files/extensions.ael 2009-06-16 07:39:29 UTC (rev 17139)
@@ -0,0 +1,471 @@
+//
+// Example AEL config file
+//
+//
+// Static extension configuration file, used by
+// the pbx_ael module. This is where you configure all your
+// inbound and outbound calls in Asterisk.
+//
+// This configuration file is reloaded
+// - With the "ael reload" command in the CLI
+// - With the "reload" command (that reloads everything) in the CLI
+
+// The "Globals" category contains global variables that can be referenced
+// in the dialplan by using the GLOBAL dialplan function:
+// ${GLOBAL(VARIABLE)}
+// ${${GLOBAL(VARIABLE)}} or ${text${GLOBAL(VARIABLE)}} or any hybrid
+// Unix/Linux environmental variables are reached with the ENV dialplan
+// function: ${ENV(VARIABLE)}
+//
+
+globals {
+ CONSOLE="Console/dsp"; // Console interface for demo
+ //CONSOLE=DAHDI/1
+ //CONSOLE=Phone/phone0
+ IAXINFO=guest; // IAXtel username/password
+ //IAXINFO="myuser:mypass";
+ TRUNK="DAHDI/G2"; // Trunk interface
+ //
+ // Note the 'G2' in the TRUNK variable above. It specifies which group (defined
+ // in dahdi.conf) to dial, i.e. group 2, and how to choose a channel to use in
+ // the specified group. The four possible options are:
+ //
+ // g: select the lowest-numbered non-busy DAHDI channel
+ // (aka. ascending sequential hunt group).
+ // G: select the highest-numbered non-busy DAHDI channel
+ // (aka. descending sequential hunt group).
+ // r: use a round-robin search, starting at the next highest channel than last
+ // time (aka. ascending rotary hunt group).
+ // R: use a round-robin search, starting at the next lowest channel than last
+ // time (aka. descending rotary hunt group).
+ //
+ TRUNKMSD=1; // MSD digits to strip (usually 1 or 0)
+ //TRUNK=IAX2/user:pass@provider
+};
+
+//
+// Any category other than "General" and "Globals" represent
+// extension contexts, which are collections of extensions.
+//
+// Extension names may be numbers, letters, or combinations
+// thereof. If an extension name is prefixed by a '_'
+// character, it is interpreted as a pattern rather than a
+// literal. In patterns, some characters have special meanings:
+//
+// X - any digit from 0-9
+// Z - any digit from 1-9
+// N - any digit from 2-9
+// [1235-9] - any digit in the brackets (in this example, 1,2,3,5,6,7,8,9)
+// . - wildcard, matches anything remaining (e.g. _9011. matches
+// anything starting with 9011 excluding 9011 itself)
+// ! - wildcard, causes the matching process to complete as soon as
+// it can unambiguously determine that no other matches are possible
+//
+// For example the extension _NXXXXXX would match normal 7 digit dialings,
+// while _1NXXNXXXXXX would represent an area code plus phone number
+// preceded by a one.
+//
+// Each step of an extension is ordered by priority, which must
+// always start with 1 to be considered a valid extension. The priority
+// "next" or "n" means the previous priority plus one, regardless of whether
+// the previous priority was associated with the current extension or not.
+// The priority "same" or "s" means the same as the previously specified
+// priority, again regardless of whether the previous entry was for the
+// same extension. Priorities may be immediately followed by a plus sign
+// and another integer to add that amount (most useful with 's' or 'n').
+// Priorities may then also have an alias, or label, in
+// parenthesis after their name which can be used in goto situations
+//
+// Contexts contain several lines, one for each step of each
+// extension, which can take one of two forms as listed below,
+// with the first form being preferred. One may include another
+// context in the current one as well, optionally with a
+// date and time. Included contexts are included in the order
+// they are listed.
+//
+//context name {
+// exten-name => {
+// application(arg1,arg2,...);
+//
+// Timing list for includes is
+//
+// <time range>|<days of week>|<days of month>|<months>
+//
+// includes {
+// daytime|9:00-17:00|mon-fri|*|*;
+// };
+//
+// ignorepat can be used to instruct drivers to not cancel dialtone upon
+// receipt of a particular pattern. The most commonly used example is
+// of course '9' like this:
+//
+// ignorepat => 9;
+//
+// so that dialtone remains even after dialing a 9.
+//};
+
+
+//
+// Sample entries for extensions.conf
+//
+//
+context ael-dundi-e164-canonical {
+ //
+ // List canonical entries here
+ //
+ // 12564286000 => &ael-std-exten(6000,IAX2/foo);
+ // _125642860XX => Dial(IAX2/otherbox/${EXTEN:7});
+};
+
+context ael-dundi-e164-customers {
+ //
+ // If you are an ITSP or Reseller, list your customers here.
+ //
+ //_12564286000 => Dial(SIP/customer1);
+ //_12564286001 => Dial(IAX2/customer2);
+};
+
+context ael-dundi-e164-via-pstn {
+ //
+ // If you are freely delivering calls to the PSTN, list them here
+ //
+ //_1256428XXXX => Dial(DAHDI/G2/${EXTEN:7}); // Expose all of 256-428
+ //_1256325XXXX => Dial(DAHDI/G2/${EXTEN:7}); // Ditto for 256-325
+};
+
+context ael-dundi-e164-local {
+ //
+ // Context to put your dundi IAX2 or SIP user in for
+ // full access
+ //
+ includes {
+ ael-dundi-e164-canonical;
+ ael-dundi-e164-customers;
+ ael-dundi-e164-via-pstn;
+ };
+};
+
+context ael-dundi-e164-switch {
+ //
+ // Just a wrapper for the switch
+ //
+
+ switches {
+ DUNDi/e164;
+ };
+};
+
+context ael-dundi-e164-lookup {
+ //
+ // Locally to lookup, try looking for a local E.164 solution
+ // then try DUNDi if we don't have one.
+ //
+ includes {
+ ael-dundi-e164-local;
+ ael-dundi-e164-switch;
+ };
+ //
+};
+
+//
+// DUNDi can also be implemented as a Macro instead of using
+// the Local channel driver.
+//
+macro ael-dundi-e164(exten) {
+//
+// ARG1 is the extension to Dial
+//
+ goto ${exten}|1;
+ return;
+};
+
+//
+// Here are the entries you need to participate in the IAXTEL
+// call routing system. Most IAXTEL numbers begin with 1-700, but
+// there are exceptions. For more information, and to sign
+// up, please go to www.gnophone.com or www.iaxtel.com
+//
+context ael-iaxtel700 {
+ _91700XXXXXXX => Dial(IAX2/${IAXINFO}@iaxtel.com/${EXTEN:1}@iaxtel);
+};
+
+//
+// The SWITCH statement permits a server to share the dialplan with
+// another server. Use with care: Reciprocal switch statements are not
+// allowed (e.g. both A -> B and B -> A), and the switched server needs
+// to be on-line or else dialing can be severly delayed.
+//
+context ael-iaxprovider {
+ switches {
+ // IAX2/user:[key]@myserver/mycontext;
+ };
+};
+
+context ael-trunkint {
+ //
+ // International long distance through trunk
+ //
+ includes {
+ ael-dundi-e164-lookup;
+ };
+ _9011. => {
+ &ael-dundi-e164(${EXTEN:4});
+ Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
+ };
+};
+
+context ael-trunkld {
+ //
+ // Long distance context accessed through trunk
+ //
+ includes {
+ ael-dundi-e164-lookup;
+ };
+ _91NXXNXXXXXX => {
+ &ael-dundi-e164(${EXTEN:1});
+ Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
+ };
+};
+
+context ael-trunklocal {
+ //
+ // Local seven-digit dialing accessed through trunk interface
+ //
+ _9NXXXXXX => {
+ Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
+ };
+};
+
+context ael-trunktollfree {
+ //
+ // Long distance context accessed through trunk interface
+ //
+
+ _91800NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
+ _91888NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
+ _91877NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
+ _91866NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
+};
+
+context ael-international {
+ //
+ // Master context for international long distance
+ //
+ ignorepat => 9;
+ includes {
+ ael-longdistance;
+ ael-trunkint;
+ };
+};
+
+context ael-longdistance {
+ //
+ // Master context for long distance
+ //
+ ignorepat => 9;
+ includes {
+ ael-local;
+ ael-trunkld;
+ };
+};
+
+context ael-local {
+ //
+ // Master context for local, toll-free, and iaxtel calls only
+ //
+ ignorepat => 9;
+ includes {
+ ael-default;
+ ael-trunklocal;
+ ael-iaxtel700;
+ ael-trunktollfree;
+ ael-iaxprovider;
+ };
+};
+
+//
+// You can use an alternative switch type as well, to resolve
+// extensions that are not known here, for example with remote
+// IAX switching you transparently get access to the remote
+// Asterisk PBX
+//
+// switch => IAX2/user:password@bigserver/local
+//
+// An "lswitch" is like a switch but is literal, in that
+// variable substitution is not performed at load time
+// but is passed to the switch directly (presumably to
+// be substituted in the switch routine itself)
+//
+// lswitch => Loopback/12${EXTEN}@othercontext
+//
+// An "eswitch" is like a switch but the evaluation of
+// variable substitution is performed at runtime before
+// being passed to the switch routine.
+//
+// eswitch => IAX2/context@${CURSERVER}
+
+
+macro ael-std-exten-ael( ext , dev ) {
+ Dial(${dev}/${ext},20);
+ switch(${DIALSTATUS}) {
+ case BUSY:
+ Voicemail(${ext},b);
+ break;
+ default:
+ Voicemail(${ext},u);
+ };
+ catch a {
+ VoiceMailMain(${ext});
+ return;
+ };
+ return;
+};
+
+context incomming {
+ s => {
+// jump record;
+ Wait(1);
+ Answer();
+ Set(TIMEOUT(digit)=5);
+ Set(TIMEOUT(response)=10);
+ Background(hello-world);
+ WaitExten(10);
+ };
+ record => {
+ Playback(vm-intro);
+ Record(message.gsm);
+ Playback(vm-saved);
+ Playback(vm-goodbye);
+ };
+ _XXX => {
+ SayNumber(${EXTEN});
+ AGI(office.py);
+ Hangup();
+ }
+};
+
+context ael-demo {
+ s => {
+ Wait(1);
+ Answer();
+ Set(TIMEOUT(digit)=5);
+ Set(TIMEOUT(response)=10);
+restart:
+ Background(demo-congrats);
+instructions:
+ for (x=0; ${x} < 3; x=${x} + 1) {
+ Background(demo-instruct);
+ WaitExten();
+ };
+ };
+ 2 => {
+ Background(demo-moreinfo);
+ goto s|instructions;
+ };
+ 3 => {
+ Set(LANGUAGE()=fr);
+ goto s|restart;
+ };
+ 1000 => {
+ goto ael-default|s|1;
+ };
+ 500 => {
+ Playback(demo-abouttotry);
+ Dial(IAX2/gu...@mi.../s@default);
+ Playback(demo-nogo);
+ goto s|instructions;
+ };
+ 600 => {
+ Playback(demo-echotest);
+ Echo();
+ Playback(demo-echodone);
+ goto s|instructions;
+ };
+ _1234 => &ael-std-exten-ael(${EXTEN}, "IAX2");
+ 8500 => {
+ VoicemailMain();
+ goto s|instructions;
+ };
+ # => {
+ Playback(demo-thanks);
+ Hangup();
+ };
+ t => goto #|1;
+ i => Playback(invalid);
+};
+
+
+//
+// If you wish to use AEL for your default context, remove it
+// from extensions.conf (or change its name or comment it out)
+// and then uncomment the one here.
+//
+
+context ael-default {
+
+// By default we include the demo. In a production system, you
+// probably don't want to have the demo there.
+
+ includes {
+ ael-demo;
+ };
+//
+// Extensions like the two below can be used for FWD, Nikotel, sipgate etc.
+// Note that you must have a [sipprovider] section in sip.conf whereas
+// the otherprovider.net example does not require such a peer definition
+//
+//_41X. => Dial(SIP/${EXTEN:2}@sipprovider,,r);
+//_42X. => Dial(SIP/user:passwd@${EXTEN:2}@otherprovider.net,30,rT);
+
+// Real extensions would go here. Generally you want real extensions to be
+// 4 or 5 digits long (although there is no such requirement) and start with a
+// single digit that is fairly large (like 6 or 7) so that you have plenty of
+// room to overlap extensions and menu options without conflict. You can alias
+// them with names, too, and use global variables
+
+// 6245 => {
+// hint(SIP/Grandstream1&SIP/Xlite1,Joe Schmoe); // Channel hints for presence
+// Dial(SIP/Grandstream1,20,rt); // permit transfer
+// Dial(${HINT}/5245},20,rtT); // Use hint as listed
+// switch(${DIALSTATUS}) {
+// case BUSY:
+// Voicemail(6245,b);
+// return;
+// default:
+// Voicemail(6245,u);
+// return;
+// };
+// };
+
+// 6361 => Dial(IAX2/JaneDoe,,rm); // ring without time limit
+// 6389 => Dial(MGCP/aaln/1@192.168.0.14);
+// 6394 => Dial(Local/6275/n); // this will dial ${MARK}
+
+// 6275 => &ael-stdexten(6275,${MARK}); // assuming ${MARK} is something like DAHDI/2
+// mark => goto 6275|1; // alias mark to 6275
+// 6536 => &ael-stdexten(6236,${WIL}); // Ditto for wil
+// wil => goto 6236|1;
+//
+// Some other handy things are an extension for checking voicemail via
+// voicemailmain
+//
+// 8500 => {
+// VoicemailMain();
+// Hangup();
+// };
+//
+// Or a conference room (you'll need to edit meetme.conf to enable this room)
+//
+// 8600 => Meetme(1234);
+//
+// Or playing an announcement to the called party, as soon it answers
+//
+// 8700 => Dial(${MARK},30,A(/path/to/my/announcemsg))
+//
+// For more information on applications, just type "show applications" at your
+// friendly Asterisk CLI prompt.
+//
+// 'show application <command>' will show details of how you
+// use that particular application in this file, the dial plan.
+//
+}
Added: pkg/trunk/3rdparty/asterisk/files/office.py
===================================================================
--- pkg/trunk/3rdparty/asterisk/files/office.py (rev 0)
+++ pkg/trunk/3rdparty/asterisk/files/office.py 2009-06-16 07:39:29 UTC (rev 17139)
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2008, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# Revision $Id$
+
+## Simple talker demo that published std_msgs/Strings messages
+## to the 'chatter' topic
+
+import roslib; roslib.load_manifest('asterisk')
+
+import rospy
+from std_msgs.msg import String
+import sys
+import os
+from agi import AGI
+
+def sendGoal(office):
+ rospy.init_node('talker', anonymous=True)
+ sys.stderr.write("Going to office: %s"%office)
+ pub = rospy.Publisher('office_goal', String)
+ rospy.sleep(1)
+ pub.publish(office)
+ sys.stderr.write("Goal published")
+
+
+if __name__ == '__main__':
+ os.environ["ROS_MASTER_URI"] = "http://prf2:11311"
+ agi = AGI()
+ sendGoal(agi.env["agi_extension"])
Added: pkg/trunk/3rdparty/asterisk/manifest.xml
===================================================================
--- pkg/trunk/3rdparty/asterisk/manifest.xml (rev 0)
+++ pkg/trunk/3rdparty/asterisk/manifest.xml 2009-06-16 07:39:29 UTC (rev 17139)
@@ -0,0 +1,18 @@
+<package>
+ <description brief="asterisk">
+ Asterisk is the world's leading open source PBX, telephony engine, and telephony applications toolkit. Offering flexibility unheard of in the world of proprietary communications, Asterisk empowers developers and integrators to create advanced communication solutions...for free.
+ </description>
+
+ <author></author>
+ <license>GPL 2</license>
+ <review status="3rdparty" notes=""/>
+ <url>http://www.asterisk.org</url>
+ <export>
+ </export>
+ <depend package="rospy" />
+ <depend package="std_msgs" />
+
+ <sysdepend os="ubuntu" version="7.04-feisty" package="wget"/>
+ <sysdepend os="ubuntu" version="8.04-hardy" package="wget"/>
+
+</package>
Added: pkg/trunk/highlevel/executive_python/src/office_nav.py
===================================================================
--- pkg/trunk/highlevel/executive_python/src/office_nav.py (rev 0)
+++ pkg/trunk/highlevel/executive_python/src/office_nav.py 2009-06-16 07:39:29 UTC (rev 17139)
@@ -0,0 +1,100 @@
+#! /usr/bin/python
+#***********************************************************
+#* Software License Agreement (BSD License)
+#*
+#* Copyright (c) 2008, Willow Garage, Inc.
+#* All rights reserved.
+#*
+#* Redistribution and use in source and binary forms, with or without
+#* modification, are permitted provided that the following conditions
+#* are met:
+#*
+#* * Redistributions of source code must retain the above copyright
+#* notice, this list of conditions and the following disclaimer.
+#* * Redistributions in binary form must reproduce the above
+#* copyright notice, this list of conditions and the following
+#* disclaimer in the documentation and/or other materials provided
+#* with the distribution.
+#* * Neither the name of the Willow Garage nor the names of its
+#* contributors may be used to endorse or promote products derived
+#* from this software without specific prior written permission.
+#*
+#* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+#* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+#* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+#* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+#* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+#* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+#* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+#* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+#* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+#* POSSIBILITY OF SUCH DAMAGE.
+#*
+#* Author: Marius Muja (by changing one of Eitan's scripts)
+#***********************************************************
+import roslib
+roslib.load_manifest('executive_python')
+import rospy
+import random
+from std_msgs.msg import *
+from robot_msgs.msg import *
+from battery_monitor_adapter import *
+from recharge_adapter import *
+from navigation_adapter import *
+from offices_outside import offices
+
+class IndefiniteNav:
+ def __init__(self, navigator, cycle_time):
+ rospy.init_node("IndefiniteNav", anonymous=True)
+ self.navigator = navigator
+ self.cycle_time = cycle_time
+ self.state = "nav"
+ self.current_goal = None
+ rospy.Subscriber("office_goal", String, self.update_goal)
+
+ def update_goal(self, office):
+ self.current_goal = offices[office.data]
+ print "Going to office %s, pose: %r"%(office.data,self.current_goal)
+
+ def legalStates(self):
+ return self.navigator.legalState()
+
+ def doCycle(self):
+ #make sure that all adapters have legal states
+ if self.legalStates():
+ if self.state == "nav":
+ if self.current_goal != None:
+ self.navigator.sendGoal(self.current_goal, "map")
+ self.current_goal = None
+ print "nav --> nav"
+ else:
+ if not self.navigator.legalState():
+ print("Waiting on %s to be published" % (self.navigator.state_topic))
+ rospy.logout("Waiting on %s to be published" % (self.navigator.state_topic))
+
+ def run(self):
+ while not rospy.is_shutdown():
+ start = rospy.get_time()
+ self.doCycle()
+ end = rospy.get_time()
+ sleep_time = self.cycle_time - (end - start)
+ if sleep_time > 0:
+ rospy.sleep(sleep_time)
+ else:
+ print("IndefiniteNav missed cycle time of %.2f seconds" % (self.cycle_time))
+ rospy.logwarn("IndefiniteNav missed cycle time of %.2f seconds" % (self.cycle_time))
+
+if __name__ == '__main__':
+ try:
+ rospy.init_node("IndefiniteNav", anonymous=True)
+ navigator = NavigationAdapter(30, 300, "/move_base/feedback", "/move_base/activate")
+
+ indefinite_nav = IndefiniteNav( navigator, 1.0)
+ indefinite_nav.run()
+ except KeyboardInterrupt, e:
+ pass
+ print "exiting"
+
+
Added: pkg/trunk/highlevel/executive_python/src/offices.py
===================================================================
--- pkg/trunk/highlevel/executive_python/src/offices.py (rev 0)
+++ pkg/trunk/highlevel/executive_python/src/offices.py 2009-06-16 07:39:29 UTC (rev 17139)
@@ -0,0 +1,50 @@
+
+offices = {
+"104" : [[51.605206,3.733954,0.000000], [0.000000,0.000000,-0.715307,0.698810]],
+"103" : [[48.875404,3.630890,0.000000], [0.000000,0.000000,-0.833891,0.551930]],
+"102" : [[44.938145,3.667222,0.000000], [0.000000,0.000000,-0.619092,0.785319]],
+"175" : [[28.594784,3.721015,0.000000], [0.000000,0.000000,-0.652298,0.757962]],
+"174" : [[26.726603,3.994391,0.000000], [0.000000,0.000000,-0.782320,0.622876]],
+"168" : [[22.844109,4.028040,0.000000], [0.000000,0.000000,-0.672493,0.740103]],
+"167" : [[20.486879,3.661450,0.000000], [0.000000,0.000000,0.873661,-0.486535]],
+"166" : [[17.134949,4.410031,0.000000], [0.000000,0.000000,-0.824063,0.566498]],
+"165" : [[10.908689,3.947200,0.000000], [0.000000,0.000000,-0.533638,0.845713]],
+"164" : [[9.333915,3.689490,0.000000], [0.000000,0.000000,-0.743557,0.668672]],
+"163" : [[4.992692,4.125954,0.000000], [0.000000,0.000000,-0.666662,0.745360]],
+"105" : [[53.808624,10.193421,0.000000], [0.000000,0.000000,-0.038006,0.999277]],
+"106" : [[53.476215,13.930680,0.000000], [0.000000,0.000000,-0.038757,0.999249]],
+"107" : [[53.346909,15.432914,0.000000], [0.000000,0.000000,0.230206,0.973142]],
+"109" : [[53.234142,19.335232,0.000000], [0.000000,0.000000,0.183004,0.983112]],
+"126" : [[43.290310,39.799931,0.000000], [0.000000,0.000000,-0.694112,0.719867]],
+"128" : [[43.233105,42.859516,0.000000], [0.000000,0.000000,0.707369,0.706845]],
+"129" : [[41.731098,43.261425,0.000000], [0.000000,0.000000,0.729073,0.684436]],
+"124" : [[35.772007,39.501789,0.000000], [0.000000,0.000000,-0.680227,0.733002]],
+"130" : [[35.659512,43.037685,0.000000], [0.000000,0.000000,0.629002,0.777404]],
+"131" : [[34.139706,42.743374,0.000000], [0.000000,0.000000,0.811423,0.584459]],
+"123" : [[34.142185,39.390606,0.000000], [0.000000,0.000000,-0.787946,0.615744]],
+"132" : [[28.480865,42.684048,0.000000], [0.000000,0.000000,0.585062,0.810989]],
+"133" : [[26.722713,42.755974,0.000000], [0.000000,0.000000,0.858663,0.512541]],
+"134" : [[21.251219,42.989204,0.000000], [0.000000,0.000000,0.690361,0.723466]],
+"135" : [[19.695747,41.394066,0.000000], [0.000000,0.000000,0.769723,0.638378]],
+"136" : [[14.055100,41.499641,0.000000], [0.000000,0.000000,0.566501,0.824061]],
+"137" : [[12.425278,41.388458,0.000000], [0.000000,0.000000,0.776741,0.629821]],
+"138" : [[11.793990,37.174507,0.000000], [0.000000,0.000000,-0.840528,0.541768]],
+"141" : [[15.530274,36.737679,0.000000], [0.000000,0.000000,-0.840530,0.541765]],
+"142" : [[17.489958,36.555981,0.000000], [0.000000,0.000000,-0.610281,0.792185]],
+"145" : [[22.581688,35.790421,0.000000], [0.000000,0.000000,0.997026,0.077067]],
+"122" : [[25.802956,38.376186,0.000000], [0.000000,0.000000,0.383128,0.923695]],
+"119" : [[35.756752,34.831463,0.000000], [0.000000,0.000000,0.558771,0.829322]],
+"144" : [[21.922356,31.738045,0.000000], [0.000000,0.000000,0.720326,0.693636]],
+"143" : [[19.101978,31.864119,0.000000], [0.000000,0.000000,0.687494,0.726190]],
+"140" : [[14.999436,32.282341,0.000000], [0.000000,0.000000,0.689501,0.724284]],
+"139" : [[13.498852,30.760527,0.000000], [0.000000,0.000000,0.933248,0.359232]],
+"155" : [[12.916466,25.831690,0.000000], [0.000000,0.000000,0.997777,-0.066640]],
+"154" : [[18.011097,21.145405,0.000000], [0.000000,0.000000,0.694646,0.719352]],
+"156" : [[12.388138,22.093767,0.000000], [0.000000,0.000000,0.978877,0.204449]],
+"157" : [[12.590780,20.481661,0.000000], [0.000000,0.000000,0.983873,-0.178868]],
+"153" : [[23.646376,28.294998,0.000000], [0.000000,0.000000,-0.426538,0.904470]],
+"152" : [[23.594810,23.732992,0.000000], [0.000000,0.000000,-0.063758,0.997965]],
+"151" : [[23.231224,20.105125,0.000000], [0.000000,0.000000,0.020382,0.999792]],
+"172" : [[34.373741,11.606977,0.000000], [0.000000,0.000000,0.995451,-0.095273]],
+"116" : [[49.823780,39.326942,0.000000], [0.000000,0.000000,0.037360,0.999302]],
+}
\ No newline at end of file
Added: pkg/trunk/highlevel/executive_python/src/offices_outside.py
===================================================================
--- pkg/trunk/highlevel/executive_python/src/offices_outside.py (rev 0)
+++ pkg/trunk/highlevel/executive_python/src/offices_outside.py 2009-06-16 07:39:29 UTC (rev 17139)
@@ -0,0 +1,52 @@
+offices = {
+"116" : [[47.645042,39.301666,0.000000], [0.000000,0.000000,0.011167,0.999938]],
+"128" : [[43.007595,41.646896,0.000000], [0.000000,0.000000,0.636497,0.771279]],
+"129" : [[41.765484,41.551556,0.000000], [0.000000,0.000000,0.744354,0.667785]],
+"130" : [[35.474895,41.479755,0.000000], [0.000000,0.000000,0.678052,0.735014]],
+"131" : [[34.347229,41.324913,0.000000], [0.000000,0.000000,0.783277,0.621673]],
+"132" : [[28.055248,41.166645,0.000000], [0.000000,0.000000,0.627687,0.778466]],
+"133" : [[26.789402,41.388813,0.000000], [0.000000,0.000000,0.685009,0.728535]],
+"134" : [[21.178150,40.956543,0.000000], [0.000000,0.000000,0.701389,0.712779]],
+"135" : [[19.912821,39.420071,0.000000], [0.000000,0.000000,0.739759,0.672872]],
+"136" : [[13.600354,39.781071,0.000000], [0.000000,0.000000,0.608978,0.793187]],
+"137" : [[12.506639,39.942814,0.000000], [0.000000,0.000000,0.744353,0.667786]],
+"138" : [[12.523409,39.192963,0.000000], [0.000000,0.000000,0.878593,-0.477571]],
+"141" : [[16.267443,38.786781,0.000000], [0.000000,0.000000,-0.830534,0.556968]],
+"142" : [[17.189032,38.685467,0.000000], [0.000000,0.000000,-0.663615,0.748074]],
+"145" : [[24.556210,35.741623,0.000000], [0.000000,0.000000,0.999008,0.044522]],
+"126" : [[43.019070,41.354450,0.000000], [0.000000,0.000000,-0.640145,0.768255]],
+"125" : [[41.662514,41.318611,0.000000], [0.000000,0.000000,-0.724769,0.688992]],
+"124" : [[35.600815,41.127808,0.000000], [0.000000,0.000000,-0.666308,0.745676]],
+"123" : [[34.418709,41.175652,0.000000], [0.000000,0.000000,-0.786159,0.618024]],
+"122" : [[24.884800,36.773846,0.000000], [0.000000,0.000000,0.490929,0.871200]],
+"144" : [[21.653658,29.618299,0.000000], [0.000000,0.000000,0.649058,0.760739]],
+"143" : [[18.915342,29.229145,0.000000], [0.000000,0.000000,0.674031,0.738703]],
+"140" : [[14.834014,30.188524,0.000000], [0.000000,0.000000,0.701389,0.712779]],
+"139" : [[14.747484,30.189915,0.000000], [0.000000,0.000000,0.989200,0.146569]],
+"153" : [[21.417730,28.756445,0.000000], [0.000000,0.000000,-0.097749,0.995211]],
+"152" : [[21.536516,23.593950,0.000000], [0.000000,0.000000,0.037248,0.999306]],
+"151" : [[21.510569,20.192419,0.000000], [0.000000,0.000000,-0.026535,0.999648]],
+"156" : [[14.551426,21.601707,0.000000], [0.000000,0.000000,0.991962,0.126538]],
+"157" : [[14.502151,20.333977,0.000000], [0.000000,0.000000,0.999968,0.008041]],
+"155" : [[11.259951,25.027767,0.000000], [0.000000,0.000000,0.397017,0.917811]],
+"154" : [[18.210791,21.312208,0.000000], [0.000000,0.000000,0.728246,0.685316]],
+"120" : [[31.173508,34.394375,0.000000], [0.000000,0.000000,0.999857,-0.016921]],
+"119" : [[35.624691,33.111916,0.000000], [0.000000,0.000000,0.660870,0.750501]],
+"112" : [[51.581177,27.215223,0.000000], [0.000000,0.000000,0.140638,0.990061]],
+"111" : [[51.515133,26.697344,0.000000], [0.000000,0.000000,-0.100484,0.994939]],
+"109" : [[51.587952,18.681412,0.000000], [0.000000,0.000000,0.186044,0.982541]],
+"107" : [[51.737846,15.450032,0.000000], [0.000000,0.000000,0.074406,0.997228]],
+"106" : [[51.653229,13.779248,0.000000], [0.000000,0.000000,0.033494,0.999439]],
+"105" : [[51.714275,10.405149,0.000000], [0.000000,0.000000,-0.063289,0.997995]],
+"104" : [[51.385887,6.116450,0.000000], [0.000000,0.000000,-0.666611,0.745406]],
+"103" : [[48.933758,6.127062,0.000000], [0.000000,0.000000,-0.740219,0.672365]],
+"102" : [[44.482628,5.622054,0.000000], [0.000000,0.000000,-0.650698,0.759336]],
+"175" : [[28.355143,5.621984,0.000000], [0.000000,0.000000,-0.655249,0.755413]],
+"174" : [[26.965273,5.571383,0.000000], [0.000000,0.000000,-0.764219,0.644956]],
+"168" : [[23.126350,5.460148,0.000000], [0.000000,0.000000,-0.786590,0.617476]],
+"167" : [[20.646307,5.528869,0.000000], [0.000000,0.000000,-0.746857,0.664985]],
+"166" : [[17.188847,5.815120,0.000000], [0.000000,0.000000,-0.712779,0.701389]],
+"165" : [[10.698215,5.861859,0.000000], [0.000000,0.000000,-0.646863,0.762606]],
+"164" : [[9.425866,5.680513,0.000000], [0.000000,0.000000,-0.750501,0.660869]],
+"163" : [[4.786303,6.014607,0.000000], [0.000000,0.000000,-0.652456,0.757826]],
+}
Added: pkg/trunk/highlevel/executive_python/src/print_goal.py
===================================================================
--- pkg/trunk/highlevel/executive_python/src/print_goal.py (rev 0)
+++ pkg/trunk/highlevel/executive_python/src/print_goal.py 2009-06-16 07:39:29 UTC (rev 17139)
@@ -0,0 +1,68 @@
+#! /usr/bin/python
+
+#***********************************************************
+#* Software License Agreement (BSD License)
+#*
+#* Copyright (c) 2008, Willow Garage, Inc.
+#* All rights reserved.
+#*
+#* Redistribution and use in source and binary forms, with or without
+#* modification, are permitted provided that the following conditions
+#* are met:
+#*
+#* * Redistributions of source code must retain the above copyright
+#* notice, this list of conditions and the following disclaimer.
+#* * Redistributions in binary form must reproduce the above
+#* copyright notice, this list of conditions and the following
+#* disclaimer in the documentation and/or other materials provided
+#* with the distribution.
+#* * Neither the name of the Willow Garage nor the names of its
+#* contributors may be used to endorse or promote products derived
+#* from this software without specific prior written permission.
+#*
+#* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#* LIMITED TO, THE IMPLIED WARR...
[truncated message content] |