Motor
The /qtrobot/motor/... services and topics list motors, control torque/homing/velocity, and stream joint state, errors, and commands. These examples assume the gateway from Connection is already running.
List motors
ros2 service call /qtrobot/motor/list qtrobot_interfaces/srv/MotorList "{}"
Torque on/off and homing
ros2 service call /qtrobot/motor/on/all qtrobot_interfaces/srv/MotorOnAll "{}"
ros2 service call /qtrobot/motor/move/home/all qtrobot_interfaces/srv/MotorMoveHomeAll "{}"
ros2 service call /qtrobot/motor/on qtrobot_interfaces/srv/MotorOn "{motor: 'HeadYaw'}"
ros2 service call /qtrobot/motor/off qtrobot_interfaces/srv/MotorOff "{motor: 'HeadYaw'}"
ros2 service call /qtrobot/motor/move/home qtrobot_interfaces/srv/MotorMoveHome "{motor: 'HeadYaw'}"
Set velocity
ros2 service call /qtrobot/motor/velocity/set qtrobot_interfaces/srv/MotorVelocitySet \
"{motor: 'HeadYaw', velocity: 50}"
Subscribing to joint state
Before writing a node, it's often useful to peek at a topic's live data and exact type from the command line:
ros2 topic echo /qtrobot/motor/joints/state/stream
ros2 interface show qtrobot_interfaces/msg/MotorJointsStateFrame
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from qtrobot_interfaces.msg import MotorJointsStateFrame
class JointStateListener(Node):
def __init__(self):
super().__init__('joint_state_listener')
self.subscription = self.create_subscription(
MotorJointsStateFrame,
'/qtrobot/motor/joints/state/stream',
self.on_joint_state,
10,
)
def on_joint_state(self, msg: MotorJointsStateFrame):
for joint in msg.joints:
self.get_logger().info(
f'{joint.name}: position={joint.position:.1f} deg, '
f'velocity={joint.velocity:.1f} deg/s, temperature={joint.temperature:.1f} C'
)
def main():
rclpy.init()
node = JointStateListener()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
MotorJointsStateFrame carries a joints array of MotorJointState entries (name, position, velocity, effort, voltage, temperature), published at 10 Hz.