could not convert string to float 9DOF Razor IMU - python
I am receiving the "could not convert string to float" error in this code. Could anyone take a look to see what is wrong please? I am working with the 9DOF Razor IMU connected to the PC using an FTDI, both from sparkfun. I am trying to see the axis x,y and z and the yaw, pitch and roll bars moving while I rotate my Razor, but I am receiving this error. It's the first project I'm working on, so everything I am doing is based on tutorials and blogs. English is not my motherlanguage, so sorry 'bout any english mistakes i've made. Thank you.
# This script needs VPhyton, pyserial and pywin modules
from visual import *
import serial
import string
import math
from time import time
grad2rad = 3.141592/180.0
# Check your COM port and baud rate
ser = serial.Serial(port='COM13',baudrate=57600, timeout=1)
# Main scene
scene=display(title="9DOF Razor IMU test")
scene.range=(1.2,1.2,1.2)
#scene.forward = (0,-1,-0.25)
scene.forward = (1,0,-0.25)
scene.up=(0,0,1)
# Second scene (Roll, Pitch, Yaw)
scene2 = display(title='9DOF Razor IMU test',x=0, y=0, width=500, height=200,center=(0,0,0), background=(0,0,0))
scene2.range=(1,1,1)
scene.width=500
scene.y=200
scene2.select()
#Roll, Pitch, Yaw
cil_roll = cylinder(pos=(-0.4,0,0),axis=(0.2,0,0),radius=0.01,color=color.red)
cil_roll2 = cylinder(pos=(-0.4,0,0),axis=(-0.2,0,0),radius=0.01,color=color.red)
cil_pitch = cylinder(pos=(0.1,0,0),axis=(0.2,0,0),radius=0.01,color=color.green)
cil_pitch2 = cylinder(pos=(0.1,0,0),axis=(-0.2,0,0),radius=0.01,color=color.green)
#cil_course = cylinder(pos=(0.6,0,0),axis=(0.2,0,0),radius=0.01,color=color.blue)
#cil_course2 = cylinder(pos=(0.6,0,0),axis=(-0.2,0,0),radius=0.01,color=color.blue)
arrow_course = arrow(pos=(0.6,0,0),color=color.cyan,axis=(-0.2,0,0), shaftwidth=0.02, fixedwidth=1)
#Roll,Pitch,Yaw labels
label(pos=(-0.4,0.3,0),text="Roll",box=0,opacity=0)
label(pos=(0.1,0.3,0),text="Pitch",box=0,opacity=0)
label(pos=(0.55,0.3,0),text="Yaw",box=0,opacity=0)
label(pos=(0.6,0.22,0),text="N",box=0,opacity=0,color=color.yellow)
label(pos=(0.6,-0.22,0),text="S",box=0,opacity=0,color=color.yellow)
label(pos=(0.38,0,0),text="W",box=0,opacity=0,color=color.yellow)
label(pos=(0.82,0,0),text="E",box=0,opacity=0,color=color.yellow)
label(pos=(0.75,0.15,0),height=7,text="NE",box=0,color=color.yellow)
label(pos=(0.45,0.15,0),height=7,text="NW",box=0,color=color.yellow)
label(pos=(0.75,-0.15,0),height=7,text="SE",box=0,color=color.yellow)
label(pos=(0.45,-0.15,0),height=7,text="SW",box=0,color=color.yellow)
L1 = label(pos=(-0.4,0.22,0),text="-",box=0,opacity=0)
L2 = label(pos=(0.1,0.22,0),text="-",box=0,opacity=0)
L3 = label(pos=(0.7,0.3,0),text="-",box=0,opacity=0)
# Main scene objects
scene.select()
# Reference axis (x,y,z)
arrow(color=color.green,axis=(1,0,0), shaftwidth=0.02, fixedwidth=1)
arrow(color=color.green,axis=(0,-1,0), shaftwidth=0.02 , fixedwidth=1)
arrow(color=color.green,axis=(0,0,-1), shaftwidth=0.02, fixedwidth=1)
# labels
label(pos=(0,0,0.8),text="9DOF Razor IMU test",box=0,opacity=0)
label(pos=(1,0,0),text="X",box=0,opacity=0)
label(pos=(0,-1,0),text="Y",box=0,opacity=0)
label(pos=(0,0,-1),text="Z",box=0,opacity=0)
# IMU object
platform = box(length=1, height=0.05, width=1, color=color.red)
p_line = box(length=1,height=0.08,width=0.1,color=color.yellow)
plat_arrow = arrow(color=color.green,axis=(1,0,0), shaftwidth=0.06, fixedwidth=1)
f = open("Serial"+str(time())+".txt", 'w')
roll=0
pitch=0
yaw=0
while 1:
line = ser.readline()
line = line.replace("!ANG:","") # Delete "!ANG:"
print line
f.write(line) # Write to the output log file
words = string.split(line,",") # Fields split
if len(words) > 2:
try:
roll = float(words[0])*grad2rad
pitch = float(words[1])*grad2rad
yaw = float(words[2])*grad2rad
except:
print "Invalid line"
axis=(cos(pitch)*cos(yaw),-cos(pitch)*sin(yaw),sin(pitch))
up=(sin(roll)*sin(yaw)+cos(roll)*sin(pitch)*cos(yaw),sin(roll)*cos(yaw)- cos(roll)*sin(pitch)*sin(yaw),-cos(roll)*cos(pitch))
platform.axis=axis
platform.up=up
platform.length=1.0
platform.width=0.65
plat_arrow.axis=axis
plat_arrow.up=up
plat_arrow.length=0.8
p_line.axis=axis
p_line.up=up
cil_roll.axis=(0.2*cos(roll),0.2*sin(roll),0)
cil_roll2.axis=(-0.2*cos(roll),-0.2*sin(roll),0)
cil_pitch.axis=(0.2*cos(pitch),0.2*sin(pitch),0)
cil_pitch2.axis=(-0.2*cos(pitch),-0.2*sin(pitch),0)
arrow_course.axis=(0.2*sin(yaw),0.2*cos(yaw),0)
L1.text = str(float(words[0]))
L2.text = str(float(words[1]))
L3.text = str(float(words[2]))
ser.close
f.close
You must be using some old tutorials if the are suggesting stuff like string.split(line,",")
From your source, it seems the problem is here:
L1.text = str(float(words[0]))
L2.text = str(float(words[1]))
L3.text = str(float(words[2]))
You are trying to convert something to a float, that Python can't convert to a number. From the looks of it, these are text labels, so why not try:
L1.text = words[0]
L2.text = words[1]
L3.text = words[2]
Some more tips:
words = line.split(',') # instead of: words = string.split(line,",")
ser.close() # close is a function, so you should call it.
f.close()
make the following changes to the code:
replace the line
line = line.replace("!ANG:","")
with
line = line.replace("#YPR=","")
replace the split line as told earlier and that should just do the trick!
Related
Tkinter GUI to be able to change variables of an separate continuous process
I have designed an marine engine simulator - it's a program that sends some serial DATA using a certain protocol called "BlueVision". The data is encoded based on a header, a block number, a block type, actual data (indexed), a checksum and a footer. Due to the fact that if you want to change a value in the actual data - then the checksum changes - I designed an recalculation of the block with the correct checksum when the data is changed. I made a GUI that allows me to change the value of 2 data points in order to be able to test live. The problem is that I don't know how to use threads or subprocesses correctly and the window keeps on freezing. The application works - but works badly and I kept on searching for a similar issue - and did find some suggestions but I haven't been able to implement it. Can someone help? PS: the code is awkward at best - please don't judge - I know I could of made it way better - but this is the best I could do with the time I had. The issue might not be clear to you if you don't have a COM port where the program writes to. # Blue Vision is a MTU serial communication protocol - based on HEX values grouped in BLOCKS import tkinter as tk from tkinter import ttk import time import serial def split_by_n(seq, n): while seq: yield seq[:n] seq= seq[n:] def after(self, ms, func=None, *args): """Call function once after given time. MS specifies the time in milliseconds. FUNC gives the function which shall be called. Additional parameters are given as parameters to the function call. Return identifier to cancel scheduling with after_cancel.""" win = tk.Tk() win.title("GUI - TEST VERSION") win.geometry("750x250") label = tk.Label(win, text = "Main Engine Overspeed") label.pack() v = tk.StringVar() v.set('00') c = tk.StringVar() c.set("00") def setText(word): v.set(word) a = ttk.Button(win, text ="01", command =lambda:setText("01")) a.pack() b = ttk.Button(win, text="00", command = lambda:setText("00")) b.pack() label1 = tk.Label(win, text ="Main Engine Speed") label1.pack() name_entry = tk.Entry(win, textvariable=c) name_entry.pack() def task(): MyVar = v.get() priEngSp =c.get() if len(priEngSp) == 0: priEngSp = '00' block_3 = 'FAF500030002000000290100000001000100000001000001000000000000000000000000000222AF5F' block_4 = 'FAF500040003000001A000004650000047E00000000000000000000000000007EF4000083D6000000000000000000000000000000000000000000000012C000006D600000000000000000000278D00000000000000007FFFFFFF000000000001991500000000000000000016E36000000000000923D8000971F8000001F40000059F000026AC00002774000005800000251C00000580000027740000283C0000056200001D4C00001F400000061800000000000060FB00004650000036B000007D0000008CA0000006180000251C0000000000000000000000000000284800192D500017A6B00000051B0000251CFFFFFFA8000002580000044C000000FA0000000000000000000006770000CB200000D6D8000006770000CB200000D6D80000060600005DC000000000000027100000000000000000000000000000000000000000000003C2000061A8000000000000000000000000000000000000000000000000000000000000000000000000000000000000363300000EA6000249F0FFFFFB1E000F42400000000000000000000000000000000000000000000032D9AF5F' block_5 = 'FAF5000500020000005600000000000000000000000000000000000000000000007F7F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034AAF5F' block_6 = 'FAF5000600020000003D00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000234AF5F' block_7 = 'FAF5000700030000008C000006280000064A0000064A0000068D0000066B0000068D0000068D000006AE0000000000000000000006AE000006070000060700000607000005E5000005A2000006070000064A00000000000000000000062A000006AE000005A20000350EFFFFF07C00003CDEFFFFE8AC00000000000000000000000000000000000012DEAF5F' block_8 = 'FAF50008000300000070000000000000112900000000000000000000059C000027740000283C000047E000000000000000000000000000000000000000000000000000000000000000007FFFFFFF7FFFFFFF0000055100002CEC0000000000000000000000000000000000000DD1AF5F' block_9 = 'FAF50009000200000020000000000000000000000000000000000000021AAF5F' block_10 = 'FAF5000A0002000000260000000000000000000000000000000000000000000000000221AF5F' block_11 = 'FAF5000B0003000000EC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E9AF5F' block_12 = 'FAF5000C000200000045000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000242AF5F' block_2 = 'FAF50002000200000074010001000000000000000000000000000000000000000000007F0000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E9AF5F' checksum = hex(0x00) block_2split = list(split_by_n(block_2,2)) block_2split[10] = MyVar.upper() #Overspeed Alarm Position for i in range(len(block_2split)-6): checksum = hex(int(checksum, 16) + int(block_2split[i], 16)) checksum_string = str(checksum) checksum_actvalue = checksum_string[2:] checksum_long = checksum_actvalue.rjust(8,'0').upper() checksum_split = list(split_by_n(checksum_long,2)) block_2split[len(block_2split)-3] = checksum_split[3] block_2split[len(block_2split)-4] = checksum_split[2] block_2split[len(block_2split)-5] = checksum_split[1] block_2split[len(block_2split)-6] = checksum_split[0] Block_2Output = ''.join(str(item) for item in block_2split) iEngineSpeed = int(priEngSp,10) hEngineSpeed = hex(iEngineSpeed * 10) sEngineSpeed = str(hEngineSpeed)[2:].upper() while (len(sEngineSpeed)<8): sEngineSpeed = '0' + sEngineSpeed block_4split = list(split_by_n(block_4,4)) sEngineSpeed_split = list(split_by_n(sEngineSpeed,4)) block_4split[5] = sEngineSpeed_split[0] block_4split[6] = sEngineSpeed_split[1] Block_4joint = ''.join(str(item) for item in block_4split) Block_4joint_sp = list(split_by_n(Block_4joint,2)) checksumb4 = hex(0x00) for i in range(len(Block_4joint_sp)-6): checksumb4 = hex(int(checksumb4, 16) + int(Block_4joint_sp[i], 16)) checksumb4_string = str(checksumb4) checksumb4_actvalue = checksumb4_string[2:] checksumb4_long = checksumb4_actvalue.rjust(8,'0').upper() checksumb4_split = list(split_by_n(checksumb4_long,2)) Block_4joint_sp[len(Block_4joint_sp)-3] = checksumb4_split[3] Block_4joint_sp[len(Block_4joint_sp)-4] = checksumb4_split[2] Block_4joint_sp[len(Block_4joint_sp)-5] = checksumb4_split[1] Block_4joint_sp[len(Block_4joint_sp)-6] = checksumb4_split[0] Block_4Output = ''.join(str(item) for item in Block_4joint_sp) blocks = [Block_2Output, block_3, Block_4Output, block_5, block_6, block_7, block_8, block_9, block_10, block_11, block_12] with serial.Serial('COM5', '9600') as ser: #you might wanna comment this part out for block in blocks: print(block) ser.write(bytes.fromhex(block.strip())) #you might wanna comment this part out time.sleep(1) win.after(200, task) win.after(200, task) win.mainloop()
To avoid freezing, one of the way is to use thread: from threading import Thread ... def task(): while True: MyVar = v.get() ... blocks = [Block_2Output, block_3, Block_4Output, block_5, block_6, block_7, block_8, block_9, block_10, block_11, block_12] with serial.Serial('COM5', '9600') as ser: #you might wanna comment this part out for block in blocks: print(block) ser.write(bytes.fromhex(block.strip())) #you might wanna comment this part out time.sleep(1) time.sleep(0.2) # run task() in a thread Thread(target=task, daemon=1).start() win.mainloop()
MoviePy multiple textClips one after another
I have an audio file and its script file, that looks like this One day I was playing Fortnite solos until I got a strange fend invites I never seen before I joned it an he said time to play a game I sruged it of like no big deal I regreted doing that but he kept saying time to play over and over and over ugen My goal is to make a video where voice is followed by text appearing on the screen (next line appears, previous disappears). The way I do it is obviously wrong and it just renders all lines at the beginning of the video stacked on each other + I can not know how much lines of script there will be so doing texts[0], texts[1]... is not an option. Please send help! My code: videoclip = VideoFileClip("Satisfying Minecraft Parkour.mp4") audioclip = AudioFileClip(f"audio.mp3") new_audioclip = CompositeAudioClip([audioclip]) videoclip.audio = new_audioclip texts = [] with open(f'text.txt', 'r') as f: for line in f: txt_clip = TextClip(line, fontsize = 55, color = 'white') txt_clip = txt_clip.set_pos('center') txt_clip = txt_clip.set_duration(audio_in_seconds/len(str(text))*len(line)) texts.append(txt_clip) video = CompositeVideoClip([videoclip, texts[0]]) video = CompositeVideoClip([video, texts[1]])
Can't seem to get uasyncio working in a micropython script for a PyBoard
I am designing a new time/score keeper for an air hockey table using a PyBoard as a base. My plan is to use a TM1627 (4x7seg) for time display, rotary encoder w/ button to set the time, IR and a couple 7segs for scoring, IR reflector sensors for goallines, and a relay to control the fan. I'm getting hung up trying to separate the clock into its own thread while focusing on reading the sensors. Figured I could use uasyncio to split everything up nicely, but I can't figure out where to put the directives to spin off a thread for the clock and eventually the sensors. On execution right now, it appears the rotary encoder is assigned the default value, no timer is started, the encoder doesn't set the time, and the program returns control to REPL rather quickly. Prior to trying to async everything, I had the rotary encoder and timer working well. Now, not so much. from rotary_irq_pyb import RotaryIRQ from machine import Pin import tm1637 import utime import uasyncio async def countdown(cntr): # just init min/sec to any int > 0 min = sec = 99 enableColon = True while True: # update the 4x7seg with the time remaining min = abs(int((cntr - utime.time()) / 60)) sec = (cntr - utime.time()) % 60 #print(str(), str(sec), sep=':' ) enableColon = not enableColon # alternately blink the colon tm.numbers(min, sec, colon = enableColon) if(min + sec == 0): # once both reach zero, break break await uasyncio.sleep(500) X1 = pyb.Pin.board.X1 X2 = pyb.Pin.board.X2 Y1 = pyb.Pin.board.Y1 Y2 = pyb.Pin.board.Y2 button = pyb.Pin(pyb.Pin.board.X3, pyb.Pin.IN) r = RotaryIRQ(pin_num_clk=X1, pin_num_dt=X2, min_val=3, max_val=10, reverse=False, range_mode=RotaryIRQ.RANGE_BOUNDED) tm = tm1637.TM1637(clk = Y1, dio = Y2) val_old = val_new = 0 while True: val_new = r.value() if(val_old != val_new): val_old = val_new print(str(val_new)) if(button.value()): # save value as minutes loop = uasyncio.get_event_loop() endTime = utime.time() + (60 * val_new) loop.create_task(countdown(endTime)) r.close() # Turn off Rotary Encoder break #loop = uasyncio.get_event_loop() #loop.create_task(countdown(et)) #loop.run_until_complete(countdown(et)) I'm sure it's something simple, but this is the first non-CLI python script I've done, so I'm sure there are a bunch of silly mistakes. Any assistance would be appreciated.
Raspberry Pi - Python & Flask web control with Adafruit DotStar LEDS
apologies if this isn't the right place to ask, but I did some searching and couldn't find much to point me in the right direction. I wasn't quite sure what to search for. I am a novice with python and programming in general, but usually can do enough googling and stealing other code snippets to get my projects running. However I'm at a bit of a roadblock here. I need to control an Adafruit DotStar lightstrip with a flask web browser app. I've been able to get the flask app working, I've done a simple proof of concept with turning an LED on and off etc., and I can start my lightstrip script but the code I'm trying to run for the lightstrip needs to loop continuously and still be able to change "modes". I have several different images that display on the light strip and I would like to be able to select which one(s) is/are playing, but for now mainly I would just like to be able to start and stop a "shuffle all" mode. If I run the module in a while loop it just loops forever and I can't change the argument to a different "mode". I built a simple script based on Adafruit's DotStar library (specifically the image persistence of vision script, I'm just using PNG images as the map for the different lightstrip "shows"). It all currently works except it only runs each mode once obviously. I had it all in a while loop and it just looped the first selected mode forever and I was unable to turn it off or switch modes. I also thought maybe I should use multiprocessing, and I looked into getting that working, but I couldn't figure out how to stop a process once it started. Here is the light strip script: (the 'off' mode is just a black image. I'm sure theres a cleaner way to do this but I'm not sure on how to do that either) import Image from dotstar import Adafruit_DotStar import random def lightstrip(mode): loopLength = 120 #loop length in pixels fade = "/home/pi/lightshow/images/fade.png" sparkle = "/home/pi/lightshow/images/sparkle.png" steeplechase = "/home/pi/lightshow/images/steeplechase.png" bump = "/home/pi/lightshow/images/bump.png" spaz = "/home/pi/lightshow/images/spaz.png" sine = "/home/pi/lightshow/images/sine.png" bounce = "/home/pi/lightshow/images/bounce.png" off = "/home/pi/lightshow/images/null.png" numpixels = 30 datapin = 23 clockpin = 24 strip = Adafruit_DotStar(numpixels, 100000) rOffset = 3 gOffset = 2 bOffset = 1 strip.begin() if mode == 1: options = [fade, sparkle, steeplechase, bump, spaz, sine, bounce] print "Shuffling All..." if mode == 2: options = [bump, spaz, sine, bounce] print "Shuffling Dance..." if mode == 3: options = [fade, sparkle, steeplechase] print "Shuffling Chill..." if mode == 0: choice = off print "Lightstrip off..." if mode != 0: choice = random.choice(options) print "Loading..." img = Image.open(choice).convert("RGB") pixels = img.load() width = img.size[0] height = img.size[1] print "%dx%d pixels" % img.size # Calculate gamma correction table, makes mid-range colors look 'right': gamma = bytearray(256) for i in range(256): gamma[i] = int(pow(float(i) / 255.0, 2.7) * 255.0 + 0.5) # Allocate list of bytearrays, one for each column of image. # Each pixel REQUIRES 4 bytes (0xFF, B, G, R). print "Allocating..." column = [0 for x in range(width)] for x in range(width): column[x] = bytearray(height * 4) # Convert entire RGB image into column-wise BGR bytearray list. # The image-paint.py example proceeds in R/G/B order because it's counting # on the library to do any necessary conversion. Because we're preparing # data directly for the strip, it's necessary to work in its native order. print "Converting..." for x in range(width): # For each column of image... for y in range(height): # For each pixel in column... value = pixels[x, y] # Read pixel in image y4 = y * 4 # Position in raw buffer column[x][y4] = 0xFF # Pixel start marker column[x][y4 + rOffset] = gamma[value[0]] # Gamma-corrected R column[x][y4 + gOffset] = gamma[value[1]] # Gamma-corrected G column[x][y4 + bOffset] = gamma[value[2]] # Gamma-corrected B print "Displaying..." count = loopLength while (count > 0): for x in range(width): # For each column of image... strip.show(column[x]) # Write raw data to strip count = count - 1 And the main.py script for running the web app: from flask import * from lightshow import * from multiprocessing import Process import RPi.GPIO as GPIO import Image from dotstar import Adafruit_DotStar import random import time app = Flask(__name__) #app.route("/") def hello(): return render_template('index.html') #app.route("/lightstrip/1", methods=['POST']) def shuffleall(): lightstrip(1) return ('', 204) #app.route("/lightstrip/2", methods=['POST']) def shuffledance(): lightstrip(2) return ('', 204) #app.route("/lightstrip/3", methods=['POST']) def shufflechill(): lightstrip(3) return ('', 204) #app.route("/lightstrip/0", methods=['POST']) def off(): lightstrip(0) return ('', 204) if __name__ == "__main__": app.run(host='0.0.0.0', debug=True) Again I'm at a bit of a loss here, this may be simple fix or I may be approaching it totally wrong but any and all help would be appreciated. I am a complete beginner to approaching a problem like this. Thank you
Here's an example showing how to start and stop processes using multiprocessing and psutil. In this example the task_runner kills any running processes before starting a new one. from flask import Flask import multiprocessing import psutil app = Flask(__name__) def blink(var): while True: # do stuff print(var) def task_runner(var): processes = psutil.Process().children() for p in processes: p.kill() process = multiprocessing.Process(target=blink, args=(var,)) process.start() #app.route("/red") def red(): task_runner('red') return 'red started' #app.route("/blue") def blue(): task_runner('blue') return 'blue started' if __name__ == "__main__": app.run() For your question, the task_runner would look something like: def task_runner(mode): processes = psutil.Process().children() for p in processes: p.kill() process = multiprocessing.Process(target=lightstrip, args=(mode,)) process.start()
Python: How to draw coordinates using tkinter whilst reading from a .txt
First time user. I'm a grad student at George Mason and I've been greatly aided, and impressed by the community here so I thought that I would pose a question. I'm trying to draw points specified from a textfile using tkinter (the points are specified at the top of the code but I put them in a textfile). My assignment requires me to project the points but I want to go a step further and have them read directly from my variables so if the .txt changes they change aswell. My problem is that I'm not sure how to parse the variables to so tkinter can see them. Here is the code: """ Read the following data (I put them into .txt first): Polyline; 1: 1603714.835939442,142625.48838266544; 1603749.4678153452,142620.21243656706; 1603780.3769339535,142607.37201781105; 1603801.475846678,142582.27024446055; 1603830.4767344964,142536.14692804776; 2: 1602514.2066492266,142330.66992144473; 1602521.4127475217,142414.92978276964; 1602520.1146955898,142433.93817959353; 1602501.3840010355,142439.12358761206; 1602371.6780588734,142417.84858870413; 1602351.6610373354,142408.02716448065; 1602334.5180692307,142388.58748627454; 1602331.6999511716,142376.66073128115; 1602334.8067251327,142348.965322732; 1602338.308919772,142323.6111663878; 1602349.0226452332,142314.50124930218; 1602363.9090971674,142310.79584660195; 1602514.2066492266,142330.66992144473; The following code define a function 'readPolylineFile' to read out data one line by one line The readPolylineFile function will return two polylines In addtion, try....except...finally are used to catch the exceptions """ import math class Points: def __init__(self, x=0.0, y=0.0): self.x,self.y = x, y class Polyline: def __init__(self, points =[] ): self.points = points def getLength(self): i = 0 length = 0.0 while i < len(self.points)-1: length += math.sqrt((self.points[i+1].x -self.points[i].x)**2 + (self.points[i+1].y -self.points[i].y)**2 ) i += 1 return length ## function to read out data one line by one line ## return polylines list def readPolylineFile(fileName): ## Declare variables that will be used outside of try blocks polylines = [] ## empty polyline list to keep all polylines f = None # empty file object try: f = open(fileName, 'r') ## Open the file and assign the return object to f firstPolyLineNum = 0 index = 0 for line in f: index += 1 if index == 1: ## Pass the first line continue coords = line.split(':')[1] eachcoords = coords.split(';') coordsLen = len(eachcoords) points = [] ## Declare a points list to keep the points for each polyline for i in range(coordsLen-1): singlecoords = eachcoords[i] xCoord = singlecoords.split(',')[0] yCoord = singlecoords.split(',')[1] print singlecoords try: point = Points(float(xCoord),float(yCoord)) points.append(point) except ValueError: print 'Can not convert non-number to float' except TypeError: print 'Object type can not conver to float' ## Create a polyline object based on the points polyline = Polyline(points) polylines.append(polyline) except IOError: ##File does not exist print 'IO Error while opening or reading the file' finally: if f: ## If file object exist, close the file print 'Input .txt has been read and is now closed......' f.close() return polylines ## Return the polylines polylines = readPolylineFile('F://GMU Fall 2013/GGS 650/HW6/input.txt') try: ## Get the first polyline polyLine1 = polylines[0] lengthForFirstPoly = polyLine1.getLength() print "length for first polyline (first 5 coordinates) -> ", lengthForFirstPoly ## Gets the points for second polyline polyLine2 = polylines[1] lengthForSecondPoly = polyLine2.getLength() print "length for Second polyline (last 13 coordinates) -> ", lengthForSecondPoly except: print "error in processing polyline objects created" from Tkinter import * master = Tk() master2 = Tk() w = Canvas(master, width=800, height=600) w.pack() w.create_line(0, 0, 200, 100) w = Canvas(master2, width=800, height=600) w.pack() w.create_line(0, 0, 200, 297) mainloop()
All you need to do is create a method in Polyline that returns the coordinates of all of it's points as a flat list, then use that to create your line. Here's a quick and dirty example of returning a flattened list of coordinates: class Polyline(self): ... def getCoordinates(self): coords = [] for point in self.points: coords.append(point.x) coords.append(point.y) return coords Here's how to create a line on a canvas for every polyline: for polyline in polylines: canvas.create_line(polyline.getCoordinates())