The contents of this page include:
- Physical Construction : Basics of creating a model
- Changing the Mesh : Change a model's skin
- Changing the Material : Change a model's material
- Creating Joints : Add joints to a model
- Bodies with Multiple Geometries : Add multiple geometries to a body
- Controllers : Add controllers to a model
- XML Include : Separating models into separate files. Allows for easy inclusion of models into a world.
- Nesting Models : Connect models in a parent-child relationship
This tutorial will first describe how to create a new model using Gazebo's xml language, and then how to controll the model using interfaces and controllers.
- Name everything : All models, bodies, and geoms must have names. These names hshould be unique, but this is not strictly enforced.
- A model must contain a body.
- A body can contain only senors and/or geometries.
<model:physical name="box_model"> <xyz>0 1.5 0.5</xyz> <rpy>0.0 0.0 0.0</rpy> <canonicalBody>box1_body</canonicalBody> <static>false</static> <body:box name="box_body"> <xyz>0.0 0.0 0.0</xyz> <rpy>0.0 0.0 0.0</rpy> <geom:box name="box_geom"> <xyz>0.0 0.0 0.0</xyz> <rpy>0.0 0.0 0.0</rpy> <mesh>default</mesh> <size>1 1 1</size> <density>1.0</density> <material>Gazebo/BumpyMetal</material> </geom:box> </body:box> </model:physical>
In this example the starting position of the model is 1.5 meters up (Z-axes), and 0.5 meters along the Y axis. The model has no rotation.
canonicalBody tag defines which body within a model should be used when nesting models. Nesting occurs when a model is defined withing another model. This creates a parent-child relationship, and a joint attached the two models together by connecting their respective canonical bodies. If this tag is left out, the first body in the model is automatically used as the canonical body.
static flags indicates whether this model is affected by physics. If set to false, then the model will never move, but will still collide with other moving objects. If set to true, then the physics engine will update the model according to it mass, position, collisions, etc.
This model contains one body that is not offset from the model's position. Contained within this model is one geometry that is not offset from the body's position. The
mesh tag is used to attach a 3D mesh to the geometry. This is mesh is used for visualization only. By setting
mesh to default the internal mesh is used for the geometry.
size tag indicates how big the geometry should be. The
density tag is used to calculate the mass of the geometry. Finally, the
material tag indicates what texture should be applied to the geometry.
meshtag a new "skin" can be applied to a geometry. The value of the
meshtag should match one of the OGRE models. Contained within the Gazebo sources at
gazebo/Media/modelsis a set of predefined meshes.
If you would like to use a different mesh, say the
fish mesh, then modify the
If you want to use a different material, say
FlatBlack, then change the
material tag accordingly:
If a model is being created to simulate a Pioneer2DX robot, two hinge joints should be attached between two wheel bodies and on chassis body. Additionally, a rear castor wheel must be connected to the chassis using a ball joint. Read the ODE manual for a description of the various joints.
Suppose this pioneer2dx model has the following named bodies:
The left hinge joint would be:
<joint:hinge name="left_wheel_hinge"> <body1>left_wheel</body1> <body2>chassis_body</body2> <anchor>left_wheel</anchor> <axis>0 1 0</axis> <erp>0.4</erp> <cfm>0.008</cfm> </joint:hinge>
The right hinge joint would be:
<joint:hinge name="right_wheel_hinge"> <body1>right_wheel</body1> <body2>chassis_body</body2> <anchor>right_wheel</anchor> <axis>0 1 0</axis> <erp>0.4</erp> <cfm>0.008</cfm> </joint:hinge>
axis tag in the above two joints indicates the axis of motion. In this case the two wheels will rotate around the Y-axis. The
cfm tags indicate the error reduction parameter and constrain force mixing parameter. See the ODE manual for more insight into these parameters.
And the castor joint would be:
<joint:ball name="castor_joint"> <body1>castor_body</body1> <body2>chassis_body</body2> <anchor>castor_body</anchor> <erp>0.4</erp> <cfm>0.008</cfm> </joint:ball>
Since a ball joint rotates in all directions, no
axis tag is used.
In this example we will create a cylindrical wheel that contains a box at the hub.
<body:cylinder name="left_wheel"> <xyz>0.1 -0.17 -0.0725</xyz> <rpy>0 90 90</rpy> <geom:cylinder name="left_wheel_geom"> <mesh>default</mesh> <size>0.075 0.05</size> <density>0.5</density> <material>Gazebo/Black</material> </geom:cylinder> <geom:box name="left_wheel_box"> <mesh>default</mesh> <xyz>0.0 0.0 -0.010</xyz> <size>0.05 0.05 0.05</size> <density>0</density> <material>Gazebo/White</material> </geom:box> </body:cylinder>
Note that the cylinder geom has no position and orientation offset from the parent body, while the box geom is translate -0.01 meters along the Z-axis.
Controllers are compiled into gazebo, and are linked to model using XML:
<controller:pioneer2dx_position2d name="controller1"> <leftJoint>left_wheel_hinge</leftJoint> <rightJoint>right_wheel_hinge</rightJoint> <interface:position name="position_iface_1"/> </controller:pioneer2dx_position2d>
The above example creates a position controller for a pioneer2dx. The first two children,
rightJoint, tell this controller which two joints make up the drive train. The last child parameter, defines what libgazebo interface the controller will read commands from and write data to.
Each controller requires it's own unique set of parameters, depending on it's functionality. The interface parameter is required to link a controller to a libgazebo interface. Without this link the controller cannot receive command and publish data.
The seperate model file should only contain the definition of the model. See
gazebo/worlds/pioneer2dx.model for an example.
A model can be included within a world using two different methods. The first assumes that the included model does not require any modifications.
<include embedded="false"> <xi:include href="pioneer2dx.model" /> </include>
If an included model should have some slight modfications, such as a name or position change, then use this method:
<model:physical name="pioneer2dx_model1"> <xyz>1 0 0.25</xyz> <rpy>0.0 0.0 0.0</rpy> <controller:pioneer2dx_position2d name="controller1"> <leftJoint>left_wheel_hinge</leftJoint> <rightJoint>right_wheel_hinge</rightJoint> <interface:position name="position_iface_1"/> </controller:pioneer2dx_position2d> <!-- The include should be last within a model. All previous statements will override those in the included file --> <include embedded="true"> <xi:include href="pioneer2dx.model" /> </include> </model:physical>
In the above example the pioneer2dx model has had a controller added to it, and it's position changed. Note that the included model file should be last within the
If we have use the
pioner2dx.model and the
sicklms200.model provided in the Gazebo sources (
gazebo/worlds), out nested model would look like:
<model:physical name="pioneer2dx_model2"> <xyz>0 0 0.5</xyz> <model:physical name="laser_model"> <xyz>0 0 0.2</xyz> <include embedded="true"> <xi:include href="laser.model" /> </include> </model:physical> <include embedded="true"> <xi:include href="pioneer2dx.model" /> </include> </model:physical>