https://answers.ros.org/question/58498/what-is-the-purpose-of-catkin_depends/
sudo dnf install --skip-broken python-empy console-bridge console-bridge-devel poco-devel boost boost-devel eigen3-devel pyqt4 qt-devel gcc gcc-c++ python-devel sip sip-devel tinyxml tinyxml-devel qt-devel qt5-devel python-qt5-devel sip sip-devel python3-sip python3-sip-devel qconf curl curl-devel gtest gtest-devel lz4-devel urdfdom-devel assimp-devel qhull-devel qhull uuid uuid-devel uuid-c++ uuid-c++-devel libuuid libuuid-devel gazebo gazebo-devel collada-dom collada-dom-devel yaml-cpp yaml-cpp-devel python2-defusedxml python-netifaces pyparsing pydot python-pyqtgraph python2-matplotlib
rqt_plot
breaks due to both PyQt4 and PyQt5- do not use anaconda & pip to install missing packages
https://docs.ros.org/kinetic/api/catkin/html/howto/format1/system_library_dependencies.html
project(my_package_name) # Must match package name defined in package.xml
...
catkin_package(
INCLUDE_DIRS include
LIBRARIES my_library_name # Must match library name defined in add_library(my_library_name ...)
)
...
add_library(my_library_name src/CountedTryFunc.cpp)
add_dependencies(my_library_name ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_include_directories(my_library_name PUBLIC ${PROJECT_SOURCE_DIR}/include)
...
install(
TARGETS
my_library_name
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
https://cmake.org/cmake/help/v3.2/manual/cmake-buildsystem.7.html#interface-libraries http://www.mariobadr.com/creating-a-header-only-library-with-cmake.html https://dominikberner.ch/cmake-interface-lib/
Note that colcon
automatically puts header files from include
into include/${PROJECT_NAME}
,
hence it is recommended to follow the convention for interoperability between colcon
and catkin
include_directories(include)
catkin_package(
INCLUDE_DIRS include
)
add_library(${PROJECT_NAME} INTERFACE)
target_include_directories(${PROJECT_NAME} INTERFACE include)
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION})
include(GNUInstallDirs)
add_library(${PROJECT_NAME} INTERFACE)
target_include_directories(${PROJECT_NAME}
INTERFACE $<BUILD_INTERFACE:${${PROJECT_NAME}_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
ament_export_interfaces(${PROJECT_NAME} HAS_LIBRARY_TARGET)
install(
TARGETS ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(
DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
catkin_make --only-pkg-with-deps pkgs
Only bind relevant topics to relevant functions in the node main
using namespace std::placeholders;
MyClass my_class;
ros::Subscriber sub = n.subscribe("my_topic", std::bind([&](const std_msgs::Int8::ConstPtr& msg){
my_class.my_func(msg->data);
}, _1));
sub = nh.subscribe<MyMessage>("my_topic", 1,
[&](const MyMessage::ConstPtr& message)
{
... *message ...
});
service = nh.advertiseService<std_srvs::Empty::Request, std_srvs::Empty::Response>("my_service",
[&](std_srvs::Empty::Request &req, std_srvs::Empty::Response &res) -> bool
{
...
});
//https://wiki.ros.org/actionlib_tutorials/Tutorials/SimpleActionServer(ExecuteCallbackMethod)
move_base.sendGoal(move_base_goal, [this](const actionlib::SimpleClientGoalState& state, const move_base_msgs::MoveBaseResultConstPtr& result)
{
...
});
Note that an empty capture []
is not allowed and will result in
call of overloaded 'subscribe(const char [20], int, main(int, char**)::<lambda(const ConstPtr&)>)' is ambiguous
catkin_make tests # Build tests only
catkin_make run-tests # Build and run tests only
catkin_make all # All non-tests only
catkin build --catkin-make-args tests # Build tests only
catkin build --catkin-make-args test # Build and run tests
rosrun tf tf_echo /map /base_link
rosrun rqt_tf_tree rqt_tf_tree
In ROS, roll, pitch, yaw are specified w.r.t. the initial frame.
/opt/ros/melodic/include/ros/message_traits.h:126:14: error: ‘const class std::__cxx11::basic_string<char>’ has no member named ‘__getMD5Sum’
return m.__getMD5Sum().c_str();
Occurs when you
std::string msg = "...";
pub.publish(msg);
instead of
std_msgs::String msg;
msg.data = "...";
pub.publish(msg);
<node pkg="rosservice" type="rosservice" name="set_safezone" args="call --wait /set_safezone '{pose: {position: {x: 1.0, y: 0.0, z: 0.5}, orientation: {x: 0.0, y: 0.0, z: 0.0, w: 1.0}}, size: {x: 1.0, y: 1.0, z: 1.0}}'"/>
<node pkg="rosservice" type="rosservice" name="set_move_base_log_level" args="call --wait /move_base/set_logger_level 'ros.move_base' 'debug'" />
Check if function for subscription callback is fully defined, especially parameter type, i.e.
std::function<void(const my_msg_type::SharedPtr)> ...
<class name="my_plugin"
using MyActionServer = actionlib::SimpleActionServer<my::MyAction>;
controller.registerPublishFeedback(
[&](const my::MyFeedback& feedback)
{
action_server.publishFeedback(feedback);
});
Alternative, uglier, std::bind
way
// Because publishFeedback is overloaded
// https://stackoverflow.com/questions/13064698/stdbind-and-overloaded-function
controller.registerPublishFeedback(
std::bind(static_cast<void(MyActionServer::*)(const my::MyFeedback&)>(&MyActionServer::publishFeedback), &action_server, std::placeholders::_1));
controller.registerSetSucceeded(
[&](const my::MyResult& result)
{
action_server.setSucceeded(result);
});
Alternative, uglier, std::bind
way
controller.registerSetSucceeded(
std::bind(&MyActionServer::setSucceeded, &action_server, std::placeholders::_1, ""));
<node pkg="tf2_ros" type="static_transform_publisher" name="my_tf" args="0 0 0 0 0 0 from_link to_link" />
Client:
rosrun actionlib axclient.py
Server:
rosrun actionlib axserver.py
- https://medium.com/@slaterobotics/how-to-implement-ros-control-on-a-custom-robot-748b52751f2e
- https://github.com/ros-controls/ros_control/wiki/hardware_interface
controller_manager::update()
triggers all controllers associated with joints with names registered throughhardware_interface::JointStateInterface
to read from variables registered throughhardware_interface::JointStateInterface
and writes to the variables registered throughhardware_interface::XXXJointInterface
set(ROSLINT_CPP_OPTS "--filter=-legal/copyright,-build/c++11,-whitespace/braces")
roslint_cpp()
set(ROSLINT_PYTHON_OPTS "1>&2") # Redirect stdout to stderr so it gets printed out during build
roslint_python()
roslint_add_test()
stdbuf -oL rostopic hz /my_topic &> output.txt
- Check relevant TF publishers publishing time
- Check relevant
TransformStamped
timestamps - Check relevant TF buffer lookup time
Note that constants defined in the goal section of the .action
file is only accessible from XXXGoal
namespace and not XXXActionGoal
namespace
if __name__ == '__main__':
# Shutdown is handled by Flask
rospy.init_node("payload_rest_interface", disable_signals=True)
app = Flask(__name__)
rospy.loginfo("Creating REST interface...")
interface = PayloadInterface()
executor = ThreadPoolExecutor(max_workers=1)
@app.route('/payload/test', methods=['POST'])
def test():
return Response(status=200, headers={})
@app.route('/payload/execute', methods=['POST'])
def execute():
data = request.get_json()
action_type = data['action_type']
shelf = data['shelf']
location = data['location']
interface.activatePayload(action_type, shelf, location)
executor.submit(interface.wait_and_notify)
return Response(status=200, headers={})
@app.route('/payload/status', methods=['GET'])
def status():
return Response(status=200, headers={})
rospy.loginfo("Starting server...")
app.run(host=interface.host, port=interface.port)
https://answers.ros.org/question/194592/how-to-read-a-vectorstrings-parameter-from-command-line/
- Currently,
JointTrajectoryController
only supportshardware_interface::HW_IF_POSITION
(i.e. position command interface)
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}_msgs
"msg/PointTrajectory.msg"
LIBRARY_NAME ${PROJECT_NAME} # See https://github.com/ros2/rosidl/issues/441#issuecomment-591025515
)
add_library(${PROJECT_NAME} src/Robot.cpp)
ament_target_dependencies(${PROJECT_NAME}
rclcpp
moveit_ros_planning_interface
)
rosidl_target_interfaces(${PROJECT_NAME} ${PROJECT_NAME}_msgs "rosidl_typesupport_cpp")
add_executable(node src/node.cpp)
ament_target_dependencies(node rclcpp)
target_link_libraries(node ${PROJECT_NAME})
rosidl_target_interfaces(node ${PROJECT_NAME}_msgs "rosidl_typesupport_cpp")
- https://answers.ros.org/question/326008/ros2-run-symbol-not-found-on-custom-msg/
- Try cleaning
install
directory. Sometimessetup.zsh
is not updated correctly
https://answers.ros.org/question/305795/ros2-latching/
export PYTHONUNBUFFERED=1
ros2 topic echo ... | grep --line-buffered ...
RCLCPP_INFO(rclcpp::get_logger("my_logger"), "my_message");
ros2 run tf2_ros tf2_echo map base_link
https://docs.ros.org/en/humble/Tutorials/Demos/Logging-and-logger-configuration.html
--ros-args --log-level my_logger:=debug