Skip to content

Commit

Permalink
Allow creating a task panel without being able to load segmentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
sammy-tri committed Mar 8, 2017
1 parent 1385206 commit 588f3c5
Show file tree
Hide file tree
Showing 13 changed files with 245 additions and 250 deletions.
4 changes: 3 additions & 1 deletion src/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ set(python_files
director/lcmgl.py
director/lcmobjectcollection.py
director/lcmoctomap.py
director/lcmcollections.py
director/lcmcollections.py
director/lcmspy.py
director/lcmUtils.py
director/mainwindowapp.py
Expand Down Expand Up @@ -154,6 +154,8 @@ set(python_files
director/macros/segmentation_view/perspective.py

director/tasks/__init__.py
director/tasks/basictasks.py
director/tasks/imagebasedaffordancefit.py
director/tasks/robottasks.py
director/tasks/taskmanagerwidget.py
director/tasks/taskuserpanel.py
Expand Down
2 changes: 1 addition & 1 deletion src/python/director/doordemo.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from director import planplayback
from director.footstepsdriver import FootstepRequestGenerator
from director.tasks.taskuserpanel import TaskUserPanel
from director.tasks.taskuserpanel import ImageBasedAffordanceFit
from director.tasks.imagebasedaffordancefit import ImageBasedAffordanceFit


import director.tasks.robottasks as rt
Expand Down
2 changes: 1 addition & 1 deletion src/python/director/drilldemo.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from director import vtkNumpy as vnp

from director.tasks.taskuserpanel import TaskUserPanel
from director.tasks.taskuserpanel import ImageBasedAffordanceFit
from director.tasks.imagebasedaffordancefit import ImageBasedAffordanceFit

import director.tasks.robottasks as rt
import director.tasks.taskmanagerwidget as tmw
Expand Down
1 change: 0 additions & 1 deletion src/python/director/polarisplatformplanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@


from director.tasks.taskuserpanel import TaskUserPanel
from director.tasks.taskuserpanel import ImageBasedAffordanceFit

import director.tasks.robottasks as rt
import director.tasks.taskmanagerwidget as tmw
Expand Down
6 changes: 1 addition & 5 deletions src/python/director/surprisetask.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from director import switchplanner

from director.tasks.taskuserpanel import TaskUserPanel
from director.tasks.taskuserpanel import ImageBasedAffordanceFit
from director.tasks.imagebasedaffordancefit import ImageBasedAffordanceFit

import director.tasks.robottasks as rt
import director.tasks.taskmanagerwidget as tmw
Expand Down Expand Up @@ -278,7 +278,3 @@ def fitSwitchBox(self):
self.fitter.imagePicker.numberOfPoints = 2
self.fitter.pointCloudSource = 'lidar'
self.fitter.fitFunc = self.fitter.fitSwitchBox




1 change: 0 additions & 1 deletion src/python/director/switchplanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
from director import vtkNumpy as vnp

from director.tasks.taskuserpanel import TaskUserPanel
from director.tasks.taskuserpanel import ImageBasedAffordanceFit

import director.tasks.robottasks as rt
import director.tasks.taskmanagerwidget as tmw
Expand Down
181 changes: 181 additions & 0 deletions src/python/director/tasks/basictasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import copy
import inspect
import re

from director import asynctaskqueue as atq
from director import propertyset
from director.simpletimer import SimpleTimer

from PythonQt import QtCore
from PythonQt import QtGui

def _splitCamelCase(name):
name = re.sub('(.)([A-Z][a-z]+)', r'\1 \2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1 \2', name)


class AsyncTask(object):
'''
AsyncTask documentation.
'''

def __init__(self, **kwargs):
self.statusMessage = ''
self.failReason = ''
self.properties = propertyset.PropertySet()
self.properties.addProperty('Name', _splitCamelCase(self.__class__.__name__).lower())

for cls in reversed(inspect.getmro(self.__class__)):
if hasattr(cls, 'getDefaultProperties'):
cls.getDefaultProperties(self.properties)

for name, value in kwargs.iteritems():
self.properties.setProperty(_splitCamelCase(name).capitalize(), value)


def __call__(self):
return self.run()

def stop(self):
pass

def run(self):
pass

def fail(self, reason):
self.failReason = reason
raise atq.AsyncTaskQueue.FailException(reason)

def copy(self):
return copy.deepcopy(self)


class PrintTask(AsyncTask):
'''
Name: Print Task
Short Description: prints a string
Description:
This task prints a message string.
'''

printFunction = None

@staticmethod
def getDefaultProperties(properties):
properties.addProperty('Message', '<empty message>')

def run(self):
if self.printFunction:
self.printFunction(self.properties.message)
else:
print self.properties.message


class CallbackTask(AsyncTask):

def __init__(self, callback=None, **kwargs):
AsyncTask.__init__(self, **kwargs)
self.callback = callback

def run(self):
if self.callback:
yield self.callback()


class ExceptionTask(AsyncTask):

def run(self):
raise Exception('Task exception')


class UserPromptTask(AsyncTask):

promptsEnabled = True
promptFunction = None


@staticmethod
def getDefaultProperties(properties):
properties.addProperty('Message', 'continue?')
properties.addProperty('Always', False)

def showUserPrompt(self):
if self.promptFunction:
self.promptFunction(self, self.properties.message)
else:
self.showDialog()

def showDialog(self):

self.d = QtGui.QDialog()

buttons = QtGui.QDialogButtonBox()
buttons.addButton('Yes', QtGui.QDialogButtonBox.AcceptRole)
buttons.addButton('No', QtGui.QDialogButtonBox.RejectRole)
buttons.connect('accepted()', self.d.accept)
buttons.connect('rejected()', self.d.reject)

l = QtGui.QVBoxLayout(self.d)
l.addWidget(QtGui.QLabel(self.properties.message))
l.addWidget(buttons)

self.d.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
self.d.show()
self.d.raise_()
self.d.connect('accepted()', self.accept)
self.d.connect('rejected()', self.reject)

def accept(self):
self.result = True

def reject(self):
self.result = False

def run(self):

if not self.promptsEnabled and not self.properties.getProperty('Always'):
return

self.result = None

self.showUserPrompt()

while self.result is None:
yield

if not self.result:
raise atq.AsyncTaskQueue.PauseException()


class DelayTask(AsyncTask):

@staticmethod
def getDefaultProperties(properties):
properties.addProperty('Delay time', 1.0, attributes=propertyset.PropertyAttributes(minimum=0.0, maximum=1e4, singleStep=0.1))

def run(self):

delayTime = self.properties.getProperty('Delay time')
t = SimpleTimer()

while True:

elapsed = t.elapsed()
if elapsed >= delayTime:
break

self.statusMessage = 'Waiting %.1f seconds' % (delayTime - elapsed)
yield


class PauseTask(AsyncTask):

def run(self):
raise atq.AsyncTaskQueue.PauseException()


class QuitTask(AsyncTask):

def run(self):
QtCore.QCoreApplication.instance().quit()
42 changes: 42 additions & 0 deletions src/python/director/tasks/imagebasedaffordancefit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from director import cameraview
from director.pointpicker import ImagePointPicker
from director import segmentation

class ImageBasedAffordanceFit(object):

def __init__(self, imageView=None, numberOfPoints=1):

self.imageView = imageView or cameraview.CameraImageView(cameraview.imageManager, self.getImageChannel(), 'image view')
self.imagePicker = ImagePointPicker(self.imageView, numberOfPoints=numberOfPoints)
self.imagePicker.connectDoubleClickEvent(self.onImageViewDoubleClick)
self.imagePicker.annotationFunc = self.onImageAnnotation
self.imagePicker.start()

self.pointCloudSource = 'lidar'
self.pickLineRadius = 0.05
self.pickNearestToCamera = True

def getImageChannel(self):
return 'CAMERA_LEFT'

def getPointCloud(self):
assert self.pointCloudSource in ('lidar', 'stereo')
if self.pointCloudSource == 'stereo':
return segmentation.getDisparityPointCloud(decimation=1, removeOutliers=False)
else:
return segmentation.getCurrentRevolutionData()

def onImageAnnotation(self, *points):
polyData = self.getPointCloud()
points = [self.getPointCloudLocationFromImage(p, self.imageView, polyData) for p in points]
self.fit(polyData, points)

def getPointCloudLocationFromImage(self, imagePixel, imageView, polyData):
cameraPos, ray = imageView.getWorldPositionAndRay(imagePixel)
return segmentation.extractPointsAlongClickRay(cameraPos, ray, polyData, distanceToLineThreshold=self.pickLineRadius, nearestToCamera=self.pickNearestToCamera)

def onImageViewDoubleClick(self, displayPoint, modifiers, imageView):
pass

def fit(self, pointData, points):
pass
Loading

0 comments on commit 588f3c5

Please sign in to comment.