Open adragoset opened 5 years ago
Hi @adragoset,
on ubuntu 16.04 direct IP adressing works normally. Do find out what 18.04 has set differently and as you have the full pylon SDK installed, please check the README in /opt/pylon5. Could you check, if this option from the README helps?
Problem: The IP Configurator can't see my camera. I'm not able to reconfigure the camera to make it visible again.
Solution: First make sure you don't have a firewall enabled on your network interface the camera is connected to. If you still can't see the camera, reverse path filtering in the kernel may prevent the IP Configurator to detect the camera. On some Linux distributions reverse path filtering may prevent the discovery of GigE Vision cameras. This can happen if the camera's IP address is not within the same subnet as the network adapter the camera is attached to. Normally the IP Configurator can handle this by using broadcasts to discover the camera on any subnet. Reverse-path filtering may prevent the IP Configurator to receive the answer from the broadcast which in turn prevents the IP Configurator from detecting the camera. To check whether filtering is turned on, run the following command: sysctl -a 2>/dev/null | grep '.rp_filter'
in the output look for the following lines: net.ipv4.conf.all.rp_filter=1 net.ipv4.conf.eth1.rp_filter=1
where "eth1" is the network adapter the camera is connected to. The "net.ipv4.conf.all.rp_filter" is a global switch which must be turned off. The "net.ipv4.conf.eth1.rp_filter" tells whether filtering for the specified network adapter is activated. To disable filtering, you must first turn off filtering for "all" and the specific network interface (in this sample "eth1"). Use the following commands to change the filtering behavior at runtime: sudo sysctl net.ipv4.conf.all.rp_filter=0 sudo sysctl net.ipv4.conf.eth1.rp_filter=0
Restart the IP Configurator and check whether the camera(s) are detected. Reconfigure the camera(s) and use "Write Configuration" to make your changes persistent. You can re-enable filtering by executing the same commands but set a value of 1. If you want to turn off filtering permanently, you can edit the same values in /etc/sysctl.conf.
From Linux kernel version 2.6.32 onwards, the rp_filter settings allow strict and loose filtering. To accept asymmetrically routed packets, modify /etc/sysctl.conf: net.ipv4.conf.default.rp_filter = 2 net.ipv4.conf.all.rp_filter = 2
FIrewall was disabled entirely. This setup runs out of a docker container with --network=host setting on the container.
I will try those ip settings but im not really convinced this is a linux problem because grabbing works correctly when using the following c++ code in Ubuntu 18.01 or on my Centos 7 machines whereas the above posted code for finding a camera by IP remains broken.
Pylon::PylonInitialize();
TIFactory = &CTlFactory::GetInstance();
CDeviceInfo info;
info.SetSerialNumber(cameraSerial);
std::shared_ptr<CInstantCamera> camera_ptr(new CInstantCamera(TIFactory->CreateFirstDevice(info), Pylon::Cleanup_Delete));
camera = camera_ptr;
camera->Open();
GenApi::INodeMap& nodeMap = camera -> GetNodeMap();
Something specifically about creating the camera by setting the IP on CDeviceInfo breaks grabbing.
These are the values on my centos 7 (3.10.0-957.1.3.el7.x86_64) box for the adapter connected to the cameras network. Ill set these to ) as per above and try again when i have some time to mess with the IP code.
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.enp7s0.rp_filter = 1
I'm wondering if I was running into the same issue.
When connecting to a random device with the pypylon sample code such as grab.py
I was able to capture images. But, when I attempt to attach to a specific IP address using the method described here https://github.com/basler/pypylon/issues/19 I am unable to pull an image.
I seem to have stumbled upon an undocumented way to select a specific device from the CreateFirstDevice
method by passing in an info object. Using this approach, I am able to pull images.
from pypylon import pylon
ip_address = '192.168.1.14'
info = pylon.DeviceInfo()
info.SetPropertyValue('IpAddress', ip_address)
camera = pylon.InstantCamera(pylon.TlFactory.GetInstance().CreateFirstDevice(info))
# now use the camera like in grab.py https://github.com/basler/pypylon/blob/master/samples/grab.py
Maybe this info will be useful for you.
Hey I'm on Ubuntu 19.04 and I found a solution that worked for me:
Go to the internet settings of the ethernet adapter which your GigE camera is connected to and set both the IPv4 and IPv6 methods in their tabs to "local link only" option.
I also did what thiesmoeller said before. That didn't work by itself but it might be necessary along with this step.
Hey I'm on Ubuntu 19.04 and I found a solution that worked for me:
Go to the internet settings of the ethernet adapter which your GigE camera is connected to and set both the IPv4 and IPv6 methods in their tabs to "local link only" option.
I also did what thiesmoeller said before. That didn't work by itself but it might be necessary along with this step.
Thank you! This worked for me. I was really confused because I was able to find the camera on Windows, but not Ubuntu. Camera immediately showed up after I applied this.
I'm having the exact same problem, using ubuntu 18.04. My laptop has a static ip, and the camera has a static ip as well. I'm using the C++ api though. If I instead use the commented out line, it captures fine.
ITransportLayer *pTL = CTlFactory::GetInstance().CreateTl(CBaslerGigEInstantCamera::DeviceClass());
CBaslerGigEDeviceInfo bdi(pTL->CreateDeviceInfo());
bdi.SetIpAddress(ip_address);
CBaslerGigEInstantCamera camera( pTL->CreateDevice( bdi ) );
// CBaslerGigEInstantCamera camera( pTL->CreateFirstDevice());
camera.Open();
camera.StartGrabbing();
camera.RetrieveResult(10, ptrGrabResult, TimeoutHandling_Return);
std::cout << ptrGrabResult << std::endl;
As a workaround, is there a way to list all cameras, and iterate through them, checking their ip addresses for a match? I haven't been able to find a good way to do that either.
Hi @thiesmoeller! I am experiencing the same issue on Ubuntu Server 20.4 LTS. Suppose I connect to a specified IP Address, as my Server and Camera are in totally different subnets. In that case, the destination IP is set to 0.0.0.0.
I have tried out every proposed solution. Unfortunately, I don't even get the camera to be visible. Firewall is disabled (No FW on Network, also ufw on ubuntu is disabled). Here are the same issues which still not been resolved https://github.com/basler/pypylon/issues/132, https://github.com/basler/pypylon/issues/45 and some others. Changing camera.GevSCDA to host doesnot seem to change the interaface of the camera. With camera.GetDeviceInfo().GetInterface() i always get 0.0.0.0.
Everything works fine if I stay in the same subnet as the camera. Also, the interface is detected correctly.
Can you please provide some help on that issue? Thanks!
@maximehyh
If you have a global gIp
that holds the camera IP you are looking for, you can use this utility function I wrote
Pylon::CTlFactory& TlFactory = Pylon::CTlFactory::GetInstance();
// This is a critical step- set the TL to BaslerGigEDevice class otherwise we won't find the cameras with enumerateDevices
Pylon::ITransportLayer *pTl = TlFactory.CreateTl(Pylon::BaslerGigEDeviceClass);
Pylon::DeviceInfoList_t lstDevices;
pTl->EnumerateDevices( lstDevices );
if ( lstDevices.empty() ) {
printf("[BaslerEthernetDriver] No ethernet cameras found :(\n");
}
else
{
for(auto iter = lstDevices.begin(); iter != lstDevices.end(); iter++)
{
auto ipString = (*iter).GetIpAddress();
//Compare the found IP to the one for this configured camera
if(gIp.compare(ipString.c_str()) == 0)
{
gCamera = new Pylon::CInstantCamera(Pylon::CTlFactory::GetInstance().CreateDevice((*iter)));
printf("[BaslerEthernetDriver] camera created! \n");
}
}
}
I will delete my original comment- I made a mistake as to what specific step of my process ended up fixing the problem. It was changing the way I discovered and connected to the GigE device.
@pjmara thanks for your reply. I deleted my original message as my problem actually sits somewhere else. I am trying to get a stream from a Basler camera from within a docker container.
It is working fine if I set network: host
in the docker configuration but I am having issues when trying not to use this network setup and trying to manually expose the UDP ports.
I know that upon connection the camera will negociate a UDP random port with my container and I believe it is possible to set/force this "random" port but did not find how to do it so far.
@maximehyh See https://github.com/basler/pypylon/issues/429
@thiesmoeller thanks for the quick answer. I managed to set the StreamGrabber
port using this method and it is indeed working for the Grabbing part (I can see the port being used in Wireshark). Though it seems that my issue remains.
When using using docker without network: host
, i.e pylon client being on a different network than the camera, it seems that I cannot manage to make the necessary steps to make a persistent
connection to the camera that will then allow me to start the grabbing part (we are getting a No device attached
error when trying to open()
). Looking at Wireshark I am seeing that some other random UDP ports are used while connecting and I am wondering if that could be the issue.
Below are some wireshark screenshot and code snippets that could maybe help you understand our issue.
Question 1: would it be possible to set the port for this pre grabbing/connection process? I am thinking that maybe exposing those/this port on docker could fix the issue.
Question 2: I am seeing that some TCP connection is starting and failing when camera is without network: host
. Maybe some failling step at a lower network level could cause the TCP connection to be tried (as the UDP one failed)?
FYI we did manage to make such a connection using Docker Swarm MacVLAN in the past but we would prefer not to use this network setup this time.
doConnection(const std::vector<std::string> &ip_list)
{
// Cf https://www.baslerweb.com/en/sales-support/knowledge-base/frequently-asked-questions/how-can-i-create-a-gige-camera-device-object-with-a-known-ip-address/14991/
CTlFactory& TIFactory = CTlFactory::GetInstance();
ITransportLayer *pTI = TIFactory.CreateTl( Pylon::CBaslerGigEInstantCamera::DeviceClass() );
try {
for(int i = 0; i < ip_list.size(); ++i) {
CBaslerGigEDeviceInfo bdi( pTI->CreateDeviceInfo() );
bdi.SetIpAddress(ip_list[i].c_str());
Pylon::CBaslerGigEInstantCamera ip_camera( pTI->CreateDevice( bdi ) );
ip_camera.Open();
}
} catch (GenICam_3_1_Basler_pylon_v5_1::RuntimeException &e) {
std::ostringstream oss;
oss << "[BaslerCamera] - " << e.what();
throw std::runtime_error(oss.str());
} catch (GenICam_3_1_Basler_pylon_v5_1::LogicalErrorException &e) {
std::ostringstream oss;
oss << "[BaslerCamera] - " << e.what();
throw std::runtime_error(oss.str());
} catch (GenICam_3_1_Basler_pylon_v5_1::AccessException &e) {
std::ostringstream oss;
oss << "[BaslerCamera] - " << e.what();
throw std::runtime_error(oss.str());
}
}
Result with network: host
:
Without network: host
:
# Error when trying to Open()
terminate called after throwing an instance of 'std::runtime_error'
what(): [BaslerCameraContinuous] - No device attached. : RuntimeException thrown (file 'InstantCameraImpl.h', line 2077)
Thanks!
FYI made a separate issue here: https://github.com/basler/pypylon/issues/481
I'm wondering if I was running into the same issue.
When connecting to a random device with the pypylon sample code such as
grab.py
I was able to capture images. But, when I attempt to attach to a specific IP address using the method described here #19 I am unable to pull an image.I seem to have stumbled upon an undocumented way to select a specific device from the
CreateFirstDevice
method by passing in an info object. Using this approach, I am able to pull images.from pypylon import pylon ip_address = '192.168.1.14' info = pylon.DeviceInfo() info.SetPropertyValue('IpAddress', ip_address) camera = pylon.InstantCamera(pylon.TlFactory.GetInstance().CreateFirstDevice(info)) # now use the camera like in grab.py https://github.com/basler/pypylon/blob/master/samples/grab.py
Maybe this info will be useful for you.
This solves the issue locally but doesn't seem to actually use the camera IP to connect as I'm not able to connect remotely. Using the original script below, I can connect to the camera but the frames are sent to 0.0.0.0. Is there any solution for this yet?
factory = pylon.TlFactory.GetInstance()
ptl = factory.CreateTl('BaslerGigE')
empty_camera_info = ptl.CreateDeviceInfo()
empty_camera_info.SetPropertyValue('IpAddress', ip_address)
camera_device = factory.CreateDevice(empty_camera_info)
camera = pylon.InstantCamera(camera_device)
The CBaslerGigEDeviceInfo, which is also created if we create a device info from the GigE specific Transportlayer, is deprecated alongside with other device specific info objects and camera devices since pylon 6.0 and shouldn't be used anymore. Obviously it has some issues. It's not recommended to use it anymore.
The general CDeviceInfo object works perfectly when creating a camera from a IP address.
I've done some troubleshooting on Ubuntu 18.01 and Centos and I've found that attempting to connect and use a camera by specifying IP is broken and will timeout on RetrieveResult calls. This is true for both the Python and C++ API.
Wireshark session caps show the camera attempting to establish a udp session back to the host on 0.0.0.0:34950 which will not work since 0.0.0.0 isn't a real IP. Netcat on the host reports that the pylon driver opened up port 39450 for that session on the host adapters of which there are several.
192.168.3.209 is the camera. 192.168.3.219 is the host running pylon.
netcat output
udp 0 0 0.0.0.0:34950 0.0.0.0:* 5414/./CalibrationT
I've had to roll all of my code back to grabbing the first device with a matching serial number.
To me it seems like something is being done to detect the interface on the host and that address is being reported incorrectly to the camera so it can never establish a proper udp session for data transfer.
Here is the c++ api code I've been testing with although this is reproducable with pypylon as well.