1

I am running a rosnode with a kalman filter running. The kalman filter is an object with states that get updated as time plays out. Conventionally, a ros node has a run(self) method that runs at a specified frequency using the while condition

while not rospy.is_shutdown():
    do this

Going through each loop my kalman filter object updates. I just want to be able to save the kalman filter object when the node is shutdown either some external condition or when the user presses ctrl+C. I am not able to do this. In the run(self) method, I tried

while not rospy.is_shutdown():
    do this

# save in file
output = pathlib.Path('path/to/location')
results_path = output.with_suffix('.npz')
with open(results_path, 'xb') as results_file:
    np.savez(results_file,kfObj=kf_list)

But it has not worked. Is it not executing the save command? If ctrl+C is pressed does it stop short of executing it? Whats the way to do it?

Zero
  • 185
  • 6
  • 19
  • Possible duplicate of [Saving an Object (Data persistence)](https://stackoverflow.com/questions/4529815/saving-an-object-data-persistence) – Benyamin Jafari Nov 27 '19 at 06:16

2 Answers2

0

Check out the atexit module:

http://docs.python.org/library/atexit.html

import atexit

def exit_handler():
    output = pathlib.Path('path/to/location')
    results_path = output.with_suffix('.npz')
    with open(results_path, 'xb') as results_file:
    np.savez(results_file,kfObj=kf_list

atexit.register(exit_handler)

Just be aware that this works great for normal termination of the script, but it won't get called in all cases (e.g. fatal internal errors).

prhmma
  • 843
  • 10
  • 18
  • prhmma...thanks for the reply. But where should it be included? in the function whose termination should trigger this. It did not do anything when i simply added it to the run function – Zero Nov 24 '19 at 23:40
  • it triggers when your main function ends or when you ctrl+c to terminate your program. you should include it in your main function and store data from your specific function – prhmma Nov 24 '19 at 23:43
0

Why not try the following python example class structure engaging shutdown hooks :

import rospy

class Hardware_Interface:
    def __init__(self, selectedBoard):

        ...

        # Housekeeping, cleanup at the end
        rospy.on_shutdown(self.shutdown)

        # Get the connection settings from the parameter server
        self.port = rospy.get_param("~"+self.board+"-port", "/dev/ttyACM0")

        # Get the prefix
        self.prefix = rospy.get_param("~"+self.board+"-prefix", "travel")

        # Overall loop rate
        self.rate = int(rospy.get_param("~rate", 5))
        self.period = rospy.Duration(1/float(self.rate))

        ...

    def shutdown(self):
        rospy.loginfo("Shutting down Hardware Interface Node...")

        try:
            rospy.loginfo("Stopping the robot...")

            self.controller.send(0, 0, 0, 0)
            #self.cmd_vel_pub.publish(Twist())
            rospy.sleep(2)
        except:
            rospy.loginfo("Cannot stop!")

        try:
            self.controller.close()
        except:
            pass
        finally:
            rospy.loginfo("Serial port closed.")
            os._exit(0)

This just an extract from a personal script, please modify it to your needs. I imagine that the on_shutdown will do the trick. Another similar approach comes from my friends in the Robot Ignite Academy in The Construct and seems like that

#!/usr/bin/env python

import rospy
from geometry_msgs.msg import Twist

class my_class():

    def __init__(self):
        ...
        self.cmd = Twist()
        self.ctrl_c = False
        self.rate = rospy.Rate(10) # 10hz
        rospy.on_shutdown(self.shutdownhook)

    def publish_once_in_cmd_vel(self):

        while not self.ctrl_c:
            ...


    def shutdownhook(self):
        # works better than the rospy.is_shutdown()
        self.ctrl_c = True

    def move_something(self, linear_speed=0.2, angular_speed=0.2):
        self.cmd.linear.x = linear_speed
        self.cmd.angular.z = angular_speed
        self.publish_once_in_cmd_vel()

if __name__ == '__main__':
    rospy.init_node('class_test', anonymous=True)
    ...

This is obviously a sample of their code (for more please join the academy)

angelos.p
  • 500
  • 1
  • 5
  • 12