diff --git a/clearpath_config/platform/battery.py b/clearpath_config/platform/battery.py new file mode 100644 index 0000000..1f3aaeb --- /dev/null +++ b/clearpath_config/platform/battery.py @@ -0,0 +1,155 @@ +# Software License Agreement (BSD) +# +# @author Luis Camero +# @copyright (c) 2023, Clearpath Robotics, Inc., All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Clearpath Robotics nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +from clearpath_config.common.types.config import BaseConfig +from clearpath_config.common.types.platform import Platform +from clearpath_config.common.utils.dictionary import flip_dict + + +class BatteryConfig(BaseConfig): + BATTERY = "battery" + + # Models + MODEL = "model" + UNKNOWN = "unknown" + # Husky Lead Acid + ES20_12C = "ES20-12C" + # Husky/Jackal Li_ION + HE2613 = "HE2613" + # Warthog Lead Acid + U1_35 = "U1-35" + # Warthog LiFEPO4 + ALM12V35 = "ALM12V35" + U24_12XP = "U24-12XP" + U27_12XP = "U27-12XP" + + # Configurations + CONFIGURATION = "configuration" + _2S1P = "2S1P" + _1S3P = "1S3P" + _1S4P = "1S4P" + _1S1P = "1S1P" + _4S3P = "4S3P" + _4S1P = "4S1P" + + VALID = { + Platform.GENERIC: { + UNKNOWN: [UNKNOWN] + }, + Platform.A200: { + ES20_12C: [_2S1P], + HE2613: [_1S3P, _1S4P], + }, + Platform.J100: { + HE2613: [_1S1P], + }, + Platform.W200: { + U1_35: [_4S3P], + ALM12V35: [_4S3P], + U24_12XP: [_4S1P], + U27_12XP: [_4S1P], + }, + } + + TEMPLATE = { + BATTERY: { + MODEL: MODEL, + CONFIGURATION: CONFIGURATION + } + } + + KEYS = flip_dict(TEMPLATE) + + DEFAULTS = { + MODEL: UNKNOWN, + CONFIGURATION: UNKNOWN + } + + def __init__( + self, + config: dict = {}, + model: str = DEFAULTS[MODEL], + configuration: str = DEFAULTS[CONFIGURATION], + ) -> None: + # Initialization + self._config = {} + self.model = model + self.configuration = configuration + # Setter Template + setters = { + self.KEYS[self.MODEL]: BatteryConfig.model, + self.KEYS[self.CONFIGURATION]: BatteryConfig.configuration, + } + super().__init__(setters, config, self.BATTERY) + + def update(self, serial_number: bool = False) -> None: + if serial_number: + platform = BaseConfig.get_platform_model() + self.model = list(self.VALID[platform])[0] + self.configuration = list(self.VALID[platform][self.model])[0] + + @property + def model(self) -> str: + self.set_config_param( + key=self.KEYS[self.MODEL], + value=self._model + ) + return self._model + + @model.setter + def model(self, value: str) -> None: + platform = BaseConfig.get_platform_model() + assert platform in self.VALID, ( + "Platform must be one of: %s" % self.VALID + ) + assert value in self.VALID[platform], ( + "Battery model for platform '%s' must be one of: %s" % (platform, self.VALID[platform]) + ) + self._model = value + + @property + def configuration(self) -> str: + self.set_config_param( + key=self.KEYS[self.CONFIGURATION], + value=self._configuration + ) + return self._configuration + + @configuration.setter + def configuration(self, value: str) -> None: + platform = BaseConfig.get_platform_model() + assert platform in self.VALID, ( + "Platform must be one of: %s" % self.VALID + ) + assert self.model in self.VALID[platform], ( + "Battery model for platform '%s' must be one of: %s" % (platform, self.VALID[platform]) + ) + assert value in self.VALID[platform][self.model], ( + "Battery configuration for platform '%s', and battery model '%s' must be one of: %s" % ( + platform, self.model, self.VALID[platform][self.model]) + ) + self._configuration = value diff --git a/clearpath_config/platform/platform.py b/clearpath_config/platform/platform.py index 453f471..32501da 100644 --- a/clearpath_config/platform/platform.py +++ b/clearpath_config/platform/platform.py @@ -27,6 +27,7 @@ # POSSIBILITY OF SUCH DAMAGE. from clearpath_config.common.types.config import BaseConfig from clearpath_config.common.utils.dictionary import flip_dict +from clearpath_config.platform.battery import BatteryConfig from clearpath_config.platform.extras import ExtrasConfig from clearpath_config.platform.attachments.config import BaseAttachmentsConfig from clearpath_config.platform.attachments.mux import AttachmentsConfigMux @@ -38,15 +39,19 @@ class PlatformConfig(BaseConfig): # Controllers PS4 = "ps4" LOGITECH = "logitech" + CONTROLLER = "controller" ATTACHMENTS = "attachments" # Extras EXTRAS = "extras" + # Battery + BATTERY = "battery" TEMPLATE = { PLATFORM: { CONTROLLER: CONTROLLER, ATTACHMENTS: ATTACHMENTS, + BATTERY: BATTERY, EXTRAS: EXTRAS } } @@ -57,7 +62,8 @@ class PlatformConfig(BaseConfig): # PLATFORM CONTROLLER: PS4, ATTACHMENTS: {}, - EXTRAS: ExtrasConfig.DEFAULTS + BATTERY: BatteryConfig.DEFAULTS, + EXTRAS: ExtrasConfig.DEFAULTS, } def __init__( @@ -65,17 +71,20 @@ def __init__( config: dict = {}, controller: str = DEFAULTS[CONTROLLER], attachments: str = DEFAULTS[ATTACHMENTS], - extras: str = DEFAULTS[EXTRAS] + battery: dict = DEFAULTS[BATTERY], + extras: dict = DEFAULTS[EXTRAS], ) -> None: # Initialization self._config = {} self.controller = controller self.attachments = attachments + self._battery = BatteryConfig(battery) self._extras = ExtrasConfig(extras) # Setter Template setters = { self.KEYS[self.CONTROLLER]: PlatformConfig.controller, self.KEYS[self.ATTACHMENTS]: PlatformConfig.attachments, + self.KEYS[self.BATTERY]: PlatformConfig.battery, self.KEYS[self.EXTRAS]: PlatformConfig.extras } super().__init__(setters, config, self.PLATFORM) @@ -87,6 +96,8 @@ def update(self, serial_number=False) -> None: # TODO: Set PACS Profile # Reload extras self.extras.update(serial_number=serial_number) + # Reload battery + self.battery.update(serial_number=serial_number) @property def controller(self) -> str: @@ -139,3 +150,23 @@ def extras(self, value: dict | ExtrasConfig) -> None: def get_controller(self) -> str: return self.controller + + @property + def battery(self) -> BatteryConfig: + self.set_config_param( + key=self.KEYS[self.BATTERY], + value=self._battery.config[self.BATTERY] + ) + return self._battery + + @battery.setter + def battery(self, value: dict | BatteryConfig) -> None: + if isinstance(value, dict): + self._battery.config = value + elif isinstance(value, BatteryConfig): + self._battery = value + else: + assert isinstance(value, dict) or ( + isinstance(value, BatteryConfig)), ( + "Battery configuration must be of type 'dict' or 'BatteryConfig'" + ) diff --git a/clearpath_config/sample/a200/a200_default.yaml b/clearpath_config/sample/a200/a200_default.yaml index 8d25bd2..ab11934 100644 --- a/clearpath_config/sample/a200/a200_default.yaml +++ b/clearpath_config/sample/a200/a200_default.yaml @@ -15,6 +15,9 @@ system: workspaces: [] platform: controller: ps4 + battery: + model: ES20-12C + configuration: 2S1P attachments: front_bumper: enabled: true diff --git a/clearpath_config/sample/a200/a200_dual_laser.yaml b/clearpath_config/sample/a200/a200_dual_laser.yaml index 64bd89e..a91d85b 100644 --- a/clearpath_config/sample/a200/a200_dual_laser.yaml +++ b/clearpath_config/sample/a200/a200_dual_laser.yaml @@ -15,6 +15,9 @@ system: workspaces: [] platform: controller: ps4 + battery: + model: ES20-12C + configuration: 2S1P attachments: front_bumper: enabled: true diff --git a/clearpath_config/sample/a200/a200_sample.yaml b/clearpath_config/sample/a200/a200_sample.yaml index 13e1b08..ba38865 100644 --- a/clearpath_config/sample/a200/a200_sample.yaml +++ b/clearpath_config/sample/a200/a200_sample.yaml @@ -15,6 +15,9 @@ system: workspaces: [] platform: controller: ps4 + battery: + model: ES20-12C + configuration: 2S1P attachments: front_bumper: enabled: true diff --git a/clearpath_config/sample/a200/a200_velodyne.yaml b/clearpath_config/sample/a200/a200_velodyne.yaml index a8eb08e..f57e28c 100644 --- a/clearpath_config/sample/a200/a200_velodyne.yaml +++ b/clearpath_config/sample/a200/a200_velodyne.yaml @@ -15,6 +15,9 @@ system: workspaces: [] platform: controller: ps4 + battery: + model: ES20-12C + configuration: 2S1P attachments: front_bumper: enabled: true diff --git a/clearpath_config/sample/j100/j100_default.yaml b/clearpath_config/sample/j100/j100_default.yaml index f727899..44ac95f 100644 --- a/clearpath_config/sample/j100/j100_default.yaml +++ b/clearpath_config/sample/j100/j100_default.yaml @@ -15,6 +15,9 @@ system: workspaces: [] platform: controller: ps4 + battery: + model: HE2613 + configuration: 1S1P attachments: front_fender: enabled: true diff --git a/clearpath_config/sample/j100/j100_dual_laser.yaml b/clearpath_config/sample/j100/j100_dual_laser.yaml index 4d46089..cb60f78 100644 --- a/clearpath_config/sample/j100/j100_dual_laser.yaml +++ b/clearpath_config/sample/j100/j100_dual_laser.yaml @@ -15,6 +15,9 @@ system: workspaces: [] platform: controller: ps4 + battery: + model: HE2613 + configuration: 1S1P attachments: front_fender: enabled: true diff --git a/clearpath_config/sample/j100/j100_sample.yaml b/clearpath_config/sample/j100/j100_sample.yaml index b0b3485..55cf5f5 100644 --- a/clearpath_config/sample/j100/j100_sample.yaml +++ b/clearpath_config/sample/j100/j100_sample.yaml @@ -15,6 +15,9 @@ system: workspaces: [] platform: controller: ps4 + battery: + model: HE2613 + configuration: 1S1P attachments: front_fender: enabled: true diff --git a/clearpath_config/sample/j100/j100_velodyne.yaml b/clearpath_config/sample/j100/j100_velodyne.yaml index 9e51798..6c5f1d7 100644 --- a/clearpath_config/sample/j100/j100_velodyne.yaml +++ b/clearpath_config/sample/j100/j100_velodyne.yaml @@ -15,6 +15,9 @@ system: workspaces: [] platform: controller: ps4 + battery: + model: HE2613 + configuration: 1S1P attachments: front_fender: enabled: true