diff --git a/rocolib/api/Function.py b/rocolib/api/Function.py index 8024cdb56f60588e33f29411bab2e65dc3c556c9..b0d8d076ea91266d71f6ede932157146d13be02c 100644 --- a/rocolib/api/Function.py +++ b/rocolib/api/Function.py @@ -21,7 +21,6 @@ class Function: def eval(self, parameterizable): import rocolib.utils.numsym as np - from rocolib.utils.dimensions import getDim function = eval("lambda x : " + self.fnstring, locals()) if isinstance(self.params, (list, tuple)): output = function([parameterizable.getParameter(x) for x in self.params]) diff --git a/rocolib/api/Parameterized.py b/rocolib/api/Parameterized.py index 43b8f37ef4ab8cedb273acc33beae4a8e2a1f888..18f0ad2bb69fba74d5c0a02882e030eef92621d6 100644 --- a/rocolib/api/Parameterized.py +++ b/rocolib/api/Parameterized.py @@ -1,6 +1,13 @@ -from rocolib.utils.dimensions import isDim +import re + from rocolib.utils.numsym import Dummy +import logging +import yaml + +### 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": { @@ -23,23 +30,19 @@ PARAM_TYPES = { "valueType": "int", "minValue": 0, }, - "dimension": { - "valueType": "str", - #"isValid": isDim, - }, } 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): - raise ValueError(f"Must specify either defaultValue or optional=True for parameter {name}") + if defaultValue is None and not kwargs.get("overrides", False): + raise ValueError(f"Must specify either defaultValue or overrides (implies optional) for parameter {name}") self.defaultValue = defaultValue self.spec = {} @@ -54,7 +57,7 @@ class Parameter: self.assertValid(defaultValue) vt = self.spec.get("valueType", "") - no = not(self.spec.get("optional", False)) + no = not(self.spec.get("overrides", False)) if no and ("int" in vt or "float" in vt): integer=None @@ -72,21 +75,40 @@ class Parameter: self.symbol = None self.value = None - def setValue(self, value): - self.assertValid(value) + def resolveValue(self, value): + if "values" not in self.spec: + return value + sanitize = lambda x : yaml.safe_load(yaml.safe_dump(x)) + vtest = sanitize(value) + v = sanitize(self.spec["values"]) + if isinstance(v, dict) and vtest not in list(v.keys()): + ks = list(v.keys()) + vs = list(v.values()) + if vtest in vs: + return ks[vs.index(vtest)] + return value + + def setValue(self, value, validate=True): + value = self.resolveValue(value) + 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): - self.value = value - return + if self.spec.get("overrides", False): + return True else: - raise ValueError(f"Parameter {self.name} is not optional and cannot be set to None") + raise ValueError(f"Parameter {self.name} is not optional (via overrides) and cannot be set to None") def check(spec, test, error): if (self.spec.get(spec, None) is not None and not test(self.spec[spec])): @@ -95,15 +117,48 @@ class Parameter: check("valueType", lambda x : isinstance(value, eval(x)), "is not of type") check("minValue", lambda x : value >= x, "is less than") check("maxValue", lambda x : value <= x, "is greater than") - check("isValid", lambda x : x(value), "is invalid") + check("values", lambda x : value in x, "is not in") + check("isValid", lambda x : x(self, value), "is invalid") return True + def validate(self): + return self.assertValid(self.value) + def getValue(self): if self.value is not None: - return self.value + if "values" in self.spec: + return self.spec["values"][self.value] + else: + return self.value else: return self.symbol + def doOverrides(self, c): + if self.value is None: + return + overrides = self.spec.get("overrides", []) + if isinstance(overrides, dict): + for k, fn in overrides.items(): + try: + import rocolib.utils.numsym as np + value = eval(fn, locals()) + c.setParameter(k, value) + except ValueError as e: + raise ValueError(str(e) + f" (via setting overriding parameter {self.name} to {self.value})") + except KeyError as e: + logging.debug(str(e) + f" (via setting overriding parameter {self.name} to {self.value}) -- ignoring") + elif isinstance(overrides, (list, tuple)): + for k in overrides: + try: + c.setParameter(k, self.value) + except KeyError as e: + logging.debug(str(e) + f" (via setting overriding parameter {self.name} to {self.value}) -- ignoring") + else: + try: + c.setParameter(overrides, self.value) + except KeyError as e: + logging.debug(str(e) + f" (via setting overriding parameter {self.name} to {self.value}) -- ignoring") + def getInfo(self, keys=None): if isinstance(keys, str): return getattr(self, keys) @@ -161,20 +216,33 @@ class Parameterized(object): """ for n, p in self._parameters.items(): p.setDefault(force) + for n, p in self._parameters.items(): + p.doOverrides(self) - 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 does not exist on object %s" % (n, str(self))) + def validate(self): + for p in self._parameters.values(): + p.validate() + def getParameter(self, name): """ Retrieves the parameter value with the given name @@ -183,14 +251,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 960a0db822bd5611d1b8d33ba98ef7e3ec34ea03..dd253459dbec4306292b4352b7e593f29b3767c9 100644 --- a/rocolib/api/components/Component.py +++ b/rocolib/api/components/Component.py @@ -145,7 +145,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: @@ -339,7 +339,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) @@ -506,6 +506,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 aa07db84b001e0852a7a0a2bbb88863c140bab43..a9f73f81087146d9ecb47493179faa661ceb3b1c 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 deleted file mode 100644 index f8d36edfc8bd2f097e5c6b848ef01f857f306f18..0000000000000000000000000000000000000000 --- a/rocolib/builders/ESPBrainsBuilder.py +++ /dev/null @@ -1,47 +0,0 @@ -from rocolib.api.components.Component import newComponent -from rocolib.api.Function import Function - - -self = newComponent("ESPBrains") - -self.addSubcomponent("beam", "RectBeam") -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") - -### Set specific relationships between parameters -def getBrainParameter(p): - return "brain", "getDim(x, '%s')" % 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(("header", "nrows"), *getBrainParameter("nrows")) -self.addConstraint(("header", "ncols"), *getBrainParameter("ncols")) -self.addConstraint(("header", "rowsep"), *getBrainParameter("rowsep")) -self.addConstraint(("header", "colsep"), *getBrainParameter("colsep")) - -self.addConstConstraint(("servoPins", "dy"), 8) -self.addConstConstraint(("servoPins", "dx"), 27) - -self.addConnection(("beam", "face1"), - ("header", "decoration"), - mode="hole", offset=Function(params=("length", "brain"), fnstring="(7.5, -4.5 + 0.5*(x[0]-getDim(x[1], 'length')))")) - -self.addConnection(("beam", "face1"), - ("servoPins", "decoration"), - mode="hole", rotate=True, offset=Function(params=("length", "brain"), fnstring="(-17.25, (0.5 * (x[0]-getDim(x[1], 'length')))-14)")) - -self.inheritAllInterfaces("beam", prefix=None) - -self.toLibrary() diff --git a/rocolib/builders/ESPSegBuilder.py b/rocolib/builders/ESPSegBuilder.py index a024e01ef212725fe5a0ec25fec16e951819f94b..60207d7e41aa1a6bbca292240f29e88fe6736dd1 100644 --- a/rocolib/builders/ESPSegBuilder.py +++ b/rocolib/builders/ESPSegBuilder.py @@ -1,3 +1,4 @@ +from rocolib.library import getComponent from rocolib.api.components.Component import newComponent from rocolib.api.Function import Function @@ -9,10 +10,9 @@ c.addParameter("height", 40, paramType="length") c.addParameter("tire_thickness", 0, paramType="length") -c.addParameter("controller", "nodeMCU", paramType="dimension") -c.addParameter("driveservo", "fs90r", paramType="dimension") +c.addParameter("driveservo", "fs90r", values=getComponent("ServoMotor").dims) -c.addSubcomponent("brain", "ESPBrains") +c.addSubcomponent("brain", "MountedBrains", inherit="brain", prefix=None) c.addSubcomponent("right", "Wheel", invert=True, inherit="angle") c.addSubcomponent("left", "Wheel", invert=True, inherit="angle") @@ -23,18 +23,17 @@ c.addConstraint(("left", "tire_thickness"), "tire_thickness") def depthfn(params = None, fnmod = None): if params is None: params = [] if fnmod is None: fnmod = "%s" - return ["controller", "driveservo"] + params, \ - fnmod % "max(getDim(x[0],'height'), getDim(x[1],'motorwidth'))" + return ["brain", "driveservo"] + params, \ + fnmod % "max(x[0].get('height'), x[1].get('motorwidth'))" # Set microcontroller c.addConstraint(("brain", "depth"), *depthfn()) c.addConstraint(("brain", "length"), "width") -c.addConstraint(("brain", "brain"), "controller") for servo in ("right", "left"): c.addConstraint((servo, "length"), - ("length", "controller"), - "x[0] - getDim(x[1],'width')") + ("length", "brain"), + "x[0] - x[1].get('width')") c.addConstConstraint((servo, "center"), False) c.addConstraint((servo, "servo"), "driveservo") c.addConstraint((servo, "radius"), "height") @@ -61,9 +60,9 @@ c.addConstraint(("sheath","width"), *depthfn(["battery"], "%s + x[2]")) c.addSubcomponent("sheathsplit", "SplitEdge") c.addConstraint(("sheathsplit","toplength"), "width", "(x,)") c.addConstraint(("sheathsplit","botlength"), ("driveservo", "width"), - "(getDim(x[0],'motorheight'), \ - x[1] - 2*getDim(x[0],'motorheight'), \ - getDim(x[0],'motorheight'))") + "(x[0].get('motorheight'), \ + x[1] - 2*x[0].get('motorheight'), \ + x[0].get('motorheight'))") c.addConnection(("left", "topedge1"), ("sheathsplit", "botedge2"), diff --git a/rocolib/builders/MountedBrainsBuilder.py b/rocolib/builders/MountedBrainsBuilder.py new file mode 100644 index 0000000000000000000000000000000000000000..aa8beeb249da735a28a9a5c265746527301ac81d --- /dev/null +++ b/rocolib/builders/MountedBrainsBuilder.py @@ -0,0 +1,29 @@ +from rocolib.api.components.Component import newComponent +from rocolib.api.Function import Function + + +self = newComponent("MountedBrains") + +self.addSubcomponent("beam", "SimpleRectBeam") +self.addSubcomponent("brain", "Brains", inherit="brain", prefix=None) + +self.addParameter("length", 90, paramType="length") +self.addParameter("width", 50, paramType="length") +self.addParameter("depth", 20, paramType="length") +self.addParameter("offset", (0,0)) + +self.addConstraint(("beam", "width"), "depth") +self.addConstraint(("beam", "depth"), "width") +self.addConstraint(("beam", "length"), "length") + +self.addConstraint(("beam", "width#minValue"), "brain", 'x.get("height")') +self.addConstraint(("beam", "depth#minValue"), "brain", 'x.get("width")') +self.addConstraint(("beam", "length#minValue"), "brain", 'x.get("length")') + +self.addConnection(("beam", "face1"), + ("brain", "decoration"), + mode="hole", offset=Function(params=("offset"))) + +self.inheritAllInterfaces("beam", prefix=None) + +self.toLibrary() diff --git a/rocolib/builders/ServoMountBuilder.py b/rocolib/builders/ServoMountBuilder.py index 84e2c05d210d022217f2da245966e37a5d731ef8..0640496730cd357bfb9b4e247767791120f9a22d 100644 --- a/rocolib/builders/ServoMountBuilder.py +++ b/rocolib/builders/ServoMountBuilder.py @@ -1,23 +1,26 @@ +from rocolib.library import getComponent from rocolib.api.components.Component import newComponent from rocolib.api.Function import Function c = newComponent("ServoMount") -c.addParameter("servo", "fs90r", paramType="dimension") +c.addParameter("servo", "fs90r", values=getComponent("ServoMotor").dims) c.addParameter("flip", False, valueType="bool") c.addParameter("center", True, valueType="bool") c.addParameter("shift", 0, paramType="length") + # XXX TODO: Define type: tuple of two numbers -c.addParameter("offset", optional=True, overrides=("flip", "center", "shift")) +c.addParameter("offset", 0) c.addSubcomponent("beam", "SimpleRectBeam", inherit=("length", "addTabs"), prefix=None) c.addSubcomponent("mount", "Cutout") -c.addConstraint(("mount", "dx"), "servo", 'getDim(x, "motorwidth") * 0.99') -c.addConstraint(("mount", "dy"), "servo", 'getDim(x, "motorlength")') +c.addConstraint(("mount", "dx"), "servo", 'x.get("motorwidth") * 0.99') +c.addConstraint(("mount", "dy"), "servo", 'x.get("motorlength")') -c.addConstraint(("beam", "width"), "servo", 'getDim(x, "motorwidth")') -c.addConstraint(("beam", "depth"), "servo", 'getDim(x, "motorheight")') +c.addConstraint(("beam", "width"), "servo", 'x.get("motorwidth")') +c.addConstraint(("beam", "depth"), "servo", 'x.get("motorheight")') +c.addConstraint(("beam", "length#minValue"), "servo", 'x.get("motorlength") + 2 * x.get("shoulderlength")') c.inheritAllInterfaces("beam", prefix=None) c.inheritAllInterfaces("mount") diff --git a/rocolib/library/Brains.py b/rocolib/library/Brains.py new file mode 100644 index 0000000000000000000000000000000000000000..dfc5b9841a6909ba3e102b02f01de438fc617480 --- /dev/null +++ b/rocolib/library/Brains.py @@ -0,0 +1,58 @@ +from rocolib.library import getComponent +from rocolib.api.composables.graph.Face import Face + + +ThruHole = getComponent("ThruHole").__class__ + +class Brains(ThruHole): + + brains = dict( + proMini = dict( + length = 39, + width = 19, + height = 9, + nrows = 12, + ncols = 2, + rowsep = 0.1 * 25.4, + colsep = 0.6 * 25.4, + origin = (0,0), + extras = (), + ), + nodeMCU = dict( + length = 59.5, + width = 44, + height = 13, + nrows = 15, + ncols = 2, + rowsep = 0.1 * 25.4, + colsep = 0.9 * 25.4, + origin = (7.5, -4.5), + extras = dict( + servoPins = dict(center = (-17.25, -14), size = (8, 27)), + ), + ), + ) + + def define(self): + ThruHole.define(self) + self.addParameter("brain", "nodeMCU", values=self.brains, overrides = dict( + nrows = 'c.getParameter("brain").get("nrows")', + ncols = 'c.getParameter("brain").get("ncols")', + rowsep = 'c.getParameter("brain").get("rowsep")', + colsep = 'c.getParameter("brain").get("colsep")', + )) + + def assemble(self): + ThruHole.assemble(self) + brain = self.getParameter("brain") + self.graph.dotransform(origin = brain.get("origin")) + for n, e in brain.get("extras").items(): + x, y = e.get("center", (0,0)) + dx, dy = e.get("size", (1,1)) + self.addFace(Face(n, + ((x-dx/2, y-dy/2), (x+dx/2, y-dy/2), (x+dx/2, y+dy/2), (x-dx/2, y+dy/2)), + recenter=False + )) + +if __name__ == "__main__": + Brains.test() diff --git a/rocolib/library/Cutout.py b/rocolib/library/Cutout.py index cf2f49e9a4bbab332bb3681578933361c9a95242..06e6df69065e62f3a95e1dd138a4de800c1a57ca 100644 --- a/rocolib/library/Cutout.py +++ b/rocolib/library/Cutout.py @@ -2,18 +2,16 @@ from rocolib.api.components import DecorationComponent from rocolib.api.composables.graph.Face import Rectangle class Cutout(DecorationComponent): - def define(self): - self.addParameter("dx", 10, paramType="length") - self.addParameter("dy", 20, paramType="length") - self.addParameter("d", optional=True, overrides=("dx", "dy")) + def define(self): + self.addParameter("dx", 10, paramType="length") + self.addParameter("dy", 20, paramType="length") + self.addParameter("d", overrides={ + "dx": 'c.getParameter("d")', + "dy": 'c.getParameter("d")', + }) - def modifyParameters(self): - if self.p.d is not None: - self.p.dx = self.p.d - self.p.dy = self.p.d - - def assemble(self): - self.addFace(Rectangle("r0", self.p.dx, self.p.dy), prefix="r0") + def assemble(self): + self.addFace(Rectangle("r0", self.p.dx, self.p.dy), prefix="r0") if __name__ == "__main__": Cutout.test() diff --git a/rocolib/library/ESPSeg.yaml b/rocolib/library/ESPSeg.yaml index 8c941477d9bbc53a4d2aff93979cafe1e5086d10..7de2c228fb1aaf9a34c2dc9021f3a9d6f39def98 100644 --- a/rocolib/library/ESPSeg.yaml +++ b/rocolib/library/ESPSeg.yaml @@ -50,9 +50,9 @@ connections: - botedge1 - angle: 90 tabWidth: - function: max(getDim(x[0],'height'), getDim(x[1],'motorwidth'))+x[2] + function: max(x[0].get('height'), x[1].get('motorwidth'))+x[2] parameter: - - controller + - brain - driveservo - battery connection7: @@ -61,10 +61,10 @@ connections: - decoration - mode: hole offset: - function: (4-(max(getDim(x[0],'height'), getDim(x[1],'motorwidth'))+x[3])/2, - 0.5 * x[2] - 15) + function: (4-(max(x[0].get('height'), x[1].get('motorwidth'))+x[3])/2, 0.5 * + x[2] - 15) parameter: - - controller + - brain - driveservo - length - battery @@ -90,14 +90,86 @@ parameters: minValue: 0 units: mm valueType: (float, int) - controller: + brain: defaultValue: nodeMCU spec: - valueType: str + overrides: + colsep: c.getParameter("brain").get("colsep") + ncols: c.getParameter("brain").get("ncols") + nrows: c.getParameter("brain").get("nrows") + rowsep: c.getParameter("brain").get("rowsep") + values: + nodeMCU: + colsep: 22.86 + extras: + servoPins: + center: + - -17.25 + - -14 + size: + - 8 + - 27 + height: 13 + length: 59.5 + ncols: 2 + nrows: 15 + origin: + - 7.5 + - -4.5 + rowsep: 2.54 + width: 44 + proMini: + colsep: 15.239999999999998 + extras: [] + height: 9 + length: 39 + ncols: 2 + nrows: 12 + origin: + - 0 + - 0 + rowsep: 2.54 + width: 19 driveservo: defaultValue: fs90r spec: - valueType: str + values: + ds2g: + horndepth: 1 + hornheight: 9 + hornlength: 11 + hornoffset: 4 + motorheight: 11 + motorlength: 17 + motorwidth: 8.5 + shoulderlength: 3.5 + fs90r: + horndepth: 2 + hornheight: 16 + hornlength: 10 + hornoffset: 8 + motorheight: 19 + motorlength: 23 + motorwidth: 13 + shoulderlength: 5 + s4303r: + horndepth: 2 + hornheight: 14 + hornlength: 38 + hornoffset: 7 + motorheight: 29 + motorlength: 31 + motorwidth: 17 + shoulderlength: 10 + tgy1370a: + horndepth: 2 + hornheight: 10 + hornlength: 7 + hornoffset: 4 + motorheight: 14 + motorlength: 20 + motorwidth: 9 + shoulderlength: 4 flapwidth: defaultValue: 0.2 spec: @@ -151,15 +223,15 @@ parameters: source: ../builders/ESPSegBuilder.py subcomponents: brain: - classname: ESPBrains + classname: MountedBrains kwargs: {} parameters: brain: - parameter: controller + parameter: brain depth: - function: max(getDim(x[0],'height'), getDim(x[1],'motorwidth')) + function: max(x[0].get('height'), x[1].get('motorwidth')) parameter: - - controller + - brain - driveservo length: parameter: width @@ -172,10 +244,10 @@ subcomponents: parameter: left.angle center: false length: - function: x[0] - getDim(x[1],'width') + function: x[0] - x[1].get('width') parameter: &id002 - length - - controller + - brain radius: parameter: height servo: @@ -192,7 +264,7 @@ subcomponents: center: false flip: true length: - function: x[0] - getDim(x[1],'width') + function: x[0] - x[1].get('width') parameter: *id002 radius: parameter: height @@ -209,9 +281,9 @@ subcomponents: length: parameter: length width: - function: max(getDim(x[0],'height'), getDim(x[1],'motorwidth')) + x[2] + function: max(x[0].get('height'), x[1].get('motorwidth')) + x[2] parameter: - - controller + - brain - driveservo - battery sheathsplit: @@ -219,7 +291,7 @@ subcomponents: kwargs: {} parameters: botlength: - function: (getDim(x[0],'motorheight'), x[1] - 2*getDim(x[0],'motorheight'), getDim(x[0],'motorheight')) + function: (x[0].get('motorheight'), x[1] - 2*x[0].get('motorheight'), x[0].get('motorheight')) parameter: - driveservo - width @@ -231,17 +303,17 @@ subcomponents: kwargs: {} parameters: depth: - function: max(getDim(x[0],'height'), getDim(x[1],'motorwidth'))+x[2] + function: max(x[0].get('height'), x[1].get('motorwidth'))+x[2] parameter: - - controller + - brain - driveservo - battery flapwidth: parameter: flapwidth height: - function: max(getDim(x[0],'height'), getDim(x[1],'motorwidth'))/2.+x[2] + function: max(x[0].get('height'), x[1].get('motorwidth'))/2.+x[2] parameter: - - controller + - brain - driveservo - height tailwidth: diff --git a/rocolib/library/Header.py b/rocolib/library/Header.py deleted file mode 100644 index 8b68315f0a6a1c11c0eb2ec4b6fb80acf58006a4..0000000000000000000000000000000000000000 --- a/rocolib/library/Header.py +++ /dev/null @@ -1,34 +0,0 @@ -from rocolib.api.components import DecorationComponent -from rocolib.api.composables.graph.Face import Face - - -class Header(DecorationComponent): - def define(self): - self.addParameter("nrows", 3, paramType="count") - self.addParameter("ncols", 1, paramType="count") - self.addParameter("rowsep", 2.54, paramType="length") - self.addParameter("colsep", 2.54, paramType="length") - self.addParameter("diameter", 1, paramType="length") - - def assemble(self): - diam = self.p.diameter/2. - nr = self.p.nrows - nc = self.p.ncols - - def hole(i, j, d): - dx = (j - (nc-1)/2.)*self.p.colsep - dy = (i - (nr-1)/2.)*self.p.rowsep - return Face("r-%d-%d" % (i,j), - ((dx-d, dy-d), (dx+d, dy-d), (dx+d, dy+d), (dx-d, dy+d)), - recenter=False) - - for i in range(nr): - for j in range(nc): - d = diam - if (i == 0 and j == 0) or \ - (i == nr-1 and j == nc-1): - d = diam*3 - self.addFace(hole(i,j,d), prefix="r-%d-%d" % (i,j)) - -if __name__ == "__main__": - Header.test() diff --git a/rocolib/library/ESPBrains.yaml b/rocolib/library/MountedBrains.yaml similarity index 53% rename from rocolib/library/ESPBrains.yaml rename to rocolib/library/MountedBrains.yaml index 902c2bd4be821dbec9a41f038a19062f80099857..aff7f4571405a33c673fc786fd3de74012fa9a7b 100644 --- a/rocolib/library/ESPBrains.yaml +++ b/rocolib/library/MountedBrains.yaml @@ -1,25 +1,12 @@ connections: connection0: - - &id001 - - beam + - - beam - face1 - - - header + - - brain - decoration - mode: hole offset: - function: (7.5, -4.5 + 0.5*(x[0]-getDim(x[1], 'length'))) - parameter: &id002 - - length - - brain - connection1: - - *id001 - - - servoPins - - decoration - - mode: hole - offset: - function: (-17.25, (0.5 * (x[0]-getDim(x[1], 'length')))-14) - parameter: *id002 - rotate: true + parameter: offset interfaces: botedge0: interface: botedge0 @@ -67,9 +54,45 @@ parameters: brain: defaultValue: nodeMCU spec: - valueType: str + overrides: + colsep: c.getParameter("brain").get("colsep") + ncols: c.getParameter("brain").get("ncols") + nrows: c.getParameter("brain").get("nrows") + rowsep: c.getParameter("brain").get("rowsep") + values: + nodeMCU: + colsep: 22.86 + extras: + servoPins: + center: + - -17.25 + - -14 + size: + - 8 + - 27 + height: 13 + length: 59.5 + ncols: 2 + nrows: 15 + origin: + - 7.5 + - -4.5 + rowsep: 2.54 + width: 44 + proMini: + colsep: 15.239999999999998 + extras: [] + height: 9 + length: 39 + ncols: 2 + nrows: 12 + origin: + - 0 + - 0 + rowsep: 2.54 + width: 19 depth: - defaultValue: 10 + defaultValue: 20 spec: minValue: 0 units: mm @@ -80,53 +103,41 @@ parameters: minValue: 0 units: mm valueType: (float, int) + offset: + defaultValue: + - 0 + - 0 + spec: {} width: - defaultValue: 10 + defaultValue: 50 spec: minValue: 0 units: mm valueType: (float, int) -source: ../builders/ESPBrainsBuilder.py +source: ../builders/MountedBrainsBuilder.py subcomponents: beam: - classname: RectBeam + classname: SimpleRectBeam kwargs: {} parameters: - angle: 90 depth: parameter: width + depth#minValue: + function: x.get("width") + parameter: brain length: parameter: length - mindepth: - function: getDim(x, 'width') - parameter: brain - minlength: - function: getDim(x, 'length') - parameter: brain - minwidth: - function: getDim(x, 'height') + length#minValue: + function: x.get("length") parameter: brain width: parameter: depth - header: - classname: Header - kwargs: {} - parameters: - colsep: - function: getDim(x, 'colsep') - parameter: brain - ncols: - function: getDim(x, 'ncols') - parameter: brain - nrows: - function: getDim(x, 'nrows') + width#minValue: + function: x.get("height") parameter: brain - rowsep: - function: getDim(x, 'rowsep') - parameter: brain - servoPins: - classname: Cutout + brain: + classname: Brains kwargs: {} parameters: - dx: 27 - dy: 8 + brain: + parameter: brain diff --git a/rocolib/library/MountedServo.yaml b/rocolib/library/MountedServo.yaml index aaaa270f888997a30548a631d78a58d8ed5baa9a..59533eae6be6fd4f0ed49668b961fc6a7479407d 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) @@ -126,17 +133,48 @@ parameters: units: mm valueType: (float, int) offset: - defaultValue: null - spec: - optional: true - overrides: - - flip - - center - - shift + defaultValue: 0 + spec: {} servo: defaultValue: fs90r spec: - valueType: str + values: + ds2g: + horndepth: 1 + hornheight: 9 + hornlength: 11 + hornoffset: 4 + motorheight: 11 + motorlength: 17 + motorwidth: 8.5 + shoulderlength: 3.5 + fs90r: + horndepth: 2 + hornheight: 16 + hornlength: 10 + hornoffset: 8 + motorheight: 19 + motorlength: 23 + motorwidth: 13 + shoulderlength: 5 + s4303r: + horndepth: 2 + hornheight: 14 + hornlength: 38 + hornoffset: 7 + motorheight: 29 + motorlength: 31 + motorwidth: 17 + shoulderlength: 10 + tgy1370a: + horndepth: 2 + hornheight: 10 + hornlength: 7 + hornoffset: 4 + motorheight: 14 + motorlength: 20 + motorwidth: 9 + shoulderlength: 4 shift: defaultValue: 0 spec: diff --git a/rocolib/library/RectBeam.py b/rocolib/library/RectBeam.py index 474e247b39209ba69f17a9318e956041462ea762..74ebf2375dd66e0c2cf4221770ff2cafae0b7017 100644 --- a/rocolib/library/RectBeam.py +++ b/rocolib/library/RectBeam.py @@ -8,18 +8,13 @@ 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")) + self.addParameter("angle", overrides=("tangle", "bangle")) self.addParameter("tangle", 80, paramType="angle", maxValue=180) self.addParameter("bangle", 135, paramType="angle", maxValue=180) - self.addParameter("root", optional=True, valueType="int") + self.addParameter("root", 0, values=[0,1,2,3]) self.addParameter("addTabs", True, valueType="bool") for i in range(4): @@ -29,23 +24,11 @@ class RectBeam(FoldedComponent): self.addEdgeInterface("tabedge", "r3.e1", "length") self.addEdgeInterface("slotedge", "r0.e3", "length") - def modifyParameters(self): - self.p.width = max(self.p.width, self.p.minwidth) - self.p.depth = max(self.p.depth, self.p.mindepth) - self.p.length = max(self.p.length, self.p.minlength) - def assemble(self): - if self.p.angle is not None: - bangle = 90 - self.p.angle - tangle = 90 - self.p.angle - else: - bangle = 90 - self.p.bangle - tangle = 90 - self.p.tangle + bangle = 90 - self.p.bangle + tangle = 90 - self.p.tangle - try: - root = self.p.root - except KeyError: - root = None + root = self.p.root length = self.p.length width = self.p.width @@ -76,7 +59,7 @@ class RectBeam(FoldedComponent): fromEdge = None for i in range(4): - self.attachEdge(fromEdge, rs[i], "e3", prefix="r%d"%i, angle=90, root=((i == root) if root is not None else False)) + self.attachEdge(fromEdge, rs[i], "e3", prefix="r%d"%i, angle=90, root=((i == root))) fromEdge = 'r%d.e1' % i self.setFaceInterface("face%d" % i, "r%d" % ((i-phase)%4)) diff --git a/rocolib/library/ServoMotor.py b/rocolib/library/ServoMotor.py index a4f2761937f9fc127b04d1383a7024c423b52312..969c4a2b0c0cb6f525d841962ae43eba19d96c43 100644 --- a/rocolib/library/ServoMotor.py +++ b/rocolib/library/ServoMotor.py @@ -2,27 +2,99 @@ from rocolib.api.components import FoldedComponent from rocolib.api.composables.graph.Face import Rectangle as Shape from rocolib.api.ports import AnchorPort from rocolib.utils.utils import decorateGraph -from rocolib.utils.dimensions import getDim from rocolib.utils.transforms import Translate, RotateZ from rocolib.utils.numsym import dot, deg2rad class ServoMotor(FoldedComponent): - def define(self): - self.addParameter("angle", 0, paramType="angle", minValue=None, maxValue=None) - self.addParameter("servo", "fs90r", paramType="dimension") - self.addInterface("mount", AnchorPort(self, self.getGraph(), "horn", Translate([0,0,0]))) - self.addFaceInterface("horn", "horn") - - def assemble(self): - s = self.p.servo - dz = getDim(s, "hornheight") - dy = getDim(s, "motorlength") / 2 - getDim(s, "hornoffset") - - f = Shape("horn", 0, 0) - decorateGraph(f, Shape("hole", 1, 1)) - self.addFace(f) - self.setInterface("mount", AnchorPort(self, self.getGraph(), "horn", dot(RotateZ(deg2rad(self.p.angle)), Translate([0,-dy,dz])))) + def define(self): + self.addParameter("angle", 0, paramType="angle", minValue=None, maxValue=None) + self.addParameter("servo", "fs90r", values=ServoMotor.dims) + self.addInterface("mount", AnchorPort(self, self.getGraph(), "horn", Translate([0,0,0]))) + self.addFaceInterface("horn", "horn") + + def assemble(self): + s = self.p.servo + + dz = s.get("hornheight") + dy = s.get("motorlength") / 2 - s.get("hornoffset") + + f = Shape("horn", 0, 0) + decorateGraph(f, Shape("hole", 1, 1)) + self.addFace(f) + self.setInterface("mount", AnchorPort(self, self.getGraph(), "horn", dot(RotateZ(deg2rad(self.p.angle)), Translate([0,-dy,dz])))) + + + ''' + Servo dimension parameters: + + |<-G->| + ^ =====v===== { H + E _I_ + v ________| | |_____ + ^ | |<-F->|<> D + | | | + B | <--- A ---> | + | | (X) C | + v |_____________| + + A : motorlength + B : motorheight + C : motorwidth + D : shoulderlength + + E : hornheight + F : hornoffset + + G : hornlength + H : horndepth + + ''' + + dims = dict( + ds2g = dict( + motorlength = 17, + motorwidth = 8.5, + motorheight = 11, + shoulderlength= 3.5, + hornlength = 11, + hornheight = 9, + hornoffset = 4, + horndepth = 1, + ), + s4303r = dict( + motorlength = 31, + motorwidth = 17, + motorheight = 29, + shoulderlength= 10, + hornlength = 38, + hornheight = 14, + hornoffset = 7, + horndepth = 2, + ), + tgy1370a = dict( + motorlength = 20, + motorwidth = 9, + motorheight = 14, + shoulderlength= 4, + hornlength = 7, + hornheight = 10, + hornoffset = 4, + horndepth = 2, + ), + fs90r = dict( + motorlength = 23, + motorwidth = 13, + motorheight = 19, + shoulderlength= 5, + hornlength = 10, + hornheight = 16, + hornoffset = 8, + horndepth = 2, + ), + ) + if __name__ == "__main__": ServoMotor.test() + print(ServoMotor.dims) diff --git a/rocolib/library/ServoMount.py b/rocolib/library/ServoMount.py index 797a1e9823560b0849711f0bc35e1a7021e3c7e1..2d1be2ab79cd3826c834b6a88ed7046ecacacd85 100644 --- a/rocolib/library/ServoMount.py +++ b/rocolib/library/ServoMount.py @@ -1,6 +1,5 @@ from rocolib.api.components.Component import Component from rocolib.api.ports.EdgePort import EdgePort -from rocolib.utils.dimensions import getDim from rocolib.api.Function import Function @@ -11,9 +10,9 @@ class ServoMount(Component): if self.p.offset: return - ml = getDim(self.p.servo, "motorlength") - sl = getDim(self.p.servo, "shoulderlength") - ho = getDim(self.p.servo, "hornoffset") + ml = self.p.servo.get("motorlength") + sl = self.p.servo.get("shoulderlength") + ho = self.p.servo.get("hornoffset") dy = self.p.length/2. - ml/2. - sl if self.p.center: diff --git a/rocolib/library/ServoMount.yaml b/rocolib/library/ServoMount.yaml index f45cb93dc81a8f21bba35a103e820070315f0633..45d9c9e63ebbef06b611ffa8755129071419b4df 100644 --- a/rocolib/library/ServoMount.yaml +++ b/rocolib/library/ServoMount.yaml @@ -73,17 +73,48 @@ parameters: units: mm valueType: (float, int) offset: - defaultValue: null - spec: - optional: true - overrides: - - flip - - center - - shift + defaultValue: 0 + spec: {} servo: defaultValue: fs90r spec: - valueType: str + values: + ds2g: + horndepth: 1 + hornheight: 9 + hornlength: 11 + hornoffset: 4 + motorheight: 11 + motorlength: 17 + motorwidth: 8.5 + shoulderlength: 3.5 + fs90r: + horndepth: 2 + hornheight: 16 + hornlength: 10 + hornoffset: 8 + motorheight: 19 + motorlength: 23 + motorwidth: 13 + shoulderlength: 5 + s4303r: + horndepth: 2 + hornheight: 14 + hornlength: 38 + hornoffset: 7 + motorheight: 29 + motorlength: 31 + motorwidth: 17 + shoulderlength: 10 + tgy1370a: + horndepth: 2 + hornheight: 10 + hornlength: 7 + hornoffset: 4 + motorheight: 14 + motorlength: 20 + motorwidth: 9 + shoulderlength: 4 shift: defaultValue: 0 spec: @@ -99,20 +130,23 @@ subcomponents: addTabs: parameter: addTabs depth: - function: getDim(x, "motorheight") + function: x.get("motorheight") parameter: servo length: parameter: length + length#minValue: + function: x.get("motorlength") + 2 * x.get("shoulderlength") + parameter: servo width: - function: getDim(x, "motorwidth") + function: x.get("motorwidth") parameter: servo mount: classname: Cutout kwargs: {} parameters: dx: - function: getDim(x, "motorwidth") * 0.99 + function: x.get("motorwidth") * 0.99 parameter: servo dy: - function: getDim(x, "motorlength") + function: x.get("motorlength") 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/Stool.py b/rocolib/library/Stool.py index c5ce4be0f99dc40017c6b366c503ac933169ce20..8c36db6363edd2fdd15ee654141bedeeca35c399 100644 --- a/rocolib/library/Stool.py +++ b/rocolib/library/Stool.py @@ -8,14 +8,12 @@ class Stool(FoldedComponent): def define(self): self.addParameter("height", 60, paramType="length", minValue=10) self.addParameter("legs", 3, paramType="count", minValue=1) - self.addParameter("radius", optional=True, overrides=("legwidth",)) - self.addParameter("legwidth", 20, paramType="length", minValue=10) + self.addParameter("radius", minValue=10, overrides={ + "legwidth": 'c.getParameter("radius") * 2 * np.sin( np.pi() / c.getParameter("legs") / 2)', + }) + self.addParameter("legwidth", 20, paramType="length", minValue=9) self.addParameter("angle", 80, paramType="angle") - def modifyParameters(self): - if self.p.radius is not None: - self.p.legwidth = r2l.r2l(self.p.radius, self.p.legs*2) - def assemble(self): h = self.p.height lp = self.p.legs diff --git a/rocolib/library/ThruHole.py b/rocolib/library/ThruHole.py new file mode 100644 index 0000000000000000000000000000000000000000..b61671480639d9731fe14a335c8ff7e73eee81e2 --- /dev/null +++ b/rocolib/library/ThruHole.py @@ -0,0 +1,35 @@ +from rocolib.api.components import DecorationComponent +from rocolib.api.composables.graph.Face import Face + + +class ThruHole(DecorationComponent): + + def define(self): + self.addParameter("nrows", 3, paramType="count") + self.addParameter("ncols", 1, paramType="count") + self.addParameter("rowsep", 2.54, paramType="length") + self.addParameter("colsep", 2.54, paramType="length") + self.addParameter("diameter", 1, paramType="length") + + def assemble(self): + diam = self.getParameter("diameter")/2. + nr = self.getParameter("nrows") + nc = self.getParameter("ncols") + + def hole(i, j, d): + dx = (j - (nc-1)/2.)*self.getParameter("colsep") + dy = (i - (nr-1)/2.)*self.getParameter("rowsep") + return Face("r-%d-%d" % (i,j), + ((dx-d, dy-d), (dx+d, dy-d), (dx+d, dy+d), (dx-d, dy+d)), + recenter=False) + + for i in range(nr): + for j in range(nc): + d = diam + if (i == 0 and j == 0) or \ + (i == nr-1 and j == nc-1): + d = diam*3 + self.addFace(hole(i,j,d), prefix="r-%d-%d" % (i,j)) + +if __name__ == "__main__": + ThruHole.test() diff --git a/rocolib/library/UChannel.py b/rocolib/library/UChannel.py index b16166970d50c2968ff538ebd3922c6e2f76e999..f1e46835d38c5d1b7321744bcc39079c2a571836 100644 --- a/rocolib/library/UChannel.py +++ b/rocolib/library/UChannel.py @@ -9,9 +9,9 @@ class UChannel(FoldedComponent): self.addParameter("depth", 20, paramType="length") # Minimum of 45deg to make sure the geometry stays convex - self.addParameter("angle", optional=True, overrides=("tangle", "bangle")) self.addParameter("tangle", 80, paramType="angle", minValue=45) self.addParameter("bangle", 135, paramType="angle", minValue=45) + self.addParameter("angle", paramType="angle", minValue=45, overrides=("bangle", "tangle")) for i in range(3): self.addEdgeInterface("topedge%d" % i, "r%d.e0" % i, ["depth", "width"][i % 2]) @@ -23,11 +23,6 @@ class UChannel(FoldedComponent): self.addEdgeInterface("ledge", "r0.e3", "length") self.addEdgeInterface("redge", "r2.e1", "length") - def modifyParameters(self): - if self.p.angle is not None: - self.p.bangle = self.p.angle - self.p.tangle = self.p.angle - def assemble(self): bangle = 90 - self.p.bangle tangle = 90 - self.p.tangle diff --git a/rocolib/library/Wheel.yaml b/rocolib/library/Wheel.yaml index 51d9e01c2f7ca3f35118e9b7cab3c760ff056e21..6de1d93af4b845fe912b2cf84b60e44275325bc3 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) @@ -126,13 +133,8 @@ parameters: units: mm valueType: (float, int) offset: - defaultValue: null - spec: - optional: true - overrides: - - flip - - center - - shift + defaultValue: 0 + spec: {} radius: defaultValue: 25 spec: @@ -142,7 +144,43 @@ parameters: servo: defaultValue: fs90r spec: - valueType: str + values: + ds2g: + horndepth: 1 + hornheight: 9 + hornlength: 11 + hornoffset: 4 + motorheight: 11 + motorlength: 17 + motorwidth: 8.5 + shoulderlength: 3.5 + fs90r: + horndepth: 2 + hornheight: 16 + hornlength: 10 + hornoffset: 8 + motorheight: 19 + motorlength: 23 + motorwidth: 13 + shoulderlength: 5 + s4303r: + horndepth: 2 + hornheight: 14 + hornlength: 38 + hornoffset: 7 + motorheight: 29 + motorlength: 31 + motorwidth: 17 + shoulderlength: 10 + tgy1370a: + horndepth: 2 + hornheight: 10 + hornlength: 7 + hornoffset: 4 + motorheight: 14 + motorlength: 20 + motorwidth: 9 + shoulderlength: 4 shift: defaultValue: 0 spec: diff --git a/rocolib/utils/dimensions.py b/rocolib/utils/dimensions.py deleted file mode 100644 index 4d87f57f6335a69363889b7f6f15bd43d22ed6e9..0000000000000000000000000000000000000000 --- a/rocolib/utils/dimensions.py +++ /dev/null @@ -1,156 +0,0 @@ -from sympy import symbols - -dims = {} - -def isDim(obj): - return obj in dims - -def getDim(obj, param): - return dims[obj][param] - -''' -Brain dimension parameters: - params.setdefault("length") - params.setdefault("width") - params.setdefault("height") - - params.setdefault("nrows") - params.setdefault("ncols") - params.setdefault("rowsep") - params.setdefault("colsep") -''' -dims["proMini"] = { "type" : "brains", - "length" : 39, - "width" : 19, - "height" : 9, - "nrows" : 12, - "ncols" : 2, - "rowsep" : 0.1 * 25.4, - "colsep" : 0.6 * 25.4, -} - -dims["nodeMCU"] = { "type" : "brains", - "length" : 59.5, - "width" : 44, - "height" : 13, - "nrows" : 15, - "ncols" : 2, - "rowsep" : 0.1 * 25.4, - "colsep" : 0.9 * 25.4, -} - -''' -Servo dimension parameters: - - |<-G->| -^ =====v===== { H -E _I_ -v ________| | |_____ - ^ | |<-F->|<> D - | | | - B | <--- A ---> | - | | (X) C | - v |_____________| - -A : motorlength -B : motorheight -C : motorwidth -D : shoulderlength - -E : hornheight -F : hornoffset - -G : hornlength -H : horndepth - - params.setdefault("motorlength") - params.setdefault("motorwidth") - params.setdefault("motorheight") - params.setdefault("shoulderlength", 0) - - params.setdefault("hornheight", 0) - params.setdefault("hornoffset", 0) - - params.setdefault("hornlength", 0) - params.setdefault("horndepth", 0) - -If horn is not symmetric? - - params.setdefault("rhornlength", 0) - params.setdefault("lhornlength", 0) - if name == "hornlength": - self.setParameter("rhornlength", val) - self.setParameter("lhornlength", val) - -Should horn be a different object? - -''' - -dims["ds2g"] = { "type" : "servo", - "motorlength" : 17, - "motorwidth" : 8.5, - "motorheight" : 11, - "shoulderlength": 3.5, - "hornlength" : 11, - "hornheight" : 9, - "hornoffset" : 4, - "horndepth" : 1, -} - -dims["s4303r"] = { "type" : "servo", - "motorlength" : 31, - "motorwidth" : 17, - "motorheight" : 29, - "shoulderlength": 10, - "hornlength" : 38, - "hornheight" : 14, - "hornoffset" : 7, - "horndepth" : 2, -} - -dims["tgy1370a"] = { "type" : "servo", - "motorlength" : 20, - "motorwidth" : 9, - "motorheight" : 14, - "shoulderlength": 4, - "hornlength" : 7, - "hornheight" : 10, - "hornoffset" : 4, - "horndepth" : 2, -} - -dims["fs90r"] = { "type" : "servo", - "motorlength" : 23, - "motorwidth" : 13, - "motorheight" : 19, - "shoulderlength": 5, - "hornlength" : 10, - "hornheight" : 16, - "hornoffset" : 8, - "horndepth" : 2, -} - -l, w, h, r, c, rs, cs = symbols("brainLength brainWidth brainHeight brainNRows brainNCols brainRowSep brainColSep", positive=True) - -dims["brainSymbols"] = { "type" : "brains", - "length" : l, - "width" : w, - "height" : h, - "nrows" : r, - "ncols" : c, - "rowsep" : rs, - "colsep" : cs, -} - -l, w, h, s, hl, hh, ho, hd = symbols("servoLength servoWidth servoHeight servoShoulder servoHornLength servoHornHeight servoHornOffset servoHornDepth", positive=True) - -dims["servoSymbols"] = { "type" : "servo", - "motorlength" : l, - "motorwidth" : w, - "motorheight" : h, - "shoulderlength": s, - "hornlength" : hl, - "hornheight" : hh, - "hornoffset" : ho, - "horndepth" : hd, -}