SUMOReal MSDevice_Battery::getPropEnergy(SUMOVehicle& veh) { // calculate current kinetic energy SUMOReal height_cur = veh.getPositionOnLane() / veh.getLane()->getLength() * (veh.getLane()->getShape().back().z() - veh.getLane()->getShape().front().z()); // kinetic energy of vehicle with current velocity SUMOReal currentEnergy = 0.5 * getMass() * veh.getSpeed() * veh.getSpeed(); // add current potential energy of vehicle at current position currentEnergy += getMass() * 9.81 * height_cur; // Calculate the radius of the vehicle's current path if is distintc (r = ds / dphi) SUMOReal radius = 0; // If angle of vehicle was changed if (getLastAngle() != veh.getAngle()) { // Compute new radio radius = SPEED2DIST(veh.getSpeed()) / fabs(GeomHelper::angleDiff(getLastAngle(), veh.getAngle())); // Check if radius is in the interval [0.0001 - 10000] (To avoid overflow and division by zero) if (radius < 0.0001) { radius = 0.0001; } else if (radius > 10000) { radius = 10000; } } // add current rotational energy of internal rotating elements currentEnergy += getInternalMomentOfInertia() * veh.getSpeed() * veh.getSpeed(); // kinetic + potential + rotational energy gain [Ws] (MODIFICATED LAST ANGLE) SUMOReal EnergyLoss = (currentEnergy - getLastEnergy()); // save current total energy for next time step setLastEnergy(currentEnergy); // Calculate energy losses: // EnergyLoss,Air = 1/2 * rho_air [kg/m^3] * FrontSurfaceArea [m^2] * AirDragCoefficient [-] * v_Veh^2 [m/s] * s [m] // ... with rho_air [kg/m^3] = 1,2041 kg/m^3 (at T = 20°C) // ... with s [m] = v_Veh [m/s] * 1 [s] EnergyLoss += 0.5 * 1.2041 * getFrontSurfaceArea() * getAirDragCoefficient() * fabs(veh.getSpeed() * veh.getSpeed() * veh.getSpeed()); // Energy loss through Air resistance [Ws] // EnergyLoss,Tire = c_R [-] * F_N [N] * s [m] // ... with c_R = ~0.012 (car tire on asphalt) // ... with F_N [N] = Mass [kg] * g [m/s^2] EnergyLoss += getRollDragCoefficient() * 9.81 * getMass() * fabs(veh.getSpeed()); // Energy loss through Roll resistance [Ws] // ... (fabs(veh.getSpeed())>=0.01) = 0, if vehicle isn't moving // EnergyLoss,internalFrictionRadialForce = c [m] * F_rad [N]; if (getLastAngle() != veh.getAngle()) { // Energy loss through friction by radial force [Ws] EnergyLoss += getRadialDragCoefficient() * getMass() * veh.getSpeed() * veh.getSpeed() / radius; } // EnergyLoss,constantConsumers // Energy loss through constant loads (e.g. A/C) [Ws] EnergyLoss += getConstantPowerIntake(); //E_Bat = E_kin_pot + EnergyLoss; if (EnergyLoss > 0) { // Assumption: Efficiency of PropulsionEfficiency when accelerating EnergyLoss = EnergyLoss / getPropulsionEfficiency(); } else { // Assumption: Efficiency of RecuperationEfficiency when recuperating EnergyLoss = EnergyLoss * getRecuperationEfficiency(); } // convert from [Ws] to [kWh] (3600s / 1h): EnergyLoss = EnergyLoss / 3600 ; // EnergyLoss[Ws] * 1[h]/3600[s] * 1[k]/1000 // Return calculated energy return(EnergyLoss); }
bool MSDevice_Battery::notifyMove(SUMOVehicle& veh, SUMOReal /* oldPos */, SUMOReal /* newPos */, SUMOReal /* newSpeed */) { // Start vehicleStoppedTimer if the vehicle is stopped (that's mean, speed is < 0.2). In other case reset timer if (veh.getSpeed() < 0.2) { // Increase vehicle stopped timer increaseVehicleStoppedTimer(); } else { // Reset vehicle Stopped resetVehicleStoppedTimer(); } // Update Energy from the battery if (getMaximumBatteryCapacity() != 0) { Consum = getPropEnergy(veh); // Energy lost/gained from vehicle movement (via vehicle energy model) [kWh] setActualBatteryCapacity(getActualBatteryCapacity() - Consum); // saturate between 0 and MaxBatKap [kWh] if (getActualBatteryCapacity() < 0) { setActualBatteryCapacity(0); if (getMaximumBatteryCapacity() > 0) { WRITE_WARNING("Battery of vehicle '" + veh.getID() + "' is depleted."); } } else if (getActualBatteryCapacity() > getMaximumBatteryCapacity()) { setActualBatteryCapacity(getMaximumBatteryCapacity()); } setLastAngle(veh.getAngle()); } // Check if vehicle has under their position one charge Station std::string ChargingStationID = MSNet::getInstance()->getChargingStationID(veh.getLane(), veh.getPositionOnLane()); // If vehicle is over a charging station if (ChargingStationID != "") { // Declare a pointer to the charging station MSChargingStation* ChargingStationPointer = MSNet::getInstance()->getChargingStation(ChargingStationID); // if the vehicle is almost stopped, or charge in transit is enabled, then charge vehicle if ((veh.getSpeed() < 0.2) || (ChargingStationPointer->getChargeInTransit() == 1)) { // Set Flags Stopped/intransit to if (veh.getSpeed() < 0.2) { // vehicle ist almost stopped, then is charging stopped ItsChargingStopped = true; // therefore isn't charging in transit ItsChargingInTransit = false; } else { // vehicle is moving, and the Charging station allow charge in transit ItsChargingStopped = false; // Therefore charge in transit ItsChargingInTransit = true; } // Set actChargingStation parameter actChargingStation = ChargingStationID; // Only update charging start time if vehicle allow charge in transit, or in other case // if the vehicle not allow charge in transit but it's stopped. if (ChargingStationPointer->getChargeInTransit() == 1 || veh.getSpeed() < 0.2) { // Update Charging start time increaseChargingStartTime(); } // time it takes the vehicle at the station < charging station time delay? if (getChargingStartTime() > ChargingStationPointer->getChargeDelay()) { // Calulate energy charged (Fix); energyCharged = ChargingStationPointer->getChrgPower() * ChargingStationPointer->getEfficency(); // Convert from [kWs] to [kWh] (3600s / 1h): energyCharged /= 3600; // Update Battery charge if ((energyCharged + getActualBatteryCapacity()) > getMaximumBatteryCapacity()) { setActualBatteryCapacity(getMaximumBatteryCapacity()); } else { setActualBatteryCapacity(getActualBatteryCapacity() + energyCharged); } } } } // In other case, vehicle will be not charged else { // Disable flags ItsChargingInTransit = false; ItsChargingStopped = false; // Disable charging station actChargingStation = "NULL"; // Set energy charged to 0 energyCharged = 0.00; // Reset timer resetChargingStartTime(); } // Always return true. return true; }