diff --git a/rocolib/api/Parameterized.py b/rocolib/api/Parameterized.py index 39803dfbecd42e54e7be53c8d7f0e9aee9920127..1fc3fbcb7646c6d3d708abbbde25c0fedb68f65b 100644 --- a/rocolib/api/Parameterized.py +++ b/rocolib/api/Parameterized.py @@ -1,7 +1,13 @@ +import re + from rocolib.utils.dimensions import isDim from rocolib.utils.numsym import Dummy +### XXX "." is used to separate subcomponent parameters when inherited +### but we can't tell the difference here, so it's not invalid I guess +VALID_ATTR = re.compile('^[a-zA-Z_][a-zA-Z0-9_.]*$') + PARAM_TYPES = { "length": { "valueType": "(float, int)", @@ -31,11 +37,11 @@ PARAM_TYPES = { class Parameter: def __init__(self, name, defaultValue=None, paramType=None, **kwargs): - ### XXX "." is used to separate subcomponent parameters when inherited - ### but we can't tell the difference here, so it's not invalid I guess + if not VALID_ATTR.match(name): + raise ValueError("Invalid parameter name " + name) + if name[0] == '_' and not kwargs.get("hidden", False): + raise ValueError("Leading _ character reserved for hidden parameters, either set hidden flag or change name from " + name) - #if "." in name: - #raise ValueError("Invalid character '.' in parameter name " + name) self.name = name if defaultValue is None and not kwargs.get("optional", False): @@ -72,14 +78,20 @@ class Parameter: self.symbol = None self.value = None - def setValue(self, value): - self.assertValid(value) + def setValue(self, value, validate=True): + if validate: + self.assertValid(value) self.value = value def setDefault(self, force=False): if force or self.value is None: self.setValue(self.defaultValue) + def setSpec(self, spec, value, validate=False): + self.spec[spec] = value + if validate: + self.assertValid(self.value) + def assertValid(self, value): if value is None: if self.spec.get("optional", False): @@ -148,18 +160,29 @@ class Parameterized(object): p.setDefault(force) - def setParameter(self, n, v): + def setParameter(self, n, v, validate=True): """ Sets a k/v pair to the internal store if the key has been added previously Raises KeyError if the key has not been added before Passes along any ValueErrors from Parameter object """ + if "#" in n: + n, spec = n.split("#") + else: + spec = None if n in self.parameters: - self.parameters[n].setValue(v) + if spec: + self.parameters[n].setSpec(spec, v, validate) + else: + self.parameters[n].setValue(v, validate) else: raise KeyError("Parameter %s not initialized on object %s" % (n, str(self))) + def validate(self): + for p in self.parameters.values(): + p.assertValid(p.getValue()) + def getParameter(self, name): """ Retrieves the parameter value with the given name @@ -168,14 +191,14 @@ class Parameterized(object): return self.parameters[name].getValue() - def getParameterInfo(self, name=None, keys=None): + def getParameterInfo(self, name=None, keys=None, hidden=False): """ Retrieves the parameter metadata info """ if name: return self.parameters[name].getInfo(keys) else: - return {k: v.getInfo(keys) for k, v in self.parameters.items()} + return {k: v.getInfo(keys) for k, v in self.parameters.items() if hidden or not v.getSpec().get("hidden", False)} def hasParameter(self, name): diff --git a/rocolib/api/components/Component.py b/rocolib/api/components/Component.py index e2546838d0269377abce29d96b96c95c467292de..a776cc1c28040038fda27dfd1a5b7461471a3a8a 100644 --- a/rocolib/api/components/Component.py +++ b/rocolib/api/components/Component.py @@ -149,7 +149,7 @@ class Component(Parameterized): if prefix == "": prefix = name - for key, value in obj.getParameterInfo().items(): + for key, value in obj.getParameterInfo(hidden=True).items(): # inherit = True : inherit all parameters if inherit is True or key in inherit: try: @@ -343,7 +343,7 @@ class Component(Parameterized): return self.subcomponents[name]['parameters'] def setSubParameter(self, c, n, v): - self.getSubcomponent(c).setParameter(n, v) + self.getSubcomponent(c).setParameter(n, v, validate=False) def getInterfaces(self, component, name, transient=False): return self.getSubcomponent(component).getInterface(name, transient) @@ -510,6 +510,7 @@ class Component(Parameterized): if useDefaultParameters: self.useDefaultParameters() self.modifyParameters() + self.validate() scOrder = self.traverseGraph() for scName in scOrder: diff --git a/rocolib/api/components/MechanicalComponent.py b/rocolib/api/components/MechanicalComponent.py index 2b1bda83ca9590c054044390318b12bc6b4d387f..675efa8cf2014da22d8133214a8399b8069c5d25 100644 --- a/rocolib/api/components/MechanicalComponent.py +++ b/rocolib/api/components/MechanicalComponent.py @@ -14,18 +14,18 @@ def vals(x): class MechanicalComponent(Component): def predefine(self, **kwargs): - self._origin = [ self.addParameter("_d"+x, 0, paramType="length", minValue=None) + self._origin = [ self.addParameter("_d"+x, 0, paramType="length", minValue=None, hidden=True) for x in "xyz" ] if kwargs.get("euler", False): - self._euler = [ self.addParameter(x, 0, paramType="angle") + self._euler = [ self.addParameter(x, 0, paramType="angle", hidden=True) for x in "_roll _pitch _yaw".split() ] else: self._euler = None - self._quat = [ self.addParameter("_q_"+x, int(x == "a"), - valueType="(int, float)", minValue=-1, maxValue=1) + self._quat = [ self.addParameter("_q_"+x, int(x == "a"), + valueType="(int, float)", minValue=-1, maxValue=1, hidden=True) for x in "aijk" ] #self.addSemanticConstraint(np.Eq(np.norm(self._quat), 1)) diff --git a/rocolib/builders/ESPBrainsBuilder.py b/rocolib/builders/ESPBrainsBuilder.py index 0071a1dac000374f6de23bc8e369a9b0ff846dea..272317a7add8fa2a96a0a9f1ac77f57570a97fa1 100644 --- a/rocolib/builders/ESPBrainsBuilder.py +++ b/rocolib/builders/ESPBrainsBuilder.py @@ -4,14 +4,14 @@ from rocolib.api.Function import Function self = Component() -self.addSubcomponent("beam", "RectBeam") +self.addSubcomponent("beam", "SimpleRectBeam") self.addSubcomponent("header", "Header") self.addSubcomponent("servoPins", "Cutout") self.addParameter("brain", "nodeMCU", paramType="dimension") self.addParameter("length", 90, paramType="length") -self.addParameter("width", 10, paramType="length") -self.addParameter("depth", 10, paramType="length") +self.addParameter("width", 50, paramType="length") +self.addParameter("depth", 20, paramType="length") ### Set specific relationships between parameters def getBrainParameter(p): @@ -20,11 +20,10 @@ def getBrainParameter(p): self.addConstraint(("beam", "width"), "depth") self.addConstraint(("beam", "depth"), "width") self.addConstraint(("beam", "length"), "length") -self.addConstConstraint(("beam", "angle"), 90) -self.addConstraint(("beam", "minwidth"), *getBrainParameter("height")) -self.addConstraint(("beam", "mindepth"), *getBrainParameter("width")) -self.addConstraint(("beam", "minlength"), *getBrainParameter("length")) +self.addConstraint(("beam", "width#minValue"), *getBrainParameter("height")) +self.addConstraint(("beam", "depth#minValue"), *getBrainParameter("width")) +self.addConstraint(("beam", "length#minValue"), *getBrainParameter("length")) self.addConstraint(("header", "nrows"), *getBrainParameter("nrows")) self.addConstraint(("header", "ncols"), *getBrainParameter("ncols")) diff --git a/rocolib/builders/ServoMountBuilder.py b/rocolib/builders/ServoMountBuilder.py index 399f03b91bbb76b2139b6e9fa71afbe79a2f3245..53ba903b7cc5da142c3b960a361356d39d971f91 100644 --- a/rocolib/builders/ServoMountBuilder.py +++ b/rocolib/builders/ServoMountBuilder.py @@ -18,6 +18,7 @@ c.addConstraint(("mount", "dy"), "servo", 'getDim(x, "motorlength")') c.addConstraint(("beam", "width"), "servo", 'getDim(x, "motorwidth")') c.addConstraint(("beam", "depth"), "servo", 'getDim(x, "motorheight")') +c.addConstraint(("beam", "length#minValue"), "servo", 'getDim(x, "motorlength") + 2 * getDim(x, "shoulderlength")') c.inheritAllInterfaces("beam", prefix=None) c.inheritAllInterfaces("mount") diff --git a/rocolib/library/BoatBase.yaml b/rocolib/library/BoatBase.yaml index 3c13407c663fd0b04cfaf87d227ba0ce78c124b5..b1ea51aa99b7806e29debd8f4c225a958e4f958e 100644 --- a/rocolib/library/BoatBase.yaml +++ b/rocolib/library/BoatBase.yaml @@ -22,42 +22,49 @@ parameters: boat._dx: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) boat._dy: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) boat._dz: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) boat._q_a: defaultValue: 1 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) boat._q_i: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) boat._q_j: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) boat._q_k: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) @@ -82,42 +89,49 @@ parameters: bow._dx: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) bow._dy: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) bow._dz: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) bow._q_a: defaultValue: 1 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) bow._q_i: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) bow._q_j: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) bow._q_k: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) @@ -130,42 +144,49 @@ parameters: stern._dx: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) stern._dy: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) stern._dz: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) stern._q_a: defaultValue: 1 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) stern._q_i: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) stern._q_j: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) stern._q_k: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) diff --git a/rocolib/library/Canoe.yaml b/rocolib/library/Canoe.yaml index ee32d94a740f973ca132f67250b4cb01bc5f605e..fbba25f09577d373113b0db3e17c9d166f2a951d 100644 --- a/rocolib/library/Canoe.yaml +++ b/rocolib/library/Canoe.yaml @@ -137,42 +137,49 @@ parameters: boat._dx: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) boat._dy: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) boat._dz: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) boat._q_a: defaultValue: 1 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) boat._q_i: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) boat._q_j: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) boat._q_k: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) @@ -197,42 +204,49 @@ parameters: bow._dx: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) bow._dy: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) bow._dz: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) bow._q_a: defaultValue: 1 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) bow._q_i: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) bow._q_j: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) bow._q_k: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) @@ -251,42 +265,49 @@ parameters: stern._dx: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) stern._dy: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) stern._dz: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) stern._q_a: defaultValue: 1 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) stern._q_i: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) stern._q_j: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) stern._q_k: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) diff --git a/rocolib/library/ESPBrains.yaml b/rocolib/library/ESPBrains.yaml index 902c2bd4be821dbec9a41f038a19062f80099857..36578232d530a1b44f683ed3831bffd26e929b49 100644 --- a/rocolib/library/ESPBrains.yaml +++ b/rocolib/library/ESPBrains.yaml @@ -69,7 +69,7 @@ parameters: spec: valueType: str depth: - defaultValue: 10 + defaultValue: 20 spec: minValue: 0 units: mm @@ -81,7 +81,7 @@ parameters: units: mm valueType: (float, int) width: - defaultValue: 10 + defaultValue: 50 spec: minValue: 0 units: mm @@ -89,25 +89,24 @@ parameters: source: ../builders/ESPBrainsBuilder.py subcomponents: beam: - classname: RectBeam + classname: SimpleRectBeam kwargs: {} parameters: - angle: 90 depth: parameter: width - length: - parameter: length - mindepth: + depth#minValue: function: getDim(x, 'width') parameter: brain - minlength: + length: + parameter: length + length#minValue: function: getDim(x, 'length') parameter: brain - minwidth: - function: getDim(x, 'height') - parameter: brain width: parameter: depth + width#minValue: + function: getDim(x, 'height') + parameter: brain header: classname: Header kwargs: {} diff --git a/rocolib/library/MountedServo.yaml b/rocolib/library/MountedServo.yaml index aaaa270f888997a30548a631d78a58d8ed5baa9a..f6353e834719629510fc9f1d0a4b7d3a499e96ff 100644 --- a/rocolib/library/MountedServo.yaml +++ b/rocolib/library/MountedServo.yaml @@ -61,42 +61,49 @@ parameters: _dx: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) _dy: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) _dz: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) _q_a: defaultValue: 1 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) _q_i: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) _q_j: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) _q_k: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) diff --git a/rocolib/library/RectBeam.py b/rocolib/library/RectBeam.py index d45e0cd4075f1ed3e7085b1384831b9d8f3a6705..60abf3d0b1754f200d4ae23e525c5cd081695c84 100644 --- a/rocolib/library/RectBeam.py +++ b/rocolib/library/RectBeam.py @@ -8,11 +8,6 @@ class RectBeam(FoldedComponent): self.addParameter("width", 20, paramType="length") self.addParameter("depth", 50, paramType="length") - # XXX TODO: incorporate into minValue of parameters somehow - self.addParameter("minlength", 0, paramType="length") - self.addParameter("minwidth", 0, paramType="length") - self.addParameter("mindepth", 0, paramType="length") - self.addParameter("phase", 0, valueType="int") self.addParameter("angle", optional=True, overrides=("tangle", "bangle")) @@ -29,11 +24,6 @@ class RectBeam(FoldedComponent): self.addEdgeInterface("tabedge", "r3.e1", "length") self.addEdgeInterface("slotedge", "r0.e3", "length") - def modifyParameters(self): - self.setParameter("width", max(self.getParameter("width"), self.getParameter("minwidth"))) - self.setParameter("depth", max(self.getParameter("depth"), self.getParameter("mindepth"))) - self.setParameter("length", max(self.getParameter("length"), self.getParameter("minlength"))) - def assemble(self): if self.getParameter("angle") is not None: bangle = 90 - self.getParameter("angle") diff --git a/rocolib/library/ServoMount.yaml b/rocolib/library/ServoMount.yaml index f45cb93dc81a8f21bba35a103e820070315f0633..829101ab4f87dd380d724ddf8cb1ca6efa48b2e4 100644 --- a/rocolib/library/ServoMount.yaml +++ b/rocolib/library/ServoMount.yaml @@ -103,6 +103,9 @@ subcomponents: parameter: servo length: parameter: length + length#minValue: + function: getDim(x, "motorlength") + 2 * getDim(x, "shoulderlength") + parameter: servo width: function: getDim(x, "motorwidth") parameter: servo diff --git a/rocolib/library/SimpleChair.yaml b/rocolib/library/SimpleChair.yaml index 3756a211f2a105b26ef98575405efa90ef6af541..672e7b286a2f4e553a2ff625350097c66e182dcd 100644 --- a/rocolib/library/SimpleChair.yaml +++ b/rocolib/library/SimpleChair.yaml @@ -16,42 +16,49 @@ parameters: _dx: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) _dy: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) _dz: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) _q_a: defaultValue: 1 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) _q_i: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) _q_j: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) _q_k: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) diff --git a/rocolib/library/SimpleTable.yaml b/rocolib/library/SimpleTable.yaml index f377c9740c7f777beb667cda5e00dfa87c7e95ef..5a77e45e77f45fded0bcd175645f67567f650d48 100644 --- a/rocolib/library/SimpleTable.yaml +++ b/rocolib/library/SimpleTable.yaml @@ -52,42 +52,49 @@ parameters: _dx: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) _dy: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) _dz: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) _q_a: defaultValue: 1 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) _q_i: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) _q_j: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) _q_k: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) diff --git a/rocolib/library/Trimaran.yaml b/rocolib/library/Trimaran.yaml index 032a1463695d19053944a5cebb14d459c10cd91f..21ddb7017937bab514771c1511cedc692245d59c 100644 --- a/rocolib/library/Trimaran.yaml +++ b/rocolib/library/Trimaran.yaml @@ -160,42 +160,49 @@ parameters: boat._dx: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) boat._dy: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) boat._dz: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) boat._q_a: defaultValue: 1 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) boat._q_i: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) boat._q_j: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) boat._q_k: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) @@ -220,42 +227,49 @@ parameters: bow._dx: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) bow._dy: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) bow._dz: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) bow._q_a: defaultValue: 1 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) bow._q_i: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) bow._q_j: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) bow._q_k: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) @@ -280,42 +294,49 @@ parameters: stern._dx: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) stern._dy: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) stern._dz: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) stern._q_a: defaultValue: 1 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) stern._q_i: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) stern._q_j: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) stern._q_k: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) diff --git a/rocolib/library/Wheel.yaml b/rocolib/library/Wheel.yaml index 51d9e01c2f7ca3f35118e9b7cab3c760ff056e21..7d22b01b470b52e2020ad78e7a78856e00e82eef 100644 --- a/rocolib/library/Wheel.yaml +++ b/rocolib/library/Wheel.yaml @@ -61,42 +61,49 @@ parameters: _dx: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) _dy: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) _dz: defaultValue: 0 spec: + hidden: true minValue: null units: mm valueType: (float, int) _q_a: defaultValue: 1 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) _q_i: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) _q_j: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float) _q_k: defaultValue: 0 spec: + hidden: true maxValue: 1 minValue: -1 valueType: (int, float)