Merged from branch 'branches/wrap_mods' into 'trunk'

release/4.3a0
Richard Roberts 2012-07-13 23:24:45 +00:00
commit c964bec14e
182 changed files with 4368 additions and 3284 deletions

327
.cproject
View File

@ -308,6 +308,14 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testGaussianFactor.run" path="linear/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testGaussianFactor.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="all" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
@ -334,7 +342,6 @@
</target>
<target name="tests/testBayesTree.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>tests/testBayesTree.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -342,7 +349,6 @@
</target>
<target name="testBinaryBayesNet.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testBinaryBayesNet.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -390,7 +396,6 @@
</target>
<target name="testSymbolicBayesNet.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testSymbolicBayesNet.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -398,7 +403,6 @@
</target>
<target name="tests/testSymbolicFactor.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>tests/testSymbolicFactor.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -406,7 +410,6 @@
</target>
<target name="testSymbolicFactorGraph.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testSymbolicFactorGraph.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -422,20 +425,11 @@
</target>
<target name="tests/testBayesTree" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>tests/testBayesTree</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testGaussianFactor.run" path="linear/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testGaussianFactor.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testPoseRTV.run" path="build/gtsam_unstable/dynamics" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
@ -524,22 +518,6 @@
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="tests/testPose2.run" path="build_retract/gtsam/geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>tests/testPose2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="tests/testPose3.run" path="build_retract/gtsam/geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>tests/testPose3.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="all" path="CppUnitLite" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
@ -556,6 +534,22 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="tests/testPose2.run" path="build_retract/gtsam/geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>tests/testPose2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="tests/testPose3.run" path="build_retract/gtsam/geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>tests/testPose3.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="all" path="spqr_mini" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
@ -580,26 +574,26 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="all" path="build_wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="testValues.run" path="build/gtsam/nonlinear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>all</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>testValues.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="check" path="build_wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="testOrdering.run" path="build/gtsam/nonlinear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>check</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>testOrdering.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clean" path="build_wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="testKey.run" path="build/gtsam/nonlinear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>clean</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>testKey.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
@ -684,26 +678,26 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testValues.run" path="build/gtsam/nonlinear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="all" path="build_wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>testValues.run</buildTarget>
<buildArguments>-j2</buildArguments>
<buildTarget>all</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testOrdering.run" path="build/gtsam/nonlinear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="check" path="build_wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>testOrdering.run</buildTarget>
<buildArguments>-j2</buildArguments>
<buildTarget>check</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testKey.run" path="build/gtsam/nonlinear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="clean" path="build_wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>testKey.run</buildTarget>
<buildArguments>-j2</buildArguments>
<buildTarget>clean</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
@ -958,7 +952,6 @@
</target>
<target name="testGraph.run" path="build/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testGraph.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -966,7 +959,6 @@
</target>
<target name="testJunctionTree.run" path="build/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testJunctionTree.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -974,7 +966,6 @@
</target>
<target name="testSymbolicBayesNetB.run" path="build/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testSymbolicBayesNetB.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -1110,7 +1101,6 @@
</target>
<target name="testErrors.run" path="linear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testErrors.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -1574,6 +1564,7 @@
</target>
<target name="testSimulated2DOriented.run" path="slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testSimulated2DOriented.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -1613,6 +1604,7 @@
</target>
<target name="testSimulated2D.run" path="slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testSimulated2D.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -1620,6 +1612,7 @@
</target>
<target name="testSimulated3D.run" path="slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>testSimulated3D.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -1835,6 +1828,7 @@
</target>
<target name="tests/testGaussianISAM2" path="build/slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>tests/testGaussianISAM2</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -1856,6 +1850,102 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testRot3.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testRot3.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testRot2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testRot2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testPose3.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testPose3.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="timeRot3.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>timeRot3.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testPose2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testPose2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testCal3_S2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testCal3_S2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testSimpleCamera.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testSimpleCamera.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testHomography2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testHomography2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testCalibratedCamera.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testCalibratedCamera.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="check" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>check</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clean" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>clean</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testPoint2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testPoint2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="install" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
@ -2057,7 +2147,6 @@
</target>
<target name="Generate DEB Package" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cpack</buildCommand>
<buildArguments/>
<buildTarget>-G DEB</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -2065,7 +2154,6 @@
</target>
<target name="Generate RPM Package" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cpack</buildCommand>
<buildArguments/>
<buildTarget>-G RPM</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -2073,7 +2161,6 @@
</target>
<target name="Generate TGZ Package" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cpack</buildCommand>
<buildArguments/>
<buildTarget>-G TGZ</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -2081,7 +2168,6 @@
</target>
<target name="Generate TGZ Source Package" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cpack</buildCommand>
<buildArguments/>
<buildTarget>--config CPackSourceConfig.cmake</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
@ -2207,98 +2293,34 @@
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testRot3.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="testSpirit.run" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testRot3.run</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>testSpirit.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testRot2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="testWrap.run" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testRot2.run</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>testWrap.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testPose3.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="check.wrap" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testPose3.run</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>check.wrap</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="timeRot3.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="wrap" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>timeRot3.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testPose2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testPose2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testCal3_S2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testCal3_S2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testSimpleCamera.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testSimpleCamera.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testHomography2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testHomography2.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testCalibratedCamera.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testCalibratedCamera.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="check" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>check</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clean" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>clean</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testPoint2.run" path="geometry" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j2</buildArguments>
<buildTarget>testPoint2.run</buildTarget>
<buildArguments>-j5</buildArguments>
<buildTarget>wrap</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
@ -2342,46 +2364,7 @@
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testSpirit.run" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>testSpirit.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="testWrap.run" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>testWrap.run</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="check.wrap" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>check.wrap</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="wrap_gtsam" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>wrap_gtsam</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="wrap" path="build/wrap" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments>-j5</buildArguments>
<buildTarget>wrap</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
</buildTargets>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
</cproject>

View File

@ -36,41 +36,47 @@ else()
set(GTSAM_UNSTABLE_AVAILABLE 0)
endif()
# Configurable Options
option(GTSAM_BUILD_TESTS "Enable/Disable building of tests" ON)
option(GTSAM_BUILD_TIMING "Enable/Disable building of timing scripts" ON)
option(GTSAM_BUILD_EXAMPLES "Enable/Disable building of examples" ON)
if(GTSAM_UNSTABLE_AVAILABLE)
option(GTSAM_BUILD_UNSTABLE "Enable/Disable libgtsam_unstable" OFF)
option(GTSAM_BUILD_UNSTABLE "Enable/Disable libgtsam_unstable" ON)
endif()
option(GTSAM_BUILD_WRAP "Enable/Disable building of matlab wrap utility (necessary for matlab interface)" ON)
if(MSVC)
option(GTSAM_BUILD_SHARED_LIBRARY "Enable/Disable building of a shared version of gtsam" OFF)
else()
if(NOT MSVC)
option(GTSAM_BUILD_SHARED_LIBRARY "Enable/Disable building of a shared version of gtsam" ON)
endif()
option(GTSAM_BUILD_STATIC_LIBRARY "Enable/Disable building of a static version of gtsam" ON)
option(GTSAM_USE_QUATERNIONS "Enable/Disable using an internal Quaternion representation for rotations instead of rotation matrices" OFF)
if(MSVC)
option(GTSAM_BUILD_CONVENIENCE_LIBRARIES "Enable/Disable use of convenience libraries for faster development rebuilds, but slower install" OFF)
option(GTSAM_BUILD_STATIC_LIBRARY "Enable/Disable building of a static version of gtsam" ON)
else()
set(GTSAM_BUILD_STATIC_LIBRARY ON)
endif()
option(GTSAM_USE_QUATERNIONS "Enable/Disable using an internal Quaternion representation for rotations instead of rotation matrices" OFF)
if(NOT MSVC)
option(GTSAM_BUILD_CONVENIENCE_LIBRARIES "Enable/Disable use of convenience libraries for faster development rebuilds, but slower install" ON)
endif()
option(GTSAM_INSTALL_MATLAB_TOOLBOX "Enable/Disable installation of matlab toolbox" ON)
option(GTSAM_INSTALL_MATLAB_EXAMPLES "Enable/Disable installation of matlab examples" ON)
option(GTSAM_INSTALL_MATLAB_TESTS "Enable/Disable installation of matlab tests" ON)
option(GTSAM_INSTALL_WRAP "Enable/Disable installation of wrap utility" ON)
set(GTSAM_TOOLBOX_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/borg/toolbox CACHE DOCSTRING "Path to install matlab toolbox")
set(GTSAM_WRAP_HEADER_PATH ${PROJECT_SOURCE_DIR}/wrap CACHE DOCSTRING "Path to directory of matlab.h")
# Options relating to MATLAB wrapper
# TODO: Check for matlab mex binary before handling building of binaries
option(GTSAM_INSTALL_MATLAB_TOOLBOX "Enable/Disable installation of matlab toolbox" ON)
option(GTSAM_BUILD_WRAP "Enable/Disable building of matlab wrap utility (necessary for matlab interface)" ON)
option(GTSAM_INSTALL_WRAP "Enable/Disable installation of wrap utility for wrapping other libraries" ON)
set(GTSAM_TOOLBOX_INSTALL_PATH "" CACHE DOCSTRING "Matlab toolbox destination, blank defaults to CMAKE_INSTALL_PREFIX/borg/toolbox")
set(GTSAM_BUILD_MEX_BINARY_FLAGS "" CACHE STRING "Extra flags for running Matlab MEX compilation")
set(MEX_COMMAND "mex" CACHE FILEPATH "Command to use for executing mex (if on path, 'mex' will work)")
# Check / set dependent variables for MATLAB wrapper
set(GTSAM_WRAP_HEADER_PATH "${PROJECT_SOURCE_DIR}/wrap")
if(GTSAM_INSTALL_MATLAB_TOOLBOX AND NOT GTSAM_BUILD_WRAP)
message(FATAL_ERROR "GTSAM_INSTALL_MATLAB_TOOLBOX is enabled, please also enable GTSAM_BUILD_WRAP")
endif()
if(GTSAM_INSTALL_WRAP AND NOT GTSAM_BUILD_WRAP)
message(FATAL_ERROR "GTSAM_INSTALL_WRAP is enabled, please also enable GTSAM_BUILD_WRAP")
endif()
if(NOT GTSAM_TOOLBOX_INSTALL_PATH)
set(GTSAM_TOOLBOX_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/borg/toolbox")
endif()
# Flags for building/installing mex files
option(GTSAM_BUILD_MEX_BIN "Enable/Disable building of matlab mex files" OFF)
option(GTSAM_INSTALL_MEX_BIN "Enable/Disable installing matlab mex binaries" OFF)
set(GTSAM_BUILD_MEX_BINARY_FLAGS "" CACHE STRING "Flags for running Matlab MEX compilation")
set(MEX_COMMAND "mex" CACHE STRING "Command to use for executing mex (if on path, 'mex' will work)")
# Flags for choosing default packaging tools
set(CPACK_SOURCE_GENERATOR "TGZ" CACHE STRING "CPack Default Source Generator")
@ -90,7 +96,7 @@ endif(GTSAM_USE_QUATERNIONS)
# Flags to determine whether tests and examples are build during 'make install'
# Note that these remove the targets from the 'all'
option(GTSAM_DISABLE_TESTS_ON_INSTALL "Disables building tests during install" ON)
option(GTSAM_DISABLE_EXAMPLES_ON_INSTALL "Disables buildint examples during install" OFF)
option(GTSAM_DISABLE_EXAMPLES_ON_INSTALL "Disables building examples during install" OFF)
# Pull in infrastructure
if (GTSAM_BUILD_TESTS)
@ -103,7 +109,8 @@ endif()
if(CYGWIN OR MSVC OR WIN32)
set(Boost_USE_STATIC_LIBS 1)
endif()
find_package(Boost 1.43 COMPONENTS serialization REQUIRED)
find_package(Boost 1.43 COMPONENTS serialization system filesystem thread date_time REQUIRED)
set(GTSAM_BOOST_LIBRARIES ${Boost_SERIALIZATION_LIBRARY})
# General build settings
include_directories(
@ -134,7 +141,9 @@ if (GTSAM_BUILD_EXAMPLES)
endif(GTSAM_BUILD_EXAMPLES)
# Matlab toolbox
add_subdirectory(matlab)
if (GTSAM_INSTALL_MATLAB_TOOLBOX)
add_subdirectory(matlab)
endif()
# Build gtsam_unstable
if (GTSAM_BUILD_UNSTABLE)
@ -168,11 +177,12 @@ message(STATUS "Build flags ")
print_config_flag(${GTSAM_BUILD_TIMING} "Build Timing scripts ")
print_config_flag(${GTSAM_BUILD_EXAMPLES} "Build Examples ")
print_config_flag(${GTSAM_BUILD_TESTS} "Build Tests ")
print_config_flag(${GTSAM_BUILD_WRAP} "Build Wrap ")
print_config_flag(${GTSAM_BUILD_SHARED_LIBRARY} "Build shared GTSAM Library ")
print_config_flag(${GTSAM_BUILD_STATIC_LIBRARY} "Build static GTSAM Library ")
if(NOT MSVC)
print_config_flag(${GTSAM_BUILD_SHARED_LIBRARY} "Build shared GTSAM Library ")
print_config_flag(${GTSAM_BUILD_STATIC_LIBRARY} "Build static GTSAM Library ")
print_config_flag(${GTSAM_BUILD_CONVENIENCE_LIBRARIES} "Build Convenience Libraries ")
endif()
print_config_flag(${GTSAM_BUILD_TYPE_POSTFIXES} "Put build-type in library name ")
print_config_flag(${GTSAM_BUILD_CONVENIENCE_LIBRARIES} "Build Convenience Libraries ")
if(GTSAM_UNSTABLE_AVAILABLE)
print_config_flag(${GTSAM_BUILD_UNSTABLE} "Build libgtsam_unstable ")
endif()
@ -192,11 +202,8 @@ print_config_flag(${GTSAM_USE_QUATERNIONS} "Quaternions as default R
message(STATUS "MATLAB toolbox flags ")
print_config_flag(${GTSAM_INSTALL_MATLAB_TOOLBOX} "Install matlab toolbox ")
print_config_flag(${GTSAM_INSTALL_MATLAB_EXAMPLES} "Install matlab examples ")
print_config_flag(${GTSAM_INSTALL_MATLAB_TESTS} "Install matlab tests ")
print_config_flag(${GTSAM_BUILD_WRAP} "Build Wrap ")
print_config_flag(${GTSAM_INSTALL_WRAP} "Install wrap utility ")
print_config_flag(${GTSAM_BUILD_MEX_BIN} "Build MEX binaries ")
print_config_flag(${GTSAM_INSTALL_MEX_BIN} "Install MEX binaries ")
message(STATUS "===============================================================")
# Include CPack *after* all flags

252
gtsam.h
View File

@ -6,19 +6,26 @@
*
* Requirements:
* Classes must start with an uppercase letter
* Only one Method/Constructor per line
* - Can wrap a typedef
* Only one Method/Constructor per line, though methods/constructors can extend across multiple lines
* Methods can return
* - Eigen types: Matrix, Vector
* - C/C++ basic types: string, bool, size_t, size_t, double, char, unsigned char
* - void
* - Any class with which be copied with boost::make_shared()
* - boost::shared_ptr of any object type
* Limitations on methods
* - Parsing does not support overloading
* - There can only be one method (static or otherwise) with a given name
* Constructors
* - Overloads are supported
* - A class with no constructors can be returned from other functions but not allocated directly in MATLAB
* Methods
* - Constness has no effect
* Methods must start with a lowercase letter
* Static methods must start with a letter (upper or lowercase) and use the "static" keyword
* - Specify by-value (not reference) return types, even if C++ method returns reference
* - Must start with a lowercase letter
* - Overloads are supported
* Static methods
* - Must start with a letter (upper or lowercase) and use the "static" keyword
* - The first letter will be made uppercase in the generated MATLAB interface
* - Overloads are supported
* Arguments to functions any of
* - Eigen types: Matrix, Vector
* - Eigen types and classes as an optionally const reference
@ -35,7 +42,7 @@
* Namespace usage
* - Namespaces can be specified for classes in arguments and return values
* - In each case, the namespace must be fully specified, e.g., "namespace1::namespace2::ClassName"
* Using namespace
* Using namespace: FIXME: this functionality is currently broken
* - To use a namespace (e.g., generate a "using namespace x" line in cpp files), add "using namespace x;"
* - This declaration applies to all classes *after* the declaration, regardless of brackets
* Includes in C++ wrappers
@ -44,17 +51,34 @@
* - To override, add a full include statement just before the class statement
* - An override include can be added for a namespace by placing it just before the namespace statement
* - Both classes and namespace accept exactly one namespace
* Overriding type dependency checks
* Using classes defined in other modules
* - If you are using a class 'OtherClass' not wrapped in this definition file, add "class OtherClass;" to avoid a dependency error
* - Limitation: this only works if the class does not need a namespace specification
* Virtual inheritance
* - Specify fully-qualified base classes, i.e. "virtual class Derived : module::Base {"
* - Mark with 'virtual' keyword, e.g. "virtual class Base {", and also "virtual class Derived : module::Base {"
* - Forward declarations must also be marked virtual, e.g. "virtual class module::Base;" and
* also "virtual class module::Derived;"
* - Pure virtual (abstract) classes should list no constructors in this interface file
* - Virtual classes must have a clone() function in C++ (though it does not have to be included
* in the MATLAB interface). clone() will be called whenever an object copy is needed, instead
* of using the copy constructor (which is used for non-virtual objects).
* Templates
* - Basic templates are supported either with an explicit list of types to instantiate,
* e.g. template<T = {gtsam::Pose2, gtsam::Rot2, gtsam::Point3}> class Class1 { ... };
* or with typedefs, e.g.
* template<T, U> class Class2 { ... };
* typedef Class2<Type1, Type2> MyInstantiatedClass;
* - To create new instantiations in other modules, you must copy-and-paste the whole class definition
* into the new module, but use only your new instantiation types.
* - When forward-declaring template instantiations, use the generated/typedefed name, e.g.
* class gtsam::Class1Pose2;
* class gtsam::MyInstantiatedClass;
*/
/**
* Status:
* - TODO: global functions
* - TODO: default values for arguments
* - TODO: overloaded functions
* - TODO: signatures for constructors can be ambiguous if two types have the same first letter
* - TODO: Handle gtsam::Rot3M conversions to quaternions
*/
@ -64,7 +88,17 @@ namespace gtsam {
// base
//*************************************************************************
class LieVector {
virtual class Value {
// No constructors because this is an abstract class
// Testable
void print(string s) const;
// Manifold
size_t dim() const;
};
virtual class LieVector : gtsam::Value {
// Standard constructors
LieVector();
LieVector(Vector v);
@ -96,7 +130,7 @@ class LieVector {
// geometry
//*************************************************************************
class Point2 {
virtual class Point2 : gtsam::Value {
// Standard Constructors
Point2();
Point2(double x, double y);
@ -128,7 +162,7 @@ class Point2 {
Vector vector() const;
};
class StereoPoint2 {
virtual class StereoPoint2 : gtsam::Value {
// Standard Constructors
StereoPoint2();
StereoPoint2(double uL, double uR, double v);
@ -157,7 +191,7 @@ class StereoPoint2 {
Vector vector() const;
};
class Point3 {
virtual class Point3 : gtsam::Value {
// Standard Constructors
Point3();
Point3(double x, double y, double z);
@ -190,7 +224,7 @@ class Point3 {
double z() const;
};
class Rot2 {
virtual class Rot2 : gtsam::Value {
// Standard Constructors and Named Constructors
Rot2();
Rot2(double theta);
@ -232,14 +266,14 @@ class Rot2 {
Matrix matrix() const;
};
class Rot3 {
virtual class Rot3 : gtsam::Value {
// Standard Constructors and Named Constructors
Rot3();
Rot3(Matrix R);
static gtsam::Rot3 Rx(double t);
static gtsam::Rot3 Ry(double t);
static gtsam::Rot3 Rz(double t);
// static gtsam::Rot3 RzRyRx(double x, double y, double z); // FIXME: overloaded functions don't work yet
static gtsam::Rot3 RzRyRx(double x, double y, double z); // FIXME: overloaded functions don't work yet
static gtsam::Rot3 RzRyRx(Vector xyz);
static gtsam::Rot3 yaw(double t); // positive yaw is to right (as in aircraft heading)
static gtsam::Rot3 pitch(double t); // positive pitch is up (increasing aircraft altitude)
@ -261,7 +295,7 @@ class Rot3 {
// Manifold
static size_t Dim();
size_t dim() const;
// gtsam::Rot3 retractCayley(Vector v) const; // FIXME, does not exist in both Matrix and Quaternion options
gtsam::Rot3 retractCayley(Vector v) const; // FIXME, does not exist in both Matrix and Quaternion options
gtsam::Rot3 retract(Vector v) const;
Vector localCoordinates(const gtsam::Rot3& p) const;
@ -284,7 +318,7 @@ class Rot3 {
// Vector toQuaternion() const; // FIXME: Can't cast to Vector properly
};
class Pose2 {
virtual class Pose2 : gtsam::Value {
// Standard Constructor
Pose2();
Pose2(double x, double y, double theta);
@ -330,12 +364,12 @@ class Pose2 {
Matrix matrix() const;
};
class Pose3 {
virtual class Pose3 : gtsam::Value {
// Standard Constructors
Pose3();
Pose3(const gtsam::Pose3& pose);
Pose3(const gtsam::Rot3& r, const gtsam::Point3& t);
// Pose3(const gtsam::Pose2& pose2); // FIXME: shadows Pose3(Pose3 pose)
Pose3(const gtsam::Pose2& pose2); // FIXME: shadows Pose3(Pose3 pose)
Pose3(Matrix t);
// Testable
@ -373,19 +407,20 @@ class Pose3 {
double y() const;
double z() const;
Matrix matrix() const;
// gtsam::Pose3 transform_to(const gtsam::Pose3& pose) const; // FIXME: shadows other transform_to()
gtsam::Pose3 transform_to(const gtsam::Pose3& pose) const; // FIXME: shadows other transform_to()
double range(const gtsam::Point3& point);
// double range(const gtsam::Pose3& pose); // FIXME: shadows other range
double range(const gtsam::Pose3& pose);
};
class Cal3_S2 {
virtual class Cal3_S2 : gtsam::Value {
// Standard Constructors
Cal3_S2();
Cal3_S2(double fx, double fy, double s, double u0, double v0);
Cal3_S2(Vector v);
// Testable
void print(string s) const;
bool equals(const gtsam::Cal3_S2& pose, double tol) const;
bool equals(const gtsam::Cal3_S2& rhs, double tol) const;
// Manifold
static size_t Dim();
@ -409,6 +444,37 @@ class Cal3_S2 {
Matrix matrix_inverse() const;
};
virtual class Cal3DS2 : gtsam::Value {
// Standard Constructors
Cal3DS2();
Cal3DS2(double fx, double fy, double s, double u0, double v0, double k1, double k2, double k3, double k4);
Cal3DS2(Vector v);
// Testable
void print(string s) const;
bool equals(const gtsam::Cal3DS2& rhs, double tol) const;
// Manifold
static size_t Dim();
size_t dim() const;
gtsam::Cal3DS2 retract(Vector v) const;
Vector localCoordinates(const gtsam::Cal3DS2& c) const;
// Action on Point2
gtsam::Point2 uncalibrate(const gtsam::Point2& p) const;
// TODO: D2d functions that start with an uppercase letter
// Standard Interface
double fx() const;
double fy() const;
double skew() const;
double px() const;
double py() const;
Vector vector() const;
Vector k() const;
//Matrix K() const; //FIXME: Uppercase
};
class Cal3_S2Stereo {
// Standard Constructors
Cal3_S2Stereo();
@ -428,7 +494,7 @@ class Cal3_S2Stereo {
double baseline() const;
};
class CalibratedCamera {
virtual class CalibratedCamera : gtsam::Value {
// Standard Constructors and Named Constructors
CalibratedCamera();
CalibratedCamera(const gtsam::Pose3& pose);
@ -458,14 +524,14 @@ class CalibratedCamera {
double range(const gtsam::Point3& p) const; // TODO: Other overloaded range methods
};
class SimpleCamera {
virtual class SimpleCamera : gtsam::Value {
// Standard Constructors and Named Constructors
SimpleCamera();
SimpleCamera(const gtsam::Pose3& pose);
SimpleCamera(const gtsam::Pose3& pose, const gtsam::Cal3_S2& K);
static gtsam::SimpleCamera level(const gtsam::Cal3_S2& K,
const gtsam::Pose2& pose, double height);
// static gtsam::SimpleCamera level(const gtsam::Pose2& pose, double height); // FIXME overload
static gtsam::SimpleCamera level(const gtsam::Pose2& pose, double height); // FIXME overload
static gtsam::SimpleCamera lookat(const gtsam::Point3& eye,
const gtsam::Point3& target, const gtsam::Point3& upVector,
const gtsam::Cal3_S2& K);
@ -490,7 +556,7 @@ class SimpleCamera {
gtsam::Point2 project(const gtsam::Point3& point);
gtsam::Point3 backproject(const gtsam::Point2& p, double depth) const;
double range(const gtsam::Point3& point);
// double range(const gtsam::Pose3& point); // FIXME, overload
double range(const gtsam::Pose3& point); // FIXME, overload
};
//*************************************************************************
@ -679,17 +745,17 @@ class VariableIndex {
#include <gtsam/linear/NoiseModel.h>
namespace noiseModel {
class Base {
virtual class Base {
};
class Gaussian {
virtual class Gaussian : gtsam::noiseModel::Base {
static gtsam::noiseModel::Gaussian* SqrtInformation(Matrix R);
static gtsam::noiseModel::Gaussian* Covariance(Matrix R);
// Matrix R() const; // FIXME: cannot parse!!!
void print(string s) const;
};
class Diagonal {
virtual class Diagonal : gtsam::noiseModel::Gaussian {
static gtsam::noiseModel::Diagonal* Sigmas(Vector sigmas);
static gtsam::noiseModel::Diagonal* Variances(Vector variances);
static gtsam::noiseModel::Diagonal* Precisions(Vector precisions);
@ -697,14 +763,14 @@ class Diagonal {
void print(string s) const;
};
class Isotropic {
virtual class Isotropic : gtsam::noiseModel::Diagonal {
static gtsam::noiseModel::Isotropic* Sigma(size_t dim, double sigma);
static gtsam::noiseModel::Isotropic* Variance(size_t dim, double varianace);
static gtsam::noiseModel::Isotropic* Precision(size_t dim, double precision);
void print(string s) const;
};
class Unit {
virtual class Unit : gtsam::noiseModel::Isotropic {
static gtsam::noiseModel::Unit* Create(size_t dim);
void print(string s) const;
};
@ -759,7 +825,7 @@ class GaussianBayesNet {
void push_front(gtsam::GaussianConditional* conditional);
};
class GaussianFactor {
virtual class GaussianFactor {
void print(string s) const;
bool equals(const gtsam::GaussianFactor& lf, double tol) const;
double error(const gtsam::VectorValues& c) const;
@ -767,7 +833,7 @@ class GaussianFactor {
size_t size() const;
};
class JacobianFactor {
virtual class JacobianFactor : gtsam::GaussianFactor {
JacobianFactor();
JacobianFactor(Vector b_in);
JacobianFactor(size_t i1, Matrix A1, Vector b,
@ -787,7 +853,7 @@ class JacobianFactor {
gtsam::GaussianFactor* negate() const;
};
class HessianFactor {
virtual class HessianFactor : gtsam::GaussianFactor {
HessianFactor(const gtsam::HessianFactor& gf);
HessianFactor();
HessianFactor(size_t j, Matrix G, Vector g, double f);
@ -811,22 +877,19 @@ class GaussianFactorGraph {
GaussianFactorGraph(const gtsam::GaussianBayesNet& CBN);
// From FactorGraph
void push_back(gtsam::GaussianFactor* factor);
void print(string s) const;
bool equals(const gtsam::GaussianFactorGraph& lfgraph, double tol) const;
size_t size() const;
gtsam::GaussianFactor* at(size_t idx) const;
// Building the graph
void add(gtsam::JacobianFactor* factor);
// all these won't work as MATLAB can't handle overloading
// void add(Vector b);
// void add(size_t key1, Matrix A1, Vector b, const gtsam::SharedDiagonal& model);
// void add(size_t key1, Matrix A1, size_t key2, Matrix A2, Vector b,
// const gtsam::SharedDiagonal& model);
// void add(size_t key1, Matrix A1, size_t key2, Matrix A2, size_t key3, Matrix A3,
// Vector b, const gtsam::SharedDiagonal& model);
// void add(gtsam::HessianFactor* factor);
void push_back(gtsam::GaussianFactor* factor);
void add(Vector b);
void add(size_t key1, Matrix A1, Vector b, const gtsam::noiseModel::Diagonal* model);
void add(size_t key1, Matrix A1, size_t key2, Matrix A2, Vector b,
const gtsam::noiseModel::Diagonal* model);
void add(size_t key1, Matrix A1, size_t key2, Matrix A2, size_t key3, Matrix A3,
Vector b, const gtsam::noiseModel::Diagonal* model);
// error and probability
double error(const gtsam::VectorValues& c) const;
@ -909,29 +972,55 @@ class Ordering {
void insert(size_t key, size_t order);
void push_back(size_t key);
void permuteWithInverse(const gtsam::Permutation& inversePermutation);
// FIXME: Wrap InvertedMap as well
//InvertedMap invert() const;
gtsam::InvertedOrdering invert() const;
};
#include <gtsam/nonlinear/Ordering.h>
class InvertedOrdering {
InvertedOrdering();
// FIXME: add bracket operator overload
bool empty() const;
size_t size() const;
bool count(size_t index) const; // Use as a boolean function with implicit cast
void clear();
};
class NonlinearFactorGraph {
NonlinearFactorGraph();
void print(string s) const;
double error(const gtsam::Values& c) const;
double probPrime(const gtsam::Values& c) const;
gtsam::NonlinearFactor* at(size_t i) const;
void add(const gtsam::NonlinearFactor* factor);
gtsam::Ordering* orderingCOLAMD(const gtsam::Values& c) const;
// Ordering* orderingCOLAMDConstrained(const gtsam::Values& c, const std::map<gtsam::Key,int>& constraints) const;
gtsam::GaussianFactorGraph* linearize(const gtsam::Values& c, const gtsam::Ordering& ordering) const;
gtsam::NonlinearFactorGraph clone() const;
};
class NonlinearFactor {
// NonlinearFactor(); // FIXME: don't use this - creates an abstract class
virtual class NonlinearFactor {
void print(string s) const;
void equals(const gtsam::NonlinearFactor& other, double tol) const;
gtsam::KeyVector keys() const;
size_t size() const;
size_t dim() const; // FIXME: Doesn't link
size_t dim() const;
double error(const gtsam::Values& c) const;
bool active(const gtsam::Values& c) const;
gtsam::GaussianFactor* linearize(const gtsam::Values& c, const gtsam::Ordering& ordering) const;
gtsam::NonlinearFactor* clone() const;
// gtsam::NonlinearFactor* rekey(const gtsam::KeyVector& newKeys) const; //FIXME: Conversion from KeyVector to std::vector does not happen
};
class Values {
Values();
size_t size() const;
void print(string s) const;
void insert(size_t j, const gtsam::Value& value);
bool exists(size_t j) const;
gtsam::Value at(size_t j) const;
};
// Actually a FastList<Key>
@ -1012,13 +1101,13 @@ class LevenbergMarquardtParams {
LevenbergMarquardtParams();
void print(string s) const;
double getMaxIterations() const;
size_t getMaxIterations() const;
double getRelativeErrorTol() const;
double getAbsoluteErrorTol() const;
double getErrorTol() const;
string getVerbosity() const;
void setMaxIterations(double value);
void setMaxIterations(size_t value);
void setRelativeErrorTol(double value);
void setAbsoluteErrorTol(double value);
void setErrorTol(double value);
@ -1040,6 +1129,59 @@ class LevenbergMarquardtParams {
void setVerbosityLM(string s);
};
//*************************************************************************
// Nonlinear factor types
//*************************************************************************
template<T = {gtsam::LieVector, gtsam::Point2, gtsam::StereoPoint2, gtsam::Point3, gtsam::Rot2, gtsam::Rot3, gtsam::Pose2, gtsam::Pose3, gtsam::Cal3_S2, gtsam::CalibratedCamera, gtsam::SimpleCamera}>
virtual class PriorFactor : gtsam::NonlinearFactor {
PriorFactor(size_t key, const T& prior, const gtsam::noiseModel::Base* noiseModel);
};
template<T = {gtsam::LieVector, gtsam::Point2, gtsam::Point3, gtsam::Rot2, gtsam::Rot3, gtsam::Pose2, gtsam::Pose3}>
virtual class BetweenFactor : gtsam::NonlinearFactor {
BetweenFactor(size_t key1, size_t key2, const T& relativePose, const gtsam::noiseModel::Base* noiseModel);
};
template<T = {gtsam::LieVector, gtsam::Point2, gtsam::StereoPoint2, gtsam::Point3, gtsam::Rot2, gtsam::Rot3, gtsam::Pose2, gtsam::Pose3, gtsam::Cal3_S2, gtsam::CalibratedCamera, gtsam::SimpleCamera}>
virtual class NonlinearEquality : gtsam::NonlinearFactor {
// Constructor - forces exact evaluation
NonlinearEquality(size_t j, const T& feasible);
// Constructor - allows inexact evaluation
NonlinearEquality(size_t j, const T& feasible, double error_gain);
};
template<POSE, POINT>
virtual class RangeFactor : gtsam::NonlinearFactor {
RangeFactor(size_t key1, size_t key2, double measured, const gtsam::noiseModel::Base* noiseModel);
};
typedef gtsam::RangeFactor<gtsam::Pose2, gtsam::Point2> RangeFactor2D;
typedef gtsam::RangeFactor<gtsam::Pose3, gtsam::Point3> RangeFactor3D;
typedef gtsam::RangeFactor<gtsam::CalibratedCamera, gtsam::Point3> RangeFactorCalibratedCamera;
typedef gtsam::RangeFactor<gtsam::SimpleCamera, gtsam::Point3> RangeFactorSimpleCamera;
template<POSE, POINT, ROT>
virtual class BearingFactor : gtsam::NonlinearFactor {
BearingFactor(size_t key1, size_t key2, const ROT& measured, const gtsam::noiseModel::Base* noiseModel);
};
typedef gtsam::BearingFactor<gtsam::Pose2, gtsam::Point2, gtsam::Rot2> BearingFactor2D;
#include <ProjectionFactor.h>
template<POSE, LANDMARK, CALIBRATION>
virtual class GenericProjectionFactor : gtsam::NonlinearFactor {
GenericProjectionFactor(const gtsam::Point2& measured, const gtsam::noiseModel::Base* noiseModel,
size_t poseKey, size_t pointKey, const CALIBRATION* k);
gtsam::Point2 measured() const;
CALIBRATION* calibration() const;
};
typedef gtsam::GenericProjectionFactor<gtsam::Pose3, gtsam::Point3, gtsam::Cal3_S2> GenericProjectionFactorCal3_S2;
typedef gtsam::GenericProjectionFactor<gtsam::Pose3, gtsam::Point3, gtsam::Cal3DS2> GenericProjectionFactorCal3DS2;
}///\namespace gtsam
//*************************************************************************

View File

@ -95,9 +95,6 @@ if (GTSAM_BUILD_STATIC_LIBRARY)
list(APPEND GTSAM_EXPORTED_TARGETS gtsam-static)
set(GTSAM_EXPORTED_TARGETS "${GTSAM_EXPORTED_TARGETS}" PARENT_SCOPE)
set(gtsam-lib gtsam-static)
if(NOT GTSAM_BUILD_SHARED_LIBRARY)
set(gtsam-prefer-shared gtsam-static)
endif()
endif (GTSAM_BUILD_STATIC_LIBRARY)
if (GTSAM_BUILD_SHARED_LIBRARY)
@ -115,34 +112,23 @@ if (GTSAM_BUILD_SHARED_LIBRARY)
if (NOT GTSAM_BUILD_STATIC_LIBRARY)
set(gtsam-lib "gtsam-shared")
endif()
set(gtsam-prefer-shared gtsam-shared)
endif(GTSAM_BUILD_SHARED_LIBRARY)
# Create the matlab toolbox for the gtsam library
if (GTSAM_BUILD_WRAP)
if (GTSAM_INSTALL_MATLAB_TOOLBOX)
# Set up codegen
include(GtsamMatlabWrap)
# TODO: generate these includes programmatically
# Choose include flags depending on build process
if (GTSAM_BUILD_MEX_BIN)
set(MEX_INCLUDE_ROOT ${GTSAM_SOURCE_ROOT_DIR})
set(MEX_LIB_ROOT ${CMAKE_BINARY_DIR})
set(GTSAM_LIB_DIR ${MEX_LIB_ROOT}/gtsam)
else()
set(MEX_INCLUDE_ROOT ${CMAKE_INSTALL_PREFIX}/include)
set(MEX_LIB_ROOT ${CMAKE_INSTALL_PREFIX}/lib)
set(GTSAM_LIB_DIR ${MEX_LIB_ROOT})
endif()
set(MEX_INCLUDE_ROOT ${GTSAM_SOURCE_ROOT_DIR})
set(MEX_LIB_ROOT ${CMAKE_BINARY_DIR})
set(GTSAM_LIB_DIR ${MEX_LIB_ROOT}/gtsam)
# Generate, build and install toolbox
string(TOUPPER ${CMAKE_BUILD_TYPE} build_type_toupper)
get_target_property(gtsam_library_file ${gtsam-prefer-shared} LOCATION_${build_type_toupper})
set(mexFlags "${GTSAM_BUILD_MEX_BINARY_FLAGS} -I${Boost_INCLUDE_DIR} -I${MEX_INCLUDE_ROOT} -I${MEX_INCLUDE_ROOT}/gtsam -I${MEX_INCLUDE_ROOT}/gtsam/base -I${MEX_INCLUDE_ROOT}/gtsam/geometry -I${MEX_INCLUDE_ROOT}/gtsam/linear -I${MEX_INCLUDE_ROOT}/gtsam/discrete -I${MEX_INCLUDE_ROOT}/gtsam/inference -I${MEX_INCLUDE_ROOT}/gtsam/nonlinear -I${MEX_INCLUDE_ROOT}/gtsam/slam ${gtsam_library_file}")
# Lots of escapes '\' here because they get eaten during subsequent calls to 'set'
set(mexFlags "${mexFlags} -g COMPFLAGS=\\\"$$COMPFLAGS ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${build_type_toupper}}\\\"")
set(mexFlags ${GTSAM_BUILD_MEX_BINARY_FLAGS} -I${Boost_INCLUDE_DIR} -I${MEX_INCLUDE_ROOT} -I${MEX_INCLUDE_ROOT}/gtsam -I${MEX_INCLUDE_ROOT}/gtsam/base -I${MEX_INCLUDE_ROOT}/gtsam/geometry -I${MEX_INCLUDE_ROOT}/gtsam/linear -I${MEX_INCLUDE_ROOT}/gtsam/discrete -I${MEX_INCLUDE_ROOT}/gtsam/inference -I${MEX_INCLUDE_ROOT}/gtsam/nonlinear -I${MEX_INCLUDE_ROOT}/gtsam/slam)
# Macro to handle details of setting up targets
# FIXME: issue with dependency between wrap_gtsam and wrap_gtsam_build, only shows up on CMake 2.8.3
wrap_library(gtsam "${mexFlags}" "../")
wrap_library(gtsam "${mexFlags}" "../" "")
endif ()

View File

@ -16,7 +16,7 @@
*/
#pragma once
#include <boost/make_shared.hpp>
#include <boost/pool/singleton_pool.hpp>
#include <gtsam/base/Value.h>
@ -37,7 +37,8 @@ public:
/**
* Create a duplicate object returned as a pointer to the generic Value interface.
* For the sake of performance, this function use singleton pool allocator instead of the normal heap allocator
* For the sake of performance, this function use singleton pool allocator instead of the normal heap allocator.
* The result must be deleted with Value::deallocate_, not with the 'delete' operator.
*/
virtual Value* clone_() const {
void *place = boost::singleton_pool<PoolTag, sizeof(DERIVED)>::malloc();
@ -53,6 +54,13 @@ public:
boost::singleton_pool<PoolTag, sizeof(DERIVED)>::free((void*)this);
}
/**
* Clone this value (normal clone on the heap, delete with 'delete' operator)
*/
virtual boost::shared_ptr<Value> clone() const {
return boost::make_shared<DERIVED>(static_cast<const DERIVED&>(*this));
}
/// equals implementing generic Value interface
virtual bool equals_(const Value& p, double tol = 1e-9) const {
// Cast the base class Value pointer to a derived class pointer

View File

@ -101,12 +101,15 @@ namespace gtsam {
class Value {
public:
/** Allocate and construct a clone of this value */
/** Clone this value in a special memory pool, must be deleted with Value::deallocate_, *not* with the 'delete' operator. */
virtual Value* clone_() const = 0;
/** Deallocate a raw pointer of this value */
virtual void deallocate_() const = 0;
/** Clone this value (normal clone on the heap, delete with 'delete' operator) */
virtual boost::shared_ptr<Value> clone() const = 0;
/** Compare this Value with another for equality. */
virtual bool equals_(const Value& other, double tol = 1e-9) const = 0;

View File

@ -83,32 +83,32 @@ namespace gtsam {
push_back(fg);
}
/** Add a Jacobian factor */
void add(const boost::shared_ptr<JacobianFactor>& factor) {
factors_.push_back(boost::shared_ptr<GaussianFactor>(factor));
/** Add a factor by value - makes a copy */
void add(const GaussianFactor& factor) {
factors_.push_back(factor.clone());
}
/** Add a Hessian factor */
void add(const boost::shared_ptr<HessianFactor>& factor) {
factors_.push_back(boost::shared_ptr<GaussianFactor>(factor));
/** Add a factor by pointer - stores pointer without copying the factor */
void add(const sharedFactor& factor) {
factors_.push_back(factor);
}
/** Add a null factor */
void add(const Vector& b) {
add(JacobianFactor::shared_ptr(new JacobianFactor(b)));
add(JacobianFactor(b));
}
/** Add a unary factor */
void add(Index key1, const Matrix& A1,
const Vector& b, const SharedDiagonal& model) {
add(JacobianFactor::shared_ptr(new JacobianFactor(key1,A1,b,model)));
add(JacobianFactor(key1,A1,b,model));
}
/** Add a binary factor */
void add(Index key1, const Matrix& A1,
Index key2, const Matrix& A2,
const Vector& b, const SharedDiagonal& model) {
add(JacobianFactor::shared_ptr(new JacobianFactor(key1,A1,key2,A2,b,model)));
add(JacobianFactor(key1,A1,key2,A2,b,model));
}
/** Add a ternary factor */
@ -116,13 +116,13 @@ namespace gtsam {
Index key2, const Matrix& A2,
Index key3, const Matrix& A3,
const Vector& b, const SharedDiagonal& model) {
add(JacobianFactor::shared_ptr(new JacobianFactor(key1,A1,key2,A2,key3,A3,b,model)));
add(JacobianFactor(key1,A1,key2,A2,key3,A3,b,model));
}
/** Add an n-ary factor */
void add(const std::vector<std::pair<Index, Matrix> > &terms,
const Vector &b, const SharedDiagonal& model) {
add(JacobianFactor::shared_ptr(new JacobianFactor(terms,b,model)));
add(JacobianFactor(terms,b,model));
}
/**

View File

@ -17,6 +17,8 @@
* @author Frank Dellaert
*/
#pragma once
#include <gtsam/linear/GaussianDensity.h>
#include <gtsam/linear/NoiseModel.h>

View File

@ -419,7 +419,7 @@ namespace gtsam {
maps_.reserve(maps_.size() + dimensions.size());
BOOST_FOREACH(size_t dim, dimensions) {
maps_.push_back(values_.segment(varStart, dim));
varStart += dim; // varStart is continued from first for loop
varStart += (int)dim; // varStart is continued from first for loop
}
}

View File

@ -55,9 +55,14 @@ namespace gtsam {
/** Unnormalized probability. O(n) */
double probPrime(const Values& c) const;
template<class F>
void add(const F& factor) {
this->push_back(boost::shared_ptr<F>(new F(factor)));
/// Add a factor by value - copies the factor object
void add(const NonlinearFactor& factor) {
this->push_back(factor.clone());
}
/// Add a factor by pointer - stores pointer without copying factor object
void add(const sharedFactor& factor) {
this->push_back(factor);
}
/**

View File

@ -45,23 +45,23 @@ public:
Verbosity verbosity; ///< The printing verbosity during optimization (default SILENT)
NonlinearOptimizerParams() :
maxIterations(100.0), relativeErrorTol(1e-5), absoluteErrorTol(1e-5),
maxIterations(100), relativeErrorTol(1e-5), absoluteErrorTol(1e-5),
errorTol(0.0), verbosity(SILENT) {}
virtual ~NonlinearOptimizerParams() {}
virtual void print(const std::string& str = "") const ;
inline double getMaxIterations() const { return maxIterations; }
inline double getRelativeErrorTol() const { return relativeErrorTol; }
inline double getAbsoluteErrorTol() const { return absoluteErrorTol; }
inline double getErrorTol() const { return errorTol; }
inline std::string getVerbosity() const { return verbosityTranslator(verbosity); }
size_t getMaxIterations() const { return maxIterations; }
double getRelativeErrorTol() const { return relativeErrorTol; }
double getAbsoluteErrorTol() const { return absoluteErrorTol; }
double getErrorTol() const { return errorTol; }
std::string getVerbosity() const { return verbosityTranslator(verbosity); }
inline void setMaxIterations(double value) { maxIterations = value; }
inline void setRelativeErrorTol(double value) { relativeErrorTol = value; }
inline void setAbsoluteErrorTol(double value) { absoluteErrorTol = value; }
inline void setErrorTol(double value) { errorTol = value ; }
inline void setVerbosity(const std::string &src) { verbosity = verbosityTranslator(src); }
void setMaxIterations(size_t value) { maxIterations = value; }
void setRelativeErrorTol(double value) { relativeErrorTol = value; }
void setAbsoluteErrorTol(double value) { absoluteErrorTol = value; }
void setErrorTol(double value) { errorTol = value ; }
void setVerbosity(const std::string &src) { verbosity = verbosityTranslator(src); }
Verbosity verbosityTranslator(const std::string &s) const;
std::string verbosityTranslator(Verbosity value) const;

View File

@ -155,7 +155,7 @@ public:
iterator end() { return order_.end(); }
/// Test if the key exists in the ordering.
bool exists(Key key) const { return order_.count(key); }
bool exists(Key key) const { return order_.count(key) > 0; }
///TODO: comment
std::pair<iterator,bool> tryInsert(Key key, Index order) { return tryInsert(std::make_pair(key,order)); }
@ -233,7 +233,10 @@ private:
ar & BOOST_SERIALIZATION_NVP(order_);
ar & BOOST_SERIALIZATION_NVP(nVars_);
}
};
}; // \class Ordering
// typedef for use with matlab
typedef Ordering::InvertedMap InvertedOrdering;
/**
* @class Unordered

View File

@ -25,12 +25,12 @@ namespace gtsam {
/**
* Binary factor for a bearing measurement
*/
template<class POSE, class POINT>
template<class POSE, class POINT, class ROT = typename POSE::Rotation>
class BearingFactor: public NoiseModelFactor2<POSE, POINT> {
private:
typedef POSE Pose;
typedef typename Pose::Rotation Rot;
typedef ROT Rot;
typedef POINT Point;
typedef BearingFactor<POSE, POINT> This;

View File

@ -62,7 +62,7 @@ namespace gtsam {
* @param K shared pointer to the constant calibration
*/
GenericProjectionFactor(const Point2& measured, const SharedNoiseModel& model,
const Key poseKey, Key pointKey, const shared_ptrK& K) :
Key poseKey, Key pointKey, const boost::shared_ptr<CALIBRATION>& K) :
Base(model, poseKey, pointKey), measured_(measured), K_(K) {
}

View File

@ -15,10 +15,12 @@ add_custom_target(check.unstable COMMAND ${CMAKE_CTEST_COMMAND} --output-on-fail
foreach(subdir ${gtsam_unstable_subdirs})
# Build convenience libraries
file(GLOB subdir_srcs "${subdir}/*.cpp")
set(${subdir}_srcs ${subdir_srcs})
file(GLOB subdir_headers "${subdir}/*.h")
set(${subdir}_srcs ${subdir_srcs} ${subdir_headers})
gtsam_assign_source_folders("${${subdir}_srcs}") # Create MSVC structure
if (subdir_srcs AND GTSAM_BUILD_CONVENIENCE_LIBRARIES)
message(STATUS "Building Convenience Library: ${subdir}_unstable")
add_library("${subdir}_unstable" STATIC ${subdir_srcs})
add_library("${subdir}_unstable" STATIC ${${subdir}_srcs})
endif()
# Build local library and tests
@ -36,7 +38,9 @@ set(gtsam_unstable_srcs
${slam_srcs}
)
option (GTSAM_UNSTABLE_BUILD_SHARED_LIBRARY "Enable/Disable building of a shared version of gtsam_unstable" ON)
if(NOT MSVC)
option (GTSAM_UNSTABLE_BUILD_SHARED_LIBRARY "Enable/Disable building of a shared version of gtsam_unstable" ON)
endif()
# Versions - same as core gtsam library
set(gtsam_unstable_version ${GTSAM_VERSION_MAJOR}.${GTSAM_VERSION_MINOR}.${GTSAM_VERSION_PATCH})
@ -73,28 +77,21 @@ if (GTSAM_UNSTABLE_BUILD_SHARED_LIBRARY)
endif(GTSAM_UNSTABLE_BUILD_SHARED_LIBRARY)
# Wrap version for gtsam_unstable
if (GTSAM_BUILD_WRAP)
if (GTSAM_INSTALL_MATLAB_TOOLBOX)
# Set up codegen
include(GtsamMatlabWrap)
# TODO: generate these includes programmatically
# Choose include flags depending on build process
if (GTSAM_BUILD_MEX_BIN)
set(MEX_INCLUDE_ROOT ${GTSAM_SOURCE_ROOT_DIR})
set(MEX_LIB_ROOT ${CMAKE_BINARY_DIR})
set(GTSAM_LIB_DIR ${MEX_LIB_ROOT}/gtsam)
set(GTSAM_UNSTABLE_LIB_DIR ${MEX_LIB_ROOT}/gtsam_unstable)
else()
set(MEX_INCLUDE_ROOT ${CMAKE_INSTALL_PREFIX}/include)
set(MEX_LIB_ROOT ${CMAKE_INSTALL_PREFIX}/lib)
set(GTSAM_LIB_DIR ${MEX_LIB_ROOT})
set(GTSAM_UNSTABLE_LIB_DIR ${MEX_LIB_ROOT})
endif()
set(MEX_INCLUDE_ROOT ${GTSAM_SOURCE_ROOT_DIR})
set(MEX_LIB_ROOT ${CMAKE_BINARY_DIR})
set(GTSAM_LIB_DIR ${MEX_LIB_ROOT}/gtsam)
set(GTSAM_UNSTABLE_LIB_DIR ${MEX_LIB_ROOT}/gtsam_unstable)
# Generate, build and install toolbox
set(mexFlags "-I${Boost_INCLUDE_DIR} -I${MEX_INCLUDE_ROOT} -I${MEX_INCLUDE_ROOT}/gtsam_unstable -I${MEX_INCLUDE_ROOT}/gtsam_unstable/dynamics -I${MEX_INCLUDE_ROOT}/gtsam_unstable/discrete -L${GTSAM_UNSTABLE_LIB_DIR} -L${GTSAM_LIB_DIR} -lgtsam -lgtsam_unstable")
set(mexFlags -I${Boost_INCLUDE_DIR} -I${MEX_INCLUDE_ROOT} -I${MEX_INCLUDE_ROOT}/gtsam_unstable -I${MEX_INCLUDE_ROOT}/gtsam_unstable/dynamics -I${MEX_INCLUDE_ROOT}/gtsam_unstable/discrete)
# Macro to handle details of setting up targets
wrap_library(gtsam_unstable "${mexFlags}" "./")
wrap_library(gtsam_unstable "${mexFlags}" "./" gtsam)
endif(GTSAM_BUILD_WRAP)
endif(GTSAM_INSTALL_MATLAB_TOOLBOX)

View File

@ -77,8 +77,6 @@ public:
const Vector& gyro() const { return gyro_; }
const Vector& accel() const { return accel_; }
Vector z() const { return concatVectors(2, &accel_, &gyro_); }
const Key& key1() const { return this->key1_; }
const Key& key2() const { return this->key2_; }
/**
* Error evaluation with optional derivatives - calculates

View File

@ -70,8 +70,6 @@ public:
const Vector& gyro() const { return gyro_; }
const Vector& accel() const { return accel_; }
Vector z() const { return concatVectors(2, &accel_, &gyro_); }
const Key& key1() const { return this->key1_; }
const Key& key2() const { return this->key2_; }
/**
* Error evaluation with optional derivatives - calculates

View File

@ -3,10 +3,12 @@
*/
// specify the classes from gtsam we are using
class gtsam::Point3;
class gtsam::Rot3;
class gtsam::Pose3;
class gtsam::SharedNoiseModel;
virtual class gtsam::Value;
virtual class gtsam::Point3;
virtual class gtsam::Rot3;
virtual class gtsam::Pose3;
virtual class gtsam::noiseModel::Base;
virtual class gtsam::NonlinearFactor;
namespace gtsam {
@ -18,7 +20,7 @@ class Dummy {
};
#include <gtsam_unstable/dynamics/PoseRTV.h>
class PoseRTV {
virtual class PoseRTV : gtsam::Value {
PoseRTV();
PoseRTV(Vector rtv);
PoseRTV(const gtsam::Point3& pt, const gtsam::Rot3& rot, const gtsam::Point3& vel);
@ -66,6 +68,107 @@ class PoseRTV {
Vector translationIntegrationVec(const gtsam::PoseRTV& x2, double dt) const;
};
// Nonlinear factors from gtsam, for our Value types
#include <gtsam/slam/PriorFactor.h>
template<T = {gtsam::PoseRTV}>
virtual class PriorFactor : gtsam::NonlinearFactor {
PriorFactor(size_t key, const T& prior, const gtsam::noiseModel::Base* noiseModel);
};
#include <gtsam/slam/BetweenFactor.h>
template<T = {gtsam::PoseRTV}>
virtual class BetweenFactor : gtsam::NonlinearFactor {
BetweenFactor(size_t key1, size_t key2, const T& relativePose, const gtsam::noiseModel::Base* noiseModel);
};
#include <gtsam/slam/RangeFactor.h>
template<POSE, POINT>
virtual class RangeFactor : gtsam::NonlinearFactor {
RangeFactor(size_t key1, size_t key2, double measured, const gtsam::noiseModel::Base* noiseModel);
};
typedef gtsam::RangeFactor<gtsam::PoseRTV, gtsam::PoseRTV> RangeFactorRTV;
#include <gtsam/nonlinear/NonlinearEquality.h>
template<T = {gtsam::PoseRTV}>
virtual class NonlinearEquality : gtsam::NonlinearFactor {
// Constructor - forces exact evaluation
NonlinearEquality(size_t j, const T& feasible);
// Constructor - allows inexact evaluation
NonlinearEquality(size_t j, const T& feasible, double error_gain);
};
template<POSE = {gtsam::PoseRTV}>
virtual class IMUFactor : gtsam::NonlinearFactor {
/** Standard constructor */
IMUFactor(Vector accel, Vector gyro,
double dt, size_t key1, size_t key2, const gtsam::noiseModel::Base* model);
/** Full IMU vector specification */
IMUFactor(Vector imu_vector,
double dt, size_t key1, size_t key2, const gtsam::noiseModel::Base* model);
Vector gyro() const;
Vector accel() const;
Vector z() const;
size_t key1() const;
size_t key2() const;
};
template<POSE = {gtsam::PoseRTV}>
virtual class FullIMUFactor : gtsam::NonlinearFactor {
/** Standard constructor */
FullIMUFactor(Vector accel, Vector gyro,
double dt, size_t key1, size_t key2, const gtsam::noiseModel::Base* model);
/** Single IMU vector - imu = [accel, gyro] */
FullIMUFactor(Vector imu,
double dt, size_t key1, size_t key2, const gtsam::noiseModel::Base* model);
Vector gyro() const;
Vector accel() const;
Vector z() const;
size_t key1() const;
size_t key2() const;
};
#include <DynamicsPriors.h>
virtual class DHeightPrior : gtsam::NonlinearFactor {
DHeightPrior(size_t key, double height, const gtsam::noiseModel::Base* model);
};
#include <DynamicsPriors.h>
virtual class DRollPrior : gtsam::NonlinearFactor {
/** allows for explicit roll parameterization - uses canonical coordinate */
DRollPrior(size_t key, double wx, const gtsam::noiseModel::Base* model);
/** Forces roll to zero */
DRollPrior(size_t key, const gtsam::noiseModel::Base* model);
};
#include <DynamicsPriors.h>
virtual class VelocityPrior : gtsam::NonlinearFactor {
VelocityPrior(size_t key, Vector vel, const gtsam::noiseModel::Base* model);
};
#include <DynamicsPriors.h>
virtual class DGroundConstraint : gtsam::NonlinearFactor {
// Primary constructor allows for variable height of the "floor"
DGroundConstraint(size_t key, double height, const gtsam::noiseModel::Base* model);
// Fully specify vector - use only for debugging
DGroundConstraint(size_t key, Vector constraint, const gtsam::noiseModel::Base* model);
};
}///\namespace gtsam
#include <gtsam_unstable/dynamics/imuSystem.h>
@ -84,18 +187,18 @@ class Graph {
void print(string s) const;
// prior factors
void addPrior(size_t key, const gtsam::PoseRTV& pose, const gtsam::SharedNoiseModel& noiseModel);
void addPrior(size_t key, const gtsam::PoseRTV& pose, const gtsam::noiseModel::Base* noiseModel);
void addConstraint(size_t key, const gtsam::PoseRTV& pose);
void addHeightPrior(size_t key, double z, const gtsam::SharedNoiseModel& noiseModel);
void addHeightPrior(size_t key, double z, const gtsam::noiseModel::Base* noiseModel);
// inertial factors
void addFullIMUMeasurement(size_t key1, size_t key2, const Vector& accel, const Vector& gyro, double dt, const gtsam::SharedNoiseModel& noiseModel);
void addIMUMeasurement(size_t key1, size_t key2, const Vector& accel, const Vector& gyro, double dt, const gtsam::SharedNoiseModel& noiseModel);
void addVelocityConstraint(size_t key1, size_t key2, double dt, const gtsam::SharedNoiseModel& noiseModel);
void addFullIMUMeasurement(size_t key1, size_t key2, const Vector& accel, const Vector& gyro, double dt, const gtsam::noiseModel::Base* noiseModel);
void addIMUMeasurement(size_t key1, size_t key2, const Vector& accel, const Vector& gyro, double dt, const gtsam::noiseModel::Base* noiseModel);
void addVelocityConstraint(size_t key1, size_t key2, double dt, const gtsam::noiseModel::Base* noiseModel);
// other measurements
void addBetween(size_t key1, size_t key2, const gtsam::PoseRTV& z, const gtsam::SharedNoiseModel& noiseModel);
void addRange(size_t key1, size_t key2, double z, const gtsam::SharedNoiseModel& noiseModel);
void addBetween(size_t key1, size_t key2, const gtsam::PoseRTV& z, const gtsam::noiseModel::Base* noiseModel);
void addRange(size_t key1, size_t key2, double z, const gtsam::noiseModel::Base* noiseModel);
// optimization
imu::Values optimize(const imu::Values& init) const;

View File

@ -1,37 +1,29 @@
# Install matlab components
if (GTSAM_BUILD_WRAP)
if (GTSAM_INSTALL_MATLAB_TOOLBOX)
# Utility functions
message(STATUS "Installing Matlab Utility Functions")
# Matlab files: *.m and *.fig
file(GLOB matlab_utils_m "${GTSAM_SOURCE_ROOT_DIR}/matlab/*.m")
file(GLOB matlab_utils_fig "${GTSAM_SOURCE_ROOT_DIR}/matlab/*.fig")
set(matlab_utils ${matlab_utils_m} ${matlab_utils_fig})
install(FILES ${matlab_utils} DESTINATION ${GTSAM_TOOLBOX_INSTALL_PATH}/gtsam)
# Tests
if (GTSAM_INSTALL_MATLAB_TESTS)
message(STATUS "Installing Matlab Toolbox Tests")
file(GLOB matlab_tests "${GTSAM_SOURCE_ROOT_DIR}/matlab/tests/*.m")
install(FILES ${matlab_tests} DESTINATION ${GTSAM_TOOLBOX_INSTALL_PATH}/gtsam/tests)
endif ()
# Examples
if (GTSAM_INSTALL_MATLAB_EXAMPLES)
message(STATUS "Installing Matlab Toolbox Examples")
# Matlab files: *.m and *.fig
file(GLOB matlab_examples_m "${GTSAM_SOURCE_ROOT_DIR}/matlab/examples/*.m")
file(GLOB matlab_examples_fig "${GTSAM_SOURCE_ROOT_DIR}/matlab/examples/*.fig")
set(matlab_examples ${matlab_examples_m} ${matlab_examples_fig})
install(FILES ${matlab_examples} DESTINATION ${GTSAM_TOOLBOX_INSTALL_PATH}/gtsam/examples)
message(STATUS "Installing Matlab Toolbox Examples (Data)")
# Data files: *.graph and *.txt
file(GLOB matlab_examples_data_graph "${GTSAM_SOURCE_ROOT_DIR}/examples/Data/*.graph")
file(GLOB matlab_examples_data_txt "${GTSAM_SOURCE_ROOT_DIR}/examples/Data/*.txt")
set(matlab_examples_data ${matlab_examples_data_graph} ${matlab_examples_data_txt})
install(FILES ${matlab_examples_data} DESTINATION ${GTSAM_TOOLBOX_INSTALL_PATH}/gtsam/Data)
endif ()
endif ()
endif ()
# Utility functions
message(STATUS "Installing Matlab Utility Functions")
# Matlab files: *.m and *.fig
file(GLOB matlab_utils_m "${GTSAM_SOURCE_ROOT_DIR}/matlab/*.m")
file(GLOB matlab_utils_fig "${GTSAM_SOURCE_ROOT_DIR}/matlab/*.fig")
set(matlab_utils ${matlab_utils_m} ${matlab_utils_fig})
install(FILES ${matlab_utils} DESTINATION ${GTSAM_TOOLBOX_INSTALL_PATH}/gtsam)
# Tests
message(STATUS "Installing Matlab Toolbox Tests")
file(GLOB matlab_tests "${GTSAM_SOURCE_ROOT_DIR}/matlab/tests/*.m")
install(FILES ${matlab_tests} DESTINATION ${GTSAM_TOOLBOX_INSTALL_PATH}/gtsam/tests)
# Examples
message(STATUS "Installing Matlab Toolbox Examples")
# Matlab files: *.m and *.fig
file(GLOB matlab_examples_m "${GTSAM_SOURCE_ROOT_DIR}/matlab/examples/*.m")
file(GLOB matlab_examples_fig "${GTSAM_SOURCE_ROOT_DIR}/matlab/examples/*.fig")
set(matlab_examples ${matlab_examples_m} ${matlab_examples_fig})
install(FILES ${matlab_examples} DESTINATION ${GTSAM_TOOLBOX_INSTALL_PATH}/gtsam/examples)
message(STATUS "Installing Matlab Toolbox Examples (Data)")
# Data files: *.graph and *.txt
file(GLOB matlab_examples_data_graph "${GTSAM_SOURCE_ROOT_DIR}/examples/Data/*.graph")
file(GLOB matlab_examples_data_txt "${GTSAM_SOURCE_ROOT_DIR}/examples/Data/*.txt")
set(matlab_examples_data ${matlab_examples_data_graph} ${matlab_examples_data_txt})
install(FILES ${matlab_examples_data} DESTINATION ${GTSAM_TOOLBOX_INSTALL_PATH}/gtsam/Data)

View File

@ -29,7 +29,7 @@ data.K = truth.K;
for i=1:options.nrCameras
theta = (i-1)*2*pi/options.nrCameras;
t = gtsamPoint3([r*cos(theta), r*sin(theta), height]');
truth.cameras{i} = gtsamSimpleCamera_lookat(t, gtsamPoint3, gtsamPoint3([0,0,1]'), truth.K);
truth.cameras{i} = gtsamSimpleCamera.Lookat(t, gtsamPoint3, gtsamPoint3([0,0,1]'), truth.K);
% Create measurements
for j=1:nrPoints
% All landmarks seen in every frame

View File

@ -6,10 +6,10 @@ function [noiseModels,isam,result] = VisualISAMInitialize(data,truth,options)
isam = visualSLAMISAM(options.reorderInterval);
%% Set Noise parameters
noiseModels.pose = gtsamnoiseModelDiagonal_Sigmas([0.001 0.001 0.001 0.1 0.1 0.1]');
noiseModels.odometry = gtsamnoiseModelDiagonal_Sigmas([0.001 0.001 0.001 0.1 0.1 0.1]');
noiseModels.point = gtsamnoiseModelIsotropic_Sigma(3, 0.1);
noiseModels.measurement = gtsamnoiseModelIsotropic_Sigma(2, 1.0);
noiseModels.pose = gtsamnoiseModelDiagonal.Sigmas([0.001 0.001 0.001 0.1 0.1 0.1]');
noiseModels.odometry = gtsamnoiseModelDiagonal.Sigmas([0.001 0.001 0.001 0.1 0.1 0.1]');
noiseModels.point = gtsamnoiseModelIsotropic.Sigma(3, 0.1);
noiseModels.measurement = gtsamnoiseModelIsotropic.Sigma(2, 1.0);
%% Add constraints/priors
% TODO: should not be from ground truth!

View File

@ -20,13 +20,13 @@ graph = pose2SLAMGraph;
%% Add two odometry factors
odometry = gtsamPose2(2.0, 0.0, 0.0); % create a measurement for both factors (the same in this case)
odometryNoise = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]); % 20cm std on x,y, 0.1 rad on theta
odometryNoise = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]); % 20cm std on x,y, 0.1 rad on theta
graph.addRelativePose(1, 2, odometry, odometryNoise);
graph.addRelativePose(2, 3, odometry, odometryNoise);
%% Add three "GPS" measurements
% We use Pose2 Priors here with high variance on theta
noiseModel = gtsamnoiseModelDiagonal_Sigmas([0.1; 0.1; 10]);
noiseModel = gtsamnoiseModelDiagonal.Sigmas([0.1; 0.1; 10]);
graph.addPosePrior(1, gtsamPose2(0.0, 0.0, 0.0), noiseModel);
graph.addPosePrior(2, gtsamPose2(2.0, 0.0, 0.0), noiseModel);
graph.addPosePrior(3, gtsamPose2(4.0, 0.0, 0.0), noiseModel);

View File

@ -20,12 +20,12 @@ graph = pose2SLAMGraph;
%% Add a Gaussian prior on pose x_1
priorMean = gtsamPose2(0.0, 0.0, 0.0); % prior mean is at origin
priorNoise = gtsamnoiseModelDiagonal_Sigmas([0.3; 0.3; 0.1]); % 30cm std on x,y, 0.1 rad on theta
priorNoise = gtsamnoiseModelDiagonal.Sigmas([0.3; 0.3; 0.1]); % 30cm std on x,y, 0.1 rad on theta
graph.addPosePrior(1, priorMean, priorNoise); % add directly to graph
%% Add two odometry factors
odometry = gtsamPose2(2.0, 0.0, 0.0); % create a measurement for both factors (the same in this case)
odometryNoise = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]); % 20cm std on x,y, 0.1 rad on theta
odometryNoise = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]); % 20cm std on x,y, 0.1 rad on theta
graph.addRelativePose(1, 2, odometry, odometryNoise);
graph.addRelativePose(2, 3, odometry, odometryNoise);

View File

@ -28,18 +28,18 @@ graph = planarSLAMGraph;
%% Add prior
priorMean = gtsamPose2(0.0, 0.0, 0.0); % prior at origin
priorNoise = gtsamnoiseModelDiagonal_Sigmas([0.3; 0.3; 0.1]);
priorNoise = gtsamnoiseModelDiagonal.Sigmas([0.3; 0.3; 0.1]);
graph.addPosePrior(i1, priorMean, priorNoise); % add directly to graph
%% Add odometry
odometry = gtsamPose2(2.0, 0.0, 0.0);
odometryNoise = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]);
odometryNoise = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]);
graph.addRelativePose(i1, i2, odometry, odometryNoise);
graph.addRelativePose(i2, i3, odometry, odometryNoise);
%% Add bearing/range measurement factors
degrees = pi/180;
noiseModel = gtsamnoiseModelDiagonal_Sigmas([0.1; 0.2]);
noiseModel = gtsamnoiseModelDiagonal.Sigmas([0.1; 0.2]);
graph.addBearingRange(i1, j1, gtsamRot2(45*degrees), sqrt(4+4), noiseModel);
graph.addBearingRange(i2, j1, gtsamRot2(90*degrees), 2, noiseModel);
graph.addBearingRange(i3, j2, gtsamRot2(90*degrees), 2, noiseModel);

View File

@ -15,22 +15,22 @@
i1 = symbol('x',1); i2 = symbol('x',2); i3 = symbol('x',3);
graph = planarSLAMGraph;
priorMean = gtsamPose2(0.0, 0.0, 0.0); % prior at origin
priorNoise = gtsamnoiseModelDiagonal_Sigmas([0.3; 0.3; 0.1]);
priorNoise = gtsamnoiseModelDiagonal.Sigmas([0.3; 0.3; 0.1]);
graph.addPosePrior(i1, priorMean, priorNoise); % add directly to graph
odometry = gtsamPose2(2.0, 0.0, 0.0);
odometryNoise = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]);
odometryNoise = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]);
graph.addRelativePose(i1, i2, odometry, odometryNoise);
graph.addRelativePose(i2, i3, odometry, odometryNoise);
%% Except, for measurements we offer a choice
j1 = symbol('l',1); j2 = symbol('l',2);
degrees = pi/180;
noiseModel = gtsamnoiseModelDiagonal_Sigmas([0.1; 0.2]);
noiseModel = gtsamnoiseModelDiagonal.Sigmas([0.1; 0.2]);
if 1
graph.addBearingRange(i1, j1, gtsamRot2(45*degrees), sqrt(4+4), noiseModel);
graph.addBearingRange(i2, j1, gtsamRot2(90*degrees), 2, noiseModel);
else
bearingModel = gtsamnoiseModelDiagonal_Sigmas(0.1);
bearingModel = gtsamnoiseModelDiagonal.Sigmas(0.1);
graph.addBearing(i1, j1, gtsamRot2(45*degrees), bearingModel);
graph.addBearing(i2, j1, gtsamRot2(90*degrees), bearingModel);
end

View File

@ -24,19 +24,19 @@ graph = pose2SLAMGraph;
%% Add prior
% gaussian for prior
priorMean = gtsamPose2(0.0, 0.0, 0.0); % prior at origin
priorNoise = gtsamnoiseModelDiagonal_Sigmas([0.3; 0.3; 0.1]);
priorNoise = gtsamnoiseModelDiagonal.Sigmas([0.3; 0.3; 0.1]);
graph.addPosePrior(1, priorMean, priorNoise); % add directly to graph
%% Add odometry
% general noisemodel for odometry
odometryNoise = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]);
odometryNoise = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]);
graph.addRelativePose(1, 2, gtsamPose2(2.0, 0.0, 0.0 ), odometryNoise);
graph.addRelativePose(2, 3, gtsamPose2(2.0, 0.0, pi/2), odometryNoise);
graph.addRelativePose(3, 4, gtsamPose2(2.0, 0.0, pi/2), odometryNoise);
graph.addRelativePose(4, 5, gtsamPose2(2.0, 0.0, pi/2), odometryNoise);
%% Add pose constraint
model = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]);
model = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]);
graph.addRelativePose(5, 2, gtsamPose2(2.0, 0.0, pi/2), model);
% print

View File

@ -25,20 +25,20 @@ graph = pose2SLAMGraph;
%% Add prior
% gaussian for prior
priorNoise = gtsamnoiseModelDiagonal_Sigmas([0.3; 0.3; 0.1]);
priorNoise = gtsamnoiseModelDiagonal.Sigmas([0.3; 0.3; 0.1]);
priorMean = gtsamPose2(0.0, 0.0, 0.0); % prior at origin
graph.addPosePrior(1, priorMean, priorNoise); % add directly to graph
%% Add odometry
% general noisemodel for odometry
odometryNoise = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]);
odometryNoise = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]);
odometry = gtsamPose2(2.0, 0.0, 0.0); % create a measurement for both factors (the same in this case)
graph.addRelativePose(1, 2, odometry, odometryNoise);
graph.addRelativePose(2, 3, odometry, odometryNoise);
%% Add measurements
% general noisemodel for measurements
measurementNoise = gtsamnoiseModelDiagonal_Sigmas([0.1; 0.2]);
measurementNoise = gtsamnoiseModelDiagonal.Sigmas([0.1; 0.2]);
% print
graph.print('full graph');

View File

@ -11,7 +11,7 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Create a hexagon of poses
hexagon = pose2SLAMValues_Circle(6,1.0);
hexagon = pose2SLAMValues.Circle(6,1.0);
p0 = hexagon.pose(0);
p1 = hexagon.pose(1);
@ -19,7 +19,7 @@ p1 = hexagon.pose(1);
fg = pose2SLAMGraph;
fg.addPoseConstraint(0, p0);
delta = p0.between(p1);
covariance = gtsamnoiseModelDiagonal_Sigmas([0.05; 0.05; 5*pi/180]);
covariance = gtsamnoiseModelDiagonal.Sigmas([0.05; 0.05; 5*pi/180]);
fg.addRelativePose(0,1, delta, covariance);
fg.addRelativePose(1,2, delta, covariance);
fg.addRelativePose(2,3, delta, covariance);

View File

@ -11,13 +11,13 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Initialize graph, initial estimate, and odometry noise
model = gtsamnoiseModelDiagonal_Sigmas([0.05; 0.05; 5*pi/180]);
model = gtsamnoiseModelDiagonal.Sigmas([0.05; 0.05; 5*pi/180]);
[graph,initial]=load2D('../../examples/Data/w100-odom.graph',model);
initial.print(sprintf('Initial estimate:\n'));
%% Add a Gaussian prior on pose x_1
priorMean = gtsamPose2(0.0, 0.0, 0.0); % prior mean is at origin
priorNoise = gtsamnoiseModelDiagonal_Sigmas([0.01; 0.01; 0.01]);
priorNoise = gtsamnoiseModelDiagonal.Sigmas([0.01; 0.01; 0.01]);
graph.addPosePrior(0, priorMean, priorNoise); % add directly to graph
%% Plot Initial Estimate

View File

@ -22,19 +22,19 @@ graph = pose2SLAMGraph;
%% Add prior
% gaussian for prior
priorMean = gtsamPose2(0.0, 0.0, 0.0); % prior at origin
priorNoise = gtsamnoiseModelDiagonal_Sigmas([0.3; 0.3; 0.1]);
priorNoise = gtsamnoiseModelDiagonal.Sigmas([0.3; 0.3; 0.1]);
graph.addPrior(1, priorMean, priorNoise); % add directly to graph
%% Add odometry
% general noisemodel for odometry
odometryNoise = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]);
odometryNoise = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]);
graph.addOdometry(1, 2, gtsamPose2(2.0, 0.0, 0.0 ), odometryNoise);
graph.addOdometry(2, 3, gtsamPose2(2.0, 0.0, pi/2), odometryNoise);
graph.addOdometry(3, 4, gtsamPose2(2.0, 0.0, pi/2), odometryNoise);
graph.addOdometry(4, 5, gtsamPose2(2.0, 0.0, pi/2), odometryNoise);
%% Add pose constraint
model = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]);
model = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]);
graph.addRelativePose(5, 2, gtsamPose2(2.0, 0.0, pi/2), model);
% print

View File

@ -11,7 +11,7 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Create a hexagon of poses
hexagon = pose3SLAMValues_Circle(6,1.0);
hexagon = pose3SLAMValues.Circle(6,1.0);
p0 = hexagon.pose(0);
p1 = hexagon.pose(1);
@ -19,7 +19,7 @@ p1 = hexagon.pose(1);
fg = pose3SLAMGraph;
fg.addPoseConstraint(0, p0);
delta = p0.between(p1);
covariance = gtsamnoiseModelDiagonal_Sigmas([0.05; 0.05; 0.05; 5*pi/180; 5*pi/180; 5*pi/180]);
covariance = gtsamnoiseModelDiagonal.Sigmas([0.05; 0.05; 0.05; 5*pi/180; 5*pi/180; 5*pi/180]);
fg.addRelativePose(0,1, delta, covariance);
fg.addRelativePose(1,2, delta, covariance);
fg.addRelativePose(2,3, delta, covariance);

View File

@ -16,7 +16,7 @@ N = 2500;
filename = '../../examples/Data/sphere2500.txt';
%% Initialize graph, initial estimate, and odometry noise
model = gtsamnoiseModelDiagonal_Sigmas([0.05; 0.05; 0.05; 5*pi/180; 5*pi/180; 5*pi/180]);
model = gtsamnoiseModelDiagonal.Sigmas([0.05; 0.05; 0.05; 5*pi/180; 5*pi/180; 5*pi/180]);
[graph,initial]=load3D(filename,model,true,N);
%% Plot Initial Estimate

View File

@ -34,7 +34,7 @@ graph = sparseBAGraph;
%% Add factors for all measurements
measurementNoise = gtsamnoiseModelIsotropic_Sigma(2,measurementNoiseSigma);
measurementNoise = gtsamnoiseModelIsotropic.Sigma(2,measurementNoiseSigma);
for i=1:length(data.Z)
for k=1:length(data.Z{i})
j = data.J{i}{k};
@ -43,11 +43,11 @@ for i=1:length(data.Z)
end
%% Add Gaussian priors for a pose and a landmark to constrain the system
cameraPriorNoise = gtsamnoiseModelDiagonal_Sigmas(cameraNoiseSigmas);
cameraPriorNoise = gtsamnoiseModelDiagonal.Sigmas(cameraNoiseSigmas);
firstCamera = gtsamSimpleCamera(truth.cameras{1}.pose, truth.K);
graph.addSimpleCameraPrior(symbol('c',1), firstCamera, cameraPriorNoise);
pointPriorNoise = gtsamnoiseModelIsotropic_Sigma(3,pointNoiseSigma);
pointPriorNoise = gtsamnoiseModelIsotropic.Sigma(3,pointNoiseSigma);
graph.addPointPrior(symbol('p',1), truth.points{1}, pointPriorNoise);
%% Print the graph

View File

@ -32,7 +32,7 @@ poseNoiseSigmas = [0.001 0.001 0.001 0.1 0.1 0.1]';
graph = visualSLAMGraph;
%% Add factors for all measurements
measurementNoise = gtsamnoiseModelIsotropic_Sigma(2,measurementNoiseSigma);
measurementNoise = gtsamnoiseModelIsotropic.Sigma(2,measurementNoiseSigma);
for i=1:length(data.Z)
for k=1:length(data.Z{i})
j = data.J{i}{k};
@ -41,9 +41,9 @@ for i=1:length(data.Z)
end
%% Add Gaussian priors for a pose and a landmark to constrain the system
posePriorNoise = gtsamnoiseModelDiagonal_Sigmas(poseNoiseSigmas);
posePriorNoise = gtsamnoiseModelDiagonal.Sigmas(poseNoiseSigmas);
graph.addPosePrior(symbol('x',1), truth.cameras{1}.pose, posePriorNoise);
pointPriorNoise = gtsamnoiseModelIsotropic_Sigma(3,pointNoiseSigma);
pointPriorNoise = gtsamnoiseModelIsotropic.Sigma(3,pointNoiseSigma);
graph.addPointPrior(symbol('p',1), truth.points{1}, pointPriorNoise);
%% Print the graph

View File

@ -31,7 +31,7 @@ graph.addPoseConstraint(x1, first_pose);
%% Create realistic calibration and measurement noise model
% format: fx fy skew cx cy baseline
K = gtsamCal3_S2Stereo(1000, 1000, 0, 320, 240, 0.2);
stereo_model = gtsamnoiseModelDiagonal_Sigmas([1.0; 1.0; 1.0]);
stereo_model = gtsamnoiseModelDiagonal.Sigmas([1.0; 1.0; 1.0]);
%% Add measurements
% pose 1

View File

@ -14,7 +14,7 @@
% format: fx fy skew cx cy baseline
calib = dlmread('../../examples/Data/VO_calibration.txt');
K = gtsamCal3_S2Stereo(calib(1), calib(2), calib(3), calib(4), calib(5), calib(6));
stereo_model = gtsamnoiseModelDiagonal_Sigmas([1.0; 1.0; 1.0]);
stereo_model = gtsamnoiseModelDiagonal.Sigmas([1.0; 1.0; 1.0]);
%% create empty graph and values
graph = visualSLAMGraph;

View File

@ -29,7 +29,7 @@ for i=1:n
i=v{2};
if (~successive & i<N | successive & i==0)
t = gtsamPoint3(v{3}, v{4}, v{5});
R = gtsamRot3_ypr(v{8}, -v{7}, v{6});
R = gtsamRot3.Ypr(v{8}, -v{7}, v{6});
initial.insertPose(i, gtsamPose3(R,t));
end
elseif strcmp('EDGE3',line_i(1:5))
@ -39,7 +39,7 @@ for i=1:n
if i1<N & i2<N
if ~successive | abs(i2-i1)==1
t = gtsamPoint3(e{4}, e{5}, e{6});
R = gtsamRot3_ypr(e{9}, e{8}, e{7});
R = gtsamRot3.Ypr(e{9}, e{8}, e{7});
dpose = gtsamPose3(R,t);
graph.addRelativePose(i1, i2, dpose, model);
if successive

View File

@ -30,7 +30,7 @@ x1 = 3;
% the RHS
b2=[-1;1.5;2;-1];
sigmas = [1;1;1;1];
model4 = gtsamnoiseModelDiagonal_Sigmas(sigmas);
model4 = gtsamnoiseModelDiagonal.Sigmas(sigmas);
combined = gtsamJacobianFactor(x2, Ax2, l1, Al1, x1, Ax1, b2, model4);
% eliminate the first variable (x2) in the combined factor, destructive !
@ -69,7 +69,7 @@ Bx1 = [
% the RHS
b1= [0.0;0.894427];
model2 = gtsamnoiseModelDiagonal_Sigmas([1;1]);
model2 = gtsamnoiseModelDiagonal.Sigmas([1;1]);
expectedLF = gtsamJacobianFactor(l1, Bl1, x1, Bx1, b1, model2);
% check if the result matches the combined (reduced) factor

View File

@ -22,13 +22,13 @@
F = eye(2,2);
B = eye(2,2);
u = [1.0; 0.0];
modelQ = gtsamnoiseModelDiagonal_Sigmas([0.1;0.1]);
modelQ = gtsamnoiseModelDiagonal.Sigmas([0.1;0.1]);
Q = 0.01*eye(2,2);
H = eye(2,2);
z1 = [1.0, 0.0]';
z2 = [2.0, 0.0]';
z3 = [3.0, 0.0]';
modelR = gtsamnoiseModelDiagonal_Sigmas([0.1;0.1]);
modelR = gtsamnoiseModelDiagonal.Sigmas([0.1;0.1]);
R = 0.01*eye(2,2);
%% Create the set of expected output TestValues

View File

@ -15,7 +15,7 @@ graph = pose2SLAMGraph;
%% Add two odometry factors
odometry = gtsamPose2(2.0, 0.0, 0.0); % create a measurement for both factors (the same in this case)
odometryNoise = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]); % 20cm std on x,y, 0.1 rad on theta
odometryNoise = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]); % 20cm std on x,y, 0.1 rad on theta
graph.addRelativePose(1, 2, odometry, odometryNoise);
graph.addRelativePose(2, 3, odometry, odometryNoise);
@ -25,7 +25,7 @@ groundTruth = pose2SLAMValues;
groundTruth.insertPose(1, gtsamPose2(0.0, 0.0, 0.0));
groundTruth.insertPose(2, gtsamPose2(2.0, 0.0, 0.0));
groundTruth.insertPose(3, gtsamPose2(4.0, 0.0, 0.0));
noiseModel = gtsamnoiseModelDiagonal_Sigmas([0.1; 0.1; 10]);
noiseModel = gtsamnoiseModelDiagonal.Sigmas([0.1; 0.1; 10]);
for i=1:3
graph.addPosePrior(i, groundTruth.pose(i), noiseModel);
end

View File

@ -15,12 +15,12 @@ graph = pose2SLAMGraph;
%% Add a Gaussian prior on pose x_1
priorMean = gtsamPose2(0.0, 0.0, 0.0); % prior mean is at origin
priorNoise = gtsamnoiseModelDiagonal_Sigmas([0.3; 0.3; 0.1]); % 30cm std on x,y, 0.1 rad on theta
priorNoise = gtsamnoiseModelDiagonal.Sigmas([0.3; 0.3; 0.1]); % 30cm std on x,y, 0.1 rad on theta
graph.addPosePrior(1, priorMean, priorNoise); % add directly to graph
%% Add two odometry factors
odometry = gtsamPose2(2.0, 0.0, 0.0); % create a measurement for both factors (the same in this case)
odometryNoise = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]); % 20cm std on x,y, 0.1 rad on theta
odometryNoise = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]); % 20cm std on x,y, 0.1 rad on theta
graph.addRelativePose(1, 2, odometry, odometryNoise);
graph.addRelativePose(2, 3, odometry, odometryNoise);

View File

@ -28,18 +28,18 @@ graph = planarSLAMGraph;
%% Add prior
priorMean = gtsamPose2(0.0, 0.0, 0.0); % prior at origin
priorNoise = gtsamnoiseModelDiagonal_Sigmas([0.3; 0.3; 0.1]);
priorNoise = gtsamnoiseModelDiagonal.Sigmas([0.3; 0.3; 0.1]);
graph.addPosePrior(i1, priorMean, priorNoise); % add directly to graph
%% Add odometry
odometry = gtsamPose2(2.0, 0.0, 0.0);
odometryNoise = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]);
odometryNoise = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]);
graph.addRelativePose(i1, i2, odometry, odometryNoise);
graph.addRelativePose(i2, i3, odometry, odometryNoise);
%% Add bearing/range measurement factors
degrees = pi/180;
noiseModel = gtsamnoiseModelDiagonal_Sigmas([0.1; 0.2]);
noiseModel = gtsamnoiseModelDiagonal.Sigmas([0.1; 0.2]);
graph.addBearingRange(i1, j1, gtsamRot2(45*degrees), sqrt(4+4), noiseModel);
graph.addBearingRange(i2, j1, gtsamRot2(90*degrees), 2, noiseModel);
graph.addBearingRange(i3, j2, gtsamRot2(90*degrees), 2, noiseModel);

View File

@ -24,19 +24,19 @@ graph = pose2SLAMGraph;
%% Add prior
% gaussian for prior
priorMean = gtsamPose2(0.0, 0.0, 0.0); % prior at origin
priorNoise = gtsamnoiseModelDiagonal_Sigmas([0.3; 0.3; 0.1]);
priorNoise = gtsamnoiseModelDiagonal.Sigmas([0.3; 0.3; 0.1]);
graph.addPosePrior(1, priorMean, priorNoise); % add directly to graph
%% Add odometry
% general noisemodel for odometry
odometryNoise = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]);
odometryNoise = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]);
graph.addRelativePose(1, 2, gtsamPose2(2.0, 0.0, 0.0 ), odometryNoise);
graph.addRelativePose(2, 3, gtsamPose2(2.0, 0.0, pi/2), odometryNoise);
graph.addRelativePose(3, 4, gtsamPose2(2.0, 0.0, pi/2), odometryNoise);
graph.addRelativePose(4, 5, gtsamPose2(2.0, 0.0, pi/2), odometryNoise);
%% Add pose constraint
model = gtsamnoiseModelDiagonal_Sigmas([0.2; 0.2; 0.1]);
model = gtsamnoiseModelDiagonal.Sigmas([0.2; 0.2; 0.1]);
graph.addRelativePose(5, 2, gtsamPose2(2.0, 0.0, pi/2), model);
%% Initialize to noisy points

View File

@ -11,7 +11,7 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Create a hexagon of poses
hexagon = pose3SLAMValues_Circle(6,1.0);
hexagon = pose3SLAMValues.Circle(6,1.0);
p0 = hexagon.pose(0);
p1 = hexagon.pose(1);
@ -19,7 +19,7 @@ p1 = hexagon.pose(1);
fg = pose3SLAMGraph;
fg.addPoseConstraint(0, p0);
delta = p0.between(p1);
covariance = gtsamnoiseModelDiagonal_Sigmas([0.05; 0.05; 0.05; 5*pi/180; 5*pi/180; 5*pi/180]);
covariance = gtsamnoiseModelDiagonal.Sigmas([0.05; 0.05; 0.05; 5*pi/180; 5*pi/180; 5*pi/180]);
fg.addRelativePose(0,1, delta, covariance);
fg.addRelativePose(1,2, delta, covariance);
fg.addRelativePose(2,3, delta, covariance);

View File

@ -23,7 +23,7 @@ poseNoiseSigmas = [0.001 0.001 0.001 0.1 0.1 0.1]';
graph = visualSLAMGraph;
%% Add factors for all measurements
measurementNoise = gtsamnoiseModelIsotropic_Sigma(2,measurementNoiseSigma);
measurementNoise = gtsamnoiseModelIsotropic.Sigma(2,measurementNoiseSigma);
for i=1:length(data.Z)
for k=1:length(data.Z{i})
j = data.J{i}{k};
@ -31,9 +31,9 @@ for i=1:length(data.Z)
end
end
posePriorNoise = gtsamnoiseModelDiagonal_Sigmas(poseNoiseSigmas);
posePriorNoise = gtsamnoiseModelDiagonal.Sigmas(poseNoiseSigmas);
graph.addPosePrior(symbol('x',1), truth.cameras{1}.pose, posePriorNoise);
pointPriorNoise = gtsamnoiseModelIsotropic_Sigma(3,pointNoiseSigma);
pointPriorNoise = gtsamnoiseModelIsotropic.Sigma(3,pointNoiseSigma);
graph.addPointPrior(symbol('p',1), truth.points{1}, pointPriorNoise);
%% Initial estimate

View File

@ -31,7 +31,7 @@ graph.addPoseConstraint(x1, first_pose);
%% Create realistic calibration and measurement noise model
% format: fx fy skew cx cy baseline
K = gtsamCal3_S2Stereo(1000, 1000, 0, 320, 240, 0.2);
stereo_model = gtsamnoiseModelDiagonal_Sigmas([1.0; 1.0; 1.0]);
stereo_model = gtsamnoiseModelDiagonal.Sigmas([1.0; 1.0; 1.0]);
%% Add measurements
% pose 1

View File

@ -13,6 +13,7 @@
* @file Argument.ccp
* @author Frank Dellaert
* @author Andrew Melim
* @author Richard Roberts
**/
#include <iostream>
@ -64,7 +65,7 @@ void Argument::matlab_unwrap(FileWriter& file, const string& matlabName) const {
file.oss << cppType << " " << name << " = unwrap< ";
file.oss << cppType << " >(" << matlabName;
if (is_ptr || is_ref) file.oss << ", \"" << matlabType << "\"";
if (is_ptr || is_ref) file.oss << ", \"ptr_" << matlabType << "\"";
file.oss << ");" << endl;
}

View File

@ -14,6 +14,7 @@
* @brief arguments to constructors and methods
* @author Frank Dellaert
* @author Andrew Melim
* @author Richard Roberts
**/
#pragma once

View File

@ -1,6 +1,6 @@
# Build/install Wrap
find_package(Boost 1.42 COMPONENTS system filesystem thread REQUIRED)
set(WRAP_BOOST_LIBRARIES ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY})
# Build the executable itself
file(GLOB wrap_srcs "*.cpp")
@ -9,19 +9,21 @@ list(REMOVE_ITEM wrap_srcs ${CMAKE_CURRENT_SOURCE_DIR}/wrap.cpp)
add_library(wrap_lib STATIC ${wrap_srcs} ${wrap_headers})
gtsam_assign_source_folders(${wrap_srcs} ${wrap_headers})
add_executable(wrap wrap.cpp)
target_link_libraries(wrap wrap_lib ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY})
target_link_libraries(wrap wrap_lib ${WRAP_BOOST_LIBRARIES})
# Install wrap binary
# Install wrap binary and export target
if (GTSAM_INSTALL_WRAP)
install(TARGETS wrap DESTINATION bin)
install(TARGETS wrap EXPORT GTSAM-exports DESTINATION bin)
list(APPEND GTSAM_EXPORTED_TARGETS wrap)
set(GTSAM_EXPORTED_TARGETS "${GTSAM_EXPORTED_TARGETS}" PARENT_SCOPE)
endif(GTSAM_INSTALL_WRAP)
# Install matlab header
install(FILES matlab.h DESTINATION include/wrap)
# Build tests
if (GTSAM_BUILD_TESTS)
set(wrap_local_libs wrap_lib ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY})
if (GTSAM_BUILD_TESTS)
set(wrap_local_libs wrap_lib ${WRAP_BOOST_LIBRARIES})
gtsam_add_subdir_tests("wrap" "${wrap_local_libs}" "${wrap_local_libs}" "")
endif(GTSAM_BUILD_TESTS)

View File

@ -1,176 +1,317 @@
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file Class.cpp
* @author Frank Dellaert
* @author Andrew Melim
**/
#include <vector>
#include <iostream>
#include <fstream>
#include <boost/foreach.hpp>
#include "Class.h"
#include "utilities.h"
#include "Argument.h"
using namespace std;
using namespace wrap;
/* ************************************************************************* */
void Class::matlab_proxy(const string& classFile) const {
// open destination classFile
FileWriter file(classFile, verbose_, "%");
// get the name of actual matlab object
string matlabName = qualifiedName();
// emit class proxy code
// we want our class to inherit the handle class for memory purposes
file.oss << "classdef " << matlabName << " < handle" << endl;
file.oss << " properties" << endl;
file.oss << " self = 0" << endl;
file.oss << " end" << endl;
file.oss << " methods" << endl;
// constructor
file.oss << " function obj = " << matlabName << "(varargin)" << endl;
//i is constructor id
int id = 0;
BOOST_FOREACH(ArgumentList a, constructor.args_list)
{
constructor.matlab_proxy_fragment(file,matlabName, id, a);
id++;
}
//Static constructor collect call
file.oss << " if nargin ==14, new_" << matlabName << "(varargin{1},0); end" << endl;
file.oss << " if nargin ~= 13 && nargin ~= 14 && obj.self == 0, error('" << matlabName << " constructor failed'); end" << endl;
file.oss << " end" << endl;
// deconstructor
file.oss << " function delete(obj)" << endl;
file.oss << " if obj.self ~= 0" << endl;
//TODO: Add verbosity flag
//file.oss << " fprintf(1,'MATLAB class deleting %x',obj.self);" << endl;
file.oss << " new_" << matlabName << "(obj.self);" << endl;
file.oss << " obj.self = 0;" << endl;
file.oss << " end" << endl;
file.oss << " end" << endl;
file.oss << " function display(obj), obj.print(''); end" << endl;
file.oss << " function disp(obj), obj.display; end" << endl;
file.oss << " end" << endl;
file.oss << "end" << endl;
// close file
file.emit(true);
}
/* ************************************************************************* */
//TODO: Consolidate into single file
void Class::matlab_constructors(const string& toolboxPath) const {
/*BOOST_FOREACH(Constructor c, constructors) {
args_list.push_back(c.args);
}*/
BOOST_FOREACH(ArgumentList a, constructor.args_list) {
constructor.matlab_mfile(toolboxPath, qualifiedName(), a);
}
constructor.matlab_wrapper(toolboxPath, qualifiedName("::"), qualifiedName(),
using_namespaces, includes);
}
/* ************************************************************************* */
void Class::matlab_methods(const string& classPath) const {
string matlabName = qualifiedName(), cppName = qualifiedName("::");
BOOST_FOREACH(Method m, methods) {
m.matlab_mfile (classPath);
m.matlab_wrapper(classPath, name, cppName, matlabName, using_namespaces, includes);
}
}
/* ************************************************************************* */
void Class::matlab_static_methods(const string& toolboxPath) const {
string matlabName = qualifiedName(), cppName = qualifiedName("::");
BOOST_FOREACH(const StaticMethod& m, static_methods) {
m.matlab_mfile (toolboxPath, qualifiedName());
m.matlab_wrapper(toolboxPath, name, matlabName, cppName, using_namespaces, includes);
}
}
/* ************************************************************************* */
void Class::matlab_make_fragment(FileWriter& file,
const string& toolboxPath,
const string& mexFlags) const {
string mex = "mex " + mexFlags + " ";
string matlabClassName = qualifiedName();
file.oss << mex << constructor.matlab_wrapper_name(matlabClassName) << ".cpp" << endl;
BOOST_FOREACH(StaticMethod sm, static_methods)
file.oss << mex << matlabClassName + "_" + sm.name << ".cpp" << endl;
file.oss << endl << "cd @" << matlabClassName << endl;
BOOST_FOREACH(Method m, methods)
file.oss << mex << m.name << ".cpp" << endl;
file.oss << endl;
}
/* ************************************************************************* */
void Class::makefile_fragment(FileWriter& file) const {
// new_Point2_.$(MEXENDING): new_Point2_.cpp
// $(MEX) $(mex_flags) new_Point2_.cpp
// new_Point2_dd.$(MEXENDING): new_Point2_dd.cpp
// $(MEX) $(mex_flags) new_Point2_dd.cpp
// @Point2/x.$(MEXENDING): @Point2/x.cpp
// $(MEX) $(mex_flags) @Point2/x.cpp -output @Point2/x
// @Point2/y.$(MEXENDING): @Point2/y.cpp
// $(MEX) $(mex_flags) @Point2/y.cpp -output @Point2/y
// @Point2/dim.$(MEXENDING): @Point2/dim.cpp
// $(MEX) $(mex_flags) @Point2/dim.cpp -output @Point2/dim
//
// Point2: new_Point2_.$(MEXENDING) new_Point2_dd.$(MEXENDING) @Point2/x.$(MEXENDING) @Point2/y.$(MEXENDING) @Point2/dim.$(MEXENDING)
string matlabName = qualifiedName();
// collect names
vector<string> file_names;
string file_base = constructor.matlab_wrapper_name(matlabName);
file_names.push_back(file_base);
BOOST_FOREACH(StaticMethod c, static_methods) {
string file_base = matlabName + "_" + c.name;
file_names.push_back(file_base);
}
BOOST_FOREACH(Method c, methods) {
string file_base = "@" + matlabName + "/" + c.name;
file_names.push_back(file_base);
}
BOOST_FOREACH(const string& file_base, file_names) {
file.oss << file_base << ".$(MEXENDING): " << file_base << ".cpp";
file.oss << " $(PATH_TO_WRAP)/matlab.h" << endl;
file.oss << "\t$(MEX) $(mex_flags) " << file_base << ".cpp -output " << file_base << endl;
}
// class target
file.oss << "\n" << matlabName << ": ";
BOOST_FOREACH(const string& file_base, file_names) {
file.oss << file_base << ".$(MEXENDING) ";
}
file.oss << "\n" << endl;
}
/* ************************************************************************* */
string Class::qualifiedName(const string& delim) const {
string result;
BOOST_FOREACH(const string& ns, namespaces)
result += ns + delim;
return result + name;
}
/* ************************************************************************* */
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file Class.cpp
* @author Frank Dellaert
* @author Andrew Melim
* @author Richard Roberts
**/
#include <vector>
#include <iostream>
#include <fstream>
//#include <cstdint> // on Linux GCC: fails with error regarding needing C++0x std flags
//#include <cinttypes> // same failure as above
#include <stdint.h> // works on Linux GCC
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include "Class.h"
#include "utilities.h"
#include "Argument.h"
using namespace std;
using namespace wrap;
/* ************************************************************************* */
void Class::matlab_proxy(const string& classFile, const string& wrapperName,
const TypeAttributesTable& typeAttributes,
FileWriter& wrapperFile, vector<string>& functionNames) const {
// open destination classFile
FileWriter proxyFile(classFile, verbose_, "%");
// get the name of actual matlab object
const string matlabName = qualifiedName(), cppName = qualifiedName("::");
const string matlabBaseName = wrap::qualifiedName("", qualifiedParent);
const string cppBaseName = wrap::qualifiedName("::", qualifiedParent);
// emit class proxy code
// we want our class to inherit the handle class for memory purposes
const string parent = qualifiedParent.empty() ?
"handle" : ::wrap::qualifiedName("", qualifiedParent);
proxyFile.oss << "classdef " << matlabName << " < " << parent << endl;
proxyFile.oss << " properties" << endl;
proxyFile.oss << " ptr_" << matlabName << " = 0" << endl;
proxyFile.oss << " end" << endl;
proxyFile.oss << " methods" << endl;
// Constructor
proxyFile.oss << " function obj = " << matlabName << "(varargin)" << endl;
// Special pointer constructors - one in MATLAB to create an object and
// assign a pointer returned from a C++ function. In turn this MATLAB
// constructor calls a special C++ function that just adds the object to
// its collector. This allows wrapped functions to return objects in
// other wrap modules - to add these to their collectors the pointer is
// passed from one C++ module into matlab then back into the other C++
// module.
pointer_constructor_fragments(proxyFile, wrapperFile, wrapperName, functionNames);
wrapperFile.oss << "\n";
// Regular constructors
BOOST_FOREACH(ArgumentList a, constructor.args_list)
{
const int id = (int)functionNames.size();
constructor.proxy_fragment(proxyFile, wrapperName, matlabName, matlabBaseName, id, a);
const string wrapFunctionName = constructor.wrapper_fragment(wrapperFile,
cppName, matlabName, cppBaseName, id, using_namespaces, a);
wrapperFile.oss << "\n";
functionNames.push_back(wrapFunctionName);
}
proxyFile.oss << " else\n";
proxyFile.oss << " error('Arguments do not match any overload of " << matlabName << " constructor');" << endl;
proxyFile.oss << " end\n";
if(!qualifiedParent.empty())
proxyFile.oss << " obj = obj@" << matlabBaseName << "(uint64(" << ptr_constructor_key << "), base_ptr);\n";
proxyFile.oss << " obj.ptr_" << matlabName << " = my_ptr;\n";
proxyFile.oss << " end\n\n";
// Deconstructor
{
const int id = (int)functionNames.size();
deconstructor.proxy_fragment(proxyFile, wrapperName, matlabName, id);
proxyFile.oss << "\n";
const string functionName = deconstructor.wrapper_fragment(wrapperFile, cppName, matlabName, id, using_namespaces);
wrapperFile.oss << "\n";
functionNames.push_back(functionName);
}
proxyFile.oss << " function display(obj), obj.print(''); end\n\n";
proxyFile.oss << " function disp(obj), obj.display; end\n\n";
// Methods
BOOST_FOREACH(const Methods::value_type& name_m, methods) {
const Method& m = name_m.second;
m.proxy_wrapper_fragments(proxyFile, wrapperFile, cppName, matlabName, wrapperName, using_namespaces, typeAttributes, functionNames);
proxyFile.oss << "\n";
wrapperFile.oss << "\n";
}
proxyFile.oss << " end\n";
proxyFile.oss << "\n";
proxyFile.oss << " methods(Static = true)\n";
// Static methods
BOOST_FOREACH(const StaticMethods::value_type& name_m, static_methods) {
const StaticMethod& m = name_m.second;
m.proxy_wrapper_fragments(proxyFile, wrapperFile, cppName, matlabName, wrapperName, using_namespaces, typeAttributes, functionNames);
proxyFile.oss << "\n";
wrapperFile.oss << "\n";
}
proxyFile.oss << " end" << endl;
proxyFile.oss << "end" << endl;
// Close file
proxyFile.emit(true);
}
/* ************************************************************************* */
string Class::qualifiedName(const string& delim) const {
return ::wrap::qualifiedName(delim, namespaces, name);
}
/* ************************************************************************* */
void Class::pointer_constructor_fragments(FileWriter& proxyFile, FileWriter& wrapperFile, const string& wrapperName, vector<string>& functionNames) const {
const string matlabName = qualifiedName(), cppName = qualifiedName("::");
const string baseMatlabName = wrap::qualifiedName("", qualifiedParent);
const string baseCppName = wrap::qualifiedName("::", qualifiedParent);
const int collectorInsertId = (int)functionNames.size();
const string collectorInsertFunctionName = matlabName + "_collectorInsertAndMakeBase_" + boost::lexical_cast<string>(collectorInsertId);
functionNames.push_back(collectorInsertFunctionName);
int upcastFromVoidId;
string upcastFromVoidFunctionName;
if(isVirtual) {
upcastFromVoidId = (int)functionNames.size();
upcastFromVoidFunctionName = matlabName + "_upcastFromVoid_" + boost::lexical_cast<string>(upcastFromVoidId);
functionNames.push_back(upcastFromVoidFunctionName);
}
// MATLAB constructor that assigns pointer to matlab object then calls c++
// function to add the object to the collector.
if(isVirtual) {
proxyFile.oss << " if (nargin == 2 || (nargin == 3 && strcmp(varargin{3}, 'void')))";
} else {
proxyFile.oss << " if nargin == 2";
}
proxyFile.oss << " && isa(varargin{1}, 'uint64') && varargin{1} == uint64(" << ptr_constructor_key << ")\n";
if(isVirtual) {
proxyFile.oss << " if nargin == 2\n";
proxyFile.oss << " my_ptr = varargin{2};\n";
proxyFile.oss << " else\n";
proxyFile.oss << " my_ptr = " << wrapperName << "(" << upcastFromVoidId << ", varargin{2});\n";
proxyFile.oss << " end\n";
} else {
proxyFile.oss << " my_ptr = varargin{2};\n";
}
if(qualifiedParent.empty()) // If this class has a base class, we'll get a base class pointer back
proxyFile.oss << " ";
else
proxyFile.oss << " base_ptr = ";
proxyFile.oss << wrapperName << "(" << collectorInsertId << ", my_ptr);\n"; // Call collector insert and get base class ptr
// C++ function to add pointer from MATLAB to collector. The pointer always
// comes from a C++ return value; this mechanism allows the object to be added
// to a collector in a different wrap module. If this class has a base class,
// a new pointer to the base class is allocated and returned.
wrapperFile.oss << "void " << collectorInsertFunctionName << "(int nargout, mxArray *out[], int nargin, const mxArray *in[])" << endl;
wrapperFile.oss << "{\n";
wrapperFile.oss << " mexAtExit(&_deleteAllObjects);\n";
generateUsingNamespace(wrapperFile, using_namespaces);
// Typedef boost::shared_ptr
wrapperFile.oss << " typedef boost::shared_ptr<" << cppName << "> Shared;\n";
wrapperFile.oss << "\n";
// Get self pointer passed in
wrapperFile.oss << " Shared *self = *reinterpret_cast<Shared**> (mxGetData(in[0]));\n";
// Add to collector
wrapperFile.oss << " collector_" << matlabName << ".insert(self);\n";
// If we have a base class, return the base class pointer (MATLAB will call the base class collectorInsertAndMakeBase to add this to the collector and recurse the heirarchy)
if(!qualifiedParent.empty()) {
wrapperFile.oss << "\n";
wrapperFile.oss << " typedef boost::shared_ptr<" << baseCppName << "> SharedBase;\n";
wrapperFile.oss << " out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);\n";
wrapperFile.oss << " *reinterpret_cast<SharedBase**>(mxGetData(out[0])) = new SharedBase(*self);\n";
}
wrapperFile.oss << "}\n";
// If this is a virtual function, C++ function to dynamic upcast it from a
// shared_ptr<void>. This mechanism allows automatic dynamic creation of the
// real underlying derived-most class when a C++ method returns a virtual
// base class.
if(isVirtual)
wrapperFile.oss <<
"\n"
"void " << upcastFromVoidFunctionName << "(int nargout, mxArray *out[], int nargin, const mxArray *in[]) {\n"
" mexAtExit(&_deleteAllObjects);\n"
" typedef boost::shared_ptr<" << cppName << "> Shared;\n"
" boost::shared_ptr<void> *asVoid = *reinterpret_cast<boost::shared_ptr<void>**> (mxGetData(in[0]));\n"
" out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);\n"
" Shared *self = new Shared(boost::static_pointer_cast<" << cppName << ">(*asVoid));\n"
" *reinterpret_cast<Shared**>(mxGetData(out[0])) = self;\n"
"}\n";
}
/* ************************************************************************* */
vector<ArgumentList> expandArgumentListsTemplate(const vector<ArgumentList>& argLists, const string& templateArg, const vector<string>& instName) {
vector<ArgumentList> result;
BOOST_FOREACH(const ArgumentList& argList, argLists) {
ArgumentList instArgList;
BOOST_FOREACH(const Argument& arg, argList) {
Argument instArg = arg;
if(arg.type == templateArg) {
instArg.namespaces.assign(instName.begin(), instName.end()-1);
instArg.type = instName.back();
}
instArgList.push_back(instArg);
}
result.push_back(instArgList);
}
return result;
}
/* ************************************************************************* */
template<class METHOD>
map<string, METHOD> expandMethodTemplate(const map<string, METHOD>& methods, const string& templateArg, const vector<string>& instName) {
map<string, METHOD> result;
typedef pair<const string, METHOD> Name_Method;
BOOST_FOREACH(const Name_Method& name_method, methods) {
const METHOD& method = name_method.second;
METHOD instMethod = method;
instMethod.argLists = expandArgumentListsTemplate(method.argLists, templateArg, instName);
instMethod.returnVals.clear();
BOOST_FOREACH(const ReturnValue& retVal, method.returnVals) {
ReturnValue instRetVal = retVal;
if(retVal.type1 == templateArg) {
instRetVal.namespaces1.assign(instName.begin(), instName.end()-1);
instRetVal.type1 = instName.back();
}
if(retVal.type2 == templateArg) {
instRetVal.namespaces2.assign(instName.begin(), instName.end()-1);
instRetVal.type2 = instName.back();
}
instMethod.returnVals.push_back(instRetVal);
}
result.insert(make_pair(name_method.first, instMethod));
}
return result;
}
/* ************************************************************************* */
Class expandClassTemplate(const Class& cls, const string& templateArg, const vector<string>& instName) {
Class inst;
inst.name = cls.name;
inst.templateArgs = cls.templateArgs;
inst.typedefName = cls.typedefName;
inst.isVirtual = cls.isVirtual;
inst.qualifiedParent = cls.qualifiedParent;
inst.methods = expandMethodTemplate(cls.methods, templateArg, instName);
inst.static_methods = expandMethodTemplate(cls.static_methods, templateArg, instName);
inst.namespaces = cls.namespaces;
inst.using_namespaces = cls.using_namespaces;
bool allIncludesEmpty = true;
BOOST_FOREACH(const string& inc, cls.includes) { if(!inc.empty()) { allIncludesEmpty = false; break; } }
if(allIncludesEmpty)
inst.includes.push_back(cls.name + ".h");
else
inst.includes = cls.includes;
inst.constructor = cls.constructor;
inst.constructor.args_list = expandArgumentListsTemplate(cls.constructor.args_list, templateArg, instName);
inst.constructor.name = inst.name;
inst.deconstructor = cls.deconstructor;
inst.deconstructor.name = inst.name;
inst.verbose_ = cls.verbose_;
return inst;
}
/* ************************************************************************* */
vector<Class> Class::expandTemplate(const string& templateArg, const vector<vector<string> >& instantiations) const {
vector<Class> result;
BOOST_FOREACH(const vector<string>& instName, instantiations) {
Class inst = expandClassTemplate(*this, templateArg, instName);
inst.name = name + instName.back();
inst.templateArgs.clear();
inst.typedefName = qualifiedName("::") + "<" + wrap::qualifiedName("::", instName) + ">";
result.push_back(inst);
}
return result;
}
/* ************************************************************************* */
Class Class::expandTemplate(const string& templateArg, const vector<string>& instantiation) const {
return expandClassTemplate(*this, templateArg, instantiation);
}
/* ************************************************************************* */
std::string Class::getTypedef() const {
string result;
BOOST_FOREACH(const string& namesp, namespaces) {
result += ("namespace " + namesp + " { ");
}
result += ("typedef " + typedefName + " " + name + ";");
BOOST_FOREACH(const string& namesp, namespaces) {
result += " }";
}
return result;
}
/* ************************************************************************* */

View File

@ -14,44 +14,58 @@
* @brief describe the C++ class that is being wrapped
* @author Frank Dellaert
* @author Andrew Melim
* @author Richard Roberts
**/
#pragma once
#include <string>
#include <map>
#include "Constructor.h"
#include "Deconstructor.h"
#include "Method.h"
#include "StaticMethod.h"
#include "TypeAttributesTable.h"
namespace wrap {
/// Class has name, constructors, methods
struct Class {
typedef std::map<std::string, Method> Methods;
typedef std::map<std::string, StaticMethod> StaticMethods;
/// Constructor creates an empty class
Class(bool verbose=true) : verbose_(verbose) {}
Class(bool verbose=true) : isVirtual(false), verbose_(verbose) {}
// Then the instance variables are set directly by the Module constructor
std::string name; ///< Class name
std::vector<Method> methods; ///< Class methods
std::vector<StaticMethod> static_methods; ///< Static methods
std::vector<std::string> templateArgs; ///< Template arguments
std::string typedefName; ///< The name to typedef *from*, if this class is actually a typedef, i.e. typedef [typedefName] [name]
bool isVirtual; ///< Whether the class is part of a virtual inheritance chain
std::vector<std::string> qualifiedParent; ///< The *single* parent - the last string is the parent class name, preceededing elements are a namespace stack
Methods methods; ///< Class methods
StaticMethods static_methods; ///< Static methods
std::vector<std::string> namespaces; ///< Stack of namespaces
std::vector<std::string> using_namespaces; ///< default namespaces
std::vector<std::string> using_namespaces;///< default namespaces
std::vector<std::string> includes; ///< header include overrides
Constructor constructor; ///< Class constructors
Constructor constructor; ///< Class constructors
Deconstructor deconstructor; ///< Deconstructor to deallocate C++ object
bool verbose_; ///< verbose flag
// And finally MATLAB code is emitted, methods below called by Module::matlab_code
void matlab_proxy(const std::string& classFile) const; ///< emit proxy class
void matlab_constructors(const std::string& toolboxPath) const; ///< emit constructor wrappers
void matlab_methods(const std::string& classPath) const; ///< emit method wrappers
void matlab_static_methods(const std::string& classPath) const; ///< emit static method wrappers
void matlab_make_fragment(FileWriter& file,
const std::string& toolboxPath,
const std::string& mexFlags) const; ///< emit make fragment for global make script
void makefile_fragment(FileWriter& file) const; ///< emit makefile fragment
void matlab_proxy(const std::string& classFile, const std::string& wrapperName, const TypeAttributesTable& typeAttributes,
FileWriter& wrapperFile, std::vector<std::string>& functionNames) const; ///< emit proxy class
std::string qualifiedName(const std::string& delim = "") const; ///< creates a namespace-qualified name, optional delimiter
std::vector<Class> expandTemplate(const std::string& templateArg, const std::vector<std::vector<std::string> >& instantiations) const;
Class expandTemplate(const std::string& templateArg, const std::vector<std::string>& instantiation) const;
// The typedef line for this class, if this class is a typedef, otherwise returns an empty string.
std::string getTypedef() const;
private:
void pointer_constructor_fragments(FileWriter& proxyFile, FileWriter& wrapperFile, const std::string& wrapperName, std::vector<std::string>& functionNames) const;
};
} // \namespace wrap

View File

@ -13,6 +13,7 @@
* @file Constructor.ccp
* @author Frank Dellaert
* @author Andrew Melim
* @author Richard Roberts
**/
#include <iostream>
@ -20,6 +21,7 @@
#include <algorithm>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include "utilities.h"
#include "Constructor.h"
@ -35,11 +37,11 @@ string Constructor::matlab_wrapper_name(const string& className) const {
}
/* ************************************************************************* */
void Constructor::matlab_proxy_fragment(FileWriter& file,
const string& className, const int id, const ArgumentList args) const {
void Constructor::proxy_fragment(FileWriter& file, const std::string& wrapperName,
const string& matlabName, const string& matlabBaseName, const int id, const ArgumentList args) const {
size_t nrArgs = args.size();
// check for number of arguments...
file.oss << " if (nargin == " << nrArgs;
file.oss << " elseif nargin == " << nrArgs;
if (nrArgs>0) file.oss << " && ";
// ...and their types
bool first = true;
@ -49,117 +51,60 @@ void Constructor::matlab_proxy_fragment(FileWriter& file,
first=false;
}
// emit code for calling constructor
file.oss << "), obj.self = " << matlab_wrapper_name(className) << "(" << "0," << id;
if(matlabBaseName.empty())
file.oss << "\n my_ptr = ";
else
file.oss << "\n [ my_ptr, base_ptr ] = ";
file.oss << wrapperName << "(" << id;
// emit constructor arguments
for(size_t i=0;i<nrArgs;i++) {
file.oss << ",";
file.oss << ", ";
file.oss << "varargin{" << i+1 << "}";
}
file.oss << "); end" << endl;
file.oss << ");\n";
}
/* ************************************************************************* */
void Constructor::matlab_mfile(const string& toolboxPath, const string& qualifiedMatlabName, const ArgumentList args) const {
string matlabName = matlab_wrapper_name(qualifiedMatlabName);
// open destination m-file
string wrapperFile = toolboxPath + "/" + matlabName + ".m";
FileWriter file(wrapperFile, verbose_, "%");
// generate code
file.oss << "function result = " << matlabName << "(obj";
if (args.size()) file.oss << "," << args.names();
file.oss << ")" << endl;
file.oss << " error('need to compile " << matlabName << ".cpp');" << endl;
file.oss << "end" << endl;
// close file
file.emit(true);
}
/* ************************************************************************* */
void Constructor::matlab_wrapper(const string& toolboxPath,
string Constructor::wrapper_fragment(FileWriter& file,
const string& cppClassName,
const string& matlabClassName,
const string& cppBaseClassName,
int id,
const vector<string>& using_namespaces,
const vector<string>& includes) const {
string matlabName = matlab_wrapper_name(matlabClassName);
const ArgumentList& al) const {
// open destination wrapperFile
string wrapperFile = toolboxPath + "/" + matlabName + ".cpp";
FileWriter file(wrapperFile, verbose_, "//");
// generate code
generateIncludes(file, name, includes);
generateUsingNamespace(file, using_namespaces);
const string wrapFunctionName = matlabClassName + "_constructor_" + boost::lexical_cast<string>(id);
file.oss << "void " << wrapFunctionName << "(int nargout, mxArray *out[], int nargin, const mxArray *in[])" << endl;
file.oss << "{\n";
file.oss << " mexAtExit(&_deleteAllObjects);\n";
generateUsingNamespace(file, using_namespaces);
//Typedef boost::shared_ptr
file.oss << "typedef boost::shared_ptr<" << cppClassName << "> Shared;" << endl;
file.oss << endl;
file.oss << " typedef boost::shared_ptr<" << cppClassName << "> Shared;\n";
file.oss << "\n";
//Generate collector
file.oss << "static std::set<Shared*> collector;" << endl;
file.oss << endl;
//Check to see if there will be any arguments and remove {} for consiseness
if(al.size() > 0)
al.matlab_unwrap(file); // unwrap arguments
file.oss << " Shared *self = new Shared(new " << cppClassName << "(" << al.names() << "));" << endl;
file.oss << " collector_" << matlabClassName << ".insert(self);\n";
//Generate cleanup function
file.oss << "void cleanup(void) {" << endl;
file.oss << " for(std::set<Shared*>::iterator iter = collector.begin(); iter != collector.end(); ) {\n";
file.oss << " delete *iter;\n";
file.oss << " collector.erase(iter++);\n";
file.oss << " }\n";
file.oss << "}" << endl;
if(verbose_)
file.oss << " std::cout << \"constructed \" << self << \" << std::endl;" << endl;
file.oss << " out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);" << endl;
file.oss << " *reinterpret_cast<Shared**> (mxGetData(out[0])) = self;" << endl;
file.oss << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])" << endl;
file.oss << "{" << endl;
//Cleanup function callback
file.oss << " mexAtExit(cleanup);" << endl;
file.oss << endl;
file.oss << " const mxArray* input = in[0];" << endl;
file.oss << " Shared* self = *(Shared**) mxGetData(input);" << endl;
file.oss << endl;
file.oss << " if(self) {" << endl;
file.oss << " if(nargin > 1) {" << endl;
file.oss << " collector.insert(self);" << endl;
if(verbose_)
file.oss << " std::cout << \"Collected\" << collector.size() << std::endl;" << endl;
file.oss << " }" << endl;
file.oss << " else if(collector.erase(self))" << endl;
file.oss << " delete self;" << endl;
file.oss << " } else {" << endl;
file.oss << " int nc = unwrap<int>(in[1]);" << endl << endl;
int i = 0;
BOOST_FOREACH(ArgumentList al, args_list)
{
//Check to see if there will be any arguments and remove {} for consiseness
if(al.size())
{
file.oss << " if(nc == " << i <<") {" << endl;
al.matlab_unwrap(file, 2); // unwrap arguments, start at 1
file.oss << " self = new Shared(new " << cppClassName << "(" << al.names() << "));" << endl;
file.oss << " }" << endl;
}
else
{
file.oss << " if(nc == " << i <<")" << endl;
file.oss << " self = new Shared(new " << cppClassName << "(" << al.names() << "));" << endl;
}
i++;
}
//file.oss << " self = construct(nc, in);" << endl;
file.oss << " collector.insert(self);" << endl;
if(verbose_)
file.oss << " std::cout << \"constructed \" << self << \", size=\" << collector.size() << std::endl;" << endl;
file.oss << " out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);" << endl;
file.oss << " *reinterpret_cast<Shared**> (mxGetPr(out[0])) = self;" << endl;
file.oss << " }" << endl;
// If we have a base class, return the base class pointer (MATLAB will call the base class collectorInsertAndMakeBase to add this to the collector and recurse the heirarchy)
if(!cppBaseClassName.empty()) {
file.oss << "\n";
file.oss << " typedef boost::shared_ptr<" << cppBaseClassName << "> SharedBase;\n";
file.oss << " out[1] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);\n";
file.oss << " *reinterpret_cast<SharedBase**>(mxGetData(out[1])) = new SharedBase(*self);\n";
}
file.oss << "}" << endl;
// close file
file.emit(true);
return wrapFunctionName;
}
/* ************************************************************************* */

View File

@ -13,6 +13,7 @@
* @file Constructor.h
* @brief class describing a constructor + code generation
* @author Frank Dellaert
* @author Richard Roberts
**/
#pragma once
@ -48,21 +49,18 @@ struct Constructor {
* Create fragment to select constructor in proxy class, e.g.,
* if nargin == 2, obj.self = new_Pose3_RP(varargin{1},varargin{2}); end
*/
void matlab_proxy_fragment(FileWriter& file,
const std::string& className, const int i,
void proxy_fragment(FileWriter& file, const std::string& wrapperName,
const std::string& className, const std::string& matlabBaseName, const int id,
const ArgumentList args) const;
/// m-file
void matlab_mfile(const std::string& toolboxPath,
const std::string& qualifiedMatlabName,
const ArgumentList args) const;
/// cpp wrapper
void matlab_wrapper(const std::string& toolboxPath,
std::string wrapper_fragment(FileWriter& file,
const std::string& cppClassName,
const std::string& matlabClassName,
const std::string& cppBaseClassName,
int id,
const std::vector<std::string>& using_namespaces,
const std::vector<std::string>& includes) const;
const ArgumentList& al) const;
/// constructor function
void generate_construct(FileWriter& file, const std::string& cppClassName,

View File

@ -13,12 +13,14 @@
* @file Deconstructor.ccp
* @author Frank Dellaert
* @author Andrew Melim
* @author Richard Roberts
**/
#include <iostream>
#include <fstream>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include "utilities.h"
#include "Deconstructor.h"
@ -33,51 +35,42 @@ string Deconstructor::matlab_wrapper_name(const string& className) const {
}
/* ************************************************************************* */
void Deconstructor::matlab_mfile(const string& toolboxPath, const string& qualifiedMatlabName) const {
void Deconstructor::proxy_fragment(FileWriter& file,
const std::string& wrapperName,
const std::string& qualifiedMatlabName, int id) const {
string matlabName = matlab_wrapper_name(qualifiedMatlabName);
// open destination m-file
string wrapperFile = toolboxPath + "/" + matlabName + ".m";
FileWriter file(wrapperFile, verbose_, "%");
// generate code
file.oss << "function result = " << matlabName << "(obj";
if (args.size()) file.oss << "," << args.names();
file.oss << ")" << endl;
file.oss << " error('need to compile " << matlabName << ".cpp');" << endl;
file.oss << "end" << endl;
// close file
file.emit(true);
file.oss << " function delete(obj)\n";
file.oss << " " << wrapperName << "(" << id << ", obj.ptr_" << qualifiedMatlabName << ");\n";
file.oss << " end\n";
}
/* ************************************************************************* */
void Deconstructor::matlab_wrapper(const string& toolboxPath,
string Deconstructor::wrapper_fragment(FileWriter& file,
const string& cppClassName,
const string& matlabClassName,
const vector<string>& using_namespaces, const vector<string>& includes) const {
string matlabName = matlab_wrapper_name(matlabClassName);
int id,
const vector<string>& using_namespaces) const {
const string matlabName = matlab_wrapper_name(matlabClassName);
// open destination wrapperFile
string wrapperFile = toolboxPath + "/" + matlabName + ".cpp";
FileWriter file(wrapperFile, verbose_, "//");
// generate code
//
generateIncludes(file, name, includes);
cout << "Generate includes " << name << endl;
generateUsingNamespace(file, using_namespaces);
const string wrapFunctionName = matlabClassName + "_deconstructor_" + boost::lexical_cast<string>(id);
file.oss << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])" << endl;
file.oss << "void " << wrapFunctionName << "(int nargout, mxArray *out[], int nargin, const mxArray *in[])" << endl;
file.oss << "{" << endl;
generateUsingNamespace(file, using_namespaces);
file.oss << " typedef boost::shared_ptr<" << cppClassName << "> Shared;" << endl;
//Deconstructor takes 1 arg, the mxArray obj
file.oss << " checkArguments(\"" << matlabName << "\",nargout,nargin," << "1" << ");" << endl;
file.oss << " delete_shared_ptr< " << cppClassName << " >(in[0],\"" << matlabClassName << "\");" << endl;
file.oss << " Shared *self = *reinterpret_cast<Shared**>(mxGetData(in[0]));\n";
file.oss << " Collector_" << matlabClassName << "::iterator item;\n";
file.oss << " item = collector_" << matlabClassName << ".find(self);\n";
file.oss << " if(item != collector_" << matlabClassName << ".end()) {\n";
file.oss << " delete self;\n";
file.oss << " collector_" << matlabClassName << ".erase(item);\n";
file.oss << " }\n";
file.oss << "}" << endl;
// close file
file.emit(true);
return wrapFunctionName;
}
/* ************************************************************************* */

View File

@ -14,6 +14,7 @@
* @brief class describing a constructor + code generation
* @author Frank Dellaert
* @author Andrew Melim
* @author Richard Roberts
**/
#pragma once
@ -34,7 +35,6 @@ struct Deconstructor {
}
// Then the instance variables are set directly by the Module deconstructor
ArgumentList args;
std::string name;
bool verbose_;
@ -46,15 +46,16 @@ struct Deconstructor {
std::string matlab_wrapper_name(const std::string& className) const;
/// m-file
void matlab_mfile(const std::string& toolboxPath,
const std::string& qualifiedMatlabName) const;
void proxy_fragment(FileWriter& file,
const std::string& wrapperName,
const std::string& qualifiedMatlabName, int id) const;
/// cpp wrapper
void matlab_wrapper(const std::string& toolboxPath,
std::string wrapper_fragment(FileWriter& file,
const std::string& cppClassName,
const std::string& matlabClassName,
const std::vector<std::string>& using_namespaces,
const std::vector<std::string>& includes) const;
int id,
const std::vector<std::string>& using_namespaces) const;
};
} // \namespace wrap

32
wrap/ForwardDeclaration.h Normal file
View File

@ -0,0 +1,32 @@
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file Class.h
* @brief describe the C++ class that is being wrapped
* @author Frank Dellaert
* @author Andrew Melim
* @author Richard Roberts
**/
#pragma once
#include <string>
namespace wrap {
struct ForwardDeclaration {
std::string name;
bool isVirtual;
ForwardDeclaration() : isVirtual(false) {}
};
}

View File

@ -12,12 +12,14 @@
/**
* @file Method.ccp
* @author Frank Dellaert
* @author Richard Roberts
**/
#include <iostream>
#include <fstream>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include "Method.h"
#include "utilities.h"
@ -26,57 +28,108 @@ using namespace std;
using namespace wrap;
/* ************************************************************************* */
void Method::matlab_mfile(const string& classPath) const {
void Method::addOverload(bool verbose, bool is_const, const std::string& name,
const ArgumentList& args, const ReturnValue& retVal) {
this->verbose_ = verbose;
this->is_const_ = is_const;
this->name = name;
this->argLists.push_back(args);
this->returnVals.push_back(retVal);
}
// open destination m-file
string wrapperFile = classPath + "/" + name + ".m";
FileWriter file(wrapperFile, verbose_, "%");
void Method::proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wrapperFile,
const string& cppClassName,
const string& matlabClassName,
const string& wrapperName,
const vector<string>& using_namespaces,
const TypeAttributesTable& typeAttributes,
vector<string>& functionNames) const {
// generate code
string returnType = returnVal.matlab_returnType();
file.oss << "% " << returnType << " = obj." << name << "(" << args.names() << ")" << endl;
file.oss << "function " << returnType << " = " << name << "(obj";
if (args.size()) file.oss << "," << args.names();
file.oss << ")" << endl;
file.oss << " error('need to compile " << name << ".cpp');" << endl;
file.oss << "end" << endl;
proxyFile.oss << " function varargout = " << name << "(this, varargin)\n";
// close file
file.emit(false);
for(size_t overload = 0; overload < argLists.size(); ++overload) {
const ArgumentList& args = argLists[overload];
const ReturnValue& returnVal = returnVals[overload];
size_t nrArgs = args.size();
const int id = functionNames.size();
// Output proxy matlab code
// check for number of arguments...
proxyFile.oss << " " << (overload==0?"":"else") << "if length(varargin) == " << nrArgs;
if (nrArgs>0) proxyFile.oss << " && ";
// ...and their types
bool first = true;
for(size_t i=0;i<nrArgs;i++) {
if (!first) proxyFile.oss << " && ";
proxyFile.oss << "isa(varargin{" << i+1 << "},'" << args[i].matlabClass() << "')";
first=false;
}
proxyFile.oss << "\n";
// output call to C++ wrapper
string output;
if(returnVal.isPair)
output = "[ varargout{1} varargout{2} ] = ";
else if(returnVal.category1 == ReturnValue::VOID)
output = "";
else
output = "varargout{1} = ";
proxyFile.oss << " " << output << wrapperName << "(" << id << ", this, varargin{:});\n";
// Output C++ wrapper code
const string wrapFunctionName = wrapper_fragment(
wrapperFile, cppClassName, matlabClassName, overload, id, using_namespaces, typeAttributes);
// Add to function list
functionNames.push_back(wrapFunctionName);
}
proxyFile.oss << " else\n";
proxyFile.oss << " error('Arguments do not match any overload of function " <<
matlabClassName << "." << name << "');" << endl;
proxyFile.oss << " end\n";
proxyFile.oss << " end\n";
}
/* ************************************************************************* */
void Method::matlab_wrapper(const string& classPath,
const string& className,
string Method::wrapper_fragment(FileWriter& file,
const string& cppClassName,
const string& matlabClassName,
const vector<string>& using_namespaces, const std::vector<std::string>& includes) const {
// open destination wrapperFile
string wrapperFile = classPath + "/" + name + ".cpp";
FileWriter file(wrapperFile, verbose_, "//");
int overload,
int id,
const vector<string>& using_namespaces,
const TypeAttributesTable& typeAttributes) const {
// generate code
// header
generateIncludes(file, className, includes);
generateUsingNamespace(file, using_namespaces);
const string wrapFunctionName = matlabClassName + "_" + name + "_" + boost::lexical_cast<string>(id);
const ArgumentList& args = argLists[overload];
const ReturnValue& returnVal = returnVals[overload];
// call
file.oss << "void " << wrapFunctionName << "(int nargout, mxArray *out[], int nargin, const mxArray *in[])\n";
// start
file.oss << "{\n";
generateUsingNamespace(file, using_namespaces);
if(returnVal.isPair)
{
if(returnVal.category1 == ReturnValue::CLASS)
file.oss << "typedef boost::shared_ptr<" << returnVal.qualifiedType1("::") << "> Shared" << returnVal.type1 << ";"<< endl;
file.oss << " typedef boost::shared_ptr<" << returnVal.qualifiedType1("::") << "> Shared" << returnVal.type1 << ";"<< endl;
if(returnVal.category2 == ReturnValue::CLASS)
file.oss << "typedef boost::shared_ptr<" << returnVal.qualifiedType2("::") << "> Shared" << returnVal.type2 << ";"<< endl;
file.oss << " typedef boost::shared_ptr<" << returnVal.qualifiedType2("::") << "> Shared" << returnVal.type2 << ";"<< endl;
}
else
if(returnVal.category1 == ReturnValue::CLASS)
file.oss << "typedef boost::shared_ptr<" << returnVal.qualifiedType1("::") << "> Shared" << returnVal.type1 << ";"<< endl;
file.oss << " typedef boost::shared_ptr<" << returnVal.qualifiedType1("::") << "> Shared" << returnVal.type1 << ";"<< endl;
file.oss << "typedef boost::shared_ptr<" << cppClassName << "> Shared;" << endl;
// call
file.oss << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])\n";
// start
file.oss << "{\n";
file.oss << " typedef boost::shared_ptr<" << cppClassName << "> Shared;" << endl;
// check arguments
// extra argument obj -> nargin-1 is passed !
@ -85,26 +138,21 @@ void Method::matlab_wrapper(const string& classPath,
// get class pointer
// example: shared_ptr<Test> = unwrap_shared_ptr< Test >(in[0], "Test");
file.oss << " Shared obj = unwrap_shared_ptr<" << cppClassName << ">(in[0], \"" << cppClassName << "\");" << endl;
file.oss << " Shared obj = unwrap_shared_ptr<" << cppClassName << ">(in[0], \"ptr_" << matlabClassName << "\");" << endl;
// unwrap arguments, see Argument.cpp
args.matlab_unwrap(file,1);
// call method
// example: bool result = self->return_field(t);
file.oss << " ";
// call method and wrap result
// example: out[0]=wrap<bool>(self->return_field(t));
if (returnVal.type1!="void")
file.oss << returnVal.return_type(true,ReturnValue::pair) << " result = ";
file.oss << "obj->" << name << "(" << args.names() << ");\n";
// wrap result
// example: out[0]=wrap<bool>(result);
returnVal.wrap_result(file);
returnVal.wrap_result("obj->"+name+"("+args.names()+")", file, typeAttributes);
else
file.oss << " obj->"+name+"("+args.names()+");\n";
// finish
file.oss << "}\n";
// close file
file.emit(true);
return wrapFunctionName;
}
/* ************************************************************************* */

View File

@ -13,6 +13,7 @@
* @file Method.h
* @brief describes and generates code for methods
* @author Frank Dellaert
* @author Richard Roberts
**/
#pragma once
@ -22,6 +23,7 @@
#include "Argument.h"
#include "ReturnValue.h"
#include "TypeAttributesTable.h"
namespace wrap {
@ -30,25 +32,37 @@ struct Method {
/// Constructor creates empty object
Method(bool verbose = true) :
verbose_(verbose) {}
verbose_(verbose), is_const_(false) {}
// Then the instance variables are set directly by the Module constructor
bool verbose_;
bool is_const_;
std::string name;
ArgumentList args;
ReturnValue returnVal;
std::vector<ArgumentList> argLists;
std::vector<ReturnValue> returnVals;
// The first time this function is called, it initializes the class members
// with those in rhs, but in subsequent calls it adds additional argument
// lists as function overloads.
void addOverload(bool verbose, bool is_const, const std::string& name,
const ArgumentList& args, const ReturnValue& retVal);
// MATLAB code generation
// classPath is class directory, e.g., ../matlab/@Point2
void proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wrapperFile,
const std::string& cppClassName, const std::string& matlabClassName,
const std::string& wrapperName, const std::vector<std::string>& using_namespaces,
const TypeAttributesTable& typeAttributes,
std::vector<std::string>& functionNames) const;
void matlab_mfile(const std::string& classPath) const; ///< m-file
void matlab_wrapper(const std::string& classPath,
const std::string& className,
private:
std::string wrapper_fragment(FileWriter& file,
const std::string& cppClassName,
const std::string& matlabClassname,
int overload,
int id,
const std::vector<std::string>& using_namespaces,
const std::vector<std::string>& includes) const; ///< cpp wrapper
const TypeAttributesTable& typeAttributes) const; ///< cpp wrapper
};
} // \namespace wrap

View File

@ -1,389 +1,604 @@
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file Module.ccp
* @author Frank Dellaert
* @author Alex Cunningham
* @author Andrew Melim
**/
#include "Module.h"
#include "FileWriter.h"
#include "utilities.h"
#include "spirit_actors.h"
//#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/classic_confix.hpp>
#include <boost/spirit/include/classic_clear_actor.hpp>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <algorithm>
using namespace std;
using namespace wrap;
using namespace BOOST_SPIRIT_CLASSIC_NS;
namespace fs = boost::filesystem;
typedef rule<BOOST_SPIRIT_CLASSIC_NS::phrase_scanner_t> Rule;
/* ************************************************************************* */
// We parse an interface file into a Module object.
// The grammar is defined using the boost/spirit combinatorial parser.
// For example, str_p("const") parses the string "const", and the >>
// operator creates a sequence parser. The grammar below, composed of rules
// and with start rule [class_p], doubles as the specs for our interface files.
/* ************************************************************************* */
Module::Module(const string& interfacePath,
const string& moduleName, bool enable_verbose) : name(moduleName), verbose(enable_verbose)
{
// these variables will be imperatively updated to gradually build [cls]
// The one with postfix 0 are used to reset the variables after parse.
ReturnValue retVal0, retVal;
Argument arg0, arg;
ArgumentList args0, args;
vector<string> arg_dup; ///keep track of duplicates
Constructor constructor0(enable_verbose), constructor(enable_verbose);
//Deconstructor deconstructor0(enable_verbose), deconstructor(enable_verbose);
Method method0(enable_verbose), method(enable_verbose);
StaticMethod static_method0(enable_verbose), static_method(enable_verbose);
Class cls0(enable_verbose),cls(enable_verbose);
vector<string> namespaces, /// current namespace tag
namespace_includes, /// current set of includes
namespaces_return, /// namespace for current return type
using_namespace_current; /// All namespaces from "using" declarations
string include_path = "";
string class_name = "";
const string null_str = "";
//----------------------------------------------------------------------------
// Grammar with actions that build the Class object. Actions are
// defined within the square brackets [] and are executed whenever a
// rule is successfully parsed. Define BOOST_SPIRIT_DEBUG to debug.
// The grammar is allows a very restricted C++ header
// lexeme_d turns off white space skipping
// http://www.boost.org/doc/libs/1_37_0/libs/spirit/classic/doc/directives.html
// ----------------------------------------------------------------------------
Rule comments_p = comment_p("/*", "*/") | comment_p("//", eol_p);
Rule basisType_p =
(str_p("string") | "bool" | "size_t" | "int" | "double" | "char" | "unsigned char");
Rule keywords_p =
(str_p("const") | "static" | "namespace" | basisType_p);
Rule eigenType_p =
(str_p("Vector") | "Matrix");
Rule className_p = (lexeme_d[upper_p >> *(alnum_p | '_')] - eigenType_p - keywords_p)[assign_a(class_name)];
Rule namespace_name_p = lexeme_d[lower_p >> *(alnum_p | '_')] - keywords_p;
Rule namespace_arg_p = namespace_name_p[push_back_a(arg.namespaces)] >> str_p("::");
Rule argEigenType_p =
eigenType_p[assign_a(arg.type)] >>
!ch_p('*')[assign_a(arg.is_ptr,true)];
Rule eigenRef_p =
!str_p("const") [assign_a(arg.is_const,true)] >>
eigenType_p [assign_a(arg.type)] >>
ch_p('&') [assign_a(arg.is_ref,true)];
Rule classArg_p =
!str_p("const") [assign_a(arg.is_const,true)] >>
*namespace_arg_p >>
className_p[assign_a(arg.type)] >>
(ch_p('*')[assign_a(arg.is_ptr,true)] | ch_p('&')[assign_a(arg.is_ref,true)]);
Rule name_p = lexeme_d[alpha_p >> *(alnum_p | '_')];
Rule argument_p =
((basisType_p[assign_a(arg.type)] | argEigenType_p | eigenRef_p | classArg_p)
>> name_p[assign_a(arg.name)])
[push_back_a(args, arg)]
[assign_a(arg,arg0)];
Rule argumentList_p = !argument_p >> * (',' >> argument_p);
Rule constructor_p =
(className_p >> '(' >> argumentList_p >> ')' >> ';' >> !comments_p)
[push_back_a(constructor.args_list, args)]
[assign_a(args,args0)];
//[assign_a(constructor.args,args)]
//[assign_a(constructor.name,cls.name)]
//[push_back_a(cls.constructors, constructor)]
//[assign_a(constructor,constructor0)];
Rule namespace_ret_p = namespace_name_p[push_back_a(namespaces_return)] >> str_p("::");
Rule returnType1_p =
(basisType_p[assign_a(retVal.type1)][assign_a(retVal.category1, ReturnValue::BASIS)]) |
((*namespace_ret_p)[assign_a(retVal.namespaces1, namespaces_return)][clear_a(namespaces_return)]
>> (className_p[assign_a(retVal.type1)][assign_a(retVal.category1, ReturnValue::CLASS)]) >>
!ch_p('*')[assign_a(retVal.isPtr1,true)]) |
(eigenType_p[assign_a(retVal.type1)][assign_a(retVal.category1, ReturnValue::EIGEN)]);
Rule returnType2_p =
(basisType_p[assign_a(retVal.type2)][assign_a(retVal.category2, ReturnValue::BASIS)]) |
((*namespace_ret_p)[assign_a(retVal.namespaces2, namespaces_return)][clear_a(namespaces_return)]
>> (className_p[assign_a(retVal.type2)][assign_a(retVal.category2, ReturnValue::CLASS)]) >>
!ch_p('*') [assign_a(retVal.isPtr2,true)]) |
(eigenType_p[assign_a(retVal.type2)][assign_a(retVal.category2, ReturnValue::EIGEN)]);
Rule pair_p =
(str_p("pair") >> '<' >> returnType1_p >> ',' >> returnType2_p >> '>')
[assign_a(retVal.isPair,true)];
Rule void_p = str_p("void")[assign_a(retVal.type1)];
Rule returnType_p = void_p | returnType1_p | pair_p;
Rule methodName_p = lexeme_d[lower_p >> *(alnum_p | '_')];
Rule method_p =
(returnType_p >> methodName_p[assign_a(method.name)] >>
'(' >> argumentList_p >> ')' >>
!str_p("const")[assign_a(method.is_const_,true)] >> ';' >> *comments_p)
[assign_a(method.args,args)]
[assign_a(args,args0)]
[assign_a(method.returnVal,retVal)]
[assign_a(retVal,retVal0)]
[push_back_a(cls.methods, method)]
[assign_a(method,method0)];
Rule staticMethodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')];
Rule static_method_p =
(str_p("static") >> returnType_p >> staticMethodName_p[assign_a(static_method.name)] >>
'(' >> argumentList_p >> ')' >> ';' >> *comments_p)
[assign_a(static_method.args,args)]
[assign_a(args,args0)]
[assign_a(static_method.returnVal,retVal)]
[assign_a(retVal,retVal0)]
[push_back_a(cls.static_methods, static_method)]
[assign_a(static_method,static_method0)];
Rule functions_p = constructor_p | method_p | static_method_p;
Rule include_p = str_p("#include") >> ch_p('<') >> (*(anychar_p - '>'))[assign_a(include_path)] >> ch_p('>');
Rule class_p =
(!*include_p
>> str_p("class")[push_back_a(cls.includes, include_path)][assign_a(include_path, null_str)]
>> className_p[assign_a(cls.name)]
>> '{'
>> *(functions_p | comments_p)
>> str_p("};"))
[assign_a(constructor.name, cls.name)]
[assign_a(cls.constructor, constructor)]
[assign_a(cls.namespaces, namespaces)]
[assign_a(cls.using_namespaces, using_namespace_current)]
[append_a(cls.includes, namespace_includes)]
//[assign_a(deconstructor.name,cls.name)]
//[assign_a(cls.d, deconstructor)]
[push_back_a(classes,cls)]
//[assign_a(deconstructor,deconstructor0)]
[assign_a(constructor, constructor0)]
[assign_a(cls,cls0)];
Rule namespace_def_p =
(!*include_p
>> str_p("namespace")[push_back_a(namespace_includes, include_path)][assign_a(include_path, null_str)]
>> namespace_name_p[push_back_a(namespaces)]
>> ch_p('{')
>> *(class_p | namespace_def_p | comments_p)
>> str_p("}///\\namespace") // end namespace, avoid confusion with classes
>> !namespace_name_p)
[pop_a(namespaces)]
[pop_a(namespace_includes)];
Rule using_namespace_p =
str_p("using") >> str_p("namespace")
>> namespace_name_p[push_back_a(using_namespace_current)] >> ch_p(';');
Rule forward_declaration_p =
str_p("class") >>
(*(namespace_name_p >> str_p("::")) >> className_p)[push_back_a(forward_declarations)]
>> ch_p(';');
Rule module_content_p = comments_p | using_namespace_p | class_p | forward_declaration_p | namespace_def_p ;
Rule module_p = *module_content_p >> !end_p;
//----------------------------------------------------------------------------
// for debugging, define BOOST_SPIRIT_DEBUG
# ifdef BOOST_SPIRIT_DEBUG
BOOST_SPIRIT_DEBUG_NODE(className_p);
BOOST_SPIRIT_DEBUG_NODE(classPtr_p);
BOOST_SPIRIT_DEBUG_NODE(classRef_p);
BOOST_SPIRIT_DEBUG_NODE(basisType_p);
BOOST_SPIRIT_DEBUG_NODE(name_p);
BOOST_SPIRIT_DEBUG_NODE(argument_p);
BOOST_SPIRIT_DEBUG_NODE(argumentList_p);
BOOST_SPIRIT_DEBUG_NODE(constructor_p);
BOOST_SPIRIT_DEBUG_NODE(returnType1_p);
BOOST_SPIRIT_DEBUG_NODE(returnType2_p);
BOOST_SPIRIT_DEBUG_NODE(pair_p);
BOOST_SPIRIT_DEBUG_NODE(void_p);
BOOST_SPIRIT_DEBUG_NODE(returnType_p);
BOOST_SPIRIT_DEBUG_NODE(methodName_p);
BOOST_SPIRIT_DEBUG_NODE(method_p);
BOOST_SPIRIT_DEBUG_NODE(class_p);
BOOST_SPIRIT_DEBUG_NODE(namespace_def_p);
BOOST_SPIRIT_DEBUG_NODE(module_p);
# endif
//----------------------------------------------------------------------------
// read interface file
string interfaceFile = interfacePath + "/" + moduleName + ".h";
string contents = file_contents(interfaceFile);
// and parse contents
parse_info<const char*> info = parse(contents.c_str(), module_p, space_p);
if(!info.full) {
printf("parsing stopped at \n%.20s\n",info.stop);
throw ParseFailed(info.length);
}
}
/* ************************************************************************* */
template<class T>
void verifyArguments(const vector<string>& validArgs, const vector<T>& vt) {
BOOST_FOREACH(const T& t, vt) {
BOOST_FOREACH(Argument arg, t.args) {
string fullType = arg.qualifiedType("::");
if(find(validArgs.begin(), validArgs.end(), fullType)
== validArgs.end())
throw DependencyMissing(fullType, t.name);
}
}
}
/* ************************************************************************* */
template<class T>
void verifyReturnTypes(const vector<string>& validtypes, const vector<T>& vt) {
BOOST_FOREACH(const T& t, vt) {
const ReturnValue& retval = t.returnVal;
if (find(validtypes.begin(), validtypes.end(), retval.qualifiedType1("::")) == validtypes.end())
throw DependencyMissing(retval.qualifiedType1("::"), t.name);
if (retval.isPair && find(validtypes.begin(), validtypes.end(), retval.qualifiedType2("::")) == validtypes.end())
throw DependencyMissing(retval.qualifiedType2("::"), t.name);
}
}
/* ************************************************************************* */
void Module::matlab_code(const string& mexCommand, const string& toolboxPath,
const string& mexExt, const string& headerPath,const string& mexFlags) const {
fs::create_directories(toolboxPath);
// create make m-file
string matlabMakeFileName = toolboxPath + "/make_" + name + ".m";
FileWriter makeModuleMfile(matlabMakeFileName, verbose, "%");
// create the (actual) make file
string makeFileName = toolboxPath + "/Makefile";
FileWriter makeModuleMakefile(makeFileName, verbose, "#");
makeModuleMfile.oss << "echo on" << endl << endl;
makeModuleMfile.oss << "toolboxpath = mfilename('fullpath');" << endl;
makeModuleMfile.oss << "delims = find(toolboxpath == '/' | toolboxpath == '\\');" << endl;
makeModuleMfile.oss << "toolboxpath = toolboxpath(1:(delims(end)-1));" << endl;
makeModuleMfile.oss << "clear delims" << endl;
makeModuleMfile.oss << "addpath(toolboxpath);" << endl << endl;
makeModuleMakefile.oss << "\nMEX = " << mexCommand << "\n";
makeModuleMakefile.oss << "MEXENDING = " << mexExt << "\n";
makeModuleMakefile.oss << "PATH_TO_WRAP = " << headerPath << "\n";
makeModuleMakefile.oss << "mex_flags = " << mexFlags << "\n\n";
// Dependency check list
vector<string> validTypes = forward_declarations;
validTypes.push_back("void");
validTypes.push_back("string");
validTypes.push_back("int");
validTypes.push_back("bool");
validTypes.push_back("char");
validTypes.push_back("unsigned char");
validTypes.push_back("size_t");
validTypes.push_back("double");
validTypes.push_back("Vector");
validTypes.push_back("Matrix");
// add 'all' to Makefile
makeModuleMakefile.oss << "all: ";
BOOST_FOREACH(Class cls, classes) {
makeModuleMakefile.oss << cls.qualifiedName() << " ";
//Create a list of parsed classes for dependency checking
validTypes.push_back(cls.qualifiedName("::"));
}
makeModuleMakefile.oss << "\n\n";
// generate proxy classes and wrappers
BOOST_FOREACH(Class cls, classes) {
// create directory if needed
string classPath = toolboxPath + "/@" + cls.qualifiedName();
fs::create_directories(classPath);
// create proxy class
string classFile = classPath + "/" + cls.qualifiedName() + ".m";
cls.matlab_proxy(classFile);
// verify all of the function arguments
//TODO:verifyArguments<ArgumentList>(validTypes, cls.constructor.args_list);
verifyArguments<StaticMethod>(validTypes, cls.static_methods);
verifyArguments<Method>(validTypes, cls.methods);
// verify function return types
verifyReturnTypes<StaticMethod>(validTypes, cls.static_methods);
verifyReturnTypes<Method>(validTypes, cls.methods);
// create constructor and method wrappers
cls.matlab_constructors(toolboxPath);
cls.matlab_static_methods(toolboxPath);
cls.matlab_methods(classPath);
// create deconstructor
//cls.matlab_deconstructor(toolboxPath);
// add lines to make m-file
makeModuleMfile.oss << "%% " << cls.qualifiedName() << endl;
makeModuleMfile.oss << "cd(toolboxpath)" << endl;
cls.matlab_make_fragment(makeModuleMfile, toolboxPath, mexFlags);
// add section to the (actual) make file
makeModuleMakefile.oss << "# " << cls.qualifiedName() << endl;
cls.makefile_fragment(makeModuleMakefile);
}
// finish make m-file
makeModuleMfile.oss << "cd(toolboxpath)" << endl << endl;
makeModuleMfile.oss << "echo off" << endl;
makeModuleMfile.emit(true); // By default, compare existing file first
// make clean at end of Makefile
makeModuleMakefile.oss << "\n\nclean: \n";
makeModuleMakefile.oss << "\trm -rf *.$(MEXENDING)\n";
BOOST_FOREACH(Class cls, classes)
makeModuleMakefile.oss << "\trm -rf @" << cls.qualifiedName() << "/*.$(MEXENDING)\n";
// finish Makefile
makeModuleMakefile.oss << "\n" << endl;
makeModuleMakefile.emit(true);
}
/* ************************************************************************* */
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file Module.ccp
* @author Frank Dellaert
* @author Alex Cunningham
* @author Andrew Melim
* @author Richard Roberts
**/
#include "Module.h"
#include "FileWriter.h"
#include "TypeAttributesTable.h"
#include "utilities.h"
#include "spirit_actors.h"
//#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/classic_confix.hpp>
#include <boost/spirit/include/classic_clear_actor.hpp>
#include <boost/spirit/include/classic_insert_at_actor.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/construct.hpp>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <algorithm>
using namespace std;
using namespace wrap;
using namespace BOOST_SPIRIT_CLASSIC_NS;
namespace bl = boost::lambda;
namespace fs = boost::filesystem;
typedef rule<BOOST_SPIRIT_CLASSIC_NS::phrase_scanner_t> Rule;
/* ************************************************************************* */
// We parse an interface file into a Module object.
// The grammar is defined using the boost/spirit combinatorial parser.
// For example, str_p("const") parses the string "const", and the >>
// operator creates a sequence parser. The grammar below, composed of rules
// and with start rule [class_p], doubles as the specs for our interface files.
/* ************************************************************************* */
/* ************************************************************************* */
void handle_possible_template(vector<Class>& classes, const Class& cls, const string& templateArgument, const vector<vector<string> >& instantiations) {
if(instantiations.empty()) {
classes.push_back(cls);
} else {
vector<Class> classInstantiations = cls.expandTemplate(templateArgument, instantiations);
BOOST_FOREACH(const Class& c, classInstantiations) {
classes.push_back(c);
}
}
}
/* ************************************************************************* */
Module::Module(const string& interfacePath,
const string& moduleName, bool enable_verbose) : name(moduleName), verbose(enable_verbose)
{
// these variables will be imperatively updated to gradually build [cls]
// The one with postfix 0 are used to reset the variables after parse.
string methodName, methodName0;
bool isConst, isConst0 = false;
ReturnValue retVal0, retVal;
Argument arg0, arg;
ArgumentList args0, args;
vector<string> arg_dup; ///keep track of duplicates
Constructor constructor0(enable_verbose), constructor(enable_verbose);
Deconstructor deconstructor0(enable_verbose), deconstructor(enable_verbose);
//Method method0(enable_verbose), method(enable_verbose);
StaticMethod static_method0(enable_verbose), static_method(enable_verbose);
Class cls0(enable_verbose),cls(enable_verbose);
ForwardDeclaration fwDec0, fwDec;
vector<string> namespaces, /// current namespace tag
namespace_includes, /// current set of includes
namespaces_return, /// namespace for current return type
using_namespace_current; /// All namespaces from "using" declarations
string templateArgument;
vector<string> templateInstantiationNamespace;
vector<vector<string> > templateInstantiations;
TemplateInstantiationTypedef singleInstantiation, singleInstantiation0;
string include_path = "";
const string null_str = "";
//----------------------------------------------------------------------------
// Grammar with actions that build the Class object. Actions are
// defined within the square brackets [] and are executed whenever a
// rule is successfully parsed. Define BOOST_SPIRIT_DEBUG to debug.
// The grammar is allows a very restricted C++ header
// lexeme_d turns off white space skipping
// http://www.boost.org/doc/libs/1_37_0/libs/spirit/classic/doc/directives.html
// ----------------------------------------------------------------------------
Rule comments_p = comment_p("/*", "*/") | comment_p("//", eol_p);
Rule basisType_p =
(str_p("string") | "bool" | "size_t" | "int" | "double" | "char" | "unsigned char");
Rule keywords_p =
(str_p("const") | "static" | "namespace" | basisType_p);
Rule eigenType_p =
(str_p("Vector") | "Matrix");
Rule className_p = (lexeme_d[upper_p >> *(alnum_p | '_')] - eigenType_p - keywords_p);
Rule namespace_name_p = lexeme_d[lower_p >> *(alnum_p | '_')] - keywords_p;
Rule namespace_arg_p = namespace_name_p[push_back_a(arg.namespaces)] >> str_p("::");
Rule argEigenType_p =
eigenType_p[assign_a(arg.type)] >>
!ch_p('*')[assign_a(arg.is_ptr,true)];
Rule eigenRef_p =
!str_p("const") [assign_a(arg.is_const,true)] >>
eigenType_p [assign_a(arg.type)] >>
ch_p('&') [assign_a(arg.is_ref,true)];
Rule classArg_p =
!str_p("const") [assign_a(arg.is_const,true)] >>
*namespace_arg_p >>
className_p[assign_a(arg.type)] >>
(ch_p('*')[assign_a(arg.is_ptr,true)] | ch_p('&')[assign_a(arg.is_ref,true)]);
Rule name_p = lexeme_d[alpha_p >> *(alnum_p | '_')];
Rule classParent_p =
*(namespace_name_p[push_back_a(cls.qualifiedParent)] >> str_p("::")) >>
className_p[push_back_a(cls.qualifiedParent)];
Rule templateInstantiation_p =
(*(namespace_name_p[push_back_a(templateInstantiationNamespace)] >> str_p("::")) >>
className_p[push_back_a(templateInstantiationNamespace)])
[push_back_a(templateInstantiations, templateInstantiationNamespace)]
[clear_a(templateInstantiationNamespace)];
Rule templateInstantiations_p =
(str_p("template") >>
'<' >> name_p[assign_a(templateArgument)] >> '=' >> '{' >>
!(templateInstantiation_p >> *(',' >> templateInstantiation_p)) >>
'}' >> '>')
[push_back_a(cls.templateArgs, templateArgument)];
Rule templateSingleInstantiationArg_p =
(*(namespace_name_p[push_back_a(templateInstantiationNamespace)] >> str_p("::")) >>
className_p[push_back_a(templateInstantiationNamespace)])
[push_back_a(singleInstantiation.typeList, templateInstantiationNamespace)]
[clear_a(templateInstantiationNamespace)];
Rule templateSingleInstantiation_p =
(str_p("typedef") >>
*(namespace_name_p[push_back_a(singleInstantiation.classNamespaces)] >> str_p("::")) >>
className_p[assign_a(singleInstantiation.className)] >>
'<' >> templateSingleInstantiationArg_p >> *(',' >> templateSingleInstantiationArg_p) >>
'>' >>
className_p[assign_a(singleInstantiation.name)] >>
';')
[assign_a(singleInstantiation.namespaces, namespaces)]
[push_back_a(templateInstantiationTypedefs, singleInstantiation)]
[assign_a(singleInstantiation, singleInstantiation0)];
Rule templateList_p =
(str_p("template") >>
'<' >> name_p[push_back_a(cls.templateArgs)] >> *(',' >> name_p[push_back_a(cls.templateArgs)]) >>
'>');
Rule argument_p =
((basisType_p[assign_a(arg.type)] | argEigenType_p | eigenRef_p | classArg_p)
>> name_p[assign_a(arg.name)])
[push_back_a(args, arg)]
[assign_a(arg,arg0)];
Rule argumentList_p = !argument_p >> * (',' >> argument_p);
Rule constructor_p =
(className_p >> '(' >> argumentList_p >> ')' >> ';' >> !comments_p)
[push_back_a(constructor.args_list, args)]
[assign_a(args,args0)];
//[assign_a(constructor.args,args)]
//[assign_a(constructor.name,cls.name)]
//[push_back_a(cls.constructors, constructor)]
//[assign_a(constructor,constructor0)];
Rule namespace_ret_p = namespace_name_p[push_back_a(namespaces_return)] >> str_p("::");
Rule returnType1_p =
(basisType_p[assign_a(retVal.type1)][assign_a(retVal.category1, ReturnValue::BASIS)]) |
((*namespace_ret_p)[assign_a(retVal.namespaces1, namespaces_return)][clear_a(namespaces_return)]
>> (className_p[assign_a(retVal.type1)][assign_a(retVal.category1, ReturnValue::CLASS)]) >>
!ch_p('*')[assign_a(retVal.isPtr1,true)]) |
(eigenType_p[assign_a(retVal.type1)][assign_a(retVal.category1, ReturnValue::EIGEN)]);
Rule returnType2_p =
(basisType_p[assign_a(retVal.type2)][assign_a(retVal.category2, ReturnValue::BASIS)]) |
((*namespace_ret_p)[assign_a(retVal.namespaces2, namespaces_return)][clear_a(namespaces_return)]
>> (className_p[assign_a(retVal.type2)][assign_a(retVal.category2, ReturnValue::CLASS)]) >>
!ch_p('*') [assign_a(retVal.isPtr2,true)]) |
(eigenType_p[assign_a(retVal.type2)][assign_a(retVal.category2, ReturnValue::EIGEN)]);
Rule pair_p =
(str_p("pair") >> '<' >> returnType1_p >> ',' >> returnType2_p >> '>')
[assign_a(retVal.isPair,true)];
Rule void_p = str_p("void")[assign_a(retVal.type1)];
Rule returnType_p = void_p | returnType1_p | pair_p;
Rule methodName_p = lexeme_d[lower_p >> *(alnum_p | '_')];
Rule method_p =
(returnType_p >> methodName_p[assign_a(methodName)] >>
'(' >> argumentList_p >> ')' >>
!str_p("const")[assign_a(isConst,true)] >> ';' >> *comments_p)
[bl::bind(&Method::addOverload,
bl::var(cls.methods)[bl::var(methodName)],
verbose,
bl::var(isConst),
bl::var(methodName),
bl::var(args),
bl::var(retVal))]
[assign_a(isConst,isConst0)]
[assign_a(methodName,methodName0)]
[assign_a(args,args0)]
[assign_a(retVal,retVal0)];
Rule staticMethodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')];
Rule static_method_p =
(str_p("static") >> returnType_p >> staticMethodName_p[assign_a(methodName)] >>
'(' >> argumentList_p >> ')' >> ';' >> *comments_p)
[bl::bind(&StaticMethod::addOverload,
bl::var(cls.static_methods)[bl::var(methodName)],
verbose,
bl::var(methodName),
bl::var(args),
bl::var(retVal))]
[assign_a(methodName,methodName0)]
[assign_a(args,args0)]
[assign_a(retVal,retVal0)];
Rule functions_p = constructor_p | method_p | static_method_p;
Rule include_p = str_p("#include") >> ch_p('<') >> (*(anychar_p - '>'))[assign_a(include_path)] >> ch_p('>');
Rule class_p =
(!*include_p
>> !(templateInstantiations_p | templateList_p)
>> !(str_p("virtual")[assign_a(cls.isVirtual, true)])
>> str_p("class")[push_back_a(cls.includes, include_path)][assign_a(include_path, null_str)]
>> className_p[assign_a(cls.name)]
>> ((':' >> classParent_p >> '{') | '{')
>> *(functions_p | comments_p)
>> str_p("};"))
[assign_a(constructor.name, cls.name)]
[assign_a(cls.constructor, constructor)]
[assign_a(cls.namespaces, namespaces)]
[assign_a(cls.using_namespaces, using_namespace_current)]
[append_a(cls.includes, namespace_includes)]
[assign_a(deconstructor.name,cls.name)]
[assign_a(cls.deconstructor, deconstructor)]
[bl::bind(&handle_possible_template, bl::var(classes), bl::var(cls), bl::var(templateArgument), bl::var(templateInstantiations))]
[assign_a(deconstructor,deconstructor0)]
[assign_a(constructor, constructor0)]
[assign_a(cls,cls0)]
[clear_a(templateArgument)]
[clear_a(templateInstantiations)];
Rule namespace_def_p =
(!*include_p
>> str_p("namespace")[push_back_a(namespace_includes, include_path)][assign_a(include_path, null_str)]
>> namespace_name_p[push_back_a(namespaces)]
>> ch_p('{')
>> *(class_p | templateSingleInstantiation_p | namespace_def_p | comments_p)
>> str_p("}///\\namespace") // end namespace, avoid confusion with classes
>> !namespace_name_p)
[pop_a(namespaces)]
[pop_a(namespace_includes)];
Rule using_namespace_p =
str_p("using") >> str_p("namespace")
>> namespace_name_p[push_back_a(using_namespace_current)] >> ch_p(';');
Rule forward_declaration_p =
!(str_p("virtual")[assign_a(fwDec.isVirtual, true)])
>> str_p("class")
>> (*(namespace_name_p >> str_p("::")) >> className_p)[assign_a(fwDec.name)]
>> ch_p(';')
[push_back_a(forward_declarations, fwDec)]
[assign_a(fwDec, fwDec0)];
Rule module_content_p = comments_p | using_namespace_p | class_p | templateSingleInstantiation_p | forward_declaration_p | namespace_def_p ;
Rule module_p = *module_content_p >> !end_p;
//----------------------------------------------------------------------------
// for debugging, define BOOST_SPIRIT_DEBUG
# ifdef BOOST_SPIRIT_DEBUG
BOOST_SPIRIT_DEBUG_NODE(className_p);
BOOST_SPIRIT_DEBUG_NODE(classPtr_p);
BOOST_SPIRIT_DEBUG_NODE(classRef_p);
BOOST_SPIRIT_DEBUG_NODE(basisType_p);
BOOST_SPIRIT_DEBUG_NODE(name_p);
BOOST_SPIRIT_DEBUG_NODE(argument_p);
BOOST_SPIRIT_DEBUG_NODE(argumentList_p);
BOOST_SPIRIT_DEBUG_NODE(constructor_p);
BOOST_SPIRIT_DEBUG_NODE(returnType1_p);
BOOST_SPIRIT_DEBUG_NODE(returnType2_p);
BOOST_SPIRIT_DEBUG_NODE(pair_p);
BOOST_SPIRIT_DEBUG_NODE(void_p);
BOOST_SPIRIT_DEBUG_NODE(returnType_p);
BOOST_SPIRIT_DEBUG_NODE(methodName_p);
BOOST_SPIRIT_DEBUG_NODE(method_p);
BOOST_SPIRIT_DEBUG_NODE(class_p);
BOOST_SPIRIT_DEBUG_NODE(namespace_def_p);
BOOST_SPIRIT_DEBUG_NODE(module_p);
# endif
//----------------------------------------------------------------------------
// read interface file
string interfaceFile = interfacePath + "/" + moduleName + ".h";
string contents = file_contents(interfaceFile);
// and parse contents
parse_info<const char*> info = parse(contents.c_str(), module_p, space_p);
if(!info.full) {
printf("parsing stopped at \n%.20s\n",info.stop);
throw ParseFailed((int)info.length);
}
}
/* ************************************************************************* */
template<class T>
void verifyArguments(const vector<string>& validArgs, const map<string,T>& vt) {
typedef typename map<string,T>::value_type Name_Method;
BOOST_FOREACH(const Name_Method& name_method, vt) {
const T& t = name_method.second;
BOOST_FOREACH(const ArgumentList& argList, t.argLists) {
BOOST_FOREACH(Argument arg, argList) {
string fullType = arg.qualifiedType("::");
if(find(validArgs.begin(), validArgs.end(), fullType)
== validArgs.end())
throw DependencyMissing(fullType, t.name);
}
}
}
}
/* ************************************************************************* */
template<class T>
void verifyReturnTypes(const vector<string>& validtypes, const map<string,T>& vt) {
typedef typename map<string,T>::value_type Name_Method;
BOOST_FOREACH(const Name_Method& name_method, vt) {
const T& t = name_method.second;
BOOST_FOREACH(const ReturnValue& retval, t.returnVals) {
if (find(validtypes.begin(), validtypes.end(), retval.qualifiedType1("::")) == validtypes.end())
throw DependencyMissing(retval.qualifiedType1("::"), t.name);
if (retval.isPair && find(validtypes.begin(), validtypes.end(), retval.qualifiedType2("::")) == validtypes.end())
throw DependencyMissing(retval.qualifiedType2("::"), t.name);
}
}
}
/* ************************************************************************* */
void Module::generateIncludes(FileWriter& file) const {
// collect includes
vector<string> all_includes;
BOOST_FOREACH(const Class& cls, classes) {
bool added_include = false;
BOOST_FOREACH(const string& s, cls.includes) {
if (!s.empty()) {
all_includes.push_back(s);
added_include = true;
}
}
if (!added_include) // add default include
all_includes.push_back(cls.name + ".h");
}
// sort and remove duplicates
sort(all_includes.begin(), all_includes.end());
vector<string>::const_iterator last_include = unique(all_includes.begin(), all_includes.end());
vector<string>::const_iterator it = all_includes.begin();
// add includes to file
for (; it != last_include; ++it)
file.oss << "#include <" << *it << ">" << endl;
file.oss << "\n";
}
/* ************************************************************************* */
void Module::matlab_code(const string& toolboxPath, const string& headerPath) const {
fs::create_directories(toolboxPath);
// create the unified .cpp switch file
const string wrapperName = name + "_wrapper";
string wrapperFileName = toolboxPath + "/" + wrapperName + ".cpp";
FileWriter wrapperFile(wrapperFileName, verbose, "//");
vector<string> functionNames; // Function names stored by index for switch
wrapperFile.oss << "#include <wrap/matlab.h>\n";
wrapperFile.oss << "#include <map>\n";
wrapperFile.oss << "#include <boost/foreach.hpp>\n";
wrapperFile.oss << "\n";
// Expand templates - This is done first so that template instantiations are
// counted in the list of valid types, have their attributes and dependencies
// checked, etc.
vector<Class> expandedClasses = ExpandTypedefInstantiations(classes, templateInstantiationTypedefs);
// Dependency check list
vector<string> validTypes = GenerateValidTypes(expandedClasses, forward_declarations);
// Check that all classes have been defined somewhere
BOOST_FOREACH(const Class& cls, expandedClasses) {
// verify all of the function arguments
//TODO:verifyArguments<ArgumentList>(validTypes, cls.constructor.args_list);
verifyArguments<StaticMethod>(validTypes, cls.static_methods);
verifyArguments<Method>(validTypes, cls.methods);
// verify function return types
verifyReturnTypes<StaticMethod>(validTypes, cls.static_methods);
verifyReturnTypes<Method>(validTypes, cls.methods);
// verify parents
if(!cls.qualifiedParent.empty() && std::find(validTypes.begin(), validTypes.end(), wrap::qualifiedName("::", cls.qualifiedParent)) == validTypes.end())
throw DependencyMissing(wrap::qualifiedName("::", cls.qualifiedParent), cls.qualifiedName("::"));
}
// Create type attributes table and check validity
TypeAttributesTable typeAttributes;
typeAttributes.addClasses(expandedClasses);
typeAttributes.addForwardDeclarations(forward_declarations);
typeAttributes.checkValidity(expandedClasses);
// Generate includes while avoiding redundant includes
generateIncludes(wrapperFile);
// create typedef classes - we put this at the top of the wrap file so that collectors and method arguments can use these typedefs
BOOST_FOREACH(const Class& cls, expandedClasses) {
if(!cls.typedefName.empty())
wrapperFile.oss << cls.getTypedef() << "\n";
}
wrapperFile.oss << "\n";
// Generate collectors and cleanup function to be called from mexAtExit
WriteCollectorsAndCleanupFcn(wrapperFile, name, expandedClasses);
// generate RTTI registry (for returning derived-most types)
WriteRTTIRegistry(wrapperFile, name, expandedClasses);
// create proxy class and wrapper code
BOOST_FOREACH(const Class& cls, expandedClasses) {
string classFile = toolboxPath + "/" + cls.qualifiedName() + ".m";
cls.matlab_proxy(classFile, wrapperName, typeAttributes, wrapperFile, functionNames);
}
// finish wrapper file
wrapperFile.oss << "\n";
finish_wrapper(wrapperFile, functionNames);
wrapperFile.emit(true);
}
/* ************************************************************************* */
void Module::finish_wrapper(FileWriter& file, const std::vector<std::string>& functionNames) const {
file.oss << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])\n";
file.oss << "{\n";
file.oss << " mstream mout;\n"; // Send stdout to MATLAB console, see matlab.h
file.oss << " std::streambuf *outbuf = std::cout.rdbuf(&mout);\n\n";
file.oss << " if(!_RTTIRegister_" << name << "_done) {\n";
file.oss << " _" << name << "_RTTIRegister();\n";
file.oss << " _RTTIRegister_" << name << "_done = true;\n";
file.oss << " }\n";
file.oss << " int id = unwrap<int>(in[0]);\n\n";
file.oss << " switch(id) {\n";
for(size_t id = 0; id < functionNames.size(); ++id) {
file.oss << " case " << id << ":\n";
file.oss << " " << functionNames[id] << "(nargout, out, nargin-1, in+1);\n";
file.oss << " break;\n";
}
file.oss << " }\n";
file.oss << "\n";
file.oss << " std::cout.rdbuf(outbuf);\n"; // Restore cout, see matlab.h
file.oss << "}\n";
}
/* ************************************************************************* */
vector<Class> Module::ExpandTypedefInstantiations(const vector<Class>& classes, const vector<TemplateInstantiationTypedef> instantiations) {
vector<Class> expandedClasses = classes;
BOOST_FOREACH(const TemplateInstantiationTypedef& inst, instantiations) {
// Add the new class to the list
expandedClasses.push_back(inst.findAndExpand(classes));
}
// Remove all template classes
for(int i = 0; i < expandedClasses.size(); ++i)
if(!expandedClasses[size_t(i)].templateArgs.empty()) {
expandedClasses.erase(expandedClasses.begin() + size_t(i));
-- i;
}
return expandedClasses;
}
/* ************************************************************************* */
vector<string> Module::GenerateValidTypes(const vector<Class>& classes, const vector<ForwardDeclaration> forwardDeclarations) {
vector<string> validTypes;
BOOST_FOREACH(const ForwardDeclaration& fwDec, forwardDeclarations) {
validTypes.push_back(fwDec.name);
}
validTypes.push_back("void");
validTypes.push_back("string");
validTypes.push_back("int");
validTypes.push_back("bool");
validTypes.push_back("char");
validTypes.push_back("unsigned char");
validTypes.push_back("size_t");
validTypes.push_back("double");
validTypes.push_back("Vector");
validTypes.push_back("Matrix");
//Create a list of parsed classes for dependency checking
BOOST_FOREACH(const Class& cls, classes) {
validTypes.push_back(cls.qualifiedName("::"));
}
return validTypes;
}
/* ************************************************************************* */
void Module::WriteCollectorsAndCleanupFcn(FileWriter& wrapperFile, const std::string& moduleName, const std::vector<Class>& classes) {
// Generate all collectors
BOOST_FOREACH(const Class& cls, classes) {
const string matlabName = cls.qualifiedName(), cppName = cls.qualifiedName("::");
wrapperFile.oss << "typedef std::set<boost::shared_ptr<" << cppName << ">*> "
<< "Collector_" << matlabName << ";\n";
wrapperFile.oss << "static Collector_" << matlabName <<
" collector_" << matlabName << ";\n";
}
// generate mexAtExit cleanup function
wrapperFile.oss << "\nvoid _deleteAllObjects()\n";
wrapperFile.oss << "{\n";
BOOST_FOREACH(const Class& cls, classes) {
const string matlabName = cls.qualifiedName();
const string cppName = cls.qualifiedName("::");
const string collectorType = "Collector_" + matlabName;
const string collectorName = "collector_" + matlabName;
wrapperFile.oss << " for(" << collectorType << "::iterator iter = " << collectorName << ".begin();\n";
wrapperFile.oss << " iter != " << collectorName << ".end(); ) {\n";
wrapperFile.oss << " delete *iter;\n";
wrapperFile.oss << " " << collectorName << ".erase(iter++);\n";
wrapperFile.oss << " }\n";
}
wrapperFile.oss << "}\n\n";
}
/* ************************************************************************* */
void Module::WriteRTTIRegistry(FileWriter& wrapperFile, const std::string& moduleName, const std::vector<Class>& classes) {
wrapperFile.oss <<
"static bool _RTTIRegister_" << moduleName << "_done = false;\n"
"void _" << moduleName << "_RTTIRegister() {\n"
" std::map<std::string, std::string> types;\n";
BOOST_FOREACH(const Class& cls, classes) {
if(cls.isVirtual)
wrapperFile.oss <<
" types.insert(std::make_pair(typeid(" << cls.qualifiedName("::") << ").name(), \"" << cls.qualifiedName() << "\"));\n";
}
wrapperFile.oss << "\n";
wrapperFile.oss <<
" mxArray *registry = mexGetVariable(\"global\", \"gtsamwrap_rttiRegistry\");\n"
" if(!registry)\n"
" registry = mxCreateStructMatrix(1, 1, 0, NULL);\n"
" typedef std::pair<std::string, std::string> StringPair;\n"
" BOOST_FOREACH(const StringPair& rtti_matlab, types) {\n"
" int fieldId = mxAddField(registry, rtti_matlab.first.c_str());\n"
" if(fieldId < 0)\n"
" mexErrMsgTxt(\"gtsam wrap: Error indexing RTTI types, inheritance will not work correctly\");\n"
" mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str());\n"
" mxSetFieldByNumber(registry, 0, fieldId, matlabName);\n"
" }\n"
" if(mexPutVariable(\"global\", \"gtsamwrap_rttiRegistry\", registry) != 0)\n"
" mexErrMsgTxt(\"gtsam wrap: Error indexing RTTI types, inheritance will not work correctly\");\n"
" mxDestroyArray(registry);\n"
"}\n"
"\n";
}
/* ************************************************************************* */

View File

@ -13,14 +13,18 @@
* @file Module.h
* @brief describes module to be wrapped
* @author Frank Dellaert
* @author Richard Roberts
**/
#pragma once
#include <string>
#include <vector>
#include <map>
#include "Class.h"
#include "TemplateInstantiationTypedef.h"
#include "ForwardDeclaration.h"
namespace wrap {
@ -28,11 +32,13 @@ namespace wrap {
* A module just has a name and a list of classes
*/
struct Module {
std::string name; ///< module name
std::vector<Class> classes; ///< list of classes
std::vector<TemplateInstantiationTypedef> templateInstantiationTypedefs; ///< list of template instantiations
bool verbose; ///< verbose flag
// std::vector<std::string> using_namespaces; ///< all default namespaces
std::vector<std::string> forward_declarations;
std::vector<ForwardDeclaration> forward_declarations;
/// constructor that parses interface file
Module(const std::string& interfacePath,
@ -41,11 +47,18 @@ struct Module {
/// MATLAB code generation:
void matlab_code(
const std::string& mexCommand,
const std::string& path,
const std::string& mexExt,
const std::string& headerPath,
const std::string& mexFlags) const;
const std::string& headerPath) const;
void finish_wrapper(FileWriter& file, const std::vector<std::string>& functionNames) const;
void generateIncludes(FileWriter& file) const;
private:
static std::vector<Class> ExpandTypedefInstantiations(const std::vector<Class>& classes, const std::vector<TemplateInstantiationTypedef> instantiations);
static std::vector<std::string> GenerateValidTypes(const std::vector<Class>& classes, const std::vector<ForwardDeclaration> forwardDeclarations);
static void WriteCollectorsAndCleanupFcn(FileWriter& wrapperFile, const std::string& moduleName, const std::vector<Class>& classes);
static void WriteRTTIRegistry(FileWriter& wrapperFile, const std::string& moduleName, const std::vector<Class>& classes);
};
} // \namespace wrap

View File

@ -4,6 +4,7 @@
* @date Dec 1, 2011
* @author Alex Cunningham
* @author Andrew Melim
* @author Richard Roberts
*/
#include <boost/foreach.hpp>
@ -46,45 +47,78 @@ string ReturnValue::qualifiedType2(const string& delim) const {
/* ************************************************************************* */
//TODO:Fix this
void ReturnValue::wrap_result(FileWriter& file) const {
void ReturnValue::wrap_result(const string& result, FileWriter& file, const TypeAttributesTable& typeAttributes) const {
string cppType1 = qualifiedType1("::"), matlabType1 = qualifiedType1();
string cppType2 = qualifiedType2("::"), matlabType2 = qualifiedType2();
if (isPair) {
// first return value in pair
if (isPtr1) {// if we already have a pointer
file.oss << " Shared" << type1 <<"* ret = new Shared" << type1 << "(result.first);" << endl;
file.oss << " out[0] = wrap_collect_shared_ptr(ret,\"" << matlabType1 << "\");\n";
}
else if (category1 == ReturnValue::CLASS) { // if we are going to make one
file.oss << " Shared" << type1 << "* ret = new Shared" << type1 << "(new " << cppType1 << "(result.first));\n";
file.oss << " out[0] = wrap_collect_shared_ptr(ret,\"" << matlabType1 << "\");\n";
}
else // if basis type
file.oss << " out[0] = wrap< " << return_type(true,arg1) << " >(result.first);\n";
if (category1 == ReturnValue::CLASS) { // if we are going to make one
string objCopy, ptrType;
ptrType = "Shared" + type1;
const bool isVirtual = typeAttributes.at(cppType1).isVirtual;
if(isVirtual) {
if(isPtr1)
objCopy = result + ".first";
else
objCopy = result + ".first.clone()";
} else {
if(isPtr1)
objCopy = result + ".first";
else
objCopy = ptrType + "(new " + cppType1 + "(" + result + ".first))";
}
file.oss << " out[0] = wrap_shared_ptr(" << objCopy << ",\"" << matlabType1 << "\", " << (isVirtual ? "true" : "false") << ");\n";
} else if(isPtr1) {
file.oss << " Shared" << type1 <<"* ret = new Shared" << type1 << "(" << result << ".first);" << endl;
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType1 << "\", false);\n";
} else // if basis type
file.oss << " out[0] = wrap< " << return_type(true,arg1) << " >(" << result << ".first);\n";
// second return value in pair
if (isPtr2) {// if we already have a pointer
file.oss << " Shared" << type2 <<"* ret = new Shared" << type2 << "(result.second);" << endl;
file.oss << " out[1] = wrap_collect_shared_ptr(ret,\"" << matlabType2 << "\");\n";
}
else if (category2 == ReturnValue::CLASS) { // if we are going to make one
file.oss << " Shared" << type2 << "* ret = new Shared" << type2 << "(new " << cppType2 << "(result.first));\n";
file.oss << " out[0] = wrap_collect_shared_ptr(ret,\"" << matlabType2 << "\");\n";
}
else
file.oss << " out[1] = wrap< " << return_type(true,arg2) << " >(result.second);\n";
}
else if (isPtr1){
file.oss << " Shared" << type1 <<"* ret = new Shared" << type1 << "(result);" << endl;
file.oss << " out[0] = wrap_collect_shared_ptr(ret,\"" << matlabType1 << "\");\n";
if (category2 == ReturnValue::CLASS) { // if we are going to make one
string objCopy, ptrType;
ptrType = "Shared" + type2;
const bool isVirtual = typeAttributes.at(cppType2).isVirtual;
if(isVirtual) {
if(isPtr2)
objCopy = result + ".second";
else
objCopy = result + ".second.clone()";
} else {
if(isPtr2)
objCopy = result + ".second";
else
objCopy = ptrType + "(new " + cppType2 + "(" + result + ".second))";
}
file.oss << " out[0] = wrap_shared_ptr(" << objCopy << ",\"" << matlabType2 << "\", " << (isVirtual ? "true" : "false") << ");\n";
} else if(isPtr2) {
file.oss << " Shared" << type2 <<"* ret = new Shared" << type2 << "(" << result << ".second);" << endl;
file.oss << " out[1] = wrap_shared_ptr(ret,\"" << matlabType2 << "\");\n";
} else
file.oss << " out[1] = wrap< " << return_type(true,arg2) << " >(" << result << ".second);\n";
}
else if (category1 == ReturnValue::CLASS){
file.oss << " Shared" << type1 << "* ret = new Shared" << type1 << "(new " << cppType1 << "(result));\n";
file.oss << " out[0] = wrap_collect_shared_ptr(ret,\"" << matlabType1 << "\");\n";
}
else if (matlabType1!="void")
file.oss << " out[0] = wrap< " << return_type(true,arg1) << " >(result);\n";
string objCopy, ptrType;
ptrType = "Shared" + type1;
const bool isVirtual = typeAttributes.at(cppType1).isVirtual;
if(isVirtual) {
if(isPtr1)
objCopy = result;
else
objCopy = result + ".clone()";
} else {
if(isPtr1)
objCopy = result;
else
objCopy = ptrType + "(new " + cppType1 + "(" + result + "))";
}
file.oss << " out[0] = wrap_shared_ptr(" << objCopy << ",\"" << matlabType1 << "\", " << (isVirtual ? "true" : "false") << ");\n";
} else if(isPtr1) {
file.oss << " Shared" << type1 <<"* ret = new Shared" << type1 << "(" << result << ");" << endl;
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType1 << "\");\n";
} else if (matlabType1!="void")
file.oss << " out[0] = wrap< " << return_type(true,arg1) << " >(" << result << ");\n";
}
/* ************************************************************************* */

View File

@ -5,11 +5,14 @@
*
* @date Dec 1, 2011
* @author Alex Cunningham
* @author Richard Roberts
*/
#include <vector>
#include <map>
#include "FileWriter.h"
#include "TypeAttributesTable.h"
#pragma once
@ -47,7 +50,7 @@ struct ReturnValue {
std::string matlab_returnType() const;
void wrap_result(FileWriter& file) const;
void wrap_result(const std::string& result, FileWriter& file, const TypeAttributesTable& typeAttributes) const;
};

View File

@ -13,12 +13,14 @@
* @file StaticMethod.ccp
* @author Frank Dellaert
* @author Andrew Melim
* @author Richard Roberts
**/
#include <iostream>
#include <fstream>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include "StaticMethod.h"
#include "utilities.h"
@ -26,80 +28,131 @@
using namespace std;
using namespace wrap;
/* ************************************************************************* */
void StaticMethod::matlab_mfile(const string& toolboxPath, const string& className) const {
void StaticMethod::addOverload(bool verbose, const std::string& name,
const ArgumentList& args, const ReturnValue& retVal) {
this->verbose = verbose;
this->name = name;
this->argLists.push_back(args);
this->returnVals.push_back(retVal);
}
// open destination m-file
string full_name = className + "_" + name;
string wrapperFile = toolboxPath + "/" + full_name + ".m";
FileWriter file(wrapperFile, verbose, "%");
void StaticMethod::proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wrapperFile,
const string& cppClassName,
const string& matlabClassName,
const string& wrapperName,
const vector<string>& using_namespaces,
const TypeAttributesTable& typeAttributes,
vector<string>& functionNames) const {
// generate code
string returnType = returnVal.matlab_returnType();
file.oss << "function " << returnType << " = " << full_name << "(";
if (args.size()) file.oss << args.names();
file.oss << ")" << endl;
file.oss << "% usage: x = " << full_name << "(" << args.names() << ")" << endl;
file.oss << " error('need to compile " << full_name << ".cpp');" << endl;
file.oss << "end" << endl;
string upperName = name; upperName[0] = std::toupper(upperName[0], std::locale());
// close file
file.emit(true);
proxyFile.oss << " function varargout = " << upperName << "(varargin)\n";
for(size_t overload = 0; overload < argLists.size(); ++overload) {
const ArgumentList& args = argLists[overload];
const ReturnValue& returnVal = returnVals[overload];
size_t nrArgs = args.size();
const int id = functionNames.size();
// Output proxy matlab code
// check for number of arguments...
proxyFile.oss << " " << (overload==0?"":"else") << "if length(varargin) == " << nrArgs;
if (nrArgs>0) proxyFile.oss << " && ";
// ...and their types
bool first = true;
for(size_t i=0;i<nrArgs;i++) {
if (!first) proxyFile.oss << " && ";
proxyFile.oss << "isa(varargin{" << i+1 << "},'" << args[i].matlabClass() << "')";
first=false;
}
proxyFile.oss << "\n";
// output call to C++ wrapper
string output;
if(returnVal.isPair)
output = "[ varargout{1} varargout{2} ] = ";
else if(returnVal.category1 == ReturnValue::VOID)
output = "";
else
output = "varargout{1} = ";
proxyFile.oss << " " << output << wrapperName << "(" << id << ", varargin{:});\n";
// Output C++ wrapper code
const string wrapFunctionName = wrapper_fragment(
wrapperFile, cppClassName, matlabClassName, overload, id, using_namespaces, typeAttributes);
// Add to function list
functionNames.push_back(wrapFunctionName);
}
proxyFile.oss << " else\n";
proxyFile.oss << " error('Arguments do not match any overload of function " <<
matlabClassName << "." << upperName << "');" << endl;
proxyFile.oss << " end\n";
proxyFile.oss << " end\n";
}
/* ************************************************************************* */
void StaticMethod::matlab_wrapper(const string& toolboxPath, const string& className,
const string& matlabClassName, const string& cppClassName,
const vector<string>& using_namespaces,
const vector<string>& includes) const {
// open destination wrapperFile
string full_name = matlabClassName + "_" + name;
string wrapperFile = toolboxPath + "/" + full_name + ".cpp";
FileWriter file(wrapperFile, verbose, "//");
string StaticMethod::wrapper_fragment(FileWriter& file,
const string& cppClassName,
const string& matlabClassName,
int overload,
int id,
const vector<string>& using_namespaces,
const TypeAttributesTable& typeAttributes) const {
// generate code
// header
generateIncludes(file, className, includes);
generateUsingNamespace(file, using_namespaces);
const string wrapFunctionName = matlabClassName + "_" + name + "_" + boost::lexical_cast<string>(id);
const ArgumentList& args = argLists[overload];
const ReturnValue& returnVal = returnVals[overload];
// call
file.oss << "void " << wrapFunctionName << "(int nargout, mxArray *out[], int nargin, const mxArray *in[])\n";
// start
file.oss << "{\n";
generateUsingNamespace(file, using_namespaces);
if(returnVal.isPair)
{
file.oss << "typedef boost::shared_ptr<" << returnVal.qualifiedType1("::") << "> Shared" << returnVal.type1 << ";"<< endl;
file.oss << "typedef boost::shared_ptr<" << returnVal.qualifiedType2("::") << "> Shared" << returnVal.type2 << ";"<< endl;
if(returnVal.category1 == ReturnValue::CLASS)
file.oss << " typedef boost::shared_ptr<" << returnVal.qualifiedType1("::") << "> Shared" << returnVal.type1 << ";"<< endl;
if(returnVal.category2 == ReturnValue::CLASS)
file.oss << " typedef boost::shared_ptr<" << returnVal.qualifiedType2("::") << "> Shared" << returnVal.type2 << ";"<< endl;
}
else
file.oss << "typedef boost::shared_ptr<" << returnVal.qualifiedType1("::") << "> Shared" << returnVal.type1 << ";"<< endl;
if(returnVal.category1 == ReturnValue::CLASS)
file.oss << " typedef boost::shared_ptr<" << returnVal.qualifiedType1("::") << "> Shared" << returnVal.type1 << ";"<< endl;
file.oss << "typedef boost::shared_ptr<" << cppClassName << "> Shared;" << endl;
// call
file.oss << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])\n";
// start
file.oss << "{\n";
file.oss << " typedef boost::shared_ptr<" << cppClassName << "> Shared;" << endl;
// check arguments
// NOTE: for static functions, there is no object passed
file.oss << " checkArguments(\"" << full_name << "\",nargout,nargin," << args.size() << ");\n";
file.oss << " checkArguments(\"" << matlabClassName << "." << name << "\",nargout,nargin," << args.size() << ");\n";
// unwrap arguments, see Argument.cpp
args.matlab_unwrap(file,0); // We start at 0 because there is no self object
file.oss << " ";
// call method with default type
// call method with default type and wrap result
if (returnVal.type1!="void")
file.oss << returnVal.return_type(true,ReturnValue::pair) << " result = ";
file.oss << cppClassName << "::" << name << "(" << args.names() << ");\n";
// wrap result
// example: out[0]=wrap<bool>(result);
returnVal.wrap_result(file);
returnVal.wrap_result(cppClassName+"::"+name+"("+args.names()+")", file, typeAttributes);
else
file.oss << cppClassName+"::"+name+"("+args.names()+");\n";
// finish
file.oss << "}\n";
// close file
file.emit(true);
return wrapFunctionName;
}
/* ************************************************************************* */

View File

@ -14,6 +14,7 @@
* @brief describes and generates code for static methods
* @author Frank Dellaert
* @author Alex Cunningham
* @author Richard Roberts
**/
#pragma once
@ -23,6 +24,7 @@
#include "Argument.h"
#include "ReturnValue.h"
#include "TypeAttributesTable.h"
namespace wrap {
@ -36,20 +38,31 @@ struct StaticMethod {
// Then the instance variables are set directly by the Module constructor
bool verbose;
std::string name;
ArgumentList args;
ReturnValue returnVal;
std::vector<ArgumentList> argLists;
std::vector<ReturnValue> returnVals;
// The first time this function is called, it initializes the class members
// with those in rhs, but in subsequent calls it adds additional argument
// lists as function overloads.
void addOverload(bool verbose, const std::string& name,
const ArgumentList& args, const ReturnValue& retVal);
// MATLAB code generation
// toolboxPath is the core toolbox directory, e.g., ../matlab
// NOTE: static functions are not inside the class, and
// are created with [ClassName]_[FunctionName]() format
// classPath is class directory, e.g., ../matlab/@Point2
void proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wrapperFile,
const std::string& cppClassName, const std::string& matlabClassName,
const std::string& wrapperName, const std::vector<std::string>& using_namespaces,
const TypeAttributesTable& typeAttributes,
std::vector<std::string>& functionNames) const;
void matlab_mfile(const std::string& toolboxPath, const std::string& className) const; ///< m-file
void matlab_wrapper(const std::string& toolboxPath,
const std::string& className, const std::string& matlabClassName,
const std::string& cppClassName,
const std::vector<std::string>& using_namespaces,
const std::vector<std::string>& includes) const; ///< cpp wrapper
private:
std::string wrapper_fragment(FileWriter& file,
const std::string& cppClassName,
const std::string& matlabClassname,
int overload,
int id,
const std::vector<std::string>& using_namespaces,
const TypeAttributesTable& typeAttributes) const; ///< cpp wrapper
};
} // \namespace wrap

View File

@ -0,0 +1,61 @@
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file Class.cpp
* @author Frank Dellaert
* @author Andrew Melim
* @author Richard Roberts
**/
#include "TemplateInstantiationTypedef.h"
#include "utilities.h"
using namespace std;
namespace wrap {
Class TemplateInstantiationTypedef::findAndExpand(const vector<Class>& classes) const {
// Find matching class
std::vector<Class>::const_iterator clsIt = classes.end();
for(std::vector<Class>::const_iterator it = classes.begin(); it != classes.end(); ++it) {
if(it->name == className && it->namespaces == classNamespaces && it->templateArgs.size() == typeList.size()) {
clsIt = it;
break;
}
}
if(clsIt == classes.end())
throw DependencyMissing(wrap::qualifiedName("::", classNamespaces, className),
"instantiation into typedef name " + wrap::qualifiedName("::", namespaces, name) +
". Ensure that the typedef provides the correct number of template arguments.");
// Instantiate it
Class classInst = *clsIt;
for(size_t i = 0; i < typeList.size(); ++i)
classInst = classInst.expandTemplate(classInst.templateArgs[i], typeList[i]);
// Fix class properties
classInst.name = name;
classInst.templateArgs.clear();
classInst.typedefName = clsIt->qualifiedName("::") + "<";
if(typeList.size() > 0)
classInst.typedefName += wrap::qualifiedName("::", typeList[0]);
for(size_t i = 1; i < typeList.size(); ++i)
classInst.typedefName += (", " + wrap::qualifiedName("::", typeList[i]));
classInst.typedefName += ">";
classInst.namespaces = namespaces;
return classInst;
}
}

View File

@ -0,0 +1,39 @@
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file Class.h
* @brief describe the C++ class that is being wrapped
* @author Frank Dellaert
* @author Andrew Melim
* @author Richard Roberts
**/
#pragma once
#include <vector>
#include <string>
#include "Class.h"
namespace wrap {
struct TemplateInstantiationTypedef {
std::vector<std::string> classNamespaces;
std::string className;
std::vector<std::string> namespaces;
std::string name;
std::vector<std::vector<std::string> > typeList;
Class findAndExpand(const std::vector<Class>& classes) const;
};
}

View File

@ -0,0 +1,58 @@
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file Class.cpp
* @author Frank Dellaert
* @author Andrew Melim
* @author Richard Roberts
**/
#include "TypeAttributesTable.h"
#include "Class.h"
#include "utilities.h"
#include <boost/foreach.hpp>
using namespace std;
namespace wrap {
/* ************************************************************************* */
void TypeAttributesTable::addClasses(const vector<Class>& classes) {
BOOST_FOREACH(const Class& cls, classes) {
if(!insert(make_pair(cls.qualifiedName("::"), TypeAttributes(cls.isVirtual))).second)
throw DuplicateDefinition("class " + cls.qualifiedName("::"));
}
}
/* ************************************************************************* */
void TypeAttributesTable::addForwardDeclarations(const vector<ForwardDeclaration>& forwardDecls) {
BOOST_FOREACH(const ForwardDeclaration& fwDec, forwardDecls) {
if(!insert(make_pair(fwDec.name, TypeAttributes(fwDec.isVirtual))).second)
throw DuplicateDefinition("class " + fwDec.name);
}
}
/* ************************************************************************* */
void TypeAttributesTable::checkValidity(const vector<Class>& classes) const {
BOOST_FOREACH(const Class& cls, classes) {
// Check that class is virtual if it has a parent
if(!cls.qualifiedParent.empty() && !cls.isVirtual)
throw AttributeError(cls.qualifiedName("::"), "Has a base class so needs to be declared virtual, change to 'virtual class "+cls.name+" ...'");
// Check that parent is virtual as well
if(!cls.qualifiedParent.empty() && !at(wrap::qualifiedName("::", cls.qualifiedParent)).isVirtual)
throw AttributeError(wrap::qualifiedName("::", cls.qualifiedParent),
"Is the base class of " + cls.qualifiedName("::") + ", so needs to be declared virtual");
}
}
}

View File

@ -0,0 +1,55 @@
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file Class.h
* @brief describe the C++ class that is being wrapped
* @author Frank Dellaert
* @author Andrew Melim
* @author Richard Roberts
**/
#include <map>
#include <string>
#include <vector>
#include "ForwardDeclaration.h"
#pragma once
namespace wrap {
// Forward declarations
struct Class;
/** Attributes about valid classes, both for classes defined in this module and
* also those forward-declared from others. At the moment this only contains
* whether the class is virtual, which is used to know how to copy the class,
* and whether to try to convert it to a more derived type upon returning it.
*/
struct TypeAttributes {
bool isVirtual;
TypeAttributes() : isVirtual(false) {}
TypeAttributes(bool isVirtual) : isVirtual(isVirtual) {}
};
/** Map of type names to attributes. */
class TypeAttributesTable : public std::map<std::string, TypeAttributes> {
public:
TypeAttributesTable() {}
void addClasses(const std::vector<Class>& classes);
void addForwardDeclarations(const std::vector<ForwardDeclaration>& forwardDecls);
void checkValidity(const std::vector<Class>& classes) const;
};
}

View File

@ -1,372 +1,426 @@
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file matlab.h
* @brief header file to be included in MATLAB wrappers
* @date 2008
* @author Frank Dellaert
*
* wrapping and unwrapping is done using specialized templates, see
* http://www.cplusplus.com/doc/tutorial/templates.html
*/
#include <gtsam/base/Vector.h>
#include <gtsam/base/Matrix.h>
using gtsam::Vector;
using gtsam::Matrix;
extern "C" {
#include <mex.h>
}
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/foreach.hpp>
#include <list>
#include <string>
#include <sstream>
#include <typeinfo>
#include <set>
using namespace std;
using namespace boost; // not usual, but for conciseness of generated code
// start GTSAM Specifics /////////////////////////////////////////////////
// to enable Matrix and Vector constructor for SharedGaussian:
#define GTSAM_MAGIC_GAUSSIAN
// end GTSAM Specifics /////////////////////////////////////////////////
#if defined(__LP64__) || defined(_WIN64)
// 64-bit
#define mxUINT32OR64_CLASS mxUINT64_CLASS
#else
#define mxUINT32OR64_CLASS mxUINT32_CLASS
#endif
//*****************************************************************************
// Utilities
//*****************************************************************************
void error(const char* str) {
mexErrMsgIdAndTxt("wrap:error", str);
}
mxArray *scalar(mxClassID classid) {
mwSize dims[1]; dims[0]=1;
return mxCreateNumericArray(1, dims, classid, mxREAL);
}
void checkScalar(const mxArray* array, const char* str) {
int m = mxGetM(array), n = mxGetN(array);
if (m!=1 || n!=1)
mexErrMsgIdAndTxt("wrap: not a scalar in ", str);
}
//*****************************************************************************
// Check arguments
//*****************************************************************************
void checkArguments(const string& name, int nargout, int nargin, int expected) {
stringstream err;
err << name << " expects " << expected << " arguments, not " << nargin;
if (nargin!=expected)
error(err.str().c_str());
}
//*****************************************************************************
// wrapping C++ basis types in MATLAB arrays
//*****************************************************************************
// default wrapping throws an error: only basis types are allowed in wrap
template <typename Class>
mxArray* wrap(Class& value) {
error("wrap internal error: attempted wrap of invalid type");
}
// specialization to string
// wraps into a character array
template<>
mxArray* wrap<string>(string& value) {
return mxCreateString(value.c_str());
}
// specialization to char
template<>
mxArray* wrap<char>(char& value) {
mxArray *result = scalar(mxUINT32OR64_CLASS);
*(char*)mxGetData(result) = value;
return result;
}
// specialization to unsigned char
template<>
mxArray* wrap<unsigned char>(unsigned char& value) {
mxArray *result = scalar(mxUINT32OR64_CLASS);
*(unsigned char*)mxGetData(result) = value;
return result;
}
// specialization to bool
template<>
mxArray* wrap<bool>(bool& value) {
mxArray *result = scalar(mxUINT32OR64_CLASS);
*(bool*)mxGetData(result) = value;
return result;
}
// specialization to size_t
template<>
mxArray* wrap<size_t>(size_t& value) {
mxArray *result = scalar(mxUINT32OR64_CLASS);
*(size_t*)mxGetData(result) = value;
return result;
}
// specialization to int
template<>
mxArray* wrap<int>(int& value) {
mxArray *result = scalar(mxUINT32OR64_CLASS);
*(int*)mxGetData(result) = value;
return result;
}
// specialization to double -> just double
template<>
mxArray* wrap<double>(double& value) {
return mxCreateDoubleScalar(value);
}
// wrap a const Eigen vector into a double vector
mxArray* wrap_Vector(const gtsam::Vector& v) {
int m = v.size();
mxArray *result = mxCreateDoubleMatrix(m, 1, mxREAL);
double *data = mxGetPr(result);
for (int i=0;i<m;i++) data[i]=v(i);
return result;
}
// specialization to Eigen vector -> double vector
template<>
mxArray* wrap<gtsam::Vector >(gtsam::Vector& v) {
return wrap_Vector(v);
}
// const version
template<>
mxArray* wrap<const gtsam::Vector >(const gtsam::Vector& v) {
return wrap_Vector(v);
}
// wrap a const Eigen MATRIX into a double matrix
mxArray* wrap_Matrix(const gtsam::Matrix& A) {
int m = A.rows(), n = A.cols();
#ifdef DEBUG_WRAP
mexPrintf("wrap_Matrix called with A = \n", m,n);
gtsam::print(A);
#endif
mxArray *result = mxCreateDoubleMatrix(m, n, mxREAL);
double *data = mxGetPr(result);
// converts from column-major to row-major
for (int j=0;j<n;j++) for (int i=0;i<m;i++,data++) *data = A(i,j);
return result;
}
// specialization to Eigen MATRIX -> double matrix
template<>
mxArray* wrap<gtsam::Matrix >(gtsam::Matrix& A) {
return wrap_Matrix(A);
}
// const version
template<>
mxArray* wrap<const gtsam::Matrix >(const gtsam::Matrix& A) {
return wrap_Matrix(A);
}
//*****************************************************************************
// unwrapping MATLAB arrays into C++ basis types
//*****************************************************************************
// default unwrapping throws an error
// as wrap only supports passing a reference or one of the basic types
template <typename T>
T unwrap(const mxArray* array) {
error("wrap internal error: attempted unwrap of invalid type");
}
// specialization to string
// expects a character array
// Warning: relies on mxChar==char
template<>
string unwrap<string>(const mxArray* array) {
char *data = mxArrayToString(array);
if (data==NULL) error("unwrap<string>: not a character array");
string str(data);
mxFree(data);
return str;
}
// Check for 64-bit, as Mathworks says mxGetScalar only good for 32 bit
template <typename T>
T myGetScalar(const mxArray* array) {
switch (mxGetClassID(array)) {
case mxINT64_CLASS:
return (T) *(int64_t*) mxGetData(array);
case mxUINT64_CLASS:
return (T) *(uint64_t*) mxGetData(array);
default:
// hope for the best!
return (T) mxGetScalar(array);
}
}
// specialization to bool
template<>
bool unwrap<bool>(const mxArray* array) {
checkScalar(array,"unwrap<bool>");
return myGetScalar<bool>(array);
}
// specialization to char
template<>
char unwrap<char>(const mxArray* array) {
checkScalar(array,"unwrap<char>");
return myGetScalar<char>(array);
}
// specialization to unsigned char
template<>
unsigned char unwrap<unsigned char>(const mxArray* array) {
checkScalar(array,"unwrap<unsigned char>");
return myGetScalar<unsigned char>(array);
}
// specialization to int
template<>
int unwrap<int>(const mxArray* array) {
checkScalar(array,"unwrap<int>");
return myGetScalar<int>(array);
}
// specialization to size_t
template<>
size_t unwrap<size_t>(const mxArray* array) {
checkScalar(array, "unwrap<size_t>");
return myGetScalar<size_t>(array);
}
// specialization to double
template<>
double unwrap<double>(const mxArray* array) {
checkScalar(array,"unwrap<double>");
return myGetScalar<double>(array);
}
// specialization to Eigen vector
template<>
gtsam::Vector unwrap< gtsam::Vector >(const mxArray* array) {
int m = mxGetM(array), n = mxGetN(array);
if (mxIsDouble(array)==false || n!=1) error("unwrap<vector>: not a vector");
#ifdef DEBUG_WRAP
mexPrintf("unwrap< gtsam::Vector > called with %dx%d argument\n", m,n);
#endif
double* data = (double*)mxGetData(array);
gtsam::Vector v(m);
for (int i=0;i<m;i++,data++) v(i) = *data;
#ifdef DEBUG_WRAP
gtsam::print(v);
#endif
return v;
}
// specialization to Eigen matrix
template<>
gtsam::Matrix unwrap< gtsam::Matrix >(const mxArray* array) {
if (mxIsDouble(array)==false) error("unwrap<matrix>: not a matrix");
int m = mxGetM(array), n = mxGetN(array);
#ifdef DEBUG_WRAP
mexPrintf("unwrap< gtsam::Matrix > called with %dx%d argument\n", m,n);
#endif
double* data = (double*)mxGetData(array);
gtsam::Matrix A(m,n);
// converts from row-major to column-major
for (int j=0;j<n;j++) for (int i=0;i<m;i++,data++) A(i,j) = *data;
#ifdef DEBUG_WRAP
gtsam::print(A);
#endif
return A;
}
/*
[create_object] creates a MATLAB proxy class object with a mexhandle
in the self property. Matlab does not allow the creation of matlab
objects from within mex files, hence we resort to an ugly trick: we
invoke the proxy class constructor by calling MATLAB, and pass 13
dummy arguments to let the constructor know we want an object without
the self property initialized. We then assign the mexhandle to self.
*/
mxArray* create_object(const char *classname, mxArray* h) {
mxArray *result;
mxArray* dummy[13] = {h,h,h,h,h, h,h,h,h,h, h,h,h};
mexCallMATLAB(1,&result,13,dummy,classname);
mxSetProperty(result, 0, "self", h);
return result;
}
/*
* Similar to create object, this also collects the shared_ptr in addition
* to creating the dummy object. Mainly used for static constructor methods
* which don't have direct access to the function.
*/
mxArray* create_collect_object(const char *classname, mxArray* h){
mxArray *result;
//First arg is a flag to collect
mxArray* dummy[14] = {h,h,h,h,h, h,h,h,h,h, h,h,h,h};
mexCallMATLAB(1,&result,14,dummy,classname);
mxSetProperty(result, 0, "self", h);
return result;
}
/*
When the user calls a method that returns a shared pointer, we create
an ObjectHandle from the shared_pointer and return it as a proxy
class to matlab.
*/
template <typename Class>
mxArray* wrap_shared_ptr(boost::shared_ptr< Class >* shared_ptr, const char *classname) {
mxArray* mxh = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
*reinterpret_cast<boost::shared_ptr<Class>**> (mxGetData(mxh)) = shared_ptr;
//return mxh;
return create_object(classname, mxh);
}
template <typename Class>
mxArray* wrap_collect_shared_ptr(boost::shared_ptr< Class >* shared_ptr, const char *classname) {
mxArray* mxh = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
*reinterpret_cast<boost::shared_ptr<Class>**> (mxGetData(mxh)) = shared_ptr;
//return mxh;
return create_collect_object(classname, mxh);
}
template <typename Class>
boost::shared_ptr<Class> unwrap_shared_ptr(const mxArray* obj, const string& className) {
mxArray* mxh = mxGetProperty(obj,0,"self");
if (mxGetClassID(mxh) != mxUINT32OR64_CLASS || mxIsComplex(mxh)
|| mxGetM(mxh) != 1 || mxGetN(mxh) != 1) error(
"Parameter is not an Shared type.");
boost::shared_ptr<Class>* spp = *reinterpret_cast<boost::shared_ptr<Class>**> (mxGetData(mxh));
return *spp;
}
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file matlab.h
* @brief header file to be included in MATLAB wrappers
* @date 2008
* @author Frank Dellaert
* @author Alex Cunningham
* @author Andrew Melim
* @author Richard Roberts
*
* wrapping and unwrapping is done using specialized templates, see
* http://www.cplusplus.com/doc/tutorial/templates.html
*/
#include <gtsam/base/Vector.h>
#include <gtsam/base/Matrix.h>
using gtsam::Vector;
using gtsam::Matrix;
extern "C" {
#include <mex.h>
}
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/foreach.hpp>
#include <list>
#include <string>
#include <sstream>
#include <typeinfo>
#include <set>
#include <streambuf>
using namespace std;
using namespace boost; // not usual, but for conciseness of generated code
// start GTSAM Specifics /////////////////////////////////////////////////
// to enable Matrix and Vector constructor for SharedGaussian:
#define GTSAM_MAGIC_GAUSSIAN
// end GTSAM Specifics /////////////////////////////////////////////////
#if defined(__LP64__) || defined(_WIN64)
// 64-bit
#define mxUINT32OR64_CLASS mxUINT64_CLASS
#else
#define mxUINT32OR64_CLASS mxUINT32_CLASS
#endif
// "Unique" key to signal calling the matlab object constructor with a raw pointer
// to a shared pointer of the same C++ object type as the MATLAB type.
// Also present in utilities.h
static const uint64_t ptr_constructor_key =
(uint64_t('G') << 56) |
(uint64_t('T') << 48) |
(uint64_t('S') << 40) |
(uint64_t('A') << 32) |
(uint64_t('M') << 24) |
(uint64_t('p') << 16) |
(uint64_t('t') << 8) |
(uint64_t('r'));
//*****************************************************************************
// Utilities
//*****************************************************************************
void error(const char* str) {
mexErrMsgIdAndTxt("wrap:error", str);
}
mxArray *scalar(mxClassID classid) {
mwSize dims[1]; dims[0]=1;
return mxCreateNumericArray(1, dims, classid, mxREAL);
}
void checkScalar(const mxArray* array, const char* str) {
int m = mxGetM(array), n = mxGetN(array);
if (m!=1 || n!=1)
mexErrMsgIdAndTxt("wrap: not a scalar in ", str);
}
// Replacement streambuf for cout that writes to the MATLAB console
// Thanks to http://stackoverflow.com/a/249008
class mstream : public std::streambuf {
protected:
virtual std::streamsize xsputn(const char *s, std::streamsize n) {
mexPrintf("%.*s",n,s);
return n;
}
virtual int overflow(int c = EOF) {
if (c != EOF) {
mexPrintf("%.1s",&c);
}
return 1;
}
};
//*****************************************************************************
// Check arguments
//*****************************************************************************
void checkArguments(const string& name, int nargout, int nargin, int expected) {
stringstream err;
err << name << " expects " << expected << " arguments, not " << nargin;
if (nargin!=expected)
error(err.str().c_str());
}
//*****************************************************************************
// wrapping C++ basis types in MATLAB arrays
//*****************************************************************************
// default wrapping throws an error: only basis types are allowed in wrap
template <typename Class>
mxArray* wrap(const Class& value) {
error("wrap internal error: attempted wrap of invalid type");
return 0;
}
// specialization to string
// wraps into a character array
template<>
mxArray* wrap<string>(const string& value) {
return mxCreateString(value.c_str());
}
// specialization to char
template<>
mxArray* wrap<char>(const char& value) {
mxArray *result = scalar(mxUINT32OR64_CLASS);
*(char*)mxGetData(result) = value;
return result;
}
// specialization to unsigned char
template<>
mxArray* wrap<unsigned char>(const unsigned char& value) {
mxArray *result = scalar(mxUINT32OR64_CLASS);
*(unsigned char*)mxGetData(result) = value;
return result;
}
// specialization to bool
template<>
mxArray* wrap<bool>(const bool& value) {
mxArray *result = scalar(mxUINT32OR64_CLASS);
*(bool*)mxGetData(result) = value;
return result;
}
// specialization to size_t
template<>
mxArray* wrap<size_t>(const size_t& value) {
mxArray *result = scalar(mxUINT32OR64_CLASS);
*(size_t*)mxGetData(result) = value;
return result;
}
// specialization to int
template<>
mxArray* wrap<int>(const int& value) {
mxArray *result = scalar(mxUINT32OR64_CLASS);
*(int*)mxGetData(result) = value;
return result;
}
// specialization to double -> just double
template<>
mxArray* wrap<double>(const double& value) {
return mxCreateDoubleScalar(value);
}
// wrap a const Eigen vector into a double vector
mxArray* wrap_Vector(const gtsam::Vector& v) {
int m = v.size();
mxArray *result = mxCreateDoubleMatrix(m, 1, mxREAL);
double *data = mxGetPr(result);
for (int i=0;i<m;i++) data[i]=v(i);
return result;
}
// specialization to Eigen vector -> double vector
template<>
mxArray* wrap<gtsam::Vector >(const gtsam::Vector& v) {
return wrap_Vector(v);
}
// wrap a const Eigen MATRIX into a double matrix
mxArray* wrap_Matrix(const gtsam::Matrix& A) {
int m = A.rows(), n = A.cols();
#ifdef DEBUG_WRAP
mexPrintf("wrap_Matrix called with A = \n", m,n);
gtsam::print(A);
#endif
mxArray *result = mxCreateDoubleMatrix(m, n, mxREAL);
double *data = mxGetPr(result);
// converts from column-major to row-major
for (int j=0;j<n;j++) for (int i=0;i<m;i++,data++) *data = A(i,j);
return result;
}
// specialization to Eigen MATRIX -> double matrix
template<>
mxArray* wrap<gtsam::Matrix >(const gtsam::Matrix& A) {
return wrap_Matrix(A);
}
//*****************************************************************************
// unwrapping MATLAB arrays into C++ basis types
//*****************************************************************************
// default unwrapping throws an error
// as wrap only supports passing a reference or one of the basic types
template <typename T>
T unwrap(const mxArray* array) {
error("wrap internal error: attempted unwrap of invalid type");
}
// specialization to string
// expects a character array
// Warning: relies on mxChar==char
template<>
string unwrap<string>(const mxArray* array) {
char *data = mxArrayToString(array);
if (data==NULL) error("unwrap<string>: not a character array");
string str(data);
mxFree(data);
return str;
}
// Check for 64-bit, as Mathworks says mxGetScalar only good for 32 bit
template <typename T>
T myGetScalar(const mxArray* array) {
switch (mxGetClassID(array)) {
case mxINT64_CLASS:
return (T) *(int64_t*) mxGetData(array);
case mxUINT64_CLASS:
return (T) *(uint64_t*) mxGetData(array);
default:
// hope for the best!
return (T) mxGetScalar(array);
}
}
// specialization to bool
template<>
bool unwrap<bool>(const mxArray* array) {
checkScalar(array,"unwrap<bool>");
return myGetScalar<bool>(array);
}
// specialization to char
template<>
char unwrap<char>(const mxArray* array) {
checkScalar(array,"unwrap<char>");
return myGetScalar<char>(array);
}
// specialization to unsigned char
template<>
unsigned char unwrap<unsigned char>(const mxArray* array) {
checkScalar(array,"unwrap<unsigned char>");
return myGetScalar<unsigned char>(array);
}
// specialization to int
template<>
int unwrap<int>(const mxArray* array) {
checkScalar(array,"unwrap<int>");
return myGetScalar<int>(array);
}
// specialization to size_t
template<>
size_t unwrap<size_t>(const mxArray* array) {
checkScalar(array, "unwrap<size_t>");
return myGetScalar<size_t>(array);
}
// specialization to double
template<>
double unwrap<double>(const mxArray* array) {
checkScalar(array,"unwrap<double>");
return myGetScalar<double>(array);
}
// specialization to Eigen vector
template<>
gtsam::Vector unwrap< gtsam::Vector >(const mxArray* array) {
int m = mxGetM(array), n = mxGetN(array);
if (mxIsDouble(array)==false || n!=1) error("unwrap<vector>: not a vector");
#ifdef DEBUG_WRAP
mexPrintf("unwrap< gtsam::Vector > called with %dx%d argument\n", m,n);
#endif
double* data = (double*)mxGetData(array);
gtsam::Vector v(m);
for (int i=0;i<m;i++,data++) v(i) = *data;
#ifdef DEBUG_WRAP
gtsam::print(v);
#endif
return v;
}
// specialization to Eigen matrix
template<>
gtsam::Matrix unwrap< gtsam::Matrix >(const mxArray* array) {
if (mxIsDouble(array)==false) error("unwrap<matrix>: not a matrix");
int m = mxGetM(array), n = mxGetN(array);
#ifdef DEBUG_WRAP
mexPrintf("unwrap< gtsam::Matrix > called with %dx%d argument\n", m,n);
#endif
double* data = (double*)mxGetData(array);
gtsam::Matrix A(m,n);
// converts from row-major to column-major
for (int j=0;j<n;j++) for (int i=0;i<m;i++,data++) A(i,j) = *data;
#ifdef DEBUG_WRAP
gtsam::print(A);
#endif
return A;
}
/*
[create_object] creates a MATLAB proxy class object with a mexhandle
in the self property. Matlab does not allow the creation of matlab
objects from within mex files, hence we resort to an ugly trick: we
invoke the proxy class constructor by calling MATLAB with a special
uint64 value ptr_constructor_key and the pointer itself. MATLAB
allocates the object. Then, the special constructor in our wrap code
that is activated when the ptr_constructor_key is passed in passes
the pointer back into a C++ function to add the pointer to its
collector. We go through this extra "C++ to MATLAB to C++ step" in
order to be able to add to the collector could be in a different wrap
module.
*/
mxArray* create_object(const std::string& classname, void *pointer, bool isVirtual, const char *rttiName) {
mxArray *result;
mxArray *input[3];
int nargin = 2;
// First input argument is pointer constructor key
input[0] = mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL);
*reinterpret_cast<uint64_t*>(mxGetData(input[0])) = ptr_constructor_key;
// Second input argument is the pointer
input[1] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
*reinterpret_cast<void**>(mxGetData(input[1])) = pointer;
// If the class is virtual, use the RTTI name to look up the derived matlab type
const char *derivedClassName;
if(isVirtual) {
const mxArray *rttiRegistry = mexGetVariablePtr("global", "gtsamwrap_rttiRegistry");
if(!rttiRegistry)
mexErrMsgTxt(
"gtsam wrap: RTTI registry is missing - it could have been cleared from the workspace."
" You can issue 'clear all' to completely clear the workspace, and next time a wrapped object is"
" created the RTTI registry will be recreated.");
const mxArray *derivedNameMx = mxGetField(rttiRegistry, 0, rttiName);
if(!derivedNameMx)
mexErrMsgTxt((
"gtsam wrap: The derived class type " + string(rttiName) + " was not found in the RTTI registry. "
"Try calling 'clear all' twice consecutively - we have seen things not get unloaded properly the "
"first time. If this does not work, this may indicate an inconsistency in your wrap interface file. "
"The most likely cause for this is that a base class was marked virtual in the wrap interface "
"definition header file for gtsam or for your module, but a derived type was returned by a C++ "
"function and that derived type was not marked virtual (or was not specified in the wrap interface "
"definition header at all).").c_str());
size_t strLen = mxGetN(derivedNameMx);
char *buf = new char[strLen+1];
if(mxGetString(derivedNameMx, buf, strLen+1))
mexErrMsgTxt("gtsam wrap: Internal error reading RTTI table, try 'clear all' to clear your workspace and reinitialize the toolbox.");
derivedClassName = buf;
input[2] = mxCreateString("void");
nargin = 3;
} else {
derivedClassName = classname.c_str();
}
// Call special pointer constructor, which sets 'self'
mexCallMATLAB(1,&result, nargin, input, derivedClassName);
// Deallocate our memory
mxDestroyArray(input[0]);
mxDestroyArray(input[1]);
if(isVirtual) {
mxDestroyArray(input[2]);
delete[] derivedClassName;
}
return result;
}
/*
When the user calls a method that returns a shared pointer, we create
an ObjectHandle from the shared_pointer and return it as a proxy
class to matlab.
*/
template <typename Class>
mxArray* wrap_shared_ptr(boost::shared_ptr< Class > shared_ptr, const std::string& matlabName, bool isVirtual) {
// Create actual class object from out pointer
mxArray* result;
if(isVirtual) {
boost::shared_ptr<void> void_ptr(shared_ptr);
result = create_object(matlabName, &void_ptr, isVirtual, typeid(*shared_ptr).name());
} else {
boost::shared_ptr<Class> *heapPtr = new boost::shared_ptr<Class>(shared_ptr);
result = create_object(matlabName, heapPtr, isVirtual, "");
}
return result;
}
template <typename Class>
boost::shared_ptr<Class> unwrap_shared_ptr(const mxArray* obj, const string& propertyName) {
mxArray* mxh = mxGetProperty(obj,0, propertyName.c_str());
if (mxGetClassID(mxh) != mxUINT32OR64_CLASS || mxIsComplex(mxh)
|| mxGetM(mxh) != 1 || mxGetN(mxh) != 1) error(
"Parameter is not an Shared type.");
boost::shared_ptr<Class>* spp = *reinterpret_cast<boost::shared_ptr<Class>**> (mxGetData(mxh));
return *spp;
}

View File

@ -1,22 +0,0 @@
% automatically generated by wrap
classdef Point2 < handle
properties
self = 0
end
methods
function obj = Point2(varargin)
if (nargin == 0), obj.self = new_Point2(0,0); end
if (nargin == 2 && isa(varargin{1},'double') && isa(varargin{2},'double')), obj.self = new_Point2(0,1,varargin{1},varargin{2}); end
if nargin ==14, new_Point2(varargin{1},0); end
if nargin ~= 13 && nargin ~= 14 && obj.self == 0, error('Point2 constructor failed'); end
end
function delete(obj)
if obj.self ~= 0
new_Point2(obj.self);
obj.self = 0;
end
end
function display(obj), obj.print(''); end
function disp(obj), obj.display; end
end
end

View File

@ -1,11 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <Point2.h>
typedef boost::shared_ptr<Point2> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("argChar",nargout,nargin-1,1);
Shared obj = unwrap_shared_ptr<Point2>(in[0], "Point2");
char a = unwrap< char >(in[1]);
obj->argChar(a);
}

View File

@ -1,4 +0,0 @@
% result = obj.argChar(a)
function result = argChar(obj,a)
error('need to compile argChar.cpp');
end

View File

@ -1,11 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <Point2.h>
typedef boost::shared_ptr<Point2> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("argUChar",nargout,nargin-1,1);
Shared obj = unwrap_shared_ptr<Point2>(in[0], "Point2");
unsigned char a = unwrap< unsigned char >(in[1]);
obj->argUChar(a);
}

View File

@ -1,4 +0,0 @@
% result = obj.argUChar(a)
function result = argUChar(obj,a)
error('need to compile argUChar.cpp');
end

View File

@ -1,11 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <Point2.h>
typedef boost::shared_ptr<Point2> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("dim",nargout,nargin-1,0);
Shared obj = unwrap_shared_ptr<Point2>(in[0], "Point2");
int result = obj->dim();
out[0] = wrap< int >(result);
}

View File

@ -1,4 +0,0 @@
% result = obj.dim()
function result = dim(obj)
error('need to compile dim.cpp');
end

View File

@ -1,11 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <Point2.h>
typedef boost::shared_ptr<Point2> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("returnChar",nargout,nargin-1,0);
Shared obj = unwrap_shared_ptr<Point2>(in[0], "Point2");
char result = obj->returnChar();
out[0] = wrap< char >(result);
}

View File

@ -1,4 +0,0 @@
% result = obj.returnChar()
function result = returnChar(obj)
error('need to compile returnChar.cpp');
end

View File

@ -1,13 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <Point2.h>
typedef boost::shared_ptr<VectorNotEigen> SharedVectorNotEigen;
typedef boost::shared_ptr<Point2> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("vectorConfusion",nargout,nargin-1,0);
Shared obj = unwrap_shared_ptr<Point2>(in[0], "Point2");
VectorNotEigen result = obj->vectorConfusion();
SharedVectorNotEigen* ret = new SharedVectorNotEigen(new VectorNotEigen(result));
out[0] = wrap_collect_shared_ptr(ret,"VectorNotEigen");
}

View File

@ -1,4 +0,0 @@
% result = obj.vectorConfusion()
function result = vectorConfusion(obj)
error('need to compile vectorConfusion.cpp');
end

View File

@ -1,11 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <Point2.h>
typedef boost::shared_ptr<Point2> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("x",nargout,nargin-1,0);
Shared obj = unwrap_shared_ptr<Point2>(in[0], "Point2");
double result = obj->x();
out[0] = wrap< double >(result);
}

View File

@ -1,4 +0,0 @@
% result = obj.x()
function result = x(obj)
error('need to compile x.cpp');
end

View File

@ -1,11 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <Point2.h>
typedef boost::shared_ptr<Point2> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("y",nargout,nargin-1,0);
Shared obj = unwrap_shared_ptr<Point2>(in[0], "Point2");
double result = obj->y();
out[0] = wrap< double >(result);
}

View File

@ -1,4 +0,0 @@
% result = obj.y()
function result = y(obj)
error('need to compile y.cpp');
end

View File

@ -1,21 +0,0 @@
% automatically generated by wrap
classdef Point3 < handle
properties
self = 0
end
methods
function obj = Point3(varargin)
if (nargin == 3 && isa(varargin{1},'double') && isa(varargin{2},'double') && isa(varargin{3},'double')), obj.self = new_Point3(0,0,varargin{1},varargin{2},varargin{3}); end
if nargin ==14, new_Point3(varargin{1},0); end
if nargin ~= 13 && nargin ~= 14 && obj.self == 0, error('Point3 constructor failed'); end
end
function delete(obj)
if obj.self ~= 0
new_Point3(obj.self);
obj.self = 0;
end
end
function display(obj), obj.print(''); end
function disp(obj), obj.display; end
end
end

View File

@ -1,12 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <Point3.h>
using namespace geometry;
typedef boost::shared_ptr<Point3> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("norm",nargout,nargin-1,0);
Shared obj = unwrap_shared_ptr<Point3>(in[0], "Point3");
double result = obj->norm();
out[0] = wrap< double >(result);
}

View File

@ -1,4 +0,0 @@
% result = obj.norm()
function result = norm(obj)
error('need to compile norm.cpp');
end

View File

@ -1,22 +0,0 @@
% automatically generated by wrap
classdef Test < handle
properties
self = 0
end
methods
function obj = Test(varargin)
if (nargin == 0), obj.self = new_Test(0,0); end
if (nargin == 2 && isa(varargin{1},'double') && isa(varargin{2},'double')), obj.self = new_Test(0,1,varargin{1},varargin{2}); end
if nargin ==14, new_Test(varargin{1},0); end
if nargin ~= 13 && nargin ~= 14 && obj.self == 0, error('Test constructor failed'); end
end
function delete(obj)
if obj.self ~= 0
new_Test(obj.self);
obj.self = 0;
end
end
function display(obj), obj.print(''); end
function disp(obj), obj.display; end
end
end

View File

@ -1,12 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <folder/path/to/Test.h>
using namespace geometry;
typedef boost::shared_ptr<Test> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("arg_EigenConstRef",nargout,nargin-1,1);
Shared obj = unwrap_shared_ptr<Test>(in[0], "Test");
Matrix& value = *unwrap_shared_ptr< Matrix >(in[1], "Matrix");
obj->arg_EigenConstRef(value);
}

View File

@ -1,4 +0,0 @@
% result = obj.arg_EigenConstRef(value)
function result = arg_EigenConstRef(obj,value)
error('need to compile arg_EigenConstRef.cpp');
end

View File

@ -1,17 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <folder/path/to/Test.h>
using namespace geometry;
typedef boost::shared_ptr<Test> SharedTest;
typedef boost::shared_ptr<Test> SharedTest;
typedef boost::shared_ptr<Test> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("create_MixedPtrs",nargout,nargin-1,0);
Shared obj = unwrap_shared_ptr<Test>(in[0], "Test");
pair< Test, SharedTest > result = obj->create_MixedPtrs();
SharedTest* ret = new SharedTest(new Test(result.first));
out[0] = wrap_collect_shared_ptr(ret,"Test");
SharedTest* ret = new SharedTest(result.second);
out[1] = wrap_collect_shared_ptr(ret,"Test");
}

View File

@ -1,4 +0,0 @@
% [first,second] = obj.create_MixedPtrs()
function [first,second] = create_MixedPtrs(obj)
error('need to compile create_MixedPtrs.cpp');
end

View File

@ -1,17 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <folder/path/to/Test.h>
using namespace geometry;
typedef boost::shared_ptr<Test> SharedTest;
typedef boost::shared_ptr<Test> SharedTest;
typedef boost::shared_ptr<Test> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("create_ptrs",nargout,nargin-1,0);
Shared obj = unwrap_shared_ptr<Test>(in[0], "Test");
pair< SharedTest, SharedTest > result = obj->create_ptrs();
SharedTest* ret = new SharedTest(result.first);
out[0] = wrap_collect_shared_ptr(ret,"Test");
SharedTest* ret = new SharedTest(result.second);
out[1] = wrap_collect_shared_ptr(ret,"Test");
}

View File

@ -1,4 +0,0 @@
% [first,second] = obj.create_ptrs()
function [first,second] = create_ptrs(obj)
error('need to compile create_ptrs.cpp');
end

View File

@ -1,11 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <folder/path/to/Test.h>
using namespace geometry;
typedef boost::shared_ptr<Test> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("print",nargout,nargin-1,0);
Shared obj = unwrap_shared_ptr<Test>(in[0], "Test");
obj->print();
}

View File

@ -1,4 +0,0 @@
% result = obj.print()
function result = print(obj)
error('need to compile print.cpp');
end

View File

@ -1,15 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <folder/path/to/Test.h>
using namespace geometry;
typedef boost::shared_ptr<Point2> SharedPoint2;
typedef boost::shared_ptr<Test> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("return_Point2Ptr",nargout,nargin-1,1);
Shared obj = unwrap_shared_ptr<Test>(in[0], "Test");
bool value = unwrap< bool >(in[1]);
SharedPoint2 result = obj->return_Point2Ptr(value);
SharedPoint2* ret = new SharedPoint2(result);
out[0] = wrap_collect_shared_ptr(ret,"Point2");
}

View File

@ -1,4 +0,0 @@
% result = obj.return_Point2Ptr(value)
function result = return_Point2Ptr(obj,value)
error('need to compile return_Point2Ptr.cpp');
end

View File

@ -1,15 +0,0 @@
// automatically generated by wrap
#include <wrap/matlab.h>
#include <folder/path/to/Test.h>
using namespace geometry;
typedef boost::shared_ptr<Test> SharedTest;
typedef boost::shared_ptr<Test> Shared;
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("return_Test",nargout,nargin-1,1);
Shared obj = unwrap_shared_ptr<Test>(in[0], "Test");
boost::shared_ptr<Test> value = unwrap_shared_ptr< Test >(in[1], "Test");
Test result = obj->return_Test(value);
SharedTest* ret = new SharedTest(new Test(result));
out[0] = wrap_collect_shared_ptr(ret,"Test");
}

View File

@ -1,4 +0,0 @@
% result = obj.return_Test(value)
function result = return_Test(obj,value)
error('need to compile return_Test.cpp');
end

Some files were not shown because too many files have changed in this diff Show More