Bring back the gazebo plugins (#1063)

The models and meshes are not included. We will need
to find an alternate way to reintegrate these and use them.

* Add simulation/gz_msgs back, and build with Gradle.

* Add back in the frc simulation plugins for gazebo.

* Add a new shared library, halsim_gazebo.

This library will become the interface between the
HAL sim layer and gazebo.

* Preserve the first channel number used in created Encoders in the Sim MockData.

This allows us to use the DIO channel number to connect with simulated encoders.

* Have the HAL Simulator set the reverse direction on creation.

This enables a simulator to be aware of the direction.

* Add a drive_motor plugin.

This is a bit of a 'magic' motor, which allows us to build robot
models that drive in a more realistic fashion.  It does this
by apply forces directly to the chassis, rather than relying on
the complex motion dynamics of a driven wheel.

This in turn allows the model to reduce wheel friction,
reducing scrub, and allowing for a more natural driving experience.
This commit is contained in:
Jeremy White
2018-06-30 02:45:21 -05:00
committed by Peter Johnson
parent 70960b0251
commit ebd41fe0bb
60 changed files with 5278 additions and 1 deletions

View File

@@ -0,0 +1,22 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "external_limit_switch.h"
#include <string>
ExternalLimitSwitch::ExternalLimitSwitch(sdf::ElementPtr sdf) {
sensor = std::dynamic_pointer_cast<gazebo::sensors::ContactSensor>(
gazebo::sensors::get_sensor(sdf->Get<std::string>("sensor")));
gzmsg << "\texternal limit switch: "
<< " sensor=" << sensor->Name() << std::endl;
}
bool ExternalLimitSwitch::Get() {
return sensor->Contacts().contact().size() > 0;
}

View File

@@ -0,0 +1,38 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "internal_limit_switch.h"
#include <string>
InternalLimitSwitch::InternalLimitSwitch(gazebo::physics::ModelPtr model,
sdf::ElementPtr sdf) {
joint = model->GetJoint(sdf->Get<std::string>("joint"));
min = sdf->Get<double>("min");
max = sdf->Get<double>("max");
if (sdf->HasElement("units")) {
radians = sdf->Get<std::string>("units") != "degrees";
} else {
radians = true;
}
gzmsg << "\tinternal limit switch: "
<< " type=" << joint->GetName() << " range=[" << min << "," << max
<< "] radians=" << radians << std::endl;
}
bool InternalLimitSwitch::Get() {
double value;
joint->GetAngle(0).Normalize();
if (radians) {
value = joint->GetAngle(0).Radian();
} else {
value = joint->GetAngle(0).Degree();
}
return value >= min && value <= max;
}

View File

@@ -0,0 +1,57 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "limit_switch.h"
#include <boost/algorithm/string/replace.hpp>
GZ_REGISTER_MODEL_PLUGIN(LimitSwitch)
void LimitSwitch::Load(gazebo::physics::ModelPtr model, sdf::ElementPtr sdf) {
this->model = model;
// Parse SDF properties
if (sdf->HasElement("topic")) {
topic = sdf->Get<std::string>("topic");
} else {
topic = "~/" + sdf->GetAttribute("name")->GetAsString();
}
invert = sdf->HasElement("invert");
std::string type = sdf->Get<std::string>("type");
gzmsg << "Initializing limit switch: " << topic << " type=" << type
<< std::endl;
if (type == "internal") {
ls = new InternalLimitSwitch(model, sdf);
} else if (type == "external") {
ls = new ExternalLimitSwitch(sdf);
} else {
gzerr << "WARNING: unsupported limit switch type " << type;
}
// Connect to Gazebo transport for messaging
std::string scoped_name =
model->GetWorld()->GetName() + "::" + model->GetScopedName();
boost::replace_all(scoped_name, "::", "/");
node = gazebo::transport::NodePtr(new gazebo::transport::Node());
node->Init(scoped_name);
pub = node->Advertise<gazebo::msgs::Bool>(topic);
// Connect to the world update event.
// This will trigger the Update function every Gazebo iteration
updateConn = gazebo::event::Events::ConnectWorldUpdateBegin(
boost::bind(&LimitSwitch::Update, this, _1));
}
void LimitSwitch::Update(const gazebo::common::UpdateInfo& info) {
gazebo::msgs::Bool msg;
if (invert)
msg.set_data(!ls->Get());
else
msg.set_data(ls->Get());
pub->Publish(msg);
}

View File

@@ -0,0 +1,29 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <boost/pointer_cast.hpp>
#include <gazebo/gazebo.hh>
#include <gazebo/sensors/sensors.hh>
#ifdef _WIN32
#include <Winsock2.h>
#endif
#include "switch.h"
class ExternalLimitSwitch : public Switch {
public:
explicit ExternalLimitSwitch(sdf::ElementPtr sdf);
/// \brief Returns true when the switch is triggered.
virtual bool Get();
private:
gazebo::sensors::ContactSensorPtr sensor;
};

View File

@@ -0,0 +1,30 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <gazebo/gazebo.hh>
#include <gazebo/physics/physics.hh>
#ifdef _WIN32
#include <Winsock2.h>
#endif
#include "switch.h"
class InternalLimitSwitch : public Switch {
public:
InternalLimitSwitch(gazebo::physics::ModelPtr model, sdf::ElementPtr sdf);
/// \brief Returns true when the switch is triggered.
virtual bool Get();
private:
gazebo::physics::JointPtr joint;
double min, max;
bool radians;
};

View File

@@ -0,0 +1,99 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <string>
#include <gazebo/gazebo.hh>
#include <gazebo/physics/physics.hh>
#include <gazebo/transport/transport.hh>
#include "external_limit_switch.h"
#include "internal_limit_switch.h"
#include "simulation/gz_msgs/msgs.h"
#include "switch.h"
/**
* \brief Plugin for reading limit switches.
*
* This plugin publishes whether or not the limit switch has been
* triggered every physics update. There are two types of limit switches:
*
* - Internal: Measure joint limits. Triggerd if the joint is within
* some range.
* - External: Measure interactions with the outside world. Triggerd
* if some link is in collision.
*
* To add a limit swithch to your robot, add the following XML to your
* robot model.
*
* Internal:
*
* <plugin name="my_limit_switch" filename="liblimit_switch.so">
* <topic>~/my/topic</topic>
* <type>internal</type>
* <joint>Joint Name</joint>
* <units>{degrees, radians}</units>
* <min>Number</min>
* <max>Number</max>
* </plugin>
*
* External:
*
* <plugin name="my_limit_switch" filename="liblimit_switch.so">
* <topic>~/my/topic</topic>
* <type>external</type>
* <sensor>Sensor Name</sensor>
* </plugin>
*
* Common:
* - `topic`: Optional. Message will be published as a gazebo.msgs.Bool.
* Recommended values are of the form:
* /gazebo/frc/simulator/dio/n
* - `type`: Required. The type of limit switch that this is
* - `invert`: Optional. If given, the output meaning will be inverted
*
* Internal
* - `joint`: Name of the joint this potentiometer is attached to.
* - `units`: Optional. Defaults to radians.
* - `min`: Minimum angle considered triggered.
* - `max`: Maximum angle considered triggered.
*
* External
* - `sensor`: Name of the contact sensor that this limit switch uses.
*/
class LimitSwitch : public gazebo::ModelPlugin {
public:
/// \brief Load the limit switch and configures it according to the sdf.
void Load(gazebo::physics::ModelPtr model, sdf::ElementPtr sdf);
/// \brief Sends out the limit switch reading each timestep.
void Update(const gazebo::common::UpdateInfo& info);
private:
/// \brief Publish the limit switch value on this topic.
std::string topic;
/// \brief LimitSwitch object, currently internal or external.
Switch* ls;
/// \brief Indicate if we should invert the output
bool invert;
/// \brief The model to which this is attached.
gazebo::physics::ModelPtr model;
/// \brief Pointer to the world update function.
gazebo::event::ConnectionPtr updateConn;
/// \brief The node on which we're advertising.
gazebo::transport::NodePtr node;
/// \brief Publisher handle.
gazebo::transport::PublisherPtr pub;
};

View File

@@ -0,0 +1,16 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
class Switch {
public:
virtual ~Switch() = default;
/// \brief Returns true when the switch is triggered.
virtual bool Get() = 0;
};