point_cloud_utility.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # @file point_cloud_utility.cc
4 #
5 # Copyright 2013-2025
6 # Carnegie Robotics, LLC
7 # 4501 Hatfield Street, Pittsburgh, PA 15201
8 # http://www.carnegierobotics.com
9 #
10 # All rights reserved.
11 #
12 # Redistribution and use in source and binary forms, with or without
13 # modification, are permitted provided that the following conditions are met:
14 # * Redistributions of source code must retain the above copyright
15 # notice, this list of conditions and the following disclaimer.
16 # * Redistributions in binary form must reproduce the above copyright
17 # notice, this list of conditions and the following disclaimer in the
18 # documentation and/or other materials provided with the distribution.
19 # * Neither the name of the Carnegie Robotics, LLC nor the
20 # names of its contributors may be used to endorse or promote products
21 # derived from this software without specific prior written permission.
22 #
23 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 # DISCLAIMED. IN NO EVENT SHALL CARNEGIE ROBOTICS, LLC BE LIABLE FOR ANY
27 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #
34 # Significant history (date, user, job code, action):
35 # 2025-02-07, malvarado@carnegierobotics.com, IRAD, Created file.
36 #
37 
38 import argparse
39 import numpy as np
40 
41 import libmultisense as lms
42 
43 
44 luma_point_type = np.dtype({'names': ['x', 'y', 'z', 'luma'],
45  'formats': [np.float32, np.float32, np.float32, np.uint8],
46  'offsets': [0, 4, 8, 12],
47  'itemsize': 13})
48 
49 color_point_type = np.dtype({'names': ['x', 'y', 'z', 'blue', 'green', 'red'],
50  'formats': [np.float32, np.float32, np.float32, np.uint8, np.uint8, np.uint8],
51  'offsets': [0, 4, 8, 12, 13, 14],
52  'itemsize': 15})
53 
54 def main(args):
55  channel_config = lms.ChannelConfig()
56  channel_config.ip_address = args.ip_address
57  channel_config.mtu = args.mtu
58 
59  with lms.Channel.create(channel_config) as channel:
60  if not channel:
61  print("Invalid channel")
62  exit(1)
63 
64  config = channel.get_config()
65  config.frames_per_second = 10.0
66  if channel.set_config(config) != lms.Status.OK:
67  print("Cannot set configuration")
68  exit(1)
69 
70  info = channel.get_info()
71  color_stream = lms.DataSource.AUX_RECTIFIED_RAW if args.use_color and info.device.has_aux_camera() else lms.DataSource.LEFT_RECTIFIED_RAW
72 
73  if channel.start_streams([color_stream, lms.DataSource.LEFT_DISPARITY_RAW]) != lms.Status.OK:
74  print("Unable to start streams")
75  exit(1)
76 
77  while True:
78  frame = channel.get_next_image_frame()
79  if frame:
80  if color_stream == lms.DataSource.LEFT_RECTIFIED_RAW:
81  point_cloud = lms.create_gray8_pointcloud(frame,
82  args.max_range,
83  lms.DataSource.LEFT_RECTIFIED_RAW,
84  lms.DataSource.LEFT_DISPARITY_RAW)
85 
86  # Convert to numpy array and compute the average depth
87  point_cloud_array = point_cloud.as_raw_array.view(luma_point_type)
88  mean_depth = np.mean(point_cloud_array["z"])
89  print("Mean depth:", mean_depth, "(m)")
90 
91  print("Saving pointcloud for frame id: ", frame.frame_id)
92  lms.write_pointcloud_ply(point_cloud, str(frame.frame_id) + ".ply")
93  else:
94  bgr = lms.create_bgr_image(frame, color_stream)
95  if bgr:
96  point_cloud = lms.create_bgr_pointcloud(frame.get_image(lms.DataSource.LEFT_DISPARITY_RAW),
97  bgr,
98  args.max_range,
99  frame.calibration)
100 
101  # Convert to numpy array and compute the average depth
102  point_cloud_array = point_cloud.as_raw_array.view(color_point_type)
103  mean_depth = np.mean(point_cloud_array["z"])
104  print("Mean depth:", mean_depth, "(m)")
105 
106  print("Saving color pointcloud for frame id: ", frame.frame_id)
107  lms.write_pointcloud_ply(point_cloud, str(frame.frame_id) + ".ply")
108 
109 
110 if __name__ == '__main__':
111  parser = argparse.ArgumentParser("LibMultiSense save image utility")
112  parser.add_argument("-a", "--ip_address", default="10.66.171.21", help="The IPv4 address of the MultiSense.")
113  parser.add_argument("-m", "--mtu", type=int, default=1500, help="The MTU to use to communicate with the camera.")
114  parser.add_argument("-r", "--max-range", type=float, default=50.0, help="The max point cloud range in meters.")
115  parser.add_argument("-c", "--use-color", action="store_true", help="Try to use the aux color image for colorizing")
116  main(parser.parse_args())
multisense::create_bgr_image
std::optional< Image > create_bgr_image(const ImageFrame &frame, const DataSource &output_source)
Convert a YCbCr420 luma + chroma image into a BGR color image.
Definition: utilities.cc:340
multisense::write_pointcloud_ply
MULTISENSE_API bool write_pointcloud_ply(const PointCloud< Color > &point_cloud, const std::filesystem::path &path)
Write a point cloud to a ASCII ply file.
Definition: MultiSenseUtilities.hh:276
point_cloud_utility.main
def main(args)
Definition: point_cloud_utility.py:54


multisense_lib
Author(s):
autogenerated on Thu Apr 17 2025 02:49:09