Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added service to force an Arduino hard reset in serial_node.py #349

Merged
merged 8 commits into from
Mar 24, 2018

Conversation

chrisspen
Copy link
Contributor

An Arduino may become unresponsive, either due to subtle coding bugs, memory fragmentation, or electrical faults. When this happens, it will often become completely unresponsive, resulting in the repeated rosserial error "Lost sync with device, restarting...". However, despite this message, there's no code in serial_node.py to actually restart the Arduino. It merely waits for the Arduino to come back online, which rarely ever happens. Currently, in this instance, the only fix is to reset the Arduino, either by manually pressing the Arduino's reset button or by running a program like ard-reset-arduino <port>.

This change adds the ability to programmatically reset the Arduino via a service call to the serial_node.py. It has the same effect as someone pressing the Arduino's reset button.

I debated adding code to automatically call this reset, but decided not to because I thought the logic of when it should be called would heavily depends on the application, and so it would better be left to the end user to implement in a custom node.

The intended use case of this would be to implement a custom node that monitors the diagnostic messages generated by serial_node.py, looking for the "last sync lost" key, and if this is seen repeatedly, then to call the ~hard_reset service on the node to force the Arduino to come back online.

@romainreignier
Copy link
Contributor

I like the idea of remote resetting an Arduino but it is very Arduino specific and it is pity to put it in the general rosserial_python node (I know it is the only place to put that snippet).

rosserial is used in a lot more systems than Arduinos and will be useless there.

Maybe rename the service ~hard_reset_arduino to make it clear for the user that it only applies to Arduinos?

@chrisspen
Copy link
Contributor Author

That's a good point. I've only used this package for Arduino, but you're right, Arduino isn't the only thing supported. Renaming the service makes sense.

@@ -334,7 +334,7 @@ def __init__(self, port=None, baud=57600, timeout=5.0, fix_pyserial_for_test=Fal

self.pub_diagnostics = rospy.Publisher('/diagnostics', diagnostic_msgs.msg.DiagnosticArray, queue_size=10)

rospy.Service('~hard_reset', Empty, self.hard_reset)
rospy.Service('~hard_reset_arduino', Empty, self.hard_reset_arduino)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pedantic, but isn't this more of a soft reset?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it depends on your definition. I would define a soft reset asking the Arduino to reset itself in your sketch, which may or may not be supported. I believe toggling the DTR pin actually pulls the Arduino's reset pin, so it's not effected by the sketch.

@mikepurvis
Copy link
Member

I'm also not over the moon about putting something so Arduino-specific into the generic node. The ideal way to handle this would be putting a hook in SerialClient.py such that an Arduino-specific version of the python node (eg, in the rosserial_arduino package) could import the generic functionality and supply the additional stuff on top.

That said, I can appreciate the pragmatism of just baking this in.

@chrisspen
Copy link
Contributor Author

Should I relocate this functionality to an arduino-specific serial_node.py and SerialClient.py and put them in rosserial_arduino?

@mikepurvis
Copy link
Member

I would prefer that path if it's not ridiculous. However, I can definitely picture that it might be, in which case the proposed scheme is acceptable.

@chrisspen
Copy link
Contributor Author

It'll create a lot more changed files, but it would cleanly separate the Arduino-specific functionality.

…k when both Arduino and serial_node.py get stuck writing to each other. Added pylint config to help clean up code.
@chrisspen
Copy link
Contributor Author

I've refactored the Arduino-specific reset functionality into a "rosserial_arduino" package, as requested.

I also fixed a major deadlock bug in the main serial_node.py, causing periodic freezes on some platforms, by refactoring it to use separate threads for reads and writes.

@chrisspen
Copy link
Contributor Author

Do you know why the travis tests are failing? It's complaining about a missing compiler environment variable, but I haven't touched any C components.

@mikepurvis
Copy link
Member

I think the Travis container's version of Clang got updated; I've fixed our builds now and re-kicked this PR's job, so it should now pass.

pep8.sh Outdated
@@ -0,0 +1,2 @@
#!/bin/bash
pylint --rcfile=pylint.rc rosserial_python/src/rosserial_python rosserial_arduino/src/rosserial_arduino/SerialClient.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this and the config file below. My preference would be to integrate roslint (http://wiki.ros.org/roslint), but if there are valid reasons to do something separate here, let's discuss it on a PR dedicated to that purpose.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

rospy.loginfo("Shutting down process %r", process)
process.terminate()
process.join()
rospy.loginfo("All done")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there arduinos using the TCP connection? If not, let's remove this section and the params above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -0,0 +1,11 @@
#!/usr/bin/env python
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding Python modules to rosserial_arduino requires a bunch of changes to the CMakeLists.txt and package.xml files. Please ensure those are included here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these should now be up to date. Please let me know if I missed anything.

…include dependencies. Removed unnecessary tcp functionality from arduino-specific serial_node.py
@mikepurvis
Copy link
Member

Thanks for the quick response! Looks like there's now a build problem that Travis has caught:

CMake Error at /opt/ros/indigo/share/catkin/cmake/catkin_python_setup.cmake:24 (message):
  generate_messages() must be called after catkin_python_setup() in project
  'rosserial_arduino'
Call Stack (most recent call first):
  rosserial/rosserial_arduino/CMakeLists.txt:23 (catkin_python_setup)
-- Configuring incomplete, errors occurred!
See also "/home/travis/catkin_ws/build/CMakeFiles/CMakeOutput.log".
See also "/home/travis/catkin_ws/build/CMakeFiles/CMakeError.log".
Invoking "cmake" failed

@chrisspen
Copy link
Contributor Author

I think CMakeLists.txt should now be fixed.

@mikepurvis
Copy link
Member

Great, thanks!

Please take a quick look at the rosserial_arduino tutorials, and update where appropriate to recommend the use of the server from rosserial_arduino rather than rosserial_python and note the availability of the new functionality.

@mikepurvis mikepurvis merged commit fe1e233 into ros-drivers:jade-devel Mar 24, 2018
@chrisspen
Copy link
Contributor Author

Will do.

romainreignier pushed a commit to 1r0b1n0/rosserial that referenced this pull request Nov 7, 2018
…am to jade-devel

* commit 'a707373c7e9f9ad40ad9440550840e29960c9290':
  Changed hardcoded pin 13 to LED_BUILTIN (ros-drivers#328)
  Re-attempting rosserial for VEX Cortex (ros-drivers#380)
  Added service to force an Arduino hard reset in serial_node.py (ros-drivers#349)
  Fix compiling on boost > 1.66 (ros-drivers#362)
  Use the ! prefix introduced in gcc4mbed for mbed examples (ros-drivers#304)
  Add support for boolean parameters (ros-drivers#355)
  Change Travis to use clang-5.0.0 (ros-drivers#363)
  [python] fix an unboundlocalerror (ros-drivers#346)
  Added ESP32 support (ros-drivers#345)
  Retry opening the serial port every 3 seconds (ros-drivers#342)
  In rosserial_arduino, changed embedded type size for ROS uint64 to 8 bytes from 4. (ros-drivers#312)
  0.7.7
  Changes
  Copy src/examples to install dir so make_libraries.py doesn't fail (ros-drivers#336)
  Add overall spin timeout to rosserial read. (ros-drivers#334)
  Fixing formatting on files. (ros-drivers#333)
  Fix catkin lint errors (ros-drivers#296)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants