Ok guys, I found a way.
A possibility is to simply add a graph containing the ROS2 subscriber and Odometry if necessary like so:
def graph_twist(self)
# with self.targetPrim = "/World/Vehicle" targeting your rigid body vehicle
: print("Graph") og.Controller.edit(
{
"graph_path" : "/ROS2Ackermann",
"evaluator_name" : "execution"
},
{
og.Controller.Keys.CREATE_NODES : [
("onPlaybackTick", "omni.graph.action.OnPlaybackTick"),
("readSimTime", "isaacsim.core.nodes.IsaacReadSimulationTime"),
("computeOdom", "isaacsim.core.nodes.IsaacComputeOdometry"),
("publishOdom", "isaacsim.ros2.bridge.ROS2PublishOdometry"),
("subscribeTwist", "isaacsim.ros2.bridge.ROS2SubscribeTwist"),
("QoSSensor", "isaacsim.ros2.bridge.ROS2QoSProfile"),
],
og.Controller.Keys.SET_VALUES : [
("computeOdom.inputs:chassisPrim", [Sdf.Path(self.targetPrim)]),
("subscribeTwist.inputs:topicName", "/car/cmd_vel"),
("publishOdom.inputs:topicName", "/car/odom"),
("QoSSensor.inputs:createProfile", "Sensor Data"),
],
og.Controller.Keys.CREATE_ATTRIBUTES : [],
og.Controller.Keys.CONNECT : [
("onPlaybackTick.outputs:tick", "computeOdom.inputs:execIn"),
("onPlaybackTick.outputs:tick", "publishOdom.inputs:execIn"),
("readSimTime.outputs:simulationTime",
"publishOdom.inputs:timeStamp"),
("computeOdom.outputs:angularVelocity",
"publishOdom.inputs:angularVelocity"),
("computeOdom.outputs:linearVelocity",
"publishOdom.inputs:linearVelocity"),
("computeOdom.outputs:orientation",
"publishOdom.inputs:orientation"),
("computeOdom.outputs:position", "publishOdom.inputs:position"),
("onPlaybackTick.outputs:tick", "subscribeTwist.inputs:execIn"),
("QoSSensor.outputs:qosProfile",
"subscribeTwist.inputs:qosProfile"),
("QoSSensor.outputs:qosProfile","publishOdom.inputs:qosProfile"),
],
}, )
And retrieve the message fields that you are interested in like the control inputs and odometry data using:
def create(self, stage):
self.graph_twist() # create the graph first then target the graph fields
self.ros_linear_inputs = og.Controller.attribute("/ROS2Ackermann/subscribeTwist.outputs:linearVelocity")
self.ros_angular_inputs = og.Controller.attribute("/ROS2Ackermann/subscribeTwist.outputs:angularVelocity")
Finally, by overloading the demo.Base update method, you can update the physxVehicleController directly:
def update(self, stage, dt, viewport, physxIFace):
if self.vehicle_prim and self.ros_linear_inputs and self.ros_angular_inputs:
torque_commands = og.DataView(self.ros_linear_inputs)
torques_val = np.array(torque_commands.get())
steer_commands = og.DataView(self.ros_angular_inputs)
steer_val = np.array(steer_commands.get())
# deal with data, clamping...
# update the controller with linearVelocity.x and angularVelocity.z
self.vehicle_prim.GetAttribute('physxVehicleController:accelerator').Set(torques_val[0])
self.vehicle_prim.GetAttribute('physxVehicleController:steer').Set(steer_val[2])
return
I my case I send torque commands.
The keyboard control can be deactivated by unchecking “Input Enabled” in the side panel of the vehicle in “Vehicle Controller Settings”
Best,
Bryan