|
| 1 | + |
| 2 | +#include "SnobotSim/Config/SimulatorConfigReaderV1.h" |
| 3 | + |
| 4 | +#include <iostream> |
| 5 | + |
| 6 | +#include <filesystem> |
| 7 | + |
| 8 | +#include "SnobotSim/Config/SimulatorConfigV1.h" |
| 9 | +#include "SnobotSim/GetSensorActuatorHelper.h" |
| 10 | +#include "SnobotSim/Logging/SnobotLogger.h" |
| 11 | +#include "SnobotSim/ModuleWrapper/Factories/FactoryContainer.h" |
| 12 | +#include "SnobotSim/MotorSim/GravityLoadDcMotorSim.h" |
| 13 | +#include "SnobotSim/MotorSim/RotationalLoadDcMotorSim.h" |
| 14 | +#include "SnobotSim/MotorSim/SimpleMotorSimulator.h" |
| 15 | +#include "SnobotSim/MotorSim/StaticLoadDcMotorSim.h" |
| 16 | +#include "SnobotSim/SensorActuatorRegistry.h" |
| 17 | +#include "yaml-cpp/yaml.h" |
| 18 | + |
| 19 | +void ParseMap(const YAML::Node& aNode, std::map<int, std::string>& aMap) |
| 20 | +{ |
| 21 | + for (YAML::const_iterator it = aNode.begin(); it != aNode.end(); ++it) |
| 22 | + { |
| 23 | + aMap[it->first.as<int>()] = it->second.as<std::string>(); |
| 24 | + } |
| 25 | +} |
| 26 | + |
| 27 | +template <typename T> |
| 28 | +void ParseVector(const YAML::Node& aNode, std::vector<T>& aVector) |
| 29 | +{ |
| 30 | + for (YAML::const_iterator it = aNode.begin(); it != aNode.end(); ++it) |
| 31 | + { |
| 32 | + T value; |
| 33 | + (*it) >> value; |
| 34 | + aVector.push_back(value); |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +void LoadBasicConfig(const YAML::Node& aNode, BasicModuleConfig& aOutput) |
| 39 | +{ |
| 40 | + aOutput.mHandle = aNode["mHandle"].as<int>(); |
| 41 | + aOutput.mName = aNode["mName"].as<std::string>(); |
| 42 | + aOutput.mType = aNode["mType"].as<std::string>(); |
| 43 | +} |
| 44 | + |
| 45 | +const YAML::Node& operator>>(const YAML::Node& aNode, EncoderConfig& aOutput) |
| 46 | +{ |
| 47 | + LoadBasicConfig(aNode, aOutput); |
| 48 | + aOutput.mConnectedSpeedControllerHandle = aNode["mConnectedSpeedControllerHandle"].as<int>(); |
| 49 | + return aNode; |
| 50 | +} |
| 51 | + |
| 52 | +const YAML::Node& operator>>(const YAML::Node& aNode, PwmConfig& aOutput) |
| 53 | +{ |
| 54 | + LoadBasicConfig(aNode, aOutput); |
| 55 | + |
| 56 | + if (aNode["mMotorSimConfig"]) |
| 57 | + { |
| 58 | + const YAML::Node& motorSimConfig = aNode["mMotorSimConfig"]; |
| 59 | + const std::string& motorSimConfigTag = motorSimConfig.Tag(); |
| 60 | + |
| 61 | + if (motorSimConfigTag == "tag:yaml.org,2002:com.snobot.simulator.motor_sim.SimpleMotorSimulationConfig") |
| 62 | + { |
| 63 | + aOutput.mMotorSimConfigType = PwmConfig::Simple; |
| 64 | + aOutput.mMotorSimConfig.mSimple.mMaxSpeed = motorSimConfig["mMaxSpeed"].as<double>(); |
| 65 | + } |
| 66 | + else if (motorSimConfigTag == "tag:yaml.org,2002:com.snobot.simulator.motor_sim.StaticLoadMotorSimulationConfig") |
| 67 | + { |
| 68 | + aOutput.mMotorSimConfigType = PwmConfig::Static; |
| 69 | + aOutput.mMotorSimConfig.mStatic.mLoad = motorSimConfig["mLoad"].as<double>(); |
| 70 | + aOutput.mMotorSimConfig.mStatic.mConversionFactor = motorSimConfig["mConversionFactor"].as<double>(); |
| 71 | + } |
| 72 | + else if (motorSimConfigTag == "tag:yaml.org,2002:com.snobot.simulator.motor_sim.GravityLoadMotorSimulationConfig") |
| 73 | + { |
| 74 | + aOutput.mMotorSimConfigType = PwmConfig::Gravity; |
| 75 | + aOutput.mMotorSimConfig.mGravity.mLoad = motorSimConfig["mLoad"].as<double>(); |
| 76 | + } |
| 77 | + else if (motorSimConfigTag == "tag:yaml.org,2002:com.snobot.simulator.motor_sim.RotationalLoadMotorSimulationConfig") |
| 78 | + { |
| 79 | + aOutput.mMotorSimConfigType = PwmConfig::Rotational; |
| 80 | + aOutput.mMotorSimConfig.mRotational.mArmCenterOfMass = motorSimConfig["mArmCenterOfMass"].as<double>(); |
| 81 | + aOutput.mMotorSimConfig.mRotational.mArmMass = motorSimConfig["mArmMass"].as<double>(); |
| 82 | + aOutput.mMotorSimConfig.mRotational.mConstantAssistTorque = motorSimConfig["mConstantAssistTorque"].as<double>(); |
| 83 | + aOutput.mMotorSimConfig.mRotational.mOverCenterAssistTorque = motorSimConfig["mOverCenterAssistTorque"].as<double>(); |
| 84 | + } |
| 85 | + } |
| 86 | + else |
| 87 | + { |
| 88 | + SNOBOT_LOG(SnobotLogging::LOG_LEVEL_CRITICAL, "Thing is null"); |
| 89 | + } |
| 90 | + |
| 91 | + return aNode; |
| 92 | +} |
| 93 | + |
| 94 | +const YAML::Node& operator>>(const YAML::Node& aNode, BasicModuleConfig& aOutput) |
| 95 | +{ |
| 96 | + LoadBasicConfig(aNode, aOutput); |
| 97 | + return aNode; |
| 98 | +} |
| 99 | + |
| 100 | +const YAML::Node& operator>>(const YAML::Node& configNode, SimulatorConfigV1& config) |
| 101 | +{ |
| 102 | + ParseMap(configNode["mDefaultI2CWrappers"], config.mDefaultI2CWrappers); |
| 103 | + ParseMap(configNode["mDefaultSpiWrappers"], config.mDefaultSpiWrappers); |
| 104 | + ParseVector(configNode["mAccelerometers"], config.mAccelerometers); |
| 105 | + ParseVector(configNode["mAnalogIn"], config.mAnalogIn); |
| 106 | + ParseVector(configNode["mAnalogOut"], config.mAnalogOut); |
| 107 | + ParseVector(configNode["mDigitalIO"], config.mDigitalIO); |
| 108 | + ParseVector(configNode["mGyros"], config.mGyros); |
| 109 | + ParseVector(configNode["mRelays"], config.mRelays); |
| 110 | + ParseVector(configNode["mSolenoids"], config.mSolenoids); |
| 111 | + ParseVector(configNode["mEncoders"], config.mEncoders); |
| 112 | + ParseVector(configNode["mPwm"], config.mPwm); |
| 113 | + |
| 114 | + return configNode; |
| 115 | +} |
| 116 | + |
| 117 | +SimulatorConfigReaderV1::SimulatorConfigReaderV1() |
| 118 | +{ |
| 119 | +} |
| 120 | + |
| 121 | +SimulatorConfigReaderV1::~SimulatorConfigReaderV1() |
| 122 | +{ |
| 123 | +} |
| 124 | + |
| 125 | +template <typename FactoryType, typename WrapperType> |
| 126 | +void CreateBasicComponent(std::shared_ptr<FactoryType> aFactory, const std::map<int, WrapperType>& wrapperMap, const BasicModuleConfig& aConfig) |
| 127 | +{ |
| 128 | + aFactory->Create(aConfig.mHandle, aConfig.mType); |
| 129 | + auto findIter = wrapperMap.find(aConfig.mHandle); |
| 130 | + if (findIter != wrapperMap.end()) |
| 131 | + { |
| 132 | + findIter->second->SetName(aConfig.mName); |
| 133 | + } |
| 134 | + else |
| 135 | + { |
| 136 | + SNOBOT_LOG(SnobotLogging::LOG_LEVEL_CRITICAL, "Could not set name for handle " << aConfig.mHandle); |
| 137 | + } |
| 138 | +} |
| 139 | + |
| 140 | +template <typename FactoryType, typename WrapperType> |
| 141 | +void CreateBasicComponents(std::shared_ptr<FactoryType> aFactory, const std::map<int, WrapperType>& wrapperMap, const std::vector<BasicModuleConfig>& aConfigs) |
| 142 | +{ |
| 143 | + for (auto it : aConfigs) |
| 144 | + { |
| 145 | + CreateBasicComponent(aFactory, wrapperMap, it); |
| 146 | + } |
| 147 | +} |
| 148 | + |
| 149 | +void CreatePwmComponents(std::shared_ptr<SpeedControllerFactory> aFactory, const std::map<int, std::shared_ptr<ISpeedControllerWrapper>>& wrapperMap, const std::vector<PwmConfig>& aConfigs) |
| 150 | +{ |
| 151 | + for (auto it : aConfigs) |
| 152 | + { |
| 153 | + CreateBasicComponent(aFactory, wrapperMap, it); |
| 154 | + |
| 155 | + std::shared_ptr<ISpeedControllerWrapper> speedController = GetSensorActuatorHelper::GetISpeedControllerWrapper(it.mHandle); |
| 156 | + if (!speedController) |
| 157 | + { |
| 158 | + SNOBOT_LOG(SnobotLogging::LOG_LEVEL_CRITICAL, "Invalid Speed Controller " << it.mHandle); |
| 159 | + continue; |
| 160 | + } |
| 161 | + |
| 162 | + DcMotorModelConfig::FactoryParams factoryParams( |
| 163 | + it.mMotorModelConfig.mFactoryParams.mMotorType, |
| 164 | + it.mMotorModelConfig.mFactoryParams.mNumMotors, |
| 165 | + it.mMotorModelConfig.mFactoryParams.mGearReduction, |
| 166 | + it.mMotorModelConfig.mFactoryParams.mGearboxEfficiency); |
| 167 | + |
| 168 | + DcMotorModelConfig motorModelConfig( |
| 169 | + factoryParams, |
| 170 | + it.mMotorModelConfig.mMotorParams.mNominalVoltage, |
| 171 | + it.mMotorModelConfig.mMotorParams.mFreeSpeedRpm, |
| 172 | + it.mMotorModelConfig.mMotorParams.mFreeCurrent, |
| 173 | + it.mMotorModelConfig.mMotorParams.mStallTorque, |
| 174 | + it.mMotorModelConfig.mMotorParams.mStallCurrent, |
| 175 | + it.mMotorModelConfig.mMotorParams.mMotorInertia, |
| 176 | + it.mMotorModelConfig.mFactoryParams.mHasBrake, |
| 177 | + it.mMotorModelConfig.mFactoryParams.mInverted); |
| 178 | + |
| 179 | + DcMotorModel motorModel(motorModelConfig); |
| 180 | + |
| 181 | + switch (it.mMotorSimConfigType) |
| 182 | + { |
| 183 | + case PwmConfig::Simple: |
| 184 | + { |
| 185 | + speedController->SetMotorSimulator(std::shared_ptr<IMotorSimulator>(new SimpleMotorSimulator( |
| 186 | + it.mMotorSimConfig.mSimple.mMaxSpeed))); |
| 187 | + break; |
| 188 | + } |
| 189 | + case PwmConfig::Static: |
| 190 | + { |
| 191 | + speedController->SetMotorSimulator(std::shared_ptr<IMotorSimulator>(new StaticLoadDcMotorSim( |
| 192 | + motorModel, |
| 193 | + it.mMotorSimConfig.mStatic.mLoad, |
| 194 | + it.mMotorSimConfig.mStatic.mConversionFactor))); |
| 195 | + break; |
| 196 | + } |
| 197 | + case PwmConfig::Gravity: |
| 198 | + { |
| 199 | + speedController->SetMotorSimulator(std::shared_ptr<IMotorSimulator>(new GravityLoadDcMotorSim( |
| 200 | + motorModel, |
| 201 | + it.mMotorSimConfig.mGravity.mLoad))); |
| 202 | + break; |
| 203 | + } |
| 204 | + case PwmConfig::Rotational: |
| 205 | + { |
| 206 | + speedController->SetMotorSimulator(std::shared_ptr<IMotorSimulator>(new RotationalLoadDcMotorSim( |
| 207 | + motorModel, |
| 208 | + speedController, |
| 209 | + it.mMotorSimConfig.mRotational.mArmCenterOfMass, |
| 210 | + it.mMotorSimConfig.mRotational.mArmMass, |
| 211 | + it.mMotorSimConfig.mRotational.mConstantAssistTorque, |
| 212 | + it.mMotorSimConfig.mRotational.mOverCenterAssistTorque))); |
| 213 | + break; |
| 214 | + } |
| 215 | + case PwmConfig::None: |
| 216 | + default: |
| 217 | + break; |
| 218 | + } |
| 219 | + } |
| 220 | +} |
| 221 | + |
| 222 | +void CreateEncoderComponents(std::shared_ptr<EncoderFactory> aFactory, const std::map<int, std::shared_ptr<IEncoderWrapper>>& wrapperMap, const std::vector<EncoderConfig>& aConfigs) |
| 223 | +{ |
| 224 | + for (auto it : aConfigs) |
| 225 | + { |
| 226 | + CreateBasicComponent(aFactory, wrapperMap, it); |
| 227 | + if (it.mHandle != -1 && it.mConnectedSpeedControllerHandle != -1) |
| 228 | + { |
| 229 | + std::shared_ptr<IEncoderWrapper> encoder = GetSensorActuatorHelper::GetIEncoderWrapper(it.mHandle); |
| 230 | + std::shared_ptr<ISpeedControllerWrapper> speedController = GetSensorActuatorHelper::GetISpeedControllerWrapper(it.mConnectedSpeedControllerHandle); |
| 231 | + if (encoder && speedController) |
| 232 | + { |
| 233 | + encoder->SetSpeedController(speedController); |
| 234 | + } |
| 235 | + else |
| 236 | + { |
| 237 | + SNOBOT_LOG(SnobotLogging::LOG_LEVEL_CRITICAL, "Necessary components not set (" << encoder << ", " << speedController << ")"); |
| 238 | + } |
| 239 | + } |
| 240 | + } |
| 241 | +} |
| 242 | + |
| 243 | +void SetupSimulator(const SimulatorConfigV1& aConfig) |
| 244 | +{ |
| 245 | + for (auto it : aConfig.mDefaultI2CWrappers) |
| 246 | + { |
| 247 | + FactoryContainer::Get().GetI2CWrapperFactory()->RegisterDefaultWrapperType(it.first, it.second); |
| 248 | + FactoryContainer::Get().GetI2CWrapperFactory()->GetI2CWrapper(it.first); |
| 249 | + } |
| 250 | + for (auto it : aConfig.mDefaultSpiWrappers) |
| 251 | + { |
| 252 | + FactoryContainer::Get().GetSpiWrapperFactory()->RegisterDefaultWrapperType(it.first, it.second); |
| 253 | + FactoryContainer::Get().GetSpiWrapperFactory()->GetSpiWrapper(it.first); |
| 254 | + } |
| 255 | + |
| 256 | + CreateBasicComponents(FactoryContainer::Get().GetAccelerometerFactory(), SensorActuatorRegistry::Get().GetIAccelerometerWrapperMap(), aConfig.mAccelerometers); |
| 257 | + CreateBasicComponents(FactoryContainer::Get().GetAnalogInFactory(), SensorActuatorRegistry::Get().GetIAnalogInWrapperMap(), aConfig.mAnalogIn); |
| 258 | + CreateBasicComponents(FactoryContainer::Get().GetAnalogOutFactory(), SensorActuatorRegistry::Get().GetIAnalogOutWrapperMap(), aConfig.mAnalogOut); |
| 259 | + CreateBasicComponents(FactoryContainer::Get().GetDigitalIoFactory(), SensorActuatorRegistry::Get().GetIDigitalIoWrapperMap(), aConfig.mDigitalIO); |
| 260 | + CreateBasicComponents(FactoryContainer::Get().GetGyroFactory(), SensorActuatorRegistry::Get().GetIGyroWrapperMap(), aConfig.mGyros); |
| 261 | + CreateBasicComponents(FactoryContainer::Get().GetRelayFactory(), SensorActuatorRegistry::Get().GetIRelayWrapperMap(), aConfig.mRelays); |
| 262 | + CreateBasicComponents(FactoryContainer::Get().GetSolenoidFactory(), SensorActuatorRegistry::Get().GetISolenoidWrapperMap(), aConfig.mSolenoids); |
| 263 | + |
| 264 | + CreatePwmComponents(FactoryContainer::Get().GetSpeedControllerFactory(), SensorActuatorRegistry::Get().GetISpeedControllerWrapperMap(), aConfig.mPwm); |
| 265 | + CreateEncoderComponents(FactoryContainer::Get().GetEncoderFactory(), SensorActuatorRegistry::Get().GetIEncoderWrapperMap(), aConfig.mEncoders); |
| 266 | +} |
| 267 | + |
| 268 | +bool SimulatorConfigReaderV1::LoadConfig(const std::string& aConfigFile) |
| 269 | +{ |
| 270 | + namespace fs = std::experimental::filesystem; |
| 271 | + fs::path configFile = aConfigFile; |
| 272 | + |
| 273 | + bool success = true; |
| 274 | + SNOBOT_LOG(SnobotLogging::LOG_LEVEL_INFO, "Loading config file '" << fs::canonical(configFile) << "'"); |
| 275 | + |
| 276 | + try |
| 277 | + { |
| 278 | + YAML::Node configNode = YAML::LoadFile(aConfigFile); |
| 279 | + |
| 280 | + SimulatorConfigV1 config; |
| 281 | + configNode >> config; |
| 282 | + |
| 283 | + SetupSimulator(config); |
| 284 | + } |
| 285 | + catch (std::exception& ex) |
| 286 | + { |
| 287 | + SNOBOT_LOG(SnobotLogging::LOG_LEVEL_CRITICAL, "Could not parse config file... " << ex.what()); |
| 288 | + success = false; |
| 289 | + } |
| 290 | + |
| 291 | + return success; |
| 292 | +} |
0 commit comments