-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathvsfm_socket_util.py
153 lines (122 loc) · 4.82 KB
/
vsfm_socket_util.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
"""
@author: Nick Rhinehart
Carnegie Mellon University
Simple pythonic socket interface for
Visual Structure From Motion by
Changchang Wu
"""
from multiprocessing import Process
from collections import OrderedDict
import os, pdb
import time
import socket
import sys
import thread
import subprocess, signal
import type_util as typeu
import data.vsfm_ui as vsfm_ui
cur_dir = os.path.dirname(os.path.realpath(__file__))
# programmatically make functions based on py dictionary of commands
class VSFMCommander(object):
def __init__(self, socket):
self.functions = OrderedDict()
self.socket = socket
self.create_functions_from_dictionary(vsfm_ui.menu)
def __repr__(self):
s = 'VSFM Commander on socket {}. Function List:\n--\n'.format(self.socket.getsockname()[1])
for fn, (fid, _) in self.functions.items():
s += '{}(*args, **kwargs) ({})\n'.format(fn, fid)
return s
# create functions with prefixes depending on menu / dictionary hierarchy
def create_functions_from_dictionary(self, d, prefix = ''):
for k,v in d.items():
if isinstance(k, str) and k.find('menu') == 0:
self.create_functions_from_dictionary(v, prefix = '_'.join(k.split('_')[1:]) + '_')
else:
fid, func_name = k, prefix + v
assert(not hasattr(self, func_name))
func = self.create_single_function(fid, func_name)
setattr(self, func_name, func)
self.functions[func_name] = fid, func
# create functions that send commands over socket... these functions will return after
# sending the command
def create_single_function(self, fid, func_name):
def _(*args, **kwargs):
cmd = '{}{}{} {}\n'.format(fid,
'c' if 'control' in kwargs else '',
's' if 'shift' in kwargs else '',
args[0] if len(args) > 0 else '')
print "sending command over port {}: ({},{}".format(self.socket.getsockname()[1], func_name, cmd.strip())
self.socket.sendall(cmd)
return _
# main interface class
class VSFMInterface(object):
@typeu.member_initializer
def __init__(self,
vsfm_binary_fn = '/home/nrhineha/dev/vsfm/bin/VisualSFM',
port = None,
host = 'localhost'):
self.init()
def init(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if self.port is None:
tmp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tmp_sock.bind(('', 0))
self.port = tmp_sock.getsockname()[1]
tmp_sock.close()
del tmp_sock
print "will bind to port: {}".format(self.port)
self.vsfm_process = Process(target = self.start_program)
self.vsfm_process.start()
def handle_sigint(sig, frame):
self.close()
raise KeyboardInterrupt()
def handle_sigquit(sig, frame):
self.close()
sys.exit(0)
signal.signal(signal.SIGINT, handle_sigint)
signal.signal(signal.SIGQUIT, handle_sigquit)
for _ in range(10):
try:
self.sock.connect((self.host, self.port))
break
except:
time.sleep(0.1)
time.sleep(0.05)
self.commander = VSFMCommander(self.sock)
self.add_functions_from_commander()
self.create_overrides()
def restart(self):
try:
self.commander.file_exit_program()
except:
pass
try:
self.vsfm_process.join()
except:
pass
self.port = None
self.init()
def add_functions_from_commander(self):
for func_name, (fid, func) in self.commander.functions.items():
setattr(self, func_name, func)
# create overriding functions... e.g. dense_reconstruction requires a
# path but will fail silently if you don't pass one
def create_overrides(self):
def reconstruct_dense(path = 'dense_recon'):
path = os.path.abspath(path)
if not os.path.isdir(path):
os.mkdir(path)
fid, rd_func = self.commander.functions['sfm_reconstruct_dense']
rd_func(path)
setattr(self, 'sfm_reconstruct_dense', reconstruct_dense)
def start_program(self):
self.cmd = '{} listen+log {}'.format(self.vsfm_binary_fn, self.port)
self.args = self.cmd.split(' ')
self.vsfm_subprocess = subprocess.Popen(self.args)
def close(self):
self.commander.file_exit_program()
self.sock.close()