LiquidLens#

/***********************************************************************************
 *
 * Itala API - Copyright (C) 2022 Opto Engineering
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY SUFFERED BY LICENSE AS
 * A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *
 ***********************************************************************************/

/**
 * @example LiquidLens.cpp
 *
 * @brief "LiquidLens" example shows how to control optics
 * with integrated liquid lens technology directly from the device,
 * in both current and power mode. The liquid lens functionality is
 * exposed as a custom set of GenICam features in the device nodemap.
 * WARNING: To avoid additional complexity, the following example
 * doesn't restore the initial liquid lens configuration, just its
 * activation state.
 *
 * @see DefectivePixelCorrection.cpp
 * @see Events.cpp
 */

// Include Itala API
#include "ItalaApi/Itala.h"

// Include the GenICam library
#include "GenICam.h"

#define INDENT "\t"

void LiquidLens_Sample() {
  std::cout << "***** LiquidLens example started. *****" << std::endl << std::endl;

  Itala::ISystem* pSystem = Itala::CreateSystem();
  Itala::DeviceInfoList deviceInfos = pSystem->EnumerateDevices(700);

  if (deviceInfos.size() == 0) throw GENERIC_EXCEPTION("No devices found. Example canceled.");

  if (deviceInfos[0].AccessStatus() != Itala::DeviceAccessStatus::AvailableReadWrite)
    throw GENERIC_EXCEPTION("Target device is unaccessible in RW mode. Example canceled.");

  Itala::IDevice* pDevice = pSystem->CreateDevice(deviceInfos[0]);

  std::cout << "First device initialized." << std::endl;

  // Enable the liquid lens functionality. Keep the original activation state and restore
  // it at the end of the program.
  GenApi::CBooleanPtr pOeLiquidLensEnable = pDevice->GetNodeMap().GetNode("oeLiquidLensEnable");
  if (!IsWritable(pOeLiquidLensEnable))
    throw GENERIC_EXCEPTION("Unable to activate liquid lens functionality. Aborting.");
  bool originalOeLiquidLensEnable = pOeLiquidLensEnable->GetValue();
  pOeLiquidLensEnable->SetValue(true);

  std::cout << "Liquid lens functionality enabled." << std::endl;

  // Gather some information about the connected liquid lens.
  GenApi::CFloatPtr pOeLiquidLensTemperature =
      pDevice->GetNodeMap().GetNode("oeLiquidLensTemperature");
  if (!IsReadable(pOeLiquidLensTemperature))
    throw GENERIC_EXCEPTION("Unable to read liquid lens temperature. Aborting.");

  GenApi::CStringPtr pOeLiquidLensSerialNumber =
      pDevice->GetNodeMap().GetNode("oeLiquidLensSerialNumber");
  if (!IsReadable(pOeLiquidLensSerialNumber))
    throw GENERIC_EXCEPTION("Unable to read liquid lens serial number. Aborting.");

  std::cout << "Connected lens is " << pOeLiquidLensSerialNumber->GetValue() << std::endl;
  std::cout << "Lens temperature: " << pOeLiquidLensTemperature->GetValue() << " C\370" << std::endl
            << std::endl;

  // Liquid lenses can be controlled in current or power mode. In the first case, the
  // input given to the lens is an amount of current which leads to a certain
  // optical power. The second case is the opposite: by specifing the optical power
  // as input, the liquid lens absorbs a certain amount of current.
  // Let's start with current mode.
  GenApi::CEnumerationPtr pOeLiquidLensMode = pDevice->GetNodeMap().GetNode("oeLiquidLensMode");
  if (!IsWritable(pOeLiquidLensEnable))
    throw GENERIC_EXCEPTION("Unable to configure the liquid lens mode. Aborting.");
  pOeLiquidLensMode->FromString("CurrentMode");

  std::cout << INDENT << "Current mode enabled." << std::endl;

  // Define the amount of current to be set in mA.
  double lensCurrent = 10.0f;

  // Write it to the node.
  GenApi::CFloatPtr pOeLiquidLensCurrent = pDevice->GetNodeMap().GetNode("oeLiquidLensCurrent");
  if (!IsWritable(pOeLiquidLensCurrent))
    throw GENERIC_EXCEPTION("Unable to configure the amount of current of the lens. Aborting.");
  pOeLiquidLensCurrent->SetValue(lensCurrent);

  // Read the amount of optical power resulting from the electrical current set.
  GenApi::CFloatPtr pOeLiquidLensResultingPower =
      pDevice->GetNodeMap().GetNode("oeLiquidLensResultingPower");
  if (!IsReadable(pOeLiquidLensResultingPower))
    throw GENERIC_EXCEPTION(
        "Unable to read the resulting amount of power from the lens. Aborting.");

  std::cout << INDENT << "Lens current set to " << lensCurrent << " mA." << std::endl;
  std::cout << INDENT << "Resulting lens power is " << pOeLiquidLensResultingPower->GetValue()
            << " dpt." << std::endl
            << std::endl;

  // Switch to power mode.
  pOeLiquidLensMode->FromString("PowerMode");
  std::cout << INDENT << "Power mode enabled." << std::endl;

  // Define the lens power to be set in dpt.
  double lensPower = 2.0f;

  // Write it to the node.
  GenApi::CFloatPtr pOeLiquidLensPower = pDevice->GetNodeMap().GetNode("oeLiquidLensPower");
  if (!IsWritable(pOeLiquidLensPower))
    throw GENERIC_EXCEPTION("Unable to configure the amount of power of the lens. Aborting.");
  pOeLiquidLensPower->SetValue(lensPower);

  // Read the amount of current resulting from the optical power set.
  GenApi::CFloatPtr pOeLiquidLensResultingCurrent =
      pDevice->GetNodeMap().GetNode("oeLiquidLensResultingCurrent");
  if (!IsReadable(pOeLiquidLensResultingCurrent))
    throw GENERIC_EXCEPTION(
        "Unable to read the resulting amount of current from the lens. Aborting.");

  std::cout << INDENT << "Lens set to " << lensPower << " dpt." << std::endl;
  std::cout << INDENT << "Resulting lens current is " << pOeLiquidLensResultingCurrent->GetValue()
            << " mA." << std::endl
            << std::endl;

  // Restore the original lens activation state.
  pOeLiquidLensEnable->SetValue(originalOeLiquidLensEnable);

  pDevice->Dispose();
  pDevice = nullptr;
  std::cout << "Device instance disposed." << std::endl;

  pSystem->Dispose();
  pSystem = nullptr;
  std::cout << "System instance disposed." << std::endl;
}

int main(int /*argc*/, char** /*argv*/) {
  try {
    LiquidLens_Sample();
  } catch (GenICam::GenericException& e) {
    std::cout << e.what() << std::endl;
  }
}