From e4880ae9cccfcf33b332245dae70d48669f4c693 Mon Sep 17 00:00:00 2001 From: Andreas Klintberg Date: Thu, 1 Feb 2018 21:39:28 -0800 Subject: [PATCH 1/7] changed to setuptools and replaced cStringIO --- .gitignore | 1 + pypcd/pypcd.py | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index b176547..dc1a88c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.pyc pypcd.egg-info build +dist diff --git a/pypcd/pypcd.py b/pypcd/pypcd.py index 9c9aab1..e02dd1e 100644 --- a/pypcd/pypcd.py +++ b/pypcd/pypcd.py @@ -10,7 +10,7 @@ import re import struct import copy -import cStringIO as sio +from io import StringIO as sio import numpy as np import warnings import lzf diff --git a/setup.py b/setup.py index 550b643..077ab44 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ import os -from distutils.core import setup +from setuptools import setup # Get version and release info, which is all stored in pypcd/version.py ver_file = os.path.join('pypcd', 'version.py') From ab7b07a7f0828230e2447f7eaa2f7439ba0fbabf Mon Sep 17 00:00:00 2001 From: Andreas Klintberg Date: Fri, 2 Feb 2018 01:02:28 -0800 Subject: [PATCH 2/7] tests passes for python 3 --- pypcd/pypcd.py | 28 +++++++++++++++------------- pypcd/tests/test_pypcd.py | 18 +++++++++--------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/pypcd/pypcd.py b/pypcd/pypcd.py index e02dd1e..a95f376 100644 --- a/pypcd/pypcd.py +++ b/pypcd/pypcd.py @@ -87,11 +87,11 @@ def parse_header(lines): elif key in ('fields', 'type'): metadata[key] = value.split() elif key in ('size', 'count'): - metadata[key] = map(int, value.split()) + metadata[key] = list(map(int, value.split())) elif key in ('width', 'height', 'points'): metadata[key] = int(value) elif key == 'viewpoint': - metadata[key] = map(float, value.split()) + metadata[key] = list(map(float, value.split())) elif key == 'data': metadata[key] = value.strip().lower() # TODO apparently count is not required? @@ -199,9 +199,9 @@ def _build_dtype(metadata): fieldnames.append(f) typenames.append(np_type) else: - fieldnames.extend(['%s_%04d' % (f, i) for i in xrange(c)]) + fieldnames.extend(['%s_%04d' % (f, i) for i in range(c)]) typenames.extend([np_type]*c) - dtype = np.dtype(zip(fieldnames, typenames)) + dtype = np.dtype(list(zip(fieldnames, typenames))) return dtype @@ -267,6 +267,8 @@ def point_cloud_from_fileobj(f): header = [] while True: ln = f.readline().strip() + if isinstance(ln, bytes): + ln = ln.decode('utf-8') header.append(ln) if ln.startswith('DATA'): metadata = parse_header(header) @@ -309,13 +311,13 @@ def point_cloud_to_fileobj(pc, fileobj, data_compression=None): assert(data_compression in ('ascii', 'binary', 'binary_compressed')) metadata['data'] = data_compression - header = write_header(metadata) + header = write_header(metadata).encode('utf-8') fileobj.write(header) if metadata['data'].lower() == 'ascii': fmtstr = build_ascii_fmtstr(pc) np.savetxt(fileobj, pc.pc_data, fmt=fmtstr) elif metadata['data'].lower() == 'binary': - fileobj.write(pc.pc_data.tostring('C')) + fileobj.write(pc.pc_data.tostring()) elif metadata['data'].lower() == 'binary_compressed': # TODO # a '_' field is ignored by pcl and breakes compressed point clouds. @@ -324,9 +326,9 @@ def point_cloud_to_fileobj(pc, fileobj, data_compression=None): # reorder to column-by-column uncompressed_lst = [] for fieldname in pc.pc_data.dtype.names: - column = np.ascontiguousarray(pc.pc_data[fieldname]).tostring('C') + column = np.ascontiguousarray(pc.pc_data[fieldname]).tostring() uncompressed_lst.append(column) - uncompressed = ''.join(uncompressed_lst) + uncompressed = b''.join(uncompressed_lst) uncompressed_size = len(uncompressed) # print("uncompressed_size = %r"%(uncompressed_size)) buf = lzf.compress(uncompressed) @@ -359,19 +361,19 @@ def point_cloud_to_buffer(pc, data_compression=None): def save_point_cloud(pc, fname): """ save pointcloud to fname in ascii format """ - with open(fname, 'w') as f: + with open(fname, 'wb') as f: point_cloud_to_fileobj(pc, f, 'ascii') def save_point_cloud_bin(pc, fname): """ save pointcloud to fname in binary format """ - with open(fname, 'w') as f: + with open(fname, 'wb') as f: point_cloud_to_fileobj(pc, f, 'binary') def save_point_cloud_bin_compressed(pc, fname): - with open(fname, 'w') as f: + with open(fname, 'wb') as f: point_cloud_to_fileobj(pc, f, 'binary_compressed') @@ -461,7 +463,7 @@ def add_fields(pc, metadata, pc_data): else: fieldnames.extend(['%s_%04d' % (f, i) for i in xrange(c)]) typenames.extend([np_type]*c) - dtype = zip(fieldnames, typenames) + dtype = list(zip(fieldnames, typenames)) # new dtype. could be inferred? new_dtype = [(f, pc.pc_data.dtype[f]) for f in pc.pc_data.dtype.names] + dtype @@ -631,7 +633,7 @@ def save_pcd(self, fname, compression=None, **kwargs): warnings.warn('data_compression keyword is deprecated for' ' compression') compression = kwargs['data_compression'] - with open(fname, 'w') as f: + with open(fname, 'wb') as f: point_cloud_to_fileobj(self, f, compression) def save_pcd_to_fileobj(self, fileobj, compression=None, **kwargs): diff --git a/pypcd/tests/test_pypcd.py b/pypcd/tests/test_pypcd.py index a3a41fe..36ec6cb 100644 --- a/pypcd/tests/test_pypcd.py +++ b/pypcd/tests/test_pypcd.py @@ -77,7 +77,7 @@ def test_parse_header(): def test_from_path(pcd_fname): - import pypcd + from pypcd import pypcd pc = pypcd.PointCloud.from_path(pcd_fname) fields = 'x y z normal_x normal_y normal_z curvature boundary k vp_x vp_y vp_z principal_curvature_x principal_curvature_y principal_curvature_z pc1 pc2'.split() @@ -88,7 +88,7 @@ def test_from_path(pcd_fname): def test_add_fields(pcd_fname): - import pypcd + from pypcd import pypcd pc = pypcd.PointCloud.from_path(pcd_fname) old_md = pc.get_metadata() @@ -107,7 +107,7 @@ def test_add_fields(pcd_fname): def test_path_roundtrip_ascii(pcd_fname): - import pypcd + from pypcd import pypcd pc = pypcd.PointCloud.from_path(pcd_fname) md = pc.get_metadata() @@ -131,7 +131,7 @@ def test_path_roundtrip_ascii(pcd_fname): def test_path_roundtrip_binary(pcd_fname): - import pypcd + from pypcd import pypcd pc = pypcd.PointCloud.from_path(pcd_fname) md = pc.get_metadata() @@ -145,7 +145,7 @@ def test_path_roundtrip_binary(pcd_fname): pc2 = pypcd.PointCloud.from_path(tmp_fname) md2 = pc2.get_metadata() - for k, v in md2.iteritems(): + for k, v in md2.items(): if k == 'data': assert v == 'binary' else: @@ -159,7 +159,7 @@ def test_path_roundtrip_binary(pcd_fname): def test_path_roundtrip_binary_compressed(pcd_fname): - import pypcd + from pypcd import pypcd pc = pypcd.PointCloud.from_path(pcd_fname) md = pc.get_metadata() @@ -173,7 +173,7 @@ def test_path_roundtrip_binary_compressed(pcd_fname): pc2 = pypcd.PointCloud.from_path(tmp_fname) md2 = pc2.get_metadata() - for k, v in md2.iteritems(): + for k, v in md2.items(): if k == 'data': assert v == 'binary_compressed' else: @@ -186,7 +186,7 @@ def test_path_roundtrip_binary_compressed(pcd_fname): def test_cat_pointclouds(pcd_fname): - import pypcd + from pypcd import pypcd pc = pypcd.PointCloud.from_path(pcd_fname) pc2 = pc.copy() pc2.pc_data['x'] += 0.1 @@ -196,7 +196,7 @@ def test_cat_pointclouds(pcd_fname): assert(pc3.width == pc.width+pc2.width) def test_ascii_bin1(ascii_pcd_fname, bin_pcd_fname): - import pypcd + from pypcd import pypcd apc1 = pypcd.point_cloud_from_path(ascii_pcd_fname) bpc1 = pypcd.point_cloud_from_path(bin_pcd_fname) am = cloud_centroid(apc1) From f29adbcd0117f4d05c4301e732bcbc1c1a410979 Mon Sep 17 00:00:00 2001 From: Andreas Klintberg Date: Tue, 20 Mar 2018 23:36:28 -0700 Subject: [PATCH 3/7] fixed py2 compatibility --- .gitignore | 7 +++++++ pypcd/pypcd.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index dc1a88c..c1abc5c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,10 @@ pypcd.egg-info build dist +bin +lib +include +.Python +.idea +pip-selfcheck.json +.pytest_cache/ \ No newline at end of file diff --git a/pypcd/pypcd.py b/pypcd/pypcd.py index a95f376..6b4ea57 100644 --- a/pypcd/pypcd.py +++ b/pypcd/pypcd.py @@ -267,7 +267,7 @@ def point_cloud_from_fileobj(f): header = [] while True: ln = f.readline().strip() - if isinstance(ln, bytes): + if not isinstance(ln, str): ln = ln.decode('utf-8') header.append(ln) if ln.startswith('DATA'): From 4ed7d8b544982e5da8ff3ecab1ad3473a6ec3c6f Mon Sep 17 00:00:00 2001 From: Emmanuel Kring Date: Wed, 29 Apr 2020 23:28:42 +0200 Subject: [PATCH 4/7] fix py3 compatibility in import statement --- pypcd/pypcd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pypcd/pypcd.py b/pypcd/pypcd.py index 6b4ea57..93f58e8 100644 --- a/pypcd/pypcd.py +++ b/pypcd/pypcd.py @@ -18,7 +18,7 @@ HAS_SENSOR_MSGS = True try: from sensor_msgs.msg import PointField - import numpy_pc2 # needs sensor_msgs + from . import numpy_pc2 # needs sensor_msgs except ImportError: HAS_SENSOR_MSGS = False From 8d6d620e0cae3f27ab80c8ff3f3cebf6d70eecdd Mon Sep 17 00:00:00 2001 From: Emmanuel Kring Date: Thu, 30 Apr 2020 00:00:08 +0200 Subject: [PATCH 5/7] fix import statements --- pypcd/pdutil.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pypcd/pdutil.py b/pypcd/pdutil.py index 809b2f9..601de7e 100644 --- a/pypcd/pdutil.py +++ b/pypcd/pdutil.py @@ -1,5 +1,5 @@ -import pypcd - +from pypcd import pypcd +from pypcd import numpy_pc2 def data_frame_to_point_cloud(df): """ create a PointCloud object from a dataframe. """ @@ -28,4 +28,4 @@ def data_frame_to_point_cloud(df): def data_frame_to_message(df, stamp=None, frame_id=None): pc_data = df.to_records(index=False) - return pypcd.numpy_pc2.array_to_pointcloud2(pc_data, stamp=stamp, frame_id=frame_id) + return numpy_pc2.array_to_pointcloud2(pc_data, stamp=stamp, frame_id=frame_id) From 19b40095d8f8e0ee0a8ac88ca20f3238ab2a611d Mon Sep 17 00:00:00 2001 From: Yuwen Heng <15895948+heng-yuwen@users.noreply.github.com> Date: Tue, 6 Dec 2022 15:52:45 +0800 Subject: [PATCH 6/7] Update pypcd.py Fix ValueError: field '__0000' occurs more than once --- pypcd/pypcd.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pypcd/pypcd.py b/pypcd/pypcd.py index 93f58e8..db0fb52 100644 --- a/pypcd/pypcd.py +++ b/pypcd/pypcd.py @@ -77,6 +77,8 @@ def parse_header(lines): for ln in lines: if ln.startswith('#') or len(ln) < 2: continue + ln = ln.replace('_','s',1) + ln = ln.replace('_','m',1) match = re.match('(\w+)\s+([\w\s\.]+)', ln) if not match: warnings.warn("warning: can't understand line: %s" % ln) From d5fe28155ac54a9ba4ae38fc612f8ded342c4853 Mon Sep 17 00:00:00 2001 From: Yuwen Heng <15895948+heng-yuwen@users.noreply.github.com> Date: Fri, 9 Dec 2022 17:56:33 +0800 Subject: [PATCH 7/7] Update pypcd.py FIx DATA binary_compressed parsing error --- pypcd/pypcd.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pypcd/pypcd.py b/pypcd/pypcd.py index db0fb52..77a90b0 100644 --- a/pypcd/pypcd.py +++ b/pypcd/pypcd.py @@ -77,8 +77,8 @@ def parse_header(lines): for ln in lines: if ln.startswith('#') or len(ln) < 2: continue - ln = ln.replace('_','s',1) - ln = ln.replace('_','m',1) + ln = ln.replace(' _ ',' s ',1) + ln = ln.replace(' _ ',' m ',1) match = re.match('(\w+)\s+([\w\s\.]+)', ln) if not match: warnings.warn("warning: can't understand line: %s" % ln)