From 91ed6490d806abd1d61c5e06eccd9d4809696fe8 Mon Sep 17 00:00:00 2001 From: mehtank <mehtank@ucla.edu> Date: Mon, 19 Sep 2022 03:39:35 +0000 Subject: [PATCH] Overrides --- rocolib/api/Parameterized.py | 38 +++++++++++++++++++++++---- rocolib/builders/ServoMountBuilder.py | 4 ++- rocolib/library/Cutout.py | 24 ++++++++--------- rocolib/library/MountedServo.yaml | 9 ++----- rocolib/library/RectBeam.py | 2 +- rocolib/library/ServoMount.yaml | 9 ++----- rocolib/library/Stool.py | 10 +++---- rocolib/library/UChannel.py | 10 +++---- rocolib/library/Wheel.yaml | 9 ++----- 9 files changed, 62 insertions(+), 53 deletions(-) diff --git a/rocolib/api/Parameterized.py b/rocolib/api/Parameterized.py index 1fc3fbc..b3d3632 100644 --- a/rocolib/api/Parameterized.py +++ b/rocolib/api/Parameterized.py @@ -44,8 +44,8 @@ class Parameter: 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 = {} @@ -60,7 +60,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 @@ -94,11 +94,11 @@ class Parameter: def assertValid(self, value): if value is None: - if self.spec.get("optional", False): + if self.spec.get("overrides", False): self.value = value return 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])): @@ -116,6 +116,32 @@ class Parameter: 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) @@ -158,6 +184,8 @@ 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, validate=True): diff --git a/rocolib/builders/ServoMountBuilder.py b/rocolib/builders/ServoMountBuilder.py index 53ba903..900cde2 100644 --- a/rocolib/builders/ServoMountBuilder.py +++ b/rocolib/builders/ServoMountBuilder.py @@ -4,11 +4,13 @@ from rocolib.api.Function import Function c = Component() c.addParameter("servo", "fs90r", paramType="dimension") + 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") diff --git a/rocolib/library/Cutout.py b/rocolib/library/Cutout.py index 77cb2bb..feb51f7 100644 --- a/rocolib/library/Cutout.py +++ b/rocolib/library/Cutout.py @@ -2,20 +2,18 @@ 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": lambda c : c.getParameter("d"), + "dy": lambda c : c.getParameter("d"), + }) - def modifyParameters(self): - if self.getParameter("d") is not None: - self.setParameter("dx", self.getParameter("d")) - self.setParameter("dy", self.getParameter("d")) - - def assemble(self): - dx = self.getParameter("dx") - dy = self.getParameter("dy") - self.addFace(Rectangle("r0", dx, dy), prefix="r0") + def assemble(self): + dx = self.getParameter("dx") + dy = self.getParameter("dy") + self.addFace(Rectangle("r0", dx, dy), prefix="r0") if __name__ == "__main__": Cutout.test() diff --git a/rocolib/library/MountedServo.yaml b/rocolib/library/MountedServo.yaml index f6353e8..2bcbbe8 100644 --- a/rocolib/library/MountedServo.yaml +++ b/rocolib/library/MountedServo.yaml @@ -133,13 +133,8 @@ parameters: units: mm valueType: (float, int) offset: - defaultValue: null - spec: - optional: true - overrides: - - flip - - center - - shift + defaultValue: 0 + spec: {} servo: defaultValue: fs90r spec: diff --git a/rocolib/library/RectBeam.py b/rocolib/library/RectBeam.py index 60abf3d..12a323d 100644 --- a/rocolib/library/RectBeam.py +++ b/rocolib/library/RectBeam.py @@ -14,7 +14,7 @@ class RectBeam(FoldedComponent): 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, valueType="int", minValue=0) self.addParameter("addTabs", True, valueType="bool") for i in range(4): diff --git a/rocolib/library/ServoMount.yaml b/rocolib/library/ServoMount.yaml index 829101a..9aa85d0 100644 --- a/rocolib/library/ServoMount.yaml +++ b/rocolib/library/ServoMount.yaml @@ -73,13 +73,8 @@ parameters: units: mm valueType: (float, int) offset: - defaultValue: null - spec: - optional: true - overrides: - - flip - - center - - shift + defaultValue: 0 + spec: {} servo: defaultValue: fs90r spec: diff --git a/rocolib/library/Stool.py b/rocolib/library/Stool.py index 3bf5b6e..a7d4165 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": lambda c: r2l.r2l(c.getParameter("radius"), c.getParameter("legs")*2) + }) + self.addParameter("legwidth", 20, paramType="length", minValue=9) self.addParameter("angle", 80, paramType="angle") - def modifyParameters(self): - if self.getParameter("radius") is not None: - self.setParameter("legwidth", r2l.r2l(self.getParameter("radius"), self.getParameter("legs")*2)) - def assemble(self): h = self.getParameter("height") lp = self.getParameter("legs") diff --git a/rocolib/library/UChannel.py b/rocolib/library/UChannel.py index 010014d..088b9ac 100644 --- a/rocolib/library/UChannel.py +++ b/rocolib/library/UChannel.py @@ -9,9 +9,12 @@ 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": lambda c : c.getParameter("angle"), + "tangle": lambda c : c.getParameter("angle"), + }) for i in range(3): self.addEdgeInterface("topedge%d" % i, "r%d.e0" % i, ["depth", "width"][i % 2]) @@ -23,11 +26,6 @@ class UChannel(FoldedComponent): self.addEdgeInterface("ledge", "r0.e3", "length") self.addEdgeInterface("redge", "r2.e1", "length") - def modifyParameters(self): - if self.getParameter("angle") is not None: - self.setParameter("bangle", self.getParameter("angle")) - self.setParameter("tangle", self.getParameter("angle")) - def assemble(self): bangle = 90 - self.getParameter("bangle") tangle = 90 - self.getParameter("tangle") diff --git a/rocolib/library/Wheel.yaml b/rocolib/library/Wheel.yaml index 7d22b01..f902aa7 100644 --- a/rocolib/library/Wheel.yaml +++ b/rocolib/library/Wheel.yaml @@ -133,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: -- GitLab