Add a sensor part
A sensor is a part like any other, plus what the simulator needs to make it sense. The split keeps the description Gazebo free:
The part declares its sensing frame. In
<part>_info, aframesentry at the sensing origin, oriented as the sensor looks (the Ping declaresbeamat its transducer face). It becomes the URDF link<name>_beam, carried in TF, and survives Gazebo’s lumping as a frame.blueboat_gazeboknows the part type. Inmodel.sdf.xacro, thegz_partemitter has one branch per sensor type (and one for any part with adrivetable, the propellers). Add one for yours: a<sensor>block on a massless link posedrelative_to="${name}_<frame>", with<frame_id>set to that frame under the instance name and the topic fromtopic_base(the Ping branch is the template;infois the part’spart_infoif you need its frames or other metadata). The emitter runs inside the same assembly resolution that built the URDF, so it fires for every instance of the type, defaults and free placements alike.The bridge knows the topics. In
scripts/generate_bridge_config.py, add the type toPART_TOPICS: one(suffix, ros type, gz type, direction)per topic the sensor produces. The generator reads the fitted instances from the URDF manifest, so again no per vehicle edit.Fit it: in a slot (add the type to the slot’s
accepts, make it thedefaultif it should come standard) or free placed.
The tests guard the contract: every sensor’s frame_id must be a TF frame of the instance,
every sensor’s frame must survive URDF to SDF conversion, and the Gazebo
topics must equal the bridge’s, for the default, a full catalog and a
renamed instance config. Run colcon test --packages-select blueboat_gazebo.