Esempio n. 1
0
        private static void Main(string[] args)
        {
            // Display the API version to console output for visual confirmation as to
            // the version being used for this example.
            Console.WriteLine($"{nameof(JoeScan.Pinchot)}: {VersionInformation.Version}");

            // Grab the serial number of the scan head from the command line.
            if (args.Length == 0)
            {
                Console.WriteLine("Must provide a scan head serial number as argument.");
                return;
            }

            foreach (var argument in args)
            {
                if (!uint.TryParse(argument, out var scanHeadSerialNumber))
                {
                    Console.WriteLine($"Argument {argument} cannot be parsed as a uint.");
                    return;
                }

                ScanHeadSerialNumbers.Add(scanHeadSerialNumber);
            }

            // First step is to create a scan manager to manage the scan heads.
            _scanSystem = new ScanSystem();

            // Create a scan head for each serial number passed in on the command line
            // and configure each one with the same parameters. Note that there is
            // nothing stopping users from configuring each scan head independently.
            var id = 0U;

            foreach (var serialNumber in ScanHeadSerialNumbers)
            {
                _scanSystem.CreateScanHead(serialNumber, id++);
            }

            var configuration = new ScanHeadConfiguration
            {
                ScanPhaseOffset         = 0,
                LaserDetectionThreshold = 120,
                SaturationThreshold     = 800,
                SaturatedPercentage     = 30
            };

            configuration.SetCameraExposureTime(10000, 47000, 900000);
            configuration.SetLaserOnTime(100, 100, 1000);

            var scanWindow = ScanWindow.CreateScanWindowRectangular(20.0, -20.0, -20.0, 20.0);

            foreach (var scanHead in _scanSystem.ScanHeads)
            {
                scanHead.Configure(configuration);
                scanHead.SetWindow(scanWindow);
                scanHead.SetAlignment(0, 0, 0, ScanHeadOrientation.CableIsUpstream);
            }

            // Now that the scan heads are configured, we'll connect to the heads.
            var scanHeadsThatFailedToConnect = _scanSystem.Connect(TimeSpan.FromSeconds(3));

            foreach (var scanHead in scanHeadsThatFailedToConnect)
            {
                Console.WriteLine($"Failed to connect to scan head {scanHead.SerialNumber}.");
            }

            if (scanHeadsThatFailedToConnect.Count > 0)
            {
                return;
            }

            // Once configured, we can then read the maximum scan rate of the scan
            // system. This rate is governed by the scan head with the lowest scan
            // rate based off window size and exposure values.
            double maxScanRate = _scanSystem.GetMaxScanRate();

            Console.WriteLine($"The system has a maximum scan rate of {maxScanRate}Hz.");

            // To begin scanning on all of the scan heads, all we need to do is
            // command the scan system to start scanning. This will cause all of the
            // scan heads associated with it to begin scanning at the specified rate
            // and data format.
            const double     rate   = 900;
            const DataFormat format = DataFormat.XYFullLMFull;

            _scanSystem.StartScanning(rate, format);

            // In order to achieve a performant application, we'll create a thread
            // for each scan head. This allows the CPU load of reading out profiles
            // to be distributed across all the cores available on the system rather
            // than keeping the heavy lifting in an application within a single process.
            var threads = new List <Thread>();

            foreach (var scanHead in _scanSystem.ScanHeads)
            {
                var thread = new Thread(() => Receiver(scanHead));
                thread.Start();
                threads.Add(thread);
            }

            // Put this thread to sleep until the total scan time is done.
            Thread.Sleep(1000);

            // Calling `ScanSystem.StopScanning()` will return immediately rather than
            // blocking until the scan heads have fully stopped. As a consequence, we
            // will need to add a small delay before the scan heads begin sending
            // new status updates.
            _scanSystem.StopScanning();
            Thread.Sleep(2000);

            // We can verify that we received all of the profiles sent by the scan
            // heads by reading each scan head's status message and summing up the
            // number of profiles that were sent. If everything went well and the
            // CPU load didn't exceed what the system can manage, this value should
            // be equal to the number of profiles we received in this application.
            var expectedProfilesCount = _scanSystem.ScanHeads.Sum(scanHead => scanHead.Status.ProfilesSentCount);

            Console.WriteLine(
                $"Number of profiles received: {_profilesCount}, number of profiles expected: {expectedProfilesCount}");

            // Wait for each thread to terminate before disposing resources.
            foreach (var thread in threads)
            {
                thread.Join();
            }

            // Free resources.
            _scanSystem.Dispose();
        }
Esempio n. 2
0
        private static void Main(string[] args)
        {
            // Display the API version to console output for visual confirmation as to
            // the version being used for this example.
            Console.WriteLine($"{nameof(JoeScan.Pinchot)}: {VersionInformation.Version}");

            // Grab the serial number of the scan head from the command line.
            if (args.Length == 0)
            {
                Console.WriteLine("Must provide a scan head serial number as argument.");
                return;
            }

            if (!uint.TryParse(args[0], out _scanHeadSerialNumber))
            {
                Console.WriteLine($"Argument {args[0]} cannot be parsed as a uint.");
                return;
            }

            // One of the first calls to the API should be to create a scan manager
            // software object. This object will be used to manage groupings of scan
            // heads, telling them when to start and stop scanning.
            _scanSystem = new ScanSystem();

            // Create a scan head software object for the user's specified serial
            // number and associate it with the scan manager we just created. We'll
            // also assign it a user defined ID that can be used within the application
            // as an optional identifier if preferred over the serial number. Note that
            // at this point, we haven't connected with the physical scan head yet.
            var scanHead = _scanSystem.CreateScanHead(_scanHeadSerialNumber, 1);

            // Now that we have successfully created the required software objects
            // needed to interface with the scan head and the scan system it is
            // associated with, we can begin to configure the scan head.

            // Many of the settings directly related to the operation of the cameras
            // and lasers can be found in the `ScanHeadConfiguration` class. Refer
            // to the API documentation for specific details regarding each field. For
            // this example, we'll use some generic values not specifically set for any
            // particular scenario.
            var configuration = new ScanHeadConfiguration
            {
                ScanPhaseOffset         = 0,
                LaserDetectionThreshold = 120,
                SaturationThreshold     = 800,
                SaturatedPercentage     = 30
            };

            configuration.SetCameraExposureTime(10000, 47000, 900000);
            configuration.SetLaserOnTime(100, 100, 1000);
            scanHead.Configure(configuration);

            // Proper window selection can be crucial to successful scanning as it
            // allows users to limit the region of interest for scanning; filtering out
            // other sources of light that could complicate scanning. It is worth
            // noting that there is an inverse relationship with the scan window and
            // the overall scan rate a system can run at. Using larger scan windows
            // will reduce the maximum scan rate of a system, whereas using a smaller
            // scan window will increase the maximum scan rate.
            var scanWindow = ScanWindow.CreateScanWindowRectangular(30.0, -30.0, -30.0, 30.0);

            scanHead.SetWindow(scanWindow);

            // Setting the alignment through the following function can help to
            // correct for any mounting issues with a scan head that could affect
            // the 3D measurement. For this example, we'll assume that the scan head
            // is mounted perfectly such that the laser is pointed directly at the scan
            // target.
            scanHead.SetAlignment(0, 0, 0, ScanHeadOrientation.CableIsUpstream);

            // We've now successfully configured the scan head. Now comes the time to
            // connect to the physical scanner and transmit the configuration values
            // we previously set up.
            var scanHeadsThatFailedToConnect = _scanSystem.Connect(TimeSpan.FromSeconds(3));

            if (scanHeadsThatFailedToConnect.Count > 0)
            {
                Console.WriteLine("Failed to connect to scan system.");
                return;
            }

            // Now that we are connected, we can query the scan head to get its
            // current status. Note that the status will be updated periodically by the
            // scan head and calling this function multiple times will provide the
            // last reported status of the scan head.
            PrintScanHeadStatus(scanHead.Status);

            // Once connected, this is the point where we could command the scan system
            // to start scanning; obtaining profile data from the scan heads associated
            // with it. This will be the focus of a later example.

            // We've accomplished what we set out to do for this example; now it's time
            // to bring down our system.
            _scanSystem.Disconnect();

            // Clean up resources allocated by the scan manager.
            _scanSystem.Dispose();
        }
Esempio n. 3
0
        private static void Main(string[] args)
        {
            // Display the API version to console output for visual confirmation as to
            // the version being used for this example.
            Console.WriteLine($"{nameof(JoeScan.Pinchot)}: {VersionInformation.Version}");

            // Grab the serial number of the scan head from the command line.
            if (args.Length == 0)
            {
                Console.WriteLine("Must provide a scan head serial number as argument.");
                return;
            }

            foreach (var argument in args)
            {
                if (!uint.TryParse(argument, out var scanHeadSerialNumber))
                {
                    Console.WriteLine($"Argument {argument} cannot be parsed as a uint.");
                    return;
                }

                ScanHeadSerialNumbers.Add(scanHeadSerialNumber);
            }

            // First step is to create a scan manager to manage the scan heads.
            _scanSystem = new ScanSystem();

            // Create a scan head software object for each serial number passed in
            // through the command line. We'll assign each one a unique ID starting at
            // zero; we'll use this as an easy index for associating profile data with
            // a given scan head.
            var id = 0U;

            foreach (var serialNumber in ScanHeadSerialNumbers)
            {
                _scanSystem.CreateScanHead(serialNumber, id++);
            }

            // For this example application, we'll just use the same configuration
            // settings we made use of in the "Configure and Connect" example. The
            // only real difference here is that we will be applying this configuration
            // to multiple scan heads, using a "for" loop to configure each scan head
            // one after the other.
            var configuration = new ScanHeadConfiguration
            {
                ScanPhaseOffset         = 0,
                LaserDetectionThreshold = 120,
                SaturationThreshold     = 800,
                SaturatedPercentage     = 30
            };

            configuration.SetCameraExposureTime(10000, 47000, 900000);
            configuration.SetLaserOnTime(100, 100, 1000);

            foreach (var scanHead in _scanSystem.ScanHeads)
            {
                scanHead.Configure(configuration);

                // To illustrate that each scan head can be configured independently,
                // we'll alternate between two different windows for each scan head. The
                // other options we will leave the same only for the sake of convenience;
                // these can be independently configured as needed.
                var scanWindow = scanHead.ID % 2 == 0
                    ? ScanWindow.CreateScanWindowRectangular(20.0, -20.0, -20.0, 20.0)
                    : ScanWindow.CreateScanWindowRectangular(30.0, -30.0, -30.0, 30.0);
                scanHead.SetWindow(scanWindow);
                scanHead.SetAlignment(0, 0, 0, ScanHeadOrientation.CableIsUpstream);
            }

            // Now that the scan heads are configured, we'll connect to the heads.
            var scanHeadsThatFailedToConnect = _scanSystem.Connect(TimeSpan.FromSeconds(3));

            foreach (var scanHead in scanHeadsThatFailedToConnect)
            {
                Console.WriteLine($"Failed to connect to scan head {scanHead.SerialNumber}.");
            }

            if (scanHeadsThatFailedToConnect.Count > 0)
            {
                return;
            }

            // Once configured, we can then read the maximum scan rate of the scan
            // system. This rate is governed by the scan head with the lowest scan
            // rate based off window size and exposure values.
            double maxScanRate = _scanSystem.GetMaxScanRate();

            Console.WriteLine($"The system has a maximum scan rate of {maxScanRate}Hz.");

            // To begin scanning on all of the scan heads, all we need to do is
            // command the scan system to start scanning. This will cause all of the
            // scan heads associated with it to begin scanning at the specified rate
            // and data format.
            const double     rate   = 400;
            const DataFormat format = DataFormat.XYFullLMFull;

            _scanSystem.StartScanning(rate, format);

            // We'll read out a small number of profiles for each scan head, servicing
            // each one in a round robin fashion until the requested number of profiles
            // have been obtained.
            const int maxProfiles = 10;
            var       timeout     = TimeSpan.FromSeconds(10);
            var       stopwatch   = Stopwatch.StartNew();
            var       profiles    = _scanSystem.ScanHeads.ToDictionary(scanHead => scanHead, scanHead => new List <Profile>());

            while (profiles.Values.Any(l => l.Count < maxProfiles))
            {
                foreach (var scanHead in _scanSystem.ScanHeads)
                {
                    scanHead.TryTakeNextProfile(out var profile, TimeSpan.FromMilliseconds(100),
                                                new CancellationToken());

                    if (profile is null)
                    {
                        continue;
                    }

                    profiles[scanHead].Add(profile);
                }

                if (stopwatch.Elapsed > timeout)
                {
                    Console.WriteLine($"Timed-out waiting to collect {maxProfiles} profiles.");
                    return;
                }
            }

            // We've collected all of our data; time to stop scanning. Calling this
            // function will cause each scan head within the entire scan system to
            // stop scanning. Once we're done scanning, we'll process the data.
            _scanSystem.StopScanning();
            foreach (var scanHead in _scanSystem.ScanHeads)
            {
                var highestPoint = FindScanProfileHighestPoint(profiles[scanHead]);
                Console.WriteLine($"Highest point from scan head {scanHead.ID} is X: {highestPoint.X:F3}\tY: {highestPoint.Y:F3}\tBrightness: {highestPoint.Brightness}");
            }

            // Free resources.
            _scanSystem.Dispose();
        }