Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Post-Release merge 'noetic-devel' into 'main' #33

Merged
merged 3 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
Changelog for package camera_aravis
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

4.1.0 (2024-03-12)
------------------
* Feature: Export GenICam XML (`#32 <https://github.com/FraunhoferIOSB/camera_aravis/issues/32>`_)
* Added node export_genicam_xml
* Updated Readme
* Contributors: Boitumelo Ruf

4.0.5 (2024-02-01)
------------------
* Added launch parameters allowing to manually set white balance
Expand Down
8 changes: 7 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ add_executable(cam_aravis
target_link_libraries(cam_aravis ${PROJECT_NAME} ${LIBRARIES})
add_dependencies(cam_aravis ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

add_executable(export_genicam_xml
src/export_genicam_xml_node.cpp
)
target_link_libraries(export_genicam_xml ${PROJECT_NAME} ${LIBRARIES})
add_dependencies(export_genicam_xml ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h"
Expand All @@ -109,7 +115,7 @@ install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
)

install(TARGETS cam_aravis
install(TARGETS cam_aravis export_genicam_xml
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

Expand Down
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ set initial values for the camera by setting ROS parameters in the camera's name
In addition to the above features, this driver now supports (almost) every feature of every camera,
you just have to know how the feature is specified; each GenICam-based camera contains
an XML file onboard, and by viewing this file you can determine which ROS parameters to set
for camera_aravis to write to the camera. You can use arv-tool-0.2 to see the feature list
and the XML file (e.g. "arv-tool-0.2 --name=Basler-21285878 features")
for camera_aravis to write to the camera. Details on how to export the camera-specific XML can be found here: [Extracting Camera-Specific GenICam XML](#extracting-camera-specific-genicam-xml).

Note that for this special feature access, the ROS parameter type must match the feature type.
For example, a Basler ac640 has a boolean feature called "GammaEnable", an integer feature
Expand Down Expand Up @@ -240,6 +239,29 @@ time in order for the camera to be properly disconnected.
The shutdown delay time in secondes can by configured by the parameter ```shutdown_delay_s```,
default: 5 seconds.

## Extracting Camera-Specific GenICam XML

Each camera model has a specific XML data stored inside the device memory which describes the GenICam interface of the camera.
In this XML data the supported features of the camera are documented and can help to configure the camera.
To extract this XML data and write it into a file, camera_aravis provides the node `export_genicam_xml` which can be invoked as shown below:

```bash
rosrun camera_aravis export_genicam_xml _guid:=<camera_guid> _xml_file:=<output_file>
```

If `_guid` is omitted, the XML data will be read from any of the cameras which are connected and found by camera_aravis.
As a `_xml_file`, either a relative or absolute path can be provided in which the XML data is to be saved.
If omitted, the data is saved into a file in the current working directory with the 'guid' as filename.


Alternatively, you can use `aravis-tools` to see the feature list and the XML file:

```
sudo apt install aravis-tools
arv-tool-0.6 --name=<camera_guid> features
arv-tool-0.6 --name=<camera_guid> genicam
```

## Known Issues

### Slow read of white balance and black level values
Expand Down
2 changes: 1 addition & 1 deletion package.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<package format="2">
<name>camera_aravis</name>
<version>4.0.5</version>
<version>4.1.0</version>
<description>camera_aravis: A complete and comfortable GenICam (USB3Vision and GigEVision) based camera driver for ROS (ethernet and usb).</description>

<maintainer email="[email protected]">Boitumelo Ruf, Fraunhofer IOSB</maintainer>
Expand Down
142 changes: 142 additions & 0 deletions src/export_genicam_xml_node.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/****************************************************************************
*
* camera_aravis
*
* Copyright © 2024 Fraunhofer IOSB and contributors
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
****************************************************************************/

extern "C" {
#include <arv.h>
}

#include <fstream>

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>

#include <ros/ros.h>

int main(int argc, char** argv)
{
ros::init(argc, argv, "export_genicam_xml");

/// private node handle
ros::NodeHandle pnh("~");

/// GUID of the camera for which the xml is to be exported.
std::string guid = pnh.param<std::string>("guid", "");

/// Path string of output xml file.
std::string xmlFileStr = pnh.param<std::string>("xml_file", "");

//--- Print out some useful info.
ROS_INFO("Attached cameras:");
arv_update_device_list();
uint n_interfaces = arv_get_n_interfaces();
ROS_INFO("# Interfaces: %d", n_interfaces);

uint n_devices = arv_get_n_devices();
ROS_INFO("# Devices: %d", n_devices);
for (uint i = 0; i < n_devices; i++)
ROS_INFO("Device%d: %s", i, arv_get_device_id(i));

if (n_devices == 0)
{
ROS_ERROR("No cameras detected.");
return -1;
}

//--- Open the camera.
ArvCamera *p_camera = nullptr;
while (!p_camera)
{
if (guid.empty())
{
ROS_INFO("Opening: (any)");
p_camera = arv_camera_new(NULL);
}
else
{
ROS_INFO("Opening: %s", guid.c_str());
p_camera = arv_camera_new(guid.c_str());
}
ros::Duration(1.0).sleep();
}

//--- get device
ArvDevice *p_device = arv_camera_get_device(p_camera);
const char* vendor_name = arv_camera_get_vendor_name(p_camera);
const char* model_name = arv_camera_get_model_name(p_camera);
const char* device_id = arv_camera_get_device_id(p_camera);
const char* device_sn = arv_device_get_string_feature_value(p_device, "DeviceSerialNumber");
ROS_INFO("Successfully Opened: %s-%s-%s", vendor_name, model_name,
(device_sn) ? device_sn : device_id);

//--- if xmlFileStr is empty construct relative path from guid

/// Path of output xml file.
boost::filesystem::path xmlFilePath;
if(xmlFileStr.empty())
{
std::string tmpFileName = "";
if(guid.empty())
{
tmpFileName += std::string(vendor_name);
tmpFileName += "-" + std::string(model_name);
tmpFileName += "-" + std::string((device_sn) ? device_sn : device_id);
}
else
{
tmpFileName = guid;
}

xmlFilePath = boost::filesystem::path(tmpFileName + ".xml");
}
else
{
xmlFilePath = boost::filesystem::path(xmlFileStr);
}

//--- make path absolute
xmlFilePath = boost::filesystem::absolute(xmlFilePath);

//--- print warning if file already exists
if(boost::filesystem::exists(xmlFilePath))
ROS_WARN("Output file already exists and will be overwritten. Path: %s",
boost::filesystem::canonical(xmlFilePath).c_str());

//--- make parent directory if not existing
if(!xmlFilePath.parent_path().empty())
boost::filesystem::create_directories(xmlFilePath.parent_path());

//--- extract and save XML
size_t xmlSize = 0;
const char* p_xmldata = arv_device_get_genicam_xml(p_device, &xmlSize);
std::ofstream fout;
fout.open(xmlFilePath.c_str(), std::ios::binary | std::ios::out);
fout.write(p_xmldata, xmlSize);
fout.close();

ROS_INFO("Written GenICam XML to file: %s", boost::filesystem::canonical(xmlFilePath).c_str());

//--- release camera
g_object_unref(p_camera);

return 0;
}
Loading