Closed planetsLightningArrester closed 4 years ago
Thanks for reporting! Does the FreeCAD plugin report any specific error?
Hi! At first, it doesn't prompt any useful error just: "Incompatible file format". So I looked over the addon python files and it seems that it was just that the addon looks in the first line of the file for the kicad description like:
"(kicad_pcb (version 20171130) (host pcbnew "(5.1.6)-1")"
Which is in the second line of your generated file. This error is resolved just deleting the first empty line of the .kicad_pcb output file.
But loading the files still prompts a lot of errors. I'm pretty sure its because the addon uses regex expression expecting a specific indentation/spacing/formatting for the whole file. For example layer "F.SilkS"
, fp_text reference "R1"
and every other layer/net_name and so must not have quotation marks. For the addon identifies it correctly it should be layer F.SilkS
, fp_text reference R1
. Change it all resolves some issues.
But the formatting issues are more complex. Following this error:
[' D1(at 0.762 1.016 0)(layer F.SilkS)\n (effects (font (size 1.143 1.143) (thickness 0.152)) (justify left)'][]Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\franc\AppData\Roaming\FreeCAD\Mod\pcb\PCBbrd.py", line 66, in open
importBRD(filename, wersjaFormatu[0])
File "C:\Users\franc\AppData\Roaming\FreeCAD\Mod\pcb\PCBbrd.py", line 235, in importBRD
plytka = plytkaPCB.generate(doc)
File "C:\Users\franc\AppData\Roaming\FreeCAD\Mod\pcb\formats\PCBmainForms.py", line 134, in generate
self.importParts()
File "C:\Users\franc\AppData\Roaming\FreeCAD\Mod\pcb\formats\PCBmainForms.py", line 247, in importParts
for i in self.wersjaFormatu.getParts():
File "C:\Users\franc\AppData\Roaming\FreeCAD\Mod\pcb\formats\kicad_v3.py", line 833, in getParts
i['EL_Name'] = dataName[0]
<class 'IndexError'>: list index out of range
I reached this method:
def getParts(self):
self.getElements()
parts = []
###########
for i in self.elements:
if i['side'] == 1:
i['side'] = "TOP"
else:
i['side'] = "BOTTOM"
####################################
dataName = self.getAnnotations(re.findall(r'\(fp_text reference(.+?)\)\n\s+\)\n\s+\(', i['dataElement'], re.MULTILINE|re.DOTALL), mode='param')
i['EL_Name'] = dataName[0]
i['EL_Name']["text"] = "NAME"
i['EL_Name']["x"] = i['EL_Name']["x"] + i["x"]
i['EL_Name']["y"] = i['EL_Name']["y"] + i["y"]
i['EL_Name']["rot"] = i['EL_Name']["rot"] - i["rot"]
####################################
dataValue = self.getAnnotations(re.findall(r'\(fp_text value(.+?)\)\n\s+\)\n\s+\(', i['dataElement'], re.MULTILINE|re.DOTALL), mode='param')
i['EL_Value'] = dataValue[0]
i['EL_Value']["text"] = "VALUE"
i['EL_Value']["x"] = i['EL_Value']["x"] + i["x"]
i['EL_Value']["y"] = i['EL_Value']["y"] + i["y"]
i['EL_Value']["rot"] = i['EL_Value']["rot"] - i["rot"]
####################################
parts.append(i)
#
return parts
And dataName
returns an empty list most of the time which rises index errors on the next line. The getAnnotations
method is as follows.
def getAnnotations(self, data, mode='anno'):
adnotacje = []
#
for i in data:
try:
txt = re.search(r'\s(.*?)\s\(at', i).groups(0)[0].replace('"', '').replace('\r\n', '\n').replace('\r', '\n').replace('\\n', '\n')
[x, y, rot] = re.search(r'\(at\s+([0-9\.-]*?)\s+([0-9\.-]*?)(\s+[0-9\.-]*?|)\)', i).groups()
layer = re.search(r'\(layer\s+(.+?)\)', i).groups()[0]
size = re.search(r'\(size\s+([0-9\.]*?)\s+[0-9\.]*?\)', i).groups()[0]
justify = re.findall(r'( \(justify .*?\)|)\)', i)[-1].strip()
except:
continue
#
if rot == '':
rot = 0.0
else:
rot = float(rot)
if layer.startswith('F.') or (self.spisWarstw[layer] in [15, 21] and self.databaseType == "kicad") or (self.spisWarstw[layer] in [0, 33, 35, 37, 39, 40, 41, 42, 43, 44, 45, 47, 49] and self.databaseType == "kicad_v4"):
side = 'TOP'
else:
side = 'BOTTOM'
extra = re.findall(r'\(justify( [left|right]+|)( mirror|)\)', justify, re.DOTALL)
if len(extra):
if extra[0][0].strip() == 'right':
align = 'center-right'
elif extra[0][0].strip() == 'left':
align = 'center-left'
else:
align = 'center'
if extra[0][1].strip() == 'mirror':
mirror = 2
else:
mirror = 0
else:
align = 'center'
mirror = False
adnotacje.append({
"text": txt,
"x": float(x),
"y": float(y) * (-1),
"z": 0,
"size": float(size),
"rot": rot,
"side": side,
"align": align,
"spin": False,
"font": 'Proportional',
"display": True,
"distance": 1,
"tracking": 0,
"mirror": mirror,
"mode": mode
})
#
return adnotacje
So the file must follow the regex expressions so the addon can identify the parameters. It's not robust for files slightly different.
Thanks for looking into this!
Removing the first empty line should be simple, but it seems like the correct solution would actually be to rewrite the parser of the FreeCAD-PCB addon to parse the file according to the the S-expression format (section 4 describes the format). It shouldn't be too hard - the JavaScript code that parses this format takes roughly 60 lines of code.
But IMHO, the best solution for you could just be to create a python script that will load the file in pcbnew, and then save it again under a different name. I believe that should take less than 10 lines of code, and will probably be the lowest hanging fruit here.
I'll probably stick with Python script's solution. Thank you so much for your help!
Hi.
I developed a simple PCB that I'd like to import in FreeCAD using this addon which seems to works great with some .kicad_pcb files from a KiCad project.
I can generate my EasyEDA file "input.json" an get the "output.kicad_pcb" in both Node library on my pc and the online converter. But FreeCAD can't open the file. As I pointed out it seems to work just fine with another directly generated .kicad_pcb files so I don't think the issue is the addon.
I got two warnings:
I can make FreeCAD open the file if I open the "output.kicad_pcb" in KiCad and save it as another file. The input.json, output.kicad_pcb and the savedAsWorking.kicad_pcb files are attached. It may be an enhancement once it works to open the output in Kicad. But it would be really nice to have this converter to works just like a KiCad "Save as ..". Anyway thank you so much for your time and let me know if I can help you with more info.
inOutFiles.zip SavedAsWorking.zip
Windows 10 Home Chrome 83.0.4103.97 EasyEDA v6.3.53 Node v12.16.3 NPM v6.14.4