ROS_Python - RicoJia/notes GitHub Wiki
========================================================================
========================================================================
0. Compilation
1. when you first create a python script, you must do this: then catkin_make
python catkin_install_python(PROGRAMS scripts/motion_controller.py scripts/test_pub.py DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} )
-
get params
val = rospy.get_param("~val")
- rospy param: Don't know why, but rospy.get_param("~name", default) works, but not rospy.get_param("name", default)
- works with
rosrun pkg node _name:=val
-
time
- 比较时间
rospy.Time.now() - start_time > rospy.Duration(secs = n)
rospy.Timer(rospy.Duration(1), callback)
- 比较时间
-
Try except
try: main() except rospy.ROSInterruptException: # this can be thrown by rospy.sleep when ctrl_c. pass
-
Include
- numpy: just import numpy in code, no need to include this in CMakelist, package.xml. Cuz this is a script, no need to be compiled
- But Numpy is not included in rospy!!
- numpy: just import numpy in code, no need to include this in CMakelist, package.xml. Cuz this is a script, no need to be compiled
-
Subscribers:
class CmdVelExecutioner(object): def __init__(self): self.cmd_vel_sub_ = rospy.Subscriber("/cmd_vel", Twist, self.cmdVelCB) def cmdVelCB(self, twist_msg):
- Each subscriber will start a new thread, but rospy.spin() will simply puts the main thread to sleep until shutdown... So generally, you don't need this .
- Therefore, rospy has no
spinOnce
, cuz each subscriber will handle its own cb.
- Therefore, rospy has no
- Working with custom message type
from beginner_tutorials.msg import Person
- Each subscriber will start a new thread, but rospy.spin() will simply puts the main thread to sleep until shutdown... So generally, you don't need this .
-
shbang:
-
#!/usr/bin/env python3
for ROS Noetic. Shbang tells which interpreter to use. - shbang with
env
is better than#!/usr/bin/python
because it env will figure out which python to use.
-
-
ROS-python, naming convention: https://www.ros.org/reps/rep-0008.html#id19 ========================================================================
========================================================================
-
when using transformlistener, you need to do: link, another link
listener.waitForTransform('/base_link','/end_effector',rospy.Time(), rospy.Duration(1.0)) (trans,rot) = listener.lookupTransform( '/base_link','/end_effector', rospy.Time(0)) rospy.sleep(0.1)
- Also, the tutorial is misleading: you need to transform from end effector to base link to see the trajectory of end effector in the base frame!!
-
publish transforms: Always make sure there is a child frame when you publish a transform! The child frame cannot be itself. link
from nav_msgs.msg import Odometry from std_msgs.msg import Header odom_pub = rospy.Publisher('/my_odom', Odometry, queue_size=10); odom = Odometry() header = Header(); #empty header, stamps, header.frame_id = '/odom'; #try rossrv show Odometry to see what info needs to be filled in. odom.pose.pose = odom.twist.twist = header.stamp = rospy.Time.now() odom_pub.publish(odom)
注意: 你在做tf listerner 的时候, broadcaster 会有delay!
-
what goes into sensor_msgs/joint_state's velocity - the velocity right after we get to the specified position or right before? How does tf use the velocity in its broadcasted transform?
A: It is just an information. Should be updated is the body velocity in body frame -
if you have roll pitch yaw like roscpp's tf2::Quaternion::setEulerZYX(yaw, pitch, roll), use Bullet: getEulerFromQuaternion(quat)
-
quat
tf2::Quaternion quat; quat.setEulerZYX(yaw,pitch,roll)
========================================================================
========================================================================
-
Rospy.spin()
is different than roscppros::spin()
, which has its own thread. its job is to keep the code from exiting the node until terminated. the thread does not interfere with other threads, such as subscriber callbacks- Side Question: Why do timer threads not execute? Because you need to wait a second for the timer callback to fire!
-
there is one main thread. But one subscriber callback has one thread!
-
rospy::spin()
is just a sleep functiontry: while not rospy.core.is_shutdown() and not self.done: time.sleep(0.5) except KeyboardInterrupt: logdebug("keyboard interrupt, shutting down")
- in rospy, since
spin()
is simply waiting for shutdown request:# method 1 while not rospy.is_shutdown(): #do stuff #method 2 rospy.spin()
- shutdown handler: messages are not guaranteed to be published. But you can do service calls / parameter server calls safely.
def my_handler(): #do stuff rospy.on_shutdown(my_handler)
- in rospy, since
========================================================================
========================================================================
- message generation: (source code to be checked)
package_name/msg/Foo.msg → package_name.msg.Foo # 2 ways to generate the message #1 import std_msgs.msg.String #2 from std_msgs.msg import String msg = String() # 3 ways to populate #1 msg.data = "lol" #2, In-Order Arguments, must provide all args msg = String("lol") msg = std_msgs.msg.ColorRGBA(255,255,255,128) #for this schema: float32 r float32 g float32 b float32 a # 3 keyword args, or kwargs, get default msgs afterwards msg = std_msgs.msg.ColorRGBA(b=255)
========================================================================
========================================================================
- rospy allows only one node, with a unique name. Code?
- this is a design choice, multiple nodes don't make sense to be in the same process. However, if we call this funtion with the same args, then it's considered the same node.
- there's a check for args
global _init_node_args if _init_node_args != (name, argv, anonymous, log_level, disable_rostime, disable_signals): raise rospy.exceptions.ROSException("rospy.init_node() has already been called with different arguments: "+str(_init_node_args))
========================================================================
========================================================================
- you main loop is placed in the init function, and should be AFTER everything else!!
- e.g, 这样这个sub永远不会被执行!!
self.strategy2_main() self.map_sub = rospy.Subscriber("map", OccupancyGrid,self.map_callback)
- e.g, 这样这个sub永远不会被执行!!
========================================================================
========================================================================
- Anaconda changes default path of Python, ROS may not run. Solution:
echo export PATH=\"/home/$USER/anaconda3/bin:$PATH\" > ~/.bashrc