我是ROS的新手,我正在计划以编程方式启动'video_stream_opencv'节点。
下面的链接:http://wiki.ros.org/video_stream_opencv
启动文件与命令Roslaunch合作良好
<!-- images will be published at /camera_name/image with the image transports plugins (e.g.: compressed) installed -->
<group ns="$(arg camera_name)">
<node pkg="video_stream_opencv" type="video_stream" name="$(arg camera_name)_stream" output="screen">
<remap from="camera" to="image_raw" />
<param name="camera_name" type="string" value="$(arg camera_name)" />
<param name="video_stream_provider" type="string" value="$(arg video_stream_provider)" />
<param name="fps" type="int" value="$(arg fps)" />
<param name="frame_id" type="string" value="$(arg frame_id)" />
<param name="camera_info_url" type="string" value="$(arg camera_info_url)" />
<param name="flip_horizontal" type="bool" value="$(arg flip_horizontal)" />
<param name="flip_vertical" type="bool" value="$(arg flip_vertical)" />
<param name="width" type="int" value="$(arg width)" />
<param name="height" type="int" value="$(arg height)" />
</node>
<node if="$(arg visualize)" name="$(arg camera_name)_image_view" pkg="image_view" type="image_view">
<remap from="image" to="image_raw" />
</node>
</group>
,但是现在我试图使用C 代码做同样的事情,但是我看不到如何在节点中设置"类型"属性...
printf("Started ROS threadn");
//glutInit(&argc, argv);
ros::init(argc, argv, "camera_name);
ROS_INFO("camera_name started");
// MY params to set
std::string camera_name = "toto";
std::string video_stream_provider = "toto";
int fps = 30;
std::string frame_id= "toto";
std::string camera_info_url= "toto";
bool flip_horizontal= false;
bool flip_vertical= false;
int width = 30;
int height = 30;
ros::NodeHandle nh;
ros::M_string remappings;
remappings.insert(std::make_pair("camera", "image_raw"));
ros::NodeHandle node_handle(nh, "camera_name",remappings);
node_handle.setParam("type",video_stream);
node_handle.setParam("camera_name",camera_name);
node_handle.setParam("video_stream_provider",video_stream_provider );
node_handle.setParam("fps",fps);
node_handle.setParam("frame_id",frame_id);
node_handle.setParam("camera_info_url", camera_info_url);
node_handle.setParam("flip_horizontal", flip_horizontal);
node_handle.setParam("flip_vertical",flip_vertical);
node_handle.setParam("width", width);
node_handle.setParam("height", height);
恢复旧线程以帮助有需要的人。
我为此目的创建了一个基于" Rosspawn"的课程。
ros_launch_manager.hpp:
#pragma once
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstdint>
#include <memory>
#include <thread>
#include <mutex>
#include <vector>
#include <algorithm>
#include <numeric>
#include "ros/ros.h"
#include "ros/console.h"
#include "rospack/rospack.h"
class ROSLaunchManager
{
std::vector<pid_t> m_pids;
std::atomic<bool> m_running;
std::thread m_thread;
std::mutex m_mutex;
public:
ROSLaunchManager(ROSLaunchManager const &)
{
}
ROSLaunchManager()
{
std::atomic_init(&m_running, true);
m_thread = std::thread(&ROSLaunchManager::wait, this);
}
~ROSLaunchManager()
{
if (m_running.load()) {
m_running.store(false);
if (m_thread.joinable()) {
m_thread.join();
}
}
}
template<typename... Args>
pid_t start(Args... args)
{
std::vector<std::string> args_vector = { args... };
if (args_vector.size() > 0) {
pid_t pid = ::fork();
if (pid == 0) {
::setsid();
::signal(SIGINT, SIG_IGN);
::fclose(stdout);
::fclose(stdin);
::fclose(stderr);
::execlp("roslaunch", "roslaunch", args..., nullptr);
}
else {
std::scoped_lock<std::mutex> scoped_lock(m_mutex);
std::string args_string = std::accumulate(std::next(std::begin(args_vector)), std::end(args_vector), args_vector[0], [](std::string lhs, std::string rhs) -> std::string { return lhs + " " + rhs; });
ROS_INFO("Starting "roslaunch %s" with PID %d", args_string.c_str(), pid);
m_pids.push_back(pid);
}
return pid;
}
else {
throw std::runtime_error("ROSLaunchManager::start - No arguments provided");
}
}
void stop(pid_t const &pid, int32_t const &signal)
{
std::scoped_lock<std::mutex> scoped_lock(m_mutex);
auto pid_it = std::find(std::begin(m_pids), std::end(m_pids), pid);
if (pid_it != m_pids.end()) {
::kill(pid, signal);
ROS_INFO("Stopping process with PID %d and signal %d", pid, signal);
}
else {
throw std::runtime_error("ROSLaunchManager::stop - PID " + std::to_string(pid) + " not found");
}
}
private:
void wait()
{
while (m_running.load()) {
std::scoped_lock<std::mutex> scoped_lock(m_mutex);
for (auto pid_it = std::begin(m_pids); pid_it != std::end(m_pids); ++pid_it) {
pid_t const pid = *pid_it;
int32_t status;
if (::waitpid(pid, &status, WUNTRACED | WCONTINUED | WNOHANG) == pid) {
if (WIFEXITED(status)) {
ROS_INFO("PID %d exited with status %d", pid, WEXITSTATUS(status));
pid_it = m_pids.erase(pid_it);
if (pid_it == std::end(m_pids)) {
break;
}
}
else if (WIFSIGNALED(status)) {
ROS_INFO("PID %d killed with signal %d", pid, WTERMSIG(status));
pid_it = m_pids.erase(pid_it);
if (pid_it == std::end(m_pids)) {
break;
}
}
else if (WIFSTOPPED(status)) {
ROS_INFO("PID %d stopped with signal %d", pid, WSTOPSIG(status));
}
else if (WIFCONTINUED(status)) {
ROS_INFO("PID %d continued" , pid);
}
}
}
}
std::scoped_lock<std::mutex> scoped_lock(m_mutex);
for (pid_t const &pid : m_pids) {
::kill(pid, SIGINT);
int32_t status;
::waitpid(pid, &status, 0);
}
}
};
用法:
ROSLaunchManager ros_launch_manager;
pid_t rtabmap_pid;
// Start roslaunch program
try {
rtabmap_pid = ros_launch_manager.start(
"rtabmap_ros", "rtabmap.launch",
"rtabmap_args:="--delete_db_on_start"",
"depth_topic:=/camera/aligned_depth_to_color/image_raw",
"rgb_topic:=/camera/color/image_raw",
"camera_info_topic:=/camera/color/camera_info",
"approx_sync:=false");
}
catch (std::exception const &exception) {
ROS_WARN("%s", exception.what());
}
// Stop roslaunch program
try {
ros_launch_manager.stop(rtabmap_pid, SIGINT);
}
catch (std::exception const &exception) {
ROS_WARN("%s", exception.what());
}
ros_launch_manager被摧毁时,其所有过程被杀死。使用Sigstop/Sigcont也可以停止/继续这些过程。
我知道启动rosnode的唯一两种方法是使用rosrun或通过启动文件来源。
https://answers.ros.org/question/198279/how-to-to-start-a-ros-node/
我假设您在询问有关rosnode的参数的类型。
在roscpp中,包括/ros/node_handle.h,SetParam()确实有多个变体,每个变体都设计用于处理特定类型的参数。
void setParam(const std::string& key, const std::string& s) const;
void setParam(const std::string& key, const char* s) const;
void setParam(const std::string& key, double d) const;
等等。
您已经在代码中完成了此操作。