@@ -88,6 +88,7 @@ def __init__(
8888 self ._current_pose = None
8989 self ._target_pose = None
9090 self ._current_joint = None
91+ self ._current_joint_velocity = None
9192 self ._target_joint = None
9293 self ._target_wrench = None
9394 self ._current_twist = None
@@ -304,6 +305,19 @@ def target_joint(self) -> NDArray:
304305 )
305306 return self ._target_joint .copy ()
306307
308+ @property
309+ def joint_velocities (self ) -> NDArray :
310+ """Get the current joint velocities of the robot.
311+
312+ Returns:
313+ numpy.ndarray: Copy of current joint velocities.
314+ """
315+ if self ._current_joint_velocity is None :
316+ raise RuntimeError (
317+ "The robot has not received any joint velocities yet. Run wait_until_ready() before running anything else."
318+ )
319+ return self ._current_joint_velocity .copy ()
320+
307321 @property
308322 def end_effector_twist (self ) -> Twist :
309323 """Get the current twist of the end effector.
@@ -510,6 +524,7 @@ def _callback_current_joint(self, msg: JointState):
510524 msg (JointState): ROS message containing joint states.
511525 """
512526 self ._current_joint = self .ros_msg_to_joint (msg ).copy ()
527+ self ._current_joint_velocity = self ._ros_msg_to_joint_velocity (msg ).copy ()
513528
514529 if self ._target_joint is None :
515530 self ._target_joint = self ._current_joint .copy ()
@@ -591,6 +606,17 @@ def ros_msg_to_joint(self, msg: JointState) -> NDArray:
591606 )
592607 return joint_values .astype (np .float32 )
593608
609+ def _ros_msg_to_joint_velocity (self , msg : JointState ) -> NDArray :
610+ """Convert a joint state message to a numpy array of joint velocities."""
611+ joint_velocities = np .zeros (self .nq )
612+ for joint_name , joint_velocity in zip (msg .name , msg .velocity ):
613+ if joint_name .removeprefix (self ._prefix ) not in self .config .joint_names :
614+ continue
615+ joint_velocities [self .config .joint_names .index (joint_name .removeprefix (self ._prefix ))] = (
616+ joint_velocity
617+ )
618+ return joint_velocities .astype (np .float32 )
619+
594620 def _parse_pose_or_position (
595621 self , position : List | NDArray | None = None , pose : Pose | None = None
596622 ) -> Pose :
0 commit comments