def com_line(alpha, a, par, part, l1, l2): '''Returns the slope and intercept for the line that passes through the part's center of mass with reference to the benchmark bicycle coordinate system. Parameters ---------- alpha : float The angle the head tube makes with the horizontal. When looking at the bicycle from the right side this is the angle between a vector point out upwards along the steer axis and the earth horizontal with the positve direction pointing from the left to the right. If the bike is in its normal configuration this would be 90 degrees plus the steer axis tilt (lambda). a : float The distance from the pendulum axis to a reference point on the part, typically the wheel centers. This is positive if the point falls to the left of the axis and negative otherwise. par : dictionary Benchmark parameters. Must include lam, rR, rF, w part : string The subscript denoting which part this refers to. l1, l2 : floats The location of the handlebar reference point relative to the front wheel center when the fork is split. This is measured perpendicular to and along the steer axis, respectively. Returns ------- m : float The slope of the line in the benchmark coordinate system. b : float The z intercept in the benchmark coordinate system. ''' # beta is the angle between the x bike frame and the x pendulum frame, rotation # about positive y beta = par['lam'] - alpha * pi / 180 # calculate the slope of the center of mass line m = -umath.tan(beta) # calculate the z intercept # this the bicycle frame if part == 'B': b = -a / umath.cos(beta) - par['rR'] # this is the fork (without handlebar) or the fork and handlebar combined elif part == 'S' or part == 'H': b = -a / umath.cos(beta) - par['rF'] + par['w'] * umath.tan(beta) # this is the handlebar (without fork) elif part == 'G': u1, u2 = fwheel_to_handlebar_ref(par['lam'], l1, l2) b = -a / umath.cos(beta) - (par['rF'] + u2) + (par['w'] - u1) * umath.tan(beta) else: print part, "doesn't exist" raise KeyError return m, b, beta
def calculate_benchmark_from_measured(mp): '''Returns the benchmark (Meijaard 2007) parameter set based on the measured data. Parameters ---------- mp : dictionary Complete set of measured data. Returns ------- par : dictionary Benchmark bicycle parameter set. ''' forkIsSplit = is_fork_split(mp) par = {} # calculate the wheelbase, steer axis tilt and trail par = geometry.calculate_benchmark_geometry(mp, par) # masses par['mB'] = mp['mB'] par['mF'] = mp['mF'] par['mR'] = mp['mR'] try: # we measured the mass of the flywheel plus the mass of the front # wheel, mp['mD'], so to get the actual mass of the flywheel, subtract # the mass of the front wheel par['mD'] = mp['mD'] - mp['mF'] except KeyError: pass if forkIsSplit: par['mS'] = mp['mS'] par['mG'] = mp['mG'] else: par['mH'] = mp['mH'] # get the slopes, intercepts and betas for each part slopes, intercepts, betas = com.part_com_lines(mp, par, forkIsSplit) # calculate the centers of mass for part in slopes.keys(): par['x' + part], par['z' + part] = com.center_of_mass( slopes[part], intercepts[part]) # find the center of mass of the handlebar/fork assembly if the fork was # split if forkIsSplit: coordinates = np.array([[par['xS'], par['xG']], [0., 0.], [par['zS'], par['zG']]]) masses = np.array([par['mS'], par['mG']]) mH, cH = inertia.total_com(coordinates, masses) par['mH'] = mH par['xH'] = cH[0] par['zH'] = cH[2] # local accelation due to gravity par['g'] = mp['g'] # calculate the wheel y inertias par['IFyy'] = inertia.compound_pendulum_inertia(mp['mF'], mp['g'], mp['lF'], mp['TcF1']) par['IRyy'] = inertia.compound_pendulum_inertia(mp['mR'], mp['g'], mp['lR'], mp['TcR1']) try: # we measured the inertia of the front wheel with the flywheel inside iFlywheelPlusFwheel = inertia.compound_pendulum_inertia( mp['mD'], mp['g'], mp['lF'], mp['TcD1']) par['IDyy'] = iFlywheelPlusFwheel - par['IFyy'] except KeyError: pass # calculate the y inertias for the frame and fork lB = (par['xB']**2 + (par['zB'] + par['rR'])**2)**(0.5) par['IByy'] = inertia.compound_pendulum_inertia(mp['mB'], mp['g'], lB, mp['TcB1']) if forkIsSplit: # fork lS = ((par['xS'] - par['w'])**2 + (par['zS'] + par['rF'])**2)**(0.5) par['ISyy'] = inertia.compound_pendulum_inertia( mp['mS'], mp['g'], lS, mp['TcS1']) # handlebar l1, l2 = geometry.calculate_l1_l2(mp['h6'], mp['h7'], mp['d5'], mp['d6'], mp['l']) u1, u2 = geometry.fwheel_to_handlebar_ref(par['lam'], l1, l2) lG = ((par['xG'] - par['w'] + u1)**2 + (par['zG'] + par['rF'] + u2)**2)**(.5) par['IGyy'] = inertia.compound_pendulum_inertia( mp['mG'], mp['g'], lG, mp['TcG1']) else: lH = ((par['xH'] - par['w'])**2 + (par['zH'] + par['rF'])**2)**(0.5) par['IHyy'] = inertia.compound_pendulum_inertia( mp['mH'], mp['g'], lH, mp['TcH1']) # calculate the stiffness of the torsional pendulum IPxx, IPyy, IPzz = inertia.tube_inertia(mp['lP'], mp['mP'], mp['dP'] / 2., 0.) torStiff = inertia.torsional_pendulum_stiffness(IPyy, mp['TtP1']) #print "Torsional pendulum stiffness:", torStiff # calculate the wheel x/z inertias par['IFxx'] = inertia.tor_inertia(torStiff, mp['TtF1']) par['IRxx'] = inertia.tor_inertia(torStiff, mp['TtR1']) try: par['IDxx'] = inertia.tor_inertia(torStiff, mp['TtD1']) - par['IFxx'] except KeyError: pass pendulumInertias = {} # calculate the in plane moments of inertia for part, slopeSet in slopes.items(): # the number of orientations for this part numOrien = len(slopeSet) # intialize arrays to store the inertia values and orientation angles penInertia = np.zeros(numOrien, dtype=object) beta = np.array(betas[part]) # fill arrays of the inertias for i in range(numOrien): penInertia[i] = inertia.tor_inertia(torStiff, mp['Tt' + part + str(i + 1)]) # store these inertias pendulumInertias[part] = list(penInertia) inert = inertia.inertia_components(penInertia, beta) for i, axis in enumerate(['xx', 'xz', 'zz']): par['I' + part + axis] = inert[i] if forkIsSplit: # combine the moments of inertia to find the total handlebar/fork MoI IG = inertia.part_inertia_tensor(par, 'G') IS = inertia.part_inertia_tensor(par, 'S') # columns are parts, rows = x, y, z coordinates = np.array([[par['xG'], par['xS']], [0., 0.], [par['zG'], par['zS']]]) masses = np.array([par['mG'], par['mS']]) par['mH'], cH = com.total_com(coordinates, masses) par['xH'] = cH[0] par['zH'] = cH[2] dG = np.array([par['xG'] - par['xH'], 0., par['zG'] - par['zH']]) dS = np.array([par['xS'] - par['xH'], 0., par['zS'] - par['zH']]) IH = (inertia.parallel_axis(IG, par['mG'], dG) + inertia.parallel_axis(IS, par['mS'], dS)) par['IHxx'] = IH[0, 0] par['IHxz'] = IH[0, 2] par['IHyy'] = IH[1, 1] par['IHzz'] = IH[2, 2] # package the extra information that is useful outside this function extras = { 'slopes': slopes, 'intercepts': intercepts, 'betas': betas, 'pendulumInertias': pendulumInertias } return par, extras
def calculate_benchmark_from_measured(mp): '''Returns the benchmark (Meijaard 2007) parameter set based on the measured data. Parameters ---------- mp : dictionary Complete set of measured data. Returns ------- par : dictionary Benchmark bicycle parameter set. ''' forkIsSplit = is_fork_split(mp) par = {} # calculate the wheelbase, steer axis tilt and trail par = geometry.calculate_benchmark_geometry(mp, par) # masses par['mB'] = mp['mB'] par['mF'] = mp['mF'] par['mR'] = mp['mR'] try: # we measured the mass of the flywheel plus the mass of the front # wheel, mp['mD'], so to get the actual mass of the flywheel, subtract # the mass of the front wheel par['mD'] = mp['mD'] - mp['mF'] except KeyError: pass if forkIsSplit: par['mS'] = mp['mS'] par['mG'] = mp['mG'] else: par['mH'] = mp['mH'] # get the slopes, intercepts and betas for each part slopes, intercepts, betas = com.part_com_lines(mp, par, forkIsSplit) # calculate the centers of mass for part in slopes.keys(): par['x' + part], par['z' + part] = com.center_of_mass(slopes[part], intercepts[part]) # find the center of mass of the handlebar/fork assembly if the fork was # split if forkIsSplit: coordinates = np.array([[par['xS'], par['xG']], [0., 0.], [par['zS'], par['zG']]]) masses = np.array([par['mS'], par['mG']]) mH, cH = inertia.total_com(coordinates, masses) par['mH'] = mH par['xH'] = cH[0] par['zH'] = cH[2] # local accelation due to gravity par['g'] = mp['g'] # calculate the wheel y inertias par['IFyy'] = inertia.compound_pendulum_inertia(mp['mF'], mp['g'], mp['lF'], mp['TcF1']) par['IRyy'] = inertia.compound_pendulum_inertia(mp['mR'], mp['g'], mp['lR'], mp['TcR1']) try: # we measured the inertia of the front wheel with the flywheel inside iFlywheelPlusFwheel = inertia.compound_pendulum_inertia(mp['mD'], mp['g'], mp['lF'], mp['TcD1']) par['IDyy'] = iFlywheelPlusFwheel - par['IFyy'] except KeyError: pass # calculate the y inertias for the frame and fork lB = (par['xB']**2 + (par['zB'] + par['rR'])**2)**(0.5) par['IByy'] = inertia.compound_pendulum_inertia(mp['mB'], mp['g'], lB, mp['TcB1']) if forkIsSplit: # fork lS = ((par['xS'] - par['w'])**2 + (par['zS'] + par['rF'])**2)**(0.5) par['ISyy'] = inertia.compound_pendulum_inertia(mp['mS'], mp['g'], lS, mp['TcS1']) # handlebar l1, l2 = geometry.calculate_l1_l2(mp['h6'], mp['h7'], mp['d5'], mp['d6'], mp['l']) u1, u2 = geometry.fwheel_to_handlebar_ref(par['lam'], l1, l2) lG = ((par['xG'] - par['w'] + u1)**2 + (par['zG'] + par['rF'] + u2)**2)**(.5) par['IGyy'] = inertia.compound_pendulum_inertia(mp['mG'], mp['g'], lG, mp['TcG1']) else: lH = ((par['xH'] - par['w'])**2 + (par['zH'] + par['rF'])**2)**(0.5) par['IHyy'] = inertia.compound_pendulum_inertia(mp['mH'], mp['g'], lH, mp['TcH1']) # calculate the stiffness of the torsional pendulum IPxx, IPyy, IPzz = inertia.tube_inertia(mp['lP'], mp['mP'], mp['dP'] / 2., 0.) torStiff = inertia.torsional_pendulum_stiffness(IPyy, mp['TtP1']) #print "Torsional pendulum stiffness:", torStiff # calculate the wheel x/z inertias par['IFxx'] = inertia.tor_inertia(torStiff, mp['TtF1']) par['IRxx'] = inertia.tor_inertia(torStiff, mp['TtR1']) try: par['IDxx'] = inertia.tor_inertia(torStiff, mp['TtD1']) - par['IFxx'] except KeyError: pass pendulumInertias = {} # calculate the in plane moments of inertia for part, slopeSet in slopes.items(): # the number of orientations for this part numOrien = len(slopeSet) # intialize arrays to store the inertia values and orientation angles penInertia = np.zeros(numOrien, dtype=object) beta = np.array(betas[part]) # fill arrays of the inertias for i in range(numOrien): penInertia[i] = inertia.tor_inertia(torStiff, mp['Tt' + part + str(i + 1)]) # store these inertias pendulumInertias[part] = list(penInertia) inert = inertia.inertia_components(penInertia, beta) for i, axis in enumerate(['xx', 'xz', 'zz']): par['I' + part + axis] = inert[i] if forkIsSplit: # combine the moments of inertia to find the total handlebar/fork MoI IG = inertia.part_inertia_tensor(par, 'G') IS = inertia.part_inertia_tensor(par, 'S') # columns are parts, rows = x, y, z coordinates = np.array([[par['xG'], par['xS']], [0., 0.], [par['zG'], par['zS']]]) masses = np.array([par['mG'], par['mS']]) par['mH'], cH = com.total_com(coordinates, masses) par['xH'] = cH[0] par['zH'] = cH[2] dG = np.array([par['xG'] - par['xH'], 0., par['zG'] - par['zH']]) dS = np.array([par['xS'] - par['xH'], 0., par['zS'] - par['zH']]) IH = (inertia.parallel_axis(IG, par['mG'], dG) + inertia.parallel_axis(IS, par['mS'], dS)) par['IHxx'] = IH[0, 0] par['IHxz'] = IH[0, 2] par['IHyy'] = IH[1, 1] par['IHzz'] = IH[2, 2] # package the extra information that is useful outside this function extras = {'slopes' : slopes, 'intercepts' : intercepts, 'betas' : betas, 'pendulumInertias' : pendulumInertias} return par, extras