ifm3d - Command Line Tool

Overview

ifm3d ships with a command line tool of the same name. The ifm3d command line tool is used to both introspect the state of a camera as well as mutate parameters. To carry out a particular task, you evoke one of the ifm3d subcommands. To get a listing of available subcommands, you can pass the --help option.

$ ifm3d --help
ifm3d: version=0.20.0


Usage:
  ifm3d [<global options>] <command> [<args>]

 global options:
  -h, --help             Produce this help message and exit
      --ip arg           IP address of the sensor (default: 192.168.0.69)
      --xmlrpc-port arg  XMLRPC port of the sensor (default: 80)
      --password arg     Password for establishing an edit-session with the
                         sensor (default: )

These are common commands used in various situations:

    app-types     List the application types supported by the sensor.

    config        Configure sensor settings from a JSON description of
                  the desired sensor state. See also `dump'.

    cp            Create a new application on the sensor,
                  bootstrapped from a copy of an existing one.

    discover      Discover ifm devices on the network.

    dump          Serialize the sensor state to JSON.

    export        Export an application or whole sensor configuration
                  into a format compatible with ifm Vision Assistant.

    hz            Compute the actual frequency at which the FrameGrabber
                  is running.

    imager-types  List the imager types supported by the sensor.

    import        Import an application or whole sensor configuration
                  that is compatible with ifm Vision Assistant's export
                  format.

    jitter        Collects statistics on framegrabber (and optionally, image
                  construction) jitter.

    ls            Lists the applications currently installed on
                  the sensor.

    passwd        Sets the password on the sensor.

    reboot        Reboot the sensor, potentially into recovery
                  mode (no recovery mode for O3R).
                  Recovery mode is useful for putting the
                  sensor into a state where it can be flashed
                  with new firmware.

    reset         Reset the sensor to factory defaults.

    rm            Deletes an application from the sensor.

    schema        Construct and analyze image acquisition schema masks.

    swupdate      Perform a firmware update on the camera. Please ensure
                  that the camera is booted to recovery beforehand.

    time          Get/set the current time on the camera.

    trace         Get trace messages from the internal camera trace buffer.

For bug reports, please see:
https://github.com/ifm/ifm3d/issues

As it is reported in the help output above, the ifm3d command line program accepts 1) a set of global arguments which control the particular platform you wish to communicate with; 2) a subcommand; and 3) arguments to the subcommand. To get a listing of the particular arguments accepted by a subcommand, you can pass the --help option to the subcommand. For exemplary purposes, let’s list the options accepted by the cp subcommand.

$ ifm3d cp --help
Usage:
  ifm3d [<global options>] cp [<cp options>]

 global options:
  -h, --help             Produce this help message and exit
      --ip arg           IP address of the sensor (default: 192.168.0.69)
      --xmlrpc-port arg  XMLRPC port of the sensor (default: 80)
      --password arg     Password for establishing an edit-session with the
                         sensor (default: )

 cp options:
      --index arg  Index of source application to copy (default: -1)

As is shown above, cp takes a source application index to copy from. Note that the concept of applications is deprecated for the O3R platform.

We now walk through a couple of simple examples of using ifm3d. This is not an exhaustive tutorial on ifm3d but rather intended to give a sense of how to use the tool. The concepts apply broadly to all of the subcommands.

Camera and Imager Configuration

Configuring the parameters of an ifm 3D camera is accomplished in ifm3d in one of two ways: 1) via the ifm3d command line tool; 2) via the ifm3d library’s camera module API. We show below how to do so with the command line tool. Please refer to this doc for instructions on configuring the camera through ifm3d library.

The primary mechanism for using the ifm3d command line tool to configure an ifm 3D camera is to utilize the dump and config subcommands to ifm3d. The dump command serializes the camera state to JSON and prints it to stdout, while the config subcommand consumes (either from a file or stdin) the same JSON serialization but interprets that JSON as a desired state for the camera. Said another way, ifm3d config will make a best effort attempt to have the actual camera hardware reflect the camera state encoded in the JSON stream passed to it.

The remainder of this document will contain a set of examples and associated narrative in hopes of demonstrating how to leverage ifm3d to configure your 3D camera. For purposes of this document, an ifm O3D303 will be utilized. However, the techniques shown here apply to any supported ifm3d camera (for example, the O3X). Additionally, since the camera state is serialized via JSON, some of the examples below will utilize the jq command line JSON processor to build up Linux pipelines to carry out a specific task. The usage of jq is not required. Standard Linux tools (grep, sed, awk, perl, python, etc.) could also be used or a single pipeline can be decomposed into multiple commands whereby data are serialized to a file, edited, then I/O redirected into ifm3d config in discrete steps. Again, the remainder of this document will assume jq is available. (To install jq on Ubuntu: sudo apt-get install jq).

Dump

Serializing the current state of the camera is accomplished through the ifm3d dump command. Exemplary output is shown below:

$ ifm3d dump
{
  "ifm3d": {
    "Apps": [
      {
        "Description": "",
        "Id": "476707713",
        "Imager": {
          "AutoExposureMaxExposureTime": "10000",
          "AutoExposureReferencePointX": "88",
          "AutoExposureReferencePointY": "66",
          "AutoExposureReferenceROI": "{\"ROIs\":[{\"id\":0,\"group\":0,\"type\":\"Rect\",\"width\":130,\"height\":100,\"angle\":0,\"center_x\":88,\"center_y\":66}]}",
          "AutoExposureReferenceType": "0",
          "Channel": "0",
          "ClippingBottom": "131",
          "ClippingCuboid": "{\"XMin\": -3.402823e+38, \"XMax\": 3.402823e+38, \"YMin\": -3.402823e+38, \"YMax\": 3.402823e+38, \"ZMin\": -3.402823e+38, \"ZMax\": 3.402823e+38}",
          "ClippingLeft": "0",
          "ClippingRight": "175",
          "ClippingTop": "0",
          "ContinuousAutoExposure": "false",
          "EnableAmplitudeCorrection": "true",
          "EnableFastFrequency": "false",
          "EnableFilterAmplitudeImage": "true",
          "EnableFilterDistanceImage": "true",
          "EnableRectificationAmplitudeImage": "false",
          "EnableRectificationDistanceImage": "false",
          "ExposureTime": "5000",
          "ExposureTimeList": "125;5000",
          "ExposureTimeRatio": "40",
          "FrameRate": "5",
          "MaxAllowedLEDFrameRate": "23.2",
          "MinimumAmplitude": "42",
          "Resolution": "0",
          "SpatialFilter": {},
          "SpatialFilterType": "0",
          "SymmetryThreshold": "0.4",
          "TemporalFilter": {},
          "TemporalFilterType": "0",
          "ThreeFreqMax2FLineDistPercentage": "80",
          "ThreeFreqMax3FLineDistPercentage": "80",
          "TwoFreqMaxLineDistPercentage": "80",
          "Type": "under5m_moderate",
          "UseSimpleBinning": "false"
        },
        "Index": "1",
        "LogicGraph": "{\"IOMap\": {\"OUT1\": \"RFT\",\"OUT2\": \"AQUFIN\"},\"blocks\": {\"B00001\": {\"pos\": {\"x\": 200,\"y\": 200},\"properties\": {},\"type\": \"PIN_EVENT_IMAGE_ACQUISITION_FINISHED\"},\"B00002\": {\"pos\": {\"x\": 200,\"y\": 75},\"properties\": {},\"type\": \"PIN_EVENT_READY_FOR_TRIGGER\"},\"B00003\": {\"pos\": {\"x\": 600,\"y\": 75},\"properties\": {\"pulse_duration\": 0},\"type\": \"DIGITAL_OUT1\"},\"B00005\": {\"pos\": {\"x\": 600,\"y\": 200},\"properties\": {\"pulse_duration\": 0},\"type\": \"DIGITAL_OUT2\"}},\"connectors\": {\"C00000\": {\"dst\": \"B00003\",\"dstEP\": 0,\"src\": \"B00002\",\"srcEP\": 0},\"C00001\": {\"dst\": \"B00005\",\"dstEP\": 0,\"src\": \"B00001\",\"srcEP\": 0}}}",
        "Name": "Sample Application",
        "PcicEipResultSchema": "{ \"layouter\": \"flexible\", \"format\": { \"dataencoding\": \"binary\", \"order\": \"big\" }, \"elements\" : [ { \"type\": \"string\", \"value\": \"star\", \"id\": \"start_string\" }, { \"type\": \"records\", \"id\": \"models\", \"elements\": [ { \"type\": \"int16\", \"id\": \"boxFound\" }, { \"type\": \"int16\", \"id\": \"width\", \"format\": { \"scale\": 1000 } }, { \"type\": \"int16\", \"id\": \"height\", \"format\": { \"scale\": 1000 } }, { \"type\": \"int16\", \"id\": \"length\", \"format\": { \"scale\": 1000 } }, { \"type\": \"int16\", \"id\": \"xMidTop\", \"format\": { \"scale\": 1000 } }, { \"type\": \"int16\", \"id\": \"yMidTop\", \"format\": { \"scale\": 1000 } }, { \"type\": \"int16\", \"id\": \"zMidTop\", \"format\": { \"scale\": 1000 } }, { \"type\": \"int16\", \"id\": \"yawAngle\" }, { \"type\": \"int16\", \"id\": \"qualityLength\" }, { \"type\": \"int16\", \"id\": \"qualityWidth\" }, { \"type\": \"int16\", \"id\": \"qualityHeight\" } ] }, { \"type\": \"string\", \"value\": \"stop\", \"id\": \"end_string\" } ] }",
        "PcicPnioResultSchema": "{\"layouter\" : \"flexible\", \"format\": { \"dataencoding\": \"binary\", \"order\": \"big\" }, \"elements\" : [ { \"type\": \"string\", \"value\": \"star\", \"id\": \"start_string\" }, { \"type\": \"records\", \"id\": \"models\", \"elements\": [ { \"type\": \"int16\", \"id\": \"boxFound\" }, { \"type\": \"int16\", \"id\": \"width\", \"format\": { \"scale\": 1000 } }, { \"type\": \"int16\", \"id\": \"height\", \"format\": { \"scale\": 1000 } }, { \"type\": \"int16\", \"id\": \"length\", \"format\": { \"scale\": 1000 } }, { \"type\": \"int16\", \"id\": \"xMidTop\", \"format\": { \"scale\": 1000 } }, { \"type\": \"int16\", \"id\": \"yMidTop\", \"format\": { \"scale\": 1000 } }, { \"type\": \"int16\", \"id\": \"zMidTop\", \"format\": { \"scale\": 1000 } }, { \"type\": \"int16\", \"id\": \"yawAngle\" }, { \"type\": \"int16\", \"id\": \"qualityLength\" }, { \"type\": \"int16\", \"id\": \"qualityWidth\" }, { \"type\": \"int16\", \"id\": \"qualityHeight\" } ] }, { \"type\": \"string\", \"value\": \"stop\", \"id\": \"end_string\" } ] }",
        "PcicTcpResultSchema": "{ \"layouter\": \"flexible\", \"format\": { \"dataencoding\": \"ascii\" }, \"elements\": [ { \"type\": \"string\", \"value\": \"star\", \"id\": \"start_string\" }, { \"type\": \"blob\", \"id\": \"normalized_amplitude_image\" }, { \"type\": \"blob\", \"id\": \"distance_image\" }, { \"type\": \"blob\", \"id\": \"x_image\" }, { \"type\": \"blob\", \"id\": \"y_image\" }, { \"type\": \"blob\", \"id\": \"z_image\" }, { \"type\": \"blob\", \"id\": \"confidence_image\" }, { \"type\": \"blob\", \"id\": \"diagnostic_data\" }, { \"type\": \"string\", \"value\": \"stop\", \"id\": \"end_string\" } ] }",
        "TemplateInfo": "",
        "TriggerMode": "1",
        "Type": "Camera"
      }
    ],
    "Device": {
      "ActiveApplication": "1",
      "ArticleNumber": "O3D303",
      "ArticleStatus": "AD",
      "Description": "",
      "DeviceType": "1:2",
      "EnableAcquisitionFinishedPCIC": "false",
      "EthernetFieldBus": "0",
      "EthernetFieldBusEndianness": "0",
      "EvaluationFinishedMinHoldTime": "10",
      "ExtrinsicCalibRotX": "0",
      "ExtrinsicCalibRotY": "0",
      "ExtrinsicCalibRotZ": "0",
      "ExtrinsicCalibTransX": "0",
      "ExtrinsicCalibTransY": "0",
      "ExtrinsicCalibTransZ": "0",
      "IODebouncing": "true",
      "IOExternApplicationSwitch": "0",
      "IOLogicType": "1",
      "IPAddressConfig": "0",
      "ImageTimestampReference": "1520963818",
      "Name": "New sensor",
      "OperatingMode": "0",
      "PNIODeviceName": "",
      "PasswordActivated": "false",
      "PcicProtocolVersion": "3",
      "PcicTcpPort": "50010",
      "SaveRestoreStatsOnApplSwitch": "true",
      "ServiceReportFailedBuffer": "15",
      "ServiceReportPassedBuffer": "15",
      "SessionTimeout": "30",
      "TemperatureFront1": "3276.7",
      "TemperatureFront2": "3276.7",
      "TemperatureIMX6": "40.7179985046387",
      "TemperatureIllu": "47.5",
      "UpTime": "1.61972222222222"
    },
    "Net": {
      "MACAddress": "00:02:01:40:7D:96",
      "NetworkSpeed": "0",
      "StaticIPv4Address": "192.168.0.69",
      "StaticIPv4Gateway": "192.168.0.201",
      "StaticIPv4SubNetMask": "255.255.255.0",
      "UseDHCP": "false"
    },
    "Time": {
      "CurrentTime": "1520963816",
      "NTPServers": "",
      "StartingSynchronization": "false",
      "Stats": "",
      "SynchronizationActivated": "false",
      "Syncing": "false",
      "WaitSyncTries": "2"
    },
    "_": {
      "Date": "Mon May  7 11:55:08 2018",
      "HWInfo": {
        "Connector": "#!02_A300_C40_02452814_008023176",
        "Diagnose": "#!02_D322_C32_03038544_008023267",
        "Frontend": "#!02_F342_C34_17_00049_008023607",
        "Illumination": "#!02_I300_001_03106810_008001175",
        "MACAddress": "00:02:01:40:7D:96",
        "Mainboard": "#!02_M381_003_03181504_008022954",
        "MiraSerial": "0e30-59af-0ef7-0244"
      },
      "SWVersion": {
        "Algorithm_Version": "2.0.45",
        "Calibration_Device": "00:02:01:40:7d:96",
        "Calibration_Version": "0.9.0",
        "Diagnostic_Controller": "v1.0.69-9dbc4ca5ef-dirty",
        "ELDK": "GOLDENEYE_YOCTO/releases%2FO3D%2FRB_1.20.x-7-06d9c894636352a6c93711c7284d02b0c794a527",
        "IFM_Recovery": "unversioned",
        "IFM_Software": "1.20.1138",
        "Linux": "Linux version 3.14.34-rt31-yocto-standard-00009-ge4ab4d94f288-dirty (jenkins@dettlx190) (gcc version 4.9.2 (GCC) ) #1 SMP PREEMPT RT Tue Mar 13 16:06:07 CET 2018",
        "Main_Application": "unknown"
      },
      "ifm3d_version": 900
    }
  }
}

In the example above, we serialize the entire state of the camera. This is useful to, for example, save to a file, edit, and push out to one or more cameras. However, sometimes we need to look at the camera configuration to simply answer a question we may have. For example, if we wanted to see which version of the firmware the camera is running we could issue the following command.

$ ifm3d dump | jq .ifm3d._.SWVersion.IFM_Software
"1.20.1138"

It follows that the entire JSON serialized configuration may be further processed either programmatically or manually via a text editor.

Config

Setting single parameters with ifm3d config

Mutating parameters on the camera is done by creating a desired camera state encoded in JSON compliant to the output produced by ifm3d dump. For example, if we wanted to change the framerate on the camera we could do the following.

  1. Before changing the framerate, let’s see what it is currently set to:

NOTE: This step is not necessary. We do this to illustrate the state of the camera prior to mutating the parameter.

$ ifm3d dump | jq .ifm3d.Apps[0].Imager.FrameRate
"5"

Note: This example shows how to view and change the framerate for the first application instantiated on the O3D camera, and for the camera head connected on port 2 for the O3R platform.

We see the current framerate is 5 fps.

  1. Let’s set it to 10 fps:

$ echo {} | jq '.ifm3d.Apps[0].Imager.FrameRate="10"' | ifm3d config
  1. Let’s check to make sure that our configuration has persisted.

$ ifm3d dump | jq .ifm3d.Apps[0].Imager.FrameRate
"10"

Let’s now break down what we did in this single Linux pipeline.

$ echo {} | jq '.ifm3d.Apps[0].Imager.FrameRate="10"' | ifm3d config

First, we start with an empty string which we fill with the JSON string processed via jq to set the FrameRate to 10 fps. We then pipe the resulting output to ifm3d config which accepts the new JSON stream on stdin and carries out the necessary network calls to mutate the camera settings and persist them.

This is the basic paradigm that can be followed to tune just about any parameter on the camera.

Setting multiple parameters

To carry out more complex configuration tasks (for example changing several parameters at once), the dump can be saved to a file, edited via a text editor, then fed into ifm3d config to perform the configuration.

$ ifm3d dump > settings.json
# Edit the settings.json file
# Save the new settings in new_settings.json
$ ifm3d config < new_settings.json

One can also take advantage of jq’s powerful features to mutate multiple parameters at once. For instance, to copy the configuration from one port to another for the O3R platform, use:

$ ifm3d dump | jq '.ports.port1=.ports.port0' | ifm3d config

Another example for the O3R platforms: set all the 2D ports to RUN mode:

$ ifm3d dump | jq '(.ports[] | select(.info.features.type == "2D") | .state ) = "RUN"' | ifm3d config

In summary, the primary concept in configuring your camera via ifm3d is that the dump subcommand can be used to access the current camera state while the config subcommand is used to declare and mutate the camera into a desired state – assuming the desired state is valid.

Examples

Creating new applications

O3R O3D O3X

Let’s first list the applications on the camera.

$ ifm3d ls
[
  {
    "Active": true,
    "Description": "",
    "Id": 476707713,
    "Index": 1,
    "Name": "Sample Application"
  }
]

Now, let’s create a new application whose settings will be bootstrapped from the application at index 1.

$ ifm3d cp --index=1
$ ifm3d ls
[
  {
    "Active": true,
    "Description": "",
    "Id": 476707713,
    "Index": 1,
    "Name": "Sample Application"
  },
  {
    "Active": false,
    "Description": "",
    "Id": 476707714,
    "Index": 2,
    "Name": "Sample Application"
  }
]

Now, let’s create a new application from scratch (bootstrapped with camera-default settings).

$ echo '{"Apps":[{}]}' | ifm3d config
$ ifm3d ls
[
  {
    "Active": true,
    "Description": "",
    "Id": 476707713,
    "Index": 1,
    "Name": "Sample Application"
  },
  {
    "Active": false,
    "Description": "",
    "Id": 476707714,
    "Index": 2,
    "Name": "Sample Application"
  },
  {
    "Active": false,
    "Description": "",
    "Id": 1755226334,
    "Index": 3,
    "Name": "New application"
  }
]

Now, let’s set the application at index 3 to be the current active application.

$ ifm3d dump | jq '.ifm3d.Device.ActiveApplication="3"' | ifm3d config
$ $ ifm3d ls
[
  {
    "Active": false,
    "Description": "",
    "Id": 476707713,
    "Index": 1,
    "Name": "Sample Application"
  },
  {
    "Active": false,
    "Description": "",
    "Id": 476707714,
    "Index": 2,
    "Name": "Sample Application"
  },
  {
    "Active": true,
    "Description": "",
    "Id": 1755226334,
    "Index": 3,
    "Name": "New application"
  }
]

Now, let’s delete applications 2 and 3.

$ ifm3d rm --index=2
$ ifm3d rm --index=3
$ ifm3d ls
[
  {
    "Active": false,
    "Description": "",
    "Id": 476707713,
    "Index": 1,
    "Name": "Sample Application"
  }
]

We note that based on the sequence of steps we took in this example, we are currently left with a camera with only a single application but it is not marked as active. So, let’s set that application as “active” and validate it.

$ ifm3d dump | jq '.ifm3d.Device.ActiveApplication="1"' | ifm3d config
$ ifm3d ls
[
  {
    "Active": true,
    "Description": "",
    "Id": 476707713,
    "Index": 1,
    "Name": "Sample Application"
  }
]

Setting NTP-Server connection on the camera

O3R O3D O3X

Using jq, you can set easily the NTP-Server on a camera. You just need to provide the right IP address. In this case, the IP: 192.168.0.100 is the NTP server.

ifm3d dump | jq '.ifm3d.Time.NTPServers="192.168.0.100"' | ifm3d config

After that, we need to activate the usage of the NTP server too.

ifm3d dump | jq '.ifm3d.Time.SynchronizationActivated="True"' | ifm3d config

Setting the time on the camera

O3R O3D O3X

To set the time on the camera we use the time subcommand. Let’s look at its usage.

$ ifm3d time --help
Usage:
  ifm3d [<global options>] time [<time options>]

 global options:
  -h, --help             Produce this help message and exit
      --ip arg           IP address of the sensor (default: 192.168.0.69)
      --xmlrpc-port arg  XMLRPC port of the sensor (default: 80)
      --password arg     Password for establishing an edit-session with the
                         sensor (default: )

 time options:
      --epoch arg  Secs since Unix epoch encoding time to be set on camera
                   (-1 == now)

To simply see the current time on the camera, we can issue the time subcommand with no arguments.

$ ifm3d time
Local time on camera is: Tue Mar 13 18:22:16 2018

Let’s now look at our local Unix time:

$ date
Mon May  7 16:20:49 EDT 2018

To synchronize the camera to our local time we can issue the following command.

$ ifm3d time --epoch=-1
Local time on camera is: Mon May  7 16:21:44 2018

And, double checking…

$ ifm3d time
Local time on camera is: Mon May  7 16:22:09 2018