14 #include <ecl/math.hpp> 15 #include <ecl/geometry/angle.hpp> 16 #include <ecl/time/sleep.hpp> 17 #include <ecl/converters.hpp> 18 #include <ecl/sigslots.hpp> 19 #include <ecl/geometry/angle.hpp> 20 #include <ecl/time/timestamp.hpp> 22 #include "../../include/kobuki_driver/kobuki.hpp" 23 #include "../../include/kobuki_driver/packet_handler/payload_headers.hpp" 38 unsigned int packet_size(
buffer.size());
40 for (
unsigned int i = 2; i < packet_size; i++)
44 return cs ?
false :
true;
52 shutdown_requested(false)
56 , version_info_reminder(0)
57 , controller_info_reminder(0)
58 , heading_offset(0.0/0.0)
59 , velocity_commands_debug(4, 0)
71 sig_debug.emit(
"Device: kobuki driver terminated.");
79 throw ecl::StandardException(LOC, ecl::ConfigurationError,
"Kobuki's parameter settings did not validate.");
88 sig_stream_data.connect(sigslots_namespace + std::string(
"/stream_data"));
94 sig_debug.connect(sigslots_namespace + std::string(
"/ros_debug"));
95 sig_info.connect(sigslots_namespace + std::string(
"/ros_info"));
96 sig_warn.connect(sigslots_namespace + std::string(
"/ros_warn"));
97 sig_error.connect(sigslots_namespace + std::string(
"/ros_error"));
98 sig_named.connect(sigslots_namespace + std::string(
"/ros_named"));
105 catch (
const ecl::StandardException &e)
107 if (e.flag() == ecl::NotFoundError) {
108 sig_warn.emit(
"device does not (yet) available, is the usb connected?.");
110 throw ecl::StandardException(LOC, e);
114 ecl::PushAndPop<unsigned char> stx(2, 0);
115 ecl::PushAndPop<unsigned char> etx(1);
179 ecl::TimeStamp last_signal_time;
180 ecl::Duration timeout(0.1);
181 unsigned char buf[256];
196 sig_info.emit(
"device is connected.");
203 catch (
const ecl::StandardException &e)
206 if (e.flag() == ecl::NotFoundError) {
207 sig_info.emit(
"device does not (yet) available on this port, waiting...");
208 }
else if (e.flag() == ecl::OpenError) {
209 sig_info.emit(
"device failed to open, waiting... [" + std::string(e.what()) +
"]");
212 throw ecl::StandardException(LOC, e);
227 if (
is_alive && ((ecl::TimeStamp() - last_signal_time) > timeout))
232 sig_debug.emit(
"Timed out while waiting for incoming bytes.");
239 std::ostringstream ostream;
240 ostream <<
"kobuki_node : serial_read(" << n <<
")" 304 if (version_match < 0) {
305 sig_error.emit(
"Robot firmware is outdated and needs to be upgraded. Consult how-to on: " \
306 "http://kobuki.yujinrobot.com/home-en/documentation/howtos/upgrading-firmware");
311 else if (version_match > 0) {
312 sig_error.emit(
"Driver version isn't not compatible with robot firmware. Please upgrade driver");
319 if (version_match < 0) {
320 sig_warn.emit(
"Robot firmware is outdated; we suggest you to upgrade it " \
321 "to benefit from the latest features. Consult how-to on: " \
322 "http://kobuki.yujinrobot.com/home-en/documentation/howtos/upgrading-firmware");
326 else if (version_match > 0) {
331 catch (std::out_of_range& e)
334 sig_error.emit(std::string(
"Invalid firmware version number: ").append(e.what()));
361 last_signal_time.stamp();
370 if (
is_alive && ((ecl::TimeStamp() - last_signal_time) > timeout))
377 sig_error.emit(
"Driver worker thread shutdown!");
382 if (byteStream.size() < 3 ) {
383 sig_named.emit(
log(
"error",
"packet",
"too small sub-payload detected."));
386 std::stringstream ostream;
387 unsigned int header_id =
static_cast<unsigned int>(byteStream.pop_front());
388 unsigned int length =
static_cast<unsigned int>(byteStream.pop_front());
389 unsigned int remains = byteStream.size();
392 ostream <<
"[" << header_id <<
"]";
393 ostream <<
"[" << length <<
"]";
396 ostream << std::setfill(
'0') << std::uppercase;
397 ostream << std::hex << std::setw(2) << header_id <<
" " << std::dec;
398 ostream << std::hex << std::setw(2) << length <<
" " << std::dec;
400 if (remains < length) to_pop = remains;
401 else to_pop = length;
403 for (
unsigned int i = 0; i < to_pop; i++ ) {
404 unsigned int byte =
static_cast<unsigned int>(byteStream.pop_front());
405 ostream << std::hex << std::setw(2) << byte <<
" " << std::dec;
409 if (remains < length)
sig_named.emit(
log(
"error",
"packet",
"malformed sub-payload detected. " + ostream.str()));
410 else sig_named.emit(
log(
"debug",
"packet",
"unknown sub-payload detected. " + ostream.str()));
421 ecl::Angle<double> heading;
423 heading = (
static_cast<double>(
inertia.
data.
angle) / 100.0) * ecl::pi / 180.0;
446 double &wheel_right_angle_rate)
465 pose_update, pose_update_rates);
496 const unsigned int &i_gain,
const unsigned int &d_gain)
499 sig_warn.emit(
"Robot firmware doesn't support this function, so you must upgrade it. " \
500 "Consult how-to on: http://kobuki.yujinrobot.com/home-en/documentation/howtos/upgrading-firmware");
513 sig_warn.emit(
"Robot firmware doesn't support this function, so you must upgrade it. " \
514 "Consult how-to on: http://kobuki.yujinrobot.com/home-en/documentation/howtos/upgrading-firmware");
531 std::vector<double> velocity_commands_received;
563 sig_debug.emit(
"Device state is not ready yet.");
574 sig_error.emit(
"command serialise failed.");
577 unsigned char checksum = 0;
613 std::cout <<
"========== Void ==========" << std::endl;
614 ecl::SigSlotsManager<>::printStatistics();
615 std::cout <<
"========= String =========" << std::endl;
616 ecl::SigSlotsManager<const std::string&>::printStatistics();
617 std::cout <<
"====== Button Event ======" << std::endl;
618 ecl::SigSlotsManager<const ButtonEvent&>::printStatistics();
619 std::cout <<
"====== Bumper Event ======" << std::endl;
620 ecl::SigSlotsManager<const BumperEvent&>::printStatistics();
621 std::cout <<
"====== Cliff Event =======" << std::endl;
622 ecl::SigSlotsManager<const CliffEvent&>::printStatistics();
623 std::cout <<
"====== Wheel Event =======" << std::endl;
624 ecl::SigSlotsManager<const WheelEvent&>::printStatistics();
625 std::cout <<
"====== Power Event =======" << std::endl;
626 ecl::SigSlotsManager<const PowerEvent&>::printStatistics();
627 std::cout <<
"====== Input Event =======" << std::endl;
628 ecl::SigSlotsManager<const InputEvent&>::printStatistics();
629 std::cout <<
"====== Robot Event =======" << std::endl;
630 ecl::SigSlotsManager<const RobotEvent&>::printStatistics();
631 std::cout <<
"====== VersionInfo =======" << std::endl;
632 ecl::SigSlotsManager<const VersionInfo&>::printStatistics();
633 std::cout <<
"===== Command Buffer =====" << std::endl;
634 ecl::SigSlotsManager<const Command::Buffer&>::printStatistics();
std::vector< std::string > log(std::string msg)
ecl::Signal< PacketFinder::BufferType & > sig_raw_data_stream
struct kobuki::Cliff::Data data
bool deserialise(ecl::PushAndPop< unsigned char > &byteStream)
ControllerInfo controller_info
AccelerationLimiter acceleration_limiter
void configure(const std::string &sigslots_namespace, const BufferType &putStx, const BufferType &putEtx, unsigned int sizeLengthField, unsigned int sizeMaxPayload, unsigned int sizeChecksumField, bool variableSizePayload)
void sendCommand(Command command)
Send the prepared command to the serial port.
EventManager event_manager
static Command SetControllerGain(const unsigned char &type, const unsigned int &p_gain, const unsigned int &i_gain, const unsigned int &d_gain)
void fixPayload(ecl::PushAndPop< unsigned char > &byteStream)
double battery_low
Threshold for battery level warnings [14.0V].
Command::Buffer command_buffer
bool setControllerGain(const unsigned char &type, const unsigned int &p_gain, const unsigned int &i_gain, const unsigned int &d_gain)
ecl::Signal< const std::string & > sig_info
int controller_info_reminder
bool deserialise(ecl::PushAndPop< unsigned char > &byteStream)
bool validate()
A validator to ensure the user has supplied correct/sensible parameter values.
struct kobuki::CoreSensors::Data data
std::string current_version()
ecl::Signal< const std::vector< short > & > sig_raw_control_command
ecl::PushAndPop< unsigned char > BufferType
bool deserialise(ecl::PushAndPop< unsigned char > &byteStream)
bool deserialise(ecl::PushAndPop< unsigned char > &byteStream)
ecl::Signal< const VersionInfo & > sig_version_info
std::string device_port
The serial device port name [/dev/kobuki].
void getWheelJointStates(double &wheel_left_angle, double &wheel_left_angle_rate, double &wheel_right_angle, double &wheel_right_angle_rate)
struct kobuki::UniqueDeviceID::Data data
std::vector< uint16_t > bottom
ecl::Signal< const std::string & > sig_error
double battery_dangerous
Threshold for battery level in danger of depletion [13.2V].
bool deserialise(ecl::PushAndPop< unsigned char > &byteStream)
std::string sigslots_namespace
The first part of a sigslot connection namespace ["/kobuki"].
bool deserialise(ecl::PushAndPop< unsigned char > &byteStream)
void update(const CoreSensors::Data &new_state, const std::vector< uint16_t > &cliff_data)
struct kobuki::Inertia::Data data
ecl::Signal< const std::string & > sig_debug
void sendBaseControlCommand()
int check_major_version()
static Command SetLedArray(const enum LedNumber &number, const enum LedColour &colour, Command::Data ¤t_data)
void getBuffer(BufferType &bufferRef)
void setLed(const enum LedNumber &number, const enum LedColour &colour)
bool deserialise(ecl::PushAndPop< unsigned char > &byteStream)
int check_minor_version()
static std::string toString(const uint32_t &version)
bool deserialise(ecl::PushAndPop< unsigned char > &byteStream)
UniqueDeviceID unique_device_id
struct kobuki::Firmware::Data data
void setExternalPower(const DigitalOutput &digital_output)
ecl::Angle< double > getHeading() const
int flashed_major_version()
ecl::Signal< Command::Buffer & > sig_raw_data_command
void playSoundSequence(const enum SoundSequences &number)
Parameter list and validator for the kobuki.
void init(Parameters ¶meters)
double getAngularVelocity() const
std::vector< double > limit(const std::vector< double > &command)
Limits the input velocity commands if gatekeeper is enabled.
void setDigitalOutput(const DigitalOutput &digital_output)
void getWheelJointStates(double &wheel_left_angle, double &wheel_left_angle_rate, double &wheel_right_angle, double &wheel_right_angle_rate)
static Command SetDigitalOutput(const DigitalOutput &digital_output, Command::Data ¤t_data)
int version_info_reminder
void velocityCommands(const double &vx, const double &wz)
int flashed_minor_version()
static Command SetVelocityControl(DiffDrive &diff_drive)
void updateOdometry(ecl::LegacyPose2D< double > &pose_update, ecl::linear_algebra::Vector3d &pose_update_rates)
Use the current sensor data (encoders and gyro) to calculate an update for the odometry.
ThreeAxisGyro three_axis_gyro
void setBaseControl(const double &linear_velocity, const double &angular_velocity)
std::vector< double > pointVelocity() const
bool deserialise(ecl::PushAndPop< unsigned char > &byteStream)
void resetBuffer(Buffer &buffer)
unsigned int numberOfDataToRead()
bool deserialise(ecl::PushAndPop< unsigned char > &byteStream)
ecl::Signal sig_controller_info
ecl::Signal< const std::string & > sig_warn
void update(const uint16_t &time_stamp, const uint16_t &left_encoder, const uint16_t &right_encoder, ecl::LegacyPose2D< double > &pose_update, ecl::linear_algebra::Vector3d &pose_update_rates)
Updates the odometry from firmware stamps and encoders.
void getPayload(BufferType &bufferRef)
double battery_capacity
Capacity voltage of the battery [16.5V].
void printSigSlotConnections() const
Print a list of all relevant sigslot connections.
static Command GetVersionInfo()
bool serialise(ecl::PushAndPop< unsigned char > &byteStream)
virtual bool update(const unsigned char *incoming, unsigned int numberOfIncoming)
ecl::Signal< const std::vector< std::string > & > sig_named
PacketFinder packet_finder
static Command PlaySoundSequence(const enum SoundSequences &number, Command::Data ¤t_data)
void init(const std::string &sigslots_namespace)
static Command GetControllerGain()
struct kobuki::Hardware::Data data
void spin()
Performs a scan looking for incoming data packets.
bool enable_acceleration_limiter
Enable or disable the acceleration limiter [true].
void init(bool enable_acceleration_limiter, double linear_acceleration_max_=0.5, double angular_acceleration_max_=3.5, double linear_deceleration_max_=-0.5 *1.2, double angular_deceleration_max_=-3.5 *1.2)
std::vector< short > velocity_commands_debug
static Command SetExternalPower(const DigitalOutput &digital_output, Command::Data ¤t_data)
void setVelocityCommands(const double &vx, const double &wz)
ecl::Signal sig_stream_data
PacketFinder::BufferType data_buffer