Skip to content

Commit 9c036aa

Browse files
Merge branch '174-core-solver-add-ceres-solver' of https://github.com/david-cattermole/mayaMatchMoveSolver into 174-core-solver-add-ceres-solver
2 parents 247b0e0 + 2df15c6 commit 9c036aa

25 files changed

+314
-200
lines changed

docs/source/commands_solve.rst

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,27 @@ The command can be run in both MEL and Python.
1414

1515
Here is a table of command flags, as currently specified in the command.
1616

17-
======================== ========================================== ======================================================================= ==============
18-
Flag Type Description Default Value
19-
======================== ========================================== ======================================================================= ==============
20-
-camera (-c) string, string Camera transform and shape nodes None
21-
-marker (-m) string, string, string Marker, Camera, Bundle None
22-
-attr (-a) string, string, string, string, string Node attribute, min value, max value, offset and scale None
23-
-frame (-f) long int Frame number to solve with 1
24-
-attrStiffness (-asf) string, string, string, string Node attribute, weight plug name, variance plug name, value plug name. None
25-
-attrSmoothness (-asm) string, string, string, string Node attribute, weight plug name, variance plug name, value plug name. None
26-
-solverType (-st) unsigned int Type of solver to use. <auto detected>
27-
-sceneGraphMode (-sgm) unsigned int The Scene Graph used; 0=Maya DAG, 1=MM Scene Graph 0 (Maya DAG)
28-
-timeEvalMode (-tem) unsigned int How to evalulate values at different times, 0=DG Context 1=Set TIme 0 (DG Context)
29-
-iterations (-it) unsigned int Maximum number of iterations 20
30-
-tauFactor (-t) double Initial Damping Factor 1E-03
31-
-epsilon1 (-e1) double Acceptable gradient change 1E-06
32-
-epsilon2 (-e2) double Acceptable parameter change 1E-06
33-
-epsilon3 (-e3) double Acceptable error 1E-06
34-
-delta (-dt) double Change to the guessed parameters each iteration 1E-04
35-
-autoDiffType (-adt) unsigned int Auto-differencing type 0=forward 1=central 0 (forward)
36-
-verbose (-v) bool Prints more information False
37-
======================== ========================================== ======================================================================= ==============
17+
======================== ===================== ========================================== ======================================================================= ==============
18+
Command Flag Command Flag (short) Type Description Default Value
19+
======================== ===================== ========================================== ======================================================================= ==============
20+
-camera -c string, string Camera transform and shape nodes. None
21+
-marker -m string, string, string Marker, Camera, Bundle. None
22+
-attr -a string, string, string, string, string Node attribute, min value, max value, offset and scale. None
23+
-frame -f long int Frame number to solve with. 1
24+
-attrStiffness -asf string, string, string, string Node attribute, weight plug name, variance plug name, value plug name. None
25+
-attrSmoothness -asm string, string, string, string Node attribute, weight plug name, variance plug name, value plug name. None
26+
-solverType -st unsigned int Type of solver to use. <auto detected>
27+
-sceneGraphMode -sgm unsigned int The Scene Graph used; 0=Maya DAG, 1=MM Scene Graph. 0 (Maya DAG)
28+
-timeEvalMode -tem unsigned int How to evalulate values at different times, 0=DG Context 1=Set Time. 0 (DG Context)
29+
-iterations -it unsigned int Maximum number of iterations. 20
30+
-tauFactor -t double Initial Damping Factor. 1E-03
31+
-functionTolerance -ftl double Acceptable function change. 1E-06
32+
-parameterTolerance -ptl double Acceptable parameter change. 1E-06
33+
-gradientTolerance -gtl double Acceptable gradient error. 1E-06
34+
-delta -dt double Change to the guessed parameters each iteration. 1E-04
35+
-autoDiffType -adt unsigned int Auto-differencing type 0=forward 1=central. 0 (forward)
36+
-verbose -v bool Prints more information. False
37+
======================== ===================== ========================================== ======================================================================= ==============
3838

3939
Return
4040
------
@@ -102,7 +102,7 @@ Python Example:
102102
solvers = maya.cmds.mmSolverType(query=True, list=True)
103103
default_solver = maya.cmds.mmSolverType(query=True, default=True)
104104
105-
105+
106106
``mmSolverAffects`` Command
107107
+++++++++++++++++++++++++++
108108

python/mmSolver/_api/solverstep.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -680,17 +680,17 @@ def compile(self, col, mkr_list, attr_list, withtest=False):
680680
if tau_factor is not None:
681681
kwargs['tauFactor'] = tau_factor
682682

683-
gradient_error_factor = self.get_gradient_error_factor()
684-
if gradient_error_factor is not None:
685-
kwargs['epsilon1'] = gradient_error_factor
683+
function_error_factor = self.get_error_factor()
684+
if function_error_factor is not None:
685+
kwargs['function_tolerance'] = function_error_factor
686686

687687
parameter_error_factor = self.get_parameter_error_factor()
688688
if parameter_error_factor is not None:
689-
kwargs['epsilon2'] = parameter_error_factor
689+
kwargs['parameter_tolerance'] = parameter_error_factor
690690

691-
error_factor = self.get_error_factor()
692-
if error_factor is not None:
693-
kwargs['epsilon3'] = error_factor
691+
gradient_error_factor = self.get_gradient_error_factor()
692+
if gradient_error_factor is not None:
693+
kwargs['gradient_tolerance'] = gradient_error_factor
694694

695695
robust_loss_type = self.get_robust_loss_type()
696696
if robust_loss_type is not None:

python/mmSolver/tools/solver/constant.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -399,9 +399,6 @@
399399
(SOLVER_TYPE_CERES_LMDER_LABEL, SOLVER_TYPE_CERES_LMDER),
400400
]
401401

402-
# Hide the Solver Type mode in the UI.
403-
SOLVER_TYPE_WIDGET_VISIBLE = False
404-
405402
# Solver Scene Graph (stored on Collection node)
406403
SOLVER_TYPE_ATTR = 'solver_type'
407404
SOLVER_TYPE_ATTR_TYPE = 'long'
@@ -433,10 +430,6 @@
433430
(SCENE_GRAPH_MODE_MM_SCENE_GRAPH_LABEL, SCENE_GRAPH_MODE_MM_SCENE_GRAPH),
434431
]
435432

436-
# Hide the Scene Graph mode in the UI, the value defaults to 'auto',
437-
# which should do work out the fastest scene graph by default.
438-
SCENE_GRAPH_MODE_WIDGET_VISIBLE = False
439-
440433
# Solver Scene Graph (stored on Collection node)
441434
SOLVER_SCENE_GRAPH_MODE_ATTR = 'solver_scene_graph'
442435
SOLVER_SCENE_GRAPH_MODE_ATTR_TYPE = 'long'

python/mmSolver/tools/solver/widget/solver_basic_widget.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,19 @@
4141
import mmSolver.tools.solver.widget.ui_solver_basic_widget as ui_solver_basic_widget
4242
import mmSolver.tools.solver.widget.framerange_widget as framerange_widget
4343
import mmSolver.tools.solver.constant as const
44+
import mmSolver.tools.userpreferences.constant as userprefs_const
45+
import mmSolver.tools.userpreferences.lib as userprefs_lib
4446

4547
LOG = mmSolver.logger.get_logger()
4648

4749

50+
def get_user_prefs_solver_options_as_developer():
51+
config = userprefs_lib.get_config()
52+
key = userprefs_const.SOLVER_UI_SOLVER_OPTIONS_KEY
53+
value = userprefs_lib.get_value(config, key)
54+
return value == userprefs_const.SOLVER_UI_SOLVER_OPTIONS_DEVELOPER_VALUE
55+
56+
4857
def _populateWidgetsEnabled(widgets):
4958
col = lib_state.get_active_collection()
5059
enabled = col is not None
@@ -94,15 +103,19 @@ def __init__(self, parent=None, *args, **kwargs):
94103
self.frameRange_widget = BasicFrameRangeWidget(self)
95104
self.frameRange_layout.addWidget(self.frameRange_widget)
96105

106+
developer_options = get_user_prefs_solver_options_as_developer()
107+
scene_graph_mode_widget_visible = developer_options
108+
solver_type_widget_visible = developer_options
109+
97110
# Solver Type Combo Box.
98111
self.solverType_model = uimodels.StringDataListModel()
99112
self.solverType_model.setStringDataList(const.SOLVER_TYPE_LABEL_VALUE_LIST)
100113
self.solverType_comboBox.setModel(self.solverType_model)
101114
self.solverType_comboBox.currentIndexChanged.connect(
102115
self.solverTypeIndexChanged
103116
)
104-
self.solverType_comboBox.setVisible(const.SOLVER_TYPE_WIDGET_VISIBLE)
105-
self.solverType_label.setVisible(const.SOLVER_TYPE_WIDGET_VISIBLE)
117+
self.solverType_comboBox.setVisible(solver_type_widget_visible)
118+
self.solverType_label.setVisible(solver_type_widget_visible)
106119

107120
# Scene Graph Mode Combo Box.
108121
self.sceneGraphMode_model = uimodels.StringDataListModel()
@@ -113,8 +126,8 @@ def __init__(self, parent=None, *args, **kwargs):
113126
self.sceneGraphMode_comboBox.currentIndexChanged.connect(
114127
self.sceneGraphModeIndexChanged
115128
)
116-
self.sceneGraphMode_comboBox.setVisible(const.SCENE_GRAPH_MODE_WIDGET_VISIBLE)
117-
self.sceneGraphMode_label.setVisible(const.SCENE_GRAPH_MODE_WIDGET_VISIBLE)
129+
self.sceneGraphMode_comboBox.setVisible(scene_graph_mode_widget_visible)
130+
self.sceneGraphMode_label.setVisible(scene_graph_mode_widget_visible)
118131

119132
self.evalComplexGraphs_checkBox.toggled.connect(
120133
self.evalComplexGraphsValueToggled

python/mmSolver/tools/solver/widget/solver_camera_widget.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,20 @@
4242
import mmSolver.tools.solver.widget.framerange_widget as framerange_widget
4343
import mmSolver.tools.solver.widget.rootframe_widget as rootframe_widget
4444
import mmSolver.tools.solver.constant as const
45+
import mmSolver.tools.userpreferences.constant as userprefs_const
46+
import mmSolver.tools.userpreferences.lib as userprefs_lib
4547

4648

4749
LOG = mmSolver.logger.get_logger()
4850

4951

52+
def get_user_prefs_solver_options_as_developer():
53+
config = userprefs_lib.get_config()
54+
key = userprefs_const.SOLVER_UI_SOLVER_OPTIONS_KEY
55+
value = userprefs_lib.get_value(config, key)
56+
return value == userprefs_const.SOLVER_UI_SOLVER_OPTIONS_DEVELOPER_VALUE
57+
58+
5059
def _populateWidgetsEnabled(widgets):
5160
col = lib_state.get_active_collection()
5261
enabled = col is not None
@@ -147,15 +156,18 @@ def __init__(self, parent=None, *args, **kwargs):
147156
self.originFrame_spinBox.valueChanged.connect(self.originFrameValueChanged)
148157
self.sceneScale_doubleSpinBox.valueChanged.connect(self.sceneScaleValueChanged)
149158

159+
developer_options = get_user_prefs_solver_options_as_developer()
160+
solver_type_widget_visible = developer_options
161+
150162
# Solver Type Combo Box.
151163
self.solverType_model = uimodels.StringDataListModel()
152164
self.solverType_model.setStringDataList(const.SOLVER_TYPE_LABEL_VALUE_LIST)
153165
self.solverType_comboBox.setModel(self.solverType_model)
154166
self.solverType_comboBox.currentIndexChanged.connect(
155167
self.solverTypeIndexChanged
156168
)
157-
self.solverType_comboBox.setVisible(const.SOLVER_TYPE_WIDGET_VISIBLE)
158-
self.solverType_label.setVisible(const.SOLVER_TYPE_WIDGET_VISIBLE)
169+
self.solverType_comboBox.setVisible(solver_type_widget_visible)
170+
self.solverType_label.setVisible(solver_type_widget_visible)
159171

160172
self.solveFocalLength_checkBox.toggled.connect(
161173
self.solveFocalLengthValueToggled

python/mmSolver/tools/solver/widget/solver_standard_widget.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,20 @@
4242
import mmSolver.tools.solver.widget.framerange_widget as framerange_widget
4343
import mmSolver.tools.solver.widget.rootframe_widget as rootframe_widget
4444
import mmSolver.tools.solver.constant as const
45+
import mmSolver.tools.userpreferences.constant as userprefs_const
46+
import mmSolver.tools.userpreferences.lib as userprefs_lib
4547

4648

4749
LOG = mmSolver.logger.get_logger()
4850

4951

52+
def get_user_prefs_solver_options_as_developer():
53+
config = userprefs_lib.get_config()
54+
key = userprefs_const.SOLVER_UI_SOLVER_OPTIONS_KEY
55+
value = userprefs_lib.get_value(config, key)
56+
return value == userprefs_const.SOLVER_UI_SOLVER_OPTIONS_DEVELOPER_VALUE
57+
58+
5059
def _populateWidgetsEnabled(widgets):
5160
col = lib_state.get_active_collection()
5261
enabled = col is not None
@@ -148,15 +157,19 @@ def __init__(self, parent=None, *args, **kwargs):
148157
self.rootFrames_widget = StandardRootFrameWidget(self)
149158
self.rootFrames_layout.addWidget(self.rootFrames_widget)
150159

160+
developer_options = get_user_prefs_solver_options_as_developer()
161+
scene_graph_mode_widget_visible = developer_options
162+
solver_type_widget_visible = developer_options
163+
151164
# Solver Type Combo Box.
152165
self.solverType_model = uimodels.StringDataListModel()
153166
self.solverType_model.setStringDataList(const.SOLVER_TYPE_LABEL_VALUE_LIST)
154167
self.solverType_comboBox.setModel(self.solverType_model)
155168
self.solverType_comboBox.currentIndexChanged.connect(
156169
self.solverTypeIndexChanged
157170
)
158-
self.solverType_comboBox.setVisible(const.SOLVER_TYPE_WIDGET_VISIBLE)
159-
self.solverType_label.setVisible(const.SOLVER_TYPE_WIDGET_VISIBLE)
171+
self.solverType_comboBox.setVisible(solver_type_widget_visible)
172+
self.solverType_label.setVisible(solver_type_widget_visible)
160173

161174
# Scene Graph Mode Combo Box.
162175
self.sceneGraphMode_model = uimodels.StringDataListModel()
@@ -167,8 +180,8 @@ def __init__(self, parent=None, *args, **kwargs):
167180
self.sceneGraphMode_comboBox.currentIndexChanged.connect(
168181
self.sceneGraphModeIndexChanged
169182
)
170-
self.sceneGraphMode_comboBox.setVisible(const.SCENE_GRAPH_MODE_WIDGET_VISIBLE)
171-
self.sceneGraphMode_label.setVisible(const.SCENE_GRAPH_MODE_WIDGET_VISIBLE)
183+
self.sceneGraphMode_comboBox.setVisible(scene_graph_mode_widget_visible)
184+
self.sceneGraphMode_label.setVisible(scene_graph_mode_widget_visible)
172185

173186
self.globalSolve_checkBox.toggled.connect(self.globalSolveValueToggled)
174187
self.onlyRootFrames_checkBox.toggled.connect(self.onlyRootFramesValueToggled)

python/mmSolver/tools/userpreferences/constant.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,26 @@
208208
]
209209

210210

211+
# "Solver UI - Solver Options" preference.
212+
#
213+
# This allows developers or testing users to display and unlock other
214+
# solver options. "Default" should be used by normal users.
215+
SOLVER_UI_SOLVER_OPTIONS_KEY = 'solver_ui/solver_options'
216+
SOLVER_UI_SOLVER_OPTIONS_TYPE = TYPE_ENUMERATION_INT
217+
SOLVER_UI_SOLVER_OPTIONS_DEVELOPER_VALUE = 1
218+
SOLVER_UI_SOLVER_OPTIONS_DEVELOPER_LABEL = 'Developer'
219+
SOLVER_UI_SOLVER_OPTIONS_DEFAULT_VALUE = 0
220+
SOLVER_UI_SOLVER_OPTIONS_DEFAULT_LABEL = 'Default'
221+
SOLVER_UI_SOLVER_OPTIONS_VALUES = [
222+
SOLVER_UI_SOLVER_OPTIONS_DEVELOPER_VALUE,
223+
SOLVER_UI_SOLVER_OPTIONS_DEFAULT_VALUE,
224+
]
225+
SOLVER_UI_SOLVER_OPTIONS_LABELS = [
226+
SOLVER_UI_SOLVER_OPTIONS_DEVELOPER_LABEL,
227+
SOLVER_UI_SOLVER_OPTIONS_DEFAULT_LABEL,
228+
]
229+
230+
211231
# "Create Controller - Shape Node Type" preference.
212232
CREATE_CONTROLLER_SHAPE_KEY = 'create_controller/shape_node_type'
213233
CREATE_CONTROLLER_SHAPE_TYPE = TYPE_ENUMERATION_INT
@@ -234,6 +254,7 @@
234254
LOAD_MARKER_UI_USE_OVERSCAN_DEFAULT_KEY: LOAD_MARKER_UI_USE_OVERSCAN_DEFAULT_VALUES,
235255
LOAD_MARKER_UI_LOAD_BUNDLE_POSITIONS_DEFAULT_KEY: LOAD_MARKER_UI_LOAD_BUNDLE_POSITIONS_DEFAULT_VALUES,
236256
SOLVER_UI_MINIMAL_UI_WHILE_SOLVING_KEY: SOLVER_UI_MINIMAL_UI_WHILE_SOLVING_VALUES,
257+
SOLVER_UI_SOLVER_OPTIONS_KEY: SOLVER_UI_SOLVER_OPTIONS_VALUES,
237258
CREATE_CONTROLLER_SHAPE_KEY: CREATE_CONTROLLER_SHAPE_VALUES,
238259
}
239260

@@ -247,6 +268,7 @@
247268
LOAD_MARKER_UI_USE_OVERSCAN_DEFAULT_KEY: LOAD_MARKER_UI_USE_OVERSCAN_DEFAULT_LABELS,
248269
LOAD_MARKER_UI_LOAD_BUNDLE_POSITIONS_DEFAULT_KEY: LOAD_MARKER_UI_LOAD_BUNDLE_POSITIONS_DEFAULT_LABELS,
249270
SOLVER_UI_MINIMAL_UI_WHILE_SOLVING_KEY: SOLVER_UI_MINIMAL_UI_WHILE_SOLVING_LABELS,
271+
SOLVER_UI_SOLVER_OPTIONS_KEY: SOLVER_UI_SOLVER_OPTIONS_LABELS,
250272
CREATE_CONTROLLER_SHAPE_KEY: CREATE_CONTROLLER_SHAPE_LABELS,
251273
}
252274

@@ -260,6 +282,7 @@
260282
LOAD_MARKER_UI_USE_OVERSCAN_DEFAULT_KEY: LOAD_MARKER_UI_USE_OVERSCAN_DEFAULT_TRUE_VALUE,
261283
LOAD_MARKER_UI_LOAD_BUNDLE_POSITIONS_DEFAULT_KEY: LOAD_MARKER_UI_LOAD_BUNDLE_POSITIONS_DEFAULT_TRUE_VALUE,
262284
SOLVER_UI_MINIMAL_UI_WHILE_SOLVING_KEY: SOLVER_UI_MINIMAL_UI_WHILE_SOLVING_TRUE_VALUE,
285+
SOLVER_UI_SOLVER_OPTIONS_KEY: SOLVER_UI_SOLVER_OPTIONS_DEFAULT_VALUE,
263286
CREATE_CONTROLLER_SHAPE_KEY: CREATE_CONTROLLER_SHAPE_LOCATOR_VALUE,
264287
}
265288

@@ -273,6 +296,7 @@
273296
LOAD_MARKER_UI_USE_OVERSCAN_DEFAULT_KEY: LOAD_MARKER_UI_USE_OVERSCAN_DEFAULT_TYPE,
274297
LOAD_MARKER_UI_LOAD_BUNDLE_POSITIONS_DEFAULT_KEY: LOAD_MARKER_UI_LOAD_BUNDLE_POSITIONS_DEFAULT_TYPE,
275298
SOLVER_UI_MINIMAL_UI_WHILE_SOLVING_KEY: SOLVER_UI_MINIMAL_UI_WHILE_SOLVING_TYPE,
299+
SOLVER_UI_SOLVER_OPTIONS_KEY: SOLVER_UI_SOLVER_OPTIONS_TYPE,
276300
CREATE_CONTROLLER_SHAPE_KEY: CREATE_CONTROLLER_SHAPE_TYPE,
277301
}
278302

python/mmSolver/tools/userprefswindow/ui/pref_layout.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ def populateUI(self, config):
5959
self.updateAddNewMarkersToWidget(config)
6060
self.updateAddNewLinesToWidget(config)
6161
self.updateSolverUIMinimalUIWhileSolvingWidget(config)
62+
self.updateSolverUISolverOptionsWidget(config)
6263
self.updateLoadMarkerUIRenameMarkersDefaultWidget(config)
6364
self.updateLoadMarkerUIDistortionModeDefaultWidget(config)
6465
self.updateLoadMarkerUIUseOverscanDefaultWidget(config)
@@ -252,3 +253,20 @@ def getSolverUIMinimalUIWhileSolvingConfigValue(self):
252253
label = self.minimalUIWhileSolvingComboBox.currentText()
253254
value = userprefs_lib.get_value_from_label(key, label)
254255
return value
256+
257+
def updateSolverUISolverOptionsWidget(self, config):
258+
key = pref_const.SOLVER_UI_SOLVER_OPTIONS_KEY
259+
value = userprefs_lib.get_value(config, key)
260+
label = userprefs_lib.get_label_from_value(key, value)
261+
assert isinstance(label, pycompat.TEXT_TYPE)
262+
labels = userprefs_lib.get_labels(key)
263+
self.solverOptionsComboBox.clear()
264+
self.solverOptionsComboBox.addItems(labels)
265+
self.solverOptionsComboBox.setCurrentText(label)
266+
return
267+
268+
def getSolverUISolverOptionsConfigValue(self):
269+
key = pref_const.SOLVER_UI_SOLVER_OPTIONS_KEY
270+
label = self.solverOptionsComboBox.currentText()
271+
value = userprefs_lib.get_value_from_label(key, label)
272+
return value

0 commit comments

Comments
 (0)