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

66 documentation for sequences #75

Merged
merged 5 commits into from
Aug 22, 2023
Merged
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
40 changes: 39 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ TiPlot is an open-source visualisation tool for flight logs. With TiPlot, you ca
- 3D viewer for displaying the paths of your UAVs.
- Add multiple UAVs to compare flights.
- Sync the 3D view with a specific timestamp by hovering over it.
- Perform customized operations on data currently being processed.
- Ability to send a data dictionary and entities to be displayed in the 3D view over TCP port `5555` from a Python script or a Jupyter notebook.
- Layouts are automatically saved after every change.
- Drag and drop plots to reposition them.
Expand All @@ -41,7 +42,7 @@ TiPlot is an open-source visualisation tool for flight logs. With TiPlot, you ca

### Prebuilt AppImage

To install TiPlot using the prebuilt AppImage, follow these steps:
To run TiPlot using the prebuilt AppImage, follow these steps:

1. Download the latest AppImage from the [releases page](https://github.com/tilak-io/tiplot/releases/latest).
2. Make the AppImage executable by running:
Expand Down Expand Up @@ -116,6 +117,43 @@ Note that `datadict` is the data dictionary returned by the parser.

For more info check out the Jupyter notebooks in the [templates](https://github.com/tilak-io/tiplot/blob/main/templates) folder.

## Running Sequences and Custom Operations

In this guide, we will walk you through the process of creating and executing sequences, which are Python functions containing a set of operations to manipulate log data. These sequences can be customized to suit your specific needs. Follow these steps to get started:

1. **Set Preferred Editor**: Ensure that you have configured your preferred code editor in the tool settings by navigating to `Tools > Settings > General > External Editor`. If you intend to use a terminal-based editor such as Vim or Nano, make sure to specify the appropriate command to launch the terminal. (i.e: `kitty nvim` for kitty, `gnome-terminal -- nvim` for ubuntu's default terminal, `xterm -e nvim` for xterm...)

2. **Create a New Sequence**: To begin, create a new sequence by navigating to `Tools > Sequences > Add New Sequence`.

3. **Provide a Descriptive Name**: Give your sequence a meaningful and descriptive name that reflects its purpose.

4. **Edit the Sequence**: Upon creating a new sequence, your preferred code editor will open with a template function. You can now define the operations you want to perform on the log data.

Here's an example of a sequence that transforms log data from the NED (North-East-Down) representation to the ENU (East-North-Up) representation for a topic called `vehicle_local_position_enu`:

```python
def handle_data(datadict):
import numpy as np
new = datadict
# Coordinate transformation matrix from NED to ENU
NED_to_ENU = np.array([
[0, 1, 0], # East (ENU X) corresponds to North (NED Y)
[1, 0, 0], # North (ENU Y) corresponds to East (NED X)
[0, 0, -1] # Up (ENU Z) corresponds to -Down (NED Z)
])
# Apply the coordinate transformation to the 'x', 'y', and 'z' columns
new['vehicle_local_position_enu'] = new['vehicle_local_position'].copy()
xyz_ned = new['vehicle_local_position_enu'][['x', 'y', 'z']].values
xyz_enu = np.dot(xyz_ned, NED_to_ENU.T) # Transpose the transformation matrix for NED to ENU
new['vehicle_local_position_enu'][['x', 'y', 'z']] = xyz_enu
return new
```

***NOTE: the imports should be inside the function***

Feel free to adapt and customize your sequence function to perform the operations that are relevant to your data processing needs.

Happy sequencing 🎉!

## Contributing
We welcome contributions to TiPlot. If you would like to contribute, please follow these steps:
Expand Down
16 changes: 15 additions & 1 deletion api/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,21 @@ def create_sequence_file():

return {"ok": ok, "err": err}


@app.route('/open_sequence_file', methods=['POST'])
def open_sequence_file():
body = request.get_json()
sequence_name = body['sequence']
sequence_file = sequences_dir + sequence_name
try:
command = body['editorBinary'].split(" ")
command.append(sequence_file)
subprocess.Popen(command) # run the command asyncronously
ok = True
err = "no error"
except:
err = traceback.format_exc()
ok = False
return {"ok": ok, "err": err}

@socketio.on("disconnect")
def disconnected():
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tiplot",
"version": "1.1.9",
"version": "1.2.0",
"private": true,
"homepage": "./",
"proxy": "http://localhost:5000",
Expand Down Expand Up @@ -44,7 +44,7 @@
"react-bootstrap-submenu": "^3.0.1",
"react-dom": "^18.2.0",
"react-grid-layout": "^1.3.4",
"react-icons": "^4.4.0",
"react-icons": "^4.10.1",
"react-new-window": "^1.0.1",
"react-plotly.js": "^2.6.0",
"react-router-dom": "^6.6.2",
Expand Down
61 changes: 46 additions & 15 deletions src/components/ToolBar.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import { useState, useEffect } from "react";
import { useEffect, useState } from "react";
import {
Button,
Container,
Form,
Modal,
Nav,
Navbar,
NavDropdown,
Modal,
Button,
Navbar,
Tab,
Tabs,
Table,
Form
Tabs
} from "react-bootstrap";
import { DropdownSubmenu, NavDropdownMenu } from "react-bootstrap-submenu";
import { FaToggleOn, FaToggleOff, FaInfoCircle } from "react-icons/fa";
import { FcRadarPlot, FcScatterPlot, FcHeatMap } from "react-icons/fc";
import "react-bootstrap-submenu/dist/index.css";
import logo from "../static/img/logo.png";
import { generateUUID } from "three/src/math/MathUtils";
import { PORT } from "../static/js/constants";
import { FaInfoCircle, FaToggleOff, FaToggleOn } from "react-icons/fa";
import { FcHeatMap, FcRadarPlot, FcScatterPlot } from "react-icons/fc";
import { LuEdit, LuPlay } from "react-icons/lu";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { generateUUID } from "three/src/math/MathUtils";
import logo from "../static/img/logo.png";
import { PORT } from "../static/js/constants";
import { defaultSettings } from "../views/Settings";

function ToolBar({
page,
Expand Down Expand Up @@ -287,9 +289,19 @@ function ToolBar({
rows.push(
<NavDropdown.Item
key={generateUUID()}
onClick={() => runSequence(seq_name)}
style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}
>
{seq_name}
<div>{seq_name}</div>
&nbsp;
<div className="form-group">
<Button variant="outline-success"
onClick={() => runSequence(seq_name)}
><LuPlay /></Button>
&nbsp;
<Button variant="outline-outline"
onClick={() => openFileWithEditor(seq_name)}
><LuEdit /></Button>
</div>
</NavDropdown.Item>
);
});
Expand All @@ -316,13 +328,32 @@ function ToolBar({
}
).then((res) => res.json());

if (response.ok) toast.success(`"${name}" created successfully`);
else toast.error(response.err);
if (response.ok) {
toast.success(`"${name}" created successfully`);
openFileWithEditor(`${name}.py`);
}
else {
toast.error(response.err);
}

getSequences();
setShowCreateMessage(false);
};

const openFileWithEditor = async (sequenceName) => {
const general_settings = parseLocalStorage("general_settings");
const externalEditor =
general_settings.externalEditor ?? defaultSettings["externalEditor"];
const response = await fetch(`http://localhost:${PORT}/open_sequence_file`, {
headers: {
"Content-Type": "application/json",
},
method: "POST",
body: JSON.stringify({ sequence: sequenceName, editorBinary: externalEditor }),
}).then((res) => res.json());
if (!response.ok) toast.error(response.err);
}

const paramSearch = (query, dict) => {
const value = query.target.value;
setSearchQuery(value);
Expand Down
14 changes: 14 additions & 0 deletions src/views/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const defaultSettings = {
dampingFactor: 0.8,
fov: 75,
textYValue: 0,
externalEditor: "/usr/bin/code"
};

function Settings() {
Expand Down Expand Up @@ -72,6 +73,19 @@ function Settings() {
<ToolBar page="settings" />
<Container className="settings-page">
<Form>
<fieldset>
<legend>• General ⚙️</legend>
<InputGroup>
<InputGroup.Text>External Editor</InputGroup.Text>
<Form.Control
onChange={handleChange}
id="externalEditor"
type="text"
min={1}
aria-label="ExternalEditor"
/>
</InputGroup>
</fieldset>
<fieldset>
<legend>• View Layouts 🪟</legend>
<Form.Check
Expand Down
14 changes: 7 additions & 7 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3712,9 +3712,9 @@ caniuse-api@^3.0.0:
lodash.uniq "^4.5.0"

caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426:
version "1.0.30001443"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001443.tgz#8fc85f912d5471c9821acacf9e715c421ca0dd1f"
integrity sha512-jUo8svymO8+Mkj3qbUbVjR8zv8LUGpGkUM/jKvc9SO2BvjCI980dp9fQbf/dyLs6RascPzgR4nhAKFA4OHeSaA==
version "1.0.30001522"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001522.tgz"
integrity sha512-TKiyTVZxJGhsTszLuzb+6vUZSjVOAhClszBr2Ta2k9IwtNBT/4dzmL6aywt0HCgEZlmwJzXJd8yNiob6HgwTRg==

canvas-fit@^1.5.0:
version "1.5.0"
Expand Down Expand Up @@ -9867,10 +9867,10 @@ react-grid-layout@^1.3.4:
react-draggable "^4.0.0"
react-resizable "^3.0.4"

react-icons@^4.4.0:
version "4.7.1"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.7.1.tgz#0f4b25a5694e6972677cb189d2a72eabea7a8345"
integrity sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==
react-icons@^4.10.1:
version "4.10.1"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.10.1.tgz#3f3b5eec1f63c1796f6a26174a1091ca6437a500"
integrity sha512-/ngzDP/77tlCfqthiiGNZeYFACw85fUjZtLbedmJ5DTlNDIwETxhwBzdOJ21zj4iJdvc0J3y7yOsX3PpxAJzrw==

react-is@^16.13.1, react-is@^16.3.2, react-is@^16.7.0:
version "16.13.1"
Expand Down