[ros-users] ROS nodes & SIGINT handler

Kaijen Hsiao kaijenhsiao at gmail.com
Tue Aug 31 23:53:05 UTC 2010


I would recommend against using fork()/exec() to run "rosbag record",
actually--I tried to do so myself not long ago, and found that the
forked process wouldn't respond to SIGINT, and so I couldn't close any
of the bagfiles being recorded.  Although maybe you'll have better
luck (or maybe Tim knows of a trick to make that work--I'm certainly
no expert at using fork/exec).

rxbag's Recorder class, on the other hand, was fairly easy to extend
for my needs.

-Kaijen

On Tue, Aug 31, 2010 at 3:39 PM, Tim Field <tfield at willowgarage.com> wrote:
> Hi Gautier,
> One option is rxbag's Recorder class,
> i.e. https://code.ros.org/svn/ros/stacks/ros/tags/cturtle/tools/rxbag/src/rxbag/recorder.py.
> Here's some code to get you started:
>
> import roslib; roslib.load_manifest('rxbag')
> from rxbag.recorder import Recorder
> r = Recorder('altimeter.bag', topics=['/fake_alti'])
> r.start()
> r.pause()
> r.unpause()
> r.stop()
>
> If that's too slow to record your data (ROS message serialization is slow in
> Python), I'd follow Josh's suggestion and fork()/exec() a process to run
> "rosbag record".
> For Diamondback, rosbag will have a ROS API for recording and playback.
> Tim
> On Tue, Aug 31, 2010 at 12:06 PM, Gautier Dumonteil
> <gautier.dumonteil at gmail.com> wrote:
>>
>> Hi users,
>>
>> In our reseach project, we would like to be able to record bags
>> "automatically" (e.g recording when our UAV is flying).
>> So, I'm trying to write a simple node (recorder_interface) with two
>> services "start_record" and "stop_record", where "start_record" callback
>> launch the rosbag::recorder::run() in a child process using fork(). The
>> "stop_record" callback just sends the SIGINT signal to recorder PID to stop
>> recording ... but nothing happen. It seems that the ROS node forked doesn't
>> handle SIGINT signals.
>>
>> Also, when checking available nodes with "rosnode list", I've only the
>> recorder_interface node. I should have also something like
>> "record_1283279499007996727", which is the rosbag record node.
>>
>> I'm wondering if a node can launch others nodes??
>>
>> Here, the console output and code:
>>
>> [ INFO] [1283279481.648585599]: Recorder_interface spinning: ready to
>> record.
>> [ INFO] [1283279499.006083281]: Request to record topics: test
>> [ INFO] [1283279499.007996722]: Child: pid = 10497
>>
>> [ INFO] [1283279499.008979878]: Subscribing to /fake_alti
>> [ INFO] [1283279499.009749320]: Recording to test_2010-08-31-14-31-39.bag.
>>
>> #include <signal.h>
>> #include "ros/ros.h"
>> #include "recorder_interface/rec_interface.h"
>> #include "rosbag/recorder.h"
>> #include "rosbag/exceptions.h"
>>
>> bool  recording;
>> int   recorder_exit_code;
>> pid_t rosbag_pid;
>>
>> void rosbagRecord (rosbag::RecorderOptions opts)
>> {
>>     char ** argv = NULL;
>>     int argc=0;
>>     ros::init(argc, argv, "record", ros::init_options::AnonymousName);
>>
>>     // **** Run the recorder
>>     rosbag::Recorder recorder(opts);
>>     recorder_exit_code = recorder.run();
>>     ROS_INFO("recorder_exit_code: %d\n",recorder_exit_code);
>> }
>>
>> bool startRec(recorder_interface::rec_interface::Request &req,
>>                   recorder_interface::rec_interface::Response &res)
>> {
>>     if(!recording)
>>     {
>>         recording=true;
>>         ROS_INFO("Request to record topics: %s", req.topics.c_str ());
>>
>>         // **** Fill rosbag options
>>         rosbag::RecorderOptions opts;
>>         opts.record_all = false;
>>         opts.quiet = true;
>>         opts.prefix = req.prefix;
>>         opts.append_date = true;
>>         opts.topics.push_back("/fake_alti");
>>
>>         rosbag_pid = fork();
>>         if(rosbag_pid == -1)
>>         {
>>             // **** ouch, fork() failed
>>             perror("fork");
>>             exit(-1);
>>         }
>>         else if(rosbag_pid == 0)
>>         {
>>             // **** child
>>             ROS_INFO("Child: pid = %d\n", (int)getpid());
>>             rosbagRecord(opts);
>>             exit(-1);
>>         }
>>     }
>>     else
>>     {
>>         ROS_WARN("Already recording!");
>>     }
>>    return true;
>> }
>>
>>
>> bool stopRec(recorder_interface::rec_interface::Request &req,
>>                   recorder_interface::rec_interface::Response &res)
>> {
>>    if(recording)
>>     {
>>         int err = kill(rosbag_pid, SIGINT);
>>         ROS_INFO("err = %d\n",err);
>>         if(err==0)
>>         {
>>             res.ans=recorder_exit_code;
>>             recording=false;
>>         }
>>     }
>>     else
>>     {
>>         ROS_WARN("Not recording!");
>>     }
>>    return true;
>> }
>>
>> int main(int argc, char **argv)
>> {
>>   recording=false;
>>
>>   ros::init(argc, argv, "recorder_interface");
>>   ros::NodeHandle n;
>>
>>   ros::ServiceServer serviceStart,serviceStop;
>>   serviceStart = n.advertiseService("start_record", startRec);
>>   serviceStop = n.advertiseService("stop_record", stopRec);
>>   ROS_INFO("Recorder_interface spinning: ready to record.");
>>   ros::spin();
>>   return 0;
>> }
>>
>>
>>
>> _______________________________________________
>> ros-users mailing list
>> ros-users at code.ros.org
>> https://code.ros.org/mailman/listinfo/ros-users
>>
>
>
> _______________________________________________
> ros-users mailing list
> ros-users at code.ros.org
> https://code.ros.org/mailman/listinfo/ros-users
>
>



More information about the ros-users mailing list