3
# Copyright 2011 Shadow Robot Company Ltd.
5
# This program is free software: you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by the Free
7
# Software Foundation, either version 2 of the License, or (at your option)
10
# This program is distributed in the hope that it will be useful, but WITHOUT
11
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15
# You should have received a copy of the GNU General Public License along
16
# with this program. If not, see <http://www.gnu.org/licenses/>.
19
import roslib; roslib.load_manifest('sr_friction_compensation')
22
from etherCAT_hand_lib import EtherCAT_Hand_Lib
23
#from sensor_msgs import JointState
24
from std_msgs.msg import Float64
25
from pylab import plot, savefig
27
from scipy.optimize import leastsq
28
#from numpy import interp
34
class SrFrictionCompensation(object):
41
self.lib = EtherCAT_Hand_Lib()
43
self.joint_name = "FFJ3"
44
if rospy.has_param("~joint_name"):
45
self.joint_name = rospy.get_param("~joint_name")
48
if rospy.has_param("~min"):
49
self.min = rospy.get_param("~min")
52
if rospy.has_param("~max"):
53
self.max = rospy.get_param("~max")
55
self.nb_repetition = 2
56
if rospy.has_param("~nb_repetition"):
57
self.nb_repetition = rospy.get_param("~nb_repetition")
59
print " nb repetition: ", self.nb_repetition
62
if rospy.has_param("~sign"):
63
self.sign = rospy.get_param("~sign")
64
rospy.loginfo("sign: "+str(self.sign))
66
self.publisher = rospy.Publisher("/sr_friction_compensation/"+self.joint_name, Float64)
67
self.rate = rospy.Rate(100)
76
for i in range(0,self.nb_repetition):
79
self.record_map( -self.sign )
82
print "forces length: ", len(self.forces), " pos length: ", len(self.positions)
84
self.interpolate_map(1)
89
for i in range(0, self.nb_repetition):
90
self.move_to_start(False)
92
self.record_map( self.sign, False )
94
print "forces length: ", len(self.forces), " pos length: ", len(self.positions)
97
self.interpolate_map(2)
99
def move_to_start(self, start_at_min = True):
102
#try to get past the minimum
104
rospy.loginfo("Moving to the starting position ("+str(self.min)+")")
106
rospy.loginfo("Moving to the starting position ("+str(self.max)+")")
108
#250 should be big enough to move the finger to the end of its range
109
msg.data = self.sign * 250
110
while (self.lib.get_position(self.joint_name) > self.min) and not rospy.is_shutdown():
111
self.publisher.publish(msg)
114
#250 should be big enough to move the finger to the end of its range
115
msg.data = -self.sign * 250
117
while (self.lib.get_position(self.joint_name) < self.max) and not rospy.is_shutdown():
118
self.publisher.publish(msg)
122
for i in range(0,20):
123
self.publisher.publish(msg)
126
rospy.loginfo("Starting position reached")
128
def record_map(self, sign, increasing = True):
130
rospy.loginfo("Recording increasing map, until "+str(self.max))
132
rospy.loginfo("Recording decreasing map, until"+str(self.min))
136
while (self.lib.get_position(self.joint_name) < self.max) and not rospy.is_shutdown():
137
self.map_step(sign, msg)
139
while (self.lib.get_position(self.joint_name) > self.min) and not rospy.is_shutdown():
140
self.map_step(sign, msg, False)
142
def map_step(self, sign, msg, increasing=True):
143
#keep the tendon under tension
149
force, pos = self.find_smallest_force(self.lib.get_position(self.joint_name), sign, min_force)
151
self.forces.append(force)
152
self.positions.append(pos)
153
msg.data = sign*min_force
154
self.publisher.publish(msg)
155
rospy.Rate(2).sleep()
157
def find_smallest_force(self, first_position, sign, min_force):
160
for force in range(min_force, 400):
161
if rospy.is_shutdown():
164
if abs(self.lib.get_position(self.joint_name) - first_position) > epsilon:
165
#ok, the finger moved, return the necessary force
166
measured_force = self.lib.get_effort(self.joint_name)
167
print "finger moved from ",first_position, " with force ", measured_force
168
return measured_force, first_position
170
msg.data = sign*force
171
self.publisher.publish(msg)
176
def interpolate_map(self, index):
178
interp_pos = numpy.linspace(self.min, self.max, 10)
179
fp = lambda v, x: v[0]+ v[1]*x
181
v = self.linear_interp(-1, -1)
184
plot(interp_pos, fp(v, interp_pos), '-')
186
print "forces length: ", len(self.forces), " pos length: ", len(self.positions)
187
plot(self.positions, self.forces, 'o')
189
savefig("friction_compensation_"+self.joint_name+".png")
191
def linear_interp(self, min_index, max_index):
193
fp = lambda v, x: v[0]+ v[1]*x
194
e = lambda v, x, y: (fp(v,x)-y)
199
if min_index == -1 and max_index == -1:
200
v, success = leastsq(e, v0, args=(self.positions,self.forces), maxfev=10000)
202
v, success = leastsq(e, v0, args=(self.positions[min_index:max_index],self.forces[min_index:max_index]), maxfev=10000)
206
if __name__ == '__main__':
207
rospy.init_node('sr_friction_compensation', anonymous=True)
209
sr_fric = SrFrictionCompensation()