Closed kapkunal closed 3 years ago
Well, I can only guess you mean https://www.ros.org/. I don't know their build system either. As we are able to build for Windows, Linux, macOS and FreeBSD, I am pretty sure it wouldn't be to difficult for you to convert our 64 lines Makefile for ROS.
Hi,
You can just copy the source files in AdsLib to your workspace and add them as a library to your Cmake. Make sure to include the header files.
Hi,
I've copied the source files and included the directory into the ros packae cmake but I'm getting this error:
/usr/bin/ld: CMakeFiles/bk_example.dir/src/bk_example.cpp.o: in function
NotifyCallback(AmsAddr const, AdsNotificationHeader const, unsigned int)':
bk_example.cpp:(.text+0xc0): undefined reference to operator<<(std::ostream&, AmsNetId const&)' /usr/bin/ld: CMakeFiles/bk_example.dir/src/bk_example.cpp.o: in function
readStateExample(std::ostream&, AdsDevice const&)':
bk_example.cpp:(.text+0xbf1): undefined reference to AdsDevice::GetState() const' /usr/bin/ld: CMakeFiles/bk_example.dir/src/bk_example.cpp.o: in function
runExample(std::ostream&)':
bk_example.cpp:(.text+0xcec): undefined reference to AmsNetId::AmsNetId(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)' /usr/bin/ld: bk_example.cpp:(.text+0xd8d): undefined reference to
AdsDevice::AdsDevice(std::cxx11::basic_string<char, std::char_traitsAdsNotification::AdsNotification(AdsDevice const&, unsigned int, unsigned int, AdsNotificationAttrib const&, void (*)(AmsAddr const*, AdsNotificationHeader const*, unsigned int), unsigned int)': bk_example.cpp:(.text._ZN15AdsNotificationC2ERK9AdsDevicejjRK21AdsNotificationAttribPFvPK7AmsAddrPK21AdsNotificationHeaderjEj[_ZN15AdsNotificationC5ERK9AdsDevicejjRK21AdsNotificationAttribPFvPK7AmsAddrPK21AdsNotificationHeaderjEj]+0x44): undefined reference to
AdsDevice::GetHandle(unsigned int) const'
/usr/bin/ld: bk_example.cpp:(.text._ZN15AdsNotificationC2ERK9AdsDevicejjRK21AdsNotificationAttribPFvPK7AmsAddrPK21AdsNotificationHeaderjEj[_ZN15AdsNotificationC5ERK9AdsDevicejjRK21AdsNotificationAttribPFvPK7AmsAddrPK21AdsNotificationHeaderjEj]+0x6e): undefined reference to AdsDevice::GetHandle(unsigned int, unsigned int, AdsNotificationAttrib const&, void (*)(AmsAddr const*, AdsNotificationHeader const*, unsigned int), unsigned int) const' /usr/bin/ld: CMakeFiles/bk_example.dir/src/bk_example.cpp.o: in function
AdsVariableAdsDevice::GetHandle(unsigned int) const' /usr/bin/ld: CMakeFiles/bk_example.dir/src/bk_example.cpp.o: in function
AdsVariableAdsVariable<std::array<unsigned char, 4ul> >::AdsVariable(AdsDevice const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)': bk_example.cpp:(.text._ZN11AdsVariableISt5arrayIhLm4EEEC2ERK9AdsDeviceRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN11AdsVariableISt5arrayIhLm4EEEC5ERK9AdsDeviceRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x54): undefined reference to
AdsDevice::GetHandle(std::__cxx11::basic_string<char, std::char_traitsAdsVariable<unsigned char>::Read(unsigned long, void*) const': bk_example.cpp:(.text._ZNK11AdsVariableIhE4ReadEmPv[_ZNK11AdsVariableIhE4ReadEmPv]+0x69): undefined reference to
AdsDevice::ReadReqEx2(unsigned int, unsigned int, unsigned long, void, unsigned int) const'
/usr/bin/ld: CMakeFiles/bk_example.dir/src/bk_example.cpp.o: in function AdsVariable<unsigned char>::Write(unsigned long, void const*) const': bk_example.cpp:(.text._ZNK11AdsVariableIhE5WriteEmPKv[_ZNK11AdsVariableIhE5WriteEmPKv]+0x4c): undefined reference to
AdsDevice::WriteReqEx(unsigned int, unsigned int, unsigned long, void const) const'
/usr/bin/ld: CMakeFiles/bk_example.dir/src/bk_example.cpp.o: in function `AdsVariable<std::array<unsigned char, 4ul> >::Write(unsigned long, void const) const':
bk_example.cpp:(.text._ZNK11AdsVariableISt5arrayIhLm4EEE5WriteEmPKv[_ZNK11AdsVariableISt5arrayIhLm4EEE5WriteEmPKv]+0x4c): undefined reference to AdsDevice::WriteReqEx(unsigned int, unsigned int, unsigned long, void const*) const' /usr/bin/ld: CMakeFiles/bk_example.dir/src/bk_example.cpp.o: in function
AdsVariable<std::array<unsigned char, 4ul> >::Read(unsigned long, void) const':
bk_example.cpp:(.text._ZNK11AdsVariableISt5arrayIhLm4EEE4ReadEmPv[_ZNK11AdsVariableISt5arrayIhLm4EEE4ReadEmPv]+0x69): undefined reference to `AdsDevice::ReadReqEx2(unsigned int, unsigned int, unsigned long, void, unsigned int*) const'
collect2: error: ld returned 1 exit status
make[2]: [beckhoff_ros/CMakeFiles/bk_example.dir/build.make:281: /home/amire/catkin_ws/devel/lib/beckhoff_ros/bk_example] Error 1
make[1]: [CMakeFiles/Makefile2:4138: beckhoff_ros/CMakeFiles/bk_example.dir/all] Error 2
make: *** [Makefile:141: all] Error 2
Invoking "make -j8 -l8" failed
`
@roboticswithamir That's pretty hard to read. Do you build the AdsLib before and link it correctly in your CMakeFiles?
Wow it’s been a while! I had it working. If I could find my code, I will respond. It was very straight forward except configuring cmakelist
Hey @jstiefel and @kapkunal. So this is the main code which is just a modified version of ADS example.cpp:
#include <ros/ros.h>
#include <std_msgs/String.h>
#include "AdsLib.h"
#include "AdsNotificationOOI.h"
#include "AdsVariable.h"
#include <array>
#include <cstring>
#include <iostream>
#include <iomanip>
using ExampleDatatype = uint8_t;
static ros::Publisher ads_publisher;
static void NotifyCallback(const AmsAddr* pAddr, const AdsNotificationHeader* pNotification, uint32_t hUser)
{
ExampleDatatype data{};
std::memcpy(&data, pNotification + 1, std::min<size_t>(sizeof(data), pNotification->cbSampleSize));
std::cout << std::setfill('0') <<
"NetId: " << pAddr->netId <<
" hUser 0x" << std::hex << hUser <<
" sample time: " << std::dec << pNotification->nTimeStamp <<
" sample size: " << std::dec << pNotification->cbSampleSize <<
" value:" << " 0x" << std::hex << +data <<
'\n';
}
static void notificationExample(std::ostream& out, const AdsDevice& route)
{
const AdsNotificationAttrib attrib = {
sizeof(ExampleDatatype),
ADSTRANS_SERVERCYCLE,
0,
{4000000}
};
AdsNotification notification { route, 0x4020, 4, attrib, &NotifyCallback, 0xDEADBEEF };
out << "Hit ENTER to stop notifications\n";
std::cin.ignore();
}
static void notificationByNameExample(std::ostream& out, const AdsDevice& route)
{
const AdsNotificationAttrib attrib = {
sizeof(ExampleDatatype),
ADSTRANS_SERVERCYCLE,
0,
{4000000}
};
out << __FUNCTION__ << "():\n";
AdsNotification notification { route, "MAIN.byByte[4]", attrib, &NotifyCallback, 0xBEEFDEAD };
out << "Hit ENTER to stop by name notifications\n";
std::cin.ignore();
}
static void readExample(std::ostream& out, const AdsDevice& route)
{
AdsVariable<uint8_t> readVar {route, 0x4020, 0};
out << __FUNCTION__ << "():\n";
for (size_t i = 0; i < 8; ++i) {
out << "ADS read " << std::hex << (uint32_t)readVar << '\n';
}
}
static void readByNameExample(std::ostream& out, const AdsDevice& route)
{
AdsVariable<uint8_t> readVar {route, "MAIN.byByte[4]"};
out << __FUNCTION__ << "():\n";
for (size_t i = 0; i < 8; ++i) {
out << "ADS read " << std::hex << (uint32_t)readVar << '\n';
}
}
static void readWriteExample(std::ostream& out, const AdsDevice& route)
{
AdsVariable<uint8_t> simpleVar {route, "MAIN.byByte[0]"};
AdsVariable<uint8_t> validation {route, "MAIN.byByte[0]"};
out << __FUNCTION__ << "():\n";
simpleVar = 0xA5;
out << "Wrote " << 0xA5 << " to MAIN.byByte and read " << (uint32_t)validation << " back\n";
simpleVar = 0x5A;
out << "Wrote " << (uint32_t)simpleVar << " to MAIN.byByte and read " << (uint32_t)validation << " back\n";
}
static void readWriteArrayExample(std::ostream& out, const AdsDevice& route)
{
static const std::array<uint8_t, 4> arrayToWrite = { 1, 2, 3, 4 };
AdsVariable<std::array<uint8_t, 4> > arrayVar {route, "MAIN.byByte"};
arrayVar = arrayToWrite;
std::array<uint8_t, 4> readArray = arrayVar;
out << "Wrote array with first value " << (uint32_t)arrayToWrite[0] << " and last value " <<
(uint32_t)arrayToWrite[3] << "\n";
out << "Read back array with first value " << (uint32_t)readArray[0] << " and last value " <<
(uint32_t)readArray[3] << "\n";
}
static void readStateExample(std::ostream& out, const AdsDevice& route)
{
const auto state = route.GetState();
out << "ADS state: " << std::dec << (uint16_t)state.ads << " devState: " << std::dec << (uint16_t)state.device <<
'\n';
}
static void runExample(std::ostream& out)
{
static const AmsNetId remoteNetId { 192, 168, 0, 231, 1, 1 };
static const char remoteIpV4[] = "ads-server";
// uncomment and adjust if automatic AmsNetId deduction is not working as expected
//bhf::ads::SetLocalAddress({192, 168, 0, 1, 1, 1});
AdsDevice route {remoteIpV4, remoteNetId, AMSPORT_R0_PLC_TC3};
notificationExample(out, route);
notificationByNameExample(out, route);
readExample(out, route);
readByNameExample(out, route);
readWriteExample(out, route);
readWriteArrayExample(out, route);
readStateExample(out, route);
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "ros_ads_node");
ros::NodeHandle nh;
ads_publisher = nh.advertise<std_msgs::String>("ads_data", 1000);
try
{
runExample(std::cout);
}
catch (const AdsException& ex)
{
std::cout << "Error: " << ex.errorCode << "\n";
std::cout << "AdsException message: " << ex.what() << "\n";
}
catch (const std::runtime_error& ex)
{
std::cout << ex.what() << '\n';
}
std::cout << "Hit ENTER to continue\n";
std::cin.ignore();
ros::spin();
return 0;
}
And this is the CMakeLists.txt:
cmake_minimum_required(VERSION 3.0.2)
project(beckhoff_ros)
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs tf image_transport)
find_package(cv_bridge REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(OpenCV REQUIRED)
find_package(message_generation REQUIRED)
find_package(genmsg REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(Threads)
message(STATUS "OpenCV Include Directory: ${OpenCV_INCLUDE_DIRS}")
# Message Declaration #
generate_messages(DEPENDENCIES std_msgs geometry_msgs sensor_msgs)
add_library(AdsLib ADS/AdsLib/AdsLib.cpp)
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES bebop_ros
# CATKIN_DEPENDS roscpp rospy std_msgs
# DEPENDS system_lib
)
include_directories(
include
${catkin_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS}
/home/amire/catkin_ws/src/beckhoff_ros/ADS/
/home/amire/catkin_ws/src/beckhoff_ros/ADS/AdsLib
/usr/local/include
../AdsLib/
)
add_executable(bk_example src/bk_example.cpp)
target_link_libraries(bk_example ${catkin_LIBRARIES})
target_link_libraries(bk_example ${cv_bridge_LIBRARIES})
target_link_libraries(bk_example ${OpenCV_LIBS})
target_link_libraries(bk_example AdsLib)
And I'm getting this error now:
/usr/bin/ld: CMakeFiles/bk_example.dir/src/bk_example.cpp.o: in function
NotifyCallback(AmsAddr const, AdsNotificationHeader const, unsigned int)':
bk_example.cpp:(.text+0xc0): undefined reference to operator<<(std::ostream&, AmsNetId const&)' collect2: error: ld returned 1 exit status make[2]: *** [beckhoff_ros/CMakeFiles/bk_example.dir/build.make:281: /home/amire/catkin_ws/devel/lib/beckhoff_ros/bk_example] Error 1 make[1]: *** [CMakeFiles/Makefile2:4681: beckhoff_ros/CMakeFiles/bk_example.dir/all] Error 2 make[1]: *** Waiting for unfinished jobs.... [ 98%] Linking CXX executable /home/amire/catkin_ws/devel/lib/ros_ads_node/ros_ads_node [100%] Built target ros_ads_node make: *** [Makefile:141: all] Error 2 Invoking "make -j8 -l8" failed
I know people have already published a ROS package for ADS over #165 . But I was wondering what's the routine way to integrate the AMS cmake files inot my own on ROS?
I think you missed to add the corresponding files. You get some undefined references, which are not related to ROS. Try to include the other classes as well - they are necessary, e.g.: AdsDevice.cpp
, AdsVariable.cpp
, etc.
I created a catkin package some years ago which pulls and installs the AdsLib at the correct location in your workspace. However, ADS was restructured in the meantime. If you want to use the latest version of ADS, you would need to adapt it. If you do, please create a PR :-): https://github.com/ethz-msrl/ads_catkin
Thanks a lot Julian! I forked your repo and made some changes and it's working now. The PR has also been created. One thing remains mystery though, in your wrapper you used the following GIT_TAG:
download_project(
PROJ ads
PREFIX ${CATKIN_DEVEL_PREFIX}/ads
GIT_REPOSITORY https://github.com/Beckhoff/ADS.git
GIT_TAG 6b3a03009a757cf651fe44d8be7b6df698028f0e
# GIT_TAG master
)
However, I checked all Beckhoff releases and this repo doesn't exist anymore. So, how is it still able to grab and clone the repo with the old GIT_TAG?
Thanks a lot Julian! I forked your repo and made some changes and it's working now. The PR has also been created. One thing remains mystery though, in your wrapper you used the following GIT_TAG:
download_project( PROJ ads PREFIX ${CATKIN_DEVEL_PREFIX}/ads GIT_REPOSITORY https://github.com/Beckhoff/ADS.git GIT_TAG 6b3a03009a757cf651fe44d8be7b6df698028f0e # GIT_TAG master )
However, I checked all Beckhoff releases and this repo doesn't exist anymore. So, how is it still able to grab and clone the repo with the old GIT_TAG?
Happy to help and thanks for the PR. The GIT_TAG is just referencing the latest commit that was available at that time. It was probably not a release: https://github.com/Beckhoff/ADS/tree/6b3a03009a757cf651fe44d8be7b6df698028f0e
Hi, I am not very much familiar with either ROS or ADS. We need to have a ROS node talking to Beckhoff over ADS. I am guessing ROS build system is a bit different. How can I port this library to ROS?