ROS - check if a node is still alive - communication

I'm implementing a control node for a device with four wheels. So far I have the following nodes:
TALKER:
--Publishes messages for movement of vehicle
LISTENER:
--Listens to messages for movement of vehicle and controls vehicle directly
The communication between these two works and my only problem is what to do if either one shuts down in order to prevent uncontrolled movement of the vehicle. ros::isShuttingDown() call in the LISTENER so it detects when it's about to be killed.
However, if the TALKER is shut down the LISTENER keeps moving the vehicle according to the last message received from TALKER. First I tried to use ros::isShuttingDown() in TALKER as well in order to send a final "stop" message to LISTENER, but it seems that once the node is shutting down, no communication is possible.
Therefore I'm looking for a way to check inside LISTENER if the node TALKER is still alive (or if new messages are still being received).
Anyone an idea on how to see if a node (in this case TALKER) is still alive? Or is there an easy method for detecting how long it has been since the last ROS message was received?

Take a look at the bond package. I believe it does exactly what you need.

Found another interesting and already built-in way with including "ros/network.h":
// master.h:
....
/**
* \brief Retreives the currently-known list of nodes from the master
*/
ROSCPP_DECL bool getNodes(V_string& nodes);
....
However, I didnt figure out how to use it from within another cpp file...

Related

Difference between spin and rate.sleep in ROS

I am new to ROS and trying to understand this powerful tool. I am confused between the spin and rate.sleep functions. Could anyone help me with the difference between these two functions and when to use each one?
ros::spin() and ros::spinOnce() are responsible to handle communication events, e.g. arriving messages. If you are subscribing to messages, services, or actions, you must call spin to process the events.
While ros::spinOnce() handles the events and returns immediately, ros::spin() blocks until ROS invokes a shutdown. So, ros::spinOnce() gives you more control if needed. More on that matter here: Callbacks and Spinning.
rate.sleep() on the other hand is merely a thread sleep with a duration defined by a frequency. Here is an example
ros::Rate rate(24.);
while(ros::ok())
{
rate.sleep();
}
This loop will be executed 24 times a second or less, depends what you do inside the loop. A ros::Rate object keeps track of how much time since the last rate.sleep() was executed and sleep for the correct amount of time to hit the 24 Hz mark. See ros::Rate::sleep() API.
The equivalent way in the time domain is ros::Duration::sleep()
ros::Duration duration(1./24.);
while(ros::ok())
{
duration.sleep();
}
Which one you use is just a matter of convenience.

In Dart, if I listen to a click event with two listeners, how do I know which happens first?

If I write the following Dart code, how do I know which click handler happens first?
main() {
var button = new ButtonElement();
var stream = button.onClick.asBroadcastStream();
stream.listen(clickHandler1);
stream.listen(clickHandler2);
}
Let's say I'm in other code that doesn't know anything about the first two click handlers, but I register another one.
Can I know that the stream has two listeners?
Can I pause or cancel all other subscribers?
If I write button.onClick.asBroadcastStream() again elsewhere, does it point to the same stream as was used in main?
Can I say in one of the handlers to not pass event on to the other broadcast listener? Is that a consumer?
Let's say I'm in other code that doesn't know anything about the first
two click handlers, but I register another one.
Can I know that the stream has two listeners?
No, you can't. You could extend the stream class or wrap it and provide this functionality yourself, but it does not feel like a good design choice, because I don't think a listener should know about other listeners. What are you trying to do exactly? Perhaps there's a better way than letting listeners know about each other.
Can I pause or cancel all other subscribers?
You can cancel/pause/resume only the subscriber you are dealing with. Again, you probably shouldn't touch other listeners, but I guess you could wrap/extend the Stream class to have this behavior.
If I write button.onClick.asBroadcastStream() again elsewhere, does it point to the same stream as was used in main?
No, at least not at the current version of SDK. So, unfortunately, you need to store a reference to this broadcast stream somewhere, and refer to it, because calling asBroadcastStream() multiple times will not yield in the result you might expect. (Note: at least based on quick testing: http://d.pr/i/Ip0K although the documentation seems to indicate different, I have yet to test a bit more when I find the time).
Can I say in one of the handlers to not pass event on to the other broadcast listener?
Well, there's stopPropagation() in the HTML land which means that the event won't propagate to other elements, but it's probably not what you were looking for.
For being able to stop an event firing in other listeners, there needs to be an order of which the listeners are getting called. I believe the order is the order of registration of those listeners. From the design perspective, I don't think it would be a good idea to allow a listener to cancel/pause others.
Event propagation in HTML makes sense since it's about hierarchy, but here we don't have that (and even in case of events in HTML there can be multiple listeners for the single element).
There's no way to assign weight to listeners or define the order of importance, therefore it's not surprising that there isn't a way to stop the event.
Instead of letting listeners know about each other and manipulate each other, maybe you should try to think of another way to approach your problem (whatever that is).
Is that a consumer?
The StreamConsumer is just a class that you can implement if you want to allow other streams to be piped into your class.
Can I know that the stream has two listeners?
No, you have a ´Stream´ that wraps the DOM event handling. There is no such functionality.
Can I pause or cancel all other subscribers?
Look at Event.stopPropagation() and Event.stopImmediatePropagation(), and possibly Event.preventDefault().
If I write button.onClick.asBroadcastStream() again elsewhere, does it point to the same stream as was used in main?
[Updated] No, the current implementation doesn't gives you the same Stream back since the onClick getter returns a new stream every time it is invoked. However, the returned stream is already a broadcast stream so you shouldn't invoke asBroadcastStream() on it. If you do you will hower just get a reference to the same object back.
Stream<T> asBroadcastStream() => this;
Can I say in one of the handlers to not pass event on to the other broadcast listener? Is that a consumer?
Again, take a look at Event.stopPropagation() and Event.stopImmediatePropagation(), and possibly Event.preventDefault().

Registering a child in the process that initiated the start_child call

I have a logic module that tells a supervisor to start child processes. I need to store those childrens pid in the logic modules state. But I also need to update a childs pid if the supervisor restarts it.
So I can't use the return value pid from the start_child call, since that will only give me the pid on the first start, not the restarts. Right now I make the child process call a register function (updates state with new pid) in the logic module from the childs init function. That way the logic module can update the pid in its state whenever a process is restarted. The logic module is a gen_server and I'm doing a cast when i register the child process.
Can anyone see a problem with this and are there any other more "proper" way of doing it?
One problem is that you have the ChildPid and the child might be dead by now. So sending it a message through a cast will mean the message is lost. And through a call you will crash yourself with an {'EXIT', noproc} unless you catch it out of the call. Your solution must take into account that a Pid might be long gone the instant you send a message. Usually by ignoring that the message is lost, by crashing yourself, or by remedying the problem and then go on.
There are a couple of options. This is a loose list:
Do as you do. Let the childs register themselves.
Let the logic module have a monitor on the child. That way you know if it dies.
Use Erlang Solutions gproc module: https://github.com/esl/gproc which gives you a neat interface to an ETS table keeping track of the information. Note that you can look up a pid in gproc and await its arrival if the process is just restarting.
Use supervisor:which_children to find the relevant child.
Roll your own ETS table as a variant of gproc
local names have to be atoms, but globally registered names can be any term (they are stored internally in a ETS table looking somewhat like gproc's, see the global_name_server in kernel/stdlib). Use the global structure to track the pids in question.

Can I handle any received message in gen_fsm state callbacks?

I noticed that messages sent to the pid of a gen_fsm process are matched in the state callbacks as events. Is this just accidental or can I rely on this feature?
Normally I would expect general messages sent to a gen_fsm to show up in the handle_info/3 callback and thought I would have to re-send it using gen_fsm:send_event.
Does gen_fsm try to match the message first to the state callback and then allways with the handle_info/3 callback? Or only if it doesn't match a state callback clause?
However when I try it my message seems to be handled twice according to debug output.
So basically the question can also be stated like: how to correctly handle received messages as events in gen_fsm state functions?
Clarification: that some of the events are occurring by getting messages passed should be considered given for this question.
I'm aware that in many cases its cleaner to make the protocol visible by using function calls into the fsm only.
I'm not so sure if this would improve the current framework where the mentioned gen_fsm has to fit in: Diverse protocol stacks where each layer calls a connect() function to attach (and sometimes start) the lower layer. Packets are sent to lower layers ba calling a function (send) and received by receiveing a message. Much like gen_tcp.
By looking at the code for gen_fsm I already figured out that general messages are only passed to handle_info, so only the question remains wether to call the state function directly from the handle_info/3 callback or resent using gen_fsm:send_event.
General messages are handled by handle_info callback, unless you have something like this in your code:
handle_info(Info, StateName, StateData) ->
?MODULE:StateName(Info, StateData).
Which avoids resending, but I do not recommend neither that, nor resending.
Delivering events exclusively by means of API calls encapsulating send_event/sync_send_event/send_all_state_event/sync_send_all_state_event makes protocol explicit. Which is a right thing, as it is easier to understand, maintain and document with edoc.

State in OTP event manager process (not handler!)

Can an OTP event manager process (e.g. a logger) have some state of its own (e.g. logging level) and filter/transform events based on it?
I also have a need to put some state into the gen_event itself, and my best idea at the moment is to use the process dictionary (get/put). Handlers are invoked in the context of the gen_event process, so the same process dictionary will be there for all handler calls.
Yes, process dictionaries are evil, but in this case they seem less evil than alternatives (ets table, state server).
The gen_event implementation as contained in the OTP does no provide means for adding state.
You could extend the implementation to achieve this and use your implementation instead of gen_event. However I would advise against it.
The kind of state you want to add to the event manager belongs really in the event handler for several reasons:
You might want to use different levels in different handlers, e.g. only show errors on the console but write everything to the disk.
If the event level would be changed in the manager event handlers depending on getting all unfiltered events might cease to function (events have more uses than just logging). This might lead to hard to debug problems.
If you want a event manager for multiple handlers that all only get filtered events you can easily achieve this by having two managers: one for unfiltered messages and one for e.g. level filtered messages. Then install a handler to the unfiltered one, filter in the handler by level (easy) and pass on the filtered events to the other manager. All handlers that only want to get filtered messages can be registered to the second manager.
The handlers can have their own state that gets passed on every callback like:
Module:handle_event(Event, State) -> Result
Filtering might look like this (assuming e.g. {level N, Content} events):
handle_event({level, Lvl, Content}, State#state{max_level=Max}) when Lvl >= Max ->
gen_event:notify(filtered_man, Content);
The State can be changed either by special events, by gen_event:call\3,4 (preferably) or by messages handled by handle_info.
For details see Gen_Event Behaviour and gen_event(3)
When you start_link a gen_event process - thing that you should always do via a supervisor -, you can merely specify a name for the new process, if you need/want it to be registered.
As far as I can see, there's no way to initiate a state of some sort using that behaviour.
Of course, you can write your own behaviour, on the top of a gen_event or of a simple gen_server.
As an alternative, you might use a separate gen_event process for each debugging level.
Or you can just filter the messages in the handlers.

Resources