Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ros logging #508

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions examples/Logging.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
<script src="../build/roslib.js"></script>

<script>
// Connecting to ROS
// -----------------
var ros = new ROSLIB.Ros();

// If there is an error on the backend, an 'error' emit will be emitted.
ros.on('error', function(error) {
document.getElementById('connecting').style.display = 'none';
document.getElementById('connected').style.display = 'none';
document.getElementById('closed').style.display = 'none';
document.getElementById('error').style.display = 'inline';
console.log(error);
});

// Find out exactly when we made a connection.
ros.on('connection', function() {
console.log('Connection made!');
document.getElementById('connecting').style.display = 'none';
document.getElementById('error').style.display = 'none';
document.getElementById('closed').style.display = 'none';
document.getElementById('connected').style.display = 'inline';
});

ros.on('close', function() {
console.log('Connection closed.');
document.getElementById('connecting').style.display = 'none';
document.getElementById('connected').style.display = 'none';
document.getElementById('closed').style.display = 'inline';
});

// Create a connection to the rosbridge WebSocket server.
ros.connect('ws://localhost:9090');
</script>

<!-- This script needs to imported after roslib has been initialized -->
<script src="ros_log.js"></script>

</head>

<body>
<h1>Simple Logging Example</h1>
<p>Run the following commands in the terminal then refresh this page. Check the JavaScript
console and the terminal for the output.</p>
<ol>
<li><tt>roscore</tt></li>
<li><tt>rostopic echo /rosout</tt></li>
<li><tt>roslaunch rosbridge_server rosbridge_websocket.launch</tt></li>
</ol>
<div id="statusIndicator">
<p id="connecting">
Connecting to rosbridge...
</p>
<p id="connected" style="color:#00D600; display:none">
Connected
</p>
<p id="error" style="color:#FF0000; display:none">
Error in the backend!
</p>
<p id="closed" style="display:none">
Connection closed.
</p>
</div>

<button onclick="logDebug('This is a DEBUG message!')">DEBUG</button>
<button onclick="logInfo('This is an INFO message!')">INFO</button>
<button onclick="logWarn('This is a WARN message!')">WARN</button>
<button onclick="logErr('This is an ERROR message!')">ERROR</button>
<button onclick="logFatal('This is a FATAL message!')">FATAL</button>
</body>
</html>
144 changes: 144 additions & 0 deletions examples/ros_log.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/**
* Implements ROS logging capability with functions
* that are called similarly to the python logging functions.
*
* This script must be imported after ROSLIB.ros() has been created
* and a ROS connection has been established.
*
* @author Joshua Glazer - github.com/vashmata
*/



// ROS logging severity level constants
const ROSDEBUG = 1 // debug level
const ROSINFO = 2 // general level
const ROSWARN = 4 // warning level
const ROSERROR = 8 // error level
const ROSFATAL = 16 // fatal/critical level

// create a publisher to send log messages to /rosout
ros_logger = new ROSLIB.Topic({
ros: ros,
name: 'rosout',
messageType: 'rosgraph_msgs/Log'
})

/**
* Gets the current time and formats it for ROS and the console.
* @return array of two variables: ROS time object, string containing hh:mm:ss
*/
function rosTimestamp () {
// next few lines taken and adjusted from roslibjs action server example
let currentTime = new Date()
let secs = currentTime.getTime()/1000 // seconds before truncating the decimal
let secsFloored = Math.floor(secs) // seconds after truncating
let nanoSecs = Math.round(1000000000*(secs-secsFloored)) // nanoseconds since the previous second

// return a dictionary for the ROS log and a string for the console
let stampTime = currentTime.toString().split(' ')[4] // hh:mm:ss from date object
return [{secs : secsFloored, nsecs : nanoSecs}, stampTime]
}

/**
* Creates and publishes a ROS log message to /rosout based on the parameters
* @param logLevel one of the ROS loglevel constants defined above
* @param timestamp ros time object containing seconds and nanoseconds
* @param message the log message
*/
function publishRosLog (logLevel, timestamp, message) {
ros_logger.publish(
new ROSLIB.Message({
// I'm only publishing the essentials. We could include more info if so desired
header : {
// seq // uint32: sequence ID, seems to increment automatically
stamp : timestamp // dictionary: contains truncated seconds and nanoseconds
// frame_id // string: probably only useful for tf
},
level : logLevel, // int: see log level constants above
// name : '/web_gui', // name of the node (proposed)
msg : message, // string: this is the log message
// file // string: we could specify the js file that generated the log
// function // string: we could specify the parent function that generated the log
// line // uint32: we could specify the specific line of code that generated the log
// topics // string[]: topic names that the node publishes
})
)
}

/**
* Publishes the log message and prints it to the chrome console.
* @param logLevel one of the ROS loglevel constants defined above
* @param message the log message
*/
function rosLog (logLevel, message) {
logData = {}
logData[ROSDEBUG] = {prefix : '[DEBUG]', type : 'log'}
logData[ROSINFO] = {prefix : '[INFO]', type : 'log'}
logData[ROSWARN] = {prefix : '[WARN]', type : 'warn'}
logData[ROSERROR] = {prefix : '[ERROR]', type : 'error'}
logData[ROSFATAL] = {prefix : '[FATAL]', type : 'error'}

stamps = rosTimestamp()
consoleMsg = logData[logLevel].prefix + ' [' + stamps[1] + ']: ' + message

if (logData[logLevel].type === 'log') {
console.log(consoleMsg)
} else if (logData[logLevel].type === 'warn') {
console.warn(consoleMsg)
} else if (logData[logLevel].type === 'error') {
console.error(consoleMsg)
}

// log messages go to log file: currently rosout.log
publishRosLog(logLevel, stamps[0], message)
}


// these functions mimic the rospy logging functions

/**
* Sends a debug message with timestamp to the GUI and chrome consoles.
* Also publishes it to /rosout.
* @param message the log message
*/
function logDebug (message) {
// unlike rospy, (currently) the debug messages we generate will get published
rosLog(ROSDEBUG, message)
}

/**
* Sends an info message with timestamp to the GUI and chrome consoles.
* Also publishes it to /rosout.
* @param message the log message
*/
function logInfo (message) {
rosLog(ROSINFO, message)
}

/**
* Sends a warning message with timestamp to the GUI and chrome consoles.
* Also publishes it to /rosout.
* @param message the log message
*/
function logWarn (message) {
rosLog(ROSWARN, message)
}

/**
* Sends an error message with timestamp to the GUI and chrome consoles.
* Also publishes it to /rosout.
* @param message the log message
*/
function logErr (message) {
rosLog(ROSERROR, message)
}

/**
* Sends a fatal error message with timestamp to the GUI and chrome consoles.
* Also publishes it to /rosout.
* @param message the log message
*/
function logFatal (message) {
rosLog(ROSFATAL, message)
}