Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 import numpy as np
00019 import rospy
00020 from cob_msgs.msg import PowerState
00021 from cob_phidgets.msg import AnalogSensor
00022
00023
00024 class PowerStatePhidget():
00025 PHIDGET_MAX_VALUE = 999
00026 PHIDGET_MIN_VALUE = 0
00027 PERIOD_RECORD_SIZE = 6
00028 VOLTAGE_COLLECTION_TIME = 6.0
00029
00030 def __init__(self):
00031 self.voltage = None
00032 self.current = None
00033 self.last_update = rospy.Time(0)
00034 self.charging = False
00035 try:
00036 self.voltage_divider_factor = rospy.get_param("~voltage_divider_factor")
00037 except KeyError:
00038 raise KeyError("Parameter \"~voltage_divider_factor\" not found on parameter server.")
00039 self.voltage_full = rospy.get_param("~voltage_full", 52.0)
00040 self.voltage_empty = rospy.get_param("~voltage_empty", 38.0)
00041 self.current_max = rospy.get_param("~current_max", 30.0)
00042 self.current_min = rospy.get_param("~current_min", -30.0)
00043
00044 self.pub_power_state = rospy.Publisher('power_state', PowerState, queue_size=1)
00045 self.sub_analog_sensors = rospy.Subscriber("analog_sensors", AnalogSensor, self.phidget_cb)
00046
00047 self.pr_next = 0
00048 self.period_record = []
00049 self.cb_avg_time = 0.1
00050 self.voltage_bag_maxlen = 100
00051 self.voltage_bag = []
00052
00053 def append_voltage_bag(self, num):
00054 while len(self.voltage_bag) >= self.voltage_bag_maxlen:
00055 self.voltage_bag.pop(0)
00056 self.voltage_bag.append(num)
00057
00058 def calculate_voltage(self):
00059 if len(self.voltage_bag) > 0:
00060 self.voltage = np.mean(self.voltage_bag)
00061
00062 def phidget_cb(self, msg):
00063
00064
00065 if len(self.period_record) < self.PERIOD_RECORD_SIZE:
00066 self.period_record.append((rospy.Time.now() - self.last_update).to_sec())
00067 else:
00068 self.period_record[self.pr_next] = (rospy.Time.now() - self.last_update).to_sec()
00069
00070 self.pr_next += 1
00071 self.pr_next %= len(self.period_record)
00072 self.last_update = rospy.Time.now()
00073
00074 if len(self.period_record) <= self.PERIOD_RECORD_SIZE / 2:
00075
00076 self.cb_avg_time = 0.1
00077 else:
00078
00079 self.cb_avg_time = np.median(self.period_record)
00080
00081
00082 self.voltage_bag_maxlen = int(self.VOLTAGE_COLLECTION_TIME / self.cb_avg_time)
00083
00084 voltage_raw = None
00085 current_raw = None
00086
00087 for i in range(0, len(msg.uri)):
00088 if msg.uri[i] == "voltage":
00089 voltage_raw = msg.value[i]
00090 if msg.uri[i] == "current":
00091 current_raw = msg.value[i]
00092
00093 if voltage_raw != None:
00094
00095 voltage = self.voltage_divider_factor * voltage_raw / self.PHIDGET_MAX_VALUE
00096 voltage = round(voltage, 3)
00097 self.append_voltage_bag(voltage)
00098
00099 if current_raw != None:
00100
00101 self.current = self.current_min + (self.current_max - self.current_min) * (current_raw -
00102 self.PHIDGET_MIN_VALUE) / (self.PHIDGET_MAX_VALUE - self.PHIDGET_MIN_VALUE)
00103 self.current = round(self.current, 3)
00104
00105 if self.current > 0:
00106 self.charging = True
00107 else:
00108 self.charging = False
00109
00110 def calculate_power_consumption(self):
00111 if not self.charging and self.voltage != None and self.current != None:
00112 return round(self.voltage * abs(self.current), 3)
00113 else:
00114 return 0.0
00115
00116 def calculate_relative_remaining_capacity(self):
00117 percentage = None
00118 if self.voltage != None:
00119 percentage = round((self.voltage - self.voltage_empty) * 100 / (self.voltage_full - self.voltage_empty), 3)
00120 percentage = min(percentage, 100)
00121 percentage = max(percentage, 0)
00122 return percentage
00123 else:
00124 return 0.0
00125
00126 def publish(self):
00127 self.calculate_voltage()
00128 if self.voltage != None and self.current != None and (rospy.Time.now() - self.last_update) < rospy.Duration(1):
00129 ps = PowerState()
00130 ps.header.stamp = self.last_update
00131 ps.voltage = self.voltage
00132 ps.current = self.current
00133 ps.power_consumption = self.calculate_power_consumption()
00134 ps.relative_remaining_capacity = self.calculate_relative_remaining_capacity()
00135 ps.charging = self.charging
00136 self.pub_power_state.publish(ps)
00137
00138 if __name__ == "__main__":
00139 rospy.init_node("power_state_phidget")
00140 try:
00141 psp = PowerStatePhidget()
00142 except KeyError as e:
00143 rospy.logerr("Shutting down: {}".format(e.message))
00144 exit(1)
00145
00146 rospy.loginfo("power state phidget running")
00147 rate = rospy.Rate(10)
00148 while not rospy.is_shutdown():
00149 psp.publish()
00150 rate.sleep()